Slixfeed/slixfeed/__main__.py

277 lines
9 KiB
Python
Raw Normal View History

"""
FIXME
1) Check feed duplication on runtime.
When feed is valid and is not yet in the database it is
posible to send a batch which would result in duplication.
Consequently, it might result in database lock error upon
feed removal attempt
TODO
1) SQL prepared statements;
2) Machine Learning for scrapping Title, Link, Summary and Timstamp;
2023-12-24 19:37:05 +01:00
Scrape element </article> (example: Liferea)
http://intertwingly.net/blog/
https://www.brandenburg.de/
3) Set MUC subject
Feeds which entries are to be set as groupchat subject.
Perhaps not, as it would require to check every feed for this setting.
2023-12-24 19:37:05 +01:00
Maybe a separate bot;
4) Support categories;
5) XMPP commands;
6) Bot as service;
7) OMEMO;
8) Logging;
2023-12-24 19:37:05 +01:00
https://docs.python.org/3/howto/logging.html
9) Readability
2023-12-24 19:37:05 +01:00
See project /buriy/python-readability
9.1) IDEA: Bot to display Title and Excerpt
(including sending a PDF version of it) of posted link
2024-01-09 16:53:19 +01:00
10) Fetch summary from URL, instead of storing summary, or
Store 5 upcoming summaries.
This would help making the database files smaller.
2023-11-15 15:02:39 +01:00
2024-01-09 16:53:19 +01:00
11) Support protocol Gopher
2023-12-24 19:37:05 +01:00
See project /michael-lazar/pygopherd
See project /gopherball/gb
2023-11-15 15:02:39 +01:00
2024-01-09 16:53:19 +01:00
12) Support ActivityPub @person@domain (see Tip Of The Day).
2024-01-09 16:53:19 +01:00
13) Tip Of The Day.
Did you know that you can follow you favorite Mastodon feeds by just
sending the URL address?
Supported fediverse websites are:
Akkoma, Firefish (Calckey), Friendica, HubZilla,
Mastodon, Misskey, Pixelfed, Pleroma, Socialhome, Soapbox.
2024-01-09 16:53:19 +01:00
14) Brand: News Broker, Newsman, Newsdealer, Laura Harbinger
2024-01-09 16:53:19 +01:00
15) See project /offpunk/offblocklist.py
2023-12-24 19:37:05 +01:00
2024-01-09 16:53:19 +01:00
16) Search messages of government regulated publishers, and promote other sources.
2023-12-24 19:37:05 +01:00
Dear reader, we couldn't get news from XYZ as they don't provide RSS feeds.
However, you might want to get news from (1) (2) and (3) instead!
2024-01-09 16:53:19 +01:00
17) Make the program portable (directly use the directory assets) -- Thorsten
2024-01-14 19:05:12 +01:00
18) The operator account will be given reports from the bot about its
activities every X minutes.
When a suspicious activity is detected, it will be reported immediately.
19) Communicate to messages of new contacts (not subscribed and not in roster)
"""
2023-07-16 17:23:10 +02:00
# vars and their meanings:
# jid = Jabber ID (XMPP)
# res = response (HTTP)
from argparse import ArgumentParser
2024-01-18 21:57:49 +01:00
from getpass import getpass
import sys
import configparser
# import filehandler
# from slixfeed.file import get_default_confdir
2023-07-16 17:23:10 +02:00
from getpass import getpass
import logging
import os
2023-07-16 17:23:10 +02:00
# from datetime import date
# import time
2023-07-16 17:23:10 +02:00
# from eliot import start_action, to_file
# # to_file(open("slixfeed.log", "w"))
# # with start_action(action_type="set_date()", jid=jid):
# # with start_action(action_type="message()", msg=msg):
2023-07-16 17:23:10 +02:00
#import slixfeed.smtp
#import slixfeed.irc
#import slixfeed.matrix
from slixfeed.config import get_default_config_directory, get_value
2023-07-16 17:23:10 +02:00
import socks
import socket
xmpp_type = get_value(
"accounts", "XMPP", "type")
match xmpp_type:
case "client":
from slixfeed.xmpp.client import Slixfeed
case "component":
2024-01-24 21:28:14 +01:00
from slixfeed.xmpp.component import SlixfeedComponent
class JabberComponent:
2024-01-24 21:28:14 +01:00
def __init__(self, jid, secret, hostname, port, alias=None):
xmpp = SlixfeedComponent(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()
2023-07-16 17:23:10 +02:00
class JabberClient:
2024-01-24 21:28:14 +01:00
def __init__(self, jid, password, hostname=None, port=None, alias=None):
xmpp = Slixfeed(jid, password, 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
2024-01-17 15:36:28 +01:00
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
2024-01-17 15:36:28 +01:00
xmpp.register_plugin('xep_0084') # User Avatar
# xmpp.register_plugin('xep_0085') # Chat State Notifications
2024-01-17 15:36:28 +01:00
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
# proxy_enabled = get_value("accounts", "XMPP", "proxy_enabled")
# if proxy_enabled == '1':
# values = get_value("accounts", "XMPP", [
# "proxy_host",
# "proxy_port",
# "proxy_username",
# "proxy_password"
# ])
# print("Proxy is enabled: {}:{}".format(values[0], values[1]))
# xmpp.use_proxy = True
# xmpp.proxy_config = {
# 'host': values[0],
# 'port': values[1],
# 'username': values[2],
# 'password': values[3]
# }
# proxy = {'socks5': (values[0], values[1])}
# xmpp.proxy = {'socks5': ('localhost', 9050)}
# Connect to the XMPP server and start processing XMPP stanzas.
address = get_value(
"accounts", "XMPP Client", ["hostname", "port"])
if address[0] and address[1]:
xmpp.connect(tuple(address))
else:
xmpp.connect()
xmpp.process()
2024-01-18 21:57:49 +01:00
def main():
config_dir = get_default_config_directory()
logging.info("Reading configuration from {}".format(config_dir))
print("Reading configuration from {}".format(config_dir))
values = get_value(
"accounts", "XMPP Proxy", ["socks5_host", "socks5_port"])
if values[0] and values[1]:
host = values[0]
port = values[1]
s = socks.socksocket()
s.set_proxy(socks.SOCKS5, host, port)
# socks.set_default_proxy(socks.SOCKS5, host, port)
# socket.socket = socks.socksocket
2024-01-18 21:57:49 +01:00
# Setup the command line arguments.
parser = ArgumentParser(description=Slixfeed.__doc__)
# Output verbosity options.
parser.add_argument(
"-q", "--quiet", help="set logging to ERROR",
action="store_const", dest="loglevel",
const=logging.ERROR, default=logging.INFO)
parser.add_argument(
"-d", "--debug", help="set logging to DEBUG",
action="store_const", dest="loglevel",
const=logging.DEBUG, default=logging.INFO)
# JID and password options.
parser.add_argument(
"-j", "--jid", dest="jid", help="Jabber ID")
parser.add_argument(
"-p", "--password", dest="password", help="Password of JID")
parser.add_argument(
"-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")
2024-01-18 21:57:49 +01:00
args = parser.parse_args()
# Setup logging.
logging.basicConfig(
level=args.loglevel, format='%(levelname)-8s %(message)s')
# Try configuration file
values = get_value(
"accounts", "XMPP Client", [
2024-01-24 19:59:10 +01:00
"alias", "jid", "password", "hostname", "port"])
alias = values[0]
2024-01-24 19:59:10 +01:00
jid = values[1]
2024-01-18 21:57:49 +01:00
password = values[2]
hostname = values[3]
port = values[4]
2024-01-18 21:57:49 +01:00
# Use arguments if were given
if args.jid:
2024-01-24 19:59:10 +01:00
jid = args.jid
2024-01-18 21:57:49 +01:00
if args.password:
password = args.password
if args.alias:
alias = args.alias
if args.hostname:
hostname = args.hostname
if args.port:
port = args.port
2024-01-18 21:57:49 +01:00
# Prompt for credentials if none were given
2024-01-24 19:59:10 +01:00
if not jid:
jid = input("JID: ")
2024-01-18 21:57:49 +01:00
if not password:
password = getpass("Password: ")
if not alias:
alias = (input("Alias: ")) or "Slixfeed"
match xmpp_type:
case "client":
2024-01-24 21:28:14 +01:00
JabberClient(jid, password, hostname=hostname, port=port, alias=alias)
case "component":
2024-01-24 21:28:14 +01:00
JabberComponent(jid, password, hostname, port, alias=alias)
2024-01-18 21:57:49 +01:00
sys.exit(0)
if __name__ == "__main__":
main()