Fix PubSub;

Improve permission handling;
Catch more errors.
This commit is contained in:
Schimon Jehudah 2024-05-14 19:39:58 +00:00
parent 8055f64c96
commit 4ac8e0836d
11 changed files with 315 additions and 219 deletions

View file

@ -40,6 +40,7 @@ import slixfeed.crawl as crawl
import slixfeed.dt as dt import slixfeed.dt as dt
import slixfeed.fetch as fetch import slixfeed.fetch as fetch
import slixfeed.sqlite as sqlite import slixfeed.sqlite as sqlite
import slixfeed.url as uri
from slixfeed.url import ( from slixfeed.url import (
complete_url, complete_url,
join_url, join_url,
@ -298,14 +299,30 @@ async def xmpp_pubsub_send_unread_items(self, jid_bare):
# node_subtitle = feed_properties[5] # node_subtitle = feed_properties[5]
node_id = sqlite.get_feed_identifier(db_file, feed_id) node_id = sqlite.get_feed_identifier(db_file, feed_id)
node_id = node_id[0] node_id = node_id[0]
if not node_id:
counter = 0
hostname = uri.get_hostname(url)
hostname = hostname.replace('.','-')
identifier = hostname + ':' + str(counter)
while True:
if sqlite.check_identifier_exist(db_file, identifier):
counter += 1
identifier = hostname + ':' + str(counter)
else:
break
await sqlite.update_feed_identifier(db_file, feed_id, identifier)
node_id = sqlite.get_feed_identifier(db_file, feed_id)
node_id = node_id[0]
node_title = sqlite.get_feed_title(db_file, feed_id) node_title = sqlite.get_feed_title(db_file, feed_id)
node_title = node_title[0] node_title = node_title[0]
node_subtitle = sqlite.get_feed_subtitle(db_file, feed_id) node_subtitle = sqlite.get_feed_subtitle(db_file, feed_id)
node_subtitle = node_subtitle[0] node_subtitle = node_subtitle[0]
xep = None xep = None
iq_create_node = XmppPubsub.create_node( node_exist = await XmppPubsub.get_node_configuration(self, jid_bare, node_id)
self, jid_bare, node_id, xep, node_title, node_subtitle) if not node_exist:
await XmppIQ.send(self, iq_create_node) iq_create_node = XmppPubsub.create_node(
self, jid_bare, node_id, xep, node_title, node_subtitle)
await XmppIQ.send(self, iq_create_node)
entries = sqlite.get_unread_entries_of_feed(db_file, feed_id) entries = sqlite.get_unread_entries_of_feed(db_file, feed_id)
report[url] = len(entries) report[url] = len(entries)
for entry in entries: for entry in entries:

View file

@ -17,7 +17,7 @@ class Logger:
def __init__(self, name): def __init__(self, name):
self.logger = logging.getLogger(name) self.logger = logging.getLogger(name)
self.logger.setLevel(logging.WARNING) self.logger.setLevel(logging.WARNING) # DEBUG
ch = logging.StreamHandler() ch = logging.StreamHandler()
ch.setLevel(logging.WARNING) ch.setLevel(logging.WARNING)

View file

@ -562,6 +562,7 @@ def insert_feed_preferences(cur, feed_id):
logger.error(e) logger.error(e)
# TODO Test
def insert_feed_properties(cur, feed_id): def insert_feed_properties(cur, feed_id):
""" """
Set feed properties. Set feed properties.
@ -578,7 +579,7 @@ def insert_feed_properties(cur, feed_id):
""" """
INSERT INSERT
INTO feeds_properties( INTO feeds_properties(
feed_id) id)
VALUES( VALUES(
?) ?)
""" """
@ -953,7 +954,7 @@ def get_feed_identifier(db_file, feed_id):
""" """
SELECT identifier SELECT identifier
FROM feeds_properties FROM feeds_properties
WHERE feed_id = ? WHERE id = ?
""" """
) )
par = (feed_id,) par = (feed_id,)
@ -1762,20 +1763,20 @@ async def archive_entry(db_file, ix):
cur.execute(sql, par) cur.execute(sql, par)
def get_feed_title(db_file, ix): def get_feed_title(db_file, feed_id):
function_name = sys._getframe().f_code.co_name function_name = sys._getframe().f_code.co_name
logger.debug('{}: db_file: {} ix: {}' logger.debug('{}: db_file: {} feed_id: {}'
.format(function_name, db_file, ix)) .format(function_name, db_file, feed_id))
with create_connection(db_file) as conn: with create_connection(db_file) as conn:
cur = conn.cursor() cur = conn.cursor()
sql = ( sql = (
""" """
SELECT title SELECT title
FROM feeds_properties FROM feeds_properties
WHERE id = :ix WHERE id = :feed_id
""" """
) )
par = (ix,) par = (feed_id,)
title = cur.execute(sql, par).fetchone() title = cur.execute(sql, par).fetchone()
return title return title
@ -1790,7 +1791,7 @@ def get_feed_subtitle(db_file, feed_id):
""" """
SELECT subtitle SELECT subtitle
FROM feeds_properties FROM feeds_properties
WHERE feed_id = :feed_id WHERE id = :feed_id
""" """
) )
par = (feed_id,) par = (feed_id,)
@ -1885,20 +1886,20 @@ def get_entry_url(db_file, ix):
return url return url
def get_feed_url(db_file, ix): def get_feed_url(db_file, feed_id):
function_name = sys._getframe().f_code.co_name function_name = sys._getframe().f_code.co_name
logger.debug('{}: db_file: {} ix: {}' logger.debug('{}: db_file: {} feed_id: {}'
.format(function_name, db_file, ix)) .format(function_name, db_file, feed_id))
with create_connection(db_file) as conn: with create_connection(db_file) as conn:
cur = conn.cursor() cur = conn.cursor()
sql = ( sql = (
""" """
SELECT url SELECT url
FROM feeds_properties FROM feeds_properties
WHERE id = :ix WHERE id = :feed_id
""" """
) )
par = (ix,) par = (feed_id,)
url = cur.execute(sql, par).fetchone() url = cur.execute(sql, par).fetchone()
return url return url
@ -2355,7 +2356,7 @@ async def update_feed_identifier(db_file, feed_id, identifier):
""" """
UPDATE feeds_properties UPDATE feeds_properties
SET identifier = :identifier SET identifier = :identifier
WHERE feed_id = :feed_id WHERE id = :feed_id
""" """
) )
par = { par = {

View file

@ -1,2 +1,2 @@
__version__ = '0.1.65' __version__ = '0.1.66'
__version_info__ = (0, 1, 65) __version_info__ = (0, 1, 66)

View file

@ -42,7 +42,8 @@ from slixfeed.xmpp.muc import XmppGroupchat
from slixfeed.xmpp.message import XmppMessage from slixfeed.xmpp.message import XmppMessage
from slixfeed.xmpp.presence import XmppPresence from slixfeed.xmpp.presence import XmppPresence
from slixfeed.xmpp.upload import XmppUpload from slixfeed.xmpp.upload import XmppUpload
from slixfeed.xmpp.utility import get_chat_type, is_moderator, is_operator from slixfeed.xmpp.privilege import is_moderator, is_operator, is_access
from slixfeed.xmpp.utility import get_chat_type
import time import time
from random import randrange from random import randrange
@ -720,12 +721,48 @@ class Chat:
key_list = ['status'] key_list = ['status']
await task.start_tasks_xmpp_chat(self, jid_bare, key_list) await task.start_tasks_xmpp_chat(self, jid_bare, key_list)
XmppMessage.send_reply(self, message, response) XmppMessage.send_reply(self, message, response)
case _ if message_lowercase.startswith('pubsub list '):
jid = message_text[12:]
from slixfeed.xmpp.publish import XmppPubsub
iq = await XmppPubsub.get_nodes(self, jid)
response = 'List of nodes for {}:\n```\n'.format(jid)
for item in iq['disco_items']:
item_id = item['node']
item_name = item['name']
response += 'Name: {}\nNode: {}\n\n'.format(item_name, item_id)
response += '```'
XmppMessage.send_reply(self, message, response)
case _ if message_lowercase.startswith('pubsub send '):
if is_operator(self, jid_bare):
info = message_text[12:]
info = info.split(' ')
jid = info[0]
# num = int(info[1])
if jid:
# if num:
# report = await action.xmpp_pubsub_send_unread_items(
# self, jid, num)
# else:
# report = await action.xmpp_pubsub_send_unread_items(
# self, jid)
report = await action.xmpp_pubsub_send_unread_items(
self, jid)
response = ''
for url in report:
if report[url]:
response += url + ' : ' + str(report[url]) + '\n'
else:
response = 'PubSub JID is missing. Enter PubSub JID.'
else:
response = ('This action is restricted. '
'Type: sending news to PubSub.')
XmppMessage.send_reply(self, message, response)
# TODO Handle node error # TODO Handle node error
# sqlite3.IntegrityError: UNIQUE constraint failed: feeds_pubsub.node # sqlite3.IntegrityError: UNIQUE constraint failed: feeds_pubsub.node
# ERROR:slixmpp.basexmpp:UNIQUE constraint failed: feeds_pubsub.node # ERROR:slixmpp.basexmpp:UNIQUE constraint failed: feeds_pubsub.node
case _ if message_lowercase.startswith('send '): case _ if message_lowercase.startswith('pubsub '):
if is_operator(self, jid_bare): if is_operator(self, jid_bare):
info = message_text[5:].split(' ') info = message_text[7:].split(' ')
if len(info) > 1: if len(info) > 1:
jid = info[0] jid = info[0]
if '/' not in jid: if '/' not in jid:
@ -810,7 +847,7 @@ class Chat:
else: else:
response = ('No action has been taken.' response = ('No action has been taken.'
'\n' '\n'
'JID Must not include "/".') 'JID may not include "/".')
else: else:
response = ('No action has been taken.' response = ('No action has been taken.'
'\n' '\n'
@ -823,6 +860,7 @@ class Chat:
XmppMessage.send_reply(self, message, response) XmppMessage.send_reply(self, message, response)
case _ if (message_lowercase.startswith('http') or case _ if (message_lowercase.startswith('http') or
message_lowercase.startswith('feed:/') or message_lowercase.startswith('feed:/') or
message_lowercase.startswith('itpc:/') or
message_lowercase.startswith('rss:/')): message_lowercase.startswith('rss:/')):
url = message_text url = message_text
# task.clean_tasks_xmpp_chat(self, jid_bare, ['status']) # task.clean_tasks_xmpp_chat(self, jid_bare, ['status'])
@ -1029,9 +1067,9 @@ class Chat:
db_file, key, val) db_file, key, val)
response = 'Only new items of newly added feeds be delivered.' response = 'Only new items of newly added feeds be delivered.'
XmppMessage.send_reply(self, message, response) XmppMessage.send_reply(self, message, response)
case _ if message_lowercase.startswith('pubsub delete '): case _ if message_lowercase.startswith('node delete '):
if is_operator(self, jid_bare): if is_operator(self, jid_bare):
info = message_text[14:] info = message_text[12:]
info = info.split(' ') info = info.split(' ')
if len(info) > 2: if len(info) > 2:
jid = info[0] jid = info[0]
@ -1051,20 +1089,9 @@ class Chat:
response = ('This action is restricted. ' response = ('This action is restricted. '
'Type: sending news to PubSub.') 'Type: sending news to PubSub.')
XmppMessage.send_reply(self, message, response) XmppMessage.send_reply(self, message, response)
case _ if message_lowercase.startswith('pubsub list '): case _ if message_lowercase.startswith('node purge '):
jid = message_text[12:]
from slixfeed.xmpp.publish import XmppPubsub
iq = await XmppPubsub.get_nodes(self, jid)
response = 'List of nodes for {}:\n```\n'.format(jid)
for item in iq['disco_items']:
item_id = item['node']
item_name = item['name']
response += 'Name: {}\nNode: {}\n\n'.format(item_name, item_id)
response += '```'
XmppMessage.send_reply(self, message, response)
case _ if message_lowercase.startswith('pubsub purge '):
if is_operator(self, jid_bare): if is_operator(self, jid_bare):
info = message_text[13:] info = message_text[11:]
info = info.split(' ') info = info.split(' ')
if len(info) > 1: if len(info) > 1:
jid = info[0] jid = info[0]
@ -1084,29 +1111,6 @@ class Chat:
response = ('This action is restricted. ' response = ('This action is restricted. '
'Type: sending news to PubSub.') 'Type: sending news to PubSub.')
XmppMessage.send_reply(self, message, response) XmppMessage.send_reply(self, message, response)
case _ if message_lowercase.startswith('pubsub flash '):
if is_operator(self, jid_bare):
info = message_text[13:]
info = info.split(' ')
jid = info[0]
num = int(info[1])
if jid:
if num:
report = await action.xmpp_pubsub_send_unread_items(
self, jid, num)
else:
report = await action.xmpp_pubsub_send_unread_items(
self, jid)
response = ''
for url in report:
if report[url]:
response += url + ' : ' + str(report[url]) + '\n'
else:
response = 'PubSub JID is missing. Enter PubSub JID.'
else:
response = ('This action is restricted. '
'Type: sending news to PubSub.')
XmppMessage.send_reply(self, message, response)
case _ if message_lowercase.startswith('next'): case _ if message_lowercase.startswith('next'):
num = message_text[5:] num = message_text[5:]
if num: if num:

View file

@ -59,7 +59,8 @@ from slixfeed.xmpp.publish import XmppPubsub
from slixfeed.xmpp.roster import XmppRoster from slixfeed.xmpp.roster import XmppRoster
# import slixfeed.xmpp.service as service # import slixfeed.xmpp.service as service
from slixfeed.xmpp.presence import XmppPresence from slixfeed.xmpp.presence import XmppPresence
from slixfeed.xmpp.utility import get_chat_type, is_operator from slixfeed.xmpp.privilege import is_operator, is_access
from slixfeed.xmpp.utility import get_chat_type
import sys import sys
import time import time
@ -87,7 +88,8 @@ from slixfeed.xmpp.message import XmppMessage
from slixfeed.xmpp.presence import XmppPresence from slixfeed.xmpp.presence import XmppPresence
from slixfeed.xmpp.roster import XmppRoster from slixfeed.xmpp.roster import XmppRoster
from slixfeed.xmpp.upload import XmppUpload from slixfeed.xmpp.upload import XmppUpload
from slixfeed.xmpp.utility import get_chat_type, is_moderator from slixfeed.xmpp.privilege import is_moderator, is_operator, is_access
from slixfeed.xmpp.utility import get_chat_type
main_task = [] main_task = []
jid_tasker = {} jid_tasker = {}
@ -305,6 +307,9 @@ class Slixfeed(slixmpp.ClientXMPP):
await self['xep_0115'].update_caps() await self['xep_0115'].update_caps()
# self.send_presence() # self.send_presence()
await self.get_roster() await self.get_roster()
# XmppCommand.adhoc_commands(self)
# self.service_reactions()
task.task_ping(self)
results = await XmppPubsub.get_pubsub_services(self) results = await XmppPubsub.get_pubsub_services(self)
for result in results + [{'jid' : self.boundjid.bare, for result in results + [{'jid' : self.boundjid.bare,
'name' : self.alias}]: 'name' : self.alias}]:
@ -313,13 +318,10 @@ class Slixfeed(slixmpp.ClientXMPP):
db_file = config.get_pathname_to_database(jid_bare) db_file = config.get_pathname_to_database(jid_bare)
Config.add_settings_jid(self.settings, jid_bare, db_file) Config.add_settings_jid(self.settings, jid_bare, db_file)
await task.start_tasks_xmpp_pubsub(self, jid_bare) await task.start_tasks_xmpp_pubsub(self, jid_bare)
# XmppCommand.adhoc_commands(self)
# self.service_reactions()
bookmarks = await XmppBookmark.get_bookmarks(self) bookmarks = await XmppBookmark.get_bookmarks(self)
print('iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii') print('iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii')
await action.xmpp_muc_autojoin(self, bookmarks) await action.xmpp_muc_autojoin(self, bookmarks)
print('ooooooooooooooooooooooooooooooooo') print('ooooooooooooooooooooooooooooooooo')
task.task_ping(self)
time_end = time.time() time_end = time.time()
difference = time_end - time_begin difference = time_end - time_begin
if difference > 1: logger.warning('{} (time: {})'.format(function_name, if difference > 1: logger.warning('{} (time: {})'.format(function_name,
@ -818,19 +820,7 @@ class Slixfeed(slixmpp.ClientXMPP):
.format(function_name, jid_full)) .format(function_name, jid_full))
jid_bare = session['from'].bare jid_bare = session['from'].bare
chat_type = await get_chat_type(self, jid_bare) chat_type = await get_chat_type(self, jid_bare)
access = None if is_access(self, jid_bare, jid_full, chat_type):
print('PERMISSION JID : ' + jid_full)
print('PERMISSION CHAT : ' + chat_type)
operator = is_operator(self, jid_bare)
if operator:
if chat_type == 'groupchat':
if is_moderator(self, jid_bare, jid_full):
access = True
print('PERMISSION MOD')
else:
access = True
print('PERMISSION OP')
if access:
form = self['xep_0004'].make_form('form', 'PubSub') form = self['xep_0004'].make_form('form', 'PubSub')
form['instructions'] = 'Publish news items to PubSub nodes.' form['instructions'] = 'Publish news items to PubSub nodes.'
options = form.add_field(desc='From which medium source do you ' options = form.add_field(desc='From which medium source do you '
@ -844,18 +834,21 @@ class Slixfeed(slixmpp.ClientXMPP):
form.add_field(ftype='fixed', form.add_field(ftype='fixed',
label='* Attention', label='* Attention',
desc='Results are viewed best with Movim and ' desc='Results are viewed best with Movim and '
'Libervia.') 'Libervia.')
session['allow_prev'] = False session['allow_prev'] = False
session['has_next'] = True session['has_next'] = True
session['next'] = self._handle_publish_action session['next'] = self._handle_publish_action
session['prev'] = None session['prev'] = None
session['payload'] = form session['payload'] = form
else: else:
if not operator: if not is_operator(self, jid_bare):
text_warn = 'This resource is restricted to operators.' text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat': elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.' text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare)) .format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else: else:
text_warn = 'This resource is forbidden.' text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
@ -867,7 +860,8 @@ class Slixfeed(slixmpp.ClientXMPP):
logger.debug('{}: jid_full: {}' logger.debug('{}: jid_full: {}'
.format(function_name, jid_full)) .format(function_name, jid_full))
jid_bare = session['from'].bare jid_bare = session['from'].bare
if is_operator(self, jid_bare): chat_type = await get_chat_type(self, jid_bare)
if is_access(self, jid_bare, jid_full, chat_type):
values = payload['values'] values = payload['values']
form = self['xep_0004'].make_form('form', 'Publish') form = self['xep_0004'].make_form('form', 'Publish')
form['instructions'] = ('Choose a PubSub Jabber ID and verify ' form['instructions'] = ('Choose a PubSub Jabber ID and verify '
@ -955,7 +949,16 @@ class Slixfeed(slixmpp.ClientXMPP):
session['has_next'] = True session['has_next'] = True
session['prev'] = self._handle_publish session['prev'] = self._handle_publish
else: else:
text_warn = 'This resource is restricted to operators.' if not is_operator(self, jid_bare):
text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else:
text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
return session return session
@ -970,21 +973,23 @@ class Slixfeed(slixmpp.ClientXMPP):
jid = values['jid'] if 'jid' in values else None jid = values['jid'] if 'jid' in values else None
jid_bare = session['from'].bare jid_bare = session['from'].bare
if jid != jid_bare and not is_operator(self, jid_bare): if jid != jid_bare and not is_operator(self, jid_bare):
text_warn = ('Posting to {} is restricted to operators only.' text_warn = ('Posting to {} is restricted to operators only.'
.format(jid_bare)) # Should not this be self.boundjid.bare? .format(jid_bare)) # Should not this be self.boundjid.bare?
session['allow_prev'] = False session['allow_prev'] = False
session['has_next'] = False session['has_next'] = False
session['next'] = None session['next'] = None
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
session['prev'] = None session['prev'] = None
session['payload'] = None session['payload'] = None
return session return session
jid_file = values['jid_file'] jid_file = values['jid_file']
node = values['node'] node = values['node']
# xep = values['xep'] # xep = values['xep']
if not node: if not node:
if jid == self.boundjid.bare: if jid == self.boundjid.bare:
node = 'urn:xmpp:microblog:0' node = 'urn:xmpp:microblog:0'
else:
node = 'slixfeed'
form = self['xep_0004'].make_form('form', 'Publish') form = self['xep_0004'].make_form('form', 'Publish')
form.add_field(var='node', form.add_field(var='node',
@ -1039,14 +1044,15 @@ class Slixfeed(slixmpp.ClientXMPP):
#if jid: jid = jid[0] if isinstance(jid, list) else jid #if jid: jid = jid[0] if isinstance(jid, list) else jid
jid_bare = session['from'].bare jid_bare = session['from'].bare
if jid != jid_bare and not is_operator(self, jid_bare): if jid != jid_bare and not is_operator(self, jid_bare):
text_warn = 'You are not suppose to be here.' # TODO Report incident
session['allow_prev'] = False text_warn = 'You are not suppose to be here.'
session['has_next'] = False session['allow_prev'] = False
session['next'] = None session['has_next'] = False
session['notes'] = [['warn', text_warn]] session['next'] = None
session['prev'] = None session['notes'] = [['warn', text_warn]]
session['payload'] = None session['prev'] = None
return session session['payload'] = None
return session
# xep = values['xep'][0] # xep = values['xep'][0]
# xep = None # xep = None
@ -1073,15 +1079,17 @@ class Slixfeed(slixmpp.ClientXMPP):
jid = values['jid'] if 'jid' in values else None jid = values['jid'] if 'jid' in values else None
jid_bare = session['from'].bare jid_bare = session['from'].bare
if jid != jid_bare and not is_operator(self, jid_bare): if jid != jid_bare and not is_operator(self, jid_bare):
text_warn = ('Posting to {} is restricted to operators only.' # TODO Report incident
.format(jid_bare)) # Should not this be self.boundjid.bare? text_warn = 'You are not suppose to be here.'
session['allow_prev'] = False # text_warn = ('Posting to {} is restricted to operators only.'
session['has_next'] = False # .format(jid_bare)) # Should not this be self.boundjid.bare?
session['next'] = None session['allow_prev'] = False
session['notes'] = [['warn', text_warn]] session['has_next'] = False
session['prev'] = None session['next'] = None
session['payload'] = None session['notes'] = [['warn', text_warn]]
return session session['prev'] = None
session['payload'] = None
return session
node = values['node'] node = values['node']
url = values['url'] url = values['url']
# xep = values['xep'] # xep = values['xep']
@ -1197,14 +1205,15 @@ class Slixfeed(slixmpp.ClientXMPP):
#if jid: jid = jid[0] if isinstance(jid, list) else jid #if jid: jid = jid[0] if isinstance(jid, list) else jid
jid_bare = session['from'].bare jid_bare = session['from'].bare
if jid != jid_bare and not is_operator(self, jid_bare): if jid != jid_bare and not is_operator(self, jid_bare):
text_warn = 'You are not suppose to be here.' # TODO Report incident
session['allow_prev'] = False text_warn = 'You are not suppose to be here.'
session['has_next'] = False session['allow_prev'] = False
session['next'] = None session['has_next'] = False
session['notes'] = [['warn', text_warn]] session['next'] = None
session['prev'] = None session['notes'] = [['warn', text_warn]]
session['payload'] = None session['prev'] = None
return session session['payload'] = None
return session
url = values['url'][0] url = values['url'][0]
# xep = values['xep'][0] # xep = values['xep'][0]
xep = None xep = None
@ -1364,10 +1373,7 @@ class Slixfeed(slixmpp.ClientXMPP):
.format(function_name, jid_full)) .format(function_name, jid_full))
jid_bare = session['from'].bare jid_bare = session['from'].bare
chat_type = await get_chat_type(self, jid_bare) chat_type = await get_chat_type(self, jid_bare)
moderator = None if is_access(self, jid_bare, jid_full, chat_type):
if chat_type == 'groupchat':
moderator = is_moderator(self, jid_bare, jid_full)
if chat_type == 'chat' or moderator:
jid = session['from'].bare jid = session['from'].bare
jid_file = jid jid_file = jid
db_file = config.get_pathname_to_database(jid_file) db_file = config.get_pathname_to_database(jid_file)
@ -1407,8 +1413,16 @@ class Slixfeed(slixmpp.ClientXMPP):
session['next'] = self._handle_filters_complete session['next'] = self._handle_filters_complete
session['payload'] = form session['payload'] = form
else: else:
text_warn = ('This resource is restricted to moderators of {}.' if not is_operator(self, jid_bare):
.format(jid)) text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else:
text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
return session return session
@ -1470,10 +1484,7 @@ class Slixfeed(slixmpp.ClientXMPP):
.format(function_name, jid_full)) .format(function_name, jid_full))
jid_bare = session['from'].bare jid_bare = session['from'].bare
chat_type = await get_chat_type(self, jid_bare) chat_type = await get_chat_type(self, jid_bare)
moderator = None if is_access(self, jid_bare, jid_full, chat_type):
if chat_type == 'groupchat':
moderator = is_moderator(self, jid_bare, jid_full)
if chat_type == 'chat' or moderator:
form = self['xep_0004'].make_form('form', 'Subscribe') form = self['xep_0004'].make_form('form', 'Subscribe')
# form['instructions'] = 'Add a new custom subscription.' # form['instructions'] = 'Add a new custom subscription.'
form.add_field(desc='Enter a URL.', form.add_field(desc='Enter a URL.',
@ -1515,8 +1526,16 @@ class Slixfeed(slixmpp.ClientXMPP):
session['prev'] = None session['prev'] = None
session['payload'] = form session['payload'] = form
else: else:
text_warn = ('This resource is restricted to moderators of {}.' if not is_operator(self, jid_bare):
.format(jid_bare)) text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else:
text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
return session return session
@ -2047,11 +2066,7 @@ class Slixfeed(slixmpp.ClientXMPP):
.format(function_name, jid_full)) .format(function_name, jid_full))
jid_bare = session['from'].bare jid_bare = session['from'].bare
chat_type = await get_chat_type(self, jid_bare) chat_type = await get_chat_type(self, jid_bare)
moderator = None if is_access(self, jid_bare, jid_full, chat_type):
if chat_type == 'groupchat':
moderator = is_moderator(self, jid_bare, jid_full)
# moderator = moderator if moderator else None
if chat_type == 'chat' or moderator:
form = self['xep_0004'].make_form('form', 'Discover & Search') form = self['xep_0004'].make_form('form', 'Discover & Search')
form['instructions'] = 'Discover news subscriptions of all kinds' form['instructions'] = 'Discover news subscriptions of all kinds'
options = form.add_field(desc='Select type of search.', options = form.add_field(desc='Select type of search.',
@ -2068,8 +2083,16 @@ class Slixfeed(slixmpp.ClientXMPP):
session['payload'] = form session['payload'] = form
session['prev'] = None session['prev'] = None
else: else:
text_warn = ('This resource is restricted to moderators of {}.' if not is_operator(self, jid_bare):
.format(jid_bare)) text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else:
text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
return session return session
@ -2167,10 +2190,7 @@ class Slixfeed(slixmpp.ClientXMPP):
.format(function_name, jid_full)) .format(function_name, jid_full))
jid_bare = session['from'].bare jid_bare = session['from'].bare
chat_type = await get_chat_type(self, jid_bare) chat_type = await get_chat_type(self, jid_bare)
moderator = None if is_access(self, jid_bare, jid_full, chat_type):
if chat_type == 'groupchat':
moderator = is_moderator(self, jid_bare, jid_full)
if chat_type == 'chat' or moderator:
form = self['xep_0004'].make_form('form', 'Subscriptions') form = self['xep_0004'].make_form('form', 'Subscriptions')
form['instructions'] = ('Browse, view, toggle or remove ' form['instructions'] = ('Browse, view, toggle or remove '
'tags and subscriptions.') 'tags and subscriptions.')
@ -2214,8 +2234,16 @@ class Slixfeed(slixmpp.ClientXMPP):
session['next'] = self._handle_subscriptions_result session['next'] = self._handle_subscriptions_result
session['has_next'] = True session['has_next'] = True
else: else:
text_warn = ('This resource is restricted to moderators of {}.' if not is_operator(self, jid_bare):
.format(jid_bare)) text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else:
text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
return session return session
@ -2534,10 +2562,7 @@ class Slixfeed(slixmpp.ClientXMPP):
.format(function_name, jid_full)) .format(function_name, jid_full))
jid_bare = session['from'].bare jid_bare = session['from'].bare
chat_type = await get_chat_type(self, jid_bare) chat_type = await get_chat_type(self, jid_bare)
moderator = None if is_access(self, jid_bare, jid_full, chat_type):
if chat_type == 'groupchat':
moderator = is_moderator(self, jid_bare, jid_full)
if chat_type == 'chat' or moderator:
form = self['xep_0004'].make_form('form', 'Advanced') form = self['xep_0004'].make_form('form', 'Advanced')
form['instructions'] = 'Extended options' form['instructions'] = 'Extended options'
options = form.add_field(ftype='list-single', options = form.add_field(ftype='list-single',
@ -2558,8 +2583,16 @@ class Slixfeed(slixmpp.ClientXMPP):
session['next'] = self._handle_advanced_result session['next'] = self._handle_advanced_result
session['prev'] = self._handle_advanced session['prev'] = self._handle_advanced
else: else:
text_warn = ('This resource is restricted to moderators of {}.' if not is_operator(self, jid_bare):
.format(jid_bare)) text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else:
text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
return session return session
@ -2942,10 +2975,7 @@ class Slixfeed(slixmpp.ClientXMPP):
jid_bare = session['from'].bare jid_bare = session['from'].bare
jid_full = str(session['from']) jid_full = str(session['from'])
chat_type = await get_chat_type(self, jid_bare) chat_type = await get_chat_type(self, jid_bare)
moderator = None if is_access(self, jid_bare, jid_full, chat_type):
if chat_type == 'groupchat':
moderator = is_moderator(self, jid_bare, jid_full)
if chat_type == 'chat' or moderator:
form = self['xep_0004'].make_form('form', 'Subscribe') form = self['xep_0004'].make_form('form', 'Subscribe')
# NOTE Refresh button would be of use # NOTE Refresh button would be of use
form['instructions'] = 'Featured subscriptions' form['instructions'] = 'Featured subscriptions'
@ -2996,8 +3026,16 @@ class Slixfeed(slixmpp.ClientXMPP):
session['payload'] = form session['payload'] = form
session['prev'] = self._handle_promoted session['prev'] = self._handle_promoted
else: else:
text_warn = ('This resource is restricted to moderators of {}.' if not is_operator(self, jid_bare):
.format(jid_bare)) text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else:
text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
return session return session
@ -3640,10 +3678,7 @@ class Slixfeed(slixmpp.ClientXMPP):
.format(function_name, jid_full)) .format(function_name, jid_full))
jid_bare = session['from'].bare jid_bare = session['from'].bare
chat_type = await get_chat_type(self, jid_bare) chat_type = await get_chat_type(self, jid_bare)
moderator = None if is_access(self, jid_bare, jid_full, chat_type):
if chat_type == 'groupchat':
moderator = is_moderator(self, jid_bare, jid_full)
if chat_type == 'chat' or moderator:
jid_file = jid_bare jid_file = jid_bare
db_file = config.get_pathname_to_database(jid_file) db_file = config.get_pathname_to_database(jid_file)
if jid_bare not in self.settings: if jid_bare not in self.settings:
@ -3742,8 +3777,16 @@ class Slixfeed(slixmpp.ClientXMPP):
session['next'] = self._handle_settings_complete session['next'] = self._handle_settings_complete
session['payload'] = form session['payload'] = form
else: else:
text_warn = ('This resource is restricted to moderators of {}.' if not is_operator(self, jid_bare):
.format(jid_bare)) text_warn = 'This resource is restricted to operators.'
elif chat_type == 'groupchat':
text_warn = ('This resource is restricted to moderators of {}.'
.format(jid_bare))
elif chat_type == 'error':
text_warn = ('Could not determine chat type of {}.'
.format(jid_bare))
else:
text_warn = 'This resource is forbidden.'
session['notes'] = [['warn', text_warn]] session['notes'] = [['warn', text_warn]]
return session return session

View file

@ -8,7 +8,10 @@ class XmppIQ:
async def send(self, iq): async def send(self, iq):
try: try:
await iq.send(timeout=5) await iq.send(timeout=15)
except (IqError, IqTimeout) as e: except IqTimeout as e:
logging.error('Error Timeout')
logging.error(str(e))
except IqError as e:
logging.error('Error XmppIQ') logging.error('Error XmppIQ')
logging.error(str(e)) logging.error(str(e))

View file

@ -0,0 +1,49 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
def is_access(self, jid_bare, jid_full, chat_type):
"""Determine access privilege"""
operator = is_operator(self, jid_bare)
if operator:
if chat_type == 'groupchat':
if is_moderator(self, jid_bare, jid_full):
access = True
else:
access = True
else:
access = False
return access
def is_operator(self, jid_bare):
"""Check if given JID is an operator"""
result = False
for operator in self.operators:
if jid_bare == operator['jid']:
result = True
# operator_name = operator['name']
break
return result
def is_moderator(self, jid_bare, jid_full):
"""Check if given JID is a moderator"""
alias = jid_full[jid_full.index('/')+1:]
role = self.plugin['xep_0045'].get_jid_property(jid_bare, alias, 'role')
if role == 'moderator':
result = True
else:
result = False
return result
def is_member(self, jid_bare, jid_full):
"""Check if given JID is a member"""
alias = jid_full[jid_full.index('/')+1:]
affiliation = self.plugin['xep_0045'].get_jid_property(jid_bare, alias, 'affiliation')
if affiliation == 'member':
result = True
else:
result = False
return result

View file

@ -28,18 +28,30 @@ TODO
import glob import glob
from slixfeed.config import Config from slixfeed.config import Config
import slixfeed.config as config import slixfeed.config as config
# from slixmpp.exceptions import IqTimeout, IqError from slixmpp.exceptions import IqTimeout, IqError
# import logging import logging
import os import os
# class XmppProfile: # class XmppProfile:
async def update(self): async def update(self):
""" """ Update profile """
Update profile. try:
""" await set_vcard(self)
await set_vcard(self) except IqTimeout as e:
await set_avatar(self) logging.error('Profile vCard: Error Timeout')
logging.error(str(e))
except IqError as e:
logging.error('Profile vCard: Error XmppIQ')
logging.error(str(e))
try:
await set_avatar(self)
except IqTimeout as e:
logging.error('Profile Photo: Error Timeout')
logging.error(str(e))
except IqError as e:
logging.error('Profile Photo: Error XmppIQ')
logging.error(str(e))
async def set_avatar(self): async def set_avatar(self):

View file

@ -42,6 +42,12 @@ class XmppPubsub:
return properties return properties
async def get_node_configuration(self, jid, node_id):
node = await self.plugin['xep_0060'].get_node_config(jid, node_id)
print(node)
return node
async def get_nodes(self, jid): async def get_nodes(self, jid):
nodes = await self.plugin['xep_0060'].get_nodes(jid) nodes = await self.plugin['xep_0060'].get_nodes(jid)
# 'self' would lead to slixmpp.jid.InvalidJID: idna validation failed: # 'self' would lead to slixmpp.jid.InvalidJID: idna validation failed:

View file

@ -8,36 +8,6 @@ import logging
# class XmppUtility: # class XmppUtility:
def is_operator(self, jid_bare):
result = False
for operator in self.operators:
if jid_bare == operator['jid']:
result = True
# operator_name = operator['name']
break
return result
def is_moderator(self, jid_bare, jid_full):
alias = jid_full[jid_full.index('/')+1:]
role = self.plugin['xep_0045'].get_jid_property(jid_bare, alias, 'role')
if role == 'moderator':
result = True
else:
result = False
return result
def is_member(self, jid_bare, jid_full):
alias = jid_full[jid_full.index('/')+1:]
affiliation = self.plugin['xep_0045'].get_jid_property(jid_bare, alias, 'affiliation')
if affiliation == 'member':
result = True
else:
result = False
return result
# TODO Rename to get_jid_type # TODO Rename to get_jid_type
async def get_chat_type(self, jid): async def get_chat_type(self, jid):
""" """
@ -58,8 +28,8 @@ async def get_chat_type(self, jid):
Returns Returns
------- -------
chat_type : str result : str
'chat' or 'groupchat'. 'chat' or 'groupchat' or 'error'.
""" """
try: try:
iqresult = await self["xep_0030"].get_info(jid=jid) iqresult = await self["xep_0030"].get_info(jid=jid)
@ -68,28 +38,19 @@ async def get_chat_type(self, jid):
# if 'account' in indentity: # if 'account' in indentity:
# if 'conference' in indentity: # if 'conference' in indentity:
if ('http://jabber.org/protocol/muc' in features) and not ('/' in jid): if ('http://jabber.org/protocol/muc' in features) and not ('/' in jid):
chat_type = "groupchat" result = "groupchat"
# TODO elif <feature var='jabber:iq:gateway'/> # TODO elif <feature var='jabber:iq:gateway'/>
# NOTE Is it needed? We do not interact with gateways or services # NOTE Is it needed? We do not interact with gateways or services
else: else:
chat_type = "chat" result = "chat"
logging.info('Jabber ID: {}\n' logging.info('Jabber ID: {}\n'
'Chat Type: {}'.format(jid, chat_type)) 'Chat Type: {}'.format(jid, result))
return chat_type except (IqError, IqTimeout) as e:
# TODO Test whether this exception is realized logging.error(str(e))
except IqError as e: logging.error(jid)
message = ('IQ Error\n' result = 'error'
'IQ Stanza: {}'
'Jabber ID: {}'
.format(e, jid))
logging.error(message)
except IqTimeout as e:
message = ('IQ Timeout\n'
'IQ Stanza: {}'
'Jabber ID: {}'
.format(e, jid))
logging.error(message)
# except BaseException as e: # except BaseException as e:
# logging.error('BaseException', str(e)) # logging.error('BaseException', str(e))
# finally: # finally:
# logging.info('Chat type is:', chat_type) # logging.info('Chat type is:', chat_type)
return result