pyjetra 1.0.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.
@@ -0,0 +1,12 @@
1
+ # Authors & Contributors
2
+ ### [EN] Project Developer
3
+ ### [FA] توسعه‌دهنده پروژه
4
+
5
+ * **Name / نام**: Ali VEX
6
+ * **Email / ایمیل**: lyrdaadhrpyk802@gmail.com
7
+ * **Jetra Profile / پروفایل جترا**: https://jetra.ir/UserBoT
8
+ * **GitHub / گیت‌هاب**: https://github.com/lyrdaadhrpyk802-ux/pyjetra
9
+
10
+ ---
11
+ *This library was built with passion for the Jetra community.*
12
+ *این کتابخانه با عشق برای جامعه جترا ساخته شده است.*
pyjetra-1.0.0/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Your Name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction.
pyjetra-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,70 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyjetra
3
+ Version: 1.0.0
4
+ Summary: A modern, bilingual (Sync/Async) Python wrapper for the Jetra Bot API.
5
+ Author-email: Ali VEX <lyrdaadhrpyk802@gmail.com>
6
+ Project-URL: Homepage, https://github.com/lyrdaadhrpyk802-ux/pyjetra
7
+ Project-URL: Documentation, https://github.com/lyrdaadhrpyk802-ux/pyjetra/blob/main/README.md
8
+ Project-URL: Jetra, https://jetra.ir/UserBoT
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.7
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ License-File: AUTHORS.md
16
+ Requires-Dist: requests>=2.25.0
17
+ Requires-Dist: aiohttp>=3.8.0
18
+ Dynamic: license-file
19
+
20
+ # PyJetra Library
21
+ ### [EN] A Modern Python Wrapper for Jetra Bot API
22
+ ### [FA] یک کتابخانه مدرن پایتون برای API ربات جترا
23
+
24
+ ---
25
+
26
+ ## [EN] Features / [FA] امکانات
27
+ * **Sync & Async Support** / پشتیبانی از Sync و Async
28
+ * **State Management** / مدیریت وضعیت
29
+ * **Advanced Filters** / فیلترهای پیشرفته
30
+ * **Full Media Support** / پشتیبانی کامل از رسانه‌ها
31
+
32
+ ## [EN] Installation / [FA] نصب
33
+ ```bash
34
+ pip install requests aiohttp
35
+ ```
36
+
37
+ ## [EN] Quick Start (Sync) / [FA] شروع سریع (همزمان)
38
+ ```python
39
+ from pyjetra import JetraBot, CommandFilter
40
+
41
+ bot = JetraBot('YOUR_TOKEN')
42
+
43
+ @bot.on_message(filters=[CommandFilter('start')])
44
+ def start(msg):
45
+ msg.reply('Hello from PyJetra!')
46
+
47
+ bot.poll()
48
+ ```
49
+
50
+ ## [EN] Quick Start (Async) / [FA] شروع سریع (غیرهمزمان)
51
+ ```python
52
+ from pyjetra import AsyncJetraBot, CommandFilter
53
+ import asyncio
54
+
55
+ bot = AsyncJetraBot('YOUR_TOKEN')
56
+
57
+ @bot.on_message(filters=[CommandFilter('start')])
58
+ async def start(msg):
59
+ await msg.reply('Hello Fast!')
60
+
61
+ asyncio.run(bot.start_polling())
62
+ ```
63
+
64
+ ## [EN] Testing / [FA] تست کردن
65
+ Navigate to the `tests/` folder and run the files.
66
+ Read the comments inside each test file.
67
+
68
+ ## [EN] Developer / [FA] توسعه‌دهنده
69
+ Created with ❤️ by Ali VEX
70
+ GitHub: https://github.com/lyrdaadhrpyk802-ux
@@ -0,0 +1,51 @@
1
+ # PyJetra Library
2
+ ### [EN] A Modern Python Wrapper for Jetra Bot API
3
+ ### [FA] یک کتابخانه مدرن پایتون برای API ربات جترا
4
+
5
+ ---
6
+
7
+ ## [EN] Features / [FA] امکانات
8
+ * **Sync & Async Support** / پشتیبانی از Sync و Async
9
+ * **State Management** / مدیریت وضعیت
10
+ * **Advanced Filters** / فیلترهای پیشرفته
11
+ * **Full Media Support** / پشتیبانی کامل از رسانه‌ها
12
+
13
+ ## [EN] Installation / [FA] نصب
14
+ ```bash
15
+ pip install requests aiohttp
16
+ ```
17
+
18
+ ## [EN] Quick Start (Sync) / [FA] شروع سریع (همزمان)
19
+ ```python
20
+ from pyjetra import JetraBot, CommandFilter
21
+
22
+ bot = JetraBot('YOUR_TOKEN')
23
+
24
+ @bot.on_message(filters=[CommandFilter('start')])
25
+ def start(msg):
26
+ msg.reply('Hello from PyJetra!')
27
+
28
+ bot.poll()
29
+ ```
30
+
31
+ ## [EN] Quick Start (Async) / [FA] شروع سریع (غیرهمزمان)
32
+ ```python
33
+ from pyjetra import AsyncJetraBot, CommandFilter
34
+ import asyncio
35
+
36
+ bot = AsyncJetraBot('YOUR_TOKEN')
37
+
38
+ @bot.on_message(filters=[CommandFilter('start')])
39
+ async def start(msg):
40
+ await msg.reply('Hello Fast!')
41
+
42
+ asyncio.run(bot.start_polling())
43
+ ```
44
+
45
+ ## [EN] Testing / [FA] تست کردن
46
+ Navigate to the `tests/` folder and run the files.
47
+ Read the comments inside each test file.
48
+
49
+ ## [EN] Developer / [FA] توسعه‌دهنده
50
+ Created with ❤️ by Ali VEX
51
+ GitHub: https://github.com/lyrdaadhrpyk802-ux
@@ -0,0 +1,12 @@
1
+ from .client import JetraBot
2
+ from .async_client import AsyncJetraBot
3
+ from .exceptions import JetraError
4
+ from .types import User, Chat, Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
5
+ from .filters import CommandFilter, TextFilter
6
+ from .dev_info import get_info, DEVELOPER_NAME, VERSION
7
+
8
+ __all__ = [
9
+ "JetraBot", "AsyncJetraBot", "JetraError", "User", "Chat", "Message",
10
+ "CallbackQuery", "InlineKeyboardMarkup", "InlineKeyboardButton",
11
+ "CommandFilter", "TextFilter", "get_info", "DEVELOPER_NAME", "VERSION"
12
+ ]
@@ -0,0 +1,61 @@
1
+ import aiohttp
2
+ import asyncio
3
+ from typing import List, Optional, Callable, Any
4
+ from .exceptions import JetraError
5
+ from .types import User, Message, CallbackQuery, InlineKeyboardMarkup
6
+
7
+ class AsyncJetraBot:
8
+ def __init__(self, token: str):
9
+ self.token = token
10
+ self.base_url = f"https://jetra.ir/bot{token}/"
11
+ self._message_handlers = []
12
+ self._callback_handlers = []
13
+
14
+ async def _request(self, method: str, **params) -> Any:
15
+ async with aiohttp.ClientSession() as session:
16
+ async with session.post(self.base_url + method, json=params) as resp:
17
+ data = await resp.json()
18
+ if not data.get("ok"): raise JetraError(f"API Error: {data.get('description')}")
19
+ return data.get("result")
20
+
21
+ async def send_message(self, chat_id: int, text: str, reply_to_message_id: Optional[int] = None, reply_markup: Optional[InlineKeyboardMarkup] = None) -> dict:
22
+ params = {"chat_id": chat_id, "text": text}
23
+ if reply_to_message_id: params["reply_to_message_id"] = reply_to_message_id
24
+ if reply_markup: params["reply_markup"] = reply_markup.to_dict()
25
+ return await self._request("sendMessage", **params)
26
+
27
+ async def answer_callback_query(self, callback_query_id: str, text: Optional[str] = None, show_alert: bool = False) -> dict:
28
+ return await self._request("answerCallbackQuery", callback_query_id=callback_query_id, text=text, show_alert=show_alert)
29
+
30
+ async def get_updates(self, offset: int = 0) -> List[dict]:
31
+ return await self._request("getUpdates", offset=offset, timeout=30)
32
+
33
+ def on_message(self, func: Callable = None, filters: list = None):
34
+ def decorator(f):
35
+ self._message_handlers.append({"func": f, "filters": filters or []})
36
+ return f
37
+ return decorator(func) if func else decorator
38
+
39
+ def on_callback_query(self, func: Callable):
40
+ self._callback_handlers.append(func)
41
+ return func
42
+
43
+ async def start_polling(self):
44
+ print("Async Bot polling...")
45
+ offset = 0
46
+ while True:
47
+ try:
48
+ updates = await self.get_updates(offset)
49
+ for update in updates:
50
+ offset = update["update_id"] + 1
51
+ if "message" in update:
52
+ msg = Message(update["message"], self)
53
+ for handler in self._message_handlers:
54
+ if all(f(msg) for f in handler["filters"]):
55
+ await handler["func"](msg)
56
+ elif "callback_query" in update:
57
+ cb = CallbackQuery(update["callback_query"], self)
58
+ for handler in self._callback_handlers:
59
+ await handler(cb)
60
+ except Exception:
61
+ await asyncio.sleep(2)
@@ -0,0 +1,72 @@
1
+ import requests
2
+ import time
3
+ from typing import List, Optional, Callable, Any
4
+ from .exceptions import JetraError
5
+ from .types import User, Message, CallbackQuery, InlineKeyboardMarkup
6
+
7
+ class JetraBot:
8
+ def __init__(self, token: str):
9
+ self.token = token
10
+ self.base_url = f"https://jetra.ir/bot{token}/"
11
+ self.session = requests.Session()
12
+ self._message_handlers = []
13
+ self._callback_handlers = []
14
+ self._states = {}
15
+
16
+ def set_state(self, user_id, state): self._states[user_id] = state
17
+ def get_state(self, user_id): return self._states.get(user_id)
18
+ def clear_state(self, user_id):
19
+ if user_id in self._states: del self._states[user_id]
20
+
21
+ def _request(self, method: str, **params) -> Any:
22
+ url = self.base_url + method
23
+ try:
24
+ response = self.session.post(url, json=params, timeout=30)
25
+ data = response.json()
26
+ if not data.get("ok"): raise JetraError(f"API Error: {data.get('description')}")
27
+ return data.get("result")
28
+ except requests.exceptions.ReadTimeout: return []
29
+ except Exception as e: raise JetraError(f"Network Error: {e}")
30
+
31
+ def send_message(self, chat_id: int, text: str, reply_to_message_id: Optional[int] = None, reply_markup: Optional[InlineKeyboardMarkup] = None) -> dict:
32
+ params = {"chat_id": chat_id, "text": text}
33
+ if reply_to_message_id: params["reply_to_message_id"] = reply_to_message_id
34
+ if reply_markup: params["reply_markup"] = reply_markup.to_dict()
35
+ return self._request("sendMessage", **params)
36
+
37
+ def answer_callback_query(self, callback_query_id: str, text: Optional[str] = None, show_alert: bool = False) -> dict:
38
+ params = {"callback_query_id": callback_query_id, "text": text, "show_alert": show_alert}
39
+ return self._request("answerCallbackQuery", **params)
40
+
41
+ def get_updates(self, offset: int = 0) -> List[dict]:
42
+ return self._request("getUpdates", offset=offset, timeout=30)
43
+
44
+ def on_message(self, func: Callable = None, filters: list = None):
45
+ def decorator(f):
46
+ self._message_handlers.append({"func": f, "filters": filters or []})
47
+ return f
48
+ return decorator(func) if func else decorator
49
+
50
+ def on_callback_query(self, func: Callable):
51
+ self._callback_handlers.append(func)
52
+ return func
53
+
54
+ def poll(self):
55
+ print("Bot polling...")
56
+ offset = 0
57
+ while True:
58
+ try:
59
+ updates = self.get_updates(offset)
60
+ for update in updates:
61
+ offset = update["update_id"] + 1
62
+ if "message" in update:
63
+ msg = Message(update["message"], self)
64
+ for handler in self._message_handlers:
65
+ if all(f(msg) for f in handler["filters"]):
66
+ handler["func"](msg)
67
+ elif "callback_query" in update:
68
+ cb = CallbackQuery(update["callback_query"], self)
69
+ for handler in self._callback_handlers:
70
+ handler(cb)
71
+ except Exception:
72
+ time.sleep(2)
@@ -0,0 +1,11 @@
1
+ # [EN] Developer Information
2
+ # [FA] مشخصات توسعه‌دهنده
3
+
4
+ DEVELOPER_NAME = "Ali VEX"
5
+ DEVELOPER_EMAIL = "lyrdaadhrpyk802@gmail.com"
6
+ JETRA_LINK = "https://jetra.ir/UserBoT"
7
+ GITHUB_URL = "https://github.com/lyrdaadhrpyk802-ux/pyjetra"
8
+ VERSION = "1.0.0"
9
+
10
+ def get_info():
11
+ return f"PyJetra v{VERSION} | Developed by {DEVELOPER_NAME} | {GITHUB_URL}"
@@ -0,0 +1,2 @@
1
+ class JetraError(Exception):
2
+ pass
@@ -0,0 +1,16 @@
1
+ class Filter:
2
+ def __call__(self, message): return True
3
+
4
+ class CommandFilter(Filter):
5
+ def __init__(self, commands):
6
+ self.commands = commands if isinstance(commands, list) else [commands]
7
+ def __call__(self, message):
8
+ if not message.text: return False
9
+ cmd = message.text.split()[0].lower()
10
+ return cmd in [f"/{c}" for c in self.commands]
11
+
12
+ class TextFilter(Filter):
13
+ def __init__(self, text):
14
+ self.text = text
15
+ def __call__(self, message):
16
+ return bool(message.text and message.text.lower() == self.text.lower())
@@ -0,0 +1,7 @@
1
+ from .user import User
2
+ from .chat import Chat
3
+ from .message import Message
4
+ from .callback import CallbackQuery
5
+ from .markup import InlineKeyboardMarkup, InlineKeyboardButton
6
+
7
+ __all__ = ["User", "Chat", "Message", "CallbackQuery", "InlineKeyboardMarkup", "InlineKeyboardButton"]
@@ -0,0 +1,21 @@
1
+ from typing import Optional
2
+ from .user import User
3
+ from .message import Message
4
+
5
+ class CallbackQuery:
6
+ def __init__(self, data: dict, bot_instance):
7
+ self.id = data.get("id")
8
+ self.from_user = None
9
+ if "from" in data:
10
+ u = data["from"]
11
+ self.from_user = User(
12
+ id=u.get("id", 0), is_bot=u.get("is_bot", False),
13
+ first_name=u.get("first_name", ""), last_name=u.get("last_name"),
14
+ username=u.get("username")
15
+ )
16
+ self.data = data.get("data")
17
+ self.message = Message(data["message"], bot_instance) if "message" in data else None
18
+ self._bot = bot_instance
19
+
20
+ def answer(self, text: Optional[str] = None, show_alert: bool = False):
21
+ return self._bot.answer_callback_query(self.id, text, show_alert)
@@ -0,0 +1,11 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+ @dataclass
5
+ class Chat:
6
+ id: int
7
+ type: str
8
+ title: Optional[str] = None
9
+ first_name: Optional[str] = None
10
+ last_name: Optional[str] = None
11
+ username: Optional[str] = None
@@ -0,0 +1,18 @@
1
+ from typing import List, Optional
2
+
3
+ class InlineKeyboardButton:
4
+ def __init__(self, text: str, callback_data: Optional[str] = None, url: Optional[str] = None):
5
+ self.text = text
6
+ self.callback_data = callback_data
7
+ self.url = url
8
+ def to_dict(self) -> dict:
9
+ data = {"text": self.text}
10
+ if self.callback_data: data["callback_data"] = self.callback_data
11
+ if self.url: data["url"] = self.url
12
+ return data
13
+
14
+ class InlineKeyboardMarkup:
15
+ def __init__(self, inline_keyboard: List[List[InlineKeyboardButton]]):
16
+ self.inline_keyboard = inline_keyboard
17
+ def to_dict(self) -> dict:
18
+ return {"inline_keyboard": [[btn.to_dict() for btn in row] for row in self.inline_keyboard]}
@@ -0,0 +1,30 @@
1
+ from typing import Optional, TYPE_CHECKING
2
+ from .user import User
3
+ from .chat import Chat
4
+
5
+ class Message:
6
+ def __init__(self, data: dict, bot_instance):
7
+ self.message_id = data.get("message_id")
8
+ chat_data = data.get("chat", {})
9
+ self.chat = Chat(
10
+ id=chat_data.get("id", 0), type=chat_data.get("type", "private"),
11
+ title=chat_data.get("title"), first_name=chat_data.get("first_name"),
12
+ last_name=chat_data.get("last_name"), username=chat_data.get("username")
13
+ )
14
+ self.text = data.get("text")
15
+ self.caption = data.get("caption")
16
+ self.raw = data
17
+ self._bot = bot_instance
18
+
19
+ user_data = data.get("from")
20
+ if user_data:
21
+ self.from_user = User(
22
+ id=user_data.get("id", 0), is_bot=user_data.get("is_bot", False),
23
+ first_name=user_data.get("first_name", ""), last_name=user_data.get("last_name"),
24
+ username=user_data.get("username")
25
+ )
26
+ else:
27
+ self.from_user = None
28
+
29
+ def reply(self, text: str, reply_markup: Optional['InlineKeyboardMarkup'] = None):
30
+ return self._bot.send_message(self.chat.id, text, reply_to_message_id=self.message_id, reply_markup=reply_markup)
@@ -0,0 +1,10 @@
1
+ from dataclasses import dataclass
2
+ from typing import Optional
3
+
4
+ @dataclass
5
+ class User:
6
+ id: int
7
+ is_bot: bool
8
+ first_name: str
9
+ last_name: Optional[str] = None
10
+ username: Optional[str] = None
@@ -0,0 +1,70 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyjetra
3
+ Version: 1.0.0
4
+ Summary: A modern, bilingual (Sync/Async) Python wrapper for the Jetra Bot API.
5
+ Author-email: Ali VEX <lyrdaadhrpyk802@gmail.com>
6
+ Project-URL: Homepage, https://github.com/lyrdaadhrpyk802-ux/pyjetra
7
+ Project-URL: Documentation, https://github.com/lyrdaadhrpyk802-ux/pyjetra/blob/main/README.md
8
+ Project-URL: Jetra, https://jetra.ir/UserBoT
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.7
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ License-File: AUTHORS.md
16
+ Requires-Dist: requests>=2.25.0
17
+ Requires-Dist: aiohttp>=3.8.0
18
+ Dynamic: license-file
19
+
20
+ # PyJetra Library
21
+ ### [EN] A Modern Python Wrapper for Jetra Bot API
22
+ ### [FA] یک کتابخانه مدرن پایتون برای API ربات جترا
23
+
24
+ ---
25
+
26
+ ## [EN] Features / [FA] امکانات
27
+ * **Sync & Async Support** / پشتیبانی از Sync و Async
28
+ * **State Management** / مدیریت وضعیت
29
+ * **Advanced Filters** / فیلترهای پیشرفته
30
+ * **Full Media Support** / پشتیبانی کامل از رسانه‌ها
31
+
32
+ ## [EN] Installation / [FA] نصب
33
+ ```bash
34
+ pip install requests aiohttp
35
+ ```
36
+
37
+ ## [EN] Quick Start (Sync) / [FA] شروع سریع (همزمان)
38
+ ```python
39
+ from pyjetra import JetraBot, CommandFilter
40
+
41
+ bot = JetraBot('YOUR_TOKEN')
42
+
43
+ @bot.on_message(filters=[CommandFilter('start')])
44
+ def start(msg):
45
+ msg.reply('Hello from PyJetra!')
46
+
47
+ bot.poll()
48
+ ```
49
+
50
+ ## [EN] Quick Start (Async) / [FA] شروع سریع (غیرهمزمان)
51
+ ```python
52
+ from pyjetra import AsyncJetraBot, CommandFilter
53
+ import asyncio
54
+
55
+ bot = AsyncJetraBot('YOUR_TOKEN')
56
+
57
+ @bot.on_message(filters=[CommandFilter('start')])
58
+ async def start(msg):
59
+ await msg.reply('Hello Fast!')
60
+
61
+ asyncio.run(bot.start_polling())
62
+ ```
63
+
64
+ ## [EN] Testing / [FA] تست کردن
65
+ Navigate to the `tests/` folder and run the files.
66
+ Read the comments inside each test file.
67
+
68
+ ## [EN] Developer / [FA] توسعه‌دهنده
69
+ Created with ❤️ by Ali VEX
70
+ GitHub: https://github.com/lyrdaadhrpyk802-ux
@@ -0,0 +1,26 @@
1
+ AUTHORS.md
2
+ LICENSE
3
+ README.md
4
+ pyproject.toml
5
+ pyjetra/__init__.py
6
+ pyjetra/async_client.py
7
+ pyjetra/client.py
8
+ pyjetra/dev_info.py
9
+ pyjetra/exceptions.py
10
+ pyjetra/filters.py
11
+ pyjetra.egg-info/PKG-INFO
12
+ pyjetra.egg-info/SOURCES.txt
13
+ pyjetra.egg-info/dependency_links.txt
14
+ pyjetra.egg-info/requires.txt
15
+ pyjetra.egg-info/top_level.txt
16
+ pyjetra/types/__init__.py
17
+ pyjetra/types/callback.py
18
+ pyjetra/types/chat.py
19
+ pyjetra/types/markup.py
20
+ pyjetra/types/message.py
21
+ pyjetra/types/user.py
22
+ tests/test_advanced_buttons.py
23
+ tests/test_async.py
24
+ tests/test_error_handling.py
25
+ tests/test_registration_fsm.py
26
+ tests/test_sync.py
@@ -0,0 +1,2 @@
1
+ requests>=2.25.0
2
+ aiohttp>=3.8.0
@@ -0,0 +1 @@
1
+ pyjetra
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "pyjetra"
7
+ version = "1.0.0"
8
+ authors = [
9
+ {name = "Ali VEX", email = "lyrdaadhrpyk802@gmail.com"}
10
+ ]
11
+ description = "A modern, bilingual (Sync/Async) Python wrapper for the Jetra Bot API."
12
+ readme = "README.md"
13
+ requires-python = ">=3.7"
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Operating System :: OS Independent",
18
+ ]
19
+ dependencies = [
20
+ "requests>=2.25.0",
21
+ "aiohttp>=3.8.0"
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/lyrdaadhrpyk802-ux/pyjetra"
26
+ Documentation = "https://github.com/lyrdaadhrpyk802-ux/pyjetra/blob/main/README.md"
27
+ Jetra = "https://jetra.ir/UserBoT"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,44 @@
1
+ # [EN] Test for multi-level Inline Keyboards and Callback Parsing.
2
+ # [FA] تست برای کیبوردهای شیشه‌ای چند سطحی و پردازش کلیک‌ها.
3
+ # How to run: python tests/test_advanced_buttons.py
4
+ # Send /menu in the bot chat.
5
+
6
+ import sys, os
7
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
+ from pyjetra import JetraBot, CommandFilter, InlineKeyboardMarkup, InlineKeyboardButton
9
+
10
+ BOT_TOKEN = "1780246392:3W4m3UParm6nelq3mS2HmjtgV6_pWiIfCj8"
11
+ bot = JetraBot(BOT_TOKEN)
12
+
13
+ @bot.on_message(filters=[CommandFilter("menu")])
14
+ def show_menu(msg):
15
+ kb = InlineKeyboardMarkup([
16
+ [InlineKeyboardButton("Settings ⚙️", callback_data="settings")],
17
+ [InlineKeyboardButton("Help ❓", callback_data="help")]
18
+ ])
19
+ msg.reply("Main Menu:", reply_markup=kb)
20
+
21
+ @bot.on_callback_query()
22
+ def handle_click(cb):
23
+ if cb.data == "settings":
24
+ cb.answer("Opening settings...")
25
+ kb = InlineKeyboardMarkup([
26
+ [InlineKeyboardButton("Language 🌐", callback_data="lang")],
27
+ [InlineKeyboardButton("Back 🔙", callback_data="back")]
28
+ ])
29
+ # Editing the message to show the sub-menu
30
+ bot.edit_message_text(cb.message.chat.id, cb.message.message_id, "Settings Menu:", reply_markup=kb)
31
+
32
+ elif cb.data == "back":
33
+ cb.answer("Going back...")
34
+ kb = InlineKeyboardMarkup([
35
+ [InlineKeyboardButton("Settings ⚙️", callback_data="settings")],
36
+ [InlineKeyboardButton("Help ❓", callback_data="help")]
37
+ ])
38
+ bot.edit_message_text(cb.message.chat.id, cb.message.message_id, "Main Menu:", reply_markup=kb)
39
+
40
+ elif cb.data == "help":
41
+ cb.answer("Help is on the way!", show_alert=True)
42
+
43
+ if __name__ == "__main__":
44
+ bot.poll()
@@ -0,0 +1,15 @@
1
+ import sys, os, asyncio
2
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
3
+ from pyjetra import AsyncJetraBot, CommandFilter
4
+
5
+ BOT_TOKEN = "1780246392:3W4m3UParm6nelq3mS2HmjtgV6_pWiIfCj8"
6
+ bot = AsyncJetraBot(BOT_TOKEN)
7
+
8
+ @bot.on_message(filters=[CommandFilter("start")])
9
+ async def start_handler(msg):
10
+ await msg.reply("Async Bot is working at lightning speed!")
11
+ print("Received /start in Async mode.")
12
+
13
+ if __name__ == "__main__":
14
+ print("Starting Async Test...")
15
+ asyncio.run(bot.start_polling())
@@ -0,0 +1,24 @@
1
+ # [EN] Test how the library handles API errors gracefully.
2
+ # [FA] تست اینکه کتابخانه چگونه خطاهای API را مدیریت می‌کند.
3
+ # How to run: python tests/test_error_handling.py
4
+ # Send /error in the bot chat.
5
+
6
+ import sys, os
7
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
+ from pyjetra import JetraBot, CommandFilter, JetraError
9
+
10
+ BOT_TOKEN = "1780246392:3W4m3UParm6nelq3mS2HmjtgV6_pWiIfCj8"
11
+ bot = JetraBot(BOT_TOKEN)
12
+
13
+ @bot.on_message(filters=[CommandFilter("error")])
14
+ def trigger_error(msg):
15
+ try:
16
+ # Trying to send a message to an invalid Chat ID (999999999)
17
+ bot.send_message(999999999, "This will fail!")
18
+ except JetraError as e:
19
+ # Catch the error and inform the user
20
+ msg.reply(f"Successfully caught an error: {e}")
21
+ print(f"Error logged: {e}")
22
+
23
+ if __name__ == "__main__":
24
+ bot.poll()
@@ -0,0 +1,34 @@
1
+ # [EN] Test for State Management (FSM) - A step-by-step registration.
2
+ # [FA] تست برای مدیریت وضعیت (FSM) - یک ثبت‌نام مرحله به مرحله.
3
+ # How to run: python tests/test_registration_fsm.py
4
+ # Send /register in the bot chat.
5
+
6
+ import sys, os
7
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
+ from pyjetra import JetraBot, CommandFilter
9
+
10
+ BOT_TOKEN = "1780246392:3W4m3UParm6nelq3mS2HmjtgV6_pWiIfCj8"
11
+ bot = JetraBot(BOT_TOKEN)
12
+
13
+ @bot.on_message(filters=[CommandFilter("register")])
14
+ def start_registration(msg):
15
+ bot.set_state(msg.from_user.id, "waiting_for_name")
16
+ msg.reply("Welcome! Please type your name:")
17
+
18
+ @bot.on_message()
19
+ def handle_steps(msg):
20
+ if not msg.text or msg.text.startswith("/"):
21
+ return
22
+
23
+ state = bot.get_state(msg.from_user.id)
24
+
25
+ if state == "waiting_for_name":
26
+ bot.set_state(msg.from_user.id, "waiting_for_age")
27
+ msg.reply(f"Nice to meet you, {msg.text}! How old are you?")
28
+
29
+ elif state == "waiting_for_age":
30
+ bot.clear_state(msg.from_user.id)
31
+ msg.reply(f"You are {msg.text} years old. Registration complete! ✅")
32
+
33
+ if __name__ == "__main__":
34
+ bot.poll()
@@ -0,0 +1,15 @@
1
+ import sys, os
2
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
3
+ from pyjetra import JetraBot, CommandFilter
4
+
5
+ BOT_TOKEN = "1780246392:3W4m3UParm6nelq3mS2HmjtgV6_pWiIfCj8"
6
+ bot = JetraBot(BOT_TOKEN)
7
+
8
+ @bot.on_message(filters=[CommandFilter("start")])
9
+ def start_handler(msg):
10
+ msg.reply("Sync Bot is working perfectly!")
11
+ print("Received /start in Sync mode.")
12
+
13
+ if __name__ == "__main__":
14
+ print("Starting Sync Test...")
15
+ bot.poll()