Gyron 0.1.3__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.
gyron-0.1.3/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 YasinOliayi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
gyron-0.1.3/PKG-INFO ADDED
@@ -0,0 +1,40 @@
1
+ Metadata-Version: 2.1
2
+ Name: Gyron
3
+ Version: 0.1.3
4
+ Summary: An asynchronous framework for Bale Messenger bots
5
+ Author: Yasin Oliayi
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 YasinOliayi
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+ Project-URL: Repository, https://github.com/YasinOliayi/Gyron
28
+ Keywords: bale,bot,framework,async,messenger,Gyron
29
+ Classifier: Programming Language :: Python :: 3
30
+ Classifier: Programming Language :: Python :: 3.8
31
+ Classifier: Programming Language :: Python :: 3.9
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Operating System :: OS Independent
34
+ Requires-Python: >=3.8
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: httpx>=0.28.1
38
+ Requires-Dist: fastapi>=0.124.4
39
+
40
+ An asynchronous framework for Bale Messenger bots
gyron-0.1.3/README.md ADDED
@@ -0,0 +1 @@
1
+ An asynchronous framework for Bale Messenger bots
@@ -0,0 +1,55 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+
6
+ [project]
7
+ name = "Gyron"
8
+ version = "0.1.3"
9
+
10
+ description = "An asynchronous framework for Bale Messenger bots"
11
+
12
+ readme = "README.md"
13
+
14
+ requires-python = ">=3.8"
15
+
16
+ license = { file = "LICENSE" }
17
+
18
+ authors = [
19
+ { name = "Yasin Oliayi" }
20
+ ]
21
+
22
+ keywords = [
23
+ "bale",
24
+ "bot",
25
+ "framework",
26
+ "async",
27
+ "messenger",
28
+ "Gyron"
29
+ ]
30
+
31
+ classifiers = [
32
+ "Programming Language :: Python :: 3",
33
+ "Programming Language :: Python :: 3.8",
34
+ "Programming Language :: Python :: 3.9",
35
+ "License :: OSI Approved :: MIT License",
36
+ "Operating System :: OS Independent"
37
+ ]
38
+
39
+ dependencies = [
40
+ "httpx>=0.28.1",
41
+ "fastapi>=0.124.4"
42
+ ]
43
+
44
+
45
+ [project.urls]
46
+
47
+ Repository = "https://github.com/YasinOliayi/Gyron"
48
+
49
+
50
+
51
+ [tool.setuptools]
52
+ package-dir = {"" = "src"}
53
+
54
+ [tool.setuptools.packages.find]
55
+ where = ["src"]
gyron-0.1.3/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,301 @@
1
+ import re
2
+ from typing import Pattern, Union, Callable, Optional, Dict
3
+ from .models import Message
4
+ from time import time
5
+ class Filters:
6
+ __slots__ = ()
7
+
8
+ @staticmethod
9
+ def text(pattern = None) -> Callable:
10
+
11
+
12
+ if pattern is None:
13
+
14
+ return lambda message: message.text is not None
15
+
16
+ elif isinstance(pattern, str):
17
+ compiled = re.compile(pattern)
18
+ else:
19
+ compiled = pattern
20
+
21
+
22
+ return lambda message: bool(message.text and compiled.search(message.text))
23
+
24
+ @staticmethod
25
+ def caption(pattern = None):
26
+
27
+ if pattern is None:
28
+
29
+ return lambda message: message.caption is not None
30
+
31
+ elif isinstance(pattern, str):
32
+
33
+ compiled = re.compile(pattern)
34
+
35
+ else:
36
+ compiled = pattern
37
+
38
+ return lambda message: bool(message.caption and compiled.search(message.caption))
39
+
40
+
41
+ @staticmethod
42
+ def private() -> Callable :
43
+
44
+
45
+ return lambda message: message.chat.type == 'private'
46
+
47
+ @staticmethod
48
+ def group():
49
+
50
+
51
+ return lambda message: message.chat.type == 'group'
52
+
53
+ @staticmethod
54
+ def channel():
55
+
56
+ return lambda message: message.chat.type == 'channel'
57
+
58
+
59
+
60
+ @staticmethod
61
+ def new_member():
62
+
63
+ return lambda message: message.new_chat_member.id is not None
64
+
65
+ @staticmethod
66
+ def left_member():
67
+
68
+ return lambda message: message.left_chat_member.id is not None
69
+
70
+
71
+ @staticmethod
72
+ def is_referral():
73
+
74
+ def _filter(message):
75
+
76
+
77
+
78
+ result = message.text.split(maxsplit = 1)
79
+
80
+ if len(result) == 2 and result[0] == "/start" and result[1].isdigit() and len(result[1]) < 15:
81
+ return True
82
+ return False
83
+ return _filter
84
+
85
+ @staticmethod
86
+ def is_joined(chat_id : Union[str, int]) -> Callable:
87
+
88
+
89
+ async def _filter( message: Message):
90
+
91
+ bot = message._bot
92
+
93
+ response = await bot.get_chat_member(chat_id, user_id = message.author.id)
94
+ result = response.get('result', {}).get('status')
95
+ return result in ('member', 'creator', 'administrator')
96
+
97
+
98
+ return _filter
99
+
100
+ @staticmethod
101
+ def not_is_joined(chat_id : Union[str, int]) -> Callable:
102
+
103
+
104
+ async def _filter( message: Message):
105
+
106
+ bot = message._bot
107
+
108
+ response = await bot.get_chat_member(chat_id, user_id = message.author.id)
109
+ result = response.get('result', {}).get('status')
110
+ return result not in ('member', 'creator', 'administrator')
111
+
112
+
113
+ return _filter
114
+
115
+ @staticmethod
116
+ def pre_checkout_query():
117
+
118
+ def _filter(message:Message):
119
+
120
+ if message.pre_checkout_query.id:
121
+
122
+ return True
123
+ return False
124
+ return _filter
125
+
126
+ @staticmethod
127
+ def at_state(manager, state : str = None):
128
+
129
+
130
+ async def _filter(message: Message):
131
+
132
+
133
+ if message.author.id :
134
+
135
+ current_state = await manager.get_state_for(message)
136
+
137
+ if state is None:
138
+ return current_state is not None
139
+
140
+ return current_state == state
141
+
142
+ return _filter
143
+
144
+ @staticmethod
145
+ def callbhack_query(button_data : str = None):
146
+
147
+
148
+
149
+ def _filter(message: Message):
150
+
151
+
152
+ if button_data is None:
153
+
154
+ return message.callback_query.data is not None
155
+
156
+ return message.callback_query.data == button_data
157
+
158
+ return _filter
159
+
160
+ @staticmethod
161
+ def contact(phone_number : str = None):
162
+
163
+
164
+ def _filter(message:Message):
165
+
166
+ if phone_number is None:
167
+
168
+ return message.contact.phone_number is not None
169
+ return message.contact.phone_number == phone_number
170
+
171
+ return _filter
172
+
173
+ @staticmethod
174
+ def location():
175
+
176
+
177
+ def _filter(message:Message):
178
+
179
+ return message.location.latitude is not None
180
+ return _filter
181
+
182
+
183
+ @staticmethod
184
+ def forward():
185
+
186
+
187
+ def _filter(message:Message):
188
+
189
+ return message.forward_date is not None
190
+ return _filter
191
+
192
+ @staticmethod
193
+ def document():
194
+
195
+
196
+ def _filter(message:Message):
197
+
198
+ return message.document.id is not None
199
+ return _filter
200
+
201
+
202
+
203
+ @staticmethod
204
+ def photo():
205
+
206
+ def _filter(message:Message):
207
+
208
+
209
+ return message.photo.id is not None
210
+ return _filter
211
+
212
+ @staticmethod
213
+ def reply():
214
+
215
+
216
+ def _filter(message:Message):
217
+
218
+ return message.reply.message_id is not None
219
+ return _filter
220
+
221
+
222
+ @staticmethod
223
+ def voice():
224
+
225
+
226
+ def _filter(message:Message):
227
+
228
+ return message.voice.id is not None
229
+ return _filter
230
+
231
+
232
+
233
+ class StateManager:
234
+
235
+ __slots__ = (
236
+ 'auto_clear',
237
+ '_states'
238
+ )
239
+
240
+ def __init__(self, auto_clear: bool = True):
241
+
242
+
243
+ self.auto_clear = auto_clear
244
+ self._states = {}
245
+
246
+
247
+
248
+ async def set_state_for(self, update, state, expire : float = 10):
249
+
250
+ expires_at = None
251
+
252
+ if expire is not None:
253
+ expires_at = time() + expire
254
+
255
+ self._states[update.author.id] = {
256
+ 'state': state,
257
+ 'expires_at': expires_at
258
+ }
259
+
260
+ async def clear_state_for(self, update):
261
+
262
+ self._states.pop(update.author.id, None)
263
+
264
+ async def get_state_for(self, update):
265
+
266
+ data = self._states.get(update.author.id)
267
+
268
+ if not data:
269
+ return None
270
+
271
+ expires_at = data['expires_at']
272
+
273
+ if expires_at is not None and time() > expires_at:
274
+
275
+ if self.auto_clear:
276
+ self._states.pop(update.author.id, None)
277
+
278
+ return None
279
+
280
+ return data['state']
281
+
282
+ async def __call__(self, update):
283
+
284
+ data = self._states.get(update.author.id)
285
+
286
+ if not data:
287
+ return False
288
+
289
+ expires_at = data['expires_at']
290
+
291
+ if expires_at is not None and time() > expires_at:
292
+
293
+ if self.auto_clear:
294
+ self._states.pop(update.author.id, None)
295
+
296
+ return False
297
+
298
+ return True
299
+
300
+
301
+
@@ -0,0 +1 @@
1
+