funpaybotengine 0.3.6__tar.gz → 0.4.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.
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/PKG-INFO +5 -5
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/events/base.py +25 -5
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/events/builtin_events.py +27 -27
- funpaybotengine-0.4.0/funpaybotengine/runner/config.py +116 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/runner/runner.py +40 -10
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/messages.py +0 -1
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/pyproject.toml +5 -5
- funpaybotengine-0.4.0/temp.py +0 -0
- funpaybotengine-0.3.6/comments.json +0 -1
- funpaybotengine-0.3.6/funpaybotengine/runner/config.py +0 -49
- funpaybotengine-0.3.6/html.html +0 -209
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/.github/CODEOWNERS +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/.gitignore +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/.pre-commit-config.yaml +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/LICENSE +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/Makefile +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/README.md +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/examples/basic.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/examples/temp.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/examples/with_redis_storage.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/bot.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/default_hooks.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/session/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/session/aiohttp_session.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/session/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/session/http_methods.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/events/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/filters/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/filters/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/filters/message_filters.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/filters/order_filters.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/handlers/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/handlers/handler_manager.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/routers/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/routers/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/routers/dispatcher.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/action_exceptions.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/bot_exceptions.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/message_check_errors.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/runner_exceptions.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/session_exceptions.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/loggers.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/calc_chips.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/calc_lots.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/check_banned.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/delete_review.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_2fa_status.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_chat_history.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_chat_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_main_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_my_chips_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_my_offers_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_offer_fields.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_offer_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_order_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_profile_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_purchases.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_reviews.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_sales.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_settings_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_subcategory_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_telegram_connect_url.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_transactions.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_transactions_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/logout.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/mute_chat.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/raise_offers.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/refund.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/review.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/runner_request.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/save_offer_fields.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/set_offers_hidden.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/update_notice_channel.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/upload_avatar.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/upload_image.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/py.typed +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/runner/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/runner/event_collector.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/storage/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/storage/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/storage/inmemory.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/storage/redis.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/calc.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/categories.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/chat.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/common.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/common_page_elements.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/enums.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/finances.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/offers.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/orders.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/base.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/chat_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/main_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/my_chips_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/my_offers_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/offer_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/order_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/profile_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/settings_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/subcategory_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/transactions_page.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/requests/__init__.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/requests/runner.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/reviews.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/settings.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/updates.py +0 -0
- {funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: funpaybotengine
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.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
|
|
@@ -18,11 +18,11 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.15
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
|
-
Requires-Dist: aiohttp-socks
|
|
22
|
-
Requires-Dist: aiohttp
|
|
23
|
-
Requires-Dist: eventry<0.
|
|
21
|
+
Requires-Dist: aiohttp-socks>=0.11.0
|
|
22
|
+
Requires-Dist: aiohttp<3.14,>=3.13.3
|
|
23
|
+
Requires-Dist: eventry<1.0.0,>=0.3.6
|
|
24
24
|
Requires-Dist: funpayparsers<1.0.0,>=0.5.14
|
|
25
|
-
Requires-Dist: pydantic
|
|
25
|
+
Requires-Dist: pydantic<2.13,>=2.12
|
|
26
26
|
Provides-Extra: dev
|
|
27
27
|
Requires-Dist: mypy>=1.10.1; extra == 'dev'
|
|
28
28
|
Requires-Dist: pre-commit>=4.5.1; extra == 'dev'
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
__all__ = (
|
|
4
|
+
__all__ = (
|
|
5
|
+
'Event',
|
|
6
|
+
'RunnerEvent',
|
|
7
|
+
'BotEngineEvent',
|
|
8
|
+
'ExceptionEvent',
|
|
9
|
+
'BotUnauthenticatedEvent',
|
|
10
|
+
'BotAuthenticatedEvent',
|
|
11
|
+
)
|
|
5
12
|
|
|
6
13
|
from typing import Any, Generic, TypeVar
|
|
7
14
|
from types import MappingProxyType
|
|
@@ -16,7 +23,7 @@ EventObject = TypeVar('EventObject')
|
|
|
16
23
|
|
|
17
24
|
|
|
18
25
|
# Not inheriting from ExtendedEvent, cz __iter__ conflict is pydantic BaseModel.
|
|
19
|
-
class Event(EventryEvent, BindableObject, Generic[EventObject],
|
|
26
|
+
class Event(EventryEvent, BindableObject, Generic[EventObject], event_name='event'):
|
|
20
27
|
model_config = {
|
|
21
28
|
'arbitrary_types_allowed': True,
|
|
22
29
|
}
|
|
@@ -66,7 +73,7 @@ class Event(EventryEvent, BindableObject, Generic[EventObject], name='event'):
|
|
|
66
73
|
return MappingProxyType(self._data)
|
|
67
74
|
|
|
68
75
|
|
|
69
|
-
class RunnerEvent(Event[EventObject],
|
|
76
|
+
class RunnerEvent(Event[EventObject], event_name='runner'):
|
|
70
77
|
tag: str | None = Field(frozen=True)
|
|
71
78
|
|
|
72
79
|
@property
|
|
@@ -76,10 +83,10 @@ class RunnerEvent(Event[EventObject], name='runner'):
|
|
|
76
83
|
return injection
|
|
77
84
|
|
|
78
85
|
|
|
79
|
-
class BotEngineEvent(Event[EventObject],
|
|
86
|
+
class BotEngineEvent(Event[EventObject], event_name='funpaybotengine'): ...
|
|
80
87
|
|
|
81
88
|
|
|
82
|
-
class ExceptionEvent(BotEngineEvent[Exception],
|
|
89
|
+
class ExceptionEvent(BotEngineEvent[Exception], event_name='error'):
|
|
83
90
|
event: Event[Any] = Field(frozen=True)
|
|
84
91
|
|
|
85
92
|
@property
|
|
@@ -87,3 +94,16 @@ class ExceptionEvent(BotEngineEvent[Exception], name='error'):
|
|
|
87
94
|
injection = super().event_context_injection
|
|
88
95
|
injection.update({'on_event': self.event, 'exception': self.object})
|
|
89
96
|
return injection
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class BotUnauthenticatedEvent(BotEngineEvent[float], event_name='unauthorized'):
|
|
100
|
+
delay: float
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def event_context_injection(self) -> dict[str, Any]:
|
|
104
|
+
injection = super().event_context_injection
|
|
105
|
+
injection.update({'delay': self.delay})
|
|
106
|
+
return injection
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class BotAuthenticatedEvent(BotEngineEvent[None], event_name='authorized'): ...
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/events/builtin_events.py
RENAMED
|
@@ -43,7 +43,7 @@ from .base import RunnerEvent
|
|
|
43
43
|
from ...types.pages import OrderPage
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
class ChatChangedEvent(RunnerEvent[PrivateChatPreview],
|
|
46
|
+
class ChatChangedEvent(RunnerEvent[PrivateChatPreview], event_name='chat_changed'):
|
|
47
47
|
previous: PrivateChatPreview | None = None
|
|
48
48
|
|
|
49
49
|
@property
|
|
@@ -57,7 +57,7 @@ class ChatChangedEvent(RunnerEvent[PrivateChatPreview], name='chat_changed'):
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
class NewMessageEvent(RunnerEvent[Message],
|
|
60
|
+
class NewMessageEvent(RunnerEvent[Message], event_name='new_message'):
|
|
61
61
|
@property
|
|
62
62
|
def message(self) -> Message:
|
|
63
63
|
return self.object
|
|
@@ -69,7 +69,7 @@ class NewMessageEvent(RunnerEvent[Message], name='new_message'):
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
|
|
72
|
-
class FromMessageEvent(NewMessageEvent,
|
|
72
|
+
class FromMessageEvent(NewMessageEvent, event_name='__from_message__'):
|
|
73
73
|
related_new_message_event: NewMessageEvent
|
|
74
74
|
|
|
75
75
|
@property
|
|
@@ -79,14 +79,14 @@ class FromMessageEvent(NewMessageEvent, name='__from_message__'):
|
|
|
79
79
|
return val
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-
class OrderEvent(FromMessageEvent,
|
|
82
|
+
class OrderEvent(FromMessageEvent, event_name='__order_event__'):
|
|
83
83
|
_order_preview: OrderPreview | None = PrivateAttr(default=None)
|
|
84
84
|
|
|
85
85
|
async def get_order_preview(self, update: bool = False) -> OrderPreview:
|
|
86
86
|
raise NotImplementedError
|
|
87
87
|
|
|
88
88
|
|
|
89
|
-
class SaleEvent(OrderEvent,
|
|
89
|
+
class SaleEvent(OrderEvent, event_name='__sale_event__'):
|
|
90
90
|
async def get_order_preview(self, update: bool = False) -> OrderPreview:
|
|
91
91
|
if self._order_preview is not None and not update:
|
|
92
92
|
return self._order_preview
|
|
@@ -95,7 +95,7 @@ class SaleEvent(OrderEvent, name='__sale_event__'):
|
|
|
95
95
|
return orders.orders[0]
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
class PurchaseEvent(OrderEvent,
|
|
98
|
+
class PurchaseEvent(OrderEvent, event_name='__purchase_event__'):
|
|
99
99
|
async def get_order_preview(self, update: bool = False) -> OrderPreview:
|
|
100
100
|
if self._order_preview is not None and not update:
|
|
101
101
|
return self._order_preview
|
|
@@ -106,55 +106,55 @@ class PurchaseEvent(OrderEvent, name='__purchase_event__'):
|
|
|
106
106
|
return orders.orders[0]
|
|
107
107
|
|
|
108
108
|
|
|
109
|
-
class NewSaleEvent(SaleEvent,
|
|
109
|
+
class NewSaleEvent(SaleEvent, event_name='new_sale'):
|
|
110
110
|
related_auto_message_events: list[NewMessageEvent] = Field(default_factory=list)
|
|
111
111
|
|
|
112
112
|
|
|
113
|
-
class SaleStatusChangedEvent(SaleEvent,
|
|
113
|
+
class SaleStatusChangedEvent(SaleEvent, event_name='sale_status_changed'):
|
|
114
114
|
previous: OrderPreview | None = None
|
|
115
115
|
|
|
116
116
|
|
|
117
|
-
class SaleClosedEvent(SaleStatusChangedEvent,
|
|
117
|
+
class SaleClosedEvent(SaleStatusChangedEvent, event_name='sale_closed'): ...
|
|
118
118
|
|
|
119
119
|
|
|
120
|
-
class SaleClosedByAdminEvent(SaleClosedEvent,
|
|
120
|
+
class SaleClosedByAdminEvent(SaleClosedEvent, event_name='sale_closed_by_admin'): ...
|
|
121
121
|
|
|
122
122
|
|
|
123
|
-
class SaleRefundedEvent(SaleStatusChangedEvent,
|
|
123
|
+
class SaleRefundedEvent(SaleStatusChangedEvent, event_name='sale_refunded'): ...
|
|
124
124
|
|
|
125
125
|
|
|
126
|
-
class SalePartiallyRefundedEvent(SaleRefundedEvent,
|
|
126
|
+
class SalePartiallyRefundedEvent(SaleRefundedEvent, event_name='sale_partially_refunded'): ...
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
class SaleReopenedEvent(SaleStatusChangedEvent,
|
|
129
|
+
class SaleReopenedEvent(SaleStatusChangedEvent, event_name='sale_reopened'): ...
|
|
130
130
|
|
|
131
131
|
|
|
132
|
-
class NewPurchaseEvent(PurchaseEvent,
|
|
132
|
+
class NewPurchaseEvent(PurchaseEvent, event_name='new_purchase'):
|
|
133
133
|
related_auto_message_events: list[NewMessageEvent] = Field(default_factory=list)
|
|
134
134
|
|
|
135
135
|
|
|
136
|
-
class PurchaseStatusChangedEvent(PurchaseEvent,
|
|
136
|
+
class PurchaseStatusChangedEvent(PurchaseEvent, event_name='purchase_status_changed'):
|
|
137
137
|
previous: OrderPreview | None = None
|
|
138
138
|
|
|
139
139
|
|
|
140
|
-
class PurchaseClosedEvent(PurchaseStatusChangedEvent,
|
|
140
|
+
class PurchaseClosedEvent(PurchaseStatusChangedEvent, event_name='purchase_closed'): ...
|
|
141
141
|
|
|
142
142
|
|
|
143
|
-
class PurchaseClosedByAdminEvent(PurchaseClosedEvent,
|
|
143
|
+
class PurchaseClosedByAdminEvent(PurchaseClosedEvent, event_name='purchase_closed_by_admin'): ...
|
|
144
144
|
|
|
145
145
|
|
|
146
|
-
class PurchaseRefundedEvent(PurchaseStatusChangedEvent,
|
|
146
|
+
class PurchaseRefundedEvent(PurchaseStatusChangedEvent, event_name='purchase_refunded'): ...
|
|
147
147
|
|
|
148
148
|
|
|
149
149
|
class PurchasePartiallyRefundedEvent(
|
|
150
|
-
PurchaseRefundedEvent,
|
|
150
|
+
PurchaseRefundedEvent, event_name='purchase_partially_refunded'
|
|
151
151
|
): ...
|
|
152
152
|
|
|
153
153
|
|
|
154
|
-
class PurchaseReopenedEvent(PurchaseStatusChangedEvent,
|
|
154
|
+
class PurchaseReopenedEvent(PurchaseStatusChangedEvent, event_name='purchase_reopened'): ...
|
|
155
155
|
|
|
156
156
|
|
|
157
|
-
class ReviewEvent(FromMessageEvent,
|
|
157
|
+
class ReviewEvent(FromMessageEvent, event_name='__review_event__'):
|
|
158
158
|
_order_page: OrderPage | None = PrivateAttr(default=None)
|
|
159
159
|
|
|
160
160
|
async def get_order_page(self, update: bool = False) -> OrderPage:
|
|
@@ -169,19 +169,19 @@ class ReviewEvent(FromMessageEvent, name='__review_event__'):
|
|
|
169
169
|
return order_page.review
|
|
170
170
|
|
|
171
171
|
|
|
172
|
-
class NewReviewEvent(ReviewEvent,
|
|
172
|
+
class NewReviewEvent(ReviewEvent, event_name='new_review'): ...
|
|
173
173
|
|
|
174
174
|
|
|
175
|
-
class ReviewChangedEvent(ReviewEvent,
|
|
175
|
+
class ReviewChangedEvent(ReviewEvent, event_name='review_changed'): ...
|
|
176
176
|
|
|
177
177
|
|
|
178
|
-
class ReviewDeletedEvent(ReviewEvent,
|
|
178
|
+
class ReviewDeletedEvent(ReviewEvent, event_name='review_deleted'): ...
|
|
179
179
|
|
|
180
180
|
|
|
181
|
-
class NewReviewResponseEvent(ReviewEvent,
|
|
181
|
+
class NewReviewResponseEvent(ReviewEvent, event_name='new_review_response'): ...
|
|
182
182
|
|
|
183
183
|
|
|
184
|
-
class ReviewResponseChangedEvent(ReviewEvent,
|
|
184
|
+
class ReviewResponseChangedEvent(ReviewEvent, event_name='review_response_changed'): ...
|
|
185
185
|
|
|
186
186
|
|
|
187
|
-
class ReviewResponseDeletedEvent(ReviewEvent,
|
|
187
|
+
class ReviewResponseDeletedEvent(ReviewEvent, event_name='review_response_deleted'): ...
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
__all__ = ('RunnerConfig', 'BackoffConfig', 'Backoff')
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
from typing import Literal
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class BackoffConfig:
|
|
14
|
+
min_delay: float = 6.0
|
|
15
|
+
max_delay: float = 18.0
|
|
16
|
+
factor: float = 1.3
|
|
17
|
+
|
|
18
|
+
def __post_init__(self) -> None:
|
|
19
|
+
if self.max_delay <= self.min_delay:
|
|
20
|
+
raise ValueError('`max_delay` must be greater than `min_delay`.')
|
|
21
|
+
if self.factor <= 1:
|
|
22
|
+
raise ValueError('`factor` must be greater than 1')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class RunnerConfig:
|
|
27
|
+
interval: int | float = 4.0
|
|
28
|
+
"""
|
|
29
|
+
Interval between updates requests.
|
|
30
|
+
Must be more than ``0``.
|
|
31
|
+
|
|
32
|
+
Defaults to ``4.0``.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
discover_sales: bool = True
|
|
36
|
+
"""Whether to discover new sales or not."""
|
|
37
|
+
|
|
38
|
+
discover_purchases: bool = True
|
|
39
|
+
"""Whether to discover new purchases or not."""
|
|
40
|
+
|
|
41
|
+
keep_unread: bool = False
|
|
42
|
+
"""
|
|
43
|
+
Whether to preserve the unread status of chats when getting updates.
|
|
44
|
+
|
|
45
|
+
If ``False`` (default), a batch method is used: up to 10 chats can be requested in a single
|
|
46
|
+
request, but they will be marked as read.
|
|
47
|
+
|
|
48
|
+
If ``True``, only one chat can be fetched per request to keep it unread.
|
|
49
|
+
With high incoming message volume this leads to many requests and may cause
|
|
50
|
+
``429 Too Many Requests`` errors.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
on_unauthenticated_error_policy: Literal['ignore', 'event', 'stop'] = 'ignore'
|
|
54
|
+
"""
|
|
55
|
+
What to do when an `BotUnauthenticatedError` occurred during fetching updates process?
|
|
56
|
+
|
|
57
|
+
- ``ignore``: ignore the error and continue fetching updates.
|
|
58
|
+
- ``event``: yield an error event and continue fetching updates.
|
|
59
|
+
- ``stop``: stop fetching updates, exit a function.
|
|
60
|
+
|
|
61
|
+
Defaults to ``ignore``.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
backoff_config: BackoffConfig = BackoffConfig()
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class Backoff:
|
|
68
|
+
def __init__(self, config: BackoffConfig) -> None:
|
|
69
|
+
self.config = config
|
|
70
|
+
self._next_delay = config.min_delay
|
|
71
|
+
self._current_delay = 0.0
|
|
72
|
+
self._counter = 0
|
|
73
|
+
|
|
74
|
+
def __iter__(self) -> Backoff:
|
|
75
|
+
return self
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def min_delay(self) -> float:
|
|
79
|
+
return self.config.min_delay
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def max_delay(self) -> float:
|
|
83
|
+
return self.config.max_delay
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def factor(self) -> float:
|
|
87
|
+
return self.config.factor
|
|
88
|
+
|
|
89
|
+
@property
|
|
90
|
+
def next_delay(self) -> float:
|
|
91
|
+
return self._next_delay
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def current_delay(self) -> float:
|
|
95
|
+
return self._current_delay
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def counter(self) -> int:
|
|
99
|
+
return self._counter
|
|
100
|
+
|
|
101
|
+
async def asleep(self) -> None:
|
|
102
|
+
await asyncio.sleep(next(self))
|
|
103
|
+
|
|
104
|
+
def _calculate_next(self, value: float) -> float:
|
|
105
|
+
return min(value * self.factor, self.max_delay)
|
|
106
|
+
|
|
107
|
+
def __next__(self) -> float:
|
|
108
|
+
self._current_delay = self._next_delay
|
|
109
|
+
self._next_delay = self._calculate_next(self._next_delay)
|
|
110
|
+
self._counter += 1
|
|
111
|
+
return self._current_delay
|
|
112
|
+
|
|
113
|
+
def reset(self) -> None:
|
|
114
|
+
self._current_delay = 0.0
|
|
115
|
+
self._counter = 0
|
|
116
|
+
self._next_delay = self.min_delay
|
|
@@ -14,13 +14,15 @@ from collections.abc import Iterator, AsyncGenerator
|
|
|
14
14
|
from funpaybotengine.loggers import runner_logger
|
|
15
15
|
from funpaybotengine.exceptions import UnauthorizedError, BotUnauthenticatedError
|
|
16
16
|
from funpaybotengine.storage.base import Storage
|
|
17
|
-
from funpaybotengine.
|
|
18
|
-
|
|
19
|
-
from
|
|
17
|
+
from funpaybotengine.dispatching.events import BotAuthenticatedEvent, BotUnauthenticatedEvent
|
|
18
|
+
|
|
19
|
+
from .config import Backoff, RunnerConfig
|
|
20
|
+
from .event_collector import EventCollector
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
if TYPE_CHECKING:
|
|
23
24
|
from funpaybotengine.client.bot import Bot
|
|
25
|
+
from funpaybotengine.dispatching.events import RunnerEvent, BotEngineEvent
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
@dataclass
|
|
@@ -64,34 +66,62 @@ class Runner:
|
|
|
64
66
|
config,
|
|
65
67
|
session_storage=session_storage,
|
|
66
68
|
)
|
|
69
|
+
backoff = Backoff(config.backoff_config)
|
|
67
70
|
|
|
68
71
|
await collector.init_chats()
|
|
69
72
|
|
|
73
|
+
sleep_time: float | None = None
|
|
70
74
|
while True:
|
|
71
75
|
start = time.time()
|
|
76
|
+
result: list[RunnerEvent[Any] | BotEngineEvent[Any]] = []
|
|
72
77
|
|
|
73
78
|
try:
|
|
74
79
|
result = await collector.get_events()
|
|
80
|
+
if backoff.counter:
|
|
81
|
+
backoff.reset()
|
|
82
|
+
runner_logger.info('Connection established. Continuing collecting events.')
|
|
83
|
+
if config.on_unauthenticated_error_policy == 'event':
|
|
84
|
+
result.insert(0, BotAuthenticatedEvent(object=None))
|
|
85
|
+
|
|
75
86
|
except (BotUnauthenticatedError, UnauthorizedError) as e:
|
|
76
87
|
runner_logger.warning(
|
|
77
88
|
'Bot is unauthenticated (%s). Executing current policy %r.',
|
|
78
89
|
e.__class__.__name__,
|
|
79
90
|
config.on_unauthenticated_error_policy,
|
|
80
91
|
)
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
|
|
93
|
+
if config.on_unauthenticated_error_policy in ['event', 'ignore']:
|
|
94
|
+
next(backoff)
|
|
95
|
+
sleep_time = backoff.current_delay
|
|
96
|
+
runner_logger.warning(
|
|
97
|
+
'Current attempt: %d. Delay: %f.', backoff.counter, backoff.current_delay
|
|
98
|
+
)
|
|
99
|
+
if backoff.counter == 1 and config.on_unauthenticated_error_policy == 'event':
|
|
100
|
+
result = [
|
|
101
|
+
BotUnauthenticatedEvent(object=None, delay=backoff.current_delay)
|
|
102
|
+
]
|
|
103
|
+
|
|
83
104
|
elif config.on_unauthenticated_error_policy == 'stop':
|
|
84
105
|
return
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
except Exception:
|
|
107
|
+
next(backoff)
|
|
108
|
+
runner_logger.error(
|
|
109
|
+
'Failed to collect events. Current attempt: %d. Delay: %f.',
|
|
110
|
+
backoff.counter,
|
|
111
|
+
backoff.current_delay,
|
|
112
|
+
exc_info=True,
|
|
113
|
+
)
|
|
114
|
+
sleep_time = backoff.current_delay
|
|
89
115
|
|
|
90
116
|
events_stack = EventsStack(events=tuple(result))
|
|
91
117
|
for i in events_stack:
|
|
92
118
|
yield i, events_stack
|
|
93
119
|
|
|
94
|
-
|
|
120
|
+
if sleep_time:
|
|
121
|
+
await asyncio.sleep(sleep_time)
|
|
122
|
+
sleep_time = None
|
|
123
|
+
else:
|
|
124
|
+
await _sleep(start, config.interval)
|
|
95
125
|
|
|
96
126
|
|
|
97
127
|
async def _sleep(start_time: int | float, interval: int | float) -> None:
|
|
@@ -216,7 +216,6 @@ class Message(FunPayObject, BaseModel):
|
|
|
216
216
|
|
|
217
217
|
return info.context.get('chat_id') if info.context else None
|
|
218
218
|
|
|
219
|
-
|
|
220
219
|
@field_validator('chat_name', mode='before')
|
|
221
220
|
@classmethod
|
|
222
221
|
def _get_chat_name_from_context(cls, value: Any, info: ValidationInfo) -> Any:
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "funpaybotengine"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.0"
|
|
4
4
|
description = "Framework for creating FunPay bots."
|
|
5
5
|
requires-python = ">=3.10"
|
|
6
6
|
readme = "README.md"
|
|
7
7
|
license = "MIT"
|
|
8
8
|
dependencies = [
|
|
9
|
-
"aiohttp>=3.13.3",
|
|
10
|
-
"aiohttp-socks
|
|
11
|
-
"eventry>=0.3.
|
|
9
|
+
"aiohttp>=3.13.3,<3.14",
|
|
10
|
+
"aiohttp-socks>=0.11.0",
|
|
11
|
+
"eventry>=0.3.6,<1.0.0",
|
|
12
12
|
"funpayparsers>=0.5.14,<1.0.0",
|
|
13
|
-
"pydantic
|
|
13
|
+
"pydantic>=2.12,<2.13",
|
|
14
14
|
]
|
|
15
15
|
authors = [
|
|
16
16
|
{name = "Qvvonk", email="qvvonk@gmail.com"}
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[]
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
__all__ = ('RunnerConfig',)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
from typing import Literal
|
|
8
|
-
from dataclasses import dataclass
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@dataclass
|
|
12
|
-
class RunnerConfig:
|
|
13
|
-
interval: int | float = 4.0
|
|
14
|
-
"""
|
|
15
|
-
Interval between updates requests.
|
|
16
|
-
Must be more than ``0``.
|
|
17
|
-
|
|
18
|
-
Defaults to ``4.0``.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
discover_sales: bool = True
|
|
22
|
-
"""Whether to discover new sales or not."""
|
|
23
|
-
|
|
24
|
-
discover_purchases: bool = True
|
|
25
|
-
"""Whether to discover new purchases or not."""
|
|
26
|
-
|
|
27
|
-
keep_unread: bool = False
|
|
28
|
-
"""
|
|
29
|
-
Whether to preserve the unread status of chats when getting updates.
|
|
30
|
-
|
|
31
|
-
If ``False`` (default), a batch method is used: up to 10 chats can be requested in a single
|
|
32
|
-
request, but they will be marked as read.
|
|
33
|
-
|
|
34
|
-
If ``True``, only one chat can be fetched per request to keep it unread.
|
|
35
|
-
With high incoming message volume this leads to many requests and may cause
|
|
36
|
-
``429 Too Many Requests`` errors.
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
on_unauthenticated_error_policy: Literal['ignore', 'event', 'stop', 'stop+event'] = 'ignore'
|
|
40
|
-
"""
|
|
41
|
-
What to do when an `BotUnauthenticatedError` occurred during fetching updates process?
|
|
42
|
-
|
|
43
|
-
- ``ignore``: ignore the error and continue fetching updates.
|
|
44
|
-
- ``event``: yield an error event and continue fetching updates.
|
|
45
|
-
- ``stop``: stop fetching updates, exit a function.
|
|
46
|
-
- ``stop+event``: yield an error event and stop fetching updates, exit a function.
|
|
47
|
-
|
|
48
|
-
Defaults to ``ignore``.
|
|
49
|
-
"""
|
funpaybotengine-0.3.6/html.html
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="ru">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<title>Редактирование предложения / FunPay</title><link href="https://funpay.com/700/css/main.css" rel="stylesheet" media="all">
|
|
6
|
-
<script src="https://funpay.com/517/js/bundle.js"></script>
|
|
7
|
-
<script src="https://funpay.com/517/js/lots.min.js"></script>
|
|
8
|
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
9
|
-
<link rel="alternate" hreflang="ru" href="https://funpay.com/lots/offerEdit?offer=6069527"><link rel="alternate" hreflang="uk" href="https://funpay.com/lots/offerEdit?offer=6069527"><link rel="alternate" hreflang="en" href="https://funpay.com/en/lots/offerEdit?offer=6069527"><link rel="alternate" hreflang="x-default" href="https://funpay.com/en/lots/offerEdit?offer=6069527"><script type="application/ld+json">[{"@context":"http:\/\/schema.org\/","@type":"WebSite","name":"FunPay","url":"https:\/\/funpay.com\/"}]</script><link rel="preload" href="/700/fonts/Graphik-Bold-Web.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="/700/fonts/Graphik-Semibold-Web.woff2" as="font" type="font/woff2" crossorigin><link rel="manifest" href="/manifest.json">
|
|
10
|
-
</head>
|
|
11
|
-
<body class="with-corner-cd" data-app-data="{"locale":"ru","csrf-token":"8g2f8avvrn4cd02m","userId":4067817,"webpush":{"app":"C356D-32008","enabled":true,"hwid-required":true}}">
|
|
12
|
-
<!--suppress ALL -->
|
|
13
|
-
|
|
14
|
-
<script>
|
|
15
|
-
window.dataLayer = window.dataLayer || [];
|
|
16
|
-
function gtag(){dataLayer.push(arguments);}
|
|
17
|
-
|
|
18
|
-
gtag('consent', 'default', {"analytics_storage":"granted","ad_storage":"granted","ad_user_data":"granted","ad_personalization":"denied"});
|
|
19
|
-
gtag('config', 'AW-11153904331');
|
|
20
|
-
|
|
21
|
-
window.app.analytics.addEvents([{"event":"FunpayPageview","userId":"4067817","clientId":""}]);
|
|
22
|
-
</script>
|
|
23
|
-
|
|
24
|
-
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
|
25
|
-
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
|
26
|
-
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
|
27
|
-
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
|
28
|
-
})(window,document,'script','dataLayer','GTM-TWG83B');</script>
|
|
29
|
-
|
|
30
|
-
<script type="text/javascript" >
|
|
31
|
-
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
|
32
|
-
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
|
|
33
|
-
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
|
|
34
|
-
|
|
35
|
-
function initYM() {
|
|
36
|
-
ym(36956765, "init", {
|
|
37
|
-
clickmap: false,
|
|
38
|
-
trackLinks: true,
|
|
39
|
-
accurateTrackBounce: true,
|
|
40
|
-
webvisor: false,
|
|
41
|
-
ut: "noindex",
|
|
42
|
-
ecommerce: "dataLayer"
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
initYM();
|
|
46
|
-
</script>
|
|
47
|
-
<noscript><div><img src="https://mc.yandex.ru/watch/36956765?ut=noindex" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
|
48
|
-
<div class="wrapper">
|
|
49
|
-
<div class="wrapper-content">
|
|
50
|
-
<div class="corner-cd-container"><div class="corner-cd"><img src="/img/circles/funpay_poke.jpg" alt=""></div></div>
|
|
51
|
-
<header id="header">
|
|
52
|
-
<div class="container">
|
|
53
|
-
<div id="global-origin"></div>
|
|
54
|
-
<nav class="navbar navbar-default">
|
|
55
|
-
<div class="hide-navbar"></div>
|
|
56
|
-
<div class="container-fluid">
|
|
57
|
-
<div class="navbar-header">
|
|
58
|
-
<button type="button" class="collapsed navbar-toggle navbar-toggle-logged" data-toggle="collapse" data-target="#navbar" aria-expanded="false">
|
|
59
|
-
<span class="user-link-photo"><img src="https://sfunpay.com/s/avatar/fh/97/fh97o5taxakvmvm0r3e8.jpg" alt=""></span>
|
|
60
|
-
<span class="caret"></span>
|
|
61
|
-
</button>
|
|
62
|
-
<a href="https://funpay.com/chat/" class="navbar-xs-icon icon-chat">
|
|
63
|
-
<svg viewBox="0 0 26 26"><circle cx="13" cy="13" r="12"/><polygon points="26 26, 12 20, 20 12"/></svg>
|
|
64
|
-
<span></span>
|
|
65
|
-
</a>
|
|
66
|
-
<a href="https://funpay.com/" class="navbar-brand">
|
|
67
|
-
<img src="/img/layout/logo-funpay-white.svg" alt="FunPay" class="logo-white"/>
|
|
68
|
-
<img src="/img/layout/logo-funpay.svg" alt="FunPay" class="logo-color"/>
|
|
69
|
-
</a>
|
|
70
|
-
<form action="https://funpay.com/games/promoFilter" method="post" class="navbar-form navbar-left dropdown promo-games-filter">
|
|
71
|
-
<div class="form-group">
|
|
72
|
-
<input type="text" name="query" class="form-control dropdown-toggle" data-toggle="dropdown" role="searchbox" placeholder="Поиск по 773 играм" autocomplete="off"/>
|
|
73
|
-
<div class="dropdown-menu dropdown-autocomplete hidden"></div>
|
|
74
|
-
</div>
|
|
75
|
-
<button type="submit" class="btn btn-link"><i class="fa fa-search"></i></button>
|
|
76
|
-
</form>
|
|
77
|
-
</div>
|
|
78
|
-
<div class="nav-container">
|
|
79
|
-
<div class="collapse navbar-collapse no-transition" id="navbar">
|
|
80
|
-
<ul class="nav navbar-nav">
|
|
81
|
-
<li class="visible-xs visible-sm">
|
|
82
|
-
<a href="https://funpay.com/users/4067817/" class="user-link-dropdown">
|
|
83
|
-
<div class="user-link-name">EjikMLBB</div>
|
|
84
|
-
<div class="user-link-desc">Профиль</div>
|
|
85
|
-
</a>
|
|
86
|
-
</li> <li class="dropdown"><a href="https://funpay.com/" class="menu-item-info dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Помощь <span class="caret"></span></a><ul class="dropdown-menu"><li><a href="https://funpay.com/trade/info" class="menu-item-trade_info">Правила</a></li>
|
|
87
|
-
<li><a href="https://support.funpay.com/" class="menu-item-support" target="_blank">Центр помощи</a></li>
|
|
88
|
-
<li><a href="https://support.funpay.com/tickets/new" class="menu-item-request" target="_blank">Отправить запрос</a></li>
|
|
89
|
-
<li><a href="https://support.funpay.com/tickets" class="menu-item-requests" target="_blank">Мои запросы</a></li></ul></li> <li><a href="https://funpay.com/promo/lootery" class="menu-item-lootery">Лутерея</a></li> </ul>
|
|
90
|
-
<ul class="nav navbar-nav navbar-right logged">
|
|
91
|
-
<li><a href="https://funpay.com/orders/" class="menu-item-orders">Покупки <span class="badge badge-orders">1</span></a></li> <li><a href="https://funpay.com/orders/trade" class="menu-item-trade">Продажи <span class="badge badge-trade">2</span></a></li> <li><a href="https://funpay.com/chat/" class="menu-item-chat">Сообщения <span class="badge badge-chat hidden">0</span></a></li> <li><a href="https://funpay.com/account/balance" class="menu-item-balance">Финансы <span class="badge badge-balance">62 ₽</span></a></li> <li class="dropdown hidden-sm hidden-xs">
|
|
92
|
-
<a href="javascript:void(0)" class="dropdown-toggle user-link" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
|
|
93
|
-
<div class="user-link-photo"><img src="https://sfunpay.com/s/avatar/fh/97/fh97o5taxakvmvm0r3e8.jpg" alt=""/></div>
|
|
94
|
-
<span class="caret"></span>
|
|
95
|
-
</a>
|
|
96
|
-
<ul class="dropdown-menu">
|
|
97
|
-
<li>
|
|
98
|
-
<a href="https://funpay.com/users/4067817/" class="user-link-dropdown">
|
|
99
|
-
<div class="user-link-name">EjikMLBB</div>
|
|
100
|
-
<div class="user-link-desc">Профиль</div>
|
|
101
|
-
</a>
|
|
102
|
-
</li> <li><a href="https://funpay.com/account/settings" class="menu-item-settings">Настройки</a></li><li class="dropdown">
|
|
103
|
-
<a href="javascript:void(0)" class="dropdown-toggle menu-item-langs" data-toggle="dropdown">
|
|
104
|
-
По-русски <i class="menu-icon menu-icon-lang-ru"></i> <span class="caret"></span>
|
|
105
|
-
</a>
|
|
106
|
-
<ul class="dropdown-menu">
|
|
107
|
-
<li>
|
|
108
|
-
<a href="https://funpay.com/lots/offerEdit?offer=6069527&setlocale=en" class="menu-item-lang">
|
|
109
|
-
English <i class="menu-icon menu-icon-lang-en"></i>
|
|
110
|
-
</a>
|
|
111
|
-
</li>
|
|
112
|
-
</ul>
|
|
113
|
-
</li><li class="dropdown">
|
|
114
|
-
<a href="javascript:void(0)" class="dropdown-toggle menu-item-currencies" data-toggle="dropdown">
|
|
115
|
-
Рубли <span class="caret"></span>
|
|
116
|
-
</a>
|
|
117
|
-
<ul class="dropdown-menu">
|
|
118
|
-
<li>
|
|
119
|
-
<a href="javascript:void(0)" data-cy="usd" class="user-cy-switcher menu-item-currency">
|
|
120
|
-
Доллары </a>
|
|
121
|
-
</li>
|
|
122
|
-
<li>
|
|
123
|
-
<a href="javascript:void(0)" data-cy="eur" class="user-cy-switcher menu-item-currency">
|
|
124
|
-
Евро </a>
|
|
125
|
-
</li>
|
|
126
|
-
</ul>
|
|
127
|
-
</li><li><a href="https://funpay.com/account/logout?token=a1fe429858772f68" class="menu-item-logout">Выйти</a></li> </ul>
|
|
128
|
-
</li>
|
|
129
|
-
<li class="visible-xs visible-sm"><a href="https://funpay.com/account/settings" class="menu-item-settings">Настройки</a></li><li class="visible-xs visible-sm dropdown">
|
|
130
|
-
<a href="javascript:void(0)" class="dropdown-toggle menu-item-langs" data-toggle="dropdown">
|
|
131
|
-
По-русски <i class="menu-icon menu-icon-lang-ru"></i> <span class="caret"></span>
|
|
132
|
-
</a>
|
|
133
|
-
<ul class="dropdown-menu">
|
|
134
|
-
<li>
|
|
135
|
-
<a href="https://funpay.com/lots/offerEdit?offer=6069527&setlocale=en" class="menu-item-lang">
|
|
136
|
-
English <i class="menu-icon menu-icon-lang-en"></i>
|
|
137
|
-
</a>
|
|
138
|
-
</li>
|
|
139
|
-
</ul>
|
|
140
|
-
</li><li class="visible-xs visible-sm dropdown">
|
|
141
|
-
<a href="javascript:void(0)" class="dropdown-toggle menu-item-currencies" data-toggle="dropdown">
|
|
142
|
-
Рубли <span class="caret"></span>
|
|
143
|
-
</a>
|
|
144
|
-
<ul class="dropdown-menu">
|
|
145
|
-
<li>
|
|
146
|
-
<a href="javascript:void(0)" data-cy="usd" class="user-cy-switcher menu-item-currency">
|
|
147
|
-
Доллары </a>
|
|
148
|
-
</li>
|
|
149
|
-
<li>
|
|
150
|
-
<a href="javascript:void(0)" data-cy="eur" class="user-cy-switcher menu-item-currency">
|
|
151
|
-
Евро </a>
|
|
152
|
-
</li>
|
|
153
|
-
</ul>
|
|
154
|
-
</li><li class="visible-xs visible-sm"><a href="https://funpay.com/account/logout?token=a1fe429858772f68" class="menu-item-logout">Выйти</a></li> </ul>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
</nav>
|
|
159
|
-
<div id="chat-notification" class="hidden" data-message="0">
|
|
160
|
-
<audio class="loud"><source src="/audio/chat_loud.mp3" type="audio/mpeg"></audio>
|
|
161
|
-
<audio class="quiet"><source src="/audio/chat_quiet.mp3" type="audio/mpeg"></audio>
|
|
162
|
-
</div>
|
|
163
|
-
<div id="live-counters" class="hidden" data-orders="5iz07iil" data-chat="pp9ddrdb"></div>
|
|
164
|
-
</div>
|
|
165
|
-
</header>
|
|
166
|
-
|
|
167
|
-
<section id="content-body">
|
|
168
|
-
<div class="search-fade"></div>
|
|
169
|
-
<div id="content" class="content-lots content-lots-offeredit"><div class="container">
|
|
170
|
-
<div class="row">
|
|
171
|
-
<div class="col-md-2 col-sm-3">
|
|
172
|
-
<div class="back-link">
|
|
173
|
-
<a href="https://funpay.com/" class="js-back-link"><i class="fa fa-chevron-left"></i><span class="inside">Назад</span></a>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
<div class="col-md-10 col-sm-9">
|
|
177
|
-
<div class="page-content">
|
|
178
|
-
<h1 class="page-header page-header-no-hr">Редактирование предложения</h1>
|
|
179
|
-
<p class="lead">Предложение не найдено.</p>
|
|
180
|
-
</div>
|
|
181
|
-
</div>
|
|
182
|
-
</div>
|
|
183
|
-
</div></div> </section>
|
|
184
|
-
</div>
|
|
185
|
-
|
|
186
|
-
<div class="wrapper-footer">
|
|
187
|
-
<div class="container">
|
|
188
|
-
<footer id="footer">
|
|
189
|
-
<div class="footer-block footer-block-strings">
|
|
190
|
-
<span>© 2015–2026 FunPay</span>
|
|
191
|
-
<a href="https://funpay.com/pages/privacyPolicy">Политика конфиденциальности</a> <a href="https://funpay.com/pages/cookiePolicy">Политика cookie</a> <a href="https://funpay.com/contacts.html" target="_blank" rel="nofollow">Контакты</a> </div>
|
|
192
|
-
<div class="footer-block footer-block-social">
|
|
193
|
-
<a class="btn btn-gray btn-round" href="https://t.me/+zC7jZ0ytESc1ZjUy" target="_blank" rel="nofollow">
|
|
194
|
-
<svg width="25" height="20"><use xlink:href="/3/img/layout/sprites.svg#social-logo-telegram"></use></svg> </a>
|
|
195
|
-
<a class="btn btn-gray btn-round" href="https://www.youtube.com/c/funpayofficial" target="_blank" rel="nofollow"><i class="fab fa-youtube"></i></a>
|
|
196
|
-
<a class="btn btn-gray btn-round" href="https://vk.com/funpay" target="_blank" rel="nofollow"><i class="fab fa-vk"></i></a>
|
|
197
|
-
<a class="btn btn-gray btn-round" href="https://www.facebook.com/funpay.official" target="_blank" rel="nofollow"><i class="fab fa-facebook-square"></i></a>
|
|
198
|
-
</div>
|
|
199
|
-
<div class="footer-block footer-block-als">
|
|
200
|
-
<img src="/img/layout/als-logo.svg" alt="">
|
|
201
|
-
<div>Задизайнено<br>в <a href="https://www.artlebedev.ru/funpay/" target="_blank">Студии Артемия<br>Лебедева</a></div>
|
|
202
|
-
</div>
|
|
203
|
-
</footer>
|
|
204
|
-
</div>
|
|
205
|
-
</div>
|
|
206
|
-
</div>
|
|
207
|
-
|
|
208
|
-
</body>
|
|
209
|
-
</html>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/session/aiohttp_session.py
RENAMED
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/client/session/http_methods.py
RENAMED
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/events/__init__.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/filters/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/filters/order_filters.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/handlers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/routers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/dispatching/routers/dispatcher.py
RENAMED
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/action_exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/bot_exceptions.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/message_check_errors.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/runner_exceptions.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/exceptions/session_exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_my_chips_page.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_my_offers_page.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_settings_page.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_subcategory_page.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_telegram_connect_url.py
RENAMED
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/get_transactions_page.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/save_offer_fields.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/set_offers_hidden.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/methods/update_notice_channel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/common_page_elements.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/my_chips_page.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/my_offers_page.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/settings_page.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/subcategory_page.py
RENAMED
|
File without changes
|
{funpaybotengine-0.3.6 → funpaybotengine-0.4.0}/funpaybotengine/types/pages/transactions_page.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|