python-zatolox-bot 0.1.0__tar.gz → 0.1.2__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.
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/PKG-INFO +1 -1
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/python_zatolox_bot.egg-info/PKG-INFO +1 -1
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/setup.py +1 -1
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/zatolox/__init__.py +1 -1
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/zatolox/bot.py +104 -1
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/python_zatolox_bot.egg-info/SOURCES.txt +0 -0
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/python_zatolox_bot.egg-info/dependency_links.txt +0 -0
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/python_zatolox_bot.egg-info/requires.txt +0 -0
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/python_zatolox_bot.egg-info/top_level.txt +0 -0
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/setup.cfg +0 -0
- {python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/zatolox/types.py +0 -0
|
@@ -5,7 +5,7 @@ from setuptools import setup, find_packages
|
|
|
5
5
|
# sono, meno se ne rompono.
|
|
6
6
|
setup(
|
|
7
7
|
name="python-zatolox-bot",
|
|
8
|
-
version="0.1.
|
|
8
|
+
version="0.1.2",
|
|
9
9
|
description="SDK ufficiale per costruire bot su Zatolox",
|
|
10
10
|
long_description=(
|
|
11
11
|
"Wrapper leggero attorno al gateway HTTP dei bot di Zatolox. "
|
|
@@ -45,6 +45,9 @@ class ZatoloxBot:
|
|
|
45
45
|
self.command_handlers: Dict[str, Callable[[Message], None]] = {}
|
|
46
46
|
self._message_handler: Optional[Callable[[Message], None]] = None
|
|
47
47
|
self._callback_handler: Optional[Callable[[CallbackQuery], None]] = None
|
|
48
|
+
# Handler di callback CON PREDICATO (@bot.callback_query_handler(func=...)): coppie
|
|
49
|
+
# (predicato, funzione). Il primo il cui predicato e' vero riceve il click.
|
|
50
|
+
self._callback_query_handlers: List[tuple] = []
|
|
48
51
|
|
|
49
52
|
# Offset del prossimo getUpdates. Avanza a `ultimo update_id + 1`: e' cosi' che si conferma
|
|
50
53
|
# al server di aver ricevuto tutto cio' che precede, e non lo si riceve piu'.
|
|
@@ -91,6 +94,61 @@ class ZatoloxBot:
|
|
|
91
94
|
result = self._call("getUpdates", params, http="get") or []
|
|
92
95
|
return [Update.from_dict(u) for u in result]
|
|
93
96
|
|
|
97
|
+
def set_my_commands(self, commands: List[Any]) -> List[dict]:
|
|
98
|
+
"""
|
|
99
|
+
Registra i comandi del bot sul server (come setMyCommands di Telegram).
|
|
100
|
+
|
|
101
|
+
Il client Zatolox li mostra nel menu "/" della barra input: senza almeno un comando quel
|
|
102
|
+
menu non compare proprio. Da chiamare una volta all'avvio.
|
|
103
|
+
|
|
104
|
+
`commands` accetta forme diverse, per comodita':
|
|
105
|
+
- dict: {"command": "start", "description": "avvia il bot"}
|
|
106
|
+
- tupla: ("start", "avvia il bot")
|
|
107
|
+
Lo slash iniziale e' facoltativo: lo normalizza il server. Un array vuoto azzera i comandi.
|
|
108
|
+
"""
|
|
109
|
+
norm: List[dict] = []
|
|
110
|
+
for c in commands:
|
|
111
|
+
if isinstance(c, dict):
|
|
112
|
+
norm.append({"command": str(c.get("command", "")), "description": str(c.get("description", ""))})
|
|
113
|
+
elif isinstance(c, (tuple, list)) and len(c) >= 2:
|
|
114
|
+
norm.append({"command": str(c[0]), "description": str(c[1])})
|
|
115
|
+
return self._call("setMyCommands", {"commands": norm})
|
|
116
|
+
|
|
117
|
+
def edit_message_text(
|
|
118
|
+
self, chat_id: str, message_id: str, text: str, reply_markup: Optional[Any] = None
|
|
119
|
+
) -> Optional[Message]:
|
|
120
|
+
"""
|
|
121
|
+
Riscrive un PROPRIO messaggio (testo + eventuali pulsanti). La via per navigare un menu:
|
|
122
|
+
clic -> callback -> edit del testo e dei pulsanti, senza inviare un nuovo messaggio.
|
|
123
|
+
|
|
124
|
+
Se passi `reply_markup` aggiorna la tastiera (None esplicito la rimuove); se lo ometti, i
|
|
125
|
+
pulsanti restano quelli di prima. Un bot puo' modificare solo i messaggi che ha inviato lui.
|
|
126
|
+
"""
|
|
127
|
+
payload: Dict[str, Any] = {"chat_id": chat_id, "message_id": message_id, "text": text}
|
|
128
|
+
if reply_markup is not None:
|
|
129
|
+
payload["reply_markup"] = reply_markup
|
|
130
|
+
return Message.from_dict(self._call("editMessageText", payload))
|
|
131
|
+
|
|
132
|
+
def edit_message_reply_markup(
|
|
133
|
+
self, chat_id: str, message_id: str, reply_markup: Optional[Any] = None
|
|
134
|
+
) -> Optional[Message]:
|
|
135
|
+
"""Cambia SOLO i pulsanti di un proprio messaggio, senza toccarne il testo (utile per i
|
|
136
|
+
sottomenu). `reply_markup=None` toglie la tastiera."""
|
|
137
|
+
return Message.from_dict(self._call(
|
|
138
|
+
"editMessageReplyMarkup",
|
|
139
|
+
{"chat_id": chat_id, "message_id": message_id, "reply_markup": reply_markup}
|
|
140
|
+
))
|
|
141
|
+
|
|
142
|
+
def answer_callback_query(self, callback_query_id: str, text: Optional[str] = None) -> Any:
|
|
143
|
+
"""
|
|
144
|
+
Conferma un click su un pulsante inline. Con `text` mostra un piccolo avviso a chi ha
|
|
145
|
+
toccato; senza, e' solo un ack. Da chiamare dentro l'handler della callback.
|
|
146
|
+
"""
|
|
147
|
+
payload: Dict[str, Any] = {"callback_query_id": callback_query_id}
|
|
148
|
+
if text is not None:
|
|
149
|
+
payload["text"] = text
|
|
150
|
+
return self._call("answerCallbackQuery", payload)
|
|
151
|
+
|
|
94
152
|
# ------------------------------------------------------------------ handler
|
|
95
153
|
|
|
96
154
|
def add_command_handler(self, command: str, callback: Callable[[Message], None]) -> None:
|
|
@@ -113,6 +171,43 @@ class ZatoloxBot:
|
|
|
113
171
|
return fn
|
|
114
172
|
return deco
|
|
115
173
|
|
|
174
|
+
def message_handler(self, fn: Optional[Callable[[Message], None]] = None):
|
|
175
|
+
"""
|
|
176
|
+
Decoratore per il fallback sul testo LIBERO (i messaggi che non sono comandi) — la base per
|
|
177
|
+
un bot conversazionale (es. inoltrare il testo a un'IA). Equivale ad add_message_handler.
|
|
178
|
+
|
|
179
|
+
Funziona sia nudo sia con le parentesi::
|
|
180
|
+
|
|
181
|
+
@bot.message_handler
|
|
182
|
+
def on_text(msg): ...
|
|
183
|
+
|
|
184
|
+
@bot.message_handler()
|
|
185
|
+
def on_text(msg): ...
|
|
186
|
+
"""
|
|
187
|
+
def register(f: Callable[[Message], None]) -> Callable[[Message], None]:
|
|
188
|
+
self.add_message_handler(f)
|
|
189
|
+
return f
|
|
190
|
+
# Uso nudo (@bot.message_handler): Python passa gia' la funzione qui.
|
|
191
|
+
return register(fn) if fn is not None else register
|
|
192
|
+
|
|
193
|
+
def callback_query_handler(self, func: Optional[Callable[[CallbackQuery], bool]] = None):
|
|
194
|
+
"""
|
|
195
|
+
Decoratore per i click sui pulsanti inline, con un filtro:
|
|
196
|
+
|
|
197
|
+
@bot.callback_query_handler(func=lambda call: call.data == "next")
|
|
198
|
+
def on_next(call): ...
|
|
199
|
+
|
|
200
|
+
`func` e' un predicato sul CallbackQuery: il PRIMO handler il cui predicato e' vero riceve il
|
|
201
|
+
click. Ometti `func` (o passa None) per prenderli tutti. Coesiste con add_callback_handler,
|
|
202
|
+
che resta come fallback finale.
|
|
203
|
+
"""
|
|
204
|
+
predicate = func if callable(func) else (lambda call: True)
|
|
205
|
+
|
|
206
|
+
def deco(fn: Callable[[CallbackQuery], None]) -> Callable[[CallbackQuery], None]:
|
|
207
|
+
self._callback_query_handlers.append((predicate, fn))
|
|
208
|
+
return fn
|
|
209
|
+
return deco
|
|
210
|
+
|
|
116
211
|
# ------------------------------------------------------------------ instradamento
|
|
117
212
|
|
|
118
213
|
def _dispatch(self, update: Update) -> None:
|
|
@@ -120,8 +215,16 @@ class ZatoloxBot:
|
|
|
120
215
|
stampata, non propagata, cosi' un handler difettoso non ferma il polling."""
|
|
121
216
|
try:
|
|
122
217
|
if update.callback_query is not None:
|
|
218
|
+
cb = update.callback_query
|
|
219
|
+
# Prima gli handler con predicato, in ordine di registrazione: vince il primo che
|
|
220
|
+
# accetta. E' cio' che permette di smistare per callback_data (menu/sottomenu).
|
|
221
|
+
for predicate, fn in self._callback_query_handlers:
|
|
222
|
+
if predicate(cb):
|
|
223
|
+
fn(cb)
|
|
224
|
+
return
|
|
225
|
+
# Nessuno ha accettato: fallback al singolo handler generico, se c'e'.
|
|
123
226
|
if self._callback_handler:
|
|
124
|
-
self._callback_handler(
|
|
227
|
+
self._callback_handler(cb)
|
|
125
228
|
return
|
|
126
229
|
|
|
127
230
|
msg = update.message
|
{python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/python_zatolox_bot.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/python_zatolox_bot.egg-info/requires.txt
RENAMED
|
File without changes
|
{python_zatolox_bot-0.1.0 → python_zatolox_bot-0.1.2}/python_zatolox_bot.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|