diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..d87894b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,63 @@ +[build-system] +requires = ["setuptools>=61.2"] +build-backend = "setuptools.build_meta" + +[project] +name = "Slixfeed" +version = "1.0" +description = "RSS news bot for XMPP" +authors = [{name = "Schimon Zachary", email = "sch@fedora.email"}] +license = {text = "MIT"} +classifiers = [ + "Framework :: slixmpp", + "Intended Audience :: End Users/Desktop", + "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Programming Language :: Python", + "Programming Language :: Python :: 3.10", + "Topic :: Communications :: Chat", + "Topic :: Internet :: Extensible Messaging and Presence Protocol (XMPP)", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: News/Diary", + "Topic :: Internet :: Instant Messaging", + "Topic :: Internet :: XMPP", + "Topic :: Office/Business :: News/Diary", +] +keywords = [ + "atom", + "bot", + "chat", + "im", + "jabber", + "news", + "rdf", + "rss", + "syndication", + "xmpp", +] +urls = {Homepage = "https://gitgud.io/sjehuda/slixfeed"} +dependencies = [ + "pyyaml", + "python-dateutil", + "aiohttp", + "bs4", + "feedparser", + "lxml", + "slixmpp", +] + +[project.optional-dependencies] +"export as markdown" = ["html2text"] +"export as pdf" = ["pdfkit"] +"readable html" = ["readability-lxml"] + +# [project.readme] +# text = "Slixfeed is a news aggregator bot for online news feeds. This program is primarily designed for XMPP" + +[project.scripts] +slixfeed = "slixfeed.__main__:main" + +[tool.setuptools] +platforms = ["any"] +[tool.setuptools.package-data] +"*" = ["*.ini", "*.csv", "*.svg", "*.yaml"] diff --git a/setup.py b/setup.py deleted file mode 100644 index 13e4313..0000000 --- a/setup.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python - -from distutils.core import setup - -setup( - name='Slixfeed', - version='1.0', - description='RSS news bot for XMPP', - long_description='Slixfeed is a news aggregator bot for online news feeds. This program is primarily designed for XMPP', - author='Schimon Jehudah Zakai Zockaim Zachary', - author_email='sjehuda@yandex.com', - url='https://gitgud.io/sjehuda/slixfeed', - license='MIT', - platforms=['any'], - install_require=[ - 'aiohttp', - 'bs4', - 'feedparser', - 'html2text', - 'lxml', - 'pdfkit', - 'readability-lxml', - 'slixmpp' - ], - classifiers=[ - 'Framework :: slixmpp', - 'Intended Audience :: End Users/Desktop', - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - 'License :: OSI Approved :: MIT License', - 'Natural Language :: English', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3.10', - 'Topic :: Communications :: Chat', - 'Topic :: Internet :: Extensible Messaging and Presence Protocol (XMPP)', - 'Topic :: Internet :: WWW/HTTP :: Dynamic Content :: News/Diary', - 'Topic :: Internet :: Instant Messaging', - 'Topic :: Internet :: XMPP', - 'Topic :: Office/Business :: News/Diary', - ], - keywords=[ - 'jabber', - 'xmpp', - 'bot', - 'chat', - 'im', - 'news', - 'atom', - 'rdf', - 'rss', - 'syndication' - ], -) diff --git a/slixfeed.py b/slixfeed.py deleted file mode 100644 index 9f58311..0000000 --- a/slixfeed.py +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# Copyright © 2023 Schimon Jehudah -# This program is free software: you can redistribute it and/or modify -# it under the terms of the MIT License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# MIT License for more details. -# -# You should have received a copy of the MIT License along with -# this program. If not, see -# -# Slixfeed - RSS news bot for XMPP -# -# SPDX-FileCopyrightText: 2023 Schimon Jehudah -# -# SPDX-License-Identifier: MIT - -from argparse import ArgumentParser -from getpass import getpass -import logging -from slixfeed.__main__ import Jabber -from slixfeed.config import get_value -from slixfeed.xmpp.client import Slixfeed -import sys - -# import socks -# import socket -# # socks.set_default_proxy(socks.SOCKS5, values[0], values[1]) -# socks.set_default_proxy(socks.SOCKS5, 'localhost', 9050) -# socket.socket = socks.socksocket - -if __name__ == '__main__': - - # 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( - "-n", "--nickname", dest="nickname", help="Display name") - - args = parser.parse_args() - - # Setup logging. - logging.basicConfig( - level=args.loglevel, format='%(levelname)-8s %(message)s') - - # Try configuration file - values = get_value( - "accounts", "XMPP", ["nickname", "username", "password"]) - nickname = values[0] - username = values[1] - password = values[2] - - # Use arguments if were given - if args.jid: - username = args.jid - if args.password: - password = args.password - if args.nickname: - nickname = args.nickname - - # 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: ") - - Jabber(username, password, nickname) - sys.exit(0) diff --git a/slixfeed/__main__.py b/slixfeed/__main__.py index 6bbec84..64f0930 100644 --- a/slixfeed/__main__.py +++ b/slixfeed/__main__.py @@ -1,6 +1,3 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - """ FIXME @@ -80,6 +77,8 @@ TODO # res = response (HTTP) from argparse import ArgumentParser +from getpass import getpass +import sys import configparser # import filehandler # from slixfeed.file import get_default_confdir @@ -145,3 +144,60 @@ class Jabber: # Connect to the XMPP server and start processing XMPP stanzas. xmpp.connect() xmpp.process() +def main(): + + # 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( + "-n", "--nickname", dest="nickname", help="Display name") + + args = parser.parse_args() + + # Setup logging. + logging.basicConfig( + level=args.loglevel, format='%(levelname)-8s %(message)s') + + # Try configuration file + values = get_value( + "accounts", "XMPP", ["nickname", "username", "password"]) + nickname = values[0] + username = values[1] + password = values[2] + + # Use arguments if were given + if args.jid: + username = args.jid + if args.password: + password = args.password + if args.nickname: + nickname = args.nickname + + # 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: ") + + Jabber(username, password, nickname) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/slixfeed/__pycache__/__init__.cpython-311.pyc b/slixfeed/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..43e1aea Binary files /dev/null and b/slixfeed/__pycache__/__init__.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/__main__.cpython-311.pyc b/slixfeed/__pycache__/__main__.cpython-311.pyc new file mode 100644 index 0000000..9a878f7 Binary files /dev/null and b/slixfeed/__pycache__/__main__.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/action.cpython-311.pyc b/slixfeed/__pycache__/action.cpython-311.pyc new file mode 100644 index 0000000..44e5577 Binary files /dev/null and b/slixfeed/__pycache__/action.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/config.cpython-311.pyc b/slixfeed/__pycache__/config.cpython-311.pyc new file mode 100644 index 0000000..6e19829 Binary files /dev/null and b/slixfeed/__pycache__/config.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/crawl.cpython-311.pyc b/slixfeed/__pycache__/crawl.cpython-311.pyc new file mode 100644 index 0000000..9e453cb Binary files /dev/null and b/slixfeed/__pycache__/crawl.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/dt.cpython-311.pyc b/slixfeed/__pycache__/dt.cpython-311.pyc new file mode 100644 index 0000000..f7dcd06 Binary files /dev/null and b/slixfeed/__pycache__/dt.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/fetch.cpython-311.pyc b/slixfeed/__pycache__/fetch.cpython-311.pyc new file mode 100644 index 0000000..3f4e4f5 Binary files /dev/null and b/slixfeed/__pycache__/fetch.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/sqlite.cpython-311.pyc b/slixfeed/__pycache__/sqlite.cpython-311.pyc new file mode 100644 index 0000000..d9e861d Binary files /dev/null and b/slixfeed/__pycache__/sqlite.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/task.cpython-311.pyc b/slixfeed/__pycache__/task.cpython-311.pyc new file mode 100644 index 0000000..ac0a938 Binary files /dev/null and b/slixfeed/__pycache__/task.cpython-311.pyc differ diff --git a/slixfeed/__pycache__/url.cpython-311.pyc b/slixfeed/__pycache__/url.cpython-311.pyc new file mode 100644 index 0000000..34da3a8 Binary files /dev/null and b/slixfeed/__pycache__/url.cpython-311.pyc differ diff --git a/slixfeed/action.py b/slixfeed/action.py index 09548b1..82068a0 100644 --- a/slixfeed/action.py +++ b/slixfeed/action.py @@ -32,7 +32,7 @@ import logging from lxml import html import slixfeed.config as config import slixfeed.crawl as crawl -from slixfeed.datetime import ( +from slixfeed.dt import ( current_date, current_time, now, convert_struct_time_to_iso8601, rfc2822_to_iso8601 diff --git a/slixfeed/assets/__init__.py b/slixfeed/assets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/assets/accounts.ini b/slixfeed/assets/accounts.ini similarity index 100% rename from assets/accounts.ini rename to slixfeed/assets/accounts.ini diff --git a/assets/feeds.csv b/slixfeed/assets/feeds.csv similarity index 100% rename from assets/feeds.csv rename to slixfeed/assets/feeds.csv diff --git a/assets/image.svg b/slixfeed/assets/image.svg similarity index 100% rename from assets/image.svg rename to slixfeed/assets/image.svg diff --git a/assets/lists.yaml b/slixfeed/assets/lists.yaml similarity index 100% rename from assets/lists.yaml rename to slixfeed/assets/lists.yaml diff --git a/assets/proxies.yaml b/slixfeed/assets/proxies.yaml similarity index 100% rename from assets/proxies.yaml rename to slixfeed/assets/proxies.yaml diff --git a/assets/queries.yaml b/slixfeed/assets/queries.yaml similarity index 100% rename from assets/queries.yaml rename to slixfeed/assets/queries.yaml diff --git a/assets/settings.ini b/slixfeed/assets/settings.ini similarity index 100% rename from assets/settings.ini rename to slixfeed/assets/settings.ini diff --git a/slixfeed/datetime.py b/slixfeed/dt.py similarity index 100% rename from slixfeed/datetime.py rename to slixfeed/dt.py diff --git a/slixfeed/main.py.bak b/slixfeed/main.py.bak deleted file mode 100644 index c50b185..0000000 --- a/slixfeed/main.py.bak +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" - -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. - -3) Support MUC. - -4) Support categories. - -5) Default prepackaged list of feeds. - -6) XMPP commands. - -7) Bot as transport. - -8) OMEMO. - -9) Logging. - -10) Default feeds (e.g. Blacklisted News, TBOT etc.) - -11) Download and upload/send article (xHTML, xHTMLZ, Markdown, MHTML, TXT). - Use Readability. - -12) Fetch summary from URL, instead of storing summary. - -13) Support protocol Gopher - https://github.com/michael-lazar/pygopherd - https://github.com/gopherball/gb - -13) Support ActivityPub @person@domain (see Tip Of The Day). - -12) 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, HubZilla, Mastodon, Misskey, Pixelfed, Pleroma, Soapbox. - -""" - -# vars and their meanings: -# jid = Jabber ID (XMPP) -# res = response (HTTP) - -from argparse import ArgumentParser -from getpass import getpass -import logging - -from datetime import date -import time - -# 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): - -#import irchandler -import xmpphandler -#import matrixhandler - - -if __name__ == '__main__': - # Setup the command line arguments. - parser = ArgumentParser(description=xmpphandler.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="JID to use") - parser.add_argument("-p", "--password", dest="password", - help="password to use") - - args = parser.parse_args() - - # Setup logging. - logging.basicConfig(level=args.loglevel, - format='%(levelname)-8s %(message)s') - - if args.jid is None: - args.jid = input("Username: ") - if args.password is None: - args.password = getpass("Password: ") - - # Setup the Slixfeed and register plugins. Note that while plugins may - # have interdependencies, the order in which you register them does - # not matter. - xmpp = xmpphandler.Slixfeed(args.jid, args.password) - 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_0060') # PubSub - xmpp.register_plugin('xep_0199', {'keepalive': True, 'frequency': 15}) # XMPP Ping - xmpp.register_plugin('xep_0249') # Multi-User Chat - xmpp.register_plugin('xep_0402') # PEP Native Bookmarks - - # Connect to the XMPP server and start processing XMPP stanzas. - xmpp.connect() - xmpp.process() diff --git a/slixfeed/sqlite.py b/slixfeed/sqlite.py index aeceeb9..be5368b 100644 --- a/slixfeed/sqlite.py +++ b/slixfeed/sqlite.py @@ -17,7 +17,7 @@ from datetime import date import logging import slixfeed.config as config # from slixfeed.data import join_url -from slixfeed.datetime import ( +from slixfeed.dt import ( current_time, rfc2822_to_iso8601 ) diff --git a/slixfeed/task.py b/slixfeed/task.py index ffd8009..4cb6e31 100644 --- a/slixfeed/task.py +++ b/slixfeed/task.py @@ -49,7 +49,7 @@ from slixfeed.config import ( get_pathname_to_database, get_default_data_directory, get_value_default) -from slixfeed.datetime import current_time +# from slixfeed.dt import current_time from slixfeed.sqlite import ( get_feed_title, get_feeds_url, diff --git a/slixfeed/xmpp/__init__.py b/slixfeed/xmpp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/slixfeed/xmpp/__pycache__/__init__.cpython-311.pyc b/slixfeed/xmpp/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000..cf54fc5 Binary files /dev/null and b/slixfeed/xmpp/__pycache__/__init__.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/bookmark.cpython-311.pyc b/slixfeed/xmpp/__pycache__/bookmark.cpython-311.pyc new file mode 100644 index 0000000..9ac2293 Binary files /dev/null and b/slixfeed/xmpp/__pycache__/bookmark.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/client.cpython-311.pyc b/slixfeed/xmpp/__pycache__/client.cpython-311.pyc new file mode 100644 index 0000000..2dea798 Binary files /dev/null and b/slixfeed/xmpp/__pycache__/client.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/connect.cpython-311.pyc b/slixfeed/xmpp/__pycache__/connect.cpython-311.pyc new file mode 100644 index 0000000..a2d2b4b Binary files /dev/null and b/slixfeed/xmpp/__pycache__/connect.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/manual.cpython-311.pyc b/slixfeed/xmpp/__pycache__/manual.cpython-311.pyc new file mode 100644 index 0000000..1adf823 Binary files /dev/null and b/slixfeed/xmpp/__pycache__/manual.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/muc.cpython-311.pyc b/slixfeed/xmpp/__pycache__/muc.cpython-311.pyc new file mode 100644 index 0000000..31a26e0 Binary files /dev/null and b/slixfeed/xmpp/__pycache__/muc.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/process.cpython-311.pyc b/slixfeed/xmpp/__pycache__/process.cpython-311.pyc new file mode 100644 index 0000000..400ff3e Binary files /dev/null and b/slixfeed/xmpp/__pycache__/process.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/profile.cpython-311.pyc b/slixfeed/xmpp/__pycache__/profile.cpython-311.pyc new file mode 100644 index 0000000..6c29cf0 Binary files /dev/null and b/slixfeed/xmpp/__pycache__/profile.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/roster.cpython-311.pyc b/slixfeed/xmpp/__pycache__/roster.cpython-311.pyc new file mode 100644 index 0000000..a911c8a Binary files /dev/null and b/slixfeed/xmpp/__pycache__/roster.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/state.cpython-311.pyc b/slixfeed/xmpp/__pycache__/state.cpython-311.pyc new file mode 100644 index 0000000..d575aa0 Binary files /dev/null and b/slixfeed/xmpp/__pycache__/state.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/status.cpython-311.pyc b/slixfeed/xmpp/__pycache__/status.cpython-311.pyc new file mode 100644 index 0000000..08a8371 Binary files /dev/null and b/slixfeed/xmpp/__pycache__/status.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/upload.cpython-311.pyc b/slixfeed/xmpp/__pycache__/upload.cpython-311.pyc new file mode 100644 index 0000000..17fd43c Binary files /dev/null and b/slixfeed/xmpp/__pycache__/upload.cpython-311.pyc differ diff --git a/slixfeed/xmpp/__pycache__/utility.cpython-311.pyc b/slixfeed/xmpp/__pycache__/utility.cpython-311.pyc new file mode 100644 index 0000000..3597aea Binary files /dev/null and b/slixfeed/xmpp/__pycache__/utility.cpython-311.pyc differ diff --git a/slixfeed/xmpp/connect.py b/slixfeed/xmpp/connect.py index be8e37e..7d9f1ac 100644 --- a/slixfeed/xmpp/connect.py +++ b/slixfeed/xmpp/connect.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- from slixfeed.config import get_value -from slixfeed.datetime import current_time +from slixfeed.dt import current_time from time import sleep import logging diff --git a/slixfeed/xmpp/muc.py b/slixfeed/xmpp/muc.py index 18c6874..ce5ac8b 100644 --- a/slixfeed/xmpp/muc.py +++ b/slixfeed/xmpp/muc.py @@ -15,7 +15,7 @@ TODO import logging import slixfeed.xmpp.bookmark as bookmark import slixfeed.xmpp.process as process -from slixfeed.datetime import current_time +from slixfeed.dt import current_time # async def accept_muc_invite(self, message, ctr=None): # # if isinstance(message, str): diff --git a/slixfeed/xmpp/process.py b/slixfeed/xmpp/process.py index ffddb9d..c5ba512 100644 --- a/slixfeed/xmpp/process.py +++ b/slixfeed/xmpp/process.py @@ -29,7 +29,7 @@ from slixfeed.config import ( get_value, get_pathname_to_database, remove_from_list) -from slixfeed.datetime import current_time, timestamp +from slixfeed.dt import current_time, timestamp import slixfeed.sqlite as sqlite import slixfeed.task as task import slixfeed.url as uri