Der zuvor erstellte Linienbot, der ein beliebiges Datum auf ein Foto zeichnet wurde verbessert, speichert den Namen und das Geburtsdatum in der Datenbank und wie alt es vom Aufnahmedatum ist Ich habe einen Linienbot erstellt, der berechnet, ob es sich um ein Foto handelt oder ob es in ein Bild geschrieben wird. Klicken Sie hier für Github
・ Assistent für Wachstumsaufzeichnungen (ID: @ 033cynwe)
--LineBot-Kanalerstellung
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
#Umgebungsvariablen abrufen
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)
#Bildverweispfad
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'
#Ereignis verfolgen
@handler.add(FollowEvent)
def handle_follow(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=
"Vielen Dank, dass Sie sich als Freund registriert haben. Ich werde auf dem Bild schreiben, wie alt die Person auf dem Bild ist. Bitte senden Sie mir ein Bild."))
#Bilder empfangen
@handler.add(MessageEvent, message=ImageMessage)
def handle_image(event):
global message_id, user_id, name_list, user_dict, num, src_image_path
#Liste zum Speichern von Benutzerinformationen
name_list = []
day_list = []
user_dict = {}
#message_ID abrufen
message_id = event.message.id
#user_ID abrufen
user_id = event.source.user_id
#Dateiname Nachricht_Pfad in ID konvertiert
src_image_path = Path(SRC_IMAGE_PATH.format(message_id)).absolute()
#Speichern Sie Bilder vorübergehend in Heroku
save_image(message_id, src_image_path)
#Überprüfen Sie die Benutzerinformationen und bestehen Sie sie, wenn Sie nicht registriert sind
try:
name_list, day_list = database.serch_data(user_id)
except TypeError:
pass
#Registrationsnummer
num = len(name_list)
#Wenn nicht registriert, überprüfen Sie Ihren Namen
if num == 0:
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Wie heißt die Person auf dem Foto?"))
#user_ID hinzufügen
database.add_data(user_id)
#Wenn Sie eine Registrierung haben, überprüfen Sie, wer auf dem Bild ist
elif num != 0:
#Erstellen Sie ein Wörterbuch mit Name und Tag
user_dict = dict(zip(name_list, day_list))
#Bei der Registrierung einer Person
if num == 1:
name_1 = name_list[0]
buttons_template = TemplateSendMessage(
alt_text="Wer ist auf dem Bild?",
template=ButtonsTemplate(
text="Wer ist auf dem Bild?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label="Andere", text="Andere")
]
)
)
#Bei Anmeldung von 2 Personen
elif num == 2:
name_1 = name_list[0]
name_2 = name_list[1]
buttons_template = TemplateSendMessage(
alt_text="Wer ist auf dem Bild?",
template=ButtonsTemplate(
text="Wer ist auf dem Bild?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label="Andere", text="Andere")
]
)
)
#Bei 3 Personen Registrierung
elif num == 3:
name_1 = name_list[0]
name_2 = name_list[1]
name_3 = name_list[2]
buttons_template = TemplateSendMessage(
alt_text="Wer ist auf dem Bild?",
template=ButtonsTemplate(
text="Wer ist auf dem Bild?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label=name_3, text=name_3),
MessageAction(label="Andere", text="Andere")
]
)
)
line_bot_api.reply_message(event.reply_token, buttons_template)
#Text empfangen
@handler.add(MessageEvent, message=TextMessage)
def handle_text(event):
global text_name, birthday
#Bestätigung des Geburtsdatums, falls nicht registriert
if num == 0:
text_name = event.message.text
select_day(event)
#Wenn andere ausgewählt ist, überprüfen Sie den Namen
elif event.message.text == "Andere":
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Wie heißt die Person auf dem Foto?"))
else:
text_name = event.message.text
#Wenn der Name bereits registriert ist, erhalten Sie das Geburtsdatum
if text_name in name_list:
birthday = user_dict[text_name]
#Wenn ja, wählen Sie das Aufnahmedatum, andernfalls das Geburtsdatum
select_day(event)
#Bilder verarbeiten und senden
@handler.add(PostbackEvent)
def handle_postback(event):
global birthday
#Dateiname Nachricht_Pfad in ID konvertiert
main_image_path = MAIN_IMAGE_PATH.format(message_id)
preview_image_path = PREVIEW_IMAGE_PATH.format(message_id)
#Wenn der Geburtstag nicht definiert ist
if not "birthday" in globals():
#Ersetzen Sie das Ergebnis der Datumsauswahlaktion durch den Geburtstag
birthday = event.postback.params["date"]
#Name und Tag aktualisieren
database.update_data(user_id, num, text_name, birthday)
#Auswahl des Aufnahmedatums
select_day(event)
#Wenn Geburtstag definiert ist
elif "birthday" in globals():
#Bildverarbeitung
date_the_image(src_image_path, Path(main_image_path).absolute(), event)
date_the_image(src_image_path, Path(preview_image_path).absolute(), event)
#Bild angeben
image_message = ImageSendMessage(
original_content_url=f"https://<Heroku App Name>.herokuapp.com/{main_image_path}",
preview_image_url=f"https://<Heroku App Name>.herokuapp.com/{preview_image_path}"
)
#Protokoll abrufen
app.logger.info(f"https://<Heroku App Name>.herokuapp.com/{main_image_path}")
#Bild senden
line_bot_api.reply_message(event.reply_token, image_message)
#Entfernen Sie die Variable Geburtstag
del birthday
#Speichern Sie Datenbankänderungen und trennen Sie die Verbindung
database.close_db()
#Bildspeicherfunktion
def save_image(message_id: str, save_path: str) -> None:
# message_Holen Sie sich Binärdaten des Bildes von ID
message_content = line_bot_api.get_message_content(message_id)
with open(save_path, "wb") as f:
#Schreiben Sie die erfassten Binärdaten
for chunk in message_content.iter_content():
f.write(chunk)
#Datumsauswahlfunktion
def select_day(event):
#Wenn Geburtstag definiert ist
if "birthday" in globals():
message = "Bitte wählen Sie das Aufnahmedatum"
#Wenn der Geburtstag nicht definiert ist
elif not "birthday" in globals():
message = "Bitte wählen Sie Ihr Geburtsdatum"
#Datumsauswahlaktion
date_picker = TemplateSendMessage(
alt_text=message,
template=ButtonsTemplate(
text=message,
actions=[
DatetimePickerTemplateAction(
label="Wahl",
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)
#Bildverarbeitungsfunktion
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)
#Holen Sie sich das Aufnahmedatum
date = event.postback.params["date"]
#Berechnen Sie die Anzahl der Tage nach der Geburt, indem Sie das Geburtsdatum vom Aufnahmedatum abziehen
how_old = datetime.datetime.strptime(date, "%Y-%m-%d") - datetime.datetime.strptime(str(birthday), "%Y-%m-%d")
#Geburtstage und 365(Tag)Quotient und Rest mit berechnen
years, days = divmod(how_old.days, 365)
#Rest 30(Tag)Quotient berechnen mit
month = days // 30
text = text_name + f"({years}Talent{month}Monate)"
#Textgröße
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
#Die Größe des zu zeichnenden Rechtecks
rect_size = ((text_width + margin * 6), (text_height + margin * 2))
#Zeichne ein Rechteck
rect = Image.new("RGB", rect_size, (0, 0, 0))
#Maske, um das Rechteck transparent zu machen
mask = Image.new("L", rect_size, 128)
#Fügen Sie ein Rechteck und eine Maske in das Bild ein
im.paste(rect, (x - margin * 6, y - margin * 3), mask)
#Text schreiben
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
#Datenbank-URL von Umgebungsvariable abrufen
DATABASE_URL = os.environ["DATABASE_URL"]
engine = create_engine(DATABASE_URL)
Base = declarative_base()
#Tabellendefinition
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_ID-Suche
def serch_data(user_id):
try:
#user_Suche nach ID
res = session.query(User.name1, User.day1, User.name2, User.day2, User.name3, User.day3).filter(User.user_id==f"{user_id}").one()
#Geben Sie den Namen und den Tag in die Liste ein
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_Bestehen, wenn die ID nicht registriert ist
except NoResultFound:
pass
#user_ID-Registrierung
def add_data(user_id):
session.add(User(user_id=f"{user_id}"))
#Benutzerinformationen aktualisieren
def update_data(user_id, num, text_name, birthday):
user_data = session.query(User).filter(User.user_id==f"{user_id}").one()
#Speichern Sie Name und Tag entsprechend der Anzahl der Registrierungen
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
#Speichern Sie Datenbankänderungen und trennen Sie die Verbindung
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
#Umgebungsvariablen abrufen
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)
#Bildverweispfad
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'
Importieren Sie das Modul und stellen Sie die Umgebungsvariablen im Voraus ein. Überprüfen Sie jedoch die entsprechende Rolle. Stellen Sie den Pfad der später beschriebenen Bildreferenzquelle ein und ersetzen Sie den Teil "{}" durch die "message_id", wenn das Bild empfangen wurde.
main.py
#Ereignis verfolgen
@handler.add(FollowEvent)
def handle_follow(event):
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text=
"Vielen Dank, dass Sie sich als Freund registriert haben. Ich werde auf dem Bild schreiben, wie alt die Person auf dem Bild ist. Bitte senden Sie mir ein Bild."))
Eine Nachricht wird gesendet, wenn ein Benutzer einen Freund hinzufügt.
main.py
#Bilder empfangen
@handler.add(MessageEvent, message=ImageMessage)
def handle_image(event):
global message_id, user_id, name_list, user_dict, num, src_image_path
#Liste zum Speichern von Benutzerinformationen
name_list = []
day_list = []
user_dict = {}
#message_ID abrufen
message_id = event.message.id
#user_
user_id = event.source.user_id
#_
src_image_path = Path(SRC_IMAGE_PATH.format(message_id)).absolute()
#
save_image(message_id, src_image_path)
#
try:
name_list, day_list = database.serch_data(user_id)
except TypeError:
pass
#
num = len(name_list)
#Pfad, in dem der Dateiname in messageid konvertiert wird Speichern Sie das Bild vorübergehend in Heroku. Überprüfen Sie die Benutzerinformationen und übergeben Sie, wenn keine Registrierung vorhanden ist. Anzahl der Registrierungen Wenn keine Registrierung vorliegt, überprüfen Sie den Namen
if num == 0:
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Wie heißt die Person auf dem Foto?"))
#user_ID hinzufügen
database.add_data(user_id)
#Wenn Sie eine Registrierung haben, überprüfen Sie, wer auf dem Bild ist
elif num != 0:
#Erstellen Sie ein Wörterbuch mit Name und Tag
user_dict = dict(zip(name_list, day_list))
#Bei der Registrierung einer Person
if num == 1:
name_1 = name_list[0]
buttons_template = TemplateSendMessage(
alt_text="Wer ist auf dem Bild?",
template=ButtonsTemplate(
text="Wer ist auf dem Bild?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label="Andere", text="Andere")
]
)
)
#Bei Anmeldung von 2 Personen
elif num == 2:
name_1 = name_list[0]
name_2 = name_list[1]
buttons_template = TemplateSendMessage(
alt_text="Wer ist auf dem Bild?",
template=ButtonsTemplate(
text="Wer ist auf dem Bild?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label="Andere", text="Andere")
]
)
)
#Bei 3 Personen Registrierung
elif num == 3:
name_1 = name_list[0]
name_2 = name_list[1]
name_3 = name_list[2]
buttons_template = TemplateSendMessage(
alt_text="Wer ist auf dem Bild?",
template=ButtonsTemplate(
text="Wer ist auf dem Bild?", actions=[
MessageAction(label=name_1, text=name_1),
MessageAction(label=name_2, text=name_2),
MessageAction(label=name_3, text=name_3),
MessageAction(label="Andere", text="Andere")
]
)
)
line_bot_api.reply_message(event.reply_token, buttons_template)
Geben Sie die Variable, die Sie außer MessageEvent verwenden möchten, in "global" an, damit Sie darauf verweisen können.
In der try-Anweisung "name_list, day_list = database.serch_data (user_id)" werden die "name_list", in der der Name gespeichert ist, und die "day_list", in der das Geburtsdatum gespeichert ist, von der Funktion "serch_data" der Datei "database" abgerufen. Aktualisieren zu. Wenn zu diesem Zeitpunkt user_id nicht registriert ist, wird kein Wert zurückgegeben und kann nicht aktualisiert werden. Geben Sie daher in Ausnahme "TypeError" an.
Aufgrund der Bezugnahme auf die Daten wird die Verarbeitung in Fälle ohne Registrierung und Fälle ohne Registrierung unterteilt. Wenn nicht, überprüfen Sie den Namen und fügen Sie user_id hinzu. Wenn dies der Fall ist, verwenden Sie "user_dict = dict (zip (name_list, day_list))", um ein Wörterbuch zu erstellen, das sich auf das Geburtsdatum bezieht und den Namen als Schlüssel verwendet. Danach wird der Prozess weiter durch 1 bis 3 registrierte Personen aufgeteilt und die Person auf dem Bild wird durch "TemplateSendMessage" bestätigt.
main.py
#Text empfangen
@handler.add(MessageEvent, message=TextMessage)
def handle_text(event):
global text_name, birthday
#Bestätigung des Geburtsdatums, falls nicht registriert
if num == 0:
text_name = event.message.text
select_day(event)
#Wenn andere ausgewählt ist, überprüfen Sie den Namen
elif event.message.text == "Andere":
line_bot_api.reply_message(
event.reply_token,
TextSendMessage(text="Wie heißt die Person auf dem Foto?"))
else:
text_name = event.message.text
#Wenn der Name bereits registriert ist, erhalten Sie das Geburtsdatum
if text_name in name_list:
birthday = user_dict[text_name]
#Wenn ja, wählen Sie das Aufnahmedatum, andernfalls das Geburtsdatum
select_day(event)
if num == 0:
wird ausgeführt, wenn Sie eine Antwort erhalten, die den Namen bestätigt, wenn keine Registrierung vorliegt, und das Geburtsdatum nach Erhalt des Namens bestätigt.
elif event.message.text ==" Other ":
wird ausgeführt, wenn Other bei TemplateSendMessage
ausgewählt ist, wenn eine Registrierung vorliegt, und bestätigt den Namen.
else:
wird ausgeführt, wenn ein anderer registrierter Name in TemplateSendMessage
als dem oben genannten ausgewählt ist und wenn nach Bestätigung des Namens eine Antwort eingeht.
Wenn registriert, verwenden Sie geburtstag = user_dict [text_name]
, um das Geburtsdatum mit dem Namen als Schlüssel zu erhalten.
Fahren Sie für andere Antworten mit der Datumsauswahl fort und bitten Sie sie, ihr Geburtsdatum auszuwählen.
main.py
#Bilder verarbeiten und senden
@handler.add(PostbackEvent)
def handle_postback(event):
global birthday
#Dateiname Nachricht_Pfad in ID konvertiert
main_image_path = MAIN_IMAGE_PATH.format(message_id)
preview_image_path = PREVIEW_IMAGE_PATH.format(message_id)
#Wenn der Geburtstag nicht definiert ist
if not "birthday" in globals():
#Ersetzen Sie das Ergebnis der Datumsauswahlaktion durch den Geburtstag
birthday = event.postback.params["date"]
#Name und Tag aktualisieren
database.update_data(user_id, num, text_name, birthday)
#Auswahl des Aufnahmedatums
select_day(event)
#Wenn Geburtstag definiert ist
elif "birthday" in globals():
#Bildverarbeitung
date_the_image(src_image_path, Path(main_image_path).absolute(), event)
date_the_image(src_image_path, Path(preview_image_path).absolute(), event)
#Bild angeben
image_message = ImageSendMessage(
original_content_url=f"https://<Heroku App Name>.herokuapp.com/{main_image_path}",
preview_image_url=f"https://<Heroku App Name>.herokuapp.com/{preview_image_path}"
)
#Protokoll abrufen
app.logger.info(f"https://<Heroku App Name>.herokuapp.com/{main_image_path}")
#Bild senden
line_bot_api.reply_message(event.reply_token, image_message)
#Entfernen Sie die Variable Geburtstag
del birthday
#Speichern Sie Datenbankänderungen und trennen Sie die Verbindung
database.close_db()
Führt die Verarbeitung durch, wenn der Geburtstag in "wenn nicht" Geburtstag "in globals () undefiniert ist:" (das Geburtsdatum wurde durch die Datumsauswahlaktion ausgewählt).
Holen Sie sich das von geburtstag = event.postback.params [" Datum "]
ausgewählte Datum und aktualisieren Sie den Datenbanknamen und das Geburtsdatum mit database.update_data (Benutzer_ID, Nummer, Textname, Geburtstag)
Bitten Sie sie, das Aufnahmedatum auszuwählen.
Führt die Verarbeitung durch, wenn der Geburtstag in "elif" Geburtstag "in globals () definiert ist:" (das Aufnahmedatum wurde durch die Datumsauswahlaktion ausgewählt).
image_message = ImageSendMessage( original_content_url = f "https: // <Name der Heroku-App> .herokuapp.com / {main_image_path}", Vorschau_image_url = f "https: // <Name der Heroku-App> .herokuapp.com / {Vorschau_Bildpfad}" )
Geben Sie das verarbeitete Bild an und senden Sie es.
Löschen Sie den variablen Geburtstag mit "Geburtstag löschen", damit er auch dann normal verarbeitet werden kann, wenn Bilder kontinuierlich gesendet werden. Speichern Sie abschließend die Datenbankänderungen mit "close_db ()" in der Datenbankdatei, trennen Sie die Verbindung und beenden Sie sie.
main.py
#Bildspeicherfunktion
def save_image(message_id: str, save_path: str) -> None:
# message_Holen Sie sich Binärdaten des Bildes von ID
message_content = line_bot_api.get_message_content(message_id)
with open(save_path, "wb") as f:
#Schreiben Sie die erfassten Binärdaten
for chunk in message_content.iter_content():
f.write(chunk)
Eigentlich wollte ich die Exif-Informationen des Bildes abrufen und das Aufnahmedatum automatisch eingeben, aber ich konnte es mit dieser Methode nicht abrufen, daher nahm ich die Form der obigen Datumsauswahlaktion als sorgfältige Maßnahme. Wenn jemand weiß, wie es geht, lass es mich wissen.
main.py
#Datumsauswahlfunktion
def select_day(event):
#Wenn Geburtstag definiert ist
if "birthday" in globals():
message = "Bitte wählen Sie das Aufnahmedatum"
#Wenn der Geburtstag nicht definiert ist
elif not "birthday" in globals():
message = "Bitte wählen Sie Ihr Geburtsdatum"
#Datumsauswahlaktion
date_picker = TemplateSendMessage(
alt_text=message,
template=ButtonsTemplate(
text=message,
actions=[
DatetimePickerTemplateAction(
label="Wahl",
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)
Diese Funktion wird einmal ausgeführt, wenn das Geburtsdatum registriert ist, und insgesamt zweimal, wenn es nicht registriert ist. Wenn also Geburtstag definiert ist, wird die Nachricht auf das Aufnahmedatum geändert, und wenn es nicht definiert ist, wird die Nachricht auf das Geburtsdatum geändert.
main.py
#Bildverarbeitungsfunktion
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)
#Holen Sie sich das Aufnahmedatum
date = event.postback.params["date"]
#Berechnen Sie die Anzahl der Tage nach der Geburt, indem Sie das Geburtsdatum vom Aufnahmedatum abziehen
how_old = datetime.datetime.strptime(date, "%Y-%m-%d") - datetime.datetime.strptime(str(birthday), "%Y-%m-%d")
#Geburtstage und 365(Tag)Quotient und Rest mit berechnen
years, days = divmod(how_old.days, 365)
#Rest 30(Tag)Quotient berechnen mit
month = days // 30
text = text_name + f"({years}Talent{month}Monate)"
#Textgröße
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
#Die Größe des zu zeichnenden Rechtecks
rect_size = ((text_width + margin * 6), (text_height + margin * 2))
#Zeichne ein Rechteck
rect = Image.new("RGB", rect_size, (0, 0, 0))
#Maske, um das Rechteck transparent zu machen
mask = Image.new("L", rect_size, 128)
#Fügen Sie ein Rechteck und eine Maske in das Bild ein
im.paste(rect, (x - margin * 6, y - margin * 3), mask)
#Text schreiben
draw.text((x - margin * 3, y - margin * 2), text, fill=(255, 255, 255), font=font)
im.save(desc)
Geben Sie die zu zeichnende Schriftart und Größe mit font = ImageFont.truetype (" ./fonts/AquaKana.ttc ", 50)
an.
Beim Zeichnen von Japanisch werden einige Schriftarten nicht unterstützt. Wählen Sie daher eine aus, die Japanisch in der Vorschau enthält.
Holen Sie sich das Aufnahmedatum mit date = event.postback.params [" date "]
und how_old = datetime.datetime.strptime (Datum,"% Y-% m-% d ") --datetime.datetime.strptime ( Verwenden Sie str (Geburtstag), "% Y-% m-% d")
, um die Anzahl der Tage zu erhalten, die durch Subtrahieren des Geburtsdatums vom Aufnahmedatum erhalten wurden.
Berechnen Sie den Quotienten und den Rest, indem Sie die Anzahl der Tage durch 365 (Tage) durch "Jahre, Tage = divmod (how_old.days, 365)" teilen und das Alter für Jahre und die Anzahl der Tage für den Rest durch Tage ersetzen.
month = days // 12
konvertiert die verbleibenden Tage in Monate und text = text_name + f" ({Jahre} Jahre {Monat} Monate) "
definiert, was geschrieben werden soll.
Verwenden Sie rect_size = ((text_width + margin * 6), (text_height + margin * 2))
, um die Größe des Rechtecks und der Maske festzulegen, und lassen Sie links und rechts einen Rand von 30px und oben und unten einen Rand von 10px.
Geben Sie abschließend die Position des Rechtecks und der Maske mit "im.paste (rect, (x - Rand * 6, y - Rand * 3), Maske)" an und fügen Sie sie ein und "draw.text" ( Schreiben Sie den Text mit (x - Rand * 3, y - Rand * 2), Text, Füllung = (255, 255, 255), Schriftart = Schriftart) und fertig.
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
#Datenbank-URL von Umgebungsvariable abrufen
DATABASE_URL = os.environ["DATABASE_URL"]
engine = create_engine(DATABASE_URL)
Base = declarative_base()
Importieren Sie zunächst die erforderlichen Module in die Datenbankdatei.
DATABASE_URL gibt die URL der in "heroku config" festgelegten Datenbank an.
engine = create_engine (DATABASE_URL)
undBase = declative_base ()
werden für die nächste Tabellenerstellung verwendet.
database.py
#Tabellendefinition
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)
Geben Sie in class User (Base):
den Tabellennamen und den Spalteninhalt nur zum Zeitpunkt der Erstellung an.
Zu diesem Zeitpunkt ist es erforderlich, in einer Spalte den Primärschlüssel anzugeben. Geben Sie ihn daher in einer Spalte an, die keine Duplizierung verursacht.
Bereiten Sie die Verbindung zur Datenbank mit "Base.metadata.create_all (engine)", "session = Session (bind = engine)" vor.
database.py
#user_ID-Suche
def serch_data(user_id):
try:
#user_Suche nach ID
res = session.query(User.name1, User.day1, User.name2, User.day2, User.name3, User.day3).filter(User.user_id==f"{user_id}").one()
#Geben Sie den Namen und den Tag in die Liste ein
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_Bestehen, wenn die ID nicht registriert ist
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 () Rufen Sie andere Informationen als user_id in der Zeile ab, in der user_id mit
übereinstimmt.
Da user_id nicht dupliziert werden kann, geben Sie nur eins mit one ()
an.
name_list = [n für n in res, wenn Typ (n) str ist]
um den str-Typ (name) in name_list zu ändern, day_list = [str (d) für d in res, wenn Typ (d) datetime.date ist] Fügen Sie den Typ datetime.date (Geburtsdatum) als Zeichenfolge mit
in day_list ein.
Wenn Sie die Informationen mit "res" erhalten, wird in der leeren Spalte "Keine" angezeigt, dies gilt jedoch nicht für einen der oben genannten Typen. Sie benötigen also "Wenn ~ nicht" Keine "ist.
Gibt zwei Listen mit return name_list, day_list
zurück und aktualisiert die Liste in main.py.
Wenn user_id nicht in res registriert ist, ist es NoResultFound. Geben Sie es daher mit Ausnahme an, um dies zu vermeiden.
database.py
#user_ID-Registrierung
def add_data(user_id):
session.add(User(user_id=f"{user_id}"))
#Benutzerinformationen aktualisieren
def update_data(user_id, num, text_name, birthday):
user_data = session.query(User).filter(User.user_id==f"{user_id}").one()
#Speichern Sie Name und Tag entsprechend der Anzahl der Registrierungen
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
Wenn user_id nicht in session.add (User (user_id = f" {user_id} "))
registriert ist, wird es hinzugefügt.
Erhalten Sie Benutzerinformationen mit user_data = session.query (User) .filter (User.user_id == f" {user_id} "). One ()
, verzweigen Sie mit if und aktualisieren Sie die entsprechende Spalte.
Zu diesem Zeitpunkt habe ich versucht, nur die erforderlichen Spalten abzurufen und zu aktualisieren. Es ist jedoch ein Fehler aufgetreten, sodass es sicherer erscheint, alle Informationen abzurufen.
database.py
#Speichern Sie Datenbankänderungen und trennen Sie die Verbindung
def close_db():
session.commit()
session.close()
Speichern Sie die Datenbankänderungen mit "session.commit ()" und trennen Sie die Verbindung mit "session.close ()", um den Vorgang abzuschließen.
Ungefähr zwei Monate nach letzter Fertigstellung gelang es mir, die Datenbank, mit der ich mich zum ersten Mal befasste, bis zu dem Punkt einzubinden, den ich anstrebte. Unterwegs habe ich neue Dinge ausprobiert, wie den Wechsel von MySQL zu PostgreSQL und die Verwendung von SQLalchemy, die ich zu Beginn nicht verwenden wollte, aber ich konnte sie im Vergleich zum vorherigen Mal relativ reibungslos implementieren, und ich konnte ein leichtes Wachstum spüren. ..
Für diesen Bot möchte ich ihn einmal ausfüllen und eine Anwendung erstellen, die die Unannehmlichkeiten verbessert, wenn ich Zeit habe.
Recommended Posts