mirror of
https://gitlab.com/octospacc/WinDog.git
synced 2025-06-05 22:09:20 +02:00
Rename some internal functions; Update db and start work on message filters
This commit is contained in:
@ -14,19 +14,64 @@ class BaseModel(Model):
|
||||
|
||||
class EntitySettings(BaseModel):
|
||||
language = CharField(null=True)
|
||||
#country = ...
|
||||
#timezone = ...
|
||||
|
||||
class Entity(BaseModel):
|
||||
id = CharField(null=True)
|
||||
id_hash = CharField()
|
||||
settings = ForeignKeyField(EntitySettings, backref="entity", null=True)
|
||||
|
||||
class User(Entity):
|
||||
pass
|
||||
class File(BaseModel):
|
||||
path = CharField()
|
||||
content = BlobField()
|
||||
owner = ForeignKeyField(Entity, backref="files")
|
||||
class Meta:
|
||||
indexes = (
|
||||
(('path', 'owner'), True),
|
||||
)
|
||||
|
||||
#class BaseFilter(BaseModel):
|
||||
# name = CharField(null=True)
|
||||
# owner = ForeignKeyField(Entity, backref="filters")
|
||||
|
||||
#class ScriptFilter(BaseFilter):
|
||||
# script = TextField()
|
||||
|
||||
#class StaticFilter(BaseFilter):
|
||||
# response = TextField()
|
||||
|
||||
class Filter(BaseModel):
|
||||
name = CharField(null=True)
|
||||
trigger = CharField(null=True)
|
||||
output = CharField(null=True)
|
||||
owner = ForeignKeyField(Entity, backref="filters")
|
||||
|
||||
class Room(Entity):
|
||||
pass
|
||||
|
||||
Db.create_tables([EntitySettings, User, Room], safe=True)
|
||||
UserToRoomDeferred = DeferredThroughModel()
|
||||
FilterToRoomDeferred = DeferredThroughModel()
|
||||
|
||||
class User(Entity):
|
||||
rooms = ManyToManyField(Room, backref="users", through_model=UserToRoomDeferred)
|
||||
|
||||
class UserToRoom(BaseModel):
|
||||
user = ForeignKeyField(User, backref="room_links")
|
||||
room = ForeignKeyField(Room, backref="user_links")
|
||||
|
||||
class FilterToRoom(BaseModel):
|
||||
filter = ForeignKeyField(Filter, backref="room_links")
|
||||
room = ForeignKeyField(Room, backref="filter_links")
|
||||
|
||||
UserToRoomDeferred.set_model(UserToRoom)
|
||||
FilterToRoomDeferred.set_model(FilterToRoom)
|
||||
|
||||
Db.create_tables([
|
||||
EntitySettings, File, Filter,
|
||||
User, Room,
|
||||
FilterToRoom, UserToRoom,
|
||||
], safe=True)
|
||||
|
||||
class UserSettingsData():
|
||||
def __new__(cls, user_id:str=None) -> SafeNamespace:
|
||||
|
@ -46,7 +46,7 @@ def MastodonMakeInputMessageData(status:dict) -> InputMessageData:
|
||||
def MastodonHandler(event, Mastodon):
|
||||
if event["type"] == "mention":
|
||||
data = MastodonMakeInputMessageData(event["status"])
|
||||
OnInputMessageParsed(data)
|
||||
on_input_message_parsed(data)
|
||||
call_endpoint(EventContext(platform="mastodon", event=event, manager=Mastodon), data)
|
||||
|
||||
def MastodonSender(context:EventContext, data:OutputMessageData) -> None:
|
||||
@ -67,5 +67,5 @@ def MastodonSender(context:EventContext, data:OutputMessageData) -> None:
|
||||
visibility=('direct' if context.event['status']['visibility'] == 'direct' else 'unlisted'),
|
||||
)
|
||||
|
||||
RegisterPlatform(name="Mastodon", main=MastodonMain, sender=MastodonSender, manager_class=mastodon.Mastodon)
|
||||
register_platform(name="Mastodon", main=MastodonMain, sender=MastodonSender, manager_class=mastodon.Mastodon)
|
||||
|
||||
|
@ -83,7 +83,7 @@ async def MatrixMessageHandler(room:nio.MatrixRoom, event:nio.RoomMessage) -> No
|
||||
if MatrixUsername == event.sender:
|
||||
return # ignore messages that come from the bot itself
|
||||
data = MatrixMakeInputMessageData(room, event)
|
||||
OnInputMessageParsed(data)
|
||||
on_input_message_parsed(data)
|
||||
call_endpoint(EventContext(platform="matrix", event=SafeNamespace(room=room, event=event), manager=MatrixClient), data)
|
||||
|
||||
def MatrixSender(context:EventContext, data:OutputMessageData):
|
||||
@ -97,5 +97,5 @@ def MatrixSender(context:EventContext, data:OutputMessageData):
|
||||
message_type="m.room.message",
|
||||
content={"msgtype": "m.text", "body": data.text_plain}))
|
||||
|
||||
RegisterPlatform(name="Matrix", main=MatrixMain, sender=MatrixSender, manager_class=(lambda:MatrixClient))
|
||||
register_platform(name="Matrix", main=MatrixMain, sender=MatrixSender, manager_class=(lambda:MatrixClient))
|
||||
|
||||
|
@ -68,7 +68,7 @@ def TelegramHandler(update:telegram.Update, context:CallbackContext=None) -> Non
|
||||
data = TelegramMakeInputMessageData(update.message)
|
||||
if (quoted := update.message.reply_to_message):
|
||||
data.quoted = TelegramMakeInputMessageData(quoted)
|
||||
OnInputMessageParsed(data)
|
||||
on_input_message_parsed(data)
|
||||
call_endpoint(EventContext(platform="telegram", event=update, manager=context), data)
|
||||
Thread(target=handler).start()
|
||||
|
||||
@ -107,7 +107,7 @@ def TelegramLinker(data:InputMessageData) -> SafeNamespace:
|
||||
linked.message = f"https://t.me/c/{room_id}/{message_id}"
|
||||
return linked
|
||||
|
||||
RegisterPlatform(
|
||||
register_platform(
|
||||
name="Telegram",
|
||||
main=TelegramMain,
|
||||
sender=TelegramSender,
|
||||
|
@ -55,7 +55,7 @@ class WebServerClass(BaseHTTPRequestHandler):
|
||||
def init_new_room(self, room_id:str=None):
|
||||
if not room_id:
|
||||
room_id = str(uuid7().hex)
|
||||
WebQueues[room_id] = {}#{"0": queue.Queue()}
|
||||
WebQueues[room_id] = {}
|
||||
#WebPushEvent(room_id, ".start", self.headers)
|
||||
#Thread(target=lambda:WebAntiDropEnqueue(room_id)).start()
|
||||
self.do_redirect(f"/{room_id}")
|
||||
@ -65,15 +65,16 @@ class WebServerClass(BaseHTTPRequestHandler):
|
||||
self.send_header("Content-Type", "text/html; charset=UTF-8")
|
||||
self.send_header("Content-Encoding", "chunked")
|
||||
self.end_headers()
|
||||
target = f"/{room_id}/{user_id}?page-target=1#load-target"
|
||||
if not is_redirected:
|
||||
return self.wfile.write(f'''{web_html_prefix(head_extra=f'<meta http-equiv="refresh" content="0; url={target}">')}
|
||||
target = f"/{room_id}/{user_id}?page-target=1#load-target"
|
||||
self.wfile.write(f'''{web_html_prefix(head_extra=f'<meta http-equiv="refresh" content="0; url={target}">')}
|
||||
<h3><a href="/" target="_parent">WinDog 🐶️</a></h3>
|
||||
<p>Initializing... <a href="{target}">Click here</a> if you are not automatically redirected.</p>'''.encode())
|
||||
else:
|
||||
self.wfile.write(f'''{web_html_prefix()}
|
||||
<h3><a href="/" target="_parent">WinDog 🐶️</a></h3>
|
||||
<div class="sticky-box">
|
||||
<p id="load-target" style="display: none;"><span style="color: red;">Background loading seems to have stopped...</span> Please open a new chat or <a href="{target}">reload this one</a> if you can't send new messages.</p>
|
||||
<p id="load-target" style="display: none;"><span style="color: red;">Background loading seems to have stopped...</span> Please open a new chat or <a href="/{room_id}">reload this current one</a> if you can't send new messages.</p>
|
||||
<div class="input-frame"><iframe src="/form/{room_id}/{user_id}"></iframe></div>
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: column-reverse;">'''.encode())
|
||||
@ -158,7 +159,7 @@ def WebPushEvent(room_id:str, user_id:str, text:str, headers:dict[str:str]):
|
||||
settings = UserSettingsData(),
|
||||
),
|
||||
)
|
||||
OnInputMessageParsed(data)
|
||||
on_input_message_parsed(data)
|
||||
WebSender(context, ObjectUnion(data, {"from_user": True}))
|
||||
call_endpoint(context, data)
|
||||
|
||||
@ -183,7 +184,6 @@ def WebMain(path:str) -> bool:
|
||||
return True
|
||||
|
||||
def WebSender(context:EventContext, data:OutputMessageData) -> None:
|
||||
#WebQueues[context.event.room_id][context.event.user_id].put(data)
|
||||
for user_id in (room := WebQueues[context.event.room_id]):
|
||||
room[user_id].put(data)
|
||||
|
||||
@ -194,5 +194,5 @@ def WebAntiDropEnqueue(room_id:str, user_id:str):
|
||||
WebQueues[room_id][user_id].put(OutputMessageData())
|
||||
time.sleep(WebConfig["anti_drop_interval"])
|
||||
|
||||
RegisterPlatform(name="Web", main=WebMain, sender=WebSender)
|
||||
register_platform(name="Web", main=WebMain, sender=WebSender)
|
||||
|
||||
|
0
LibWinDog/Platforms/Web/requirements.txt
Normal file → Executable file
0
LibWinDog/Platforms/Web/requirements.txt
Normal file → Executable file
0
LibWinDog/Platforms/Web/windog.css
Normal file → Executable file
0
LibWinDog/Platforms/Web/windog.css
Normal file → Executable file
0
LibWinDog/Platforms/Web/windog.js
Normal file → Executable file
0
LibWinDog/Platforms/Web/windog.js
Normal file → Executable file
@ -52,7 +52,7 @@ def cPing(context:EventContext, data:InputMessageData):
|
||||
#def cEval(context:EventContext, data:InputMessageData) -> None:
|
||||
# send_message(context, {"Text": choice(Locale.__('eval'))})
|
||||
|
||||
RegisterModule(name="Base", endpoints=[
|
||||
register_module(name="Base", endpoints=[
|
||||
SafeNamespace(names=["source"], handler=cSource),
|
||||
SafeNamespace(names=["config", "settings"], handler=cConfig, body=False, arguments={
|
||||
"get": True,
|
||||
|
@ -12,10 +12,10 @@ def cBroadcast(context:EventContext, data:InputMessageData):
|
||||
if not (destination and text):
|
||||
return send_status_400(context, language)
|
||||
result = send_message(context, {"text_plain": text, "room": SafeNamespace(id=destination)})
|
||||
send_message(context, {"text_plain": "Executed."})
|
||||
send_status(context, 201, language)
|
||||
return result
|
||||
|
||||
RegisterModule(name="Broadcast", endpoints=[
|
||||
register_module(name="Broadcast", endpoints=[
|
||||
SafeNamespace(names=["broadcast"], handler=cBroadcast, body=True, arguments={
|
||||
"destination": True,
|
||||
}),
|
||||
|
@ -41,7 +41,7 @@ def mCodings(context:EventContext, data:InputMessageData):
|
||||
except Exception:
|
||||
return send_status_error(context, language)
|
||||
|
||||
RegisterModule(name="Codings", group="Geek", endpoints=[
|
||||
register_module(name="Codings", group="Geek", endpoints=[
|
||||
SafeNamespace(names=["encode", "decode"], handler=mCodings, body=False, quoted=False, arguments={
|
||||
"algorithm": True,
|
||||
}, help_extra=(lambda endpoint, lang: f'{endpoint.module.get_string("algorithms", lang)}: <code>{"</code>, <code>".join(CodingsAlgorithms)}</code>.')),
|
||||
|
@ -6,13 +6,14 @@
|
||||
from json import dumps as json_dumps
|
||||
|
||||
# TODO work with links to messages
|
||||
# TODO remove "wrong" objects like callables
|
||||
def cDump(context:EventContext, data:InputMessageData):
|
||||
if not (message := data.quoted):
|
||||
return send_status_400(context, data.user.settings.language)
|
||||
text = json_dumps(message, default=(lambda obj: obj.__dict__), indent=" ")
|
||||
text = json_dumps(message, default=(lambda obj: (obj.__dict__ if not callable(obj) else None)), indent=" ")
|
||||
return send_message(context, {"text_html": f'<pre>{html_escape(text)}</pre>'})
|
||||
|
||||
RegisterModule(name="Dumper", group="Geek", endpoints=[
|
||||
register_module(name="Dumper", group="Geek", endpoints=[
|
||||
SafeNamespace(names=["dump"], handler=cDump, quoted=True),
|
||||
])
|
||||
|
||||
|
@ -20,7 +20,7 @@ def cEcho(context:EventContext, data:InputMessageData):
|
||||
prefix = ''
|
||||
return send_message(context, {"text_html": (prefix + html_escape(text))})
|
||||
|
||||
RegisterModule(name="Echo", endpoints=[
|
||||
register_module(name="Echo", endpoints=[
|
||||
SafeNamespace(names=["echo"], handler=cEcho, body=True),
|
||||
])
|
||||
|
||||
|
69
ModWinDog/Filters/Filters.py
Executable file
69
ModWinDog/Filters/Filters.py
Executable file
@ -0,0 +1,69 @@
|
||||
# ==================================== #
|
||||
# WinDog multi-purpose chatbot #
|
||||
# Licensed under AGPLv3 by OctoSpacc #
|
||||
# ==================================== #
|
||||
|
||||
def cFilters(context:EventContext, data:InputMessageData):
|
||||
language = data.user.settings.language
|
||||
if not check_room_admin(data.user):
|
||||
return send_status(context, 403, language)
|
||||
# action: create, delete, toggle <chatid, name/filterid>
|
||||
# * (input) handle, ignore <...>
|
||||
# * (output) setscript <..., script>
|
||||
# * (output) insert, remove <..., groupid, message>
|
||||
#arguments = data.command.parse_arguments(4)
|
||||
if not (action := data.command.arguments.action) or (action not in ["list", "create", "delete"]):
|
||||
return send_status_400(context, language)
|
||||
[room_id, filter_id, command_data] = ((None,) * 3)
|
||||
for token in data.command.tokens[2:]:
|
||||
if (not room_id) and (':' in token):
|
||||
room_id = token
|
||||
elif (not filter_id):
|
||||
filter_id = token
|
||||
elif (not command_data):
|
||||
command_data = token
|
||||
if not room_id:
|
||||
room_id = data.room.id
|
||||
if (action in ["delete"]) and (not filter_id):
|
||||
return send_status_400(context, language)
|
||||
match action:
|
||||
case "list":
|
||||
filters_list = ""
|
||||
for filter in Filter.select().where(Filter.owner == room_id).namedtuples():
|
||||
filters_list += f"\n* <code>{filter.id}</code> — {filter.name or '[?]'}"
|
||||
if filters_list:
|
||||
return send_message(context, {"text_html": f"Filters for room <code>{room_id}</code>:{filters_list}"})
|
||||
else:
|
||||
return send_status(context, 404, language, f"No filters found for the room <code>{room_id}</code>.", summary=False)
|
||||
case "create":
|
||||
...
|
||||
# TODO error message on name constraint violation
|
||||
# TODO filter name validation (no spaces or special symbols, no only numbers)
|
||||
if filter_id and (len(Filter.select().where((Filter.owner == room_id) & (Filter.name == filter_id)).tuples()) > 0):
|
||||
return
|
||||
else:
|
||||
filter_id = Filter.create(name=filter_id, owner=room_id)
|
||||
return send_status(context, 201, language, f"Filter with id <code>{filter_id}</code> in room <code>{room_id}</code> created successfully.", summary=False)
|
||||
case "delete":
|
||||
#try:
|
||||
Filter.delete().where((Filter.owner == room_id) & ((Filter.id == filter_id) | (Filter.name == filter_id))).execute()
|
||||
return send_status(context, 200, language)
|
||||
#return send_status(context, 200, language, f"Filter <code>{filter_id}</code> for room <code>{room_id}</code> deleted successfully.", summary=False)
|
||||
#except Exception:
|
||||
# ... # TODO error and success message, actually check for if the item to delete existed
|
||||
case "insert": # TODO
|
||||
#output = Filter.select().where((Filter.owner == room_id) & ((Filter.id == filter_id) | (Filter.name == filter_id))).namedtuples().get().output
|
||||
Filter.update(output=data.quoted).where((Filter.owner == room_id) & ((Filter.id == filter_id) | (Filter.name == filter_id))).execute()
|
||||
case "remove":
|
||||
...
|
||||
case "handle":
|
||||
...
|
||||
case "ignore":
|
||||
...
|
||||
|
||||
register_module(name="Filters", endpoints=[
|
||||
SafeNamespace(names=["filters"], handler=cFilters, quoted=False, arguments={
|
||||
"action": True,
|
||||
}),
|
||||
])
|
||||
|
3
ModWinDog/Filters/Filters.yaml
Executable file
3
ModWinDog/Filters/Filters.yaml
Executable file
@ -0,0 +1,3 @@
|
||||
summary:
|
||||
en: Tools for triggering actions on received messages.
|
||||
|
@ -17,7 +17,7 @@ def cGpt(context:EventContext, data:InputMessageData):
|
||||
output += (completion.choices[0].delta.content or "")
|
||||
return send_message(context, {"text_plain": f"[🤖️ GPT]\n\n{output}"})
|
||||
|
||||
RegisterModule(name="GPT", endpoints=[
|
||||
register_module(name="GPT", endpoints=[
|
||||
SafeNamespace(names=["gpt", "chatgpt"], handler=cGpt, body=True),
|
||||
])
|
||||
|
||||
|
@ -13,7 +13,7 @@ def cHash(context:EventContext, data:InputMessageData):
|
||||
return send_message(context, {
|
||||
"text_html": f"<pre>{html_escape(hashlib.new(algorithm, text_input.encode()).hexdigest())}</pre>"})
|
||||
|
||||
RegisterModule(name="Hashing", group="Geek", endpoints=[
|
||||
register_module(name="Hashing", group="Geek", endpoints=[
|
||||
SafeNamespace(names=["hash"], handler=cHash, body=False, quoted=False, arguments={
|
||||
"algorithm": True,
|
||||
}, help_extra=(lambda endpoint, lang: f'{endpoint.get_string("algorithms", lang)}: <code>{"</code>, <code>".join(hashlib.algorithms_available)}</code>.')),
|
||||
|
@ -25,7 +25,7 @@ def cHelp(context:EventContext, data:InputMessageData) -> None:
|
||||
text = text.strip()
|
||||
return send_message(context, {"text_html": text})
|
||||
|
||||
RegisterModule(name="Help", group="Basic", endpoints=[
|
||||
register_module(name="Help", group="Basic", endpoints=[
|
||||
SafeNamespace(names=["help"], handler=cHelp, arguments={
|
||||
"endpoint": False,
|
||||
}),
|
||||
|
@ -142,7 +142,7 @@ def cSafebooru(context:EventContext, data:InputMessageData):
|
||||
except Exception:
|
||||
return send_status_error(context, language)
|
||||
|
||||
RegisterModule(name="Internet", endpoints=[
|
||||
register_module(name="Internet", endpoints=[
|
||||
SafeNamespace(names=["embedded"], handler=cEmbedded, body=False, quoted=False),
|
||||
SafeNamespace(names=["web"], handler=cWeb, body=True),
|
||||
SafeNamespace(names=["translate"], handler=cTranslate, body=False, quoted=False, arguments={
|
||||
|
@ -21,7 +21,7 @@ def mMultifun(context:EventContext, data:InputMessageData):
|
||||
text = choice(fun_strings["empty"])
|
||||
return send_message(context, {"text_html": text, "ReplyTo": reply_to})
|
||||
|
||||
RegisterModule(name="Multifun", endpoints=[
|
||||
register_module(name="Multifun", endpoints=[
|
||||
SafeNamespace(names=["hug", "pat", "poke", "cuddle", "hands", "floor", "sessocto"], handler=mMultifun),
|
||||
])
|
||||
|
||||
|
@ -15,7 +15,7 @@ def mPercenter(context:EventContext, data:InputMessageData):
|
||||
) or context.endpoint.get_help_text(data.user.settings.language)
|
||||
).format(RandomPercentString(), data.command.body)})
|
||||
|
||||
RegisterModule(name="Percenter", endpoints=[
|
||||
register_module(name="Percenter", endpoints=[
|
||||
SafeNamespace(names=["wish", "level"], handler=mPercenter, body=True),
|
||||
])
|
||||
|
||||
|
@ -123,7 +123,7 @@ def cCraiyonSelenium(context:EventContext, data:InputMessageData):
|
||||
closeSelenium(driver_index, driver)
|
||||
return result
|
||||
|
||||
RegisterModule(name="Scrapers", endpoints=[
|
||||
register_module(name="Scrapers", endpoints=[
|
||||
SafeNamespace(names=["dalle"], handler=cDalleSelenium, body=True),
|
||||
SafeNamespace(names=["craiyon", "crayion"], handler=cCraiyonSelenium, body=True),
|
||||
])
|
||||
|
@ -50,7 +50,7 @@ end)()"""))})
|
||||
except (LuaError, LuaSyntaxError):
|
||||
return send_status_error(context, data.user.settings.language)
|
||||
|
||||
RegisterModule(name="Scripting", group="Geek", endpoints=[
|
||||
register_module(name="Scripting", group="Geek", endpoints=[
|
||||
SafeNamespace(names=["lua"], handler=cLua, body=False, quoted=False),
|
||||
])
|
||||
|
||||
|
@ -8,7 +8,7 @@ def cStart(context:EventContext, data:InputMessageData):
|
||||
text_html=context.endpoint.get_string(
|
||||
"start", data.user.settings.language).format(data.user.name)))
|
||||
|
||||
RegisterModule(name="Start", endpoints=[
|
||||
register_module(name="Start", endpoints=[
|
||||
SafeNamespace(names=["start"], handler=cStart),
|
||||
])
|
||||
|
||||
|
@ -28,12 +28,12 @@ def cExec(context:EventContext, data:InputMessageData):
|
||||
return send_message(context, {"text_html": f'<pre>{html_escape(text)}</pre>'})
|
||||
|
||||
def cRestart(context:EventContext, data:InputMessageData):
|
||||
if (data.user.id not in AdminIds) and (data.user.tag not in AdminIds):
|
||||
if not check_bot_admin(data.user):
|
||||
return send_status(context, 403, data.user.settings.language)
|
||||
open("./.WinDog.Restart.lock", 'w').close()
|
||||
return send_message(context, {"text_plain": "Bot restart queued."})
|
||||
|
||||
RegisterModule(name="System", endpoints=[
|
||||
register_module(name="System", endpoints=[
|
||||
SafeNamespace(names=["exec"], handler=cExec, body=True),
|
||||
SafeNamespace(names=["restart"], handler=cRestart),
|
||||
])
|
||||
|
@ -11,6 +11,7 @@ The officially-hosted instances of this bot are, respectively:
|
||||
* [@WinDogBot](https://t.me/WinDogBot) on Telegram
|
||||
* [@windog:matrix.org](https://matrix.to/#/@windog:matrix.org) on Matrix
|
||||
* [@WinDog@botsin.space](https://botsin.space/@WinDog) on Mastodon (can also be used from any other Fediverse platform)
|
||||
* [WinDog.octt.eu.org](https://windog.octt.eu.org) as a web chat
|
||||
|
||||
In case you want to run your own instance:
|
||||
|
||||
|
56
WinDog.py
56
WinDog.py
@ -127,6 +127,22 @@ def strip_url_scheme(url:str) -> str:
|
||||
tokens = urlparse.urlparse(url)
|
||||
return f"{tokens.netloc}{tokens.path}"
|
||||
|
||||
def parse_command_arguments(command, endpoint, count:int=None):
|
||||
arguments = SafeNamespace()
|
||||
body = command.body
|
||||
index = 1
|
||||
for key in (endpoint.arguments or range(count)):
|
||||
if (not count) and (endpoint.body != None) and (endpoint.arguments[key] == False):
|
||||
continue # skip optional (False) arguments for now if command expects a body, they will be implemented later
|
||||
try:
|
||||
value = command.tokens[index]
|
||||
body = body[len(value):].strip()
|
||||
except IndexError:
|
||||
value = None
|
||||
arguments[str(key)] = value
|
||||
index += 1
|
||||
return [arguments, body]
|
||||
|
||||
def TextCommandData(text:str, platform:str) -> CommandData|None:
|
||||
if not text:
|
||||
return None
|
||||
@ -145,27 +161,17 @@ def TextCommandData(text:str, platform:str) -> CommandData|None:
|
||||
command.body = text[len(command.tokens[0]):].strip()
|
||||
if not (endpoint := obj_get(Endpoints, command.name)):
|
||||
return command # TODO shouldn't this return None?
|
||||
if (endpoint.arguments):
|
||||
command.arguments = SafeNamespace()
|
||||
index = 1
|
||||
for key in endpoint.arguments:
|
||||
if (endpoint.body != None) and (endpoint.arguments[key] == False):
|
||||
continue # skip optional (False) arguments for now if command expects a body, they will be implemented later
|
||||
try:
|
||||
value = command.tokens[index]
|
||||
command.body = command.body[len(value):].strip()
|
||||
except IndexError:
|
||||
value = None
|
||||
command.arguments[key] = value
|
||||
index += 1
|
||||
command.parse_arguments = (lambda count=None: parse_command_arguments(command, endpoint, count))
|
||||
if endpoint.arguments:
|
||||
[command.arguments, command.body] = command.parse_arguments()
|
||||
return command
|
||||
|
||||
def OnInputMessageParsed(data:InputMessageData) -> None:
|
||||
def on_input_message_parsed(data:InputMessageData) -> None:
|
||||
dump_message(data, prefix='> ')
|
||||
handle_bridging(send_message, data, from_sent=False)
|
||||
update_user_db(data.user)
|
||||
|
||||
def OnOutputMessageSent(output_data:OutputMessageData, input_data:InputMessageData, from_sent:bool) -> None:
|
||||
def on_output_message_sent(output_data:OutputMessageData, input_data:InputMessageData, from_sent:bool) -> None:
|
||||
if (not from_sent) and input_data:
|
||||
output_data = ObjectUnion(output_data, {"room": input_data.room})
|
||||
dump_message(output_data, prefix=f'<{"*" if from_sent else " "}')
|
||||
@ -189,6 +195,14 @@ def handle_bridging(method:callable, data:MessageData, from_sent:bool):
|
||||
ObjectUnion(data, {"room": SafeNamespace(id=room_id)}, ({"text_plain": text_plain, "text_markdown": None, "text_html": text_html} if data.user else None)),
|
||||
from_sent=True)
|
||||
|
||||
def check_bot_admin(data:InputMessageData|UserData) -> bool:
|
||||
user = (data.user or data)
|
||||
return ((user.id in AdminIds) or (user.tag in AdminIds))
|
||||
|
||||
# TODO make this real
|
||||
def check_room_admin(data:InputMessageData|UserData) -> bool:
|
||||
return check_bot_admin(data)
|
||||
|
||||
def update_user_db(user:SafeNamespace) -> None:
|
||||
if not (user and user.id):
|
||||
return
|
||||
@ -255,23 +269,23 @@ def send_message(context:EventContext, data:OutputMessageData, *, from_sent:bool
|
||||
if (not context.manager) and (manager := platform.manager_class):
|
||||
context.manager = call_or_return(manager)
|
||||
result = platform.sender(context, data)
|
||||
OnOutputMessageSent(data, context.data, from_sent)
|
||||
on_output_message_sent(data, context.data, from_sent)
|
||||
return result
|
||||
|
||||
def send_notice(context:EventContext, data):
|
||||
pass
|
||||
...
|
||||
|
||||
def edit_message(context:EventContext, data:MessageData):
|
||||
pass
|
||||
...
|
||||
|
||||
def delete_message(context:EventContext, data:MessageData):
|
||||
pass
|
||||
...
|
||||
|
||||
def RegisterPlatform(name:str, main:callable, sender:callable, linker:callable=None, *, event_class=None, manager_class=None, agent_info=None) -> None:
|
||||
def register_platform(name:str, main:callable, sender:callable, linker:callable=None, *, event_class=None, manager_class=None, agent_info=None) -> None:
|
||||
Platforms[name.lower()] = SafeNamespace(name=name, main=main, sender=sender, linker=linker, event_class=event_class, manager_class=manager_class, agent_info=agent_info)
|
||||
app_log(f"{name}, ", inline=True)
|
||||
|
||||
def RegisterModule(name:str, endpoints:dict, *, group:str|None=None) -> None:
|
||||
def register_module(name:str, endpoints:dict, *, group:str|None=None) -> None:
|
||||
module = SafeNamespace(group=group, endpoints=endpoints, get_string=(lambda query, lang=None: None))
|
||||
if isfile(file := f"./ModWinDog/{name}/{name}.yaml"):
|
||||
module.strings = good_yaml_load(open(file, 'r').read())
|
||||
|
18
WinDog.yaml
18
WinDog.yaml
@ -17,7 +17,25 @@ statuses:
|
||||
102:
|
||||
title:
|
||||
en: Processing
|
||||
summary:
|
||||
en: Your request has been accepted and is currently being processed.
|
||||
it: La tua richiesta è stata accolta e sta venendo processata.
|
||||
icon: ⚙️
|
||||
200:
|
||||
title:
|
||||
en: OK
|
||||
summary:
|
||||
en: Your request has completed successfully.
|
||||
it: La tua richiesta è terminata con successo.
|
||||
icon: 👌️
|
||||
201:
|
||||
title:
|
||||
en: Created
|
||||
it: Creato
|
||||
summary:
|
||||
en: The specified resource has been successfully created.
|
||||
it: La risorsa specificata è stata creata con successo.
|
||||
icon: 🪙️
|
||||
403:
|
||||
title:
|
||||
en: Forbidden
|
||||
|
Reference in New Issue
Block a user