Big ass update
This commit is contained in:
@@ -3,6 +3,9 @@ import asyncio
|
||||
import slixmpp
|
||||
from slixmpp.componentxmpp import ComponentXMPP
|
||||
from slixmpp.types import PresenceArgs
|
||||
import slixmpp.stanza
|
||||
import slixmpp.plugins.xep_0084.stanza
|
||||
import base64, time
|
||||
|
||||
class GatewayXMPP(ComponentXMPP):
|
||||
def __init__(self, plexus, settings, gateway_name, gateway_data):
|
||||
@@ -29,6 +32,9 @@ class GatewayXMPP(ComponentXMPP):
|
||||
|
||||
self.xdm_id_to_origin_id = {}
|
||||
self.origin_id_to_xdm_id = {}
|
||||
|
||||
# Native user avatars
|
||||
self.avatar_cache = {}
|
||||
|
||||
self.xmpp_ready = False
|
||||
|
||||
@@ -36,15 +42,18 @@ class GatewayXMPP(ComponentXMPP):
|
||||
self.add_event_handler("groupchat_message", self.message)
|
||||
self.add_event_handler("groupchat_presence", self.groupchat_presence)
|
||||
self.register_handler(slixmpp.xmlstream.handler.Callback("nickname_conflict", slixmpp.xmlstream.matcher.StanzaPath("presence"), self.nickname_conflict))
|
||||
self.register_handler(slixmpp.xmlstream.handler.Callback("nickname_conflict", slixmpp.xmlstream.matcher.StanzaPath("iq"), self.iq_funker))
|
||||
|
||||
self.register_plugin('xep_0030') # Service Discovery
|
||||
self.register_plugin('xep_0004') # Data Forms
|
||||
self.register_plugin('xep_0060') # PubSub
|
||||
self.register_plugin('xep_0163') # PEP
|
||||
self.register_plugin('xep_0199') # XMPP Ping
|
||||
self.register_plugin('xep_0045') # MUC
|
||||
self.register_plugin('xep_0359') # Stanza IDs
|
||||
self.register_plugin('xep_0308') # Message correction
|
||||
self.register_plugin('xep_0424') # Message retraction
|
||||
self.register_plugin('xep_0084') # user avatar
|
||||
|
||||
def new_user(identification, nick_name):
|
||||
if identification[0] == "xmpp" and identification[1] == self.gateway_name:
|
||||
@@ -59,12 +68,14 @@ class GatewayXMPP(ComponentXMPP):
|
||||
"nicknames": {muc_jid: {"state": "joining", "nick": nick_name} for muc_jid in self.relevant_mucs},
|
||||
|
||||
# Messages are added and executed as separate steps
|
||||
"queue": []
|
||||
"queue": [],
|
||||
|
||||
"avatar": {"state": "ready", "desired": None, "timeout": 0}
|
||||
}
|
||||
self.my_puppets[identification] = puppet_data
|
||||
PLEXUS.sub("new_user", new_user)
|
||||
|
||||
def message(msg_unique_id, room_name, nick_name, gateway_type, gateway_name, unique_id, body, attachments, was_edit):
|
||||
def message(msg_unique_id, room_name, nick_name, avatar, gateway_type, gateway_name, unique_id, body, attachments, was_edit):
|
||||
if gateway_type == "xmpp" and gateway_name == self.gateway_name:
|
||||
# Ignore ours
|
||||
return
|
||||
@@ -75,6 +86,11 @@ class GatewayXMPP(ComponentXMPP):
|
||||
if len(attachments):
|
||||
body = str(body) + "\n\n" + "\n".join([str(a) for a in attachments])
|
||||
|
||||
if avatar and (puppet_data["avatar"]["desired"] is None):
|
||||
puppet_data["avatar"]["desired"] = avatar
|
||||
puppet_data["avatar"]["state"] = "waiting"
|
||||
puppet_data["avatar"]["timeout"] = time.time_ns()
|
||||
|
||||
def queue_callback():
|
||||
kwargs = {
|
||||
"mto": muc_jid, "mbody": body, "mtype": "groupchat", "mfrom": puppet_data["jid"]
|
||||
@@ -93,9 +109,16 @@ class GatewayXMPP(ComponentXMPP):
|
||||
self.origin_id_to_xdm_id[msg_unique_id.hex()] = msg_unique_id
|
||||
xmpp_msg["origin_id"]["id"] = msg_unique_id.hex()
|
||||
|
||||
print(xmpp_msg)
|
||||
xmpp_msg.send()
|
||||
puppet_data["queue"].append(queue_callback)
|
||||
|
||||
# If the user changed their nickname, try to update it on the puppet
|
||||
if nick_name != puppet_data["nicknames"][muc_jid]["nick"]:
|
||||
assert puppet_data["nicknames"][muc_jid]["state"] == "joined"
|
||||
puppet_data["nicknames"][muc_jid]["state"] = "joining"
|
||||
puppet_data["nicknames"][muc_jid]["nick"] = nick_name
|
||||
|
||||
|
||||
PLEXUS.sub("message", message)
|
||||
|
||||
def message_delete(msg_unique_id, room_name, gateway_type, gateway_name, unique_id):
|
||||
@@ -124,18 +147,27 @@ class GatewayXMPP(ComponentXMPP):
|
||||
# sure they've successfully reserved a nickname in each room.
|
||||
# If a puppet has not successfully joined all rooms, messages are
|
||||
# stored in a queue before being sent.
|
||||
|
||||
def is_puppet_ready(self, puppet_data):
|
||||
return puppet_data["avatar"]["state"] == "ready" and all([nn["state"] == "joined" for nn in puppet_data["nicknames"].values()])
|
||||
|
||||
async def step_puppets(self):
|
||||
while True:
|
||||
for puppet_data in self.my_puppets.values():
|
||||
puppet_jid = puppet_data["jid"]
|
||||
|
||||
if all([nn["state"] == "joined" for nn in puppet_data["nicknames"].values()]):
|
||||
# We are good for doing stuff
|
||||
if len(puppet_data["queue"]):
|
||||
if self.is_puppet_ready(puppet_data):
|
||||
if len(puppet_data["queue"]) > 0:
|
||||
cb = puppet_data["queue"].pop(0)
|
||||
cb()
|
||||
else:
|
||||
# We are still looking for nicknames
|
||||
# We are still looking for nicknames OR trying to setup an avatar
|
||||
|
||||
if puppet_data["avatar"]["state"] == "waiting" and time.time_ns() >= puppet_data["avatar"]["timeout"]:
|
||||
pass
|
||||
|
||||
puppet_data["avatar"]["state"] = "ready"
|
||||
|
||||
for muc_jid, nn in puppet_data["nicknames"].items():
|
||||
if nn["state"] == "failed":
|
||||
nn["nick"] = nn["nick"] + " (real)"
|
||||
@@ -175,7 +207,7 @@ class GatewayXMPP(ComponentXMPP):
|
||||
return
|
||||
|
||||
msg_unique_id = self.base_id_to_xdm_id[msg["replace"]["id"]]
|
||||
PLEXUS.pub("message", msg_unique_id, self.muc_to_room_name[msg["from"].bare], f"{msg['from'].resource}", "xmpp", self.gateway_name, (msg["from"].bare, msg["from"].resource), msg["body"], [], True)
|
||||
PLEXUS.pub("message", msg_unique_id, self.muc_to_room_name[msg["from"].bare], f"{msg['from'].resource}", self.avatar_cache[msg["from"].full], "xmpp", self.gateway_name, (msg["from"].bare, msg["from"].resource), msg["body"], [], True)
|
||||
|
||||
return
|
||||
|
||||
@@ -187,7 +219,10 @@ class GatewayXMPP(ComponentXMPP):
|
||||
self.xdm_id_to_stanza_id[msg_unique_id] = msg["stanza_id"]["id"]
|
||||
self.stanza_id_to_xdm_id[msg["stanza_id"]["id"]] = msg_unique_id
|
||||
|
||||
PLEXUS.pub("message", msg_unique_id, self.muc_to_room_name[msg["from"].bare], f"{msg['from'].resource}", "xmpp", self.gateway_name, (msg["from"].bare, msg["from"].resource), msg["body"], [], False)
|
||||
PLEXUS.pub("message", msg_unique_id, self.muc_to_room_name[msg["from"].bare], f"{msg['from'].resource}", self.avatar_cache[msg["from"].full], "xmpp", self.gateway_name, (msg["from"].bare, msg["from"].resource), msg["body"], [], False)
|
||||
|
||||
if msg["from"].full not in self.avatar_cache:
|
||||
# First try loading avatar before sending message
|
||||
|
||||
def groupchat_presence(self, presence):
|
||||
if presence["from"].bare not in self.relevant_mucs:
|
||||
@@ -197,14 +232,26 @@ class GatewayXMPP(ComponentXMPP):
|
||||
if item_stanza is not None:
|
||||
jid = item_stanza.attrib.get("jid")
|
||||
if jid and re.match(re.compile(f".*?@{re.escape(self.pfrom)}/mirror"), jid):
|
||||
# Ignore ours
|
||||
return
|
||||
if presence["to"] != self.pfrom:
|
||||
return
|
||||
if presence["from"].resource == self.relevant_mucs[presence["from"].bare]["nick"]:
|
||||
return
|
||||
|
||||
self.avatar_cache[presence["from"].full] = None
|
||||
|
||||
def got_avatar(stanza):
|
||||
data = stanza.xml.find(".//{urn:xmpp:avatar:data}data")
|
||||
if data is not None:
|
||||
self.avatar_cache[presence["from"].full] = base64.standard_b64decode("".join(data.itertext()))
|
||||
self.plugin["xep_0060"].get_items(jid = presence["from"].full, node = "urn:xmpp:avatar:data", ifrom = self.pfrom, callback = got_avatar, max_items = 1)
|
||||
|
||||
PLEXUS.pub("new_user", ("xmpp", self.gateway_name, (presence["from"].bare, presence["from"].resource)), presence["from"].resource)
|
||||
|
||||
def iq_funker(self, iq):
|
||||
print("GOT IQ", iq)
|
||||
|
||||
def nickname_conflict(self, presence):
|
||||
# FAILURE CASE:
|
||||
# <presence id="75220a58e9d74eb08c6945752bdec1ef" to="-0x6f6c50dd4094cb51@bridge.underware.dev/mirror" from="bridge-testing@muc.underware.dev/mid" type="error">
|
||||
|
||||
Reference in New Issue
Block a user