Add MUC support including bookmarks and improve filtering
This commit is contained in:
parent
071bf78e1d
commit
634b0e3ce6
5 changed files with 193 additions and 31 deletions
|
@ -115,8 +115,9 @@ if __name__ == '__main__':
|
||||||
xmpp.register_plugin('xep_0045') # Multi-User Chat
|
xmpp.register_plugin('xep_0045') # Multi-User Chat
|
||||||
xmpp.register_plugin('xep_0048') # Bookmarks
|
xmpp.register_plugin('xep_0048') # Bookmarks
|
||||||
xmpp.register_plugin('xep_0060') # PubSub
|
xmpp.register_plugin('xep_0060') # PubSub
|
||||||
xmpp.register_plugin('xep_0199') # XMPP Ping
|
xmpp.register_plugin('xep_0199', {'keepalive': True, 'frequency': 15}) # XMPP Ping
|
||||||
xmpp.register_plugin('xep_0249') # Multi-User Chat
|
xmpp.register_plugin('xep_0249') # Multi-User Chat
|
||||||
|
xmpp.register_plugin('xep_0402') # PEP Native Bookmarks
|
||||||
|
|
||||||
# Connect to the XMPP server and start processing XMPP stanzas.
|
# Connect to the XMPP server and start processing XMPP stanzas.
|
||||||
xmpp.connect()
|
xmpp.connect()
|
||||||
|
|
|
@ -18,7 +18,7 @@ TODO
|
||||||
import sqlitehandler
|
import sqlitehandler
|
||||||
|
|
||||||
|
|
||||||
async def set_list(newwords, keywords):
|
async def add_to_list(newwords, keywords):
|
||||||
"""
|
"""
|
||||||
Append new keywords to list.
|
Append new keywords to list.
|
||||||
|
|
||||||
|
@ -48,6 +48,36 @@ async def set_list(newwords, keywords):
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
|
async def remove_from_list(newwords, keywords):
|
||||||
|
"""
|
||||||
|
Remove given keywords from list.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
newwords : str
|
||||||
|
List of new keywords.
|
||||||
|
keywords : str
|
||||||
|
List of current keywords.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
val : str
|
||||||
|
List of new keywords.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
keywords = keywords.split(",")
|
||||||
|
except:
|
||||||
|
keywords = []
|
||||||
|
newwords = newwords.lower().split(",")
|
||||||
|
for word in newwords:
|
||||||
|
word = word.strip()
|
||||||
|
if len(word) and word in keywords:
|
||||||
|
keywords.remove(word)
|
||||||
|
keywords.sort()
|
||||||
|
val = ",".join(keywords)
|
||||||
|
return val
|
||||||
|
|
||||||
|
|
||||||
async def is_listed(db_file, key, string):
|
async def is_listed(db_file, key, string):
|
||||||
"""
|
"""
|
||||||
Check keyword match.
|
Check keyword match.
|
||||||
|
|
|
@ -1128,15 +1128,21 @@ async def last_entries(db_file, num):
|
||||||
"LIMIT :num "
|
"LIMIT :num "
|
||||||
)
|
)
|
||||||
results = cur.execute(sql, (num,))
|
results = cur.execute(sql, (num,))
|
||||||
titles_list = "Recent {} titles:\n".format(num)
|
titles_list = "Recent {} titles:\n```".format(num)
|
||||||
|
counter = 0
|
||||||
for result in results:
|
for result in results:
|
||||||
|
counter += 1
|
||||||
titles_list += (
|
titles_list += (
|
||||||
"\n{}\n{}\n"
|
"\n{}\n{}\n"
|
||||||
).format(
|
).format(
|
||||||
str(result[0]),
|
str(result[0]),
|
||||||
str(result[1])
|
str(result[1])
|
||||||
)
|
)
|
||||||
return titles_list
|
if counter:
|
||||||
|
titles_list += "```\n"
|
||||||
|
return titles_list
|
||||||
|
else:
|
||||||
|
return "There are no news at the moment."
|
||||||
|
|
||||||
|
|
||||||
async def search_feeds(db_file, query):
|
async def search_feeds(db_file, query):
|
||||||
|
@ -1185,7 +1191,7 @@ async def search_feeds(db_file, query):
|
||||||
if counter:
|
if counter:
|
||||||
return results_list + "\n```\nTotal of {} feeds".format(counter)
|
return results_list + "\n```\nTotal of {} feeds".format(counter)
|
||||||
else:
|
else:
|
||||||
return "No feeds found for: {}".format(query)
|
return "No feeds were found for: {}".format(query)
|
||||||
|
|
||||||
|
|
||||||
async def search_entries(db_file, query):
|
async def search_entries(db_file, query):
|
||||||
|
@ -1234,7 +1240,7 @@ async def search_entries(db_file, query):
|
||||||
if counter:
|
if counter:
|
||||||
return results_list + "```\nTotal of {} results".format(counter)
|
return results_list + "```\nTotal of {} results".format(counter)
|
||||||
else:
|
else:
|
||||||
return "No results found for: {}".format(query)
|
return "No results were found for: {}".format(query)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
FIXME Error due to missing date, but it appears that date is present:
|
FIXME Error due to missing date, but it appears that date is present:
|
||||||
|
|
|
@ -282,7 +282,7 @@ async def send_status(self, jid):
|
||||||
if unread:
|
if unread:
|
||||||
status_mode = "chat"
|
status_mode = "chat"
|
||||||
status_text = (
|
status_text = (
|
||||||
"📬️ You have {} news items"
|
"📬️ There are {} news items"
|
||||||
).format(str(unread))
|
).format(str(unread))
|
||||||
# status_text = (
|
# status_text = (
|
||||||
# "📰 News items: {}"
|
# "📰 News items: {}"
|
||||||
|
|
|
@ -56,6 +56,8 @@ import slixmpp
|
||||||
from random import randrange
|
from random import randrange
|
||||||
|
|
||||||
from slixmpp.plugins.xep_0363.http_upload import FileTooBig, HTTPError, UploadServiceNotFound
|
from slixmpp.plugins.xep_0363.http_upload import FileTooBig, HTTPError, UploadServiceNotFound
|
||||||
|
# from slixmpp.plugins.xep_0402 import BookmarkStorage, Conference
|
||||||
|
from slixmpp.plugins.xep_0048.stanza import Bookmarks
|
||||||
|
|
||||||
import datahandler
|
import datahandler
|
||||||
import datetimehandler
|
import datetimehandler
|
||||||
|
@ -64,6 +66,10 @@ import listhandler
|
||||||
import sqlitehandler
|
import sqlitehandler
|
||||||
import taskhandler
|
import taskhandler
|
||||||
|
|
||||||
|
import xmltodict
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
main_task = []
|
main_task = []
|
||||||
jid_tasker = {}
|
jid_tasker = {}
|
||||||
task_manager = {}
|
task_manager = {}
|
||||||
|
@ -96,6 +102,8 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
# our roster.
|
# our roster.
|
||||||
self.add_event_handler("session_start", self.start_session)
|
self.add_event_handler("session_start", self.start_session)
|
||||||
self.add_event_handler("session_resumed", self.start_session)
|
self.add_event_handler("session_resumed", self.start_session)
|
||||||
|
self.add_event_handler("session_start", self.autojoin_muc)
|
||||||
|
self.add_event_handler("session_resumed", self.autojoin_muc)
|
||||||
self.add_event_handler("got_offline", print("got_offline"))
|
self.add_event_handler("got_offline", print("got_offline"))
|
||||||
# self.add_event_handler("got_online", self.check_readiness)
|
# self.add_event_handler("got_online", self.check_readiness)
|
||||||
self.add_event_handler("changed_status", self.check_readiness)
|
self.add_event_handler("changed_status", self.check_readiness)
|
||||||
|
@ -238,18 +246,73 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
# If a room password is needed, use:
|
# If a room password is needed, use:
|
||||||
# password=the_room_password,
|
# password=the_room_password,
|
||||||
)
|
)
|
||||||
# self.add_event_handler(
|
|
||||||
# "muc::[room]::message",
|
|
||||||
# self.message
|
|
||||||
# )
|
|
||||||
|
|
||||||
# await self.get_bookmarks()
|
result = await self.plugin['xep_0048'].get_bookmarks()
|
||||||
# bookmark = self.plugin['xep_0048'].instantiate_pep()
|
bookmarks = result["private"]["bookmarks"]
|
||||||
# print(bookmark)
|
conferences = bookmarks["conferences"]
|
||||||
# nick = "Slixfeed (RSS News Bot)"
|
mucs = []
|
||||||
# bookmark.add_bookmark(muc_jid, nick=nick)
|
for conference in conferences:
|
||||||
# await self['xep_0048'].set_bookmarks(bookmark)
|
jid = conference["jid"]
|
||||||
# print(bookmark)
|
mucs.extend([jid])
|
||||||
|
if muc_jid not in mucs:
|
||||||
|
bookmarks = Bookmarks()
|
||||||
|
mucs.extend([muc_jid])
|
||||||
|
for muc in mucs:
|
||||||
|
bookmarks.add_conference(
|
||||||
|
muc,
|
||||||
|
"Slixfeed (RSS News Bot)",
|
||||||
|
autojoin=True
|
||||||
|
)
|
||||||
|
await 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="Slixfeed (RSS News Bot)"))
|
||||||
|
# await self['xep_0402'].publish(bm)
|
||||||
|
|
||||||
|
|
||||||
|
async def remove_and_leave_muc(self, muc_jid):
|
||||||
|
result = await self.plugin['xep_0048'].get_bookmarks()
|
||||||
|
bookmarks = result["private"]["bookmarks"]
|
||||||
|
conferences = bookmarks["conferences"]
|
||||||
|
mucs = []
|
||||||
|
for conference in conferences:
|
||||||
|
jid = conference["jid"]
|
||||||
|
mucs.extend([jid])
|
||||||
|
if muc_jid in mucs:
|
||||||
|
bookmarks = Bookmarks()
|
||||||
|
mucs.remove(muc_jid)
|
||||||
|
for muc in mucs:
|
||||||
|
bookmarks.add_conference(
|
||||||
|
muc,
|
||||||
|
"Slixfeed (RSS News Bot)",
|
||||||
|
autojoin=True
|
||||||
|
)
|
||||||
|
await self.plugin['xep_0048'].set_bookmarks(bookmarks)
|
||||||
|
self.plugin['xep_0045'].leave_muc(
|
||||||
|
muc_jid,
|
||||||
|
"Slixfeed (RSS News Bot)",
|
||||||
|
"Goodbye!",
|
||||||
|
self.boundjid.bare
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def autojoin_muc(self, event):
|
||||||
|
result = await self.plugin['xep_0048'].get_bookmarks()
|
||||||
|
bookmarks = result["private"]["bookmarks"]
|
||||||
|
conferences = bookmarks["conferences"]
|
||||||
|
for conference in conferences:
|
||||||
|
if conference["autojoin"]:
|
||||||
|
muc = conference["jid"]
|
||||||
|
print(muc)
|
||||||
|
self.plugin['xep_0045'].join_muc(
|
||||||
|
muc,
|
||||||
|
"Slixfeed (RSS News Bot)",
|
||||||
|
# If a room password is needed, use:
|
||||||
|
# password=the_room_password,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def on_session_end(self, event):
|
async def on_session_end(self, event):
|
||||||
|
@ -562,6 +625,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
print(self.client_roster.keys())
|
print(self.client_roster.keys())
|
||||||
print("jid")
|
print("jid")
|
||||||
print(jid)
|
print(jid)
|
||||||
|
await self.autojoin_muc()
|
||||||
|
|
||||||
case _ if message_lowercase.startswith("activate"):
|
case _ if message_lowercase.startswith("activate"):
|
||||||
if msg["type"] == "groupchat":
|
if msg["type"] == "groupchat":
|
||||||
|
@ -606,16 +670,16 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
action = "Missing URL."
|
action = "Missing URL."
|
||||||
case _ if message_lowercase.startswith("allow"):
|
case _ if message_lowercase.startswith("allow +"):
|
||||||
key = "filter-" + message[:5]
|
key = "filter-" + message[:5]
|
||||||
val = message[6:]
|
val = message[7:]
|
||||||
if val:
|
if val:
|
||||||
keywords = await filehandler.initdb(
|
keywords = await filehandler.initdb(
|
||||||
jid,
|
jid,
|
||||||
sqlitehandler.get_settings_value,
|
sqlitehandler.get_settings_value,
|
||||||
key
|
key
|
||||||
)
|
)
|
||||||
val = await listhandler.set_list(
|
val = await listhandler.add_to_list(
|
||||||
val,
|
val,
|
||||||
keywords
|
keywords
|
||||||
)
|
)
|
||||||
|
@ -630,16 +694,64 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
).format(val)
|
).format(val)
|
||||||
else:
|
else:
|
||||||
action = "Missing keywords."
|
action = "Missing keywords."
|
||||||
case _ if message_lowercase.startswith("deny"):
|
case _ if message_lowercase.startswith("allow -"):
|
||||||
key = "filter-" + message[:4]
|
key = "filter-" + message[:5]
|
||||||
val = message[5:]
|
val = message[7:]
|
||||||
if val:
|
if val:
|
||||||
keywords = await filehandler.initdb(
|
keywords = await filehandler.initdb(
|
||||||
jid,
|
jid,
|
||||||
sqlitehandler.get_settings_value,
|
sqlitehandler.get_settings_value,
|
||||||
key
|
key
|
||||||
)
|
)
|
||||||
val = await listhandler.set_list(
|
val = await listhandler.remove_from_list(
|
||||||
|
val,
|
||||||
|
keywords
|
||||||
|
)
|
||||||
|
await filehandler.initdb(
|
||||||
|
jid,
|
||||||
|
sqlitehandler.set_settings_value,
|
||||||
|
[key, val]
|
||||||
|
)
|
||||||
|
action = (
|
||||||
|
"Approved keywords\n"
|
||||||
|
"```\n{}\n```"
|
||||||
|
).format(val)
|
||||||
|
else:
|
||||||
|
action = "Missing keywords."
|
||||||
|
case _ if message_lowercase.startswith("deny +"):
|
||||||
|
key = "filter-" + message[:4]
|
||||||
|
val = message[6:]
|
||||||
|
if val:
|
||||||
|
keywords = await filehandler.initdb(
|
||||||
|
jid,
|
||||||
|
sqlitehandler.get_settings_value,
|
||||||
|
key
|
||||||
|
)
|
||||||
|
val = await listhandler.add_to_list(
|
||||||
|
val,
|
||||||
|
keywords
|
||||||
|
)
|
||||||
|
await filehandler.initdb(
|
||||||
|
jid,
|
||||||
|
sqlitehandler.set_settings_value,
|
||||||
|
[key, val]
|
||||||
|
)
|
||||||
|
action = (
|
||||||
|
"Rejected keywords\n"
|
||||||
|
"```\n{}\n```"
|
||||||
|
).format(val)
|
||||||
|
else:
|
||||||
|
action = "Missing keywords."
|
||||||
|
case _ if message_lowercase.startswith("deny -"):
|
||||||
|
key = "filter-" + message[:4]
|
||||||
|
val = message[6:]
|
||||||
|
if val:
|
||||||
|
keywords = await filehandler.initdb(
|
||||||
|
jid,
|
||||||
|
sqlitehandler.get_settings_value,
|
||||||
|
key
|
||||||
|
)
|
||||||
|
val = await listhandler.remove_from_list(
|
||||||
val,
|
val,
|
||||||
keywords
|
keywords
|
||||||
)
|
)
|
||||||
|
@ -705,6 +817,11 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
jid,
|
jid,
|
||||||
sqlitehandler.list_feeds
|
sqlitehandler.list_feeds
|
||||||
)
|
)
|
||||||
|
case "goodbye":
|
||||||
|
if msg["type"] == "groupchat":
|
||||||
|
await self.remove_and_leave_muc(jid)
|
||||||
|
else:
|
||||||
|
action = "This command is valid for groupchat only."
|
||||||
case _ if message_lowercase.startswith("interval"):
|
case _ if message_lowercase.startswith("interval"):
|
||||||
# FIXME
|
# FIXME
|
||||||
# The following error occurs only upon first attempt to set interval.
|
# The following error occurs only upon first attempt to set interval.
|
||||||
|
@ -746,7 +863,7 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
sqlitehandler.get_settings_value,
|
sqlitehandler.get_settings_value,
|
||||||
key
|
key
|
||||||
)
|
)
|
||||||
val = await listhandler.set_list(
|
val = await listhandler.add_to_list(
|
||||||
val,
|
val,
|
||||||
names
|
names
|
||||||
)
|
)
|
||||||
|
@ -955,6 +1072,9 @@ class Slixfeed(slixmpp.ClientXMPP):
|
||||||
"Unknown command. "
|
"Unknown command. "
|
||||||
"Press \"help\" for list of commands"
|
"Press \"help\" for list of commands"
|
||||||
)
|
)
|
||||||
|
# TODO Use message correction here
|
||||||
|
# NOTE This might not be a good idea if
|
||||||
|
# commands are sent one close to the next
|
||||||
if action: msg.reply(action).send()
|
if action: msg.reply(action).send()
|
||||||
|
|
||||||
|
|
||||||
|
@ -995,11 +1115,12 @@ def print_info():
|
||||||
" Dimitris Tzemos (SalixOS, Greece),"
|
" Dimitris Tzemos (SalixOS, Greece),"
|
||||||
"\n"
|
"\n"
|
||||||
" Emmanuel Gil Peyrot (poezio, France),"
|
" Emmanuel Gil Peyrot (poezio, France),"
|
||||||
|
" Florent Le Coz (poezio, France),"
|
||||||
|
"\n"
|
||||||
" George Vlahavas (SalixOS, Greece),"
|
" George Vlahavas (SalixOS, Greece),"
|
||||||
"\n"
|
|
||||||
" Pierrick Le Brun (SalixOS, France),"
|
" Pierrick Le Brun (SalixOS, France),"
|
||||||
" Thorsten Mühlfelder (SalixOS, Germany),"
|
|
||||||
"\n"
|
"\n"
|
||||||
|
" Thorsten Mühlfelder (SalixOS, Germany),"
|
||||||
" Yann Leboulanger (Gajim, France).\n"
|
" Yann Leboulanger (Gajim, France).\n"
|
||||||
"\n"
|
"\n"
|
||||||
"COPYRIGHT\n"
|
"COPYRIGHT\n"
|
||||||
|
@ -1088,10 +1209,14 @@ def print_help():
|
||||||
" Set new owner.\n"
|
" Set new owner.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"FILTER OPTIONS\n"
|
"FILTER OPTIONS\n"
|
||||||
" allow\n"
|
" allow +\n"
|
||||||
" Keywords to allow (comma separates).\n"
|
" Add keywords to allow (comma separates).\n"
|
||||||
" deny\n"
|
" allow -\n"
|
||||||
|
" Delete keywords from allow list (comma separates).\n"
|
||||||
|
" deny +\n"
|
||||||
" Keywords to block (comma separates).\n"
|
" Keywords to block (comma separates).\n"
|
||||||
|
" deny -\n"
|
||||||
|
" Delete keywords from deny list (comma separates).\n"
|
||||||
# " filter clear allow\n"
|
# " filter clear allow\n"
|
||||||
# " Reset allow list.\n"
|
# " Reset allow list.\n"
|
||||||
# " filter clear deny\n"
|
# " filter clear deny\n"
|
||||||
|
|
Loading…
Reference in a new issue