Amélioration du [robot de ligne qui dessine une date arbitraire sur une photo] précédemment créé (https://qiita.com/satoshi_199188/items/4d9bbe38ef011af5b662), enregistre le nom et la date de naissance dans la base de données et son âge à partir de la date de prise de vue J'ai créé un robot de ligne qui calcule s'il s'agit d'une photo ou l'écrit sur une image. Cliquez ici pour github
・ Assistant record de croissance (ID: @ 033cynwe)
--Création de canaux LineBot --Déployer sur heroku
main.py
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import (FollowEvent, PostbackEvent, TemplateSendMessage, MessageAction,\
ButtonsTemplate, DatetimePickerTemplateAction, ImageMessage, \
ImageSendMessage, MessageEvent, TextMessage, TextSendMessage)
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import datetime
import os
import database
app = Flask(__name__)
app.debug = False
#Obtenir des variables d'environnement
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]
line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)
#Chemin de référence de l'image
SRC_IMAGE_PATH = "static/images/{}.jpg "
MAIN_IMAGE_PATH = "static/images/{}_main.jpg "
PREVIEW_IMAGE_PATH = "static/images/{}_preview.jpg "
@app.route("/callback", methods=['POST'])
def callback():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
#Suivez l'événement
@handler.add(FollowEvent)
def handle_follow(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=
"Merci de vous être inscrit comme ami. J'écrirai dans l'image l'âge de la personne sur la photo. Veuillez m'envoyer une image."))
#Recevoir des images
@handler.add(MessageEvent, message=ImageMessage)
def handle_image(event):
global message_id, user_id, name_list, user_dict, num, src_image_path
#Liste de stockage des informations utilisateur
name_list = []
day_list = []
user_dict = {}
#message_Obtenir l'identifiant
message_id = event.message.id
#user_Obtenir l'identifiant
user_id = event.source.user_id
#Message de nom de fichier_Chemin converti en identifiant
src_image_path = Path(SRC_IMAGE_PATH.format(message_id)).absolute()
#Enregistrer temporairement les images sur Heroku
save_image(message_id, src_image_path)
#Vérifier les informations de l'utilisateur et réussir s'il n'est pas enregistré
try:
name_list, day_list = database.serch_data(user_id)
except TypeError:
pass
#Numéro d'enregistrement
num = len(name_list)
#Si non enregistré, vérifiez votre nom
if num == 0:
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Quel est le nom de la personne sur la photo?"))
#user_Ajouter un identifiant
database.add_data(user_id)
#Si vous avez une inscription, vérifiez qui est sur la photo
elif num != 0:
#Créez un dictionnaire avec le nom et le jour
user_dict = dict(zip(name_list, day_list))
#Lors de l'inscription d'une personne
if num == 1:
name_1 = name_list[0]
buttons_template = TemplateSendMessage(
alt_text="Qui est sur la photo?",
template=ButtonsTemplate(
text="Qui est sur la photo?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label="Autre", text="Autre")
]
)
)
#En cas d'inscription de 2 personnes
elif num == 2:
name_1 = name_list[0]
name_2 = name_list[1]
buttons_template = TemplateSendMessage(
alt_text="Qui est sur la photo?",
template=ButtonsTemplate(
text="Qui est sur la photo?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label="Autre", text="Autre")
]
)
)
#En cas d'inscription de 3 personnes
elif num == 3:
name_1 = name_list[0]
name_2 = name_list[1]
name_3 = name_list[2]
buttons_template = TemplateSendMessage(
alt_text="Qui est sur la photo?",
template=ButtonsTemplate(
text="Qui est sur la photo?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label=name_3, text=name_3),
MessageAction(label="Autre", text="Autre")
]
)
)
line_bot_api.reply_message(event.reply_token, buttons_template)
#Recevoir du texte
@handler.add(MessageEvent, message=TextMessage)
def handle_text(event):
global text_name, birthday
#Confirmation de la date de naissance si non enregistrée
if num == 0:
text_name = event.message.text
select_day(event)
#Si autre est sélectionné, vérifiez le nom
elif event.message.text == "Autre":
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Quel est le nom de la personne sur la photo?"))
else:
text_name = event.message.text
#Si le nom est déjà enregistré, obtenez la date de naissance
if text_name in name_list:
birthday = user_dict[text_name]
#Si si, sélectionnez la date de prise de vue, sinon sélectionnez la date de naissance
select_day(event)
#Traiter et envoyer des images
@handler.add(PostbackEvent)
def handle_postback(event):
global birthday
#Message de nom de fichier_Chemin converti en identifiant
main_image_path = MAIN_IMAGE_PATH.format(message_id)
preview_image_path = PREVIEW_IMAGE_PATH.format(message_id)
#Si l'anniversaire n'est pas défini
if not "birthday" in globals():
#Remplacer le résultat de l'action de sélection de date par anniversaire
birthday = event.postback.params["date"]
#Mettre à jour le nom et le jour
database.update_data(user_id, num, text_name, birthday)
#Sélection de la date de prise de vue
select_day(event)
#Si l'anniversaire est défini
elif "birthday" in globals():
#Traitement d'image
date_the_image(src_image_path, Path(main_image_path).absolute(), event)
date_the_image(src_image_path, Path(preview_image_path).absolute(), event)
#Spécifiez l'image
image_message = ImageSendMessage(
original_content_url=f"https://<nom de l'application heroku>.herokuapp.com/{main_image_path}",
preview_image_url=f"https://<nom de l'application heroku>.herokuapp.com/{preview_image_path}"
)
#Obtenir le journal
app.logger.info(f"https://<nom de l'application heroku>.herokuapp.com/{main_image_path}")
#Envoyer l'image
line_bot_api.reply_message(event.reply_token, image_message)
#Supprimer la variable anniversaire
del birthday
#Enregistrer les modifications de la base de données et se déconnecter
database.close_db()
#Fonction de stockage d'image
def save_image(message_id: str, save_path: str) -> None:
# message_Obtenir les données binaires de l'image à partir de l'identifiant
message_content = line_bot_api.get_message_content(message_id)
with open(save_path, "wb") as f:
#Ecrire les données binaires acquises
for chunk in message_content.iter_content():
f.write(chunk)
#Fonction de sélection de la date
def select_day(event):
#Si l'anniversaire est défini
if "birthday" in globals():
message = "Veuillez sélectionner la date de prise de vue"
#Si l'anniversaire n'est pas défini
elif not "birthday" in globals():
message = "Veuillez sélectionner votre date de naissance"
#Action de sélection de la date
date_picker = TemplateSendMessage(
alt_text=message,
template=ButtonsTemplate(
text=message,
actions=[
DatetimePickerTemplateAction(
label="Choix",
data="action=buy&itemid=1",
mode="date",
initial=str(datetime.date.today()),
max=str(datetime.date.today())
)
]
)
)
line_bot_api.reply_message(event.reply_token, date_picker)
#Fonction de traitement d'image
def date_the_image(src: str, desc: str, event) -> None:
im = Image.open(src)
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("./fonts/AquaKana.ttc", 50)
#Obtenez la date de tournage
date = event.postback.params["date"]
#Calculez le nombre de jours après la naissance en soustrayant la date de naissance de la date de prise de vue
how_old = datetime.datetime.strptime(date, "%Y-%m-%d") - datetime.datetime.strptime(str(birthday), "%Y-%m-%d")
#Jours de naissance et 365(journée)Calculer le quotient et le reste avec
years, days = divmod(how_old.days, 365)
#Reste 30(journée)Calculer le quotient avec
month = days // 30
text = text_name + f"({years}Talent{month}mois)"
#Taille du texte
text_width = draw.textsize(text, font=font)[0]
text_height = draw.textsize(text, font=font)[1]
margin = 10
x = im.width - text_width
y = im.height - text_height
#La taille du rectangle à dessiner
rect_size = ((text_width + margin * 6), (text_height + margin * 2))
#Dessinez un rectangle
rect = Image.new("RGB", rect_size, (0, 0, 0))
#Masque pour rendre le rectangle transparent
mask = Image.new("L", rect_size, 128)
#Coller un rectangle et un masque sur l'image
im.paste(rect, (x - margin * 6, y - margin * 3), mask)
#Rédaction de texte
draw.text((x - margin * 3, y - margin * 2), text, fill=(255, 255, 255), font=font)
im.save(desc)
if __name__ == "__main__":
#app.run()
port = int(os.getenv("PORT", 5000))
app.run(host="0.0.0.0", port=port)
database.py
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine, Column, String, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.orm.exc import NoResultFound
import datetime
import os
#Obtenir l'URL de la base de données à partir de la variable d'environnement
DATABASE_URL = os.environ["DATABASE_URL"]
engine = create_engine(DATABASE_URL)
Base = declarative_base()
#définition de table
class User(Base):
__tablename__ = "user_list"
user_id = Column("user_id", String(50), primary_key=True)
name1 = Column("name1", String(10))
day1 = Column("day1", Date)
name2 = Column("name2", String(10))
day2 = Column("day2", Date)
name3 = Column("name3", String(10))
day3 = Column("day3", Date)
Base.metadata.create_all(engine)
session = Session(bind=engine)
#user_recherche d'identifiant
def serch_data(user_id):
try:
#user_Recherche par identifiant
res = session.query(User.name1, User.day1, User.name2, User.day2, User.name3, User.day3).filter(User.user_id==f"{user_id}").one()
#Insérez respectivement le nom et le jour dans la liste
name_list = [n for n in res if type(n) is str]
day_list = [str(d) for d in res if type(d) is datetime.date]
return name_list, day_list
#user_Passer si l'identifiant n'est pas enregistré
except NoResultFound:
pass
#user_enregistrement d'identifiant
def add_data(user_id):
session.add(User(user_id=f"{user_id}"))
#Mettre à jour les informations utilisateur
def update_data(user_id, num, text_name, birthday):
user_data = session.query(User).filter(User.user_id==f"{user_id}").one()
#Enregistrer le nom et le jour en fonction du nombre d'inscriptions
if num == 0:
user_data.name1 = text_name
user_data.day1 = birthday
elif num == 1:
user_data.name2 = text_name
user_data.day2 = birthday
elif num == 2:
user_data.name3 = text_name
user_data.day3 = birthday
#Enregistrer les modifications de la base de données et se déconnecter
def close_db():
session.commit()
session.close()
main.py
main.py
from flask import Flask, request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import (FollowEvent, PostbackEvent, TemplateSendMessage, MessageAction,\
ButtonsTemplate, DatetimePickerTemplateAction, ImageMessage, \
ImageSendMessage, MessageEvent, TextMessage, TextSendMessage)
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont, ImageFilter
import datetime
import os
import database
app = Flask(__name__)
app.debug = False
#Obtenir des variables d'environnement
YOUR_CHANNEL_ACCESS_TOKEN = os.environ["YOUR_CHANNEL_ACCESS_TOKEN"]
YOUR_CHANNEL_SECRET = os.environ["YOUR_CHANNEL_SECRET"]
line_bot_api = LineBotApi(YOUR_CHANNEL_ACCESS_TOKEN)
handler = WebhookHandler(YOUR_CHANNEL_SECRET)
#Chemin de référence de l'image
SRC_IMAGE_PATH = "static/images/{}.jpg "
MAIN_IMAGE_PATH = "static/images/{}_main.jpg "
PREVIEW_IMAGE_PATH = "static/images/{}_preview.jpg "
@app.route("/callback", methods=['POST'])
def callback():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
app.logger.info("Request body: " + body)
try:
handler.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
Importez le module et obtenez les variables d'environnement définies à l'avance, mais veuillez vérifier le rôle détaillé le cas échéant.
Définissez le chemin de la source de référence d'image décrite plus loin, et remplacez la partie {}
par message_id
lorsque l'image a été reçue.
main.py
#Suivez l'événement
@handler.add(FollowEvent)
def handle_follow(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=
"Merci de vous être inscrit comme ami. J'écrirai dans l'image l'âge de la personne sur la photo. Veuillez m'envoyer une image."))
Un message est envoyé lorsqu'un utilisateur ajoute un ami.
main.py
#Recevoir des images
@handler.add(MessageEvent, message=ImageMessage)
def handle_image(event):
global message_id, user_id, name_list, user_dict, num, src_image_path
#Liste de stockage des informations utilisateur
name_list = []
day_list = []
user_dict = {}
#message_Obtenir l'identifiant
message_id = event.message.id
#user_Obtenir l'identifiant
user_id = event.source.user_id
#Message de nom de fichier_Chemin converti en identifiant
src_image_path = Path(SRC_IMAGE_PATH.format(message_id)).absolute()
#Enregistrer temporairement les images sur Heroku
save_image(message_id, src_image_path)
#Vérifier les informations de l'utilisateur et réussir s'il n'est pas enregistré
try:
name_list, day_list = database.serch_data(user_id)
except TypeError:
pass
#Numéro d'enregistrement
num = len(name_list)
#Si non enregistré, vérifiez votre nom
if num == 0:
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Quel est le nom de la personne sur la photo?"))
#user_Ajouter un identifiant
database.add_data(user_id)
#Si vous avez une inscription, vérifiez qui est sur la photo
elif num != 0:
#Créez un dictionnaire avec le nom et le jour
user_dict = dict(zip(name_list, day_list))
#Lors de l'inscription d'une personne
if num == 1:
name_1 = name_list[0]
buttons_template = TemplateSendMessage(
alt_text="Qui est sur la photo?",
template=ButtonsTemplate(
text="Qui est sur la photo?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label="Autre", text="Autre")
]
)
)
#En cas d'inscription de 2 personnes
elif num == 2:
name_1 = name_list[0]
name_2 = name_list[1]
buttons_template = TemplateSendMessage(
alt_text="Qui est sur la photo?",
template=ButtonsTemplate(
text="Qui est sur la photo?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label="Autre", text="Autre")
]
)
)
#En cas d'inscription de 3 personnes
elif num == 3:
name_1 = name_list[0]
name_2 = name_list[1]
name_3 = name_list[2]
buttons_template = TemplateSendMessage(
alt_text="Qui est sur la photo?",
template=ButtonsTemplate(
text="Qui est sur la photo?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label=name_3, text=name_3),
MessageAction(label="Autre", text="Autre")
]
)
)
line_bot_api.reply_message(event.reply_token, buttons_template)
Spécifiez la variable que vous souhaitez utiliser autre que MessageEvent dans global
pour pouvoir y faire référence.
Dans l'instruction try name_list, day_list = database.serch_data (user_id)
, la name_list
qui stocke le nom et la day_list
qui stocke la date de naissance sont obtenues par la fonction serch_data
du fichier database
. Mise à jour de.
À ce stade, si user_id n'est pas enregistré, aucune valeur n'est renvoyée et elle ne peut pas être mise à jour, spécifiez donc TypeError
dans except.
En raison de la référence aux données, le traitement est divisé en cas où il n'y a pas d'enregistrement et en cas où il n'y a pas d'enregistrement.
Sinon, vérifiez le nom et ajoutez user_id.
Si tel est le cas, utilisez ʻuser_dict = dict (zip (name_list, day_list)) pour créer un dictionnaire faisant référence à la date de naissance en utilisant le nom comme clé. Après cela, le processus est divisé par 1 à 3 personnes enregistrées, et la personne sur la photo est confirmée avec
TemplateSendMessage`.
main.py
#Recevoir du texte
@handler.add(MessageEvent, message=TextMessage)
def handle_text(event):
global text_name, birthday
#Confirmation de la date de naissance si non enregistrée
if num == 0:
text_name = event.message.text
select_day(event)
#Si autre est sélectionné, vérifiez le nom
elif event.message.text == "Autre":
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Quel est le nom de la personne sur la photo?"))
else:
text_name = event.message.text
#Si le nom est déjà enregistré, obtenez la date de naissance
if text_name in name_list:
birthday = user_dict[text_name]
#Si si, sélectionnez la date de prise de vue, sinon sélectionnez la date de naissance
select_day(event)
ʻIf num == 0: `est exécuté lorsque vous recevez une réponse confirmant le nom lorsqu'il n'y a pas d'enregistrement, et procède à la confirmation de la date de naissance après avoir obtenu le nom.
ʻElif event.message.text == "Other": est exécuté quand autre est sélectionné dans
TemplateSendMessage` quand il y a enregistrement, et confirme le nom.
ʻElse: est exécuté lorsqu'un nom enregistré est sélectionné dans
TemplateSendMessageautre que celui ci-dessus, et quand une réponse est reçue après confirmation du nom. S'il est enregistré, utilisez
birthday = user_dict [text_name]` pour obtenir la date de naissance en utilisant le nom comme clé.
Pour les autres réponses, procédez à la sélection de la date et demandez-leur de sélectionner leur date de naissance.
main.py
#Traiter et envoyer des images
@handler.add(PostbackEvent)
def handle_postback(event):
global birthday
#Message de nom de fichier_Chemin converti en identifiant
main_image_path = MAIN_IMAGE_PATH.format(message_id)
preview_image_path = PREVIEW_IMAGE_PATH.format(message_id)
#Si l'anniversaire n'est pas défini
if not "birthday" in globals():
#Remplacer le résultat de l'action de sélection de date par anniversaire
birthday = event.postback.params["date"]
#Mettre à jour le nom et le jour
database.update_data(user_id, num, text_name, birthday)
#Sélection de la date de prise de vue
select_day(event)
#Si l'anniversaire est défini
elif "birthday" in globals():
#Traitement d'image
date_the_image(src_image_path, Path(main_image_path).absolute(), event)
date_the_image(src_image_path, Path(preview_image_path).absolute(), event)
#Spécifiez l'image
image_message = ImageSendMessage(
original_content_url=f"https://<nom de l'application heroku>.herokuapp.com/{main_image_path}",
preview_image_url=f"https://<nom de l'application heroku>.herokuapp.com/{preview_image_path}"
)
#Obtenir le journal
app.logger.info(f"https://<nom de l'application heroku>.herokuapp.com/{main_image_path}")
#Envoyer l'image
line_bot_api.reply_message(event.reply_token, image_message)
#Supprimer la variable anniversaire
del birthday
#Enregistrer les modifications de la base de données et se déconnecter
database.close_db()
ʻSi ce n'est pas "anniversaire" dans globals (): Si l'anniversaire n'est pas défini (la date de naissance a été sélectionnée par l'action de sélection de la date), le traitement est effectué. Obtenez la date sélectionnée par
anniversaire = event.postback.params [" date "]et mettez à jour le nom de la base de données et la date de naissance avec
database.update_data (user_id, num, text_name, birthday)` , Demandez-leur de sélectionner la date de prise de vue.
ʻElif "anniversaire" dans globals (): effectue le traitement lorsque l'anniversaire est défini (la date de prise de vue a été sélectionnée par l'action de sélection de la date).
image_message = ImageSendMessage(
original_content_url = f "https: //
Supprimez la variable anniversaire avec del birthday
afin qu'elle puisse être traitée normalement même lorsque les images sont envoyées en continu.
Enfin, enregistrez les modifications de la base de données avec close_db ()
dans le fichier de base de données, déconnectez-vous et quittez.
main.py
#Fonction de stockage d'image
def save_image(message_id: str, save_path: str) -> None:
# message_Obtenir les données binaires de l'image à partir de l'identifiant
message_content = line_bot_api.get_message_content(message_id)
with open(save_path, "wb") as f:
#Ecrire les données binaires acquises
for chunk in message_content.iter_content():
f.write(chunk)
En fait, je voulais obtenir les informations Exif de l'image et entrer automatiquement la date de prise de vue, mais je ne pouvais pas l'obtenir avec cette méthode, j'ai donc pris la forme de l'action de sélection de la date ci-dessus comme une mesure minutieuse. Si quelqu'un sait comment le faire, faites-le moi savoir.
main.py
#Fonction de sélection de la date
def select_day(event):
#Si l'anniversaire est défini
if "birthday" in globals():
message = "Veuillez sélectionner la date de prise de vue"
#Si l'anniversaire n'est pas défini
elif not "birthday" in globals():
message = "Veuillez sélectionner votre date de naissance"
#Action de sélection de la date
date_picker = TemplateSendMessage(
alt_text=message,
template=ButtonsTemplate(
text=message,
actions=[
DatetimePickerTemplateAction(
label="Choix",
data="action=buy&itemid=1",
mode="date",
initial=str(datetime.date.today()),
max=str(datetime.date.today())
)
]
)
)
line_bot_api.reply_message(event.reply_token, date_picker)
Cette fonction est exécutée une fois si la date de naissance est enregistrée, et deux fois au total si elle n'est pas enregistrée. Par conséquent, si l'anniversaire est défini, le message sera remplacé par la date de prise de vue, et s'il n'est pas défini, le message sera remplacé par la date de naissance.
main.py
#Fonction de traitement d'image
def date_the_image(src: str, desc: str, event) -> None:
im = Image.open(src)
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("./fonts/AquaKana.ttc", 50)
#Obtenez la date de tournage
date = event.postback.params["date"]
#Calculez le nombre de jours après la naissance en soustrayant la date de naissance de la date de prise de vue
how_old = datetime.datetime.strptime(date, "%Y-%m-%d") - datetime.datetime.strptime(str(birthday), "%Y-%m-%d")
#Jours de naissance et 365(journée)Calculer le quotient et le reste avec
years, days = divmod(how_old.days, 365)
#Reste 30(journée)Calculer le quotient avec
month = days // 30
text = text_name + f"({years}Talent{month}mois)"
#Taille du texte
text_width = draw.textsize(text, font=font)[0]
text_height = draw.textsize(text, font=font)[1]
margin = 10
x = im.width - text_width
y = im.height - text_height
#La taille du rectangle à dessiner
rect_size = ((text_width + margin * 6), (text_height + margin * 2))
#Dessinez un rectangle
rect = Image.new("RGB", rect_size, (0, 0, 0))
#Masque pour rendre le rectangle transparent
mask = Image.new("L", rect_size, 128)
#Coller un rectangle et un masque sur l'image
im.paste(rect, (x - margin * 6, y - margin * 3), mask)
#Rédaction de texte
draw.text((x - margin * 3, y - margin * 2), text, fill=(255, 255, 255), font=font)
im.save(desc)
Spécifiez la police et la taille à dessiner avec font = ImageFont.truetype (" ./fonts/AquaKana.ttc ", 50)
.
Lorsque vous dessinez en japonais, certaines polices ne sont pas prises en charge, alors sélectionnez-en une qui contient du japonais dans l'aperçu.
Obtenez la date de prise de vue avec date = event.postback.params [" date "]
et how_old = datetime.datetime.strptime (date,"% Y-% m-% d ") --datetime.datetime.strptime ( Utilisez str (anniversaire), "% Y-% m-% d")
pour obtenir le nombre de jours obtenu en soustrayant la date de naissance de la date de prise de vue.
Calculez le quotient et le reste en divisant le nombre de jours par 365 (jours) avec years, days = divmod (how_old.days, 365)
, et remplacez l'âge pour les années et le nombre de jours pour le reste pour les jours.
month = days // 12
convertit les jours restants en mois, et text = text_name + f" ({years} years {month} mois) "
définit ce qu'il faut écrire.
Utilisez rect_size = ((text_width + margin * 6), (text_height + margin * 2))
pour définir la taille du rectangle et du masque, et laissez une marge de 30px à gauche et à droite et 10px en haut et en bas du texte.
Enfin, spécifiez la position du rectangle et du masque avec ʻim.paste (rect, (x --margin * 6, y --margin * 3), mask) ʻet collez-le, etdraw.text ( Écrivez le texte avec (x --margin * 3, y --margin * 2), text, fill = (255, 255, 255), font = font)
et vous avez terminé.
main.py
if __name__ == "__main__":
#app.run()
port = int(os.getenv("PORT", 5000))
app.run(host="0.0.0.0", port=port)
database.py
database.py
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import create_engine, Column, String, Date
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.orm.exc import NoResultFound
import datetime
import os
#Obtenir l'URL de la base de données à partir de la variable d'environnement
DATABASE_URL = os.environ["DATABASE_URL"]
engine = create_engine(DATABASE_URL)
Base = declarative_base()
Tout d'abord, importez les modules requis dans le fichier de base de données.
DATABASE_URL spécifie l'URL de la base de données définie dans heroku config
.
ʻEngine = create_engine (DATABASE_URL) ,
Base = declarative_base () `sera utilisé pour la prochaine création de table.
database.py
#définition de table
class User(Base):
__tablename__ = "user_list"
user_id = Column("user_id", String(50), primary_key=True)
name1 = Column("name1", String(10))
day1 = Column("day1", Date)
name2 = Column("name2", String(10))
day2 = Column("day2", Date)
name3 = Column("name3", String(10))
day3 = Column("day3", Date)
Base.metadata.create_all(engine)
session = Session(bind=engine)
Dans class User (Base):
, spécifiez le nom de la table et le contenu de la colonne uniquement au moment de la création.
À ce stade, il est nécessaire de spécifier primary_key dans une colonne, alors spécifiez-le dans une colonne qui ne provoque pas de duplication.
Préparez-vous à vous connecter à la base de données avec Base.metadata.create_all (engine)
, session = Session (bind = engine)
.
database.py
#user_recherche d'identifiant
def serch_data(user_id):
try:
#user_Recherche par identifiant
res = session.query(User.name1, User.day1, User.name2, User.day2, User.name3, User.day3).filter(User.user_id==f"{user_id}").one()
#Insérez respectivement le nom et le jour dans la liste
name_list = [n for n in res if type(n) is str]
day_list = [str(d) for d in res if type(d) is datetime.date]
return name_list, day_list
#user_Passer si l'identifiant n'est pas enregistré
except NoResultFound:
pass
res = session.query (User.name1, User.day1, User.name2, User.day2, User.name3, User.day3) .filter (User.user_id == f" {user_id} "). one () Obtenez des informations autres que user_id sur la ligne où user_id correspond à
.
Comme user_id ne peut pas être dupliqué, spécifiez un seul avec ʻone () `.
name_list = [n for n in res if type (n) is str]
pour changer le type de chaîne (name) en name_list, day_list = [str (d) for d in res si type (d) est datetime.date] Insérez le type datetime.date (date de naissance) dans day_list sous forme de chaîne avec
.
Lorsque vous obtenez les informations avec res
, la colonne vide obtient None, mais cela ne s'applique à aucun des types ci-dessus, donc vous n'avez pas besoin de ʻif ~ n'est pas None. Renvoie deux listes avec
return name_list, day_list` et met à jour la liste dans main.py.
Si user_id n'est pas enregistré dans res, ce sera NoResultFound, alors spécifiez-le avec sauf pour l'éviter.
database.py
#user_enregistrement d'identifiant
def add_data(user_id):
session.add(User(user_id=f"{user_id}"))
#Mettre à jour les informations utilisateur
def update_data(user_id, num, text_name, birthday):
user_data = session.query(User).filter(User.user_id==f"{user_id}").one()
#Enregistrer le nom et le jour en fonction du nombre d'inscriptions
if num == 0:
user_data.name1 = text_name
user_data.day1 = birthday
elif num == 1:
user_data.name2 = text_name
user_data.day2 = birthday
elif num == 2:
user_data.name3 = text_name
user_data.day3 = birthday
Si user_id n'est pas enregistré dans session.add (User (user_id = f" {user_id} "))
, il sera ajouté.
ʻUser_data = session.query (User) .filter (User.user_id == f "{user_id}"). Obtenez des informations sur l'utilisateur avec one () `, branchez avec if et mettez à jour la colonne appropriée. À ce stade, j'ai essayé d'obtenir et de mettre à jour uniquement les colonnes nécessaires, mais une erreur s'est produite, il semble donc plus sûr d'obtenir toutes les informations.
database.py
#Enregistrer les modifications de la base de données et se déconnecter
def close_db():
session.commit()
session.close()
Enregistrez les modifications de la base de données avec session.commit ()
et déconnectez-vous avec session.close ()
pour terminer.
Environ deux mois après le dernier achèvement, j'ai réussi à incorporer la base de données avec laquelle je travaillais pour la première fois au point que je visais. En cours de route, j'ai essayé de nouvelles choses telles que le passage de MySQL à PostgreSQL et l'utilisation de sqlalchemy que je n'avais pas prévu d'utiliser au début, mais j'ai pu l'implémenter de manière relativement fluide par rapport à la fois précédente, et j'ai pu ressentir une légère croissance. ..
Pour ce bot, j'aimerais le compléter une fois et créer une application qui améliore les inconvénients quand j'ai le temps.
Recommended Posts