فهرست منبع

🐛 fix(dialog): fix the behavior when in groups only one user can press the buttons

it was done by hacking aiogram middleware globaly
metya 2 سال پیش
والد
کامیت
24525a5945
5فایلهای تغییر یافته به همراه132 افزوده شده و 33 حذف شده
  1. 35 0
      conda/develop.yaml
  2. 2 2
      db/papers.db
  3. 20 4
      src/dialog.py
  4. 58 10
      src/progress.py
  5. 17 17
      vanitybot.py

+ 35 - 0
conda/develop.yaml

@@ -12,6 +12,7 @@ dependencies:
   - asttokens=2.2.1=pyhd8ed1ab_0
   - async-timeout=4.0.2=pyhd8ed1ab_0
   - async_generator=1.10=py_0
+  - atk-1.0=2.38.0=hcb7b3dd_1
   - attrs=22.2.0=pyh71513ae_0
   - backcall=0.2.0=pyh9f0ad1d_0
   - backports=1.0=pyhd8ed1ab_3
@@ -20,6 +21,7 @@ dependencies:
   - brotlipy=0.7.0=py311he2be06e_1005
   - bzip2=1.0.8=h3422bc3_4
   - ca-certificates=2022.12.7=h4653dfc_0
+  - cairo=1.16.0=h73a0509_1014
   - cchardet=2.1.7=py311ha397e9f_4
   - certifi=2022.12.7=pyhd8ed1ab_0
   - cffi=1.15.1=py311hae827db_3
@@ -34,15 +36,34 @@ dependencies:
   - debugpy=1.6.6=py311ha397e9f_0
   - decli=0.5.2=pyhd8ed1ab_0
   - decorator=5.1.1=pyhd8ed1ab_0
+  - deprecated=1.2.13=pyh6c4a22f_0
+  - diagrams=0.21.0=pyhd8ed1ab_0
   - distlib=0.3.6=pyhd8ed1ab_0
   - docopt=0.6.2=py_1
   - executing=1.2.0=pyhd8ed1ab_0
+  - expat=2.5.0=hb7217d7_0
   - fake-useragent=1.1.1=pyhd8ed1ab_0
   - filelock=3.9.0=pyhd8ed1ab_0
+  - font-ttf-dejavu-sans-mono=2.37=hab24e00_0
+  - font-ttf-inconsolata=3.000=h77eed37_0
+  - font-ttf-source-code-pro=2.038=h77eed37_0
+  - font-ttf-ubuntu=0.83=hab24e00_0
+  - fontconfig=2.14.2=h82840c6_0
+  - fonts-conda-ecosystem=1=0
+  - fonts-conda-forge=1=0
   - freetype=2.12.1=hd633e50_1
+  - fribidi=1.0.10=h27ca646_0
   - frozenlist=1.3.3=py311he2be06e_0
+  - gdk-pixbuf=2.42.10=h9bcf4fe_0
+  - gettext=0.21.1=h0186832_0
+  - giflib=5.2.1=h27ca646_2
+  - graphite2=1.3.13=h9f76cd9_1001
+  - graphviz=7.1.0=h4f8fbd6_0
   - greenlet=2.0.2=py311ha397e9f_0
+  - gtk2=2.24.33=h57013de_2
+  - gts=0.7.6=h4b6d4d6_2
   - h11=0.14.0=pyhd8ed1ab_0
+  - harfbuzz=6.0.0=hddbc195_0
   - icu=70.1=h6b3803e_0
   - identify=2.5.17=pyhd8ed1ab_0
   - idna=3.4=pyhd8ed1ab_0
@@ -60,12 +81,17 @@ dependencies:
   - libcxx=14.0.6=h2692d47_0
   - libdeflate=1.17=h1a8c8d9_0
   - libffi=3.4.2=h3422bc3_5
+  - libgd=2.3.3=h90fb8ed_4
+  - libglib=2.74.1=h4646484_1
   - libiconv=1.17=he4db4b2_0
   - libpng=1.6.39=h76d750c_0
+  - librsvg=2.54.4=ha2634a2_0
   - libsodium=1.0.18=h27ca646_1
   - libsqlite=3.40.0=h76d750c_0
   - libtiff=4.5.0=h5dffbdd_2
+  - libtool=2.4.7=hb7217d7_0
   - libuv=1.44.2=he4db4b2_0
+  - libwebp=1.2.4=h999c80f_1
   - libwebp-base=1.2.4=h57fd34a_0
   - libxcb=1.13=h9b22ae9_1004
   - libxml2=2.10.3=h87b0503_0
@@ -84,13 +110,16 @@ dependencies:
   - openssl=3.0.8=h03a7124_0
   - outcome=1.2.0=pyhd8ed1ab_0
   - packaging=21.3=pyhd8ed1ab_0
+  - pango=1.50.13=h6c112b8_0
   - parse=1.19.0=pyh44b312d_0
   - parso=0.8.3=pyhd8ed1ab_0
+  - pcre2=10.40=hb34f9b4_0
   - pexpect=4.8.0=pyh1a96a4e_2
   - pickleshare=0.7.5=py_1003
   - pillow=9.4.0=py311h627eb56_1
   - pip=23.0=pyhd8ed1ab_0
   - pipreqs=0.4.11=pyhd8ed1ab_0
+  - pixman=0.40.0=h27ca646_0
   - platformdirs=2.6.2=pyhd8ed1ab_0
   - pre-commit=3.0.4=py311h267d04e_0
   - prompt-toolkit=3.0.36=pyha770c72_0
@@ -103,7 +132,10 @@ dependencies:
   - pycparser=2.21=pyhd8ed1ab_0
   - pydantic=1.10.4=py311he2be06e_1
   - pyee=8.1.0=pyhd8ed1ab_0
+  - pygithub=1.58.0=pyh1a96a4e_0
   - pygments=2.14.0=pyhd8ed1ab_0
+  - pyjwt=2.6.0=pyhd8ed1ab_0
+  - pynacl=1.5.0=py311he2be06e_2
   - pyopenssl=23.0.0=pyhd8ed1ab_0
   - pyparsing=3.0.9=pyhd8ed1ab_0
   - pyppeteer=1.0.2=pyhd8ed1ab_0
@@ -112,6 +144,7 @@ dependencies:
   - python=3.11.0=h3ba56d0_1_cpython
   - python-dateutil=2.8.2=pyhd8ed1ab_0
   - python-dotenv=0.21.1=pyhd8ed1ab_0
+  - python-graphviz=0.19.2=pyhaef67bd_0
   - python_abi=3.11=3_cp311
   - pyyaml=6.0=py311he2be06e_5
   - pyzmq=25.0.0=py311h0f351f6_0
@@ -151,6 +184,7 @@ dependencies:
   - webdriver-manager=3.8.5=pyhd8ed1ab_0
   - websockets=10.4=py311he2be06e_1
   - wheel=0.38.4=pyhd8ed1ab_0
+  - wrapt=1.15.0=py311he2be06e_0
   - wsproto=1.2.0=pyhd8ed1ab_0
   - xorg-libxau=1.0.9=h27ca646_0
   - xorg-libxdmcp=1.1.3=h27ca646_0
@@ -160,6 +194,7 @@ dependencies:
   - yarl=1.8.2=py311he2be06e_0
   - zeromq=4.3.4=hbdafb3b_1
   - zipp=3.12.1=pyhd8ed1ab_0
+  - zlib=1.2.13=h03a7124_4
   - zstd=1.5.2=hf913c23_6
   - pip:
       - aiogram==2.25.1

+ 2 - 2
db/papers.db

@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:ed42d25abd51465439938b7a8997049d1c68b8ded5997b45624a6bec2d2e20e6
-size 110592
+oid sha256:1d012733f595fa372b051e4040b3f73a62ef1065839665fefa3d5441059563ee
+size 188416

+ 20 - 4
src/dialog.py

@@ -4,7 +4,7 @@ from asyncio import sleep, create_task, gather, get_event_loop, Queue, current_t
 from typing import Any, List
 from aiogram.dispatcher.filters.state import StatesGroup, State
 from aiogram.types import Message, CallbackQuery
-from aiogram_dialog import Window, Dialog, DialogManager, StartMode, Data
+from aiogram_dialog import Window, Dialog, DialogManager, StartMode, Data, BaseDialogManager
 from aiogram_dialog.widgets.kbd import Radio
 from aiogram_dialog.widgets.text import Format
 from aiogram.types import ParseMode
@@ -33,6 +33,14 @@ buttons = [
     ]
 
 
+async def time_out_dialog(manager: BaseDialogManager, widget: Any, time_out: int = 1200):
+    for _ in range(time_out):
+        await sleep(1)
+    await manager.update({"final_state": "1"})
+    await sleep(1)
+    await manager.done()
+
+
 async def get_data(dialog_manager: DialogManager, **kwargs):
     text_message = {"text": "OOOPS!"}
     if data := dialog_manager.current_context():
@@ -44,6 +52,8 @@ async def get_data(dialog_manager: DialogManager, **kwargs):
         item_id = data.widget_data.get('radio_buttons') #type: ignore
         title = data.start_data["title"] #type: ignore
         url = data.start_data["url"] #type: ignore
+        if ft:=data.dialog_data.get("final_state"):
+            item_id = ft
         if data.dialog_data.get('abs'): #type: ignore
             abstract = data.dialog_data.get('abs') #type: ignore
         else:
@@ -117,6 +127,12 @@ async def on_button_selected(c: CallbackQuery, widget: Any, manager: DialogManag
     return {"text": item_id}
 
 
+async def default_button(c: CallbackQuery, dialog_manager: DialogManager, **kwargs):
+    if widget:=dialog_manager.dialog().find("radio_buttons"):
+        await widget.set_checked(c, "1", dialog_manager)
+    create_task(time_out_dialog(manager=dialog_manager.bg(), widget=widget))
+
+
 buttons_kbd = Radio(
     Format("✓ {item[0]}"),
     Format("{item[0]}"),
@@ -135,6 +151,6 @@ dialog = Dialog(
         getter=get_data,
         parse_mode=ParseMode.MARKDOWN, # type: ignore
         # preview_data={"button": "1"}
-    )
-)
-
+    ),
+    on_start=default_button,
+)

+ 58 - 10
src/progress.py

@@ -4,16 +4,35 @@ import logging
 from aiogram import Bot, Dispatcher
 from aiogram.contrib.fsm_storage.memory import MemoryStorage
 from aiogram.dispatcher.filters.state import StatesGroup, State
-from aiogram.types import Message, CallbackQuery
+from aiogram.dispatcher.middlewares import BaseMiddleware
+from aiogram.types import Message, CallbackQuery, User
+from aiogram.utils.exceptions import Throttled
+from aiogram.dispatcher import DEFAULT_RATE_LIMIT
+from aiogram.dispatcher.handler import CancelHandler, current_handler
 
 from aiogram_dialog import Dialog, DialogManager, Window, DialogRegistry, BaseDialogManager, \
     StartMode
 from aiogram_dialog.widgets.kbd import Button
-from aiogram_dialog.widgets.text import Const, Multi, Text
+from aiogram_dialog.widgets.text import Const, Multi, Text, Format
 
-from typing import Any
+from typing import Any, Callable, Dict, Awaitable, Union
 
-from src.config import API_TOKEN
+try: 
+    from src.config import API_TOKEN
+except:
+    from config import API_TOKEN
+
+class TrickyUser(BaseMiddleware):
+    def __init__(self, user_id: int,):
+        super().__init__()
+        self.default_user = user_id
+
+    async def on_process_update(self, update, data):
+        if message:=update.message:
+            message.from_user.id = self.default_user
+        if callback:=update.callback_query:
+            callback.from_user.id = self.default_user
+        # print(update)
 
 
 class Processing(Text):
@@ -60,12 +79,29 @@ bg_dialog = Dialog(
 # main dialog
 class MainSG(StatesGroup):
     main = State()
+    background = State()
+
+
+async def start_bg(c: CallbackQuery, button: Button, dialog_manager: DialogManager, **kwargs):
+    # await manager.start(Bg.progress)
+    # asyncio.create_task(background(c, manager.bg()))
+    await dialog_manager.dialog().switch_to(MainSG.background)
+    await task_background(dialog_manager)
 
 
-async def start_bg(c: CallbackQuery, button: Button, manager: DialogManager):
-    await manager.start(Bg.progress)
-    asyncio.create_task(background(c, manager.bg()))
+async def get_task_bg_data(dialog_manager: DialogManager, **kwargs):
+    for key, val in kwargs.items():
+        print(key, val)
+    kwargs['aiogd_storage_proxy'].user_id = 1
+    print(dialog_manager)
+    return {"text": dialog_manager.current_context().dialog_data.get("text", "gay")} # type: ignore
 
+async def task_background(manager: DialogManager):
+    print(manager.current_context())
+    for i in range(5):
+        print(i)
+        await manager.update({"text": f"pidor{i}"})
+        await asyncio.sleep(1)
 
 async def background(c: CallbackQuery,
                      manager: DialogManager | BaseDialogManager,
@@ -92,17 +128,28 @@ async def background(c: CallbackQuery,
     await manager.done()
 
 
+async def back(c, button, dialog_manager):
+    await dialog_manager.dialog().back()
+
 main_menu = Dialog(
     Window(
         Const("Press button to start processing"),
         Button(Const("Start 👀"), id="start", on_click=start_bg),
         state=MainSG.main,
-        getter=get_bg_data
+        getter=get_task_bg_data
     ),
+    Window(
+        Const("THIS IS BACKGROUND"),
+        Format("{text}"),
+        Button(Const("Back"), id='back', on_click=back),
+        state=MainSG.background,
+        getter=get_task_bg_data
+    )
 )
 
 
-async def start(m: Message, dialog_manager: DialogManager):
+async def start(m: Message, dialog_manager: DialogManager, **kwargs):
+    # print(kwargs)
     await dialog_manager.start(MainSG.main, mode=StartMode.RESET_STACK)
 
 
@@ -116,8 +163,9 @@ async def main():
     registry = DialogRegistry(dp)
     registry.register(bg_dialog)
     registry.register(main_menu)
+    dp.middleware.setup(TrickyUser(1))
     dp.register_message_handler(start, text="/start", state="*")
-
+    await dp.skip_updates()
     await dp.start_polling()
 
 

+ 17 - 17
vanitybot.py

@@ -3,42 +3,36 @@ import logging
 import asyncio
 from aiogram.contrib.fsm_storage.memory import MemoryStorage
 from aiogram import Bot, Dispatcher, executor, types
-from aiogram_dialog import DialogManager, DialogRegistry, StartMode
+from aiogram_dialog import DialogManager, DialogRegistry, StartMode, BaseDialogManager
 from src.config import API_TOKEN
 from src.dialog import dialog, MySG
-from src.progress import bg_dialog
+from src.progress import bg_dialog, TrickyUser
 from src.summarize import get_paper_desc
 
 # Initialize bot and dispatcher
 bot = Bot(token=API_TOKEN) # type: ignore
 dp = Dispatcher(bot, storage=MemoryStorage())
 registry = DialogRegistry(dp)
+dp.middleware.setup(TrickyUser(1))
 registry.register(dialog)
 registry.register(bg_dialog)
 
+
 help_message = "Hello!\n\n\
 Send me a link paper from arxiv.org and \
 I'll send you back snippet of paper and arxiv-vanity.com mobile friendly link!\n\
 Or add me to chat and I'll be watching the arxiv link and \
-reply to them with fancy arxiv-vanity links."
+reply to them with fancy arxiv-vanity links.\n\
+Also, I can get summary and highlight of a paper for you."
+
 
 async def deploy_message():
     await bot.send_message(chat_id=1147194, text='The deployment has been performed')
 
-@dp.message_handler(commands=['start'])
-async def process_start_command(message: types.Message):
-    await message.reply(help_message)
-
 
-@dp.message_handler(commands=['help'])
-async def process_help_command(message: types.Message):
+@dp.message_handler(commands=['start', 'help'])
+async def process_start_command(message: types.Message):
     await message.reply(help_message)
-    
-@dp.message_handler(commands=['long'])
-async def long(message: types.Message):
-    import random
-    long = "".join(str(random.randint(1,10)) for _ in range(3700))
-    await message.reply(long)
 
 
 @dp.message_handler(regexp=r'arxiv.org\/(?:abs|pdf)\/\d{4}\.\d{5}')
@@ -77,10 +71,16 @@ async def vanitify(message: types.Message, dialog_manager: DialogManager):
     asyncio.gather(*[start_dialog(data=data) for data in list_data])
 
 
+async def main():
+    await deploy_message()
+    await dp.skip_updates()
+    await dp.start_polling()
+
 if __name__ == "__main__":
     logging.basicConfig(level=logging.INFO)
     # logging.getLogger("asyncio").setLevel(logging.DEBUG)
     # logging.getLogger("aiogram_dialog").setLevel(logging.DEBUG)
 
-    asyncio.get_event_loop().run_until_complete(deploy_message())
-    executor.start_polling(dp, skip_updates=True)
+    # asyncio.get_event_loop().run_until_complete(deploy_message())
+    # executor.start_polling(dp, skip_updates=True)
+    asyncio.run(main())