initial framework
This commit is contained in:
parent
fbb90357c5
commit
6570de995d
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
Loading…
x
Reference in New Issue
Block a user