forked from sch/Slixfeed
Python : Add support for newer OMEMO (Thank you. Syndance);
Python : Fix Ad-Hoc Commands; SQLite : Fix tagging mechanism.
This commit is contained in:
parent
178f49cb86
commit
c050c765dd
8 changed files with 216 additions and 60 deletions
|
@ -47,7 +47,6 @@ dependencies = [
|
||||||
"feedparser",
|
"feedparser",
|
||||||
"lxml",
|
"lxml",
|
||||||
"python-dateutil",
|
"python-dateutil",
|
||||||
"requests",
|
|
||||||
"slixmpp",
|
"slixmpp",
|
||||||
"tomli", # Python 3.10
|
"tomli", # Python 3.10
|
||||||
"tomli_w",
|
"tomli_w",
|
||||||
|
@ -59,14 +58,7 @@ Repository = "https://git.xmpp-it.net/sch/Slixfeed"
|
||||||
Issues = "https://gitgud.io/sjehuda/slixfeed/issues"
|
Issues = "https://gitgud.io/sjehuda/slixfeed/issues"
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
omemo = [
|
omemo = ["slixmpp-omemo"]
|
||||||
"DoubleRatchet>=0.7.0,<0.8",
|
|
||||||
"OMEMO>=0.13.0,<0.15",
|
|
||||||
"protobuf==3.20.3",
|
|
||||||
"slixmpp-omemo",
|
|
||||||
"X3DH>=0.5.9,<0.6",
|
|
||||||
"XEdDSA<0.5,>=0.4.7",
|
|
||||||
]
|
|
||||||
proxy = ["pysocks"]
|
proxy = ["pysocks"]
|
||||||
|
|
||||||
# [project.readme]
|
# [project.readme]
|
||||||
|
|
|
@ -366,7 +366,7 @@ def create_tables(db_file):
|
||||||
id INTEGER NOT NULL,
|
id INTEGER NOT NULL,
|
||||||
feed_id INTEGER NOT NULL,
|
feed_id INTEGER NOT NULL,
|
||||||
tag_id INTEGER NOT NULL,
|
tag_id INTEGER NOT NULL,
|
||||||
FOREIGN KEY ("feed_id") REFERENCES "feeds" ("id")
|
FOREIGN KEY ("feed_id") REFERENCES "feeds_properties" ("id")
|
||||||
ON UPDATE CASCADE
|
ON UPDATE CASCADE
|
||||||
ON DELETE CASCADE,
|
ON DELETE CASCADE,
|
||||||
FOREIGN KEY ("tag_id") REFERENCES "tags" ("id")
|
FOREIGN KEY ("tag_id") REFERENCES "tags" ("id")
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
__version__ = '0.1.95'
|
__version__ = '0.1.96'
|
||||||
__version_info__ = (0, 1, 95)
|
__version_info__ = (0, 1, 96)
|
||||||
|
|
|
@ -154,18 +154,23 @@ class XmppChat:
|
||||||
# await compose.message(self, jid_bare, message)
|
# await compose.message(self, jid_bare, message)
|
||||||
|
|
||||||
if self.omemo_present and self['xep_0384'].is_encrypted(message):
|
if self.omemo_present and self['xep_0384'].is_encrypted(message):
|
||||||
allow_untrusted=True # Temporary fix. This should be handled by "retry""
|
command, omemo_decrypted = await XmppOmemo.decrypt(
|
||||||
command, omemo_decrypted, retry = await XmppOmemo.decrypt(
|
self, message)
|
||||||
self, message, allow_untrusted)
|
|
||||||
if retry:
|
|
||||||
command, omemo_decrypted, retry = await XmppOmemo.decrypt(
|
|
||||||
self, message, allow_untrusted=True)
|
|
||||||
else:
|
else:
|
||||||
omemo_decrypted = None
|
omemo_decrypted = None
|
||||||
|
|
||||||
if message_type == 'groupchat':
|
if message_type == 'groupchat':
|
||||||
command = command[1:]
|
command = command[1:]
|
||||||
|
|
||||||
|
if isinstance(command, str):
|
||||||
command_lowercase = command.lower()
|
command_lowercase = command.lower()
|
||||||
|
elif isinstance(command, Message):
|
||||||
|
command_lowercase = command['body'].lower()
|
||||||
|
|
||||||
|
# This is a work-around to empty messages that are caused by function
|
||||||
|
# self.register_handler(CoroutineCallback( of module client.py.
|
||||||
|
# The code was taken from the cho bot xample of slixmpp-omemo.
|
||||||
|
#if not command_lowercase: return
|
||||||
|
|
||||||
logger.debug([message_from.full, ':', command])
|
logger.debug([message_from.full, ':', command])
|
||||||
|
|
||||||
|
@ -363,7 +368,7 @@ class XmppChat:
|
||||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||||
if self.omemo_present and encrypted:
|
if self.omemo_present and encrypted:
|
||||||
url_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
url_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
self, message_from, url)
|
self, message_from, 'chat', url)
|
||||||
XmppMessage.send_omemo_oob(self, message_from, url_encrypted, chat_type)
|
XmppMessage.send_omemo_oob(self, message_from, url_encrypted, chat_type)
|
||||||
else:
|
else:
|
||||||
XmppMessage.send_oob(self, jid_bare, url, chat_type)
|
XmppMessage.send_oob(self, jid_bare, url, chat_type)
|
||||||
|
@ -632,7 +637,7 @@ class XmppChat:
|
||||||
encrypted = True if encrypt_omemo else False
|
encrypted = True if encrypt_omemo else False
|
||||||
if self.omemo_present and encrypted and self['xep_0384'].is_encrypted(message):
|
if self.omemo_present and encrypted and self['xep_0384'].is_encrypted(message):
|
||||||
response_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
response_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
self, message_from, response)
|
self, message_from, 'chat', response)
|
||||||
if omemo_decrypted and omemo_encrypted:
|
if omemo_decrypted and omemo_encrypted:
|
||||||
# message_from = message['from']
|
# message_from = message['from']
|
||||||
# message_type = message['type']
|
# message_type = message['type']
|
||||||
|
@ -737,7 +742,7 @@ class XmppChatAction:
|
||||||
if media_url and news_digest:
|
if media_url and news_digest:
|
||||||
if self.omemo_present and encrypt_omemo:
|
if self.omemo_present and encrypt_omemo:
|
||||||
news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
self, jid, news_digest)
|
self, jid, 'chat', news_digest)
|
||||||
if self.omemo_present and encrypt_omemo and omemo_encrypted:
|
if self.omemo_present and encrypt_omemo and omemo_encrypted:
|
||||||
XmppMessage.send_omemo(self, jid, chat_type, news_digest_encrypted)
|
XmppMessage.send_omemo(self, jid, chat_type, news_digest_encrypted)
|
||||||
else:
|
else:
|
||||||
|
@ -777,7 +782,7 @@ class XmppChatAction:
|
||||||
# media_url_new = await XmppUpload.start(
|
# media_url_new = await XmppUpload.start(
|
||||||
# self, jid_bare, Path(pathname), filesize, encrypted=encrypted)
|
# self, jid_bare, Path(pathname), filesize, encrypted=encrypted)
|
||||||
media_url_new_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
media_url_new_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
self, jid, media_url_new)
|
self, jid, 'chat', media_url_new)
|
||||||
if media_url_new_encrypted and omemo_encrypted:
|
if media_url_new_encrypted and omemo_encrypted:
|
||||||
# NOTE Tested against Gajim.
|
# NOTE Tested against Gajim.
|
||||||
# FIXME This only works with aesgcm URLs, and it does
|
# FIXME This only works with aesgcm URLs, and it does
|
||||||
|
@ -801,7 +806,7 @@ class XmppChatAction:
|
||||||
if news_digest:
|
if news_digest:
|
||||||
if self.omemo_present and encrypt_omemo:
|
if self.omemo_present and encrypt_omemo:
|
||||||
news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
self, jid, news_digest)
|
self, jid, 'chat', news_digest)
|
||||||
if self.omemo_present and encrypt_omemo and omemo_encrypted:
|
if self.omemo_present and encrypt_omemo and omemo_encrypted:
|
||||||
XmppMessage.send_omemo(self, jid, chat_type, news_digest_encrypted)
|
XmppMessage.send_omemo(self, jid, chat_type, news_digest_encrypted)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -145,22 +145,40 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
self.register_plugin('xep_0115') # Entity Capabilities
|
self.register_plugin('xep_0115') # Entity Capabilities
|
||||||
self.register_plugin('xep_0122') # Data Forms Validation
|
self.register_plugin('xep_0122') # Data Forms Validation
|
||||||
self.register_plugin('xep_0153') # vCard-Based Avatars
|
self.register_plugin('xep_0153') # vCard-Based Avatars
|
||||||
self.register_plugin('xep_0199', {'keepalive': True}) # XMPP Ping
|
self.register_plugin('xep_0199', # XMPP Ping
|
||||||
|
{'keepalive': True})
|
||||||
self.register_plugin('xep_0203') # Delayed Delivery
|
self.register_plugin('xep_0203') # Delayed Delivery
|
||||||
self.register_plugin('xep_0249') # Direct MUC Invitations
|
self.register_plugin('xep_0249') # Direct MUC Invitations
|
||||||
self.register_plugin('xep_0363') # HTTP File Upload
|
self.register_plugin('xep_0363') # HTTP File Upload
|
||||||
|
self.register_plugin('xep_0380') # Explicit Message Encryption
|
||||||
self.register_plugin('xep_0402') # PEP Native Bookmarks
|
self.register_plugin('xep_0402') # PEP Native Bookmarks
|
||||||
self.register_plugin('xep_0444') # Message Reactions
|
self.register_plugin('xep_0444') # Message Reactions
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from slixfeed.xmpp.encryption import XmppOmemo
|
|
||||||
import slixmpp_omemo
|
import slixmpp_omemo
|
||||||
from slixmpp_omemo import PluginCouldNotLoad
|
|
||||||
self.omemo_present = True
|
self.omemo_present = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('Encryption of type OMEMO is not enabled. Reason: ' + str(e))
|
print('Encryption of type OMEMO is not enabled. Reason: ' + str(e))
|
||||||
self.omemo_present = False
|
self.omemo_present = False
|
||||||
|
|
||||||
|
if self.omemo_present:
|
||||||
|
#from slixmpp.xmlstream.handler import CoroutineCallback
|
||||||
|
#from slixmpp.xmlstream.matcher import MatchXPath
|
||||||
|
#self.register_handler(CoroutineCallback(
|
||||||
|
# 'Messages',
|
||||||
|
# MatchXPath(f'{{{self.default_ns}}}message'),
|
||||||
|
# self.on_message # type: ignore[arg-type]
|
||||||
|
#))
|
||||||
|
|
||||||
|
from slixfeed.xmpp.encryption import XEP_0384Impl
|
||||||
|
from slixfeed.xmpp.encryption import XmppOmemo
|
||||||
|
import slixfeed.xmpp.encryption as slixfeed_xmpp_encryption
|
||||||
|
from slixmpp.plugins import register_plugin
|
||||||
|
register_plugin(XEP_0384Impl)
|
||||||
|
self.register_plugin('xep_0384', # OMEMO Encryption
|
||||||
|
module=XEP_0384Impl)
|
||||||
|
|
||||||
|
"""
|
||||||
if self.omemo_present:
|
if self.omemo_present:
|
||||||
try:
|
try:
|
||||||
self.register_plugin(
|
self.register_plugin(
|
||||||
|
@ -177,7 +195,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
except slixmpp.plugins.base.PluginNotFound:
|
except slixmpp.plugins.base.PluginNotFound:
|
||||||
logger.error('Could not load xep_0454. Ensure you have '
|
logger.error('Could not load xep_0454. Ensure you have '
|
||||||
'\'cryptography\' from extras_require installed.')
|
'\'cryptography\' from extras_require installed.')
|
||||||
|
"""
|
||||||
# proxy_enabled = config.get_value('accounts', 'XMPP', 'proxy_enabled')
|
# proxy_enabled = config.get_value('accounts', 'XMPP', 'proxy_enabled')
|
||||||
# if proxy_enabled == '1':
|
# if proxy_enabled == '1':
|
||||||
# values = config.get_value('accounts', 'XMPP', [
|
# values = config.get_value('accounts', 'XMPP', [
|
||||||
|
@ -870,6 +888,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
# http://jabber.org/protocol/commands#actions
|
# http://jabber.org/protocol/commands#actions
|
||||||
|
|
||||||
async def _handle_publish(self, iq, session):
|
async def _handle_publish(self, iq, session):
|
||||||
|
jid = session['from']
|
||||||
jid_full = session['from'].full
|
jid_full = session['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
logger.debug('{}: jid_full: {}'
|
logger.debug('{}: jid_full: {}'
|
||||||
|
@ -911,6 +930,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
async def _handle_publish_action(self, payload, session):
|
async def _handle_publish_action(self, payload, session):
|
||||||
|
jid = session['from']
|
||||||
jid_full = session['from'].full
|
jid_full = session['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
logger.debug('{}: jid_full: {}'
|
logger.debug('{}: jid_full: {}'
|
||||||
|
@ -1340,7 +1360,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
form.add_field(label='Active',
|
form.add_field(label='Active',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=feeds_act)
|
value=feeds_act)
|
||||||
entries = sqlite.get_number_of_items(db_file, 'entries_properties')
|
entries = str(sqlite.get_number_of_items(db_file, 'entries_properties'))
|
||||||
form.add_field(label='Items',
|
form.add_field(label='Items',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=entries)
|
value=entries)
|
||||||
|
@ -1350,44 +1370,35 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
value=unread)
|
value=unread)
|
||||||
form.add_field(ftype='fixed',
|
form.add_field(ftype='fixed',
|
||||||
label='Options')
|
label='Options')
|
||||||
key_archive = Config.get_setting_value(self, jid_bare, 'archive')
|
key_archive = str(Config.get_setting_value(self, jid_bare, 'archive'))
|
||||||
key_archive = str(key_archive)
|
|
||||||
form.add_field(label='Archive',
|
form.add_field(label='Archive',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=key_archive)
|
value=key_archive)
|
||||||
key_enabled = Config.get_setting_value(self, jid_bare, 'enabled')
|
key_enabled = str(Config.get_setting_value(self, jid_bare, 'enabled'))
|
||||||
key_enabled = str(key_enabled)
|
|
||||||
form.add_field(label='Enabled',
|
form.add_field(label='Enabled',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=key_enabled)
|
value=key_enabled)
|
||||||
key_interval = Config.get_setting_value(self, jid_bare, 'interval')
|
key_interval = str(Config.get_setting_value(self, jid_bare, 'interval'))
|
||||||
key_interval = str(key_interval)
|
|
||||||
form.add_field(label='Interval',
|
form.add_field(label='Interval',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=key_interval)
|
value=key_interval)
|
||||||
key_length = Config.get_setting_value(self, jid_bare, 'length')
|
key_length = str(Config.get_setting_value(self, jid_bare, 'length'))
|
||||||
key_length = str(key_length)
|
|
||||||
form.add_field(label='Length',
|
form.add_field(label='Length',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=key_length)
|
value=key_length)
|
||||||
key_media = Config.get_setting_value(self, jid_bare, 'media')
|
key_media = str(Config.get_setting_value(self, jid_bare, 'media'))
|
||||||
key_media = str(key_media)
|
|
||||||
form.add_field(label='Media',
|
form.add_field(label='Media',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=key_media)
|
value=key_media)
|
||||||
key_old = Config.get_setting_value(self, jid_bare, 'old')
|
key_old = str(Config.get_setting_value(self, jid_bare, 'old'))
|
||||||
key_old = str(key_old)
|
|
||||||
form.add_field(label='Old',
|
form.add_field(label='Old',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=key_old)
|
value=key_old)
|
||||||
key_quantum = Config.get_setting_value(self, jid_bare, 'quantum')
|
key_quantum = str(Config.get_setting_value(self, jid_bare, 'quantum'))
|
||||||
key_quantum = str(key_quantum)
|
|
||||||
form.add_field(label='Quantum',
|
form.add_field(label='Quantum',
|
||||||
ftype='text-single',
|
ftype='text-single',
|
||||||
value=key_quantum)
|
value=key_quantum)
|
||||||
update_interval = Config.get_setting_value(self, jid_bare, 'interval')
|
update_interval = 60 * Config.get_setting_value(self, jid_bare, 'interval')
|
||||||
update_interval = str(update_interval)
|
|
||||||
update_interval = 60 * int(update_interval)
|
|
||||||
last_update_time = sqlite.get_last_update_time(db_file)
|
last_update_time = sqlite.get_last_update_time(db_file)
|
||||||
if last_update_time:
|
if last_update_time:
|
||||||
last_update_time = float(last_update_time)
|
last_update_time = float(last_update_time)
|
||||||
|
@ -2930,7 +2941,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||||
if encrypted:
|
if encrypted:
|
||||||
url_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
url_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
self, JID(jid_bare), url)
|
self, JID(jid_bare), 'chat', url)
|
||||||
XmppMessage.send_omemo_oob(self, JID(jid_bare), url_encrypted, chat_type)
|
XmppMessage.send_omemo_oob(self, JID(jid_bare), url_encrypted, chat_type)
|
||||||
else:
|
else:
|
||||||
XmppMessage.send_oob(self, jid_bare, url, chat_type)
|
XmppMessage.send_oob(self, jid_bare, url, chat_type)
|
||||||
|
|
|
@ -23,18 +23,19 @@ TODO
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from omemo.exceptions import MissingBundleException
|
import json
|
||||||
|
from omemo.storage import Just, Maybe, Nothing, Storage
|
||||||
|
from omemo.types import DeviceInformation, JSONType
|
||||||
from slixfeed.log import Logger
|
from slixfeed.log import Logger
|
||||||
from slixmpp import JID
|
from slixmpp import JID
|
||||||
from slixmpp.exceptions import IqTimeout, IqError
|
from slixmpp.exceptions import IqTimeout, IqError
|
||||||
|
#from slixmpp.plugins import register_plugin
|
||||||
from slixmpp.stanza import Message
|
from slixmpp.stanza import Message
|
||||||
from slixmpp_omemo import MissingOwnKey, EncryptionPrepareException
|
from slixmpp_omemo import TrustLevel, XEP_0384
|
||||||
from slixmpp_omemo import UndecidedException, UntrustedException, NoAvailableSession
|
from typing import Any, Dict, FrozenSet, Literal, Optional, Union
|
||||||
|
|
||||||
|
|
||||||
logger = Logger(__name__)
|
logger = Logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# for task in main_task:
|
# for task in main_task:
|
||||||
# task.cancel()
|
# task.cancel()
|
||||||
|
|
||||||
|
@ -46,7 +47,59 @@ logger = Logger(__name__)
|
||||||
class XmppOmemo:
|
class XmppOmemo:
|
||||||
|
|
||||||
|
|
||||||
async def decrypt(self, message: Message, allow_untrusted: bool = False):
|
async def decrypt(self, stanza: Message):
|
||||||
|
|
||||||
|
omemo_decrypted = None
|
||||||
|
|
||||||
|
mto = stanza["from"]
|
||||||
|
mtype = stanza["type"]
|
||||||
|
|
||||||
|
namespace = self['xep_0384'].is_encrypted(stanza)
|
||||||
|
if namespace is None:
|
||||||
|
omemo_decrypted = False
|
||||||
|
response = f"Unencrypted message or unsupported message encryption: {stanza['body']}"
|
||||||
|
else:
|
||||||
|
print(f'Message in namespace {namespace} received: {stanza}')
|
||||||
|
try:
|
||||||
|
response, device_information = await self['xep_0384'].decrypt_message(stanza)
|
||||||
|
print(f'Information about sender: {device_information}')
|
||||||
|
omemo_decrypted = True
|
||||||
|
except Exception as e: # pylint: disable=broad-exception-caught
|
||||||
|
response = f'Error {type(e).__name__}: {e}'
|
||||||
|
|
||||||
|
return response, omemo_decrypted
|
||||||
|
|
||||||
|
|
||||||
|
async def encrypt(
|
||||||
|
self,
|
||||||
|
mto: JID,
|
||||||
|
mtype: Literal['chat', 'normal'],
|
||||||
|
mbody: str
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
if isinstance(mbody, str):
|
||||||
|
reply = self.make_message(mto=mto, mtype=mtype)
|
||||||
|
reply['body'] = mbody
|
||||||
|
|
||||||
|
reply.set_to(mto)
|
||||||
|
reply.set_from(self.boundjid)
|
||||||
|
|
||||||
|
# It might be a good idea to strip everything except for the body from the stanza,
|
||||||
|
# since some things might break when echoed.
|
||||||
|
message, encryption_errors = await self['xep_0384'].encrypt_message(reply, mto)
|
||||||
|
|
||||||
|
if len(encryption_errors) > 0:
|
||||||
|
print(f'There were non-critical errors during encryption: {encryption_errors}')
|
||||||
|
# log.info(f'There were non-critical errors during encryption: {encryption_errors}')
|
||||||
|
|
||||||
|
# for namespace, message in messages.items():
|
||||||
|
# message['eme']['namespace'] = namespace
|
||||||
|
# message['eme']['name'] = self['xep_0380'].mechanisms[namespace]
|
||||||
|
|
||||||
|
return message, True
|
||||||
|
|
||||||
|
|
||||||
|
async def _decrypt(self, message: Message, allow_untrusted: bool = False):
|
||||||
jid = message['from']
|
jid = message['from']
|
||||||
try:
|
try:
|
||||||
print('XmppOmemo.decrypt')
|
print('XmppOmemo.decrypt')
|
||||||
|
@ -124,7 +177,7 @@ class XmppOmemo:
|
||||||
return response, omemo_decrypted, retry
|
return response, omemo_decrypted, retry
|
||||||
|
|
||||||
|
|
||||||
async def encrypt(self, jid: JID, message_body):
|
async def _encrypt(self, jid: JID, message_body):
|
||||||
print(jid)
|
print(jid)
|
||||||
print(message_body)
|
print(message_body)
|
||||||
expect_problems = {} # type: Optional[Dict[JID, List[int]]]
|
expect_problems = {} # type: Optional[Dict[JID, List[int]]]
|
||||||
|
@ -192,3 +245,95 @@ class XmppOmemo:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
return message_body, omemo_encrypted
|
return message_body, omemo_encrypted
|
||||||
|
|
||||||
|
|
||||||
|
class StorageImpl(Storage):
|
||||||
|
"""
|
||||||
|
Example storage implementation that stores all data in a single JSON file.
|
||||||
|
"""
|
||||||
|
|
||||||
|
JSON_FILE = "/home/admin/omemo-echo-client.json"
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.__data: Dict[str, JSONType] = {}
|
||||||
|
try:
|
||||||
|
with open(self.JSON_FILE, encoding="utf8") as f:
|
||||||
|
self.__data = json.load(f)
|
||||||
|
except Exception: # pylint: disable=broad-exception-caught
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def _load(self, key: str) -> Maybe[JSONType]:
|
||||||
|
if key in self.__data:
|
||||||
|
return Just(self.__data[key])
|
||||||
|
|
||||||
|
return Nothing()
|
||||||
|
|
||||||
|
async def _store(self, key: str, value: JSONType) -> None:
|
||||||
|
self.__data[key] = value
|
||||||
|
with open(self.JSON_FILE, "w", encoding="utf8") as f:
|
||||||
|
json.dump(self.__data, f)
|
||||||
|
|
||||||
|
async def _delete(self, key: str) -> None:
|
||||||
|
self.__data.pop(key, None)
|
||||||
|
with open(self.JSON_FILE, "w", encoding="utf8") as f:
|
||||||
|
json.dump(self.__data, f)
|
||||||
|
|
||||||
|
|
||||||
|
class XEP_0384Impl(XEP_0384): # pylint: disable=invalid-name
|
||||||
|
"""
|
||||||
|
Example implementation of the OMEMO plugin for Slixmpp.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, *args: Any, **kwargs: Any) -> None: # pylint: disable=redefined-outer-name
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# Just the type definition here
|
||||||
|
self.__storage: Storage
|
||||||
|
|
||||||
|
def plugin_init(self) -> None:
|
||||||
|
self.__storage = StorageImpl()
|
||||||
|
|
||||||
|
super().plugin_init()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def storage(self) -> Storage:
|
||||||
|
return self.__storage
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _btbv_enabled(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def _devices_blindly_trusted(
|
||||||
|
self,
|
||||||
|
blindly_trusted: FrozenSet[DeviceInformation],
|
||||||
|
identifier: Optional[str]
|
||||||
|
) -> None:
|
||||||
|
log.info(f"[{identifier}] Devices trusted blindly: {blindly_trusted}")
|
||||||
|
|
||||||
|
async def _prompt_manual_trust(
|
||||||
|
self,
|
||||||
|
manually_trusted: FrozenSet[DeviceInformation],
|
||||||
|
identifier: Optional[str]
|
||||||
|
) -> None:
|
||||||
|
# Since BTBV is enabled and we don't do any manual trust adjustments in the example, this method
|
||||||
|
# should never be called. All devices should be automatically trusted blindly by BTBV.
|
||||||
|
|
||||||
|
# To show how a full implementation could look like, the following code will prompt for a trust
|
||||||
|
# decision using `input`:
|
||||||
|
session_mananger = await self.get_session_manager()
|
||||||
|
|
||||||
|
for device in manually_trusted:
|
||||||
|
while True:
|
||||||
|
answer = input(f"[{identifier}] Trust the following device? (yes/no) {device}")
|
||||||
|
if answer in { "yes", "no" }:
|
||||||
|
await session_mananger.set_trust(
|
||||||
|
device.bare_jid,
|
||||||
|
device.identity_key,
|
||||||
|
TrustLevel.TRUSTED.value if answer == "yes" else TrustLevel.DISTRUSTED.value
|
||||||
|
)
|
||||||
|
break
|
||||||
|
print("Please answer yes or no.")
|
||||||
|
|
||||||
|
#register_plugin(XEP_0384Impl)
|
||||||
|
|
|
@ -41,14 +41,17 @@ class XmppMessage:
|
||||||
|
|
||||||
|
|
||||||
def send_omemo(self, jid: JID, chat_type, response_encrypted):
|
def send_omemo(self, jid: JID, chat_type, response_encrypted):
|
||||||
jid_from = str(self.boundjid) if self.is_component else None
|
# jid_from = str(self.boundjid) if self.is_component else None
|
||||||
message = self.make_message(mto=jid, mfrom=jid_from, mtype=chat_type)
|
# message = self.make_message(mto=jid, mfrom=jid_from, mtype=chat_type)
|
||||||
eme_ns = 'eu.siacs.conversations.axolotl'
|
# eme_ns = 'eu.siacs.conversations.axolotl'
|
||||||
# message['eme']['namespace'] = eme_ns
|
# message['eme']['namespace'] = eme_ns
|
||||||
# message['eme']['name'] = self['xep_0380'].mechanisms[eme_ns]
|
# message['eme']['name'] = self['xep_0380'].mechanisms[eme_ns]
|
||||||
message['eme'] = {'namespace': eme_ns}
|
|
||||||
# message['eme'] = {'name': self['xep_0380'].mechanisms[eme_ns]}
|
# message['eme'] = {'name': self['xep_0380'].mechanisms[eme_ns]}
|
||||||
message.append(response_encrypted)
|
# message['eme'] = {'namespace': eme_ns}
|
||||||
|
# message.append(response_encrypted)
|
||||||
|
for namespace, message in response_encrypted.items():
|
||||||
|
message['eme']['namespace'] = namespace
|
||||||
|
message['eme']['name'] = self['xep_0380'].mechanisms[namespace]
|
||||||
message.send()
|
message.send()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ class XmppUtilities:
|
||||||
access = True if XmppUtilities.is_moderator(self, room, alias) else False
|
access = True if XmppUtilities.is_moderator(self, room, alias) else False
|
||||||
if access: print('Access granted to groupchat moderator ' + alias)
|
if access: print('Access granted to groupchat moderator ' + alias)
|
||||||
else:
|
else:
|
||||||
print('Access granted to chat ' + jid_bare)
|
print('Access granted to chat jid ' + jid_bare)
|
||||||
access = True
|
access = True
|
||||||
return access
|
return access
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue