Merge pull request 'cronjobs' (#2) from cronjobs into main
All checks were successful
continuous-integration/drone/push Build is passing

Reviewed-on: #2
This commit is contained in:
Remy Moll 2023-05-24 13:59:32 +00:00
commit 3f58eab8c7
6 changed files with 176 additions and 53 deletions

View File

@ -4,7 +4,10 @@ verify_ssl = true
name = "pypi"
[packages]
python-telegram-bot = "*"
peewee = "*"
python-telegram-bot = {extras = ["job-queue"], version = "*"}
[dev-packages]
[pipenv]
allow_prereleases = true

87
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "e95b9deab62bd0c661f20a178b8701fc84420db5f663fa4416666e1d05f6ce76"
"sha256": "cd959bb2617886ea733bed6ee34cda38a9ab3c744963543582bb7e18ca1c9722"
},
"pipfile-spec": 6,
"requires": {},
@ -16,19 +16,26 @@
"default": {
"anyio": {
"hashes": [
"sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421",
"sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3"
"sha256:691adfc3c36c0d922c69a8d4105e73cf4cf697f7e66a1baf04347bf5f1a0d6a9",
"sha256:8ffa2a3572d4a9852481fb6f8b7fd3c678b27860e07b8789da4ddb06675aa219"
],
"markers": "python_full_version >= '3.6.2'",
"version": "==3.6.2"
"markers": "python_version >= '3.7'",
"version": "==3.7.0rc1"
},
"apscheduler": {
"hashes": [
"sha256:0293937d8f6051a0f493359440c1a1b93e882c57daf0197afeff0e727777b96e",
"sha256:e813ad5ada7aff36fb08cdda746b520531eaac7757832abc204868ba78e0c8f6"
],
"version": "==3.10.1"
},
"certifi": {
"hashes": [
"sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3",
"sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"
"sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7",
"sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"
],
"markers": "python_version >= '3.6'",
"version": "==2022.12.7"
"version": "==2023.5.7"
},
"h11": {
"hashes": [
@ -40,19 +47,19 @@
},
"httpcore": {
"hashes": [
"sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb",
"sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0"
"sha256:628e768aaeec1f7effdc6408ba1c3cdbd7487c1fc570f7d66844ec4f003e1ca4",
"sha256:caf508597c525f9b8bfff187e270666309f63115af30f7d68b16143a403c8356"
],
"markers": "python_version >= '3.7'",
"version": "==0.16.3"
"version": "==0.17.1"
},
"httpx": {
"hashes": [
"sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9",
"sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6"
"sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd",
"sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd"
],
"markers": "python_version >= '3.7'",
"version": "==0.23.3"
"version": "==0.24.1"
},
"idna": {
"hashes": [
@ -70,22 +77,38 @@
"version": "==3.16.2"
},
"python-telegram-bot": {
"extras": [
"job-queue"
],
"hashes": [
"sha256:4d1d4b643ce158aa17a0987b84005eaf25fe0ce8b38fd234099594985611c198",
"sha256:d0aa53e1f06d7cb7919cc0e2d6c81a02d968fc29921aeaa962edd1efb816a9bd"
"sha256:1185edee387db7b08027e87b67fa9a3cc3263ae5ab5bb55513acd1bca5c3cf4b",
"sha256:73e46a534be9d1c790ce8b494765cca18a5c2f3f5b4932d83bcb06bb0051eb4a"
],
"index": "pypi",
"version": "==20.2"
"version": "==20.3"
},
"rfc3986": {
"extras": [
"idna2008"
],
"pytz": {
"hashes": [
"sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835",
"sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97"
"sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588",
"sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"
],
"version": "==1.5.0"
"version": "==2023.3"
},
"setuptools": {
"hashes": [
"sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f",
"sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"
],
"markers": "python_version >= '3.7'",
"version": "==67.8.0"
},
"six": {
"hashes": [
"sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
"sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
],
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
"version": "==1.16.0"
},
"sniffio": {
"hashes": [
@ -94,6 +117,22 @@
],
"markers": "python_version >= '3.7'",
"version": "==1.3.0"
},
"tzdata": {
"hashes": [
"sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a",
"sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"
],
"markers": "platform_system == 'Windows'",
"version": "==2023.3"
},
"tzlocal": {
"hashes": [
"sha256:46eb99ad4bdb71f3f72b7d24f4267753e240944ecfc16f25d2719ba89827a803",
"sha256:f3596e180296aaf2dbd97d124fe76ae3a0e3d32b258447de7b939b3fd4be992f"
],
"markers": "python_version >= '3.7'",
"version": "==5.0.1"
}
},
"develop": {}

View File

@ -30,7 +30,6 @@ class MemoryHandler(BaseHandler):
search_string = " ".join(context.args)
if search_string == '~photo':
matching_models = self.models.JournalEntry.select().where(self.models.JournalEntry.media_path != "").order_by(self.models.JournalEntry.date)
else: # searching for text
@ -40,7 +39,12 @@ class MemoryHandler(BaseHandler):
)
).order_by(self.models.JournalEntry.date)
# exit if no memory matches the string
if len(matching_models) == 0:
await update.message.reply_text(f"There is no matching memory yet.")
return ConversationHandler.END
options = [[InlineKeyboardButton(m.date_pretty, callback_data=i)] for i,m in enumerate(matching_models)]
keyboard = InlineKeyboardMarkup(options)

View File

@ -1,22 +1,45 @@
import os
from pathlib import Path
from telegram.ext import ExtBot
import random
from telegram.error import BadRequest
import logging
from datetime import time, timedelta, timezone, datetime, date
from peewee import fn
MEDIA_DIR = Path(os.getenv("MEDIA_DIR"))
CHAT_ID = os.getenv("CHAT_ID")
async def set_random(bot: ExtBot) -> None:
"""Set a random chat photo."""
if os.getenv("DOCKERIZED", "false") == "false":
# only change image on prod
return
photos = list(MEDIA_DIR.glob("*.jpg")) + list(MEDIA_DIR.glob("*.png")) + list(MEDIA_DIR.glob("*.jpeg"))
if len(photos) == 0:
return
class SetChatPhotoJob():
def __init__(self, models, bot: ExtBot, job_queue):
self.models = models
self.bot = bot
self.logger = logging.getLogger(self.__class__.__name__)
if os.getenv("DOCKERIZED", "false") != "true":
# when running locally, annoy the programmer every 60 seconds <3
job_queue.run_repeating(self.callback_photo, interval=60)
else:
# set the message sending time; include UTC shift +2
sending_time = time(hour=12, minute=0, second=0, tzinfo=timezone(timedelta(hours=2)))
job_queue.run_monthly(self.callback_photo, when=sending_time, day=-1)
photo = random.choice(photos)
await bot.set_chat_photo(CHAT_ID, photo)
async def callback_photo(self, context):
# last_seen of memory must be older than 10 days in past or None
with self.models.db:
possible_photos = self.models.JournalEntry.select().where(
self.models.JournalEntry.media_path != None
).order_by(fn.Random())
try:
chosen_entry = possible_photos.get()
except:
self.logger.warning("No photos available.")
return
chat_id = os.getenv("CHAT_ID")
try:
await self.bot.set_chat_photo(chat_id, chosen_entry.media_path)
except BadRequest:
self.logger.error("This is a private chat!")
return

View File

@ -0,0 +1,61 @@
from datetime import time, timedelta, timezone, datetime, date
import os
from peewee import fn
import logging
class RandomMemoryJob():
def __init__(self, models, bot, job_queue):
self.models = models
self.bot = bot
self.logger = logging.getLogger(self.__class__.__name__)
if os.getenv("DOCKERIZED", "false") != "true":
# when running locally, annoy the programmer every 60 seconds <3
job_queue.run_repeating(self.callback_memory, interval=60)
self.min_age = 0 # do not filter messages: show them all
else:
# set the message sending time; include UTC shift +2
sending_time = time(hour=12, minute=0, second=0, tzinfo=timezone(timedelta(hours=2)))
job_queue.run_daily(self.callback_memory, sending_time)
self.min_age = 30 # days
async def callback_memory(self, context):
# last_seen of memory must be older than 10 days in past or None
with self.models.db:
possible_entries = self.models.JournalEntry.select().where(
(self.models.JournalEntry.last_shown <= datetime.today().date() - timedelta(days=self.min_age)) | \
(self.models.JournalEntry.last_shown == None)
).order_by(fn.Random())
try:
chosen_entry = possible_entries.get()
except:
self.logger.warning("Come back later for another memory.")
return
# update the last_shown of the chosen entry
chosen_entry.last_shown = datetime.today().date()
chosen_entry.save()
chat_id = os.getenv("CHAT_ID")
if chosen_entry.media_path:
await self.bot.send_photo(
chat_id = chat_id,
photo = chosen_entry.media_path,
caption =
f"On {chosen_entry.date_pretty}, "
f"{chosen_entry.author} wrote: \n"
f"{chosen_entry.text}"
)
else:
await self.bot.send_message(
chat_id = chat_id,
text =
f"On {chosen_entry.date_pretty}, "
f"{chosen_entry.author} wrote: \n"
f"{chosen_entry.text}"
)

View File

@ -5,14 +5,13 @@ import logging
import models
from commands import journal, status, turtle, memory
from commands.list import list
from cronjob import chat_photo
from cronjob import chat_photo, random_memory
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
level=logging.INFO
)
import asyncio
logging.getLogger("httpx").setLevel(logging.WARNING)
logger = logging.getLogger(__name__)
@ -24,21 +23,15 @@ def main() -> None:
models.set_db(db_path)
application = Application.builder().token(token).build()
application.add_handler(journal.JournalHandler("journal", models).handler)
application.add_handler(list.ListHandler("list", models).handler)
application.add_handler(status.StatusHandler("status", models).handler)
application.add_handler(turtle.TurtleHandler().handler)
application.add_handler(memory.MemoryHandler("memory", models).handler)
# application.add_handler(CommandHandler("help", help_command))
# on non command i.e message - echo the message on Telegram
# application.add_handler(InlineQueryHandler(inline_query))
random_memory.RandomMemoryJob(models, application.bot, application.job_queue)
chat_photo.SetChatPhotoJob(models, application.bot, application.job_queue)
# on every start set a new chat photo
# loop = asyncio.get_event_loop()
asyncio.ensure_future(chat_photo.set_random(application.bot))
# Run the bot until the user presses Ctrl-C
application.run_polling()