diff --git a/THANKS.md b/THANKS.md
index bc0f8e4..a2bdae0 100644
--- a/THANKS.md
+++ b/THANKS.md
@@ -1,9 +1,13 @@
Thank you goes to the following kind people.
+The following people have been involved in this project by consulting, developing and testing.
+
[Alixander Court](https://alixandercourt.com/)
[edhelas](https://github.com/edhelas/atomtopubsub)
+Guus der Kinderen (promptly dedicating a personal [Openfire](https://www.igniterealtime.org/projects/) server for further developments and tests)
+
[habnabit_](irc://irc.libera.chat/#python) (SQL security)
[imattau](https://github.com/imattau/atomtopubsub) (Some code, mostly URL handling, was taken from imattau)
@@ -16,4 +20,4 @@ Simone "roughnecks" Canaletti
Strix from Loqi
-Slixmpp participants who chose to remain anonymous or not to appear in this list.
+Slixmpp participants amf #python members who explicitly chose to remain anonymous or not to appear in this list.
diff --git a/slixfeed/__main__.py b/slixfeed/__main__.py
index 822f000..50c1e0f 100644
--- a/slixfeed/__main__.py
+++ b/slixfeed/__main__.py
@@ -96,21 +96,54 @@ import os
# # with start_action(action_type="set_date()", jid=jid):
# # with start_action(action_type="message()", msg=msg):
-#import slixfeed.irchandler
+#import slixfeed.smtp
+#import slixfeed.irc
+#import slixfeed.matrix
+
from slixfeed.config import get_value
-from slixfeed.xmpp.client import Slixfeed
-#import slixfeed.matrixhandler
import socks
import socket
+xmpp_type = get_value(
+ "accounts", "XMPP", "type")
-class Jabber:
- def __init__(self, jid, password, nick):
+match xmpp_type:
+ case "client":
+ from slixfeed.xmpp.client import Slixfeed
+ case "component":
+ from slixfeed.xmpp.component import Slixfeed
+
+
+class JabberComponent:
+ def __init__(self, jid, secret, hostname, port, alias):
+ xmpp = Slixfeed(jid, secret, hostname, port, alias)
+ xmpp.register_plugin('xep_0004') # Data Forms
+ xmpp.register_plugin('xep_0030') # Service Discovery
+ xmpp.register_plugin('xep_0045') # Multi-User Chat
+ # xmpp.register_plugin('xep_0048') # Bookmarks
+ xmpp.register_plugin('xep_0054') # vcard-temp
+ xmpp.register_plugin('xep_0060') # Publish-Subscribe
+ # xmpp.register_plugin('xep_0065') # SOCKS5 Bytestreams
+ xmpp.register_plugin('xep_0066') # Out of Band Data
+ xmpp.register_plugin('xep_0071') # XHTML-IM
+ xmpp.register_plugin('xep_0084') # User Avatar
+ # xmpp.register_plugin('xep_0085') # Chat State Notifications
+ xmpp.register_plugin('xep_0153') # vCard-Based Avatars
+ xmpp.register_plugin('xep_0199', {'keepalive': True}) # XMPP Ping
+ xmpp.register_plugin('xep_0249') # Multi-User Chat
+ xmpp.register_plugin('xep_0363') # HTTP File Upload
+ xmpp.register_plugin('xep_0402') # PEP Native Bookmarks
+ xmpp.connect()
+ xmpp.process()
+
+
+class JabberClient:
+ def __init__(self, jid, password, alias):
# Setup the Slixfeed and register plugins. Note that while plugins may
# have interdependencies, the order in which you register them does
# not matter.
- xmpp = Slixfeed(jid, password, nick)
+ xmpp = Slixfeed(jid, password, alias)
xmpp.register_plugin('xep_0004') # Data Forms
xmpp.register_plugin('xep_0030') # Service Discovery
xmpp.register_plugin('xep_0045') # Multi-User Chat
@@ -128,9 +161,9 @@ class Jabber:
xmpp.register_plugin('xep_0363') # HTTP File Upload
xmpp.register_plugin('xep_0402') # PEP Native Bookmarks
- # proxy_enabled = get_value("accounts", "XMPP Connect", "proxy_enabled")
+ # proxy_enabled = get_value("accounts", "XMPP", "proxy_enabled")
# if proxy_enabled == '1':
- # values = get_value("accounts", "XMPP Connect", [
+ # values = get_value("accounts", "XMPP", [
# "proxy_host",
# "proxy_port",
# "proxy_username",
@@ -150,7 +183,7 @@ class Jabber:
# Connect to the XMPP server and start processing XMPP stanzas.
address = get_value(
- "accounts", "XMPP", ["address", "port"])
+ "accounts", "XMPP Client", ["hostname", "port"])
if address[0] and address[1]:
xmpp.connect(tuple(address))
else:
@@ -189,7 +222,11 @@ def main():
parser.add_argument(
"-p", "--password", dest="password", help="Password of JID")
parser.add_argument(
- "-n", "--nickname", dest="nickname", help="Display name")
+ "-a", "--alias", dest="alias", help="Display name")
+ parser.add_argument(
+ "-n", "--hostname", dest="hostname", help="Hostname")
+ parser.add_argument(
+ "-o", "--port", dest="port", help="Port number")
args = parser.parse_args()
@@ -199,28 +236,39 @@ def main():
# Try configuration file
values = get_value(
- "accounts", "XMPP", ["nickname", "username", "password"])
- nickname = values[0]
+ "accounts", "XMPP Client", [
+ "alias", "username", "password", "hostname", "port"])
+ alias = values[0]
username = values[1]
password = values[2]
+ hostname = values[3]
+ port = values[4]
# Use arguments if were given
if args.jid:
username = args.jid
if args.password:
password = args.password
- if args.nickname:
- nickname = args.nickname
+ if args.alias:
+ alias = args.alias
+ if args.hostname:
+ hostname = args.hostname
+ if args.port:
+ port = args.port
# Prompt for credentials if none were given
if not username:
username = input("Username: ")
if not password:
password = getpass("Password: ")
- if not nickname:
- nickname = input("Nickname: ")
+ if not alias:
+ alias = (input("Alias: ")) or "Slixfeed"
- Jabber(username, password, nickname)
+ match xmpp_type:
+ case "client":
+ JabberClient(username, password, alias)
+ case "component":
+ JabberComponent(username, password, hostname, port, alias)
sys.exit(0)
if __name__ == "__main__":
diff --git a/slixfeed/action.py b/slixfeed/action.py
index 3311afd..3a1db5a 100644
--- a/slixfeed/action.py
+++ b/slixfeed/action.py
@@ -123,17 +123,22 @@ def is_feed_json(document):
True or False.
"""
value = False
- feed = json.loads(document)
- if not feed['items']:
- if "version" in feed.keys():
- if 'jsonfeed' in feed['version']:
- value = True
- # elif 'title' in feed.keys():
- # value = True
+ try:
+ feed = json.loads(document)
+ if not feed['items']:
+ if "version" in feed.keys():
+ if 'jsonfeed' in feed['version']:
+ value = True
+ else: # TODO Test
+ value = False
+ # elif 'title' in feed.keys():
+ # value = True
+ else:
+ value = False
else:
- value = False
- else:
- value = True
+ value = True
+ except:
+ pass
return value
@@ -1039,8 +1044,6 @@ def generate_document(data, url, ext, filename):
"are installed, or try again.")
error = (
"Package pdfkit or wkhtmltopdf was not found.")
- case "text":
- generate_txt(content, filename)
case "txt":
generate_txt(content, filename)
if error:
diff --git a/slixfeed/assets/accounts.ini b/slixfeed/assets/accounts.ini
index df9c6c7..ef5f150 100644
--- a/slixfeed/assets/accounts.ini
+++ b/slixfeed/assets/accounts.ini
@@ -2,36 +2,45 @@
# and also from which accounts it receives instructions.
[XMPP]
-nickname = Slixfeed
+reconnect_timeout = 30
+type = client
+#type = component
+
+[XMPP Client]
+alias = Slixfeed
username =
password =
-# JID of bot master
-operator =
-# Address may be an onion hostname
-address =
+# Hostname (also address) may be an i2p or onion hostname
+hostname =
# Port may be 5347
port =
+[XMPP Component]
+alias = Slixfeed
+username =
+password =
+hostname =
+port =
+
[XMPP Profile]
name = Slixfeed
-nickname = Slixfeed
+alias = Slixfeed
role = Syndication News Bot
organization = RSS Task Force
url = https://gitgud.io/sjehuda/slixfeed
description = XMPP news bot (supports Atom, JSON, RDF and RSS).
note = This is a syndication news bot powered by Slixfeed.
birthday = 21 June 2022
+# JID of bot master
+operator =
-[XMPP Connect]
-reconnect_timeout = 30
-
+[XMPP Proxy]
# NOTE You might want to consider support for socks4 too (this
# note was written when keys were proxy_host and proxy_port)
# NOTE Consider not to use a version number as it might give an
# impression of an archaic feature in the future.
-[XMPP Proxy]
# Example hostname 127.0.0.1
socks5_host =
# Example port 9050
diff --git a/slixfeed/assets/proxies.yaml b/slixfeed/assets/proxies.yaml
index 792c686..c8c6fd9 100644
--- a/slixfeed/assets/proxies.yaml
+++ b/slixfeed/assets/proxies.yaml
@@ -413,7 +413,7 @@ proxies:
- https://quetre.projectsegfau.lt
- https://quetre.esmailelbob.xyz
- https://quetre.odyssey346.dev
- - ://ask.habedieeh.re
+ - https://ask.habedieeh.re
- https://quetre.marcopisco.com
- https://quetre.blackdrgn.nl
- https://quetre.lunar.icu
diff --git a/slixfeed/config.py b/slixfeed/config.py
index 3995956..17509e4 100644
--- a/slixfeed/config.py
+++ b/slixfeed/config.py
@@ -17,6 +17,8 @@ TODO
5) Merge get_value_default into get_value.
+6) Use TOML https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell
+
"""
import configparser
diff --git a/slixfeed/task.py b/slixfeed/task.py
index d3cd304..db91a59 100644
--- a/slixfeed/task.py
+++ b/slixfeed/task.py
@@ -35,7 +35,7 @@ NOTE
check_readiness
๐ Send a URL from a blog or a news website.
JID: self.boundjid.bare
- MUC: self.nick
+ MUC: self.alias
"""
@@ -258,11 +258,21 @@ async def send_update(self, jid, num=None):
if media and news_digest:
# Send textual message
xmpp.Slixfeed.send_message(
- self, mto=jid, mbody=news_digest, mtype=chat_type)
+ self,
+ mto=jid,
+ mfrom=self.boundjid.bare,
+ mbody=news_digest,
+ mtype=chat_type
+ )
news_digest = ''
# Send media
message = xmpp.Slixfeed.make_message(
- self, mto=jid, mbody=media, mtype=chat_type)
+ self,
+ mto=jid,
+ mfrom=self.boundjid.bare,
+ mbody=media,
+ mtype=chat_type
+ )
message['oob']['url'] = media
message.send()
media = None
@@ -274,7 +284,12 @@ async def send_update(self, jid, num=None):
if chat_type in ("chat", "groupchat"):
# TODO Provide a choice (with or without images)
xmpp.Slixfeed.send_message(
- self, mto=jid, mbody=news_digest, mtype=chat_type)
+ self,
+ mto=jid,
+ mfrom=self.boundjid.bare,
+ mbody=news_digest,
+ mtype=chat_type
+ )
# if media:
# # message = xmpp.Slixfeed.make_message(
# # self, mto=jid, mbody=new, mtype=chat_type)
@@ -365,10 +380,10 @@ async def send_status(self, jid):
# print(await current_time(), status_text, "for", jid)
xmpp.Slixfeed.send_presence(
self,
- pshow=status_mode,
- pstatus=status_text,
pto=jid,
- #pfrom=None
+ pfrom=self.boundjid.bare,
+ pshow=status_mode,
+ pstatus=status_text
)
# await asyncio.sleep(60 * 20)
await refresh_task(
diff --git a/slixfeed/xmpp/bookmark.py b/slixfeed/xmpp/bookmark.py
index 2990576..e8bc8ac 100644
--- a/slixfeed/xmpp/bookmark.py
+++ b/slixfeed/xmpp/bookmark.py
@@ -19,7 +19,7 @@ async def add(self, muc_jid):
for muc in mucs:
bookmarks.add_conference(
muc,
- self.nick,
+ self.alias,
autojoin=True
)
await self.plugin['xep_0048'].set_bookmarks(bookmarks)
@@ -28,7 +28,7 @@ async def add(self, muc_jid):
# print(await self.plugin['xep_0048'].get_bookmarks())
# bm = BookmarkStorage()
- # bm.conferences.append(Conference(muc_jid, autojoin=True, nick=self.nick))
+ # bm.conferences.append(Conference(muc_jid, autojoin=True, nick=self.alias))
# await self['xep_0402'].publish(bm)
@@ -53,7 +53,7 @@ async def remove(self, muc_jid):
for muc in mucs:
bookmarks.add_conference(
muc,
- self.nick,
+ self.alias,
autojoin=True
)
await self.plugin['xep_0048'].set_bookmarks(bookmarks)
diff --git a/slixfeed/xmpp/client.py b/slixfeed/xmpp/client.py
index fa7a528..75ae1de 100644
--- a/slixfeed/xmpp/client.py
+++ b/slixfeed/xmpp/client.py
@@ -35,7 +35,7 @@ NOTE
check_readiness
๐ Send a URL from a blog or a news website.
JID: self.boundjid.bare
- MUC: self.nick
+ MUC: self.alias
2) Extracting attribute using xmltodict.
import xmltodict
@@ -91,13 +91,13 @@ class Slixfeed(slixmpp.ClientXMPP):
-------
News bot that sends updates from RSS feeds.
"""
- def __init__(self, jid, password, nick):
+ def __init__(self, jid, password, alias):
slixmpp.ClientXMPP.__init__(self, jid, password)
# NOTE
# The bot works fine when the nickname is hardcoded; or
# The bot won't join some MUCs when its nickname has brackets
- self.nick = nick
+ self.alias = alias
# The session_start event will be triggered when
# the bot establishes its connection with the server
# and the XML streams are ready for use. We want to
@@ -158,24 +158,24 @@ class Slixfeed(slixmpp.ClientXMPP):
async def on_session_end(self, event):
- message = "Session has ended."
+ message = "Session has ended. Reason: {}".format(event)
await connect.recover_connection(self, event, message)
async def on_connection_failed(self, event):
- message = "Connection has failed."
+ message = "Connection has failed. Reason: {}".format(event)
await connect.recover_connection(self, event, message)
async def on_session_start(self, event):
await process.event(self, event)
- await muc.autojoin(self, event)
+ await muc.autojoin(self)
await profile.update(self)
async def on_session_resumed(self, event):
await process.event(self, event)
- await muc.autojoin(self, event)
+ await muc.autojoin(self)
# TODO Request for subscription
@@ -196,10 +196,10 @@ class Slixfeed(slixmpp.ClientXMPP):
# TODO Request for subscription
async def on_presence_subscribe(self, presence):
- jid = presence["from"].bare
- await state.request(self, jid)
print("on_presence_subscribe")
print(presence)
+ jid = presence["from"].bare
+ await state.request(self, jid)
async def on_presence_subscribed(self, presence):
@@ -214,6 +214,8 @@ class Slixfeed(slixmpp.ClientXMPP):
async def on_presence_unsubscribed(self, presence):
await state.unsubscribed(self, presence)
+ jid = presence["from"].bare
+ await roster.remove(self, jid)
async def on_presence_unavailable(self, presence):
diff --git a/slixfeed/xmpp/component.py b/slixfeed/xmpp/component.py
new file mode 100644
index 0000000..750f5b0
--- /dev/null
+++ b/slixfeed/xmpp/component.py
@@ -0,0 +1,284 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+
+"""
+
+FIXME
+
+1) Function check_readiness or event "changed_status" is causing for
+ triple status messages and also false ones that indicate of lack
+ of feeds.
+
+TODO
+
+1) Use loop (with gather) instead of TaskGroup.
+
+2) Assure message delivery before calling a new task.
+ See https://slixmpp.readthedocs.io/en/latest/event_index.html#term-marker_acknowledged
+
+3) XHTTML-IM
+ case _ if message_lowercase.startswith("html"):
+ message['html']="
+Parse me!
+"
+ self.send_message(
+ mto=jid,
+ mfrom=self.boundjid.bare,
+ mhtml=message
+ )
+
+NOTE
+
+1) Self presence
+ Apparently, it is possible to view self presence.
+ This means that there is no need to store presences in order to switch or restore presence.
+ check_readiness
+ ๐ Send a URL from a blog or a news website.
+ JID: self.boundjid.bare
+ MUC: self.alias
+
+2) Extracting attribute using xmltodict.
+ import xmltodict
+ message = xmltodict.parse(str(message))
+ jid = message["message"]["x"]["@jid"]
+
+"""
+
+import asyncio
+import logging
+# import os
+from random import randrange
+import slixmpp
+import slixfeed.task as task
+from time import sleep
+
+from slixmpp.plugins.xep_0363.http_upload import FileTooBig, HTTPError, UploadServiceNotFound
+# from slixmpp.plugins.xep_0402 import BookmarkStorage, Conference
+from slixmpp.plugins.xep_0048.stanza import Bookmarks
+
+# import xmltodict
+# import xml.etree.ElementTree as ET
+# from lxml import etree
+
+import slixfeed.xmpp.connect as connect
+import slixfeed.xmpp.muc as muc
+import slixfeed.xmpp.process as process
+import slixfeed.xmpp.profile as profile
+import slixfeed.xmpp.roster as roster
+import slixfeed.xmpp.state as state
+import slixfeed.xmpp.status as status
+import slixfeed.xmpp.utility as utility
+
+main_task = []
+jid_tasker = {}
+task_manager = {}
+loop = asyncio.get_event_loop()
+# asyncio.set_event_loop(loop)
+
+# time_now = datetime.now()
+# time_now = time_now.strftime("%H:%M:%S")
+
+# def print_time():
+# # return datetime.now().strftime("%H:%M:%S")
+# now = datetime.now()
+# current_time = now.strftime("%H:%M:%S")
+# return current_time
+
+
+class Slixfeed(slixmpp.ComponentXMPP):
+ """
+ Slixmpp
+ -------
+ News bot that sends updates from RSS feeds.
+ """
+ def __init__(self, jid, secret, hostname, port, alias):
+ slixmpp.ComponentXMPP.__init__(self, jid, secret, hostname, port)
+
+ # The session_start event will be triggered when
+ # the bot establishes its connection with the server
+ # and the XML streams are ready for use. We want to
+ # listen for this event so that we we can initialize
+ # our roster.
+ self.add_event_handler("session_start", self.on_session_start)
+ self.add_event_handler("session_resumed", self.on_session_resumed)
+ self.add_event_handler("got_offline", print("got_offline"))
+ # self.add_event_handler("got_online", self.check_readiness)
+ self.add_event_handler("changed_status", self.on_changed_status)
+ self.add_event_handler("presence_available", self.on_presence_available)
+ self.add_event_handler("presence_unavailable", self.on_presence_unavailable)
+
+ self.add_event_handler("changed_subscription", self.on_changed_subscription)
+
+ self.add_event_handler("chatstate_active", self.on_chatstate_active)
+ self.add_event_handler("chatstate_gone", self.on_chatstate_gone)
+ self.add_event_handler("chatstate_composing", self.check_chatstate_composing)
+ self.add_event_handler("chatstate_paused", self.check_chatstate_paused)
+
+ # The message event is triggered whenever a message
+ # stanza is received. Be aware that that includes
+ # MUC messages and error messages.
+ self.add_event_handler("message", self.on_message)
+
+ self.add_event_handler("groupchat_invite", self.on_groupchat_invite) # XEP_0045
+ self.add_event_handler("groupchat_direct_invite", self.on_groupchat_direct_invite) # XEP_0249
+ # self.add_event_handler("groupchat_message", self.message)
+
+ # self.add_event_handler("disconnected", self.reconnect)
+ # self.add_event_handler("disconnected", self.inspect_connection)
+
+ self.add_event_handler("reactions", self.on_reactions)
+ self.add_event_handler("presence_error", self.on_presence_error)
+ self.add_event_handler("presence_subscribe", self.on_presence_subscribe)
+ self.add_event_handler("presence_subscribed", self.on_presence_subscribed)
+ self.add_event_handler("presence_unsubscribe", self.on_presence_unsubscribe)
+ self.add_event_handler("presence_unsubscribed", self.on_presence_unsubscribed)
+
+ # Initialize event loop
+ # self.loop = asyncio.get_event_loop()
+
+ # handlers for connection events
+ self.connection_attempts = 0
+ self.max_connection_attempts = 10
+ self.add_event_handler("connection_failed", self.on_connection_failed)
+ self.add_event_handler("session_end", self.on_session_end)
+
+
+ async def on_groupchat_invite(self, message):
+ print("on_groupchat_invite")
+ await muc.accept_invitation(self, message)
+
+
+ async def on_groupchat_direct_invite(self, message):
+ print("on_groupchat_direct_invite")
+ await muc.accept_invitation(self, message)
+
+
+ async def on_session_end(self, event):
+ message = "Session has ended. Reason: {}".format(event)
+ await connect.recover_connection(self, event, message)
+
+
+ async def on_connection_failed(self, event):
+ message = "Connection has failed. Reason: {}".format(event)
+ await connect.recover_connection(self, event, message)
+
+
+ async def on_session_start(self, event):
+ await process.event_component(self, event)
+ # await muc.autojoin(self)
+ await profile.update(self)
+
+
+ async def on_session_resumed(self, event):
+ await process.event_component(self, event)
+ # await muc.autojoin(self)
+
+
+ # TODO Request for subscription
+ async def on_message(self, message):
+ # print(message)
+ # breakpoint()
+ jid = message["from"].bare
+ # if "chat" == await utility.jid_type(self, jid):
+ # await roster.add(self, jid)
+ # await state.request(self, jid)
+ # chat_type = message["type"]
+ # message_body = message["body"]
+ # message_reply = message.reply
+ await process.message(self, message)
+
+
+ async def on_changed_status(self, presence):
+ await task.check_readiness(self, presence)
+
+
+ # TODO Request for subscription
+ async def on_presence_subscribe(self, presence):
+ print("on_presence_subscribe")
+ print(presence)
+ jid = presence["from"].bare
+ # await state.request(self, jid)
+ self.send_presence_subscription(
+ pto=jid,
+ pfrom=self.boundjid.bare,
+ ptype="subscribe",
+ pnick=self.alias
+ )
+
+
+ async def on_presence_subscribed(self, presence):
+ jid = presence["from"].bare
+ process.greet(self, jid)
+
+
+ async def on_presence_available(self, presence):
+ # TODO Add function to check whether task is already running or not
+ await task.start_tasks(self, presence)
+
+
+ async def on_presence_unsubscribed(self, presence):
+ await state.unsubscribed(self, presence)
+
+
+ async def on_presence_unavailable(self, presence):
+ await task.stop_tasks(self, presence)
+
+
+ async def on_changed_subscription(self, presence):
+ print("on_changed_subscription")
+ print(presence)
+ jid = presence["from"].bare
+ # breakpoint()
+
+
+ async def on_presence_unsubscribe(self, presence):
+ print("on_presence_unsubscribe")
+ print(presence)
+
+
+ async def on_presence_error(self, presence):
+ print("on_presence_error")
+ print(presence)
+
+
+ async def on_reactions(self, message):
+ print("on_reactions")
+ print(message)
+
+
+ async def on_chatstate_active(self, message):
+ print("on_chatstate_active")
+ print(message)
+
+
+ async def on_chatstate_gone(self, message):
+ print("on_chatstate_gone")
+ print(message)
+
+
+ async def check_chatstate_composing(self, message):
+ print("def check_chatstate_composing")
+ print(message)
+ if message["type"] in ("chat", "normal"):
+ jid = message["from"].bare
+ status_text="Press \"help\" for manual."
+ self.send_presence(
+ # pshow=status_mode,
+ pstatus=status_text,
+ pto=jid,
+ )
+
+
+ async def check_chatstate_paused(self, message):
+ print("def check_chatstate_paused")
+ print(message)
+ if message["type"] in ("chat", "normal"):
+ jid = message["from"].bare
+ await task.refresh_task(
+ self,
+ jid,
+ task.send_status,
+ "status",
+ 20
+ )
+
diff --git a/slixfeed/xmpp/connect.py b/slixfeed/xmpp/connect.py
index 7d9f1ac..d2bd96c 100644
--- a/slixfeed/xmpp/connect.py
+++ b/slixfeed/xmpp/connect.py
@@ -1,6 +1,18 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
+"""
+
+TODO
+
+1) Check interval, and if no connection is establish after 30 seconds
+ then disconnect and reconnect again.
+
+2) or Check ping, and if no ping is received after 30 seconds then
+ disconnect and try to reconnect again.
+
+"""
+
from slixfeed.config import get_value
from slixfeed.dt import current_time
from time import sleep
@@ -18,7 +30,7 @@ async def recover_connection(self, event, message):
# logging.error("Maximum connection attempts exceeded.")
print(current_time(), "Attempt number", self.connection_attempts)
seconds = (get_value(
- "accounts", "XMPP Connect", "reconnect_timeout")) or 30
+ "accounts", "XMPP", "reconnect_timeout")) or 30
seconds = int(seconds)
print(current_time(), "Next attempt within", seconds, "seconds")
# NOTE asyncio.sleep doesn't interval as expected
diff --git a/slixfeed/xmpp/manual.py b/slixfeed/xmpp/manual.py
index 01c79c3..f068162 100644
--- a/slixfeed/xmpp/manual.py
+++ b/slixfeed/xmpp/manual.py
@@ -40,7 +40,7 @@ def print_info():
" Supported protocols: Dat, FTP, Gemini, Gopher, HTTP and IPFS.\n"
"\n"
"AUTHORS\n"
- " Laura Harbinger, Schimon Zackary.\n"
+ " Laura Lapina, Schimon Zackary.\n"
"\n"
"THANKS\n"
" Christian Dersch (SalixOS),"
@@ -53,15 +53,19 @@ def print_info():
" Florent Le Coz (poezio, France),"
"\n"
" George Vlahavas (SalixOS, Greece),"
+ " Guus der Kinderen (IgniteRealtime.org Openfire, Netherlands),"
+ "\n"
" Maxime Buquet (slixmpp, France),"
- "\n"
" Mathieu Pasquet (slixmpp, France),"
- " Pierrick Le Brun (SalixOS, France),"
"\n"
+ " Pierrick Le Brun (SalixOS, France),"
" Remko Tronรงon (Swift, Germany),"
+ "\n"
+ " Raphael Groner (Fedora, Germany),"
" Thorsten Mรผhlfelder (SalixOS, Germany),"
"\n"
- " Yann Leboulanger (Gajim, France).\n"
+ " Yann Leboulanger (Gajim, France)."
+ "\n"
"\n"
"COPYRIGHT\n"
" Slixfeed is free software; you can redistribute it and/or\n"
@@ -70,7 +74,7 @@ def print_info():
" Slixfeed is distributed in the hope that it will be useful,\n"
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- " GNU General Public License for more details.\n"
+ " MIT License for more details.\n"
"\n"
"NOTE\n"
" You can run Slixfeed on your own computer, server, and\n"
diff --git a/slixfeed/xmpp/muc.py b/slixfeed/xmpp/muc.py
index ce5ac8b..5c911a5 100644
--- a/slixfeed/xmpp/muc.py
+++ b/slixfeed/xmpp/muc.py
@@ -31,17 +31,20 @@ async def accept_invitation(self, message):
await join(self, inviter, muc_jid)
-async def autojoin(self, event):
+async def autojoin(self):
result = await self.plugin['xep_0048'].get_bookmarks()
bookmarks = result["private"]["bookmarks"]
conferences = bookmarks["conferences"]
for conference in conferences:
if conference["autojoin"]:
muc_jid = conference["jid"]
- logging.debug("Autojoin groupchat", muc_jid)
+ logging.debug(
+ "Autojoin {} ({})".format(conference["name"], muc_jid))
+ print(
+ "Autojoin {} ({})".format(conference["name"], muc_jid))
self.plugin['xep_0045'].join_muc(
muc_jid,
- self.nick,
+ conference["nick"],
# If a room password is needed, use:
# password=the_room_password,
)
@@ -61,6 +64,7 @@ async def join(self, inviter, muc_jid):
# )
# self.send_message(
# mto=inviter,
+ # mfrom=self.boundjid.bare,
# mbody=(
# "Send activation token {} to groupchat xmpp:{}?join."
# ).format(token, muc_jid)
@@ -69,7 +73,7 @@ async def join(self, inviter, muc_jid):
print(muc_jid)
self.plugin['xep_0045'].join_muc(
muc_jid,
- self.nick,
+ self.alias,
# If a room password is needed, use:
# password=the_room_password,
)
@@ -87,13 +91,14 @@ async def leave(self, muc_jid):
for message in messages:
self.send_message(
mto=muc_jid,
+ mfrom=self.boundjid.bare,
mbody=message,
mtype="groupchat"
)
await bookmark.remove(self, muc_jid)
self.plugin['xep_0045'].leave_muc(
muc_jid,
- self.nick,
+ self.alias,
"Goodbye!",
self.boundjid.bare
)
diff --git a/slixfeed/xmpp/process.py b/slixfeed/xmpp/process.py
index 149ea5e..4824575 100644
--- a/slixfeed/xmpp/process.py
+++ b/slixfeed/xmpp/process.py
@@ -41,6 +41,10 @@ import slixfeed.xmpp.upload as upload
from slixfeed.xmpp.utility import jid_type
+async def event_component(self, event):
+ self.send_presence()
+
+
async def event(self, event):
"""
Process the session_start event.
@@ -84,12 +88,12 @@ async def message(self, message):
message_text = " ".join(message["body"].split())
# if (message["type"] == "groupchat" and
- # message['muc']['nick'] == self.nick):
+ # message['muc']['nick'] == self.alias):
# return
# FIXME Code repetition. See below.
if message["type"] == "groupchat":
- if (message['muc']['nick'] == self.nick):
+ if (message['muc']['nick'] == self.alias):
return
jid_full = str(message["from"])
role = self.plugin['xep_0045'].get_jid_property(
@@ -136,7 +140,7 @@ async def message(self, message):
# nick = message["from"][message["from"].index("/")+1:]
# nick = str(message["from"])
# nick = nick[nick.index("/")+1:]
- if (message['muc']['nick'] == self.nick or
+ if (message['muc']['nick'] == self.alias or
not message["body"].startswith("!")):
return
# token = await initdb(
@@ -198,7 +202,7 @@ async def message(self, message):
response = None
match message_lowercase:
# case "breakpoint":
- # if jid == get_value("accounts", "XMPP", "operator"):
+ # if jid == get_value("accounts", "XMPP Profile", "operator"):
# breakpoint()
# print("task_manager[jid]")
# print(task_manager[jid])
@@ -368,7 +372,7 @@ async def message(self, message):
send_reply_message(self, message, response)
case _ if message_lowercase.startswith("bookmark -"):
if jid == get_value(
- "accounts", "XMPP", "operator"):
+ "accounts", "XMPP Profile", "operator"):
muc_jid = message_text[11:]
await bookmark.remove(self, muc_jid)
response = (
@@ -382,7 +386,7 @@ async def message(self, message):
send_reply_message(self, message, response)
case "bookmarks":
if jid == get_value(
- "accounts", "XMPP", "operator"):
+ "accounts", "XMPP Profile", "operator"):
response = await action.list_bookmarks(self)
else:
response = (
@@ -485,7 +489,13 @@ async def message(self, message):
ext = ext if ext else 'pdf'
url = None
error = None
- if ext in ("epub", "html", "md", "pdf", "txt"):
+ if ext in (
+ "epub", "html", "markdown", "md", "pdf", "text", "txt"):
+ match ext:
+ case "markdown":
+ ext = "md"
+ case "text":
+ ext = "txt"
status_type = "dnd"
status_message = (
"๐๏ธ Procesing request to produce {} document..."
@@ -504,7 +514,7 @@ async def message(self, message):
try:
url = sqlite.get_entry_url(db_file, ix)
except:
- response = "No entry with Id {}".format(ix)
+ response = "No entry with index {}".format(ix)
except:
url = ix_url
if url:
@@ -539,7 +549,7 @@ async def message(self, message):
await task.start_tasks_xmpp(
self, jid, ["status"])
else:
- response = "Missing entry Id."
+ response = "Missing entry index number."
else:
response = "Unsupported filetype."
if response:
@@ -859,7 +869,7 @@ async def message(self, message):
).format(url, ix)
except:
response = (
- "No news source with ID {}."
+ "No news source with index {}."
).format(ix)
except:
url = ix_url
@@ -878,7 +888,7 @@ async def message(self, message):
await task.clean_tasks_xmpp(jid, ["status"])
await task.start_tasks_xmpp(self, jid, ["status"])
else:
- response = "Missing feed ID."
+ response = "Missing feed index number."
send_reply_message(self, message, response)
case _ if message_lowercase.startswith("reset"):
url = message_text[6:]
@@ -947,7 +957,7 @@ async def message(self, message):
"Updates are now disabled for news source {}."
).format(ix)
except:
- response = "No news source with ID {}.".format(ix)
+ response = "No news source with index {}.".format(ix)
send_reply_message(self, message, response)
case _ if message_lowercase.startswith("enable"):
ix = message_text[7:]
@@ -958,7 +968,7 @@ async def message(self, message):
"Updates are now enabled for news source {}."
).format(ix)
except:
- response = "No news source with ID {}.".format(ix)
+ response = "No news source with index {}.".format(ix)
send_reply_message(self, message, response)
case "stop":
# FIXME
@@ -1067,6 +1077,7 @@ async def send_oob_message(self, jid, url):
f'{url}