Примеры модулей¶
Каждый пример загружается в тестах (tests/test_examples.py), поэтому код ниже рабочий для текущей версии. Установить пример: ответьте на файл командой .lm или .dlm asykixd/uroboros/examples/<имя>.
counter¶
# meta developer: @uroboros
# requires_uroboros: 0.3
"""Inline form: buttons, text input, confirmation and an inline command."""
from uroboros import Module, command, inline_handler
class Counter(Module):
"""Counter with buttons"""
@command("counter")
async def counter(self, message):
"""— counter with buttons"""
await self.inline.form(message, self._text(0), self._buttons(0))
@staticmethod
def _text(value):
return f"🔢 <b>Count:</b> <code>{value}</code>"
def _buttons(self, value):
return [
[
{"text": "−", "callback": self._add, "args": (value, -1)},
{"text": "+", "callback": self._add, "args": (value, 1)},
],
[{"text": "✍️ Set", "input": "New value", "handler": self._typed}],
[
{"text": "Reset", "callback": self._add, "args": (0, 0), "confirm": "Reset the counter?"},
{"text": "✖ Close", "action": "close"},
],
]
async def _add(self, call, value, delta):
value += delta
await call.edit(self._text(value), self._buttons(value))
async def _typed(self, call, text):
if not text.lstrip("-").isdigit():
await call.edit("❌ Integer required", self._buttons(0))
return
await call.edit(self._text(int(text)), self._buttons(int(text)))
@inline_handler()
async def count_inline_handler(self, query):
"""<number> — send a counter to any chat"""
value = int(query.args) if query.args.lstrip("-").isdigit() else 0
return {
"title": f"Counter from {value}",
"message": self._text(value),
"buttons": self._buttons(value),
}
hello¶
# meta developer: @uroboros
# meta version: 1.0
# meta permissions: none
# requires_uroboros: 1.0
"""Minimal module: a command, a setting, strings and a card reply."""
from uroboros import ConfigValue, Module, ModuleConfig, command, utils, validators
class Hello(Module):
"""Says hello"""
strings = {
"hello": "👋 <b>Hello, {name}!</b>",
"count": "🔁 Greeted <code>{n}</code> times",
}
def __init__(self):
self.config = ModuleConfig(
ConfigValue("name", "world", "Default name to greet", validators.String(max_len=64)),
)
@command("hello", aliases=["hi"], emoji="👋")
async def hello(self, message):
"""[name] — say hello"""
name = utils.get_args_raw(message) or self.config["name"]
self.set("count", self.get("count", 0) + 1)
await utils.answer(
message,
utils.card(
self.strings("hello", name=name),
self.strings("count", n=self.get("count")),
hint="change the default name: <code>.cfg hello name</code>",
),
)
reminder¶
# meta developer: @uroboros
# requires_uroboros: 0.2
"""Background task: checks reminders every minute and sends them to Saved Messages."""
import time
from uroboros import Module, command, loop, utils
class Reminder(Module):
"""Reminders in Saved Messages"""
@command("remind", no_reply=True)
async def remind(self, message):
"""<minutes> <text> — remind in N minutes"""
args = utils.get_args_raw(message).split(maxsplit=1)
if len(args) != 2 or not args[0].isdigit():
await utils.answer(message, "❌ Usage: <code>remind 10 text</code>")
return
reminders = self.get("reminders", [])
reminders.append([time.time() + int(args[0]) * 60, args[1]])
self.set("reminders", reminders)
await utils.answer(message, f"✅ Reminder in {int(args[0])} min")
@loop(interval=60)
async def check(self):
now = time.time()
reminders = self.get("reminders", [])
due = [text for at, text in reminders if at <= now]
if not due:
return
self.set("reminders", [[at, text] for at, text in reminders if at > now])
for text in due:
await self.client.send_message("me", f"⏰ {utils.escape_html(text)}", parse_mode="html")
shout¶
# requires_uroboros: 0.2
"""A module that uses the textlib.py library."""
from uroboros import Module, command, utils
TEXTLIB = "https://raw.githubusercontent.com/asykixd/uroboros/HEAD/examples/textlib.py"
class Shout(Module):
"""Shouts text"""
async def on_load(self):
self.textlib = await self.import_lib(TEXTLIB)
@command("shout")
async def shout(self, message):
"""<text> — shout"""
await utils.answer(message, utils.escape_html(self.textlib.shout(utils.get_args_raw(message))))
textlib¶
# requires_uroboros: 0.2
"""Library: code shared by several modules. Imported with self.import_lib(url)."""
from uroboros import Library
class TextLib(Library):
async def on_load(self):
self.calls = 0
def shout(self, text: str) -> str:
self.calls += 1
return text.upper() + "!"
who¶
# meta developer: @uroboros
# requires_uroboros: 0.2
"""Command filters and user lookup: by reply, @username or private chat."""
from uroboros import Module, command, utils
class Who(Module):
"""User info"""
@command("who")
async def who(self, message):
"""[@username | id] — who is this (or reply to a message)"""
user = await utils.get_target(message)
if user is None:
await utils.answer(message, "❌ Reply to a message or pass @username")
return
name = getattr(user, "first_name", None) or getattr(user, "title", "")
await utils.answer(
message,
f"👤 <b>{utils.escape_html(name)}</b>\n" + utils.quote(f"id: <code>{user.id}</code>"),
)
@command("pmonly", only_pm=True)
async def pmonly(self, message):
"""— works in private chats only"""
await utils.answer(message, "✅ This is a private chat")