From 6570de995de2bb1813677fa2ad2295d3fd7b12e6 Mon Sep 17 00:00:00 2001 From: Remy Moll Date: Wed, 19 Apr 2023 23:38:09 +0200 Subject: [PATCH] initial framework --- .bot_storage/db.sqlite | Bin 0 -> 12288 bytes .drone.yml | 26 ++++++++++ .gitignore | 4 ++ Dockerfile | 12 +++++ Makefile | 7 +++ Pipfile | 13 +++++ Pipfile.lock | 101 +++++++++++++++++++++++++++++++++++++ bot/commands/journal.py | 76 ++++++++++++++++++++++++++++ bot/main.py | 35 +++++++++++++ bot/models.py | 35 +++++++++++++ deployment/deployment.yaml | 0 11 files changed, 309 insertions(+) create mode 100644 .bot_storage/db.sqlite create mode 100644 .drone.yml create mode 100644 Dockerfile create mode 100644 Makefile create mode 100644 Pipfile create mode 100644 Pipfile.lock create mode 100644 bot/commands/journal.py create mode 100644 bot/main.py create mode 100644 bot/models.py create mode 100644 deployment/deployment.yaml diff --git a/.bot_storage/db.sqlite b/.bot_storage/db.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..466c21efbda9fa7692e9df748f60e862077386d0 GIT binary patch literal 12288 zcmeI#O-sWt7zgkq6L#|Dw!Sls00Izz00bZa0SG_<0ub0wfnp%qonDV`M$Wu0>|3_ZS7u>XF8^%C zt(#Z{T9FQ}Lq)Qgl5{H5MA9(Q>Q==RJ!pz1VMveh@IHvAG*Z)Zl8JFv(xCiEy~58r z`{5*M_3Zal`~2+ECaHOOH*WqjXVz|><=^Jdic8+^bh~^LG_O$|Q~Y}Pe{t@zHupt8 z8U!E!0SG_<0uX=z1Rwwb2tWV=J1l_ue}{iAt_A@JKmY;|fB*y_009U<00I!G1ik Python # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c0c6476 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.10 +ENV dockerized=true + +WORKDIR /app + +COPY Pipfile Pipfile.lock ./ + +RUN pip install pipenv && pipenv install --system --deploy + +COPY bot . + +CMD ["python", "main.py"] \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f3536c5 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +CURRENT_DIR := $(shell pwd) +DOTENV := ${CURRENT_DIR}/dev.env +PIPENV_CMD_PREFIX := PIPENV_DOTENV_LOCATION=${DOTENV} pipenv run + + +run: + ${PIPENV_CMD_PREFIX} python bot/main.py \ No newline at end of file diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..791c853 --- /dev/null +++ b/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +python-telegram-bot = "*" +peewee = "*" + +[dev-packages] + +[requires] +python_version = "3.10" diff --git a/Pipfile.lock b/Pipfile.lock new file mode 100644 index 0000000..bbfd1ef --- /dev/null +++ b/Pipfile.lock @@ -0,0 +1,101 @@ +{ + "_meta": { + "hash": { + "sha256": "b71137ebde2ce3e6bcde400dad601555ccee09d26530c8e928d76d49aae43fee" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.10" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "anyio": { + "hashes": [ + "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421", + "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3" + ], + "markers": "python_full_version >= '3.6.2'", + "version": "==3.6.2" + }, + "certifi": { + "hashes": [ + "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", + "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" + ], + "markers": "python_version >= '3.6'", + "version": "==2022.12.7" + }, + "h11": { + "hashes": [ + "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", + "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761" + ], + "markers": "python_version >= '3.7'", + "version": "==0.14.0" + }, + "httpcore": { + "hashes": [ + "sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb", + "sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0" + ], + "markers": "python_version >= '3.7'", + "version": "==0.16.3" + }, + "httpx": { + "hashes": [ + "sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9", + "sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6" + ], + "markers": "python_version >= '3.7'", + "version": "==0.23.3" + }, + "idna": { + "hashes": [ + "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", + "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" + ], + "version": "==3.4" + }, + "peewee": { + "hashes": [ + "sha256:1800c0a04962ee99d161c07f5a12fc49549caf5cfcda426a9103e34e37f854ba" + ], + "index": "pypi", + "version": "==3.16.0" + }, + "python-telegram-bot": { + "hashes": [ + "sha256:4d1d4b643ce158aa17a0987b84005eaf25fe0ce8b38fd234099594985611c198", + "sha256:d0aa53e1f06d7cb7919cc0e2d6c81a02d968fc29921aeaa962edd1efb816a9bd" + ], + "index": "pypi", + "version": "==20.2" + }, + "rfc3986": { + "extras": [ + "idna2008" + ], + "hashes": [ + "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835", + "sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97" + ], + "version": "==1.5.0" + }, + "sniffio": { + "hashes": [ + "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101", + "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0" + } + }, + "develop": {} +} diff --git a/bot/commands/journal.py b/bot/commands/journal.py new file mode 100644 index 0000000..0ca07bf --- /dev/null +++ b/bot/commands/journal.py @@ -0,0 +1,76 @@ +import datetime + +from telegram.ext import ConversationHandler, CommandHandler, MessageHandler, filters, CallbackQueryHandler, CallbackContext +from telegram import InlineKeyboardButton, InlineKeyboardMarkup +DATE_CHOICE, DATE_ENTRY, CONTENT = range(3) + + +class JournalHandler: + def __init__(self, entry_string, models): + self.models = models + + self.handler = ConversationHandler( + entry_points=[CommandHandler(entry_string, self.start)], + states={ + DATE_CHOICE: [ + CallbackQueryHandler(self.date_choice), + ], + DATE_ENTRY: [ + MessageHandler(filters.TEXT, self.date_entry), + ], + CONTENT: [ + MessageHandler(filters.TEXT, self.content_text), + MessageHandler(filters.ATTACHMENT, self.content_media), + ], + }, + fallbacks=[], + ) + + self.current_model = None + + async def start(self, update, context): + """Send a message when the command /start is issued.""" + + options = [ + InlineKeyboardButton("Today", callback_data="today"), + InlineKeyboardButton("Yesterday", callback_data="yesterday"), + InlineKeyboardButton("Custom date", callback_data="custom"), + ] + keyboard = InlineKeyboardMarkup([options]) + await update.message.reply_text("Please choose an option for the entry:", reply_markup=keyboard) + return DATE_CHOICE + + async def date_choice(self, update, context): + query = update.callback_query + query.answer() + if query.data == "today" or query.data == "yesterday": + date = datetime.datetime.now().date() if query.data == "today" else datetime.datetime.now().date() - datetime.timedelta(days=1) + self.current_model = self.models.JournalEntry( + date = date + ) + return CONTENT + else: + await query.edit_message_text(text="Please enter the date in the format DDMMYYYY") + return DATE_ENTRY + + async def date_entry(self, update, context): + # create an inline keyboard with the option today and yesterday and custom + # date + date = update.message.text + try: + date = datetime.datetime.strptime(date, "%d%m%Y").date() + self.current_model = self.models.JournalEntry( + date = date + ) + except ValueError: + await update.message.reply_text("Please enter the date in the format DDMMYYYY") + return DATE_ENTRY + + await update.message.reply_text("Please enter the content for the entry") + return CONTENT + + async def content_text(self, update, context): + + return + async def content_media(self, update, context): + return \ No newline at end of file diff --git a/bot/main.py b/bot/main.py new file mode 100644 index 0000000..8fad5e1 --- /dev/null +++ b/bot/main.py @@ -0,0 +1,35 @@ +import os +from telegram.ext import Application +import logging + +from commands import journal +import models + +logging.basicConfig( + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO +) + +logger = logging.getLogger(__name__) + + +def main() -> None: + """Run the bot.""" + + token = os.getenv("BOT_TOKEN") + db_path = os.getenv("DB_PATH") + models.set_db(db_path) + application = Application.builder().token(token).build() + + + application.add_handler(journal.JournalHandler("journal", 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)) + + # Run the bot until the user presses Ctrl-C + application.run_polling() + + + +if __name__ == "__main__": + main() diff --git a/bot/models.py b/bot/models.py new file mode 100644 index 0000000..122b27c --- /dev/null +++ b/bot/models.py @@ -0,0 +1,35 @@ +from peewee import * +from pathlib import Path + +db = DatabaseProxy() + +class BaseModel(Model): + class Meta: + database = db + db_table = 'journal' + + +# model for a single journal entry +class JournalEntry(BaseModel): + # the date of the entry + date = DateField() + # the text of the entry + text = TextField() + media_path = TextField() + author = TextField() + + + @property + def media(self): + return Path(self.media_path).open('rb') + + @media.setter + def media(self, media): + self.media_path = Path(media).absolute() + self.save() + + +def set_db(db_path): + db.initialize(SqliteDatabase(db_path)) + db.connect() + db.create_tables([JournalEntry], safe=True) \ No newline at end of file diff --git a/deployment/deployment.yaml b/deployment/deployment.yaml new file mode 100644 index 0000000..e69de29