readme and docker-compose

This commit is contained in:
bvn13 2024-06-06 00:08:10 +03:00
parent 4d85b32efd
commit 34f375989c
4 changed files with 144 additions and 2 deletions

View File

@ -0,0 +1,13 @@
FROM python:3.10
RUN apt-get install libpq-dev -y
ADD requirements.txt requirements.txt
RUN pip install -r requirements.txt
ADD src /app
WORKDIR /app
ENTRYPOINT [ "gunicorn", "--chdir=/app/src", "--bond=127.0.0.1:8080", "main:app" ]

View File

@ -0,0 +1,45 @@
# JeDoIst клиент
## Что это?
- это клиент для телеграм-бота [JeDoIst](https://t.me/jedoist)
## Зачем вам это?
- [JeDoIst](https://t.me/jedoist) - это автоматизатор входящей очереди задач
Не так давно я прочитал книгу Максима Дорофеева "[Джедайские техники](https://t.me/bvn13_blog/108)", данный проект основан на идеях, описанных в данной книге.
## Какие идеи?
- каждый человек работает с задачами
- чтобы быть успешным, нужно **правильно** работать со своими задачами
- очередь входящий задач должна быть одна: должно быть одно место, куда складываются все входящие задачи
- **работа** заключается в постоянной проработке и декомпозиции этой очереди по правилам, описанным в книге, по принципу "для того, чтобы обезьянке стало проще выполнять"
### Улучшения
- часто идеи приходят в совершенно неподходящий для записывания "от руки" время
- хочется иметь инструмент, который послужит входящей очередью, в которую можно буквально **надиктовать** задачу
- но очередь задач должна быть одна, поэтому...
- голосовые записи должны быть расшифрованы и сложены в единую очередь
## Поэтому
- [JeDoIst](https://t.me/jedoist) является этой входящей очередью, в которую можно "надиктовать" свою идею или задачу
- он бережно расшифрует голосовое сообщение и передаст его в callback-е на любой удаленный сервер
- с одним ограничением: протокол диктует [JeDoIst](https://t.me/jedoist), и должна быть авторизация
### И поэтому...
- этот репозиторий предназначен для быстрого развертывания веб-сервера, в который будут отправляться ваши задачи
## Но!
- Вопрос: но где же опубликовать этот веб-сервер?
- Ответ: на любом VPS
- Вопрос: как сохраняются задачи?
- Ответ: в одном файле в формате Markdown
- Вопрос: файл на сервере, я работаю на ноутбуке - где логика?
- Ответ: есть Synkthing, который позволит синхронизировать файл с задачми на сервере и на ноутбуке. И на смартфоне.

View File

@ -0,0 +1,19 @@
version: '3.3'
networks:
jedoist:
external: true
services:
bot:
# build: ./
image: localhost:5001/jedoist-client:${APP_VERSION}
environment:
- TODO_PATH=/mnt/todo
- TODO_FILE=${TODO_FILE}
volumes:
- ${TODO_PATH}:/mnt/todo
restart: on-failure
networks:
- jedoist

View File

@ -1,5 +1,41 @@
import falcon import falcon
import json import json
import os
# https://falcon.readthedocs.io/en/stable/user/quickstart.html#learning-by-example
class AuthMiddleware:
def process_request(self, req, resp):
token = req.get_header('Authorization')
account_id = req.get_header('Account-ID')
challenges = ['Token type="Fernet"']
if token is None:
description = 'Please provide an auth token as part of the request.'
raise falcon.HTTPUnauthorized(
title='Auth token required',
description=description,
challenges=challenges,
href='http://docs.example.com/auth',
)
if not self._token_is_valid(token, account_id):
description = (
'The provided auth token is not valid. '
'Please request a new token and try again.'
)
raise falcon.HTTPUnauthorized(
title='Authentication required',
description=description,
challenges=challenges,
href='http://docs.example.com/auth',
)
def _token_is_valid(self, token, account_id):
return os.environ["TOKEN"] # Suuuuuure it's valid...
class RequireJSON: class RequireJSON:
@ -17,6 +53,7 @@ class RequireJSON:
href='http://docs.examples.com/api/json', href='http://docs.examples.com/api/json',
) )
class JSONTranslator: class JSONTranslator:
# NOTE: Normally you would simply use req.media and resp.media for # NOTE: Normally you would simply use req.media and resp.media for
# this particular use case; this example serves only to illustrate # this particular use case; this example serves only to illustrate
@ -72,18 +109,46 @@ def max_body(limit):
return hook return hook
########################################################################################################
class CreateTaskResource: class CreateTaskResource:
TODO_HEADER = '# ToDo'
def __init__(self) -> None:
self.__todo_path = "{0}/{1}".format(os.environ['TODO_PATH'], os.environ['TODO_FILE'])
def on_post(self, req, resp): def on_post(self, req, resp):
task = req.context.doc['task']
self.__create_task(task)
quote = { quote = {
'title': 'Получена задача', 'title': 'Получена задача',
'description': req.context.doc['task'] 'description': task
} }
resp.media = quote resp.media = quote
def __create_task(self, text: str) -> None:
content = []
section_found = False
is_waiting_empty_line = False
with open(self.__todo_path, 'r', encoding='UTF-8') as file:
while line := file.readline():
if section_found == False:
if line.strip() == CreateTaskResource.TODO_HEADER:
section_found = True
is_waiting_empty_line = True
content.append(line)
if section_found and is_waiting_empty_line == True and line.strip() == '':
content.append("- [ ] {0}\n".format(text))
is_waiting_empty_line = False
with open(self.__todo_path, 'w', encoding='utf-8') as file:
file.writelines(content)
########################################################################################################
app = falcon.App( app = falcon.App(
middleware=[ middleware=[
AuthMiddleware(),
RequireJSON(), RequireJSON(),
JSONTranslator() JSONTranslator()
] ]