python-zatolox-bot 0.1.1__tar.gz → 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.
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/PKG-INFO +1 -1
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/python_zatolox_bot.egg-info/PKG-INFO +1 -1
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/setup.py +1 -1
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/zatolox/__init__.py +1 -1
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/zatolox/bot.py +65 -1
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/zatolox/types.py +4 -0
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/python_zatolox_bot.egg-info/SOURCES.txt +0 -0
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/python_zatolox_bot.egg-info/dependency_links.txt +0 -0
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/python_zatolox_bot.egg-info/requires.txt +0 -0
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/python_zatolox_bot.egg-info/top_level.txt +0 -0
- {python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/setup.cfg +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.3",
|
|
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'.
|
|
@@ -111,6 +114,41 @@ class ZatoloxBot:
|
|
|
111
114
|
norm.append({"command": str(c[0]), "description": str(c[1])})
|
|
112
115
|
return self._call("setMyCommands", {"commands": norm})
|
|
113
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
|
+
|
|
114
152
|
# ------------------------------------------------------------------ handler
|
|
115
153
|
|
|
116
154
|
def add_command_handler(self, command: str, callback: Callable[[Message], None]) -> None:
|
|
@@ -152,6 +190,24 @@ class ZatoloxBot:
|
|
|
152
190
|
# Uso nudo (@bot.message_handler): Python passa gia' la funzione qui.
|
|
153
191
|
return register(fn) if fn is not None else register
|
|
154
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
|
+
|
|
155
211
|
# ------------------------------------------------------------------ instradamento
|
|
156
212
|
|
|
157
213
|
def _dispatch(self, update: Update) -> None:
|
|
@@ -159,8 +215,16 @@ class ZatoloxBot:
|
|
|
159
215
|
stampata, non propagata, cosi' un handler difettoso non ferma il polling."""
|
|
160
216
|
try:
|
|
161
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'.
|
|
162
226
|
if self._callback_handler:
|
|
163
|
-
self._callback_handler(
|
|
227
|
+
self._callback_handler(cb)
|
|
164
228
|
return
|
|
165
229
|
|
|
166
230
|
msg = update.message
|
|
@@ -38,6 +38,9 @@ class Message:
|
|
|
38
38
|
type: str = "TEXT"
|
|
39
39
|
date: Optional[int] = None
|
|
40
40
|
from_user: Optional[User] = None
|
|
41
|
+
# URL del media per foto/file (type IMAGE/FILE/...); None per il testo. Serve, p.es., a un bot
|
|
42
|
+
# che accetta un'immagine e la usa come avatar.
|
|
43
|
+
media_url: Optional[str] = None
|
|
41
44
|
|
|
42
45
|
@classmethod
|
|
43
46
|
def from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["Message"]:
|
|
@@ -50,6 +53,7 @@ class Message:
|
|
|
50
53
|
type=d.get("type", "TEXT"),
|
|
51
54
|
date=d.get("date"),
|
|
52
55
|
from_user=User.from_dict(d.get("from")),
|
|
56
|
+
media_url=d.get("media_url"),
|
|
53
57
|
)
|
|
54
58
|
|
|
55
59
|
@property
|
{python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/python_zatolox_bot.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/python_zatolox_bot.egg-info/requires.txt
RENAMED
|
File without changes
|
{python_zatolox_bot-0.1.1 → python_zatolox_bot-0.1.3}/python_zatolox_bot.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|