added journal command

This commit is contained in:
Remy Moll 2023-04-20 16:14:51 +02:00
parent 6570de995d
commit 2cd790e662
7 changed files with 175 additions and 20 deletions

Binary file not shown.

3
.gitignore vendored
View File

@ -2,6 +2,9 @@
dev.env dev.env
secret.yaml secret.yaml
# Static data
.bot_storage/
# ---> Python # ---> Python
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/

26
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true
},
{
"name": "Python: Current project",
"type": "python",
"request": "launch",
"program": "${workspaceFolder}/bot/main.py",
"console": "integratedTerminal",
"justMyCode": true,
"envFile": "${workspaceFolder}/dev.env",
}
]
}

View File

@ -1,5 +1,5 @@
FROM python:3.10 FROM python:3.10
ENV dockerized=true ENV DOCKERIZED=true
WORKDIR /app WORKDIR /app

View File

@ -1,6 +1,6 @@
import datetime import datetime
import os
from telegram.ext import ConversationHandler, CommandHandler, MessageHandler, filters, CallbackQueryHandler, CallbackContext from telegram.ext import ConversationHandler, CommandHandler, MessageHandler, filters, CallbackQueryHandler
from telegram import InlineKeyboardButton, InlineKeyboardMarkup from telegram import InlineKeyboardButton, InlineKeyboardMarkup
DATE_CHOICE, DATE_ENTRY, CONTENT = range(3) DATE_CHOICE, DATE_ENTRY, CONTENT = range(3)
@ -28,8 +28,15 @@ class JournalHandler:
self.current_model = None self.current_model = None
async def start(self, update, context): async def start(self, update, context):
"""Send a message when the command /start is issued.""" """Send a message when the command /start is issued."""
if os.getenv("DOCKERIZED", "false") == "true" and os.getenv("CHAT_ID") != str(update.message.chat_id):
await update.message.reply_text("You are not authorized to use this bot")
return ConversationHandler.END
print(f"User: {update.message.from_user.id}")
print(f"Chat: {update.message.chat_id}")
options = [ options = [
InlineKeyboardButton("Today", callback_data="today"), InlineKeyboardButton("Today", callback_data="today"),
@ -40,28 +47,36 @@ class JournalHandler:
await update.message.reply_text("Please choose an option for the entry:", reply_markup=keyboard) await update.message.reply_text("Please choose an option for the entry:", reply_markup=keyboard)
return DATE_CHOICE return DATE_CHOICE
async def date_choice(self, update, context): async def date_choice(self, update, context):
query = update.callback_query query = update.callback_query
query.answer() await query.answer()
if query.data == "today" or query.data == "yesterday": 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) date = datetime.datetime.now().date() if query.data == "today" else datetime.datetime.now().date() - datetime.timedelta(days=1)
self.current_model = self.models.JournalEntry( self.current_model, new = self.models.JournalEntry.get_or_create(
date = date date = date
) )
if not new:
await query.edit_message_text(text="An entry already exists for this date")
return ConversationHandler.END
await query.edit_message_text(
text="Please enter the content for the entry"
)
return CONTENT return CONTENT
else: else:
await query.edit_message_text(text="Please enter the date in the format DDMMYYYY") await query.edit_message_text(text="Please enter the date in the format DDMMYYYY")
return DATE_ENTRY return DATE_ENTRY
async def date_entry(self, update, context): async def date_entry(self, update, context):
# create an inline keyboard with the option today and yesterday and custom
# date
date = update.message.text date = update.message.text
try: try:
date = datetime.datetime.strptime(date, "%d%m%Y").date() date = datetime.datetime.strptime(date, "%d%m%Y").date()
self.current_model = self.models.JournalEntry( self.current_model, new = self.models.JournalEntry.get_or_create(
date = date date = date
) )
if not new:
await update.message.reply_text("An entry already exists for this date")
return ConversationHandler.END
except ValueError: except ValueError:
await update.message.reply_text("Please enter the date in the format DDMMYYYY") await update.message.reply_text("Please enter the date in the format DDMMYYYY")
return DATE_ENTRY return DATE_ENTRY
@ -69,8 +84,26 @@ class JournalHandler:
await update.message.reply_text("Please enter the content for the entry") await update.message.reply_text("Please enter the content for the entry")
return CONTENT return CONTENT
async def content_text(self, update, context): async def content_text(self, update, context):
self.current_model.text = update.message.text
self.current_model.author_id = update.message.from_user.id
self.current_model.save()
return ConversationHandler.END
return
async def content_media(self, update, context): async def content_media(self, update, context):
return self.current_model.author_id = update.message.from_user.id
if update.message.photo:
file = await update.message.effective_attachment[-1].get_file()
else:
file = await update.message.effective_attachment.get_file()
file_bytes = await file.download_as_bytearray()
file_path = file.file_path
self.current_model.save_media(file_bytes, file_path)
self.current_model.text = update.message.caption
self.current_model.save()
return ConversationHandler.END

View File

@ -1,5 +1,15 @@
from peewee import * from peewee import *
from pathlib import Path from pathlib import Path
import os
ID_MAPPINGS = {
"Lia": 0,
"Rémy": 364520272,
}
ID_MAPPINGS_REV = dict((v, k) for k, v in ID_MAPPINGS.items())
MEDIA_DIR = Path(os.getenv("MEDIA_DIR"))
MEDIA_DIR.mkdir(parents=True, exist_ok=True)
db = DatabaseProxy() db = DatabaseProxy()
@ -11,25 +21,38 @@ class BaseModel(Model):
# model for a single journal entry # model for a single journal entry
class JournalEntry(BaseModel): class JournalEntry(BaseModel):
# the date of the entry date = DateField(unique=True)
date = DateField() author = TextField(null=True)
# the text of the entry text = TextField(null=True)
text = TextField() media_path = TextField(null=True)
media_path = TextField()
author = TextField()
@property @property
def media(self): def media(self):
return Path(self.media_path).open('rb') return Path(self.media_path).open('rb')
@media.setter def save_media(self, media: bytearray, file_name: str):
def media(self, media): ext = Path(file_name).suffix
self.media_path = Path(media).absolute() file_name = f"{self.date.isoformat()}-media{ext}"
self.media_path = MEDIA_DIR / file_name
self.media_path.write_bytes(media)
self.save() self.save()
@property
def author_id(self):
if self.author is None:
return None
else:
return ID_MAPPINGS[self.author]
@author_id.setter
def author_id(self, author_id):
self.author = ID_MAPPINGS_REV[author_id]
self.save()
def set_db(db_path): def set_db(db_path):
db.initialize(SqliteDatabase(db_path)) db.initialize(SqliteDatabase(db_path))
db.connect() db.connect()
db.create_tables([JournalEntry], safe=True) db.create_tables([JournalEntry], safe=True)

View File

@ -0,0 +1,70 @@
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: journal
name: journal-bot
labels:
app: journal-bot
spec:
# deployment running a single container
selector:
matchLabels:
app: journal-bot
replicas: 1
template:
metadata:
labels:
app: journal-bot
spec:
containers:
- name: journal
image: mollre/journal:arm64
envFrom:
- secretRef:
name: journal-secret-env
env:
- name: MEDIA_DIR
value: /journal/media
volumeMounts:
- name: journal-nfs
mountPath: /journal
volumes:
- name: journal-nfs
persistentVolumeClaim:
claimName: journal-data-nfs
---
apiVersion: v1
kind: PersistentVolume
metadata:
namespace: journal
name: "journal-data-nfs"
labels:
directory: "journal-data"
spec:
storageClassName: fast
capacity:
storage: "100Mi"
accessModes:
- ReadWriteOnce
nfs:
path: /journal-data
server: 10.43.239.43 # assigned to nfs-server service. Won't change as long as service is not redeployed
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
namespace: journal
name: "journal-data-nfs"
spec:
storageClassName: "fast"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "100Mi"
selector:
matchLabels:
directory: "journal-data"
---