funpaybotengine 0.5.3__tar.gz → 0.6.0__tar.gz

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 (120) hide show
  1. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/PKG-INFO +2 -2
  2. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/client/bot.py +19 -1
  3. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/client/session/aiohttp_session.py +4 -0
  4. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/exceptions/action_exceptions.py +20 -2
  5. funpaybotengine-0.6.0/funpaybotengine/exceptions/method_exceptions.py +20 -0
  6. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/__init__.py +1 -0
  7. funpaybotengine-0.6.0/funpaybotengine/methods/get_sras_info_page.py +29 -0
  8. funpaybotengine-0.6.0/funpaybotengine/methods/raise_offers.py +50 -0
  9. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/save_offer_fields.py +28 -4
  10. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/__init__.py +1 -0
  11. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/common.py +12 -0
  12. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/__init__.py +1 -0
  13. funpaybotengine-0.6.0/funpaybotengine/types/pages/sras_info_page.py +16 -0
  14. funpaybotengine-0.6.0/funpaybotengine/types/sras.py +21 -0
  15. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/pyproject.toml +2 -2
  16. funpaybotengine-0.5.3/funpaybotengine/methods/raise_offers.py +0 -83
  17. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/.github/CODEOWNERS +0 -0
  18. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/.gitignore +0 -0
  19. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/.pre-commit-config.yaml +0 -0
  20. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/LICENSE +0 -0
  21. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/Makefile +0 -0
  22. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/README.md +0 -0
  23. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/examples/basic.py +0 -0
  24. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/examples/temp.py +0 -0
  25. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/examples/with_redis_storage.py +0 -0
  26. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/__init__.py +0 -0
  27. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/base.py +0 -0
  28. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/client/__init__.py +0 -0
  29. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/client/default_hooks.py +0 -0
  30. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/client/session/__init__.py +0 -0
  31. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/client/session/base.py +0 -0
  32. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/client/session/http_methods.py +0 -0
  33. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/__init__.py +0 -0
  34. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/events/__init__.py +0 -0
  35. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/events/base.py +0 -0
  36. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/events/builtin_events.py +0 -0
  37. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/filters/__init__.py +0 -0
  38. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/filters/base.py +0 -0
  39. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/filters/message_filters.py +0 -0
  40. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/filters/order_filters.py +0 -0
  41. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/handlers/__init__.py +0 -0
  42. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/handlers/handler_manager.py +0 -0
  43. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/routers/__init__.py +0 -0
  44. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/routers/base.py +0 -0
  45. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/dispatching/routers/dispatcher.py +0 -0
  46. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/exceptions/__init__.py +0 -0
  47. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/exceptions/base.py +0 -0
  48. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/exceptions/bot_exceptions.py +0 -0
  49. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/exceptions/message_check_errors.py +0 -0
  50. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/exceptions/runner_exceptions.py +0 -0
  51. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/exceptions/session_exceptions.py +0 -0
  52. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/loggers.py +0 -0
  53. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/base.py +0 -0
  54. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/calc_chips.py +0 -0
  55. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/calc_lots.py +0 -0
  56. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/check_banned.py +0 -0
  57. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/delete_review.py +0 -0
  58. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_2fa_status.py +0 -0
  59. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_chat_history.py +0 -0
  60. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_chat_page.py +0 -0
  61. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_main_page.py +0 -0
  62. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_my_chips_page.py +0 -0
  63. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_my_offers_page.py +0 -0
  64. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_offer_fields.py +0 -0
  65. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_offer_page.py +0 -0
  66. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_order_page.py +0 -0
  67. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_profile_page.py +0 -0
  68. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_purchases.py +0 -0
  69. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_reviews.py +0 -0
  70. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_sales.py +0 -0
  71. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_settings_page.py +0 -0
  72. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_subcategory_page.py +0 -0
  73. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_telegram_connect_url.py +0 -0
  74. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_transactions.py +0 -0
  75. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/get_transactions_page.py +0 -0
  76. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/logout.py +0 -0
  77. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/mute_chat.py +0 -0
  78. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/refund.py +0 -0
  79. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/review.py +0 -0
  80. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/runner_request.py +0 -0
  81. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/set_offers_hidden.py +0 -0
  82. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/update_notice_channel.py +0 -0
  83. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/upload_avatar.py +0 -0
  84. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/methods/upload_image.py +0 -0
  85. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/py.typed +0 -0
  86. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/runner/__init__.py +0 -0
  87. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/runner/config.py +0 -0
  88. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/runner/event_collector.py +0 -0
  89. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/runner/runner.py +0 -0
  90. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/storage/__init__.py +0 -0
  91. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/storage/base.py +0 -0
  92. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/storage/inmemory.py +0 -0
  93. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/storage/redis.py +0 -0
  94. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/base.py +0 -0
  95. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/calc.py +0 -0
  96. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/categories.py +0 -0
  97. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/chat.py +0 -0
  98. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/common_page_elements.py +0 -0
  99. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/enums.py +0 -0
  100. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/finances.py +0 -0
  101. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/messages.py +0 -0
  102. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/offers.py +0 -0
  103. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/orders.py +0 -0
  104. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/base.py +0 -0
  105. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/chat_page.py +0 -0
  106. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/main_page.py +0 -0
  107. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/my_chips_page.py +0 -0
  108. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/my_offers_page.py +0 -0
  109. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/offer_page.py +0 -0
  110. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/order_page.py +0 -0
  111. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/profile_page.py +0 -0
  112. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/settings_page.py +0 -0
  113. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/subcategory_page.py +0 -0
  114. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/pages/transactions_page.py +0 -0
  115. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/requests/__init__.py +0 -0
  116. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/requests/runner.py +0 -0
  117. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/reviews.py +0 -0
  118. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/settings.py +0 -0
  119. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/types/updates.py +0 -0
  120. {funpaybotengine-0.5.3 → funpaybotengine-0.6.0}/funpaybotengine/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: funpaybotengine
3
- Version: 0.5.3
3
+ Version: 0.6.0
4
4
  Summary: Framework for creating FunPay bots.
5
5
  Project-URL: Telegram, https://t.me/funpay_hub
6
6
  Project-URL: Issues, https://github.com/funpayhub/funpaybotengine/issues
@@ -21,7 +21,7 @@ Requires-Python: >=3.10
21
21
  Requires-Dist: aiohttp-socks>=0.11.0
22
22
  Requires-Dist: aiohttp<3.14,>=3.13.3
23
23
  Requires-Dist: eventry<1.0.0,>=0.3.6
24
- Requires-Dist: funpayparsers<0.7.0,>=0.6.1
24
+ Requires-Dist: funpayparsers<0.8.0,>=0.7.0
25
25
  Requires-Dist: pydantic<2.13,>=2.12
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: mypy>=1.10.1; extra == 'dev'
@@ -27,6 +27,7 @@ from funpaybotengine.types import (
27
27
  PrivateChatPreview,
28
28
  TransactionPreviewsBatch,
29
29
  CurrentlyViewingOfferInfo,
30
+ RaiseOffersResponse
30
31
  )
31
32
  from funpaybotengine.utils import (
32
33
  random_runner_tag,
@@ -61,6 +62,7 @@ from funpaybotengine.methods import (
61
62
  GetProfilePage,
62
63
  GetSettingPage,
63
64
  GetMyOffersPage,
65
+ GetSrasInfoPage,
64
66
  GetTransactions,
65
67
  SaveOfferFields,
66
68
  SetOffersHidden,
@@ -86,6 +88,7 @@ from funpaybotengine.types.pages import (
86
88
  ProfilePage,
87
89
  MyOffersPage,
88
90
  SettingsPage,
91
+ SrasInfoPage,
89
92
  SubcategoryPage,
90
93
  TransactionsPage,
91
94
  )
@@ -141,6 +144,7 @@ class Bot:
141
144
  update_categories: bool = True,
142
145
  ) -> None:
143
146
  self._golden_key = golden_key
147
+ self._golden_seal: str | None = None
144
148
  self._csrf_token: str | None = None
145
149
  self._phpsessid: str | None = phpsessid
146
150
  self._logout_token: str | None = None
@@ -201,6 +205,10 @@ class Bot:
201
205
  """
202
206
  return self._golden_key
203
207
 
208
+ @property
209
+ def golden_seal(self) -> str | None:
210
+ return self._golden_seal
211
+
204
212
  @property
205
213
  def csrf_token(self) -> str:
206
214
  """
@@ -302,7 +310,7 @@ class Bot:
302
310
  async def mute_chat(self, chat_id: int, mute: bool) -> bool:
303
311
  return (await MuteChat(chat_id=chat_id, mute=mute).execute(self)).response_obj
304
312
 
305
- async def raise_offers(self, category_id: int, *subcategory_ids: int) -> bool:
313
+ async def raise_offers(self, category_id: int, *subcategory_ids: int) -> RaiseOffersResponse:
306
314
  if not subcategory_ids:
307
315
  category = await self.storage.get_category(category_id)
308
316
  if category is None:
@@ -837,6 +845,12 @@ class Bot:
837
845
  async def get_order_page(self, order_id: str) -> OrderPage:
838
846
  return (await GetOrderPage(order_id=order_id).execute(self)).response_obj
839
847
 
848
+ async def get_sras_info_page(self) -> SrasInfoPage:
849
+ """
850
+ Retrieves the SRAS info page with seller rating restrictions per subcategory.
851
+ """
852
+ return (await GetSrasInfoPage().execute(self)).response_obj
853
+
840
854
  async def get_settings_page(self) -> SettingsPage:
841
855
  return (await GetSettingPage().execute(self)).response_obj
842
856
 
@@ -893,6 +907,9 @@ class Bot:
893
907
  self._phpsessid = result.cookies['PHPSESSID']
894
908
  self._session_updated_at = int(time.time())
895
909
 
910
+ if 'golden_seal' in result.cookies and not skip_update:
911
+ self._golden_seal = result.cookies['golden_seal']
912
+
896
913
  return result
897
914
 
898
915
  async def update(self, change_locale: Language | None = None) -> Self:
@@ -910,6 +927,7 @@ class Bot:
910
927
 
911
928
  self._csrf_token = page_obj.app_data.csrf_token
912
929
  self._phpsessid = result.cookies.get('PHPSESSID')
930
+ self._golden_seal = result.cookies.get('golden_seal')
913
931
  self._logout_token = page_obj.header.logout_token
914
932
 
915
933
  if not self._locale or change_locale is not None:
@@ -89,6 +89,10 @@ class AioHttpSession(BaseSession):
89
89
  if bot.phpsessid and not skip_session_cookies:
90
90
  session.cookie_jar.update_cookies({'PHPSESSID': bot.phpsessid})
91
91
 
92
+ with suppress(BotNotInitializedError):
93
+ if bot.golden_seal and not skip_session_cookies:
94
+ session.cookie_jar.update_cookies({'golden_seal': bot.golden_seal})
95
+
92
96
  async def make_request(
93
97
  self,
94
98
  method: FunPayMethod[MethodReturnType],
@@ -2,6 +2,8 @@ from __future__ import annotations
2
2
 
3
3
 
4
4
  __all__ = ['RefundError', 'RaiseOffersError']
5
+ import re
6
+
5
7
  from .base import FunPayBotEngineError
6
8
 
7
9
 
@@ -21,10 +23,26 @@ class RaiseOffersError(FunPayBotEngineError):
21
23
  response: str,
22
24
  category_id: int,
23
25
  message: str | None,
24
- wait_time: int | None,
25
26
  ) -> None:
26
27
  super().__init__()
27
28
  self.raw_response = response
28
29
  self.category_id = category_id
29
30
  self.message = message
30
- self.wait_time = wait_time
31
+
32
+ @staticmethod
33
+ def parse_wait_time(response: str) -> int:
34
+ x = re.search(r'(\d+)\s+', response)
35
+ time = int(x.group(1)) if x else 0
36
+
37
+ if 'секунд' in response or 'second' in response:
38
+ return time or 2
39
+ if 'минут' in response or 'хвилин' in response or 'minute' in response:
40
+ return (time or 1) * 60
41
+ if 'час' in response or 'годин' in response or 'hour' in response:
42
+ return (time or 1) * 3600
43
+
44
+ return 10
45
+
46
+ @property
47
+ def wait_time(self) -> int:
48
+ return self.parse_wait_time(self.message or '')
@@ -0,0 +1,20 @@
1
+ __all__ = [
2
+ 'MethodError',
3
+ 'InvalidOfferFieldsError'
4
+ ]
5
+
6
+
7
+ from .base import FunPayBotEngineError
8
+
9
+
10
+ class MethodError(FunPayBotEngineError):
11
+ ...
12
+
13
+
14
+ class InvalidOfferFieldsError(MethodError):
15
+ def __init__(self, message: str, fields: dict[str, str] | None = None):
16
+ self.message = message
17
+ self.fields = fields
18
+
19
+ def __str__(self):
20
+ return self.message
@@ -28,6 +28,7 @@ from .get_my_chips_page import *
28
28
  from .get_settings_page import *
29
29
  from .save_offer_fields import *
30
30
  from .set_offers_hidden import *
31
+ from .get_sras_info_page import *
31
32
  from .get_my_offers_page import *
32
33
  from .get_subcategory_page import *
33
34
  from .get_transactions_page import *
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ __all__ = ('GetSrasInfoPage',)
5
+
6
+
7
+ from funpayparsers.parsers.page_parsers import SrasInfoPageParser
8
+
9
+ from funpaybotengine.types.pages import SrasInfoPage
10
+ from funpaybotengine.methods.base import FunPayMethod
11
+ from funpaybotengine.client.session.http_methods import HTTPMethod
12
+
13
+
14
+ class GetSrasInfoPage(FunPayMethod[SrasInfoPage]):
15
+ """
16
+ Get SRAS info page (``https://funpay.com/sras/info``).
17
+
18
+ Returns seller rating restrictions per subcategory.
19
+ Returns ``funpaybotengine.types.pages.SrasInfoPage``.
20
+ """
21
+
22
+ __model_to_build__ = SrasInfoPage
23
+
24
+ def __init__(self) -> None:
25
+ super().__init__(
26
+ url='sras/info',
27
+ method=HTTPMethod.GET,
28
+ parser_cls=SrasInfoPageParser,
29
+ )
@@ -0,0 +1,50 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ __all__ = ('RaiseOffers',)
5
+
6
+ import json
7
+ from typing import TYPE_CHECKING, Any
8
+ from collections.abc import Sequence
9
+
10
+ from pydantic import Field
11
+ from typing_extensions import Annotated
12
+
13
+ from funpaybotengine.types.enums import Language
14
+ from funpaybotengine.methods.base import FunPayMethod
15
+ from funpaybotengine.client.session.http_methods import HTTPMethod
16
+ from funpaybotengine.types.common import RaiseOffersResponse
17
+
18
+
19
+ if TYPE_CHECKING:
20
+ from funpaybotengine.client.session.base import RawResponse
21
+
22
+
23
+ class RaiseOffers(FunPayMethod[RaiseOffersResponse]):
24
+ category_id: int
25
+ subcategory_ids: Annotated[Sequence[int], Field(min_length=1)]
26
+ __model_to_build__ = RaiseOffersResponse
27
+
28
+ def __init__(
29
+ self,
30
+ category_id: int,
31
+ subcategory_ids: Sequence[int],
32
+ locale: Language | None = None,
33
+ ):
34
+ super().__init__(
35
+ url='lots/raise',
36
+ method=HTTPMethod.POST,
37
+ locale=locale,
38
+ data={
39
+ 'game_id': category_id,
40
+ 'node_id': subcategory_ids[0],
41
+ 'node_ids[]': subcategory_ids,
42
+ },
43
+ headers={'x-requested-with': 'XMLHttpRequest'},
44
+ category_id=category_id,
45
+ subcategory_ids=subcategory_ids,
46
+ )
47
+
48
+ async def parse_result(self, response: RawResponse[bool]) -> dict[str, Any]:
49
+ data = json.loads(response.raw_response)
50
+ return {'raw_source': response.raw_response} | data
@@ -9,9 +9,11 @@ from pydantic import BaseModel
9
9
  from funpayparsers.types import Language
10
10
  from funpayparsers.parsers import OfferFieldsParser
11
11
 
12
+ from funpaybotengine.exceptions.method_exceptions import InvalidOfferFieldsError
12
13
  from funpaybotengine.methods.base import FunPayMethod
13
14
  from funpaybotengine.types.offers import OfferFields
14
15
  from funpaybotengine.client.session import HTTPMethod, RawResponse
16
+ import json
15
17
 
16
18
 
17
19
  class SaveOfferFields(FunPayMethod[bool], BaseModel):
@@ -33,13 +35,35 @@ class SaveOfferFields(FunPayMethod[bool], BaseModel):
33
35
  url=url,
34
36
  method=HTTPMethod.POST,
35
37
  data=offer_fields.fields_dict,
38
+ headers={'X-Requested-With': 'XMLHttpRequest'},
36
39
  parser_cls=OfferFieldsParser,
37
40
  locale=locale,
38
41
  offer_fields=offer_fields,
39
42
  )
40
43
 
41
- async def parse_result(self, response: RawResponse[Any]) -> bool:
42
- return True
44
+ async def parse_result(self, response: RawResponse[Any]) -> bool | dict[str, Any]:
45
+ try:
46
+ return json.loads(response.raw_response)
47
+ except json.decoder.JSONDecodeError:
48
+ return True
43
49
 
44
- async def transform_result(self, parsing_result: Any, response: RawResponse[Any]) -> bool:
45
- return True
50
+ async def transform_result(
51
+ self,
52
+ parsing_result: bool | dict[str, Any],
53
+ response: RawResponse[Any]
54
+ ) -> bool:
55
+ if isinstance(parsing_result, bool):
56
+ return parsing_result
57
+
58
+
59
+ if not parsing_result.get('error'):
60
+ return True
61
+
62
+ error_msg = str(parsing_result.get('msg', '')) or str(parsing_result.get('error'))
63
+ fields: list[list[str, str]] = parsing_result.get('errors')
64
+ try:
65
+ fields_dict = {field: error for field, error in fields}
66
+ except Exception:
67
+ fields_dict = {}
68
+
69
+ raise InvalidOfferFieldsError(error_msg, fields_dict)
@@ -11,6 +11,7 @@ from .reviews import *
11
11
  from .updates import *
12
12
  from .finances import *
13
13
  from .messages import *
14
+ from .sras import *
14
15
  from .settings import *
15
16
  from .categories import *
16
17
  from .common_page_elements import *
@@ -13,6 +13,7 @@ __all__ = (
13
13
  'PaymentOption',
14
14
  )
15
15
 
16
+ from datetime import datetime
16
17
 
17
18
  from pydantic import BaseModel
18
19
 
@@ -157,6 +158,17 @@ class RaiseOffersResponse(FunPayObject, BaseModel):
157
158
  msg: str
158
159
  """Status message."""
159
160
 
161
+ wait: int
162
+ """How long to wait until next raise is available (in seconds)."""
163
+
164
+ unlock_at: str
165
+ """String representation of the time when the next raise is available."""
166
+
167
+ @property
168
+ def unlock_at_datetime(self) -> datetime:
169
+ """Datetime object of the time when the next raise is available."""
170
+ return datetime.fromisoformat(self.unlock_at)
171
+
160
172
 
161
173
  class PaymentOption(FunPayObject):
162
174
  """Represents an offer payment option (typically from offer page)."""
@@ -10,4 +10,5 @@ from .my_chips_page import *
10
10
  from .settings_page import *
11
11
  from .my_offers_page import *
12
12
  from .subcategory_page import *
13
+ from .sras_info_page import *
13
14
  from .transactions_page import *
@@ -0,0 +1,16 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ __all__ = ('SrasInfoPage',)
5
+
6
+
7
+ from funpaybotengine.types.sras import SrasSectionRestriction
8
+ from funpaybotengine.types.enums import SubcategoryType
9
+ from funpaybotengine.types.pages.base import FunPayPage
10
+
11
+
12
+ class SrasInfoPage(FunPayPage):
13
+ """Represents the SRAS info page (``https://funpay.com/sras/info``)."""
14
+
15
+ restrictions: dict[SubcategoryType, dict[int, SrasSectionRestriction]]
16
+ """Restrictions grouped by subcategory type and subcategory ID."""
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ __all__ = ('SrasSectionRestriction',)
5
+
6
+
7
+ from funpaybotengine.types.base import FunPayObject
8
+ from funpaybotengine.types.enums import SubcategoryType
9
+
10
+
11
+ class SrasSectionRestriction(FunPayObject):
12
+ """Represents a SRAS restriction for a specific subcategory."""
13
+
14
+ subcategory_id: int
15
+ """Subcategory ID."""
16
+
17
+ subcategory_type: SubcategoryType
18
+ """Subcategory type."""
19
+
20
+ max_rating: int
21
+ """Maximum allowed seller rating to be listed in this subcategory."""
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "funpaybotengine"
3
- version = "0.5.3"
3
+ version = "0.6.0"
4
4
  description = "Framework for creating FunPay bots."
5
5
  requires-python = ">=3.10"
6
6
  readme = "README.md"
@@ -9,7 +9,7 @@ dependencies = [
9
9
  "aiohttp>=3.13.3,<3.14",
10
10
  "aiohttp-socks>=0.11.0",
11
11
  "eventry>=0.3.6,<1.0.0",
12
- "funpayparsers>=0.6.1,<0.7.0",
12
+ "funpayparsers>=0.7.0,<0.8.0",
13
13
  "pydantic>=2.12,<2.13",
14
14
  ]
15
15
  authors = [
@@ -1,83 +0,0 @@
1
- from __future__ import annotations
2
-
3
-
4
- __all__ = ('RaiseOffers',)
5
-
6
- import re
7
- import json
8
- from typing import TYPE_CHECKING
9
- from collections.abc import Sequence
10
-
11
- from pydantic import Field
12
- from typing_extensions import Literal, Annotated
13
-
14
- from funpaybotengine.exceptions import RaiseOffersError
15
- from funpaybotengine.types.enums import Language
16
- from funpaybotengine.methods.base import FunPayMethod
17
- from funpaybotengine.client.session.http_methods import HTTPMethod
18
-
19
-
20
- if TYPE_CHECKING:
21
- from funpaybotengine.client.session.base import RawResponse
22
-
23
-
24
- def parse_wait_time(response: str) -> int:
25
- x = re.search(r'(\d+)', response)
26
- time = int(x.group()) if x else 0
27
-
28
- if 'секунд' in response or 'second' in response:
29
- return time or 2
30
- if 'минут' in response or 'хвилин' in response or 'minute' in response:
31
- return (time - 1 if time else 1) * 60
32
- if 'час' in response or 'годин' in response or 'hour' in response:
33
- return int((time - 0.5 if time else 1) * 3600)
34
- return 10
35
-
36
-
37
- class RaiseOffers(FunPayMethod[Literal[True]]):
38
- category_id: int
39
- subcategory_ids: Annotated[Sequence[int], Field(min_length=1)]
40
-
41
- def __init__(
42
- self,
43
- category_id: int,
44
- subcategory_ids: Sequence[int],
45
- locale: Language | None = None,
46
- ):
47
- super().__init__(
48
- url='lots/raise',
49
- method=HTTPMethod.POST,
50
- locale=locale,
51
- data={
52
- 'game_id': category_id,
53
- 'node_id': subcategory_ids[0],
54
- 'node_ids[]': subcategory_ids,
55
- },
56
- headers={'x-requested-with': 'XMLHttpRequest'},
57
- category_id=category_id,
58
- subcategory_ids=subcategory_ids,
59
- )
60
-
61
- async def parse_result(self, response: RawResponse[bool]) -> Literal[True]:
62
- data = json.loads(response.raw_response)
63
- error, url, msg = data.get('error'), data.get('url'), data.get('msg')
64
-
65
- if url:
66
- raise RaiseOffersError(response.raw_response, self.category_id, url, None)
67
-
68
- if error:
69
- if msg:
70
- if any(_ in msg for _ in ('Подождите ', 'Please wait ', 'Зачекайте ')):
71
- wait = parse_wait_time(msg)
72
- else:
73
- wait = None
74
- raise RaiseOffersError(response.raw_response, self.category_id, msg, wait)
75
- raise RaiseOffersError(response.raw_response, self.category_id, msg, None)
76
- return True
77
-
78
- async def transform_result(
79
- self,
80
- parsing_result: Literal[True],
81
- response: RawResponse[bool],
82
- ) -> Literal[True]:
83
- return True
File without changes