forked from sch/Slixfeed
Improve groupchat functions to handle with erroneous cases
This commit is contained in:
parent
5c2ee8d51c
commit
c8cd5e1b09
8 changed files with 149 additions and 76 deletions
|
@ -113,6 +113,7 @@ class JabberComponent:
|
|||
xmpp.register_plugin('xep_0084') # User Avatar
|
||||
xmpp.register_plugin('xep_0085') # Chat State Notifications
|
||||
xmpp.register_plugin('xep_0115') # Entity Capabilities
|
||||
xmpp.register_plugin('xep_0122') # Data Forms Validation
|
||||
xmpp.register_plugin('xep_0153') # vCard-Based Avatars
|
||||
xmpp.register_plugin('xep_0199', {'keepalive': True}) # XMPP Ping
|
||||
xmpp.register_plugin('xep_0249') # Direct MUC Invitations
|
||||
|
@ -127,7 +128,6 @@ class JabberClient:
|
|||
def __init__(self, jid, password, hostname=None, port=None, alias=None):
|
||||
xmpp = Slixfeed(jid, password, hostname, port, alias)
|
||||
xmpp.register_plugin('xep_0004') # Data Forms
|
||||
xmpp.register_plugin('xep_0122') # Data Forms Validation
|
||||
xmpp.register_plugin('xep_0030') # Service Discovery
|
||||
xmpp.register_plugin('xep_0045') # Multi-User Chat
|
||||
xmpp.register_plugin('xep_0048') # Bookmarks
|
||||
|
@ -140,6 +140,7 @@ class JabberClient:
|
|||
xmpp.register_plugin('xep_0084') # User Avatar
|
||||
xmpp.register_plugin('xep_0085') # Chat State Notifications
|
||||
xmpp.register_plugin('xep_0115') # Entity Capabilities
|
||||
xmpp.register_plugin('xep_0122') # Data Forms Validation
|
||||
xmpp.register_plugin('xep_0153') # vCard-Based Avatars
|
||||
xmpp.register_plugin('xep_0199', {'keepalive': True}) # XMPP Ping
|
||||
xmpp.register_plugin('xep_0249') # Direct MUC Invitations
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
about = """
|
||||
Slixfeed
|
||||
A Syndication bot for the XMPP communication network.
|
||||
Slixfeed is a news broker bot for syndicated news which aims to be \
|
||||
an easy to use and fully-featured news aggregator bot.
|
||||
|
||||
Slixfeed is a news broker which aims to be an easy to use and fully-\
|
||||
featured news aggregator bot. It provides a convenient access to \
|
||||
Blogs, News websites and even Fediverse instances, along with \
|
||||
filtering functionality.
|
||||
Slixfeed is primarily designed for XMPP (aka Jabber). \
|
||||
Visit https://xmpp.org/software/ for more information.
|
||||
Slixfeed provides a convenient access to Blogs, News websites and \
|
||||
even Fediverse instances, along with filtering and other privacy \
|
||||
driven functionalities.
|
||||
|
||||
Slixfeed is designed primarily for the XMPP communication network \
|
||||
(aka Jabber). Visit https://xmpp.org/software/ for more information.
|
||||
|
||||
https://gitgud.io/sjehuda/slixfeed
|
||||
"""
|
||||
|
||||
authors = """
|
||||
|
@ -58,7 +60,8 @@ No operator was specified for this instance.
|
|||
|
||||
platforms = """
|
||||
Supported platforms: XMPP
|
||||
Platforms to be added in future: ActivityPub, Briar, Email, IRC, LXMF, Matrix, MQTT, Nostr, Session, Tox.
|
||||
Platforms to be added in future: ActivityPub, Briar, Email, IRC, LXMF, \
|
||||
Matrix, MQTT, Nostr, Session, Tox.
|
||||
For ideal experience, we recommend using XMPP.
|
||||
"""
|
||||
|
||||
|
@ -86,6 +89,24 @@ XMPP
|
|||
https://xmpp.org/about/
|
||||
"""
|
||||
|
||||
sleekxmpp = """
|
||||
SleekXMPP is an MIT licensed XMPP library for Python 2.6/3.1+, and is featured \
|
||||
in examples in the book XMPP: The Definitive Guide by Kevin Smith, Remko Tronçon, \
|
||||
and Peter Saint-Andre.
|
||||
|
||||
https://codeberg.org/fritzy/SleekXMPP
|
||||
"""
|
||||
|
||||
slixmpp = """
|
||||
Slixmpp is an MIT licensed XMPP library for Python 3.7+. It is a fork of SleekXMPP.
|
||||
|
||||
Slixmpp's goals is to only rewrite the core of the SleekXMPP library \
|
||||
(the low level socket handling, the timers, the events dispatching) \
|
||||
in order to remove all threads.
|
||||
|
||||
https://codeberg.org/poezio/slixmpp
|
||||
"""
|
||||
|
||||
terms = """
|
||||
Slixfeed is free software; you can redistribute it and/or \
|
||||
modify it under the terms of the MIT License.
|
||||
|
@ -129,6 +150,7 @@ Raphael Groner (Fedora, Germany); \
|
|||
Remko Tronçon <mko.re> (Psi , Belgium); \
|
||||
Simone "roughnecks" Canaletti <woodpeckersnest.space> (Italy); \
|
||||
Richard Lapointe (SalixOS, Connecticut); \
|
||||
Stephen Paul Weber <singpolyma.net>; \
|
||||
Strix from Loqi; \
|
||||
Thibaud Guerin (SalixOS); \
|
||||
Thorsten Fröhlich (France); \
|
||||
|
@ -144,6 +166,5 @@ chat, voice and video calls, collaboration, lightweight \
|
|||
middleware, content syndication, and generalized routing of XML \
|
||||
data.
|
||||
|
||||
Visit https://xmpp.org/about/ for more information on the XMPP \
|
||||
protocol.
|
||||
https://xmpp.org/about/
|
||||
"""
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
__version__ = '0.1.6'
|
||||
__version_info__ = (0, 1, 6)
|
||||
__version__ = '0.1.7'
|
||||
__version_info__ = (0, 1, 7)
|
||||
|
|
|
@ -44,6 +44,8 @@ class XmppBookmark:
|
|||
groupchats.extend([conference])
|
||||
if properties:
|
||||
properties['jid'] = properties['room'] + '@' + properties['host']
|
||||
if not properties['alias']: properties['alias'] = self.alias
|
||||
|
||||
else:
|
||||
properties = {
|
||||
'jid' : jid,
|
||||
|
|
|
@ -167,7 +167,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
inviter = message['from'].bare
|
||||
muc_jid = message['groupchat_invite']['jid']
|
||||
await XmppBookmark.add(self, muc_jid)
|
||||
await XmppGroupchat.join(self, inviter, muc_jid)
|
||||
XmppGroupchat.join(self, inviter, muc_jid)
|
||||
message_body = ('Greetings! I am {}, the news anchor.\n'
|
||||
'My job is to bring you the latest '
|
||||
'news from sources you provide me with.\n'
|
||||
|
@ -181,7 +181,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
inviter = message['from'].bare
|
||||
muc_jid = message['groupchat_invite']['jid']
|
||||
await XmppBookmark.add(self, muc_jid)
|
||||
await XmppGroupchat.join(self, inviter, muc_jid)
|
||||
XmppGroupchat.join(self, inviter, muc_jid)
|
||||
message_body = ('Greetings! I am {}, the news anchor.\n'
|
||||
'My job is to bring you the latest '
|
||||
'news from sources you provide me with.\n'
|
||||
|
@ -207,22 +207,23 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
self.service_reactions()
|
||||
await self['xep_0115'].update_caps()
|
||||
await self.get_roster()
|
||||
await XmppGroupchat.autojoin(self)
|
||||
await profile.update(self)
|
||||
task.task_ping(self)
|
||||
bookmarks = await self.plugin['xep_0048'].get_bookmarks()
|
||||
XmppGroupchat.autojoin(self, bookmarks)
|
||||
|
||||
# Service.commands(self)
|
||||
# Service.reactions(self)
|
||||
|
||||
|
||||
|
||||
async def on_session_resumed(self, event):
|
||||
def on_session_resumed(self, event):
|
||||
# self.send_presence()
|
||||
profile.set_identity(self, 'client')
|
||||
# self.service_commands()
|
||||
# self.service_reactions()
|
||||
self['xep_0115'].update_caps()
|
||||
await XmppGroupchat.autojoin(self)
|
||||
XmppGroupchat.autojoin(self)
|
||||
|
||||
# Service.commands(self)
|
||||
# Service.reactions(self)
|
||||
|
@ -358,7 +359,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
return
|
||||
if message['type'] in ('chat', 'normal'):
|
||||
# NOTE: Required for Cheogram
|
||||
await self['xep_0115'].update_caps(jid=jid)
|
||||
# await self['xep_0115'].update_caps(jid=jid)
|
||||
# self.send_presence(pto=jid)
|
||||
# task.clean_tasks_xmpp(self, jid, ['status'])
|
||||
await asyncio.sleep(5)
|
||||
|
@ -369,7 +370,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
if message['type'] in ('chat', 'normal'):
|
||||
jid = message['from'].bare
|
||||
# NOTE: Required for Cheogram
|
||||
await self['xep_0115'].update_caps(jid=jid)
|
||||
# await self['xep_0115'].update_caps(jid=jid)
|
||||
# self.send_presence(pto=jid)
|
||||
# task.clean_tasks_xmpp(self, jid, ['status'])
|
||||
await asyncio.sleep(5)
|
||||
|
@ -466,36 +467,42 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
# )
|
||||
|
||||
# if jid == config.get_value('accounts', 'XMPP', 'operator'):
|
||||
self['xep_0050'].add_command(node='settings',
|
||||
name='📮️ Edit settings',
|
||||
handler=self._handle_settings)
|
||||
self['xep_0050'].add_command(node='filters',
|
||||
name='🕸️ Manage filters',
|
||||
handler=self._handle_filters)
|
||||
self['xep_0050'].add_command(node='bookmarks',
|
||||
name='📔️ Organize bookmarks - Restricted',
|
||||
handler=self._handle_bookmarks)
|
||||
self['xep_0050'].add_command(node='roster',
|
||||
name='🧾️ Organize roster - Restricted',
|
||||
handler=self._handle_roster)
|
||||
self['xep_0050'].add_command(node='subscriptions',
|
||||
name='📰️ Subscriptions - All',
|
||||
name='📰️ Subscriptions',
|
||||
handler=self._handle_subscriptions)
|
||||
self['xep_0050'].add_command(node='subscriptions_cat',
|
||||
name='🔖️ Subscriptions - Categories',
|
||||
name='🔖️ Categories',
|
||||
handler=self._handle_subscription)
|
||||
self['xep_0050'].add_command(node='subscriptions_tag',
|
||||
name='🏷️ Subscriptions - Tags',
|
||||
name='🏷️ Tags',
|
||||
handler=self._handle_subscription)
|
||||
self['xep_0050'].add_command(node='subscriptions_index',
|
||||
name='📑️ Subscriptions - Indexed',
|
||||
name='📑️ Index (A - Z)',
|
||||
handler=self._handle_subscription)
|
||||
self['xep_0050'].add_command(node='credit',
|
||||
name='💡️ Credit',
|
||||
handler=self._handle_credit)
|
||||
self['xep_0050'].add_command(node='settings',
|
||||
name='📮️ Settings',
|
||||
handler=self._handle_settings)
|
||||
self['xep_0050'].add_command(node='filters',
|
||||
name='🛡️ Filters',
|
||||
handler=self._handle_filters)
|
||||
self['xep_0050'].add_command(node='bookmarks',
|
||||
name='📕 Bookmarks',
|
||||
handler=self._handle_bookmarks)
|
||||
self['xep_0050'].add_command(node='roster',
|
||||
name='📓 Roster', # 📋
|
||||
handler=self._handle_roster)
|
||||
self['xep_0050'].add_command(node='help',
|
||||
name='🛟️ Help',
|
||||
name='📔️ Manual',
|
||||
handler=self._handle_help)
|
||||
self['xep_0050'].add_command(node='motd',
|
||||
name='🗓️ MOTD',
|
||||
handler=self._handle_motd)
|
||||
self['xep_0050'].add_command(node='credit',
|
||||
name='Credits', # 💡️
|
||||
handler=self._handle_credit)
|
||||
self['xep_0050'].add_command(node='about',
|
||||
name='About', # 📜️
|
||||
handler=self._handle_about)
|
||||
# self['xep_0050'].add_command(node='search',
|
||||
# name='Search',
|
||||
# handler=self._handle_search)
|
||||
|
@ -547,7 +554,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
|
||||
jid = session['from'].bare
|
||||
form = self['xep_0004'].make_form('form', 'Filters for {}'.format(jid))
|
||||
form['instructions'] = ('🛡️ Filters have been updated')
|
||||
form['instructions'] = ('✅️ Filters have been updated')
|
||||
jid_file = jid
|
||||
db_file = config.get_pathname_to_database(jid_file)
|
||||
# In this case (as is typical), the payload is a form
|
||||
|
@ -769,18 +776,55 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
pass
|
||||
|
||||
|
||||
async def _handle_about(self, iq, session):
|
||||
import slixfeed.action as action
|
||||
# form = self['xep_0004'].make_form('result', 'Thanks')
|
||||
# form['instructions'] = action.manual('information.toml', 'thanks')
|
||||
# session['payload'] = form
|
||||
# text = '💡️ About Slixfeed, slixmpp and XMPP\n\n'
|
||||
# text += '\n\n'
|
||||
# form = self['xep_0004'].make_form('result', 'About')
|
||||
text = 'Slixfeed\n\n'
|
||||
text += ''.join(action.manual('information.toml', 'about'))
|
||||
text += '\n\n'
|
||||
text += 'Slixmpp\n\n'
|
||||
text += ''.join(action.manual('information.toml', 'slixmpp'))
|
||||
text += '\n\n'
|
||||
text += 'SleekXMPP\n\n'
|
||||
text += ''.join(action.manual('information.toml', 'sleekxmpp'))
|
||||
text += '\n\n'
|
||||
text += 'XMPP\n\n'
|
||||
text += ''.join(action.manual('information.toml', 'xmpp'))
|
||||
session['notes'] = [['info', text]]
|
||||
# form.add_field(var='about',
|
||||
# ftype='text-multi',
|
||||
# label='About',
|
||||
# value=text)
|
||||
# session['payload'] = form
|
||||
return session
|
||||
|
||||
|
||||
async def _handle_motd(self, iq, session):
|
||||
# TODO add functionality to attach image.
|
||||
text = ('Here you can add groupchat rules,post schedule, tasks or '
|
||||
'anything elaborated you might deem fit. Good luck!')
|
||||
session['notes'] = [['info', text]]
|
||||
return session
|
||||
|
||||
|
||||
async def _handle_credit(self, iq, session):
|
||||
import slixfeed.action as action
|
||||
# form = self['xep_0004'].make_form('result', 'Thanks')
|
||||
# form['instructions'] = action.manual('information.toml', 'thanks')
|
||||
# session['payload'] = form
|
||||
text = '💡️ We are Jabber\n\n'
|
||||
text = '💡️ We are XMPP\n\n'
|
||||
fren = action.manual('information.toml', 'thanks')
|
||||
fren = "".join(fren)
|
||||
fren = fren.split(';')
|
||||
fren = "\n".join(fren)
|
||||
text += fren
|
||||
text += '\n\nYOU!\n\n🫵️\n\n- Join us -\n\n🤝️'
|
||||
# text += '\n\nYOU!\n\n🫵️\n\n- Join us -\n\n🤝️'
|
||||
text += '\n\nYOU!\n\n🫵️\n\n- Join us -'
|
||||
session['notes'] = [['info', text]]
|
||||
return session
|
||||
|
||||
|
@ -819,8 +863,6 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
ftype='text-multi',
|
||||
label=key,
|
||||
value=value)
|
||||
|
||||
|
||||
session['payload'] = form
|
||||
return session
|
||||
|
||||
|
@ -864,7 +906,8 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
form.addField(var='name',
|
||||
ftype='text-single',
|
||||
label='Name',
|
||||
value=properties['name'])
|
||||
value=properties['name'],
|
||||
required=True)
|
||||
form.addField(var='room',
|
||||
ftype='text-single',
|
||||
label='Room',
|
||||
|
@ -878,7 +921,8 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
form.addField(var='alias',
|
||||
ftype='text-single',
|
||||
label='Alias',
|
||||
value=properties['nick'])
|
||||
value=properties['nick'],
|
||||
required=True)
|
||||
form.addField(var='password',
|
||||
ftype='text-private',
|
||||
label='Password',
|
||||
|
@ -920,13 +964,14 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
"""
|
||||
|
||||
form = self['xep_0004'].make_form('result', 'Bookmarks')
|
||||
form['instructions'] = ('🛡️ Bookmark has been saved')
|
||||
form['instructions'] = ('✅️ Bookmark has been saved')
|
||||
# In this case (as is typical), the payload is a form
|
||||
values = payload['values']
|
||||
await XmppBookmark.add(self, properties=values)
|
||||
for value in values:
|
||||
key = str(value)
|
||||
val = str(values[value])
|
||||
if not val: val = 'None' # '(empty)'
|
||||
form.add_field(var=key,
|
||||
ftype='text-single',
|
||||
label=key.capitalize(),
|
||||
|
@ -1067,7 +1112,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
|||
jid = session['from'].bare
|
||||
form = self['xep_0004'].make_form('form',
|
||||
'Settings for {}'.format(jid))
|
||||
form['instructions'] = ('🛡️ Settings have been saved')
|
||||
form['instructions'] = ('✅️ Settings have been saved')
|
||||
|
||||
jid_file = jid
|
||||
db_file = config.get_pathname_to_database(jid_file)
|
||||
|
|
|
@ -27,21 +27,22 @@ class XmppGroupchat:
|
|||
# jid = message['groupchat_invite']['jid']
|
||||
# else:
|
||||
# jid = message
|
||||
async def accept_invitation(self, message):
|
||||
def accept_invitation(self, message):
|
||||
# operator muc_chat
|
||||
inviter = message["from"].bare
|
||||
muc_jid = message['groupchat_invite']['jid']
|
||||
await self.join(self, inviter, muc_jid)
|
||||
jid = message['groupchat_invite']['jid']
|
||||
self.join(self, inviter, jid)
|
||||
|
||||
|
||||
async def autojoin(self):
|
||||
result = await self.plugin['xep_0048'].get_bookmarks()
|
||||
bookmarks = result["private"]["bookmarks"]
|
||||
conferences = bookmarks["conferences"]
|
||||
def autojoin(self, bookmarks):
|
||||
conferences = bookmarks["private"]["bookmarks"]["conferences"]
|
||||
for conference in conferences:
|
||||
if conference["autojoin"]:
|
||||
muc_jid = conference["jid"]
|
||||
self.plugin['xep_0045'].join_muc(muc_jid,
|
||||
if conference["jid"] and conference["autojoin"]:
|
||||
if not conference["nick"]:
|
||||
conference["nick"] = self.alias
|
||||
logging.error('Alias (i.e. Nicknname) is missing for '
|
||||
'bookmark {}'.format(conference['name']))
|
||||
self.plugin['xep_0045'].join_muc(conference["jid"],
|
||||
conference["nick"],
|
||||
# If a room password is needed, use:
|
||||
# password=the_room_password,
|
||||
|
@ -51,11 +52,14 @@ class XmppGroupchat:
|
|||
'JID : {}\n'
|
||||
'Alias : {}\n'
|
||||
.format(conference["name"],
|
||||
muc_jid,
|
||||
conference["jid"],
|
||||
conference["nick"]))
|
||||
elif not conference["jid"]:
|
||||
logging.error('JID is missing for bookmark {}'
|
||||
.format(conference['name']))
|
||||
|
||||
|
||||
async def join(self, inviter, muc_jid):
|
||||
def join(self, inviter, jid):
|
||||
# token = await initdb(
|
||||
# muc_jid,
|
||||
# get_settings_value,
|
||||
|
@ -78,27 +82,26 @@ class XmppGroupchat:
|
|||
logging.info('Joining groupchat\n'
|
||||
'JID : {}\n'
|
||||
'Inviter : {}\n'
|
||||
.format(muc_jid, inviter))
|
||||
self.plugin['xep_0045'].join_muc(muc_jid,
|
||||
.format(jid, inviter))
|
||||
self.plugin['xep_0045'].join_muc(jid,
|
||||
self.alias,
|
||||
# If a room password is needed, use:
|
||||
# password=the_room_password,
|
||||
)
|
||||
|
||||
|
||||
async def leave(self, muc_jid):
|
||||
jid = self.boundjid.bare
|
||||
def leave(self, jid):
|
||||
message = ('This news bot will now leave this groupchat.\n'
|
||||
'The JID of this news bot is xmpp:{}?message'
|
||||
.format(jid))
|
||||
.format(self.boundjid.bare))
|
||||
status_message = ('This bot has left the group. '
|
||||
'It can be reached directly via {}'
|
||||
.format(jid))
|
||||
self.send_message(mto=muc_jid,
|
||||
mfrom=self.boundjid.bare,
|
||||
.format(self.boundjid.bare))
|
||||
self.send_message(mto=jid,
|
||||
mfrom=self.boundjid,
|
||||
mbody=message,
|
||||
mtype='groupchat')
|
||||
self.plugin['xep_0045'].leave_muc(muc_jid,
|
||||
self.plugin['xep_0045'].leave_muc(jid,
|
||||
self.alias,
|
||||
status_message,
|
||||
self.boundjid.bare)
|
||||
self.boundjid)
|
||||
|
|
|
@ -17,8 +17,9 @@ class XmppPresence:
|
|||
|
||||
|
||||
def send(self, jid, status_message, presence_type=None, status_type=None):
|
||||
jid_from = str(self.boundjid) if self.is_component else None
|
||||
self.send_presence(pto=jid,
|
||||
pfrom=self.boundjid,
|
||||
pfrom=jid_from,
|
||||
pshow=status_type,
|
||||
pstatus=status_message,
|
||||
ptype=presence_type)
|
||||
|
|
|
@ -565,7 +565,7 @@ async def message(self, message):
|
|||
XmppMessage.send_reply(self, message, response)
|
||||
case 'goodbye':
|
||||
if message['type'] == 'groupchat':
|
||||
await XmppGroupchat.leave(self, jid)
|
||||
XmppGroupchat.leave(self, jid)
|
||||
await XmppBookmark.remove(self, jid)
|
||||
else:
|
||||
response = 'This command is valid in groupchat only.'
|
||||
|
@ -585,7 +585,7 @@ async def message(self, message):
|
|||
muc_jid = uri.check_xmpp_uri(message_text[5:])
|
||||
if muc_jid:
|
||||
# TODO probe JID and confirm it's a groupchat
|
||||
await XmppGroupchat.join(self, jid, muc_jid)
|
||||
XmppGroupchat.join(self, jid, muc_jid)
|
||||
# await XmppBookmark.add(self, jid=muc_jid)
|
||||
response = ('Joined groupchat {}'
|
||||
.format(message_text))
|
||||
|
@ -923,7 +923,7 @@ async def message(self, message):
|
|||
muc_jid = uri.check_xmpp_uri(message_text)
|
||||
if muc_jid:
|
||||
# TODO probe JID and confirm it's a groupchat
|
||||
await XmppGroupchat.join(self, jid, muc_jid)
|
||||
XmppGroupchat.join(self, jid, muc_jid)
|
||||
# await XmppBookmark.add(self, jid=muc_jid)
|
||||
response = ('Joined groupchat {}'
|
||||
.format(message_text))
|
||||
|
|
Loading…
Reference in a new issue