initial framework
This commit is contained in:
		
							
								
								
									
										
											BIN
										
									
								
								.bot_storage/db.sqlite
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								.bot_storage/db.sqlite
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										26
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| kind: pipeline | ||||
| type: kubernetes | ||||
| name: docker-build | ||||
|  | ||||
| node_selector: | ||||
|   kubernetes.io/arch: arm64 | ||||
|  | ||||
|  | ||||
| steps: | ||||
| - name: docker   | ||||
|   image: plugins/docker | ||||
|   settings: | ||||
|     username:  | ||||
|       from_secret: docker_uname | ||||
|     password: | ||||
|       from_secret: docker_pw | ||||
|  | ||||
|     repo: mollre/journal-bot | ||||
|     tags: latest | ||||
|  | ||||
|  | ||||
| trigger: | ||||
|   branch: | ||||
|   - main | ||||
|   event: | ||||
|   - push | ||||
							
								
								
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,3 +1,7 @@ | ||||
| # Secrets | ||||
| dev.env | ||||
| secret.yaml | ||||
|  | ||||
| # ---> Python | ||||
| # Byte-compiled / optimized / DLL files | ||||
| __pycache__/ | ||||
|   | ||||
							
								
								
									
										12
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -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"] | ||||
							
								
								
									
										7
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
							
								
								
									
										13
									
								
								Pipfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								Pipfile
									
									
									
									
									
										Normal file
									
								
							| @@ -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" | ||||
							
								
								
									
										101
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								Pipfile.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							| @@ -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": {} | ||||
| } | ||||
							
								
								
									
										76
									
								
								bot/commands/journal.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								bot/commands/journal.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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   | ||||
							
								
								
									
										35
									
								
								bot/main.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								bot/main.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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() | ||||
							
								
								
									
										35
									
								
								bot/models.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								bot/models.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||
							
								
								
									
										0
									
								
								deployment/deployment.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								deployment/deployment.yaml
									
									
									
									
									
										Normal file
									
								
							
		Reference in New Issue
	
	Block a user