forked from sch/Slixfeed
[WIP] Add OMEMO encryption;
Various of improvements and fixes.
This commit is contained in:
parent
37444c9d4e
commit
5e20b2830d
13 changed files with 682 additions and 190 deletions
|
@ -20,14 +20,15 @@ Slixfeed is primarily designed for XMPP (aka Jabber), yet it is built to be exte
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Visual interface** - Interactive interface for XMPP using Ad-Hoc Commands,
|
|
||||||
- **Ease** - Slixfeed automatically scans (i.e. crawls) for syndication feeds of given URL.
|
- **Ease** - Slixfeed automatically scans (i.e. crawls) for syndication feeds of given URL.
|
||||||
|
- **Encryption** - Messages are encrypted with the OMEMO standard.
|
||||||
- **Export** - Download articles as ePUB, HTML, Markdown and PDF.
|
- **Export** - Download articles as ePUB, HTML, Markdown and PDF.
|
||||||
- **Filtering** - Filter news items using lists of allow and deny.
|
- **Filtering** - Filter news items using lists of allow and deny.
|
||||||
- **Multimedia** - Display audios pictures and videos inline.
|
- **Multimedia** - Display audios pictures and videos inline.
|
||||||
- **Privacy** - Redirect to alternative back-ends, such as Invidious, Librarian, Nitter, for increased privacy, productivity and security.
|
- **Privacy** - Redirect to alternative back-ends, such as Invidious, Librarian, Nitter, for increased privacy, productivity and security.
|
||||||
- **Portable** - Export and import feeds with a standard OPML file.
|
- **Portable** - Export and import feeds with a standard OPML file.
|
||||||
- **Simultaneous** - Slixfeed is designed to handle multiple contacts, including groupchats, Simultaneously.
|
- **Simultaneous** - Slixfeed is designed to handle multiple contacts, including groupchats, Simultaneously.
|
||||||
|
- **Visual interface** - Interactive interface for XMPP using Ad-Hoc Commands,
|
||||||
|
|
||||||
## Preview
|
## Preview
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ interval = 300 # Update interval (Minimum value 10)
|
||||||
length = 300 # Maximum length of summary (Value 0 to disable)
|
length = 300 # Maximum length of summary (Value 0 to disable)
|
||||||
media = 0 # Display media (audio, image, video) when available
|
media = 0 # Display media (audio, image, video) when available
|
||||||
old = 0 # Mark entries of newly added entries as unread
|
old = 0 # Mark entries of newly added entries as unread
|
||||||
|
omemo = 1 # Encrypt messages with OMEMO
|
||||||
quantum = 3 # Amount of entries per update
|
quantum = 3 # Amount of entries per update
|
||||||
random = 0 # Pick random item from database
|
random = 0 # Pick random item from database
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,71 @@ class ConfigJabberID:
|
||||||
settings[jid_bare][key] = value
|
settings[jid_bare][key] = value
|
||||||
|
|
||||||
|
|
||||||
|
class Data:
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_data_directory():
|
||||||
|
"""
|
||||||
|
Determine the directory path where dbfile will be stored.
|
||||||
|
|
||||||
|
* If $XDG_DATA_HOME is defined, use it;
|
||||||
|
* else if $HOME exists, use it;
|
||||||
|
* else if the platform is Windows, use %APPDATA%;
|
||||||
|
* else use the current directory.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
Path to database file.
|
||||||
|
|
||||||
|
Note
|
||||||
|
----
|
||||||
|
This function was taken from project buku.
|
||||||
|
|
||||||
|
See https://github.com/jarun/buku
|
||||||
|
|
||||||
|
* Arun Prakash Jana (jarun)
|
||||||
|
* Dmitry Marakasov (AMDmi3)
|
||||||
|
"""
|
||||||
|
# data_home = xdg.BaseDirectory.xdg_data_home
|
||||||
|
data_home = os.environ.get('XDG_DATA_HOME')
|
||||||
|
if data_home is None:
|
||||||
|
if os.environ.get('HOME') is None:
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
data_home = os.environ.get('APPDATA')
|
||||||
|
if data_home is None:
|
||||||
|
return os.path.abspath('.slixfeed/data')
|
||||||
|
else:
|
||||||
|
return os.path.abspath('.slixfeed/data')
|
||||||
|
else:
|
||||||
|
data_home = os.path.join(
|
||||||
|
os.environ.get('HOME'), '.local', 'share'
|
||||||
|
)
|
||||||
|
return os.path.join(data_home, 'slixfeed')
|
||||||
|
|
||||||
|
|
||||||
|
def get_pathname_to_omemo_directory():
|
||||||
|
"""
|
||||||
|
Get OMEMO directory.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
object
|
||||||
|
Coroutine object.
|
||||||
|
"""
|
||||||
|
db_dir = get_default_data_directory()
|
||||||
|
if not os.path.isdir(db_dir):
|
||||||
|
os.mkdir(db_dir)
|
||||||
|
if not os.path.isdir(db_dir + "/omemo"):
|
||||||
|
os.mkdir(db_dir + "/omemo")
|
||||||
|
omemo_dir = os.path.join(db_dir, "omemo")
|
||||||
|
return omemo_dir
|
||||||
|
|
||||||
|
|
||||||
def get_values(filename, key=None):
|
def get_values(filename, key=None):
|
||||||
config_dir = get_default_config_directory()
|
config_dir = get_default_config_directory()
|
||||||
if not os.path.isdir(config_dir):
|
if not os.path.isdir(config_dir):
|
||||||
|
|
|
@ -45,6 +45,8 @@ from asyncio import TimeoutError
|
||||||
import requests
|
import requests
|
||||||
import slixfeed.config as config
|
import slixfeed.config as config
|
||||||
from slixfeed.log import Logger
|
from slixfeed.log import Logger
|
||||||
|
# import urllib.request
|
||||||
|
# from urllib.error import HTTPError
|
||||||
|
|
||||||
logger = Logger(__name__)
|
logger = Logger(__name__)
|
||||||
|
|
||||||
|
@ -55,7 +57,6 @@ except:
|
||||||
"Package magnet2torrent was not found.\n"
|
"Package magnet2torrent was not found.\n"
|
||||||
"BitTorrent is disabled.")
|
"BitTorrent is disabled.")
|
||||||
|
|
||||||
|
|
||||||
# class Dat:
|
# class Dat:
|
||||||
# async def dat():
|
# async def dat():
|
||||||
|
|
||||||
|
@ -68,52 +69,151 @@ except:
|
||||||
# class Gopher:
|
# class Gopher:
|
||||||
# async def gopher():
|
# async def gopher():
|
||||||
|
|
||||||
# class Http:
|
|
||||||
# async def http():
|
|
||||||
|
|
||||||
# class Ipfs:
|
# class Ipfs:
|
||||||
# async def ipfs():
|
# async def ipfs():
|
||||||
|
|
||||||
|
|
||||||
def http_response(url):
|
class Http:
|
||||||
"""
|
|
||||||
Download response headers.
|
|
||||||
|
|
||||||
Parameters
|
|
||||||
----------
|
|
||||||
url : str
|
|
||||||
URL.
|
|
||||||
|
|
||||||
Returns
|
# def fetch_media(url, pathname):
|
||||||
-------
|
# try:
|
||||||
response: requests.models.Response
|
# urllib.request.urlretrieve(url, pathname)
|
||||||
HTTP Header Response.
|
# status = 1
|
||||||
|
# except HTTPError as e:
|
||||||
|
# logger.error(e)
|
||||||
|
# status = 0
|
||||||
|
# return status
|
||||||
|
|
||||||
Result would contain these:
|
|
||||||
response.encoding
|
async def fetch_headers(url):
|
||||||
response.headers
|
network_settings = config.get_values('settings.toml', 'network')
|
||||||
response.history
|
user_agent = (network_settings['user_agent'] or 'Slixfeed/0.1')
|
||||||
response.reason
|
headers = {'User-Agent': user_agent}
|
||||||
response.status_code
|
proxy = (network_settings['http_proxy'] or None)
|
||||||
response.url
|
timeout = ClientTimeout(total=10)
|
||||||
"""
|
async with ClientSession(headers=headers) as session:
|
||||||
user_agent = (
|
async with session.get(url, proxy=proxy,
|
||||||
config.get_value(
|
# proxy_auth=(proxy_username, proxy_password),
|
||||||
"settings", "Network", "user_agent")
|
timeout=timeout
|
||||||
) or 'Slixfeed/0.1'
|
) as response:
|
||||||
headers = {
|
headers = response.headers
|
||||||
"User-Agent": user_agent
|
return headers
|
||||||
}
|
# print("Headers for URL:", url)
|
||||||
try:
|
# for header_name, header_value in headers.items():
|
||||||
# Do not use HEAD request because it appears that too many sites would
|
# print(f"{header_name}: {header_value}")
|
||||||
# deny it.
|
|
||||||
# response = requests.head(url, headers=headers, allow_redirects=True)
|
|
||||||
response = requests.get(url, headers=headers, allow_redirects=True)
|
# TODO Write file to disk. Consider aiofiles
|
||||||
except Exception as e:
|
async def fetch_media(url, pathname):
|
||||||
logger.warning('Error in HTTP response')
|
"""
|
||||||
logger.error(e)
|
Download media content of given URL.
|
||||||
response = None
|
|
||||||
return response
|
Parameters
|
||||||
|
----------
|
||||||
|
url : str
|
||||||
|
URL.
|
||||||
|
pathname : list
|
||||||
|
Pathname (including filename) to save content to.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
msg: list or str
|
||||||
|
Document or error message.
|
||||||
|
"""
|
||||||
|
network_settings = config.get_values('settings.toml', 'network')
|
||||||
|
user_agent = (network_settings['user_agent'] or 'Slixfeed/0.1')
|
||||||
|
headers = {'User-Agent': user_agent}
|
||||||
|
proxy = (network_settings['http_proxy'] or None)
|
||||||
|
timeout = ClientTimeout(total=10)
|
||||||
|
async with ClientSession(headers=headers) as session:
|
||||||
|
# async with ClientSession(trust_env=True) as session:
|
||||||
|
try:
|
||||||
|
async with session.get(url, proxy=proxy,
|
||||||
|
# proxy_auth=(proxy_username, proxy_password),
|
||||||
|
timeout=timeout
|
||||||
|
) as response:
|
||||||
|
status = response.status
|
||||||
|
if status in (200, 201):
|
||||||
|
try:
|
||||||
|
result = {'charset': response.charset,
|
||||||
|
'content_length': response.content_length,
|
||||||
|
'content_type': response.content_type,
|
||||||
|
'error': False,
|
||||||
|
'message': None,
|
||||||
|
'original_url': url,
|
||||||
|
'status_code': status,
|
||||||
|
'response_url': response.url}
|
||||||
|
except:
|
||||||
|
result = {'error': True,
|
||||||
|
'message': 'Could not get document.',
|
||||||
|
'original_url': url,
|
||||||
|
'status_code': status,
|
||||||
|
'response_url': response.url}
|
||||||
|
else:
|
||||||
|
result = {'error': True,
|
||||||
|
'message': 'HTTP Error:' + str(status),
|
||||||
|
'original_url': url,
|
||||||
|
'status_code': status,
|
||||||
|
'response_url': response.url}
|
||||||
|
except ClientError as e:
|
||||||
|
result = {'error': True,
|
||||||
|
'message': 'Error:' + str(e) if e else 'ClientError',
|
||||||
|
'original_url': url,
|
||||||
|
'status_code': None}
|
||||||
|
except TimeoutError as e:
|
||||||
|
result = {'error': True,
|
||||||
|
'message': 'Timeout:' + str(e) if e else 'TimeoutError',
|
||||||
|
'original_url': url,
|
||||||
|
'status_code': None}
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
result = {'error': True,
|
||||||
|
'message': 'Error:' + str(e) if e else 'Error',
|
||||||
|
'original_url': url,
|
||||||
|
'status_code': None}
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def http_response(url):
|
||||||
|
"""
|
||||||
|
Download response headers.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
url : str
|
||||||
|
URL.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
response: requests.models.Response
|
||||||
|
HTTP Header Response.
|
||||||
|
|
||||||
|
Result would contain these:
|
||||||
|
response.encoding
|
||||||
|
response.headers
|
||||||
|
response.history
|
||||||
|
response.reason
|
||||||
|
response.status_code
|
||||||
|
response.url
|
||||||
|
"""
|
||||||
|
user_agent = (
|
||||||
|
config.get_value(
|
||||||
|
"settings", "Network", "user_agent")
|
||||||
|
) or 'Slixfeed/0.1'
|
||||||
|
headers = {
|
||||||
|
"User-Agent": user_agent
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
# Do not use HEAD request because it appears that too many sites would
|
||||||
|
# deny it.
|
||||||
|
# response = requests.head(url, headers=headers, allow_redirects=True)
|
||||||
|
response = requests.get(url, headers=headers, allow_redirects=True)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning('Error in HTTP response')
|
||||||
|
logger.error(e)
|
||||||
|
response = None
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
async def http(url):
|
async def http(url):
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
__version__ = '0.1.86'
|
__version__ = '0.1.87'
|
||||||
__version_info__ = (0, 1, 86)
|
__version_info__ = (0, 1, 87)
|
||||||
|
|
|
@ -24,19 +24,26 @@ TODO
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
from random import randrange # pending_tasks: Use a list and read the first index (i.e. index 0).
|
from random import randrange # pending_tasks: Use a list and read the first index (i.e. index 0).
|
||||||
import slixfeed.config as config
|
import slixfeed.config as config
|
||||||
from slixfeed.config import Config
|
from slixfeed.config import Config
|
||||||
|
import slixfeed.fetch as fetch
|
||||||
|
from slixfeed.fetch import Http
|
||||||
from slixfeed.log import Logger
|
from slixfeed.log import Logger
|
||||||
import slixfeed.sqlite as sqlite
|
import slixfeed.sqlite as sqlite
|
||||||
from slixfeed.syndication import FeedTask
|
from slixfeed.syndication import FeedTask
|
||||||
from slixfeed.utilities import Documentation, Html, MD, Task, Url
|
from slixfeed.utilities import Documentation, Html, MD, Task, Url
|
||||||
from slixfeed.xmpp.commands import XmppCommands
|
from slixfeed.xmpp.commands import XmppCommands
|
||||||
|
from slixfeed.xmpp.encryption import XmppOmemo
|
||||||
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.status import XmppStatusTask
|
from slixfeed.xmpp.status import XmppStatusTask
|
||||||
from slixfeed.xmpp.upload import XmppUpload
|
from slixfeed.xmpp.upload import XmppUpload
|
||||||
from slixfeed.xmpp.utilities import XmppUtilities
|
from slixfeed.xmpp.utilities import XmppUtilities
|
||||||
|
from slixmpp import JID
|
||||||
|
from slixmpp.stanza import Message
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -55,7 +62,7 @@ logger = Logger(__name__)
|
||||||
class XmppChat:
|
class XmppChat:
|
||||||
|
|
||||||
|
|
||||||
async def process_message(self, message):
|
async def process_message(self, message: Message, allow_untrusted: bool = False) -> None:
|
||||||
"""
|
"""
|
||||||
Process incoming message stanzas. Be aware that this also
|
Process incoming message stanzas. Be aware that this also
|
||||||
includes MUC messages and error messages. It is usually
|
includes MUC messages and error messages. It is usually
|
||||||
|
@ -69,8 +76,10 @@ class XmppChat:
|
||||||
for stanza objects and the Message stanza to see
|
for stanza objects and the Message stanza to see
|
||||||
how it may be used.
|
how it may be used.
|
||||||
"""
|
"""
|
||||||
if message['type'] in ('chat', 'groupchat', 'normal'):
|
message_from = message['from']
|
||||||
jid_bare = message['from'].bare
|
message_type = message['type']
|
||||||
|
if message_type in ('chat', 'groupchat', 'normal'):
|
||||||
|
jid_bare = message_from.bare
|
||||||
command = ' '.join(message['body'].split())
|
command = ' '.join(message['body'].split())
|
||||||
command_time_start = time.time()
|
command_time_start = time.time()
|
||||||
|
|
||||||
|
@ -80,14 +89,14 @@ class XmppChat:
|
||||||
|
|
||||||
# FIXME Code repetition. See below.
|
# FIXME Code repetition. See below.
|
||||||
# TODO Check alias by nickname associated with conference
|
# TODO Check alias by nickname associated with conference
|
||||||
if message['type'] == 'groupchat':
|
if message_type == 'groupchat':
|
||||||
if (message['muc']['nick'] == self.alias):
|
if (message['muc']['nick'] == self.alias):
|
||||||
return
|
return
|
||||||
jid_full = str(message['from'])
|
jid_full = message_from.full
|
||||||
if not XmppUtilities.is_moderator(self, jid_bare, jid_full):
|
if not XmppUtilities.is_moderator(self, jid_bare, jid_full):
|
||||||
return
|
return
|
||||||
|
|
||||||
if message['type'] == 'groupchat':
|
if message_type == 'groupchat':
|
||||||
# nick = message['from'][message['from'].index('/')+1:]
|
# nick = message['from'][message['from'].index('/')+1:]
|
||||||
# nick = str(message['from'])
|
# nick = str(message['from'])
|
||||||
# nick = nick[nick.index('/')+1:]
|
# nick = nick[nick.index('/')+1:]
|
||||||
|
@ -109,7 +118,7 @@ class XmppChat:
|
||||||
# if nick not in operator:
|
# if nick not in operator:
|
||||||
# return
|
# return
|
||||||
# approved = False
|
# approved = False
|
||||||
jid_full = str(message['from'])
|
jid_full = message_from.full
|
||||||
if not XmppUtilities.is_moderator(self, jid_bare, jid_full):
|
if not XmppUtilities.is_moderator(self, jid_bare, jid_full):
|
||||||
return
|
return
|
||||||
# if role == 'moderator':
|
# if role == 'moderator':
|
||||||
|
@ -140,17 +149,23 @@ class XmppChat:
|
||||||
|
|
||||||
# await compose.message(self, jid_bare, message)
|
# await compose.message(self, jid_bare, message)
|
||||||
|
|
||||||
|
if self['xep_0384'].is_encrypted(message):
|
||||||
|
command, omemo_decrypted = await XmppOmemo.decrypt(
|
||||||
|
self, message, allow_untrusted)
|
||||||
|
else:
|
||||||
|
omemo_decrypted = None
|
||||||
|
|
||||||
if message['type'] == 'groupchat':
|
if message['type'] == 'groupchat':
|
||||||
command = command[1:]
|
command = command[1:]
|
||||||
command_lowercase = command.lower()
|
command_lowercase = command.lower()
|
||||||
|
|
||||||
logger.debug([str(message['from']), ':', command])
|
logger.debug([message_from.full, ':', command])
|
||||||
|
|
||||||
# Support private message via groupchat
|
# Support private message via groupchat
|
||||||
# See https://codeberg.org/poezio/slixmpp/issues/3506
|
# See https://codeberg.org/poezio/slixmpp/issues/3506
|
||||||
if message['type'] == 'chat' and message.get_plugin('muc', check=True):
|
if message['type'] == 'chat' and message.get_plugin('muc', check=True):
|
||||||
# jid_bare = message['from'].bare
|
# jid_bare = message_from.bare
|
||||||
jid_full = str(message['from'])
|
jid_full = message_from.full
|
||||||
if (jid_bare == jid_full[:jid_full.index('/')]):
|
if (jid_bare == jid_full[:jid_full.index('/')]):
|
||||||
# TODO Count and alert of MUC-PM attempts
|
# TODO Count and alert of MUC-PM attempts
|
||||||
return
|
return
|
||||||
|
@ -217,7 +232,7 @@ class XmppChat:
|
||||||
command = command[4:]
|
command = command[4:]
|
||||||
url = command.split(' ')[0]
|
url = command.split(' ')[0]
|
||||||
title = ' '.join(command.split(' ')[1:])
|
title = ' '.join(command.split(' ')[1:])
|
||||||
response = XmppCommands.feed_add(
|
response = await XmppCommands.feed_add(
|
||||||
url, db_file, jid_bare, title)
|
url, db_file, jid_bare, title)
|
||||||
case _ if command_lowercase.startswith('allow +'):
|
case _ if command_lowercase.startswith('allow +'):
|
||||||
val = command[7:]
|
val = command[7:]
|
||||||
|
@ -327,15 +342,20 @@ class XmppChat:
|
||||||
# self.pending_tasks[jid_bare][self.pending_tasks_counter] = status_message
|
# self.pending_tasks[jid_bare][self.pending_tasks_counter] = status_message
|
||||||
XmppPresence.send(self, jid_bare, status_message,
|
XmppPresence.send(self, jid_bare, status_message,
|
||||||
status_type=status_type)
|
status_type=status_type)
|
||||||
filename, response = XmppCommands.export_feeds(
|
pathname, response = XmppCommands.export_feeds(
|
||||||
jid_bare, ext)
|
jid_bare, ext)
|
||||||
url = await XmppUpload.start(self, jid_bare, filename)
|
encrypt_omemo = Config.get_setting_value(self.settings, jid_bare, 'omemo')
|
||||||
|
encrypted = True if encrypt_omemo else False
|
||||||
|
url = await XmppUpload.start(self, jid_bare, Path(pathname), encrypted=encrypted)
|
||||||
# response = (
|
# response = (
|
||||||
# 'Feeds exported successfully to {}.\n{}'
|
# 'Feeds exported successfully to {}.\n{}'
|
||||||
# ).format(ex, url)
|
# ).format(ex, url)
|
||||||
# XmppMessage.send_oob_reply_message(message, url, response)
|
# XmppMessage.send_oob_reply_message(message, url, response)
|
||||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
if url:
|
||||||
XmppMessage.send_oob(self, jid_bare, url, chat_type)
|
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||||
|
XmppMessage.send_oob(self, jid_bare, url, chat_type)
|
||||||
|
else:
|
||||||
|
response = 'OPML file export has been failed.'
|
||||||
del self.pending_tasks[jid_bare][pending_tasks_num]
|
del self.pending_tasks[jid_bare][pending_tasks_num]
|
||||||
# del self.pending_tasks[jid_bare][self.pending_tasks_counter]
|
# del self.pending_tasks[jid_bare][self.pending_tasks_counter]
|
||||||
XmppStatusTask.restart_task(self, jid_bare)
|
XmppStatusTask.restart_task(self, jid_bare)
|
||||||
|
@ -378,18 +398,18 @@ class XmppChat:
|
||||||
# del self.pending_tasks[jid_bare][self.pending_tasks_counter]
|
# del self.pending_tasks[jid_bare][self.pending_tasks_counter]
|
||||||
XmppStatusTask.restart_task(self, jid_bare)
|
XmppStatusTask.restart_task(self, jid_bare)
|
||||||
case _ if command_lowercase.startswith('pubsub list'):
|
case _ if command_lowercase.startswith('pubsub list'):
|
||||||
jid = command[12:]
|
jid_full_pubsub = command[12:]
|
||||||
response = 'List of nodes for {}:\n```\n'.format(jid)
|
response = 'List of nodes for {}:\n```\n'.format(jid_full_pubsub)
|
||||||
response = await XmppCommands.pubsub_list(self, jid)
|
response = await XmppCommands.pubsub_list(self, jid_full_pubsub)
|
||||||
response += '```'
|
response += '```'
|
||||||
case _ if command_lowercase.startswith('pubsub send'):
|
case _ if command_lowercase.startswith('pubsub send'):
|
||||||
if XmppUtilities.is_operator(self, jid_bare):
|
if XmppUtilities.is_operator(self, jid_bare):
|
||||||
info = command[12:]
|
info = command[12:]
|
||||||
info = info.split(' ')
|
info = info.split(' ')
|
||||||
jid = info[0]
|
jid_full_pubsub = info[0]
|
||||||
# num = int(info[1])
|
# num = int(info[1])
|
||||||
if jid:
|
if jid_full_pubsub:
|
||||||
response = XmppCommands.pubsub_send(self, info, jid)
|
response = XmppCommands.pubsub_send(self, info, jid_full_pubsub)
|
||||||
else:
|
else:
|
||||||
response = ('This action is restricted. '
|
response = ('This action is restricted. '
|
||||||
'Type: sending news to PubSub.')
|
'Type: sending news to PubSub.')
|
||||||
|
@ -581,7 +601,16 @@ class XmppChat:
|
||||||
command_time_finish = time.time()
|
command_time_finish = time.time()
|
||||||
command_time_total = command_time_finish - command_time_start
|
command_time_total = command_time_finish - command_time_start
|
||||||
command_time_total = round(command_time_total, 3)
|
command_time_total = round(command_time_total, 3)
|
||||||
if response: XmppMessage.send_reply(self, message, response)
|
if response:
|
||||||
|
response_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
|
self, message_from, response)
|
||||||
|
if omemo_encrypted and omemo_decrypted:
|
||||||
|
message_from = message['from']
|
||||||
|
message_type = message['type']
|
||||||
|
XmppMessage.send_omemo(self, message_from, message_type, response_encrypted)
|
||||||
|
# XmppMessage.send_omemo_reply(self, message, response_encrypted)
|
||||||
|
else:
|
||||||
|
XmppMessage.send_reply(self, message, response)
|
||||||
if Config.get_setting_value(self.settings, jid_bare, 'finished'):
|
if Config.get_setting_value(self.settings, jid_bare, 'finished'):
|
||||||
response_finished = 'Finished. Total time: {}s'.format(command_time_total)
|
response_finished = 'Finished. Total time: {}s'.format(command_time_total)
|
||||||
XmppMessage.send_reply(self, message, response_finished)
|
XmppMessage.send_reply(self, message, response_finished)
|
||||||
|
@ -616,7 +645,7 @@ class XmppChatAction:
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
jid : str
|
jid_bare : str
|
||||||
Jabber ID.
|
Jabber ID.
|
||||||
num : str, optional
|
num : str, optional
|
||||||
Number. The default is None.
|
Number. The default is None.
|
||||||
|
@ -624,6 +653,9 @@ class XmppChatAction:
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
logger.debug('{}: jid: {} num: {}'.format(function_name, jid_bare, num))
|
logger.debug('{}: jid: {} num: {}'.format(function_name, jid_bare, num))
|
||||||
db_file = config.get_pathname_to_database(jid_bare)
|
db_file = config.get_pathname_to_database(jid_bare)
|
||||||
|
encrypt_omemo = Config.get_setting_value(self.settings, jid_bare, 'omemo')
|
||||||
|
encrypted = True if encrypt_omemo else False
|
||||||
|
jid = JID(jid_bare)
|
||||||
show_media = Config.get_setting_value(self.settings, jid_bare, 'media')
|
show_media = Config.get_setting_value(self.settings, jid_bare, 'media')
|
||||||
if not num:
|
if not num:
|
||||||
num = Config.get_setting_value(self.settings, jid_bare, 'quantum')
|
num = Config.get_setting_value(self.settings, jid_bare, 'quantum')
|
||||||
|
@ -631,7 +663,7 @@ class XmppChatAction:
|
||||||
num = int(num)
|
num = int(num)
|
||||||
results = sqlite.get_unread_entries(db_file, num)
|
results = sqlite.get_unread_entries(db_file, num)
|
||||||
news_digest = ''
|
news_digest = ''
|
||||||
media = None
|
media_url = None
|
||||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||||
for result in results:
|
for result in results:
|
||||||
ix = result[0]
|
ix = result[0]
|
||||||
|
@ -658,20 +690,60 @@ class XmppChatAction:
|
||||||
# elif enclosure:
|
# elif enclosure:
|
||||||
if show_media:
|
if show_media:
|
||||||
if enclosure:
|
if enclosure:
|
||||||
media = enclosure
|
media_url = enclosure
|
||||||
else:
|
else:
|
||||||
media = await Html.extract_image_from_html(url)
|
media_url = await Html.extract_image_from_html(url)
|
||||||
|
|
||||||
if media and news_digest:
|
if media_url and news_digest:
|
||||||
# Send textual message
|
if encrypt_omemo:
|
||||||
XmppMessage.send(self, jid_bare, news_digest, chat_type)
|
news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
|
self, jid, news_digest)
|
||||||
|
if encrypt_omemo and omemo_encrypted:
|
||||||
|
XmppMessage.send_omemo(self, jid, chat_type, news_digest_encrypted)
|
||||||
|
else:
|
||||||
|
# Send textual message
|
||||||
|
XmppMessage.send(self, jid_bare, news_digest, chat_type)
|
||||||
news_digest = ''
|
news_digest = ''
|
||||||
# Send media
|
# Send media
|
||||||
XmppMessage.send_oob(self, jid_bare, media, chat_type)
|
if encrypt_omemo:
|
||||||
media = None
|
cache_dir = config.get_default_cache_directory()
|
||||||
|
filename = media_url.split('/').pop().split('?')[0]
|
||||||
|
pathname = os.path.join(cache_dir, filename)
|
||||||
|
# http_response = await Http.response(media_url)
|
||||||
|
|
||||||
|
# http_headers = await Http.fetch_headers(media_url)
|
||||||
|
# breakpoint()
|
||||||
|
# status = Http.fetch_media(media_url, pathname)
|
||||||
|
# if status:
|
||||||
|
# filesize = os.path.getsize(pathname)
|
||||||
|
# media_url_new = await XmppUpload.start(
|
||||||
|
# self, jid_bare, Path(pathname), filesize, encrypted=encrypted)
|
||||||
|
# else:
|
||||||
|
# media_url_new = media_url
|
||||||
|
|
||||||
|
media_url_new = media_url
|
||||||
|
media_url_new_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
|
self, jid, media_url_new)
|
||||||
|
|
||||||
|
# NOTE Temporary line!
|
||||||
|
XmppMessage.send_omemo_oob(self, jid_bare, media_url_new_encrypted, chat_type)
|
||||||
|
|
||||||
|
|
||||||
|
# if media_url_new_encrypted and omemo_encrypted:
|
||||||
|
# XmppMessage.send_omemo_oob(self, jid, media_url_new_encrypted, chat_type)
|
||||||
|
# elif media_url:
|
||||||
|
# XmppMessage.send_oob(self, jid_bare, media_url_new_encrypted, chat_type)
|
||||||
|
else:
|
||||||
|
XmppMessage.send_oob(self, jid_bare, media_url, chat_type)
|
||||||
|
media_url = None
|
||||||
|
|
||||||
if news_digest:
|
if news_digest:
|
||||||
XmppMessage.send(self, jid_bare, news_digest, chat_type)
|
if encrypt_omemo: news_digest_encrypted, omemo_encrypted = await XmppOmemo.encrypt(
|
||||||
|
self, jid, news_digest)
|
||||||
|
if encrypt_omemo and omemo_encrypted:
|
||||||
|
XmppMessage.send_omemo(self, jid, chat_type, news_digest_encrypted)
|
||||||
|
else:
|
||||||
|
XmppMessage.send(self, jid_bare, news_digest, chat_type)
|
||||||
# TODO Add while loop to assure delivery.
|
# TODO Add while loop to assure delivery.
|
||||||
# print(await current_time(), ">>> ACT send_message",jid)
|
# print(await current_time(), ">>> ACT send_message",jid)
|
||||||
# NOTE Do we need "if statement"? See NOTE at is_muc.
|
# NOTE Do we need "if statement"? See NOTE at is_muc.
|
||||||
|
|
|
@ -31,8 +31,9 @@ NOTE
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import os
|
|
||||||
from feedparser import parse
|
from feedparser import parse
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
import slixmpp
|
import slixmpp
|
||||||
# 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_0402 import BookmarkStorage, Conference
|
||||||
|
@ -42,8 +43,9 @@ import slixmpp
|
||||||
# import xml.etree.ElementTree as ET
|
# import xml.etree.ElementTree as ET
|
||||||
# from lxml import etree
|
# from lxml import etree
|
||||||
|
|
||||||
|
from omemo.exceptions import MissingBundleException
|
||||||
import slixfeed.config as config
|
import slixfeed.config as config
|
||||||
from slixfeed.config import Config
|
from slixfeed.config import Config, Data
|
||||||
import slixfeed.fetch as fetch
|
import slixfeed.fetch as fetch
|
||||||
from slixfeed.log import Logger
|
from slixfeed.log import Logger
|
||||||
import slixfeed.sqlite as sqlite
|
import slixfeed.sqlite as sqlite
|
||||||
|
@ -66,6 +68,9 @@ from slixfeed.xmpp.roster import XmppRoster
|
||||||
from slixfeed.xmpp.status import XmppStatusTask
|
from slixfeed.xmpp.status import XmppStatusTask
|
||||||
from slixfeed.xmpp.upload import XmppUpload
|
from slixfeed.xmpp.upload import XmppUpload
|
||||||
from slixfeed.xmpp.utilities import XmppUtilities
|
from slixfeed.xmpp.utilities import XmppUtilities
|
||||||
|
import slixmpp_omemo
|
||||||
|
from slixmpp_omemo import PluginCouldNotLoad, MissingOwnKey, EncryptionPrepareException
|
||||||
|
from slixmpp_omemo import UndecidedException, UntrustedException, NoAvailableSession
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
@ -147,6 +152,21 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
self.register_plugin('xep_0363') # HTTP File Upload
|
self.register_plugin('xep_0363') # HTTP File Upload
|
||||||
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:
|
||||||
|
self.register_plugin(
|
||||||
|
'xep_0384',
|
||||||
|
{
|
||||||
|
'data_dir': Data.get_pathname_to_omemo_directory(),
|
||||||
|
},
|
||||||
|
module=slixmpp_omemo,) # OMEMO Encryption
|
||||||
|
except (PluginCouldNotLoad,):
|
||||||
|
logger.error('An error has occured when loading the OMEMO plugin.')
|
||||||
|
sys.exit(1)
|
||||||
|
try:
|
||||||
|
self.register_plugin('xep_0454')
|
||||||
|
except slixmpp.plugins.base.PluginNotFound:
|
||||||
|
logger.error('Could not load xep_0454. Ensure you have '
|
||||||
|
'\'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':
|
||||||
|
@ -230,7 +250,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
# TODO Test
|
# TODO Test
|
||||||
async def on_groupchat_invite(self, message):
|
async def on_groupchat_invite(self, message):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(message['from'])
|
jid_full = message['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -268,7 +288,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
# NOTE Tested with Gajim and Psi
|
# NOTE Tested with Gajim and Psi
|
||||||
async def on_groupchat_direct_invite(self, message):
|
async def on_groupchat_direct_invite(self, message):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(message['from'])
|
jid_full = message['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -366,7 +386,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
async def on_disco_info(self, DiscoInfo):
|
async def on_disco_info(self, DiscoInfo):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(DiscoInfo['from'])
|
jid_full = DiscoInfo['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -381,7 +401,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
async def on_message(self, message):
|
async def on_message(self, message):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(message['from'])
|
jid_full = message['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -427,7 +447,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
async def on_changed_status(self, presence):
|
async def on_changed_status(self, presence):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(presence['from'])
|
jid_full = presence['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -452,7 +472,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
async def on_presence_subscribe(self, presence):
|
async def on_presence_subscribe(self, presence):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(presence['from'])
|
jid_full = presence['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -475,7 +495,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def on_presence_subscribed(self, presence):
|
def on_presence_subscribed(self, presence):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(presence['from'])
|
jid_full = presence['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -497,7 +517,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
async def on_presence_available(self, presence):
|
async def on_presence_available(self, presence):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(presence['from'])
|
jid_full = presence['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -521,7 +541,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def on_presence_unsubscribed(self, presence):
|
def on_presence_unsubscribed(self, presence):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(presence['from'])
|
jid_full = presence['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -542,7 +562,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def on_presence_unavailable(self, presence):
|
def on_presence_unavailable(self, presence):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(presence['from'])
|
jid_full = presence['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -570,7 +590,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
# If bookmarks, remove groupchat JID into file
|
# If bookmarks, remove groupchat JID into file
|
||||||
def on_presence_error(self, presence):
|
def on_presence_error(self, presence):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(presence['from'])
|
jid_full = presence['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -590,7 +610,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
async def on_chatstate_active(self, message):
|
async def on_chatstate_active(self, message):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(message['from'])
|
jid_full = message['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -613,7 +633,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
async def on_chatstate_composing(self, message):
|
async def on_chatstate_composing(self, message):
|
||||||
# print('on_chatstate_composing START')
|
# print('on_chatstate_composing START')
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(message['from'])
|
jid_full = message['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -636,7 +656,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def on_chatstate_gone(self, message):
|
def on_chatstate_gone(self, message):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(message['from'])
|
jid_full = message['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -653,7 +673,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def on_chatstate_inactive(self, message):
|
def on_chatstate_inactive(self, message):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(message['from'])
|
jid_full = message['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -670,7 +690,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
def on_chatstate_paused(self, message):
|
def on_chatstate_paused(self, message):
|
||||||
time_begin = time.time()
|
time_begin = time.time()
|
||||||
jid_full = str(message['from'])
|
jid_full = message['from'].full
|
||||||
function_name = sys._getframe().f_code.co_name
|
function_name = sys._getframe().f_code.co_name
|
||||||
message_log = '{}: jid_full: {}'
|
message_log = '{}: jid_full: {}'
|
||||||
logger.debug(message_log.format(function_name, jid_full))
|
logger.debug(message_log.format(function_name, jid_full))
|
||||||
|
@ -832,7 +852,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_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -873,7 +893,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_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -981,7 +1001,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
async def _handle_publish_db_preview(self, payload, session):
|
async def _handle_publish_db_preview(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1089,7 +1109,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_publish_url_preview(self, payload, session):
|
async def _handle_publish_url_preview(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1281,7 +1301,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
async def _handle_profile(self, iq, session):
|
async def _handle_profile(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1383,7 +1403,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
return session
|
return session
|
||||||
|
|
||||||
async def _handle_filters(self, iq, session):
|
async def _handle_filters(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1456,7 +1476,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
session. Additional, custom data may be saved
|
session. Additional, custom data may be saved
|
||||||
here to persist across handler callbacks.
|
here to persist across handler callbacks.
|
||||||
"""
|
"""
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1492,7 +1512,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscription_add(self, iq, session):
|
async def _handle_subscription_add(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1555,7 +1575,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_recent(self, iq, session):
|
async def _handle_recent(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1606,7 +1626,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_recent_result(self, payload, session):
|
async def _handle_recent_result(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1663,7 +1683,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
# FIXME
|
# FIXME
|
||||||
async def _handle_recent_select(self, payload, session):
|
async def _handle_recent_select(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1736,7 +1756,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscription_new(self, payload, session):
|
async def _handle_subscription_new(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1940,7 +1960,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscription_toggle(self, payload, session):
|
async def _handle_subscription_toggle(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1965,7 +1985,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscription_del_complete(self, payload, session):
|
async def _handle_subscription_del_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -1993,7 +2013,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
def _handle_cancel(self, payload, session):
|
def _handle_cancel(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2006,7 +2026,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_discover(self, iq, session):
|
async def _handle_discover(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2044,7 +2064,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
def _handle_discover_type(self, payload, session):
|
def _handle_discover_type(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2100,7 +2120,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_discover_category(self, payload, session):
|
async def _handle_discover_category(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2130,7 +2150,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscriptions(self, iq, session):
|
async def _handle_subscriptions(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2195,7 +2215,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscriptions_result(self, payload, session):
|
async def _handle_subscriptions_result(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2289,7 +2309,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscription_tag(self, payload, session):
|
async def _handle_subscription_tag(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2327,7 +2347,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscription_edit(self, payload, session):
|
async def _handle_subscription_edit(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2424,7 +2444,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
# TODO Create a new form. Do not "recycle" the last form.
|
# TODO Create a new form. Do not "recycle" the last form.
|
||||||
async def _handle_subscription_complete(self, payload, session):
|
async def _handle_subscription_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2490,7 +2510,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_advanced(self, iq, session):
|
async def _handle_advanced(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2532,7 +2552,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_advanced_result(self, payload, session):
|
async def _handle_advanced_result(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2679,7 +2699,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_about(self, iq, session):
|
async def _handle_about(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2704,7 +2724,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_about_result(self, payload, session):
|
async def _handle_about_result(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2768,7 +2788,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_motd(self, iq, session):
|
async def _handle_motd(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2781,7 +2801,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_help(self, iq, session):
|
async def _handle_help(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2822,7 +2842,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_import_complete(self, payload, session):
|
async def _handle_import_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -2863,12 +2883,11 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_export_complete(self, payload, session):
|
async def _handle_export_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
form = self['xep_0004'].make_form('result', 'Done')
|
form = self['xep_0004'].make_form('result', 'Done')
|
||||||
form['instructions'] = 'Export has been completed successfully!'
|
|
||||||
# form['type'] = 'result'
|
# form['type'] = 'result'
|
||||||
values = payload['values']
|
values = payload['values']
|
||||||
jid_bare = session['from'].bare
|
jid_bare = session['from'].bare
|
||||||
|
@ -2880,17 +2899,25 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
exts = values['filetype']
|
exts = values['filetype']
|
||||||
for ext in exts:
|
for ext in exts:
|
||||||
filename = Feed.export_feeds(jid_bare, ext)
|
filename = Feed.export_feeds(jid_bare, ext)
|
||||||
url = await XmppUpload.start(self, jid_bare, filename)
|
encrypt_omemo = Config.get_setting_value(self.settings, jid_bare, 'omemo')
|
||||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
encrypted = True if encrypt_omemo else False
|
||||||
XmppMessage.send_oob(self, jid_bare, url, chat_type)
|
url = await XmppUpload.start(
|
||||||
url_field = form.add_field(var=ext.upper(),
|
self, jid_bare, Path(filename), encrypted=encrypted)
|
||||||
ftype='text-single',
|
if url:
|
||||||
label=ext,
|
form['instructions'] = 'Export has been completed successfully!'
|
||||||
value=url)
|
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||||
url_field['validate']['datatype'] = 'xs:anyURI'
|
XmppMessage.send_oob(self, jid_bare, url, chat_type)
|
||||||
session["has_next"] = False
|
url_field = form.add_field(var=ext.upper(),
|
||||||
session['next'] = None
|
ftype='text-single',
|
||||||
session['payload'] = form
|
label=ext,
|
||||||
|
value=url)
|
||||||
|
url_field['validate']['datatype'] = 'xs:anyURI'
|
||||||
|
session["has_next"] = False
|
||||||
|
session['next'] = None
|
||||||
|
session['payload'] = form
|
||||||
|
else:
|
||||||
|
text_warn = 'OPML file export has been failed.'
|
||||||
|
session['notes'] = [['warn', text_warn]]
|
||||||
return session
|
return session
|
||||||
|
|
||||||
|
|
||||||
|
@ -2898,12 +2925,12 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
# TODO Attempt to look up for feeds of hostname of JID (i.e. scan
|
# TODO Attempt to look up for feeds of hostname of JID (i.e. scan
|
||||||
# jabber.de for feeds for juliet@jabber.de)
|
# jabber.de for feeds for juliet@jabber.de)
|
||||||
async def _handle_promoted(self, iq, session):
|
async def _handle_promoted(self, iq, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
jid_bare = session['from'].bare
|
jid_bare = session['from'].bare
|
||||||
jid_full = str(session['from'])
|
jid_full = session['from'].full
|
||||||
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
chat_type = await XmppUtilities.get_chat_type(self, jid_bare)
|
||||||
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
if XmppUtilities.is_access(self, jid_bare, jid_full, chat_type):
|
||||||
form = self['xep_0004'].make_form('form', 'Subscribe')
|
form = self['xep_0004'].make_form('form', 'Subscribe')
|
||||||
|
@ -2971,7 +2998,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_admin_action(self, payload, session):
|
async def _handle_admin_action(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3096,7 +3123,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
def _handle_nodes(self, payload, session):
|
def _handle_nodes(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3124,7 +3151,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_nodes_action(self, payload, session):
|
async def _handle_nodes_action(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3183,7 +3210,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_node_browse(self, payload, session):
|
async def _handle_node_browse(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3214,7 +3241,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_item_view(self, payload, session):
|
async def _handle_item_view(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3250,7 +3277,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
# FIXME Undefined name 'jid_bare'
|
# FIXME Undefined name 'jid_bare'
|
||||||
async def _handle_node_edit(self, payload, session):
|
async def _handle_node_edit(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3303,7 +3330,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_nodes_purge(self, payload, session):
|
async def _handle_nodes_purge(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3321,7 +3348,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_nodes_delete(self, payload, session):
|
async def _handle_nodes_delete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3339,7 +3366,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_pubsub_complete(self, payload, session):
|
async def _handle_pubsub_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3364,7 +3391,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_subscribers_complete(self, payload, session):
|
async def _handle_subscribers_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3412,7 +3439,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_contact_action(self, payload, session):
|
async def _handle_contact_action(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3480,7 +3507,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
def _handle_contacts_complete(self, payload, session):
|
def _handle_contacts_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3504,7 +3531,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_bookmarks_edit(self, payload, session):
|
async def _handle_bookmarks_edit(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3569,7 +3596,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_bookmarks_complete(self, payload, session):
|
async def _handle_bookmarks_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3604,7 +3631,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
session. Additional, custom data may be saved
|
session. Additional, custom data may be saved
|
||||||
here to persist across handler callbacks.
|
here to persist across handler callbacks.
|
||||||
"""
|
"""
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
@ -3723,7 +3750,7 @@ class XmppClient(slixmpp.ClientXMPP):
|
||||||
|
|
||||||
|
|
||||||
async def _handle_settings_complete(self, payload, session):
|
async def _handle_settings_complete(self, payload, session):
|
||||||
jid_full = str(session['from'])
|
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: {}'
|
||||||
.format(function_name, jid_full))
|
.format(function_name, jid_full))
|
||||||
|
|
|
@ -334,9 +334,9 @@ class XmppCommands:
|
||||||
|
|
||||||
|
|
||||||
def export_feeds(jid_bare, ext):
|
def export_feeds(jid_bare, ext):
|
||||||
filename = Feed.export_feeds(jid_bare, ext)
|
pathname = Feed.export_feeds(jid_bare, ext)
|
||||||
message = 'Feeds successfuly exported to {}.'.format(ext)
|
message = 'Feeds successfuly exported to {}.'.format(ext)
|
||||||
return filename, message
|
return pathname, message
|
||||||
|
|
||||||
|
|
||||||
def fetch_gemini():
|
def fetch_gemini():
|
||||||
|
|
174
slixfeed/xmpp/encryption.py
Normal file
174
slixfeed/xmpp/encryption.py
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
1) Deprecate "add" (see above) and make it interactive.
|
||||||
|
Slixfeed: Do you still want to add this URL to subscription list?
|
||||||
|
See: case _ if command_lowercase.startswith("add"):
|
||||||
|
|
||||||
|
2) If subscription is inadequate (see XmppPresence.request), send a message that says so.
|
||||||
|
|
||||||
|
elif not self.client_roster[jid]["to"]:
|
||||||
|
breakpoint()
|
||||||
|
message.reply("Share online status to activate bot.").send()
|
||||||
|
return
|
||||||
|
|
||||||
|
3) Set timeout for moderator interaction.
|
||||||
|
If moderator interaction has been made, and moderator approves the bot, then
|
||||||
|
the bot will add the given groupchat to bookmarks; otherwise, the bot will
|
||||||
|
send a message that it was not approved and therefore leaves the groupchat.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from slixfeed.log import Logger
|
||||||
|
from slixmpp import JID
|
||||||
|
from slixmpp.exceptions import IqTimeout, IqError
|
||||||
|
from slixmpp.stanza import Message
|
||||||
|
from slixmpp_omemo import PluginCouldNotLoad, MissingOwnKey, EncryptionPrepareException
|
||||||
|
from slixmpp_omemo import UndecidedException, UntrustedException, NoAvailableSession
|
||||||
|
from omemo.exceptions import MissingBundleException
|
||||||
|
|
||||||
|
|
||||||
|
logger = Logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# for task in main_task:
|
||||||
|
# task.cancel()
|
||||||
|
|
||||||
|
# Deprecated in favour of event "presence_available"
|
||||||
|
# if not main_task:
|
||||||
|
# await select_file()
|
||||||
|
|
||||||
|
|
||||||
|
class XmppOmemo:
|
||||||
|
|
||||||
|
|
||||||
|
async def decrypt(self, message: Message, allow_untrusted: bool = False):
|
||||||
|
jid = message['from']
|
||||||
|
try:
|
||||||
|
message_omemo_encrypted = message['omemo_encrypted']
|
||||||
|
message_body = await self['xep_0384'].decrypt_message(
|
||||||
|
message_omemo_encrypted, jid, allow_untrusted)
|
||||||
|
# decrypt_message returns Optional[str]. It is possible to get
|
||||||
|
# body-less OMEMO message (see KeyTransportMessages), currently
|
||||||
|
# used for example to send heartbeats to other devices.
|
||||||
|
if message_body is not None:
|
||||||
|
response = message_body.decode('utf8')
|
||||||
|
omemo_decrypted = True
|
||||||
|
else:
|
||||||
|
response = omemo_decrypted = None
|
||||||
|
except (MissingOwnKey,) as exn:
|
||||||
|
# The message is missing our own key, it was not encrypted for
|
||||||
|
# us, and we can't decrypt it.
|
||||||
|
response = ('Error: Your message has not been encrypted for '
|
||||||
|
'Slixfeed (MissingOwnKey).')
|
||||||
|
omemo_decrypted = False
|
||||||
|
logger.error(exn)
|
||||||
|
except (NoAvailableSession,) as exn:
|
||||||
|
# We received a message from that contained a session that we
|
||||||
|
# don't know about (deleted session storage, etc.). We can't
|
||||||
|
# decrypt the message, and it's going to be lost.
|
||||||
|
# Here, as we need to initiate a new encrypted session, it is
|
||||||
|
# best if we send an encrypted message directly. XXX: Is it
|
||||||
|
# where we talk about self-healing messages?
|
||||||
|
response = ('Error: Your message has not been encrypted for '
|
||||||
|
'Slixfeed (NoAvailableSession).')
|
||||||
|
omemo_decrypted = False
|
||||||
|
logger.error(exn)
|
||||||
|
except (UndecidedException, UntrustedException) as exn:
|
||||||
|
# We received a message from an untrusted device. We can
|
||||||
|
# choose to decrypt the message nonetheless, with the
|
||||||
|
# `allow_untrusted` flag on the `decrypt_message` call, which
|
||||||
|
# we will do here. This is only possible for decryption,
|
||||||
|
# encryption will require us to decide if we trust the device
|
||||||
|
# or not. Clients _should_ indicate that the message was not
|
||||||
|
# trusted, or in undecided state, if they decide to decrypt it
|
||||||
|
# anyway.
|
||||||
|
response = (f'Error: Device "{exn.device}" is not present in the '
|
||||||
|
'trusted devices of Slixfeed.')
|
||||||
|
omemo_decrypted = False
|
||||||
|
logger.error(exn)
|
||||||
|
# We resend, setting the `allow_untrusted` parameter to True.
|
||||||
|
await XmppChat.process_message(self, message, allow_untrusted=True)
|
||||||
|
except (EncryptionPrepareException,) as exn:
|
||||||
|
# Slixmpp tried its best, but there were errors it couldn't
|
||||||
|
# resolve. At this point you should have seen other exceptions
|
||||||
|
# and given a chance to resolve them already.
|
||||||
|
response = ('Error: Your message has not been encrypted for '
|
||||||
|
'Slixfeed (EncryptionPrepareException).')
|
||||||
|
omemo_decrypted = False
|
||||||
|
logger.error(exn)
|
||||||
|
except (Exception,) as exn:
|
||||||
|
response = ('Error: Your message has not been encrypted for '
|
||||||
|
'Slixfeed (Unknown).')
|
||||||
|
omemo_decrypted = False
|
||||||
|
logger.error(exn)
|
||||||
|
raise
|
||||||
|
|
||||||
|
return response, omemo_decrypted
|
||||||
|
|
||||||
|
|
||||||
|
async def encrypt(self, jid: JID, message_body):
|
||||||
|
expect_problems = {} # type: Optional[Dict[JID, List[int]]]
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
# `encrypt_message` excepts the plaintext to be sent, a list of
|
||||||
|
# bare JIDs to encrypt to, and optionally a dict of problems to
|
||||||
|
# expect per bare JID.
|
||||||
|
#
|
||||||
|
# Note that this function returns an `<encrypted/>` object,
|
||||||
|
# and not a full Message stanza. This combined with the
|
||||||
|
# `recipients` parameter that requires for a list of JIDs,
|
||||||
|
# allows you to encrypt for 1:1 as well as groupchats (MUC).
|
||||||
|
#
|
||||||
|
# `expect_problems`: See EncryptionPrepareException handling.
|
||||||
|
recipients = [jid]
|
||||||
|
message_body = await self['xep_0384'].encrypt_message(
|
||||||
|
message_body, recipients, expect_problems)
|
||||||
|
omemo_encrypted = True
|
||||||
|
break
|
||||||
|
except UndecidedException as exn:
|
||||||
|
# The library prevents us from sending a message to an
|
||||||
|
# untrusted/undecided barejid, so we need to make a decision here.
|
||||||
|
# This is where you prompt your user to ask what to do. In
|
||||||
|
# this bot we will automatically trust undecided recipients.
|
||||||
|
await self['xep_0384'].trust(exn.bare_jid, exn.device, exn.ik)
|
||||||
|
omemo_encrypted = False
|
||||||
|
# TODO: catch NoEligibleDevicesException
|
||||||
|
except EncryptionPrepareException as exn:
|
||||||
|
# This exception is being raised when the library has tried
|
||||||
|
# all it could and doesn't know what to do anymore. It
|
||||||
|
# contains a list of exceptions that the user must resolve, or
|
||||||
|
# explicitely ignore via `expect_problems`.
|
||||||
|
# TODO: We might need to bail out here if errors are the same?
|
||||||
|
for error in exn.errors:
|
||||||
|
if isinstance(error, MissingBundleException):
|
||||||
|
# We choose to ignore MissingBundleException. It seems
|
||||||
|
# to be somewhat accepted that it's better not to
|
||||||
|
# encrypt for a device if it has problems and encrypt
|
||||||
|
# for the rest, rather than error out. The "faulty"
|
||||||
|
# device won't be able to decrypt and should display a
|
||||||
|
# generic message. The receiving end-user at this
|
||||||
|
# point can bring up the issue if it happens.
|
||||||
|
message_body = (f'Could not find keys for device '
|
||||||
|
'"{error.device}"'
|
||||||
|
f' of recipient "{error.bare_jid}". '
|
||||||
|
'Skipping.')
|
||||||
|
omemo_encrypted = False
|
||||||
|
jid = JID(error.bare_jid)
|
||||||
|
device_list = expect_problems.setdefault(jid, [])
|
||||||
|
device_list.append(error.device)
|
||||||
|
except (IqError, IqTimeout) as exn:
|
||||||
|
message_body = ('An error occured while fetching information '
|
||||||
|
'on a recipient.\n%r' % exn)
|
||||||
|
omemo_encrypted = False
|
||||||
|
except Exception as exn:
|
||||||
|
message_body = ('An error occured while attempting to encrypt'
|
||||||
|
'.\n%r' % exn)
|
||||||
|
omemo_encrypted = False
|
||||||
|
raise
|
||||||
|
|
||||||
|
return message_body, omemo_encrypted
|
|
@ -34,21 +34,31 @@ class XmppGroupchat:
|
||||||
'bookmark {}'.format(bookmark['name']))
|
'bookmark {}'.format(bookmark['name']))
|
||||||
alias = bookmark["nick"]
|
alias = bookmark["nick"]
|
||||||
muc_jid = bookmark["jid"]
|
muc_jid = bookmark["jid"]
|
||||||
Message.printer('Joining to MUC {} ...'.format(muc_jid))
|
# Message.printer('Joining to MUC {} ...'.format(muc_jid))
|
||||||
|
print('Joining to MUC {} ...'.format(muc_jid))
|
||||||
result = await XmppMuc.join(self, muc_jid, alias)
|
result = await XmppMuc.join(self, muc_jid, alias)
|
||||||
if result == 'ban':
|
match result:
|
||||||
await XmppBookmark.remove(self, muc_jid)
|
case 'ban':
|
||||||
logger.warning('{} is banned from {}'.format(self.alias, muc_jid))
|
await XmppBookmark.remove(self, muc_jid)
|
||||||
logger.warning('Groupchat {} has been removed from bookmarks'
|
logger.warning('{} is banned from {}'.format(self.alias, muc_jid))
|
||||||
.format(muc_jid))
|
logger.warning('Groupchat {} has been removed from bookmarks'
|
||||||
else:
|
.format(muc_jid))
|
||||||
logger.info('Autojoin groupchat\n'
|
case 'error':
|
||||||
'Name : {}\n'
|
logger.warning('An error has occured while attempting '
|
||||||
'JID : {}\n'
|
'to join to groupchat {}'
|
||||||
'Alias : {}\n'
|
.format(muc_jid))
|
||||||
.format(bookmark["name"],
|
case 'timeout':
|
||||||
bookmark["jid"],
|
logger.warning('Timeout has reached while attempting '
|
||||||
bookmark["nick"]))
|
'to join to groupchat {}'
|
||||||
|
.format(muc_jid))
|
||||||
|
case _:
|
||||||
|
logger.info('Autojoin groupchat\n'
|
||||||
|
'Name : {}\n'
|
||||||
|
'JID : {}\n'
|
||||||
|
'Alias : {}\n'
|
||||||
|
.format(bookmark["name"],
|
||||||
|
bookmark["jid"],
|
||||||
|
bookmark["nick"]))
|
||||||
elif not bookmark["jid"]:
|
elif not bookmark["jid"]:
|
||||||
logger.error('JID is missing for bookmark {}'
|
logger.error('JID is missing for bookmark {}'
|
||||||
.format(bookmark['name']))
|
.format(bookmark['name']))
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from slixfeed.log import Logger
|
from slixfeed.log import Logger
|
||||||
|
from slixmpp import JID
|
||||||
import xml.sax.saxutils as saxutils
|
import xml.sax.saxutils as saxutils
|
||||||
|
|
||||||
logger = Logger(__name__)
|
logger = Logger(__name__)
|
||||||
|
@ -39,6 +40,43 @@ class XmppMessage:
|
||||||
mnick=self.alias)
|
mnick=self.alias)
|
||||||
|
|
||||||
|
|
||||||
|
def send_omemo(self, jid: JID, chat_type, response_encrypted):
|
||||||
|
jid_from = str(self.boundjid) if self.is_component else None
|
||||||
|
message = self.make_message(mto=jid, mfrom=jid_from, mtype=chat_type)
|
||||||
|
eme_ns = 'eu.siacs.conversations.axolotl'
|
||||||
|
# message['eme']['namespace'] = 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.append(response_encrypted)
|
||||||
|
message.send()
|
||||||
|
|
||||||
|
|
||||||
|
def send_omemo_oob(self, jid: JID, url_encrypted, chat_type, aesgcm=False):
|
||||||
|
jid_from = str(self.boundjid) if self.is_component else None
|
||||||
|
# if not aesgcm: url_encrypted = saxutils.escape(url_encrypted)
|
||||||
|
message = self.make_message(mto=jid, mfrom=jid_from, mtype=chat_type)
|
||||||
|
eme_ns = 'eu.siacs.conversations.axolotl'
|
||||||
|
# message['eme']['namespace'] = 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['oob']['url'] = url_encrypted
|
||||||
|
message.append(url_encrypted)
|
||||||
|
message.send()
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME Solve this function
|
||||||
|
def send_omemo_reply(self, message, response_encrypted):
|
||||||
|
eme_ns = 'eu.siacs.conversations.axolotl'
|
||||||
|
# message['eme']['namespace'] = 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.append(response_encrypted)
|
||||||
|
message.reply(message['body']).send()
|
||||||
|
|
||||||
|
|
||||||
# NOTE We might want to add more characters
|
# NOTE We might want to add more characters
|
||||||
# def escape_to_xml(raw_string):
|
# def escape_to_xml(raw_string):
|
||||||
# escape_map = {
|
# escape_map = {
|
||||||
|
|
|
@ -50,7 +50,7 @@ class XmppStatus:
|
||||||
status_text = '📬️ There are {} news items'.format(str(unread))
|
status_text = '📬️ There are {} news items'.format(str(unread))
|
||||||
else:
|
else:
|
||||||
# print('status no news for ' + jid_bare)
|
# print('status no news for ' + jid_bare)
|
||||||
status_mode = 'available'
|
status_mode = 'away'
|
||||||
status_text = '📭️ No news'
|
status_text = '📭️ No news'
|
||||||
else:
|
else:
|
||||||
# print('status disabled for ' + jid_bare)
|
# print('status disabled for ' + jid_bare)
|
||||||
|
@ -91,4 +91,4 @@ class XmppStatusTask:
|
||||||
self.task_manager[jid_bare]['status'].cancel()
|
self.task_manager[jid_bare]['status'].cancel()
|
||||||
else:
|
else:
|
||||||
logger.debug('No task "status" for JID {}'
|
logger.debug('No task "status" for JID {}'
|
||||||
.format(jid_bare))
|
.format(jid_bare))
|
||||||
|
|
|
@ -6,47 +6,51 @@ Based on http_upload.py example from project slixmpp
|
||||||
https://codeberg.org/poezio/slixmpp/src/branch/master/examples/http_upload.py
|
https://codeberg.org/poezio/slixmpp/src/branch/master/examples/http_upload.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
from slixfeed.log import Logger
|
from slixfeed.log import Logger
|
||||||
|
from slixmpp import JID
|
||||||
from slixmpp.exceptions import IqTimeout, IqError
|
from slixmpp.exceptions import IqTimeout, IqError
|
||||||
from slixmpp.plugins.xep_0363.http_upload import HTTPError
|
from slixmpp.plugins.xep_0363.http_upload import HTTPError
|
||||||
|
import sys
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
logger = Logger(__name__)
|
logger = Logger(__name__)
|
||||||
# import sys
|
# import sys
|
||||||
|
|
||||||
class XmppUpload:
|
class XmppUpload:
|
||||||
|
|
||||||
async def start(self, jid, filename, domain=None):
|
async def start(self, jid, filename: Path, size: Optional[int] = None,
|
||||||
|
encrypted: bool = False, domain: Optional[JID] = None):
|
||||||
logger.info(['Uploading file %s...', filename])
|
logger.info(['Uploading file %s...', filename])
|
||||||
try:
|
try:
|
||||||
upload_file = self['xep_0363'].upload_file
|
upload_file = self['xep_0363'].upload_file
|
||||||
# if self.encrypted and not self['xep_0454']:
|
if encrypted and not self['xep_0454']:
|
||||||
# print(
|
print(
|
||||||
# 'The xep_0454 module isn\'t available. '
|
'The xep_0454 module isn\'t available. '
|
||||||
# 'Ensure you have \'cryptography\' '
|
'Ensure you have \'cryptography\' '
|
||||||
# 'from extras_require installed.',
|
'from extras_require installed.',
|
||||||
# file=sys.stderr,
|
file=sys.stderr,
|
||||||
# )
|
|
||||||
# return
|
|
||||||
# elif self.encrypted:
|
|
||||||
# upload_file = self['xep_0454'].upload_file
|
|
||||||
try:
|
|
||||||
url = await upload_file(
|
|
||||||
filename, domain, timeout=10,
|
|
||||||
)
|
)
|
||||||
|
url = None
|
||||||
|
elif encrypted:
|
||||||
|
upload_file = self['xep_0454'].upload_file
|
||||||
|
try:
|
||||||
|
url = await upload_file(filename, size, domain, timeout=10,)
|
||||||
logger.info('Upload successful!')
|
logger.info('Upload successful!')
|
||||||
logger.info(['Sending file to %s', jid])
|
logger.info(['Sending file to %s', jid])
|
||||||
except HTTPError:
|
except HTTPError:
|
||||||
url = ('Error: It appears that this server does not support '
|
url = None
|
||||||
'HTTP File Upload.')
|
|
||||||
logger.error('It appears that this server does not support '
|
logger.error('It appears that this server does not support '
|
||||||
'HTTP File Upload.')
|
'HTTP File Upload.')
|
||||||
# raise HTTPError(
|
# raise HTTPError(
|
||||||
# "This server doesn't appear to support HTTP File Upload"
|
# "This server doesn't appear to support HTTP File Upload"
|
||||||
# )
|
# )
|
||||||
except IqError as e:
|
except IqError as e:
|
||||||
|
url = None
|
||||||
logger.error('Could not send message')
|
logger.error('Could not send message')
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
except IqTimeout as e:
|
except IqTimeout as e:
|
||||||
|
url = None
|
||||||
# raise TimeoutError('Could not send message in time')
|
# raise TimeoutError('Could not send message in time')
|
||||||
logger.error('Could not send message in time')
|
logger.error('Could not send message in time')
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
|
Loading…
Reference in a new issue