Handle bookmarks locally;

Atomize group chat join functionality.
This commit is contained in:
Schimon Jehudah, Adv. 2024-11-21 21:00:13 +02:00
parent f167625765
commit 020a5174b3
6 changed files with 103 additions and 229 deletions

View file

@ -0,0 +1 @@
bookmarks = []

View file

@ -1,99 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
TODO
1) Save groupchat name instead of jid in field name.
"""
from slixmpp.plugins.xep_0048.stanza import Bookmarks
class XmppBookmark:
async def get_bookmarks(self):
result = await self.plugin['xep_0048'].get_bookmarks()
conferences = result['private']['bookmarks']['conferences']
return conferences
async def get_bookmark_properties(self, jid):
result = await self.plugin['xep_0048'].get_bookmarks()
groupchats = result['private']['bookmarks']['conferences']
for groupchat in groupchats:
if jid == groupchat['jid']:
properties = {'password': groupchat['password'],
'jid': groupchat['jid'],
'name': groupchat['name'],
'nick': groupchat['nick'],
'autojoin': groupchat['autojoin'],
'lang': groupchat['lang']}
break
return properties
async def add(self, jid=None, properties=None):
result = await self.plugin['xep_0048'].get_bookmarks()
conferences = result['private']['bookmarks']['conferences']
groupchats = []
if properties:
properties['jid'] = properties['room'] + '@' + properties['host']
if not properties['alias']: properties['alias'] = self.alias
else:
properties = {
'jid' : jid,
'alias' : self.alias,
'name' : jid.split('@')[0],
'autojoin' : True,
'password' : None,
}
for conference in conferences:
if conference['jid'] != properties['jid']:
groupchats.extend([conference])
# FIXME Ad-hoc bookmark form is stuck
# if jid not in groupchats:
if properties['jid'] not in groupchats:
bookmarks = Bookmarks()
for groupchat in groupchats:
# if groupchat['jid'] == groupchat['name']:
# groupchat['name'] = groupchat['name'].split('@')[0]
bookmarks.add_conference(groupchat['jid'],
groupchat['nick'],
name=groupchat['name'],
autojoin=groupchat['autojoin'],
password=groupchat['password'])
bookmarks.add_conference(properties['jid'],
properties['alias'],
name=properties['name'],
autojoin=properties['autojoin'],
password=properties['password'])
# await self.plugin['xep_0048'].set_bookmarks(bookmarks)
self.plugin['xep_0048'].set_bookmarks(bookmarks)
# bookmarks = Bookmarks()
# await self.plugin['xep_0048'].set_bookmarks(bookmarks)
# print(await self.plugin['xep_0048'].get_bookmarks())
# bm = BookmarkStorage()
# bm.conferences.append(Conference(muc_jid, autojoin=True, nick=self.alias))
# await self['xep_0402'].publish(bm)
async def remove(self, jid):
result = await self.plugin['xep_0048'].get_bookmarks()
conferences = result['private']['bookmarks']['conferences']
groupchats = []
for conference in conferences:
if not conference['jid'] == jid:
groupchats.extend([conference])
bookmarks = Bookmarks()
for groupchat in groupchats:
bookmarks.add_conference(groupchat['jid'],
groupchat['nick'],
name=groupchat['name'],
autojoin=groupchat['autojoin'],
password=groupchat['password'])
await self.plugin['xep_0048'].set_bookmarks(bookmarks)

View file

@ -7,7 +7,6 @@ from kaikout.about import Documentation
from kaikout.database import DatabaseToml
from kaikout.log import Logger
from kaikout.utilities import Config, Log, BlockList, Toml
from kaikout.xmpp.bookmark import XmppBookmark
from kaikout.xmpp.chat import XmppChat
from kaikout.xmpp.commands import XmppCommands
from kaikout.xmpp.groupchat import XmppGroupchat
@ -60,6 +59,10 @@ class XmppClient(slixmpp.ClientXMPP):
self.action_count = 0
# A handler for alias.
self.alias = alias
# A handler for bookmarks.
self.filename_bookmarks = os.path.join(self.directory_config, 'bookmarks.toml')
self.data_bookmarks = Toml.open_file(self.filename_bookmarks)
self.bookmarks = self.data_bookmarks['bookmarks']
# A handler for configuration.
self.defaults = self.data_settings['defaults']
# Handlers for connectivity.
@ -135,30 +138,13 @@ class XmppClient(slixmpp.ClientXMPP):
async def on_groupchat_invite(self, message):
jid_full = str(message['from'])
room = message['groupchat_invite']['jid']
result = await XmppMuc.join(self, room)
if result == 'ban':
message_body = '{} is banned from {}'.format(self.alias, room)
jid_bare = message['from'].bare
# This might not be necessary because JID might not be of the inviter, but rather of the MUC
XmppMessage.send(self, jid_bare, message_body, 'chat')
logger.warning(message_body)
print("on_groupchat_invite")
print("BAN BAN BAN BAN BAN")
print("on_groupchat_invite")
print(jid_full)
print(jid_full)
print(jid_full)
print("on_groupchat_invite")
print("BAN BAN BAN BAN BAN")
print("on_groupchat_invite")
else:
await XmppBookmark.add(self, room)
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'
'You may always reach me via xmpp:{}?message'
.format(self.alias, self.boundjid.bare))
result = await XmppGroupchat.join(self, room)
if result != 'ban':
#self.bookmarks.append({'jid' : room, 'lang' : '', 'pass' : ''})
if room not in self.bookmarks: self.bookmarks.append(room)
Toml.save_file(self.filename_bookmarks, self.data_bookmarks)
message_body = ('/me moderation chat bot. Jabber ID: xmpp:'
f'{self.boundjid.bare}?message (groupchat_invite)')
XmppMessage.send(self, room, message_body, 'groupchat')
XmppStatus.send_status_message(self, room)
self.add_event_handler("muc::%s::got_online" % room, self.on_muc_got_online)
@ -168,16 +154,13 @@ class XmppClient(slixmpp.ClientXMPP):
async def on_groupchat_direct_invite(self, message):
room = message['groupchat_invite']['jid']
result = await XmppMuc.join(self, room)
if result == 'ban':
message_body = '{} is banned from {}'.format(self.alias, room)
jid_bare = message['from'].bare
XmppMessage.send(self, jid_bare, message_body, 'chat')
logger.warning(message_body)
else:
await XmppBookmark.add(self, room)
message_body = ('/me moderation chat bot. Jabber ID: xmpp:{}?message'
.format(self.boundjid.bare))
result = await XmppGroupchat.join(self, room)
if result != 'ban':
#self.bookmarks.append({'jid' : room, 'lang' : '', 'pass' : ''})
if room not in self.bookmarks: self.bookmarks.append(room)
Toml.save_file(self.filename_bookmarks, self.data_bookmarks)
message_body = ('/me moderation chat bot. Jabber ID: xmpp:'
f'{self.boundjid.bare}?message')
XmppMessage.send(self, room, message_body, 'groupchat')
XmppStatus.send_status_message(self, room)
self.add_event_handler("muc::%s::got_online" % room, self.on_muc_got_online)
@ -204,7 +187,8 @@ class XmppClient(slixmpp.ClientXMPP):
jid_full = XmppMuc.get_full_jid(self, room, alias)
if jid_full and '/' in jid_full:
jid_bare = jid_full.split('/')[0]
XmppCommands.update_last_activity(self, room, jid_bare, db_file, timestamp)
XmppCommands.update_last_activity(
self, room, jid_bare, db_file, timestamp)
# DatabaseToml.load_jid_settings(self, room)
# await XmppChat.process_message(self, message)
if (XmppMuc.is_moderator(self, room, self.alias) and
@ -216,9 +200,11 @@ class XmppClient(slixmpp.ClientXMPP):
fields = [alias, message_body, identifier, timestamp]
Log.toml(self, room, fields, 'message')
# Check for message
await XmppObservation.observe_message(self, db_file, alias, message_body, room)
await XmppObservation.observe_message(self, db_file, alias,
message_body, room)
# Check for inactivity
await XmppObservation.observe_inactivity(self, db_file, room)
await XmppObservation.observe_inactivity(self, db_file,
room)
async def on_muc_got_online(self, presence):
@ -261,9 +247,9 @@ class XmppClient(slixmpp.ClientXMPP):
status_codes = presence['muc']['status_codes']
actor_alias = presence['muc']['item']['actor']['nick']
if 301 in status_codes:
presence_body = 'User has been banned by {}'.format(actor_alias)
presence_body = f'User has been banned by {actor_alias}'
elif 307 in status_codes:
presence_body = 'User has been kicked by {}'.format(actor_alias)
presence_body = f'User has been kicked by {actor_alias}'
else:
presence_body = presence['status']
room = presence['muc']['room']
@ -283,7 +269,8 @@ class XmppClient(slixmpp.ClientXMPP):
await XmppObservation.observe_strikes(self, db_file, presence, room)
if jid_bare and jid_bare not in self.settings[room]['jid_whitelist']:
# Check for status message
await XmppObservation.observe_status_message(self, alias, db_file, jid_bare, presence_body, room)
await XmppObservation.observe_status_message(
self, alias, db_file, jid_bare, presence_body, room)
# Check for inactivity
await XmppObservation.observe_inactivity(self, db_file, room)
@ -292,14 +279,16 @@ class XmppClient(slixmpp.ClientXMPP):
actor = presence['muc']['item']['actor']['nick']
alias = presence['muc']['nick']
room = presence['muc']['room']
if actor and alias == self.alias: XmppStatus.send_status_message(self, room)
if actor and alias == self.alias: XmppStatus.send_status_message(self,
room)
# TODO Check whether group chat is not anonymous
if XmppMuc.is_moderator(self, room, self.alias):
timestamp_iso = datetime.now().isoformat()
for alias in XmppMuc.get_roster(self, room):
jid_bare = XmppMuc.get_full_jid(self, room, alias).split('/')[0]
fields = [jid_bare, alias, timestamp_iso]
if not Log.alias_jid_exist(room, fields): Log.csv_jid(room, fields)
if not Log.alias_jid_exist(room, fields): Log.csv_jid(room,
fields)
def on_reactions(self, message):
@ -358,11 +347,10 @@ class XmppClient(slixmpp.ClientXMPP):
del self.filename_blocklist
# subscribe['from'] = xmppbl.org
# subscribe['pubsub']['subscription']['node'] = 'muc_bans_sha256'
subscriptions = await XmppPubsub.get_node_subscriptions(self, jabber_id, node_id)
subscriptions = await XmppPubsub.get_node_subscriptions(
self, jabber_id, node_id)
await self['xep_0115'].update_caps()
bookmarks = await XmppBookmark.get_bookmarks(self)
print(bookmarks)
rooms = await XmppGroupchat.autojoin(self, bookmarks)
rooms = await XmppGroupchat.autojoin(self)
# See also get_joined_rooms of slixmpp.plugins.xep_0045
for room in rooms:
XmppStatus.send_status_message(self, room)

View file

@ -6,9 +6,8 @@ import kaikout.config as config
from kaikout.config import Config
from kaikout.log import Logger
from kaikout.database import DatabaseToml
from kaikout.utilities import Documentation, Url
from kaikout.utilities import Documentation, Toml, Url
from kaikout.version import __version__
from kaikout.xmpp.bookmark import XmppBookmark
from kaikout.xmpp.muc import XmppMuc
from kaikout.xmpp.status import XmppStatus
from kaikout.xmpp.utilities import XmppUtilities
@ -81,17 +80,16 @@ class XmppCommands:
async def bookmark_add(self, muc_jid):
await XmppBookmark.add(self, jid=muc_jid)
message = ('Groupchat {} has been added to bookmarks.'
.format(muc_jid))
return message
if muc_jid not in self.bookmarks: self.bookmarks.append(muc_jid)
Toml.save_file(self.filename_bookmarks, self.data_bookmarks)
return f'Groupchat {muc_jid} has been added to bookmarks.'
async def bookmark_del(self, muc_jid):
await XmppBookmark.remove(self, muc_jid)
message = ('Groupchat {} has been removed from bookmarks.'
.format(muc_jid))
return message
if muc_jid in self.bookmarks: self.bookmarks.remove(muc_jid)
Toml.save_file(self.filename_bookmarks, self.data_bookmarks)
return f'Groupchat {muc_jid} has been removed from bookmarks.'
async def invite_jid_to_muc(self, jid_bare):
muc_jid = 'slixfeed@chat.woodpeckersnest.space'
@ -122,12 +120,13 @@ class XmppCommands:
if muc_jid:
# TODO probe JID and confirm it's a groupchat
result = await XmppMuc.join(self, muc_jid)
# await XmppBookmark.add(self, jid=muc_jid)
if result == 'ban':
message = '{} is banned from {}'.format(self.alias, muc_jid)
if room in self.bookmarks: self.bookmarks.remove(room)
else:
await XmppBookmark.add(self, muc_jid)
if room not in self.bookmarks: self.bookmarks.append(room)
message = 'Joined groupchat {}'.format(muc_jid)
Toml.save_file(self.filename_bookmarks, self.data_bookmarks)
else:
message = '> {}\nGroupchat JID appears to be invalid.'.format(muc_jid)
else:
@ -137,7 +136,8 @@ class XmppCommands:
async def muc_leave(self, room):
XmppMuc.leave(self, room)
await XmppBookmark.remove(self, room)
if room in self.bookmarks: self.bookmarks.remove(room)
Toml.save_file(self.filename_bookmarks, self.data_bookmarks)
async def outcast(self, room, alias, reason):
@ -163,14 +163,11 @@ class XmppCommands:
async def print_bookmarks(self):
conferences = await XmppBookmark.get_bookmarks(self)
conferences = self.bookmarks
message = '\nList of groupchats:\n\n```\n'
for conference in conferences:
message += ('Name: {}\n'
'Room: {}\n'
'\n'
.format(conference['name'], conference['jid']))
message += ('```\nTotal of {} groupchats.\n'.format(len(conferences)))
message += f'{conference}\n'
message += (f'```\nTotal of {len(conferences)} groupchats.\n')
return message

View file

@ -1,63 +1,53 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
TODO
1) Send message to inviter that bot has joined to groupchat.
2) If groupchat requires captcha, send the consequent message.
3) If groupchat error is received, send that error message to inviter.
FIXME
1) Save name of groupchat instead of jid as name
"""
from kaikout.xmpp.bookmark import XmppBookmark
from kaikout.xmpp.message import XmppMessage
from kaikout.xmpp.muc import XmppMuc
from kaikout.xmpp.status import XmppStatus
from kaikout.utilities import Toml
from kaikout.log import Logger, Message
import random
logger = Logger(__name__)
class XmppGroupchat:
async def autojoin(self, bookmarks):
mucs_join_success = []
for bookmark in bookmarks:
if bookmark["jid"] and bookmark["autojoin"]:
if not bookmark["nick"]:
bookmark["nick"] = self.alias
logger.error('Alias (i.e. Nicknname) is missing for '
'bookmark {}'.format(bookmark['name']))
alias = bookmark["nick"]
room = bookmark["jid"]
Message.printer('Joining to MUC {} ...'.format(room))
result = await XmppMuc.join(self, room, alias)
async def join(self, room):
result = await XmppMuc.join(self, room)
if result == 'ban':
await XmppBookmark.remove(self, room)
logger.warning('{} is banned from {}'.format(self.alias, room))
logger.warning('Groupchat {} has been removed from bookmarks'
.format(room))
message_body = '{} is banned from {}'.format(self.alias, room)
jid_bare = message['from'].bare
XmppMessage.send(self, jid_bare, message_body, 'chat')
logger.warning(message_body)
elif result == 'conflict':
while result == 'conflict':
number = str(random.randrange(1000, 5000))
await XmppMuc.join(self, room, alias + ' #' + number)
print(f'Conflict. Atempting to join to {room} as {self.alias} #{number}')
result = await XmppMuc.join(self, room, f'{self.alias} #{number}')
else:
mucs_join_success.append(room)
logger.info('Autojoin groupchat\n'
'Name : {}\n'
'JID : {}\n'
'Alias : {}\n'
.format(bookmark["name"],
bookmark["jid"],
bookmark["nick"]))
elif not bookmark["jid"]:
logger.error('JID is missing for bookmark {}'
.format(bookmark['name']))
return mucs_join_success
#self.bookmarks.append({'jid' : room, 'lang' : '', 'pass' : ''})
if room not in self.bookmarks: self.bookmarks.append(room)
Toml.save_file(self.filename_bookmarks, self.data_bookmarks)
return result
async def autojoin(self):
mucs_joined = []
for room in self.bookmarks:
alias = self.alias
print(f'Joining to MUC {room} ...')
#Message.printer(f'Joining to MUC {room} ...')
result = await XmppMuc.join(self, room)
if result == 'ban':
if room in self.bookmarks: self.bookmarks.remove(room)
Toml.save_file(self.filename_bookmarks, self.data_bookmarks)
logger.warning(f'{alias} is banned from {room}')
logger.warning(f'Groupchat {room} has been removed from bookmarks')
elif result == 'conflict':
while result == 'conflict':
number = str(random.randrange(1000, 5000))
print(f'Conflict. Atempting to join to {room} as {self.alias} #{number}')
result = await XmppMuc.join(self, room, f'{alias} #{number}')
else:
mucs_joined.append(room)
return mucs_joined

View file

@ -93,21 +93,18 @@ class XmppMuc:
def is_moderator(self, room, alias):
"""Check if given JID is a moderator"""
role = self.plugin['xep_0045'].get_jid_property(room, alias, 'role')
if role == 'moderator':
result = True
else:
result = False
result = True if role == 'moderator' else False
return result
async def join(self, jid, alias=None, password=None):
logger.info('Joining groupchat\nJID : {}\n'.format(jid))
jid_from = str(self.boundjid) if self.is_component else None
async def join(self, jid_bare, alias=None, password=None):
logger.info('Joining groupchat\nJID : {}\n'.format(jid_bare))
#jid_from = str(self.boundjid) if self.is_component else None
if not alias: alias = self.alias
try:
await self.plugin['xep_0045'].join_muc_wait(jid,
await self.plugin['xep_0045'].join_muc_wait(jid_bare,
alias,
presence_options = {"pfrom" : jid_from},
#presence_options = {"pfrom" : jid_from},
password=password,
maxchars=0,
maxstanzas=0,
@ -118,24 +115,24 @@ class XmppMuc:
except IqError as e:
logger.error('Error XmppIQ')
logger.error(str(e))
logger.error(jid)
logger.error(jid_bare)
result = 'error'
except IqTimeout as e:
logger.error('Timeout XmppIQ')
logger.error(str(e))
logger.error(jid)
logger.error(jid_bare)
result = 'timeout'
except TimeoutError as e:
logger.error('Timeout AsyncIO')
logger.error(str(e))
logger.error(jid)
logger.error(jid_bare)
result = 'timeout'
except PresenceError as e:
logger.error('Error Presence')
logger.error(str(e))
if (e.condition == 'forbidden' and
e.presence['error']['code'] == '403'):
logger.warning('{} is banned from {}'.format(self.alias, jid))
logger.warning('{} is banned from {}'.format(self.alias, jid_bare))
result = 'ban'
elif e.condition == 'conflict':
logger.warning(e.presence['error']['text'])
@ -145,7 +142,7 @@ class XmppMuc:
except Exception as e:
logger.error('Unknown error')
logger.error(str(e))
logger.error(jid)
logger.error(jid_bare)
result = 'unknown'
return result