From 6548e40f3a3b0a57748247925ecd306d45e59299 Mon Sep 17 00:00:00 2001 From: James Ravenscroft Date: Sun, 6 Nov 2022 18:42:51 +0000 Subject: [PATCH] implemented webhook version of rafael woo --- poetry.lock | 77 +++++++++++++++++++++++++++++++++- pyproject.toml | 2 + src/rafael/__init__.py | 94 +++++++++++++++++++++++++++++++----------- 3 files changed, 149 insertions(+), 24 deletions(-) diff --git a/poetry.lock b/poetry.lock index a7b6ec3..fb12070 100644 --- a/poetry.lock +++ b/poetry.lock @@ -135,6 +135,24 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "fastapi" +version = "0.86.0" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" +starlette = "0.20.4" + +[package.extras] +all = ["email-validator (>=1.1.1,<2.0.0)", "itsdangerous (>=1.1.0,<3.0.0)", "jinja2 (>=2.11.2,<4.0.0)", "orjson (>=3.2.1,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "pyyaml (>=5.3.1,<7.0.0)", "requests (>=2.24.0,<3.0.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)", "uvicorn[standard] (>=0.12.0,<0.19.0)"] +dev = ["autoflake (>=1.4.0,<2.0.0)", "flake8 (>=3.8.3,<6.0.0)", "pre-commit (>=2.17.0,<3.0.0)", "uvicorn[standard] (>=0.12.0,<0.19.0)"] +doc = ["mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.3.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "pyyaml (>=5.3.1,<7.0.0)", "typer[all] (>=0.6.1,<0.7.0)"] +test = ["anyio[trio] (>=3.2.1,<4.0.0)", "black (==22.8.0)", "coverage[toml] (>=6.5.0,<7.0)", "databases[sqlite] (>=0.3.2,<0.7.0)", "email-validator (>=1.1.1,<2.0.0)", "flake8 (>=3.8.3,<6.0.0)", "flask (>=1.1.2,<3.0.0)", "httpx (>=0.23.0,<0.24.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.982)", "orjson (>=3.2.1,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "peewee (>=3.13.3,<4.0.0)", "pytest (>=7.1.3,<8.0.0)", "python-jose[cryptography] (>=3.3.0,<4.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "pyyaml (>=5.3.1,<7.0.0)", "requests (>=2.24.0,<3.0.0)", "sqlalchemy (>=1.3.18,<=1.4.41)", "types-orjson (==3.6.2)", "types-ujson (==5.5.0)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0,<6.0.0)"] + [[package]] name = "feedparser" version = "6.0.10" @@ -260,6 +278,21 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" python-dateutil = ">=2.6,<3.0" pytzdata = ">=2020.1" +[[package]] +name = "pydantic" +version = "1.10.2" +description = "Data validation and settings management using python type hints" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +typing-extensions = ">=4.1.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + [[package]] name = "python-dateutil" version = "2.8.2" @@ -393,6 +426,20 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "starlette" +version = "0.20.4" +description = "The little ASGI library that shines." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +anyio = ">=3.4.0,<5" + +[package.extras] +full = ["itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] + [[package]] name = "todoist-api-python" version = "1.1.1" @@ -413,6 +460,14 @@ category = "main" optional = false python-versions = ">= 3.7" +[[package]] +name = "typing-extensions" +version = "4.4.0" +description = "Backported and Experimental Type Hints for Python 3.7+" +category = "main" +optional = false +python-versions = ">=3.7" + [[package]] name = "tzdata" version = "2022.6" @@ -450,6 +505,21 @@ brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "uvicorn" +version = "0.19.0" +description = "The lightning-fast ASGI server." +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.0)"] + [[package]] name = "werkzeug" version = "2.2.2" @@ -467,7 +537,7 @@ watchdog = ["watchdog"] [metadata] lock-version = "1.1" python-versions = "^3.10" -content-hash = "7c348ae2ed45898d84277a10297e0f4f32dca3454ab60e4910fb4c7c15d7e937" +content-hash = "e116dc0f5326e914bdc2ad6d3dc483552ab7e51d0116a13de3f19fac9825767c" [metadata.files] anyio = [] @@ -486,6 +556,7 @@ charset-normalizer = [] click = [] colorama = [] dokuwiki = [] +fastapi = [] feedparser = [] flask = [] h11 = [] @@ -540,6 +611,7 @@ markupsafe = [ {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, ] pendulum = [] +pydantic = [] python-dateutil = [] python-dotenv = [ {file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"}, @@ -561,15 +633,18 @@ six = [ ] sniffio = [] soupsieve = [] +starlette = [] todoist-api-python = [ {file = "todoist_api_python-1.1.1-py3-none-any.whl", hash = "sha256:17e70ecf77ae879248f61bc8b8ce9fa2765a57901b78a75d92349143e614f3b5"}, {file = "todoist_api_python-1.1.1.tar.gz", hash = "sha256:5080f1b21b17378454ae0b8ceb8c647803fba023526176c8a9bb784508fb8508"}, ] tornado = [] +typing-extensions = [] tzdata = [] tzlocal = [ {file = "tzlocal-4.2-py3-none-any.whl", hash = "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745"}, {file = "tzlocal-4.2.tar.gz", hash = "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"}, ] urllib3 = [] +uvicorn = [] werkzeug = [] diff --git a/pyproject.toml b/pyproject.toml index 8aa974a..a60525e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,8 @@ python-dotenv = "^0.20.0" bs4 = "^0.0.1" feedparser = "^6.0.10" pendulum = "^2.1.2" +fastapi = "^0.86.0" +uvicorn = "^0.19.0" [tool.poetry.dev-dependencies] diff --git a/src/rafael/__init__.py b/src/rafael/__init__.py index 6835433..c502a6d 100644 --- a/src/rafael/__init__.py +++ b/src/rafael/__init__.py @@ -3,20 +3,21 @@ import dotenv import os import io import tempfile +import pydantic from datetime import datetime -from flask import Flask - +from fastapi import FastAPI, Depends, Request from telegram import Update, PhotoSize, File, BotCommand from telegram.ext import Updater, MessageHandler, CommandHandler, CallbackContext, Application - -app = Flask("rafael") +#app = Flask("rafael") RAFAEL_UA = "RAFAEL/0.1" +app = FastAPI() + from rafael.bookmarks import RafaelBookmarkPlugin from rafael.journal import JournalPlugin @@ -49,9 +50,17 @@ def handle(update: Update, context: CallbackContext): class RafaelBot: - def __init__(self): + # def __init__(self): - self.application = Application.builder().token(os.getenv("TELEGRAM_API_KEY")).build() + + + #self.updater.dispatcher.add_handler(CommandHandler("journal", handle)) + #self.updater.dispatcher.add_handler(MessageHandler(Filters.attachment, handle)) + + + async def configure_webhook(self): + + self.application = Application.builder().token(os.getenv("TELEGRAM_API_KEY")).updater(None).build() bh = RafaelBookmarkPlugin() @@ -59,35 +68,74 @@ class RafaelBot: jp = JournalPlugin() jp.register(self.application) - - #self.updater.dispatcher.add_handler(CommandHandler("journal", handle)) - #self.updater.dispatcher.add_handler(MessageHandler(Filters.attachment, handle)) - - + print("Configure webhook:", await self.application.bot.set_webhook(os.getenv("RAFAEL_WEBHOOK_EXTERNAL_URL"))) + print("Init bot", await self.application.initialize()) + print("Start bot", await self.application.start()) + + async def stop(self): + return await self.application.stop() def run(self): - self.application.run_polling() + #self.application.run_polling() + self.application.run_webhook(port=os.getenv("RAFAEL_WEBHOOK_PORT"), url_path="/webhook", webhook_url=os.getenv("RAFAEL_WEBHOOK_EXTERNAL_URL")) + +bot = RafaelBot() + + +def rafael_bot(): + return bot + + + +# @app.route("/", methods=['GET']) +# def index(): +# return "hello" + +class FastapiUpdate(pydantic.BaseModel): + + class Config: + orm_mode = True + + update_id: int + message: object -@app.route("/", methods=['GET']) -def index(): - return "hello" +@app.post('/webhook') +async def webhook(request: Request, bot: RafaelBot = Depends(dependency=rafael_bot) ): -def main(): + body = await request.json() + + print(body) + + await bot.application.update_queue.put(Update.de_json(body, bot.application.bot)) + +@app.on_event("startup") +async def startup(): dotenv.load_dotenv() - print("run bot") - bot = RafaelBot() + print(bot) + await bot.configure_webhook() + + + +@app.on_event("shutdown") +async def shutdown(): + await bot.stop() + + +# def main(): - bot.run() - print("bot run") +# dotenv.load_dotenv() + +# print("run bot") +# bot = RafaelBot() +# bot.configure_webhook() +# #bot.run() +# print("bot run") - # app.run() - - if __name__ == "__main__": main() \ No newline at end of file