fpx-engine 0.7.2__tar.gz → 0.7.4__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 (53) hide show
  1. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/PKG-INFO +1 -1
  2. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/_api/_client.py +22 -0
  3. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/_parsers/__init__.py +2 -1
  4. fpx_engine-0.7.4/fpx/_parsers/_category.py +39 -0
  5. fpx_engine-0.7.4/fpx/classes/account/subclasses/addons.py +64 -0
  6. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/account/subclasses/category.py +55 -0
  7. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/runner/subclasses/router.py +19 -2
  8. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/models/account.py +22 -0
  9. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx_engine.egg-info/PKG-INFO +1 -1
  10. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx_engine.egg-info/SOURCES.txt +1 -0
  11. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/pyproject.toml +1 -1
  12. fpx_engine-0.7.2/fpx/classes/account/subclasses/addons.py +0 -29
  13. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/LICENSE +0 -0
  14. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/README.md +0 -0
  15. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/__init__.py +0 -0
  16. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/_parsers/_base.py +0 -0
  17. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/_parsers/_chats.py +0 -0
  18. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/_parsers/_lots.py +0 -0
  19. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/_parsers/_orders.py +0 -0
  20. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/_parsers/_profile.py +0 -0
  21. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/account/account.py +0 -0
  22. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/account/subclasses/chat.py +0 -0
  23. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/account/subclasses/editor.py +0 -0
  24. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/account/subclasses/lot.py +0 -0
  25. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/account/subclasses/order.py +0 -0
  26. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/account/subclasses/profile.py +0 -0
  27. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/account/subclasses/review.py +0 -0
  28. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/runner/runner.py +0 -0
  29. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/runner/subclasses/_category.py +0 -0
  30. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/runner/subclasses/_chat.py +0 -0
  31. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/runner/subclasses/_order.py +0 -0
  32. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/classes/runner/subclasses/_review.py +0 -0
  33. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/fsm/__init__.py +0 -0
  34. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/fsm/fsm.py +0 -0
  35. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/main.py +0 -0
  36. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/middlewares/_request_engine.py +0 -0
  37. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/models/__init__.py +0 -0
  38. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/models/chat.py +0 -0
  39. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/models/lots.py +0 -0
  40. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/py.typed +0 -0
  41. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/services/__init__.py +0 -0
  42. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/utils/dependencies.py +0 -0
  43. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/utils/errors.py +0 -0
  44. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/utils/storage/__init__.py +0 -0
  45. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/utils/storage/base.py +0 -0
  46. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/utils/storage/file.py +0 -0
  47. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/utils/storage/memory.py +0 -0
  48. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx/utils/storage/redis.py +0 -0
  49. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx_engine.egg-info/dependency_links.txt +0 -0
  50. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx_engine.egg-info/requires.txt +0 -0
  51. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/fpx_engine.egg-info/top_level.txt +0 -0
  52. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/setup.cfg +0 -0
  53. {fpx_engine-0.7.2 → fpx_engine-0.7.4}/tests/test_happy_path.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fpx-engine
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Summary: Автоматизация работы с FunPay
5
5
  Author-email: Be My Code <gettofarmila@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/bymyforge/fpx
@@ -187,3 +187,25 @@ class FunPayClient:
187
187
  headers=headers
188
188
  )
189
189
  return r.json()
190
+
191
+ async def find_category(self, target):
192
+ headers = {
193
+ "X-Requested-With": "XMLHttpRequest"
194
+ }
195
+ r = await self.client.request(
196
+ 'POST', '/games/promoFilter',
197
+ data={'query': target},
198
+ headers=headers
199
+ )
200
+ return r.json()
201
+
202
+ async def calc_category_price(self, price, node_id):
203
+ headers = {
204
+ "X-Requested-With": "XMLHttpRequest"
205
+ }
206
+ r = await self.client.request(
207
+ 'POST', '/lots/calc',
208
+ data={'nodeId': node_id, 'price': price},
209
+ headers=headers
210
+ )
211
+ return r.json()
@@ -1,10 +1,11 @@
1
+ from ._category import CategoryParser
1
2
  from ._chats import ChatParser
2
3
  from ._lots import LotParser
3
4
  from ._orders import OrderParser
4
5
  from ._profile import ProfileParser
5
6
 
6
7
 
7
- class FpxParser(ChatParser, LotParser, OrderParser, ProfileParser):
8
+ class FpxParser(ChatParser, LotParser, OrderParser, ProfileParser, CategoryParser):
8
9
  '''
9
10
  Главный парсер fpx
10
11
  Собирает внутри себя методы из отдельных модулей.
@@ -0,0 +1,39 @@
1
+ import logging
2
+
3
+ from bs4 import BeautifulSoup
4
+
5
+ from fpx.models.account import Game, GameSubCategory, GameTitle
6
+
7
+ from ._base import BaseParser
8
+
9
+ logger = logging.getLogger("fpx.category_parser")
10
+
11
+
12
+ class CategoryParser(BaseParser):
13
+
14
+ @classmethod
15
+ def parse_all_categories(cls, html_content):
16
+ '''Парсит главную страницу фп на лоты'''
17
+ soup = BeautifulSoup(html_content, 'html.parser')
18
+ items = soup.find_all('div', class_='promo-game-item')
19
+ result = []
20
+ for item in items:
21
+ game_title = item.find('div', class_='game-title')
22
+ game_name = game_title.get_text(strip=True)
23
+ data_id = game_title.get('data-id')
24
+ subcategory_str = item.find('ul', class_='list-inline')
25
+ subcategory_list = subcategory_str.find_all('li')
26
+ subcategories = []
27
+ for s in subcategory_list:
28
+ a = s.find('a')
29
+ href = a.get('href')
30
+ category_id = href.split('/')[-2]
31
+ name = s.get_text()
32
+ subcategories.append(GameSubCategory(id=category_id, sub_name=name))
33
+ title = GameTitle(id=data_id, name=game_name)
34
+ result.append(Game(title=title, subcategories=subcategories))
35
+ return result
36
+
37
+ @classmethod
38
+ def parse_category_browser(cls, html_content):
39
+ BeautifulSoup(html_content, 'html.parser')
@@ -0,0 +1,64 @@
1
+
2
+ from fpx.models.account import Calc
3
+ from fpx.utils import errors as fpx_err
4
+
5
+
6
+ class AddonsManager:
7
+ def __init__(self, account):
8
+ self._account = account
9
+
10
+ async def get_game_id(self, category_id: str):
11
+ """
12
+ Получает game_id.
13
+
14
+ Args:
15
+ category_id (str | int): ID подкатегории.
16
+
17
+ Returns:
18
+ str | int: ID игры.
19
+
20
+ Raises:
21
+ FpxGetGameIDError: Ошибка запроса ID игры
22
+ """
23
+ try:
24
+ stage = 'запроса данных категории с FunPay'
25
+ html = await self._account._client.lot_menu_by_category(category_id)
26
+ stage = 'парсинга данных'
27
+ data = self._account._parser.parse_lot_menu(html)
28
+ except Exception as e:
29
+ raise fpx_err.FpxGetGameIDError(f'При выполнении {stage} произошла ошибка: {e}')
30
+ return data
31
+
32
+ async def calc_category_price(self, price, node_id):
33
+ '''
34
+ Считает цену в категории с включенной комиссией.
35
+ Args:
36
+ price (str | float | int): Твоя цена до комиссии.
37
+ node_id (str | int): ID категории
38
+ Returns:
39
+ list[Calc]: Список объектов. В каждой итерации содержит:
40
+ - type_name (str): Название типа оплаты(банковская карта, сбп)
41
+ - price (str): Цена с комиссией
42
+ - unit (str): Символ валюты(типа еврики, рубли, доллары $$$)
43
+ - pos (str): Позиция. В 99% не нужный параметр,
44
+ если вам будет нужно, вы уже должны знать
45
+ об этом
46
+ Raises:
47
+ FpxGetGameIDError: Ошибка запроса данных
48
+ '''
49
+ try:
50
+ data = await self._account._client.calc_category_price(price, node_id)
51
+ price_list = data['methods']
52
+ except Exception as e:
53
+ raise fpx_err.FpxRequestError(f'При сборе всех категорий произошла ошибка: {e}')
54
+ calc_list = []
55
+ for price in price_list:
56
+ calc_list.append(
57
+ Calc(
58
+ type_name=price['name'],
59
+ price=price['price'],
60
+ unit=price['unit'],
61
+ pos=price['pos']
62
+ )
63
+ )
64
+ return calc_list
@@ -1,5 +1,6 @@
1
1
 
2
2
 
3
+ from fpx.models.account import Game
3
4
  from fpx.models.lots import CategoryLastLot
4
5
  from fpx.utils import errors as fpx_err
5
6
 
@@ -65,3 +66,57 @@ class CategoryManager:
65
66
  for el in data:
66
67
  result.append(CategoryLastLot(category_id=chip_category_id, **el))
67
68
  return result
69
+
70
+ async def get_all_categories(self) -> list[Game]:
71
+ '''
72
+ Собирает все категории с фанпей.
73
+ Returns:
74
+ list[Game]: Список объектов, в каждой итерации
75
+ содержит в себе:
76
+ - title (GameTitle):
77
+ Который содержит в себе:
78
+ - id (int): ID категории
79
+ - name (str): Название категории
80
+
81
+ - subcategories (GameSubCategory):
82
+ - id (int): ID подкатегории
83
+ - sub_name (str): Название подкатегории
84
+ Raises:
85
+ FpxRequestError: Ошибка запроса данных
86
+ '''
87
+ try:
88
+ html = await self._account._client.get_main_menu()
89
+ data = self._account._parser.parse_all_categories(html)
90
+ except Exception as e:
91
+ raise fpx_err.FpxRequestError(f'При сборе всех категорий произошла ошибка: {e}')
92
+ return data
93
+
94
+ async def find_category(self, target):
95
+ '''
96
+ Использует встроенный поиск фанпей,
97
+ ищет категории по совпадениям, допустимы
98
+ довольно критичные погрешности.
99
+
100
+ Args:
101
+ target (str): Слово, по которому идет поиск
102
+ Returns:
103
+ list[Game]: Список объектов, в каждой итерации
104
+ содержит в себе:
105
+ - title (GameTitle):
106
+ Который содержит в себе:
107
+ - id (int): ID категории
108
+ - name (str): Название категории
109
+
110
+ - subcategories (GameSubCategory):
111
+ - id (int): ID подкатегории
112
+ - sub_name (str): Название подкатегории
113
+ Raises:
114
+ FpxRequestError: Ошибка запроса данных
115
+
116
+ '''
117
+ try:
118
+ html = await self._account._client.find_category(target)
119
+ data = self._account._parser.parse_all_categories(html['html'])
120
+ except Exception as e:
121
+ raise fpx_err.FpxRequestError(f'При сборе всех категорий произошла ошибка: {e}')
122
+ return data
@@ -38,10 +38,12 @@ class Router:
38
38
 
39
39
  async def invoke(self, h_func, event, state_ctx=None, args=None):
40
40
  '''Вызывает хендлер'''
41
+ generators_to_close = []
41
42
  async def endpoint(ev):
42
43
  sig = inspect.signature(h_func)
43
44
  kwargs = {}
44
45
  arg_index = 0
46
+ nonlocal generators_to_close
45
47
  for param_name, param in sig.parameters.items():
46
48
  if param.annotation is not inspect.Parameter.empty and isinstance(ev, param.annotation):
47
49
  kwargs[param_name] = ev
@@ -52,7 +54,15 @@ class Router:
52
54
  if isinstance(param.default, Dependency):
53
55
  dep_func = param.default.dependency
54
56
  dep_sig = inspect.signature(dep_func)
55
- if len(dep_sig.parameters) == 0:
57
+ if inspect.isasyncgenfunction(dep_func):
58
+ gen = dep_func(ev)
59
+ try:
60
+ resolved_val = await anext(gen)
61
+ kwargs[param_name] = resolved_val
62
+ generators_to_close.append(gen)
63
+ except StopAsyncIteration:
64
+ pass
65
+ elif len(dep_sig.parameters) == 0:
56
66
  if asyncio.iscoroutinefunction(dep_func):
57
67
  kwargs[param_name] = await dep_func(ev)
58
68
  else:
@@ -75,7 +85,14 @@ class Router:
75
85
  return await mw(ev, next_)
76
86
  return call
77
87
  call_next = await make_next()
78
- await call_next(event)
88
+ try:
89
+ await call_next(event)
90
+ finally:
91
+ for gen in generators_to_close:
92
+ try:
93
+ await gen.aclose()
94
+ except Exception:
95
+ pass
79
96
 
80
97
  def include_router(self, router):
81
98
  '''Метод для подключения плагинов и сторонних роутеров'''
@@ -13,6 +13,13 @@ class Balance:
13
13
  usd: float=0.0
14
14
  eur: float=0.0
15
15
 
16
+ @dataclass
17
+ class Calc:
18
+ type_name: str
19
+ price: str
20
+ unit: str
21
+ pos: str
22
+
16
23
  @dataclass
17
24
  class CurReview:
18
25
  text: str
@@ -103,3 +110,18 @@ class Review:
103
110
  text: str
104
111
  stars: int
105
112
  answer: str
113
+
114
+ @dataclass
115
+ class GameTitle:
116
+ id: int
117
+ name: str
118
+
119
+ @dataclass
120
+ class GameSubCategory:
121
+ id: int
122
+ sub_name: str
123
+
124
+ @dataclass
125
+ class Game:
126
+ title: GameTitle
127
+ subcategories: list[GameSubCategory] = field(default_factory=list)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fpx-engine
3
- Version: 0.7.2
3
+ Version: 0.7.4
4
4
  Summary: Автоматизация работы с FunPay
5
5
  Author-email: Be My Code <gettofarmila@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/bymyforge/fpx
@@ -7,6 +7,7 @@ fpx/py.typed
7
7
  fpx/_api/_client.py
8
8
  fpx/_parsers/__init__.py
9
9
  fpx/_parsers/_base.py
10
+ fpx/_parsers/_category.py
10
11
  fpx/_parsers/_chats.py
11
12
  fpx/_parsers/_lots.py
12
13
  fpx/_parsers/_orders.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fpx-engine"
7
- version = "0.7.2"
7
+ version = "0.7.4"
8
8
  authors = [
9
9
  { name="Be My Code", email="gettofarmila@gmail.com" },
10
10
  ]
@@ -1,29 +0,0 @@
1
-
2
- from fpx.utils import errors as fpx_err
3
-
4
-
5
- class AddonsManager:
6
- def __init__(self, account):
7
- self._account = account
8
-
9
- async def get_game_id(self, category_id: str):
10
- """
11
- Получает game_id.
12
-
13
- Args:
14
- category_id (str | int): ID подкатегории.
15
-
16
- Returns:
17
- str | int: ID игры.
18
-
19
- Raises:
20
- FpxGetGameIDError: Ошибка запроса ID игры
21
- """
22
- try:
23
- stage = 'запроса данных категории с FunPay'
24
- html = await self._account._client.lot_menu_by_category(category_id)
25
- stage = 'парсинга данных'
26
- data = self._account._parser.parse_lot_menu(html)
27
- except Exception as e:
28
- raise fpx_err.FpxGetGameIDError(f'При выполнении {stage} произошла ошибка: {e}')
29
- return data
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes