diff --git a/pyconfr-to-mastodon.py b/pyconfr-to-mastodon.py index e70fce2..179f9ff 100644 --- a/pyconfr-to-mastodon.py +++ b/pyconfr-to-mastodon.py @@ -4,15 +4,39 @@ import argparse import logging import re import sqlite3 -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from time import sleep +from pathlib import Path +from zoneinfo import ZoneInfo +from contextlib import suppress from mastodon import Mastodon +from jinja2 import Environment, FileSystemLoader +from html2image import Html2Image + + +def generate_file(output_path, title, author, type, date, salle): + environment = Environment(loader=FileSystemLoader("template/")) + template = environment.get_template("template.html") + + rend = template.render( + title=title, author=author, type=type, date=date, salle=salle + ) + + hti = Html2Image() + hti.load_file("template/illustration_1.png") + hti.load_file("template/logo_pyconfr_1.png") + hti.screenshot( + html_str=rend, + css_file="template/styles.css", + save_as=output_path, + size=(1200, 675), + ) def convert_datetime(val): """Convert ISO 8601 datetime to datetime.datetime object.""" - return datetime.fromisoformat(val.decode()) + return datetime.fromisoformat(val.decode() + "+00:00") sqlite3.register_converter("datetime", convert_datetime) @@ -64,7 +88,8 @@ def get_talks(django_site_id=4): with con: res = con.execute( f""" - SELECT cfp_talk.start_date, + SELECT cfp_talk.id, + cfp_talk.start_date, cfp_room.name room, GROUP_CONCAT(cfp_participant.name, x'00') participant, GROUP_CONCAT(cfp_participant.mastodon, x'00') mastodon, @@ -116,12 +141,28 @@ def live_toot(talks, mastodon: Mastodon, ahead_days=0): for talk in talks: if talk.category == "Sprint": continue # We don't toot sprints. - delta = talk.start_date - datetime.now() - timedelta(days=ahead_days) + delta = ( + talk.start_date - datetime.now(timezone.utc) - timedelta(days=ahead_days) + ) if delta.total_seconds() > 10: logging.info("Waiting %s for %s to start.", delta, talk.title) sleep(delta.total_seconds() - 2) # Wait for the talk to start. sleep(2) # This is just a fool guard so we can Ctrl-C easily anytime. - mastodon.toot(toot_for(talk, ahead_days)) + png_name = f"talk-{talk.id}.png" + with suppress(FileNotFoundError): + Path(png_name).unlink() + generate_file( + output_path=png_name, + title=talk.title, + author=", ".join(talk.participants), + type=talk.category.split()[0], + date=talk.start_date.astimezone(ZoneInfo("Europe/Paris")).strftime( + "%A %d %B %HH%M" + ), + salle="Salle " + talk.room.split("/")[0], + ) + media = mastodon.media_post("rend.png") + mastodon.status_post(toot_for(talk, ahead_days), media_ids=[media]) class DryRunMastodon: @@ -136,6 +177,12 @@ class DryRunMastodon: def toot(self, message): print(message) + def media_post(self, *args, **kwargs): + print("Would upload media to Mastodon.") + + def status_post(self, *args, **kwargs): + print("Would tooting", args, kwargs) + def main(): args = parse_args() diff --git a/requirements.txt b/requirements.txt index 11522db..820e72c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,3 @@ Mastodon.py +Jinja2==3.1.2 +html2image==2.0.1 diff --git a/template/illustration_1.png b/template/illustration_1.png new file mode 100644 index 0000000..96594d1 Binary files /dev/null and b/template/illustration_1.png differ diff --git a/template/logo_pyconfr_1.png b/template/logo_pyconfr_1.png new file mode 100644 index 0000000..cb33882 Binary files /dev/null and b/template/logo_pyconfr_1.png differ diff --git a/template/styles.css b/template/styles.css new file mode 100644 index 0000000..0ea291e --- /dev/null +++ b/template/styles.css @@ -0,0 +1,133 @@ +.1_3 { + overflow:hidden; +} +.e1_3 { + background-color:rgba(255, 255, 255, 1); + width:1200px; + height:675px; +} +.e1_4 { + width:1200px; + height:675px; + position:absolute; + left:0px; + top:0px; +} +.e4_34 { + width:1200px; + height:675px; + position:absolute; + left:0px; + top:0px; + background-image:url(illustration_1.png); + background-repeat:no-repeat; + background-size:cover; +} +.e1_8 { + background-color:rgba(22.4910007417202, 61.18752770125866, 69.30900290608406, 1); + width:975px; + height:309px; + position:absolute; + left:127px; + top:138px; + border-top-left-radius:16px; + border-top-right-radius:16px; + border-bottom-left-radius:16px; + border-bottom-right-radius:16px; +} +.e1_9 { + color:rgba(183.60000729560852, 242.1246188879013, 255, 1); + width:943px; + height:79px; + position:absolute; + left:16px; + top:8px; + font-family:Fira Sans; + text-align:center; + font-size:64px; + letter-spacing:5; +} +.e1_10 { + width:943px; + height:198px; + position:absolute; + left:16px; + top:95px; +} +.e1_11 { + color:rgba(255, 255, 255, 1); + width:943px; + height:154px; + position:absolute; + left:0px; + top:0px; + font-family:Fira Sans; + text-align:center; + font-size:42px; + letter-spacing:0; +} +.e1_12 { + color:rgba(255, 255, 255, 1); + width:943px; + height:44px; + position:absolute; + left:0px; + top:154px; + font-family:Fira Sans; + text-align:center; + font-size:30px; + letter-spacing:0; +} +.e1_13 { + background-color:rgba(250.00000029802322, 249.00000035762787, 247.00000047683716, 1); + width:739px; + height:115px; + position:absolute; + left:231px; + top:493px; + border-top-left-radius:16px; + border-top-right-radius:16px; + border-bottom-left-radius:16px; + border-bottom-right-radius:16px; +} +.e1_15 { + width:515px; + height:83px; + position:absolute; + left:208px; + top:16px; +} +.e1_16 { + color:rgba(22.000000588595867, 61.00000016391277, 69.00000348687172, 1); + width:515px; + height:38px; + position:absolute; + left:0px; + top:0px; + font-family:Fira Sans; + text-align:center; + font-size:44px; + letter-spacing:-2; +} +.e1_17 { + color:rgba(22.000000588595867, 61.00000016391277, 69.00000348687172, 1); + width:512px; + height:27px; + position:absolute; + left:0px; + top:56px; + font-family:Fira Sans; + text-align:center; + font-size:26px; + letter-spacing:-1.5; +} +.e4_35 { + width:176px; + height:83px; + position:absolute; + left:16px; + top:16px; + background-image:url(logo_pyconfr_1.png); + background-repeat:no-repeat; + background-size:cover; +} diff --git a/template/template.html b/template/template.html new file mode 100644 index 0000000..484d792 --- /dev/null +++ b/template/template.html @@ -0,0 +1,25 @@ + + + + + Html Generated + + + + + + + + + + + +
{{type}}
{{title}}{{type}} de {{author}}
{{date}}Université de Bordeaux · {{salle}}
+ + \ No newline at end of file diff --git a/template/variables.scss b/template/variables.scss new file mode 100644 index 0000000..4faaa11 --- /dev/null +++ b/template/variables.scss @@ -0,0 +1 @@ +$fira sans-font : "Fira Sans" \ No newline at end of file