misc: Fix general things
This commit is contained in:
parent
6afffe0440
commit
27d1529e6d
2
setup.py
2
setup.py
@ -22,7 +22,7 @@ setup(
|
|||||||
zip_safe = True,
|
zip_safe = True,
|
||||||
entry_points = {
|
entry_points = {
|
||||||
"console_scripts": [
|
"console_scripts": [
|
||||||
"discord-xmpp-bridge = discord_xmpp_bridge.main:main"
|
"xmpp-discord-bridge = xmpp_discord_bridge.main:main"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
import logging
|
import logging
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
|
||||||
from slixmpp.exceptions import IqError
|
from slixmpp.exceptions import IqError
|
||||||
|
|
||||||
class AvatarManager:
|
class AvatarManager:
|
||||||
|
"""
|
||||||
|
The AvatarManager class is responsible for aquiring the XMPP avatars
|
||||||
|
using the means of either XEP-0153 (XEP-0054), XEP-0084 or (in the future)
|
||||||
|
XEP-0292, storing and providing a publicly available URL to those avatars.
|
||||||
|
"""
|
||||||
def __init__(self, xmpp, config):
|
def __init__(self, xmpp, config):
|
||||||
self._xmpp = xmpp
|
self._xmpp = xmpp
|
||||||
self._path = config["avatars"]["path"]
|
self._path = config["avatars"]["path"]
|
||||||
@ -12,7 +19,7 @@ class AvatarManager:
|
|||||||
|
|
||||||
self._logger = logging.getLogger("xmpp.avatar")
|
self._logger = logging.getLogger("xmpp.avatar")
|
||||||
|
|
||||||
def save_avatar(self, jid, data, type_):
|
def _save_avatar(self, jid, data, type_):
|
||||||
filename = hashlib.sha1(data).hexdigest() + "." + type_.split("/")[1]
|
filename = hashlib.sha1(data).hexdigest() + "." + type_.split("/")[1]
|
||||||
path = os.path.join(self._path, filename)
|
path = os.path.join(self._path, filename)
|
||||||
|
|
||||||
@ -31,7 +38,7 @@ class AvatarManager:
|
|||||||
ifrom=self._xmpp._bot_jid_full)
|
ifrom=self._xmpp._bot_jid_full)
|
||||||
type_ = iq["vcard_temp"]["PHOTO"]["TYPE"]
|
type_ = iq["vcard_temp"]["PHOTO"]["TYPE"]
|
||||||
data = iq["vcard_temp"]["PHOTO"]["BINVAL"]
|
data = iq["vcard_temp"]["PHOTO"]["BINVAL"]
|
||||||
self.save_avatar(jid, data, type_)
|
self._save_avatar(jid, data, type_)
|
||||||
return True
|
return True
|
||||||
except IqError:
|
except IqError:
|
||||||
self._logger.debug("Avatar retrieval via XEP-0054/XEP-0153 failed. Probably no vCard for XEP-0054 published")
|
self._logger.debug("Avatar retrieval via XEP-0054/XEP-0153 failed. Probably no vCard for XEP-0054 published")
|
||||||
@ -43,12 +50,17 @@ class AvatarManager:
|
|||||||
node="urn:xmpp:avatar:data",
|
node="urn:xmpp:avatar:data",
|
||||||
max_items=1,
|
max_items=1,
|
||||||
ifrom=self._xmpp._bot_jid_full)
|
ifrom=self._xmpp._bot_jid_full)
|
||||||
|
data = iq["pubsub"]["items"]["substanzas"][0]["data"]
|
||||||
|
self._save_avatar(jid, data, "image/png")
|
||||||
|
return True
|
||||||
except IqError:
|
except IqError:
|
||||||
self._logger.debug("Avatar retrieval via XEP-0084 failed. Probably no avatar published or subscription model not fulfilled.")
|
self._logger.debug("Avatar retrieval via XEP-0084 failed. Probably no avatar published or subscription model not fulfilled.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def aquire_avatar(self, jid):
|
async def aquire_avatar(self, jid):
|
||||||
# First try vCard via 0054/0153
|
"""
|
||||||
|
Attempt to request the avatar of @jid
|
||||||
|
"""
|
||||||
for f in [self.try_xep_0153, self.try_xep_0084]:
|
for f in [self.try_xep_0153, self.try_xep_0084]:
|
||||||
if await f(jid):
|
if await f(jid):
|
||||||
self._logger.debug("Avatar retrieval successful for %s",
|
self._logger.debug("Avatar retrieval successful for %s",
|
||||||
@ -58,5 +70,8 @@ class AvatarManager:
|
|||||||
self._logger.debug("Avatar retrieval failed for %s. Giving up.",
|
self._logger.debug("Avatar retrieval failed for %s. Giving up.",
|
||||||
jid)
|
jid)
|
||||||
|
|
||||||
def get_avatar(self, jid):
|
def get_avatar_url(self, jid):
|
||||||
|
"""
|
||||||
|
Returns either the URL to the avatar of @jid or None.
|
||||||
|
"""
|
||||||
return self._avatars.get(jid, None)
|
return self._avatars.get(jid, None)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
from discord import Status
|
||||||
|
|
||||||
def discord_status_to_xmpp_show(status):
|
def discord_status_to_xmpp_show(status):
|
||||||
return {
|
return {
|
||||||
discord.Status.online: "available",
|
Status.online: "available",
|
||||||
discord.Status.idle: "away",
|
Status.idle: "away",
|
||||||
discord.Status.dnd: "dnd",
|
Status.dnd: "dnd",
|
||||||
discord.Status.do_not_disturb: "dnd",
|
Status.do_not_disturb: "dnd",
|
||||||
discord.Status.invisible: "xa", # TODO: Kinda
|
Status.invisible: "xa", # TODO: Kinda
|
||||||
discord.Status.offline: "unavailable"
|
Status.offline: "unavailable"
|
||||||
}.get(status, "available")
|
}.get(status, "available")
|
||||||
|
@ -16,6 +16,7 @@ from slixmpp.componentxmpp import ComponentXMPP
|
|||||||
from slixmpp.exceptions import XMPPError, IqError
|
from slixmpp.exceptions import XMPPError, IqError
|
||||||
from slixmpp.xmlstream import register_stanza_plugin
|
from slixmpp.xmlstream import register_stanza_plugin
|
||||||
from slixmpp.jid import JID
|
from slixmpp.jid import JID
|
||||||
|
from discord import Status
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from xmpp_discord_bridge.slixmpp.oob import OOBData
|
from xmpp_discord_bridge.slixmpp.oob import OOBData
|
||||||
@ -124,7 +125,7 @@ class BridgeComponent(ComponentXMPP):
|
|||||||
self._virtual_muc_users[muc] = []
|
self._virtual_muc_users[muc] = []
|
||||||
self._virtual_muc_nicks[muc] = {}
|
self._virtual_muc_nicks[muc] = {}
|
||||||
for member in dchannel.members:
|
for member in dchannel.members:
|
||||||
if member.status == discord.Status.offline:
|
if member.status == Status.offline and not self._dont_ignore_offline:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._virtual_muc_users[muc].append(member.display_name)
|
self._virtual_muc_users[muc].append(member.display_name)
|
||||||
@ -208,8 +209,8 @@ class BridgeComponent(ComponentXMPP):
|
|||||||
"username": message["from"].resource
|
"username": message["from"].resource
|
||||||
}
|
}
|
||||||
|
|
||||||
if self._relay_xmpp_avatars and self._avatars.get_avatar(message["from"]):
|
if self._relay_xmpp_avatars and self._avatars.get_avatar_url(message["from"]):
|
||||||
webhook["avatar_url"] = self._avatar.get_avatar(message["from"])
|
webhook["avatar_url"] = self._avatar.get_avatar_url(message["from"])
|
||||||
|
|
||||||
# Look for mentions and replace them
|
# Look for mentions and replace them
|
||||||
guild, channel = self._muc_map[muc]
|
guild, channel = self._muc_map[muc]
|
||||||
@ -230,12 +231,13 @@ class BridgeComponent(ComponentXMPP):
|
|||||||
requests.post(self._webhooks[muc],
|
requests.post(self._webhooks[muc],
|
||||||
data=webhook)
|
data=webhook)
|
||||||
|
|
||||||
def virtual_user_update_presence(self, muc, uid, pshow):
|
def virtual_user_update_presence(self, muc, uid, pshow, pstatus=None):
|
||||||
"""
|
"""
|
||||||
Change the status of a virtual MUC member.
|
Change the status of a virtual MUC member.
|
||||||
NOTE: This assumes that the user is in the MUC
|
NOTE: This assumes that the user is in the MUC
|
||||||
"""
|
"""
|
||||||
self.send_presence(pshow=pshow,
|
self.send_presence(pshow=pshow,
|
||||||
|
pstatus=pstatus,
|
||||||
pto="%s/%s" % (muc, self._virtual_muc_nicks[muc][uid]),
|
pto="%s/%s" % (muc, self._virtual_muc_nicks[muc][uid]),
|
||||||
pfrom=self.spoof_member_jid(uid))
|
pfrom=self.spoof_member_jid(uid))
|
||||||
|
|
||||||
@ -246,7 +248,7 @@ class BridgeComponent(ComponentXMPP):
|
|||||||
|
|
||||||
If update_state_tracking is True, then _virtual_muc_... gets updates.
|
If update_state_tracking is True, then _virtual_muc_... gets updates.
|
||||||
"""
|
"""
|
||||||
if member.status == discord.Status.offline and not self._dont_ignore_offline:
|
if member.status == Status.offline and not self._dont_ignore_offline:
|
||||||
return
|
return
|
||||||
|
|
||||||
if update_state_tracking:
|
if update_state_tracking:
|
||||||
@ -256,13 +258,18 @@ class BridgeComponent(ComponentXMPP):
|
|||||||
# Prevent offline users from getting an unavailable presence by
|
# Prevent offline users from getting an unavailable presence by
|
||||||
# accident
|
# accident
|
||||||
pshow = discord_status_to_xmpp_show(member.status)
|
pshow = discord_status_to_xmpp_show(member.status)
|
||||||
if member.status == discord.Status.offline:
|
pstatus = ""
|
||||||
|
if member.status == Status.offline:
|
||||||
pshow = "xa"
|
pshow = "xa"
|
||||||
|
|
||||||
|
if self._dont_ignore_offline:
|
||||||
|
pstatus = "Offline"
|
||||||
|
|
||||||
self.plugin["xep_0045"].join_muc(muc,
|
self.plugin["xep_0045"].join_muc(muc,
|
||||||
nick=member.display_name,
|
nick=member.display_name,
|
||||||
pfrom=self.spoof_member_jid(member.id),
|
pfrom=self.spoof_member_jid(member.id),
|
||||||
pshow=pshow)
|
pshow=pshow,
|
||||||
|
pstatus=pstatus)
|
||||||
|
|
||||||
async def on_discord_member_join(self, member):
|
async def on_discord_member_join(self, member):
|
||||||
guild = member.guild.id
|
guild = member.guild.id
|
||||||
@ -300,11 +307,12 @@ class BridgeComponent(ComponentXMPP):
|
|||||||
# Handle a status change
|
# Handle a status change
|
||||||
for channel in self._guild_map[guild]:
|
for channel in self._guild_map[guild]:
|
||||||
muc = self._guild_map[guild][channel]
|
muc = self._guild_map[guild][channel]
|
||||||
if after.status == discord.Status.offline:
|
if after.status == Status.offline:
|
||||||
if self._dont_ignore_offline:
|
if self._dont_ignore_offline:
|
||||||
self.virtual_user_update_presence(muc,
|
self.virtual_user_update_presence(muc,
|
||||||
after.id,
|
after.id,
|
||||||
"xa")
|
"xa",
|
||||||
|
"Offline")
|
||||||
else:
|
else:
|
||||||
self._logger.debug("%s went offline. Removing from state tracking.",
|
self._logger.debug("%s went offline. Removing from state tracking.",
|
||||||
after.display_name)
|
after.display_name)
|
||||||
@ -315,7 +323,7 @@ class BridgeComponent(ComponentXMPP):
|
|||||||
# Remove from all state tracking
|
# Remove from all state tracking
|
||||||
self._virtual_muc_users[muc].remove(after.display_name)
|
self._virtual_muc_users[muc].remove(after.display_name)
|
||||||
del self._virtual_muc_nicks[muc][after.id]
|
del self._virtual_muc_nicks[muc][after.id]
|
||||||
elif before.status == discord.Status.offline and after.status != discord.Status.offline:
|
elif before.status == Status.offline and after.status != Status.offline and not self._dont_ignore_offline:
|
||||||
self.virtual_user_join_muc(muc, after, update_state_tracking=True)
|
self.virtual_user_join_muc(muc, after, update_state_tracking=True)
|
||||||
else:
|
else:
|
||||||
self.virtual_user_update_presence(muc,
|
self.virtual_user_update_presence(muc,
|
||||||
@ -425,7 +433,7 @@ class BridgeComponent(ComponentXMPP):
|
|||||||
self._real_muc_users[muc].append(resource)
|
self._real_muc_users[muc].append(resource)
|
||||||
|
|
||||||
async def on_session_start(self, event):
|
async def on_session_start(self, event):
|
||||||
self._discord = DiscordClient(self, config)
|
self._discord = DiscordClient(self, self._config)
|
||||||
asyncio.ensure_future(self._discord.start(self._token))
|
asyncio.ensure_future(self._discord.start(self._token))
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@ -441,7 +449,7 @@ def main():
|
|||||||
"-d", "--debug", dest="debug", help="Enable debug logging", action="store_true"
|
"-d", "--debug", dest="debug", help="Enable debug logging", action="store_true"
|
||||||
)
|
)
|
||||||
|
|
||||||
(option, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
verbosity = logging.DEBUG if options.debug else logging.INFO
|
verbosity = logging.DEBUG if options.debug else logging.INFO
|
||||||
|
|
||||||
general = config["general"]
|
general = config["general"]
|
||||||
|
Loading…
Reference in New Issue
Block a user