arpakitlib 1.8.4__py3-none-any.whl → 1.8.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. arpakitlib/_arpakit_project_template_v_1/alembic/env.py +1 -1
  2. arpakitlib/_arpakit_project_template_v_1/api/auth.py +31 -2
  3. arpakitlib/_arpakit_project_template_v_1/api/event.py +1 -1
  4. arpakitlib/_arpakit_project_template_v_1/api/exception_handler.py +2 -2
  5. arpakitlib/_arpakit_project_template_v_1/api/router/main_router.py +0 -3
  6. arpakitlib/_arpakit_project_template_v_1/api/router/v1/clear_log_file.py +4 -5
  7. arpakitlib/_arpakit_project_template_v_1/api/router/v1/get_errors_info.py +10 -1
  8. arpakitlib/_arpakit_project_template_v_1/api/router/v1/get_log_file.py +4 -5
  9. arpakitlib/_arpakit_project_template_v_1/api/router/v1/main_router.py +12 -20
  10. arpakitlib/_arpakit_project_template_v_1/api/router/v1/raise_fake_error.py +4 -5
  11. arpakitlib/_arpakit_project_template_v_1/api/router/v1/reinit_sqlalchemy_db.py +33 -0
  12. arpakitlib/_arpakit_project_template_v_1/api/schema/v1/out.py +1 -1
  13. arpakitlib/_arpakit_project_template_v_1/business_service/remove_operations.py +2 -2
  14. arpakitlib/_arpakit_project_template_v_1/command/check_sqlalchemy_db.py +1 -1
  15. arpakitlib/_arpakit_project_template_v_1/command/drop_sqlalchemy_db.py +2 -1
  16. arpakitlib/_arpakit_project_template_v_1/command/init_sqlalchemy_db.py +1 -1
  17. arpakitlib/_arpakit_project_template_v_1/command/reinit_sqlalchemy_db.py +1 -1
  18. arpakitlib/_arpakit_project_template_v_1/command/remove_story_logs.py +2 -2
  19. arpakitlib/_arpakit_project_template_v_1/command/start_api_for_prod.py +19 -0
  20. arpakitlib/_arpakit_project_template_v_1/command/{start_sync_operation_executor_worker.py → start_operation_executor_worker_for_not_prod.py} +1 -1
  21. arpakitlib/_arpakit_project_template_v_1/command/{start_sync_operation_executor_workers.py → start_operation_executor_workers_for_not_prod.py} +1 -1
  22. arpakitlib/_arpakit_project_template_v_1/command/start_tg_bot_for_prod.py +11 -0
  23. arpakitlib/_arpakit_project_template_v_1/core/const.py +3 -1
  24. arpakitlib/_arpakit_project_template_v_1/core/settings.py +2 -2
  25. arpakitlib/_arpakit_project_template_v_1/more/helloworld +1 -0
  26. arpakitlib/_arpakit_project_template_v_1/operation_execution/operation_executor_worker.py +2 -2
  27. arpakitlib/_arpakit_project_template_v_1/operation_execution/scheduled_operation_creator_worker.py +2 -2
  28. arpakitlib/_arpakit_project_template_v_1/operation_execution/scheduled_operations.py +1 -1
  29. arpakitlib/_arpakit_project_template_v_1/sqladmin_/add_admin_in_app.py +1 -1
  30. arpakitlib/_arpakit_project_template_v_1/sqladmin_/model_view.py +1 -1
  31. arpakitlib/_arpakit_project_template_v_1/{sqlalchemy_db → sqlalchemy_db_}/sqlalchemy_db.py +1 -1
  32. arpakitlib/_arpakit_project_template_v_1/{sqlalchemy_db → sqlalchemy_db_}/sqlalchemy_model.py +1 -1
  33. arpakitlib/_arpakit_project_template_v_1/tg_bot/blank/blank.py +20 -1
  34. arpakitlib/_arpakit_project_template_v_1/tg_bot/const.py +1 -1
  35. arpakitlib/_arpakit_project_template_v_1/tg_bot/event.py +41 -15
  36. arpakitlib/_arpakit_project_template_v_1/tg_bot/filter_.py +69 -0
  37. arpakitlib/_arpakit_project_template_v_1/tg_bot/kb/inline_/callback.py +37 -0
  38. arpakitlib/_arpakit_project_template_v_1/tg_bot/kb/inline_/common.py +15 -0
  39. arpakitlib/_arpakit_project_template_v_1/tg_bot/kb/static_/common.py +14 -0
  40. arpakitlib/_arpakit_project_template_v_1/tg_bot/middleware/init_user.py +0 -3
  41. arpakitlib/_arpakit_project_template_v_1/tg_bot/middleware/middleware.py +4 -4
  42. arpakitlib/_arpakit_project_template_v_1/tg_bot/router/arpakitlib_project_template_info.py +14 -0
  43. arpakitlib/_arpakit_project_template_v_1/tg_bot/router/error.py +0 -3
  44. arpakitlib/_arpakit_project_template_v_1/tg_bot/router/healthcheck.py +2 -1
  45. arpakitlib/_arpakit_project_template_v_1/tg_bot/router/main_router.py +7 -3
  46. arpakitlib/_arpakit_project_template_v_1/tg_bot/start_tg_bot.py +19 -14
  47. arpakitlib/_arpakit_project_template_v_1/tg_bot/tg_bot_dispatcher.py +3 -2
  48. arpakitlib/_arpakit_project_template_v_1/util/read_arpakitlib_project_template_file.py +1 -1
  49. arpakitlib/ar_aiogram_util.py +3 -123
  50. {arpakitlib-1.8.4.dist-info → arpakitlib-1.8.5.dist-info}/METADATA +1 -1
  51. {arpakitlib-1.8.4.dist-info → arpakitlib-1.8.5.dist-info}/RECORD +63 -65
  52. arpakitlib/_arpakit_project_template_v_1/command/start_async_operation_executor_worker.py +0 -14
  53. arpakitlib/_arpakit_project_template_v_1/command/start_async_scheduled_operation_creator_worker.py +0 -14
  54. arpakitlib/_arpakit_project_template_v_1/tg_bot/blank/util.py +0 -12
  55. arpakitlib/_arpakit_project_template_v_1/tg_bot/filter/__init__.py +0 -0
  56. arpakitlib/_arpakit_project_template_v_1/tg_bot/filter/not_prod_mode.py +0 -8
  57. arpakitlib/_arpakit_project_template_v_1/tg_bot/filter/prod_mode.py +0 -8
  58. arpakitlib/_arpakit_project_template_v_1/tg_bot/router/arpakitlib_.py +0 -10
  59. arpakitlib/_arpakit_project_template_v_1/tg_bot/transmitted_tg_data.py +0 -58
  60. /arpakitlib/_arpakit_project_template_v_1/api/router/v1/{arpakitlib_project_template.py → arpakitlib_project_template_info.py} +0 -0
  61. /arpakitlib/_arpakit_project_template_v_1/{arpakitlib_project_template.json → arpakitlib_project_template_info.json} +0 -0
  62. /arpakitlib/_arpakit_project_template_v_1/command/{alembic_upgrade_head .sh → alembic_upgrade_head.sh} +0 -0
  63. /arpakitlib/_arpakit_project_template_v_1/command/{start_api_with_reload.py → start_api_with_reload_for_not_prod.py} +0 -0
  64. /arpakitlib/_arpakit_project_template_v_1/command/{start_api_without_reload.py → start_api_without_reload_for_not_prod.py} +0 -0
  65. /arpakitlib/_arpakit_project_template_v_1/command/{start_sync_scheduled_operation_creator_worker.py → start_scheduled_operation_creator_worker_for_not_prod.py} +0 -0
  66. /arpakitlib/_arpakit_project_template_v_1/{sqlalchemy_db → sqlalchemy_db_}/__init__.py +0 -0
  67. /arpakitlib/_arpakit_project_template_v_1/{sqlalchemy_db → sqlalchemy_db_}/const.py +0 -0
  68. /arpakitlib/_arpakit_project_template_v_1/{sqlalchemy_db → sqlalchemy_db_}/util.py +0 -0
  69. {arpakitlib-1.8.4.dist-info → arpakitlib-1.8.5.dist-info}/LICENSE +0 -0
  70. {arpakitlib-1.8.4.dist-info → arpakitlib-1.8.5.dist-info}/WHEEL +0 -0
  71. {arpakitlib-1.8.4.dist-info → arpakitlib-1.8.5.dist-info}/entry_points.txt +0 -0
@@ -3,7 +3,15 @@ from typing import Callable
3
3
 
4
4
  from aiogram import Dispatcher
5
5
 
6
- from tg_bot.transmitted_tg_data import get_cached_transmitted_tg_bot_data
6
+ from arpakitlib.ar_base_worker_util import safe_run_worker_in_background, SafeRunInBackgroundModes
7
+ from core.cache_file_storage_in_dir import get_cached_cache_file_storage_in_dir
8
+ from core.dump_file_storage_in_dir import get_cached_dump_file_storage_in_dir
9
+ from core.media_file_storage_in_dir import get_cached_media_file_storage_in_dir
10
+ from core.settings import get_cached_settings
11
+ from json_db.json_db import get_cached_json_db
12
+ from operation_execution.operation_executor_worker import create_operation_executor_worker
13
+ from operation_execution.scheduled_operation_creator_worker import create_scheduled_operation_creator_worker
14
+ from sqlalchemy_db_.sqlalchemy_db import get_cached_sqlalchemy_db
7
15
 
8
16
  _logger = logging.getLogger(__name__)
9
17
 
@@ -11,20 +19,38 @@ _logger = logging.getLogger(__name__)
11
19
  async def on_startup():
12
20
  _logger.info("start")
13
21
 
14
- if get_cached_transmitted_tg_bot_data().media_file_storage_in_dir is not None:
15
- get_cached_transmitted_tg_bot_data().media_file_storage_in_dir.init()
16
-
17
- if get_cached_transmitted_tg_bot_data().cache_file_storage_in_dir is not None:
18
- get_cached_transmitted_tg_bot_data().cache_file_storage_in_dir.init()
19
-
20
- if get_cached_transmitted_tg_bot_data().dump_file_storage_in_dir is not None:
21
- get_cached_transmitted_tg_bot_data().dump_file_storage_in_dir.init()
22
-
23
- if get_cached_transmitted_tg_bot_data().settings.api_init_sqlalchemy_db:
24
- get_cached_transmitted_tg_bot_data().sqlalchemy_db.init()
25
-
26
- if get_cached_transmitted_tg_bot_data().settings.api_init_json_db:
27
- get_cached_transmitted_tg_bot_data().json_db.init()
22
+ if get_cached_media_file_storage_in_dir() is not None:
23
+ get_cached_media_file_storage_in_dir().init()
24
+
25
+ if get_cached_cache_file_storage_in_dir() is not None:
26
+ get_cached_cache_file_storage_in_dir().init()
27
+
28
+ if get_cached_dump_file_storage_in_dir() is not None:
29
+ get_cached_dump_file_storage_in_dir().init()
30
+
31
+ if (
32
+ get_cached_sqlalchemy_db() is not None
33
+ and get_cached_settings().api_init_sqlalchemy_db
34
+ ):
35
+ get_cached_sqlalchemy_db().init()
36
+
37
+ if (
38
+ get_cached_json_db() is not None
39
+ and get_cached_settings().api_init_json_db
40
+ ):
41
+ get_cached_json_db().init()
42
+
43
+ if get_cached_settings().api_start_operation_executor_worker:
44
+ _ = safe_run_worker_in_background(
45
+ worker=create_operation_executor_worker(),
46
+ mode=SafeRunInBackgroundModes.thread
47
+ )
48
+
49
+ if get_cached_settings().api_start_scheduled_operation_creator_worker:
50
+ _ = safe_run_worker_in_background(
51
+ worker=create_scheduled_operation_creator_worker(),
52
+ mode=SafeRunInBackgroundModes.async_task
53
+ )
28
54
 
29
55
  _logger.info("finish")
30
56
 
@@ -0,0 +1,69 @@
1
+ from typing import Iterable
2
+
3
+ import aiogram.types
4
+ from aiogram.filters import Filter
5
+
6
+ from arpakitlib.ar_type_util import raise_for_type
7
+ from core.settings import get_cached_settings
8
+
9
+
10
+ class NotProdModeFilterTgBotFilter(Filter):
11
+ async def __call__(self, *args, **kwargs) -> bool:
12
+ return get_cached_settings().is_mode_type_not_prod
13
+
14
+
15
+ class ProdModeFilterTgBotFilter(Filter):
16
+ async def __call__(self, *args, **kwargs) -> bool:
17
+ return get_cached_settings().is_mode_type_prod
18
+
19
+
20
+ class TextFilterTgBotFilter(Filter):
21
+
22
+ def __init__(
23
+ self,
24
+ *texts: str | Iterable[str],
25
+ ignore_case: bool = True
26
+ ) -> None:
27
+ self.ignore_case = ignore_case
28
+ self.texts = set()
29
+
30
+ for text in texts:
31
+
32
+ if isinstance(text, str):
33
+ if ignore_case is True:
34
+ text = text.lower()
35
+ text = text.strip()
36
+ self.texts.add(text)
37
+
38
+ elif isinstance(text, Iterable):
39
+ for text_ in text:
40
+ raise_for_type(text_, str)
41
+ if ignore_case is True:
42
+ text_ = text_.lower()
43
+ text_ = text_.strip()
44
+ self.texts.add(text_)
45
+
46
+ else:
47
+ raise TypeError(f"text has bad type = {type(text)}")
48
+
49
+ async def __call__(self, message: aiogram.types.Message, *args, **kwargs) -> bool:
50
+ raise_for_type(message, aiogram.types.Message)
51
+
52
+ if message.text is None:
53
+ return False
54
+
55
+ text = message.text.strip()
56
+ if self.ignore_case is True:
57
+ text = text.lower()
58
+
59
+ return text in self.texts
60
+
61
+
62
+ class IsPrivateChatTgBotFilter(Filter):
63
+ async def __call__(self, update: aiogram.types.Message | aiogram.types.CallbackQuery) -> bool:
64
+ if isinstance(update, aiogram.types.Message):
65
+ return update.chat.type == aiogram.enums.ChatType.PRIVATE
66
+ elif isinstance(update, aiogram.types.CallbackQuery):
67
+ return update.message.chat.type == aiogram.enums.ChatType.PRIVATE
68
+ else:
69
+ return False
@@ -0,0 +1,37 @@
1
+ from aiogram.filters.callback_data import CallbackData
2
+
3
+ _used_cd_prefixes = set()
4
+
5
+
6
+ def get_used_cd_prefixes() -> set[str]:
7
+ return _used_cd_prefixes
8
+
9
+
10
+ def generate_callback_data_prefix(string: str) -> str:
11
+ res = 0
12
+ for s_ in string:
13
+ res += ord(s_)
14
+ res += len(string)
15
+ res = str(res)
16
+ return res
17
+
18
+
19
+ class BaseCD(CallbackData, prefix="BaseCD"):
20
+
21
+ def __init_subclass__(cls, **kwargs):
22
+ if not cls.__name__.endswith("CD"):
23
+ raise ValueError("callback data class should ends with CD")
24
+
25
+ if "prefix" not in kwargs:
26
+ kwargs["prefix"] = str(generate_callback_data_prefix(cls.__name__.lower().removesuffix("cd")))
27
+ prefix = kwargs["prefix"]
28
+
29
+ if prefix in _used_cd_prefixes:
30
+ raise ValueError(f"prefix({prefix}) already in _used_cd_prefixes({_used_cd_prefixes})")
31
+ _used_cd_prefixes.add(prefix)
32
+
33
+ super().__init_subclass__(**kwargs)
34
+
35
+
36
+ class WithFromCD(BaseCD, prefix="WithFromCD"):
37
+ from_: str | None = None
@@ -0,0 +1,15 @@
1
+ from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
2
+ from aiogram.utils.keyboard import InlineKeyboardBuilder
3
+
4
+ from tg_bot.blank.blank import get_cached_tg_bot_blank
5
+
6
+
7
+ def groups_inline_kb() -> InlineKeyboardMarkup:
8
+ kb_builder = InlineKeyboardBuilder()
9
+
10
+ kb_builder.row(InlineKeyboardButton(
11
+ text=get_cached_tg_bot_blank().hello_world(),
12
+ callback_data="Hello world"
13
+ ))
14
+
15
+ return kb_builder.as_markup()
@@ -0,0 +1,14 @@
1
+ from aiogram.types import ReplyKeyboardMarkup, KeyboardButton
2
+ from aiogram.utils.keyboard import ReplyKeyboardBuilder
3
+
4
+ from tg_bot.blank.blank import get_cached_tg_bot_blank
5
+
6
+
7
+ def hello_world_static_kb() -> ReplyKeyboardMarkup:
8
+ kb_builder = ReplyKeyboardBuilder()
9
+
10
+ kb_builder.row(KeyboardButton(
11
+ text=get_cached_tg_bot_blank().hello_world()
12
+ ))
13
+
14
+ return kb_builder.as_markup(resize_keyboard=True, one_time_keyboard=False)
@@ -4,8 +4,6 @@ from typing import Any, Awaitable, Callable, Dict
4
4
  from aiogram import BaseMiddleware
5
5
  from aiogram.types import TelegramObject
6
6
 
7
- from tg_bot.transmitted_tg_data import TransmittedTgBotData
8
-
9
7
  _logger = logging.getLogger(__name__)
10
8
 
11
9
 
@@ -18,7 +16,6 @@ class InitUserTgBotMiddleware(BaseMiddleware):
18
16
  data: Dict[str, Any],
19
17
  ) -> Any:
20
18
  _logger.info("start")
21
- transmitted_tg_bot_data: TransmittedTgBotData = data["transmitted_tg_bot_data"]
22
19
  # ...
23
20
  _logger.info("finish")
24
21
  return await handler(event, data)
@@ -3,10 +3,10 @@ import aiogram
3
3
  from tg_bot.middleware.init_user import InitUserTgBotMiddleware
4
4
 
5
5
 
6
- def register_tg_bot_middleware(
6
+ def register_middlewares_to_tg_bot(
7
7
  *,
8
- tg_bot_dp: aiogram.Dispatcher,
8
+ tg_bot_dispatcher: aiogram.Dispatcher,
9
9
  **kwargs
10
10
  ) -> aiogram.Dispatcher:
11
- tg_bot_dp.update.outer_middleware.register(InitUserTgBotMiddleware())
12
- return tg_bot_dp
11
+ tg_bot_dispatcher.update.outer_middleware.register(InitUserTgBotMiddleware())
12
+ return tg_bot_dispatcher
@@ -0,0 +1,14 @@
1
+ import aiogram.filters
2
+
3
+ from arpakitlib.ar_json_util import safely_transfer_obj_to_json_str
4
+ from tg_bot.const import TgBotCommands
5
+ from util.read_arpakitlib_project_template_file import read_arpakitlib_project_template_file
6
+
7
+ tg_bot_router = aiogram.Router()
8
+
9
+
10
+ @tg_bot_router.message(aiogram.filters.Command(TgBotCommands.arpakitlib_project_template_info))
11
+ async def _(m: aiogram.types.Message, **kwargs):
12
+ await m.answer(
13
+ text=safely_transfer_obj_to_json_str(data=read_arpakitlib_project_template_file())
14
+ )
@@ -1,15 +1,12 @@
1
1
  import aiogram
2
2
  from aiogram import Router
3
3
 
4
- from tg_bot.transmitted_tg_data import TransmittedTgBotData
5
-
6
4
  tg_bot_router = Router()
7
5
 
8
6
 
9
7
  @tg_bot_router.error()
10
8
  async def _(
11
9
  event: aiogram.types.ErrorEvent,
12
- transmitted_tg_bot_data: TransmittedTgBotData,
13
10
  **kwargs
14
11
  ):
15
12
  pass
@@ -1,5 +1,6 @@
1
1
  import aiogram.filters
2
2
 
3
+ from tg_bot.blank.blank import get_cached_tg_bot_blank
3
4
  from tg_bot.const import TgBotCommands
4
5
 
5
6
  tg_bot_router = aiogram.Router()
@@ -7,4 +8,4 @@ tg_bot_router = aiogram.Router()
7
8
 
8
9
  @tg_bot_router.message(aiogram.filters.Command(TgBotCommands.healthcheck))
9
10
  async def _(m: aiogram.types.Message, **kwargs):
10
- await m.answer(text="healthcheck")
11
+ await m.answer(text=get_cached_tg_bot_blank().healthcheck())
@@ -1,14 +1,18 @@
1
1
  from aiogram import Router
2
2
 
3
- from tg_bot.router import error
3
+ from tg_bot.router import error, arpakitlib_project_template_info
4
4
  from tg_bot.router import healthcheck
5
5
 
6
6
  main_tg_bot_router = Router()
7
7
 
8
+ # Error
9
+
10
+ main_tg_bot_router.include_router(router=error.tg_bot_router)
11
+
8
12
  # Healthcheck
9
13
 
10
14
  main_tg_bot_router.include_router(router=healthcheck.tg_bot_router)
11
15
 
12
- # Error
16
+ # arpakit project template
13
17
 
14
- main_tg_bot_router.include_router(router=error.tg_bot_router)
18
+ main_tg_bot_router.include_router(router=arpakitlib_project_template_info.tg_bot_router)
@@ -1,32 +1,37 @@
1
- from arpakitlib.ar_aiogram_util import start_aiogram_tg_bot_with_webhook
1
+ import asyncio
2
+
3
+ import aiohttp
4
+ import aiohttp.web
5
+ from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application
6
+
7
+ from core.settings import get_cached_settings
2
8
  from core.util import setup_logging
3
- from tg_bot.event import add_events_to_tg_bot_dispatcher
4
9
  from tg_bot.tg_bot import create_tg_bot
5
10
  from tg_bot.tg_bot_dispatcher import create_tg_bot_dispatcher
6
- from tg_bot.transmitted_tg_data import get_cached_transmitted_tg_bot_data
7
11
 
8
12
 
9
13
  def start_tg_bot():
10
14
  setup_logging()
11
15
 
12
- transmitted_tg_bot_data = get_cached_transmitted_tg_bot_data()
13
-
14
16
  tg_bot = create_tg_bot()
15
17
 
16
18
  tg_bot_dispatcher = create_tg_bot_dispatcher()
17
19
 
18
- add_events_to_tg_bot_dispatcher(tg_bot_dispatcher=tg_bot_dispatcher)
19
-
20
- if transmitted_tg_bot_data.settings.tg_bot_webhook_enabled:
21
- tg_bot_dispatcher.start_polling(tg_bot)
20
+ if not get_cached_settings().tg_bot_webhook_enabled:
21
+ asyncio.run(tg_bot_dispatcher.start_polling(tg_bot))
22
22
  else:
23
- start_aiogram_tg_bot_with_webhook(
23
+ app = aiohttp.web.Application()
24
+ simple_requests_handler = SimpleRequestHandler(
24
25
  dispatcher=tg_bot_dispatcher,
25
26
  bot=tg_bot,
26
- webhook_secret=transmitted_tg_bot_data.settings.tg_bot_webhook_secret,
27
- webhook_path=transmitted_tg_bot_data.settings.tg_bot_webhook_path,
28
- webhook_server_hostname=transmitted_tg_bot_data.settings.tg_bot_webhook_server_hostname,
29
- webhook_server_port=transmitted_tg_bot_data.settings.tg_bot_webhook_server_port
27
+ secret_token=get_cached_settings().tg_bot_webhook_secret
28
+ )
29
+ simple_requests_handler.register(app, path=get_cached_settings().tg_bot_webhook_path)
30
+ setup_application(app, tg_bot_dispatcher, bot=tg_bot)
31
+ aiohttp.web.run_app(
32
+ app=app,
33
+ host=get_cached_settings().tg_bot_webhook_server_hostname,
34
+ port=get_cached_settings().tg_bot_webhook_server_port
30
35
  )
31
36
 
32
37
 
@@ -2,18 +2,19 @@ import aiogram
2
2
  from aiogram.fsm.storage.memory import MemoryStorage
3
3
 
4
4
  from tg_bot.event import add_events_to_tg_bot_dispatcher
5
+ from tg_bot.middleware.middleware import register_middlewares_to_tg_bot
5
6
  from tg_bot.router.main_router import main_tg_bot_router
6
- from tg_bot.transmitted_tg_data import get_cached_transmitted_tg_bot_data
7
7
 
8
8
 
9
9
  def create_tg_bot_dispatcher() -> aiogram.Dispatcher:
10
10
  tg_bot_dispatcher = aiogram.Dispatcher(
11
11
  storage=MemoryStorage(),
12
- transmitted_tg_bot_data=get_cached_transmitted_tg_bot_data()
13
12
  )
14
13
 
15
14
  add_events_to_tg_bot_dispatcher(tg_bot_dispatcher=tg_bot_dispatcher)
16
15
 
16
+ register_middlewares_to_tg_bot(tg_bot_dispatcher=tg_bot_dispatcher)
17
+
17
18
  tg_bot_dispatcher.include_router(router=main_tg_bot_router)
18
19
 
19
20
  return tg_bot_dispatcher
@@ -5,7 +5,7 @@ from core.const import ProjectPaths
5
5
 
6
6
 
7
7
  def read_arpakitlib_project_template_file() -> dict[str, Any]:
8
- with open(ProjectPaths.arpakit_lib_project_template_filepath, mode="r", encoding="utf-8") as fr:
8
+ with open(ProjectPaths.arpakit_lib_project_template_info_filepath, mode="r", encoding="utf-8") as fr:
9
9
  return json.load(fp=fr)
10
10
 
11
11
 
@@ -2,118 +2,22 @@
2
2
 
3
3
  import asyncio
4
4
  import logging
5
- from typing import Optional, Any, Union, Callable, Iterable
5
+ from typing import Optional, Any, Callable
6
6
 
7
- import aiogram
8
- import aiohttp
9
- import aiohttp.web
10
7
  from aiogram import types
11
- from aiogram.enums import ChatType
12
8
  from aiogram.exceptions import AiogramError
13
- from aiogram.filters import CommandObject, Filter
14
- from aiogram.filters.callback_data import CallbackData
15
- from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application
16
- from aiohttp import web
9
+ from aiogram.filters import CommandObject
17
10
  from pydantic import BaseModel
18
11
 
19
12
  from arpakitlib.ar_need_type_util import parse_need_type, NeedTypes
20
13
  from arpakitlib.ar_parse_command import BadCommandFormat, parse_command
21
- from arpakitlib.ar_type_util import raise_for_types, raise_for_type
14
+ from arpakitlib.ar_type_util import raise_for_types
22
15
 
23
16
  _ARPAKIT_LIB_MODULE_VERSION = "3.0"
24
17
 
25
18
  _logger = logging.getLogger(__name__)
26
19
 
27
20
 
28
- class TextFilter(Filter):
29
-
30
- def __init__(
31
- self,
32
- *texts: Union[str, Iterable[str]],
33
- ignore_case: bool = True
34
- ) -> None:
35
- self.ignore_case = ignore_case
36
- self.texts = set()
37
-
38
- for text in texts:
39
-
40
- if isinstance(text, str):
41
- if ignore_case is True:
42
- text = text.lower()
43
- text = text.strip()
44
- self.texts.add(text)
45
-
46
- elif isinstance(text, Iterable):
47
- for text_ in text:
48
- raise_for_type(text_, str)
49
- if ignore_case is True:
50
- text_ = text_.lower()
51
- text_ = text_.strip()
52
- self.texts.add(text_)
53
-
54
- else:
55
- raise TypeError(f"text has bad type = {type(text)}")
56
-
57
- async def __call__(self, message: types.Message, *args, **kwargs) -> bool:
58
- raise_for_type(message, types.Message)
59
-
60
- if message.text is None:
61
- return False
62
-
63
- text = message.text.strip()
64
- if self.ignore_case is True:
65
- text = text.lower()
66
-
67
- return text in self.texts
68
-
69
-
70
- class IsPrivateChat(Filter):
71
- async def __call__(self, update: types.Message | types.CallbackQuery) -> bool:
72
- if isinstance(update, types.Message):
73
- return update.chat.type == ChatType.PRIVATE
74
- elif isinstance(update, types.CallbackQuery):
75
- return update.message.chat.type == ChatType.PRIVATE
76
- else:
77
- return False
78
-
79
-
80
- _used_cd_prefixes = set()
81
-
82
-
83
- def get_used_cd_prefixes() -> set[str]:
84
- return _used_cd_prefixes
85
-
86
-
87
- def generate_cd_prefix(string: str) -> str:
88
- res = 0
89
- for s_ in string:
90
- res += ord(s_)
91
- res += len(string)
92
- res = str(res)
93
- return res
94
-
95
-
96
- class BaseCD(CallbackData, prefix="BaseCD"):
97
-
98
- def __init_subclass__(cls, **kwargs):
99
- if not cls.__name__.endswith("CD"):
100
- raise ValueError("callback data class should ends with CD")
101
-
102
- if "prefix" not in kwargs:
103
- kwargs["prefix"] = str(generate_cd_prefix(cls.__name__.lower().removesuffix("cd")))
104
- prefix = kwargs["prefix"]
105
-
106
- if prefix in _used_cd_prefixes:
107
- raise ValueError(f"prefix({prefix}) already in _used_cd_prefixes({_used_cd_prefixes})")
108
- _used_cd_prefixes.add(prefix)
109
-
110
- super().__init_subclass__(**kwargs)
111
-
112
-
113
- class WithFromCD(BaseCD, prefix="WithFromCD"):
114
- from_: Optional[str] = None
115
-
116
-
117
21
  class BadTgCommandFormat(BadCommandFormat):
118
22
  pass
119
23
 
@@ -314,30 +218,6 @@ def as_tg_command(
314
218
  return decorator
315
219
 
316
220
 
317
- def start_aiogram_tg_bot_with_webhook(
318
- *,
319
- dispatcher: aiogram.Dispatcher,
320
- bot: aiogram.Bot,
321
- webhook_secret: str = "123",
322
- webhook_path: str = "/tg_bot_webhook",
323
- webhook_server_hostname: str = "127.0.0.1",
324
- webhook_server_port: int = 8080
325
- ):
326
- app = aiohttp.web.Application()
327
- simple_requests_handler = SimpleRequestHandler(
328
- dispatcher=dispatcher,
329
- bot=bot,
330
- secret_token=webhook_secret
331
- )
332
- simple_requests_handler.register(app, path=webhook_path)
333
- setup_application(app, dispatcher, bot=bot)
334
- web.run_app(
335
- app=app,
336
- host=webhook_server_hostname,
337
- port=webhook_server_port
338
- )
339
-
340
-
341
221
  def __example():
342
222
  pass
343
223
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arpakitlib
3
- Version: 1.8.4
3
+ Version: 1.8.5
4
4
  Summary: arpakitlib
5
5
  License: Apache-2.0
6
6
  Keywords: arpakitlib,arpakit,arpakit-company,arpakitcompany,arpakit_company