chore(*): ready for packaging

Signed-off-by: Rongrong <15956627+Rongronggg9@users.noreply.github.com>
This commit is contained in:
Rongrong 2022-03-30 15:21:09 +08:00
parent e2e60328b2
commit 2339760532
No known key found for this signature in database
GPG Key ID: A36C9CDA260CB264
14 changed files with 141 additions and 30 deletions

3
pyproject.toml Normal file
View File

@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools>=42", "wheel", "setuptools-declarative-requirements"]
build-backend = "setuptools.build_meta"

View File

@ -16,7 +16,7 @@ minify-html>=0.6.10, <=0.8.0 # 0.6.10 for Python 3.7 (however, minify-html<0.7.
matplotlib==3.5.1 matplotlib==3.5.1
# db # db
git+https://github.com/Rongronggg9/asyncpg.git@fix/pep-621 asyncpg@git+https://github.com/Rongronggg9/asyncpg.git@fix/pep-621
tortoise-orm[accel]==0.19.0 tortoise-orm[accel]==0.19.0
aerich==0.6.2 aerich==0.6.2

43
setup.cfg Normal file
View File

@ -0,0 +1,43 @@
[metadata]
name = rsstt
author = Rongrong
author_email = Rongronggg9@outlook.com
description = A Telegram RSS bot that cares about your reading experience
long_description = file: README.md
long_description_content_type = text/markdown
license = AGPLv3+
platforms = Linux, Windows, MacOS
url = https://github.com/Rongronggg9/RSS-to-Telegram-Bot
project_urls =
Bug Tracker = https://github.com/Rongronggg9/RSS-to-Telegram-Bot/issues
Documentation = https://github.com/Rongronggg9/RSS-to-Telegram-Bot/blob/dev/docs/README.md
Source Code = https://github.com/Rongronggg9/RSS-to-Telegram-Bot
Changelog = https://github.com/Rongronggg9/RSS-to-Telegram-Bot/blob/dev/docs/CHANGELOG.md
classifiers =
Development Status :: 5 - Production/Stable
Environment :: Console
Framework :: AsyncIO
Framework :: aiohttp
License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
Operating System :: POSIX :: Linux
Operating System :: Microsoft :: Windows
Operating System :: MacOS
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Topic :: Communications :: Chat
Topic :: Internet
Topic :: Multimedia
[requirements-files]
install_requires = requirements.txt
[options]
zip_safe = False
python_requires = >=3.7
[options.package_data]
* = *.json, *.opml, *.sql, *.txt
rsstt = ../requirements.txt

19
setup.py Normal file
View File

@ -0,0 +1,19 @@
import re
from functools import partial
from setuptools import setup, find_packages
from distutils.util import convert_path
version = {}
with open(convert_path('src/version.py')) as f:
exec(f.read(), version)
replacePackagePath = partial(re.compile(rf'^src').sub, 'rsstt')
source_packages = find_packages(include=['src', f'src.*'])
proj_packages = [replacePackagePath(name) for name in source_packages]
setup(
version=version['__version__'],
packages=proj_packages,
package_dir={'rsstt': 'src'},
)

View File

@ -18,7 +18,7 @@ from telethon import TelegramClient, events
from telethon.errors import ApiIdPublishedFloodError from telethon.errors import ApiIdPublishedFloodError
from telethon.tl import types from telethon.tl import types
from random import sample from random import sample
from pathlib import Path from os import path
from . import env, log, db, command from . import env, log, db, command
from .i18n import i18n, ALL_LANGUAGES, get_commands_list from .i18n import i18n, ALL_LANGUAGES, get_commands_list
@ -30,7 +30,6 @@ logger = log.getLogger('RSStT')
# initializing bot # initializing bot
loop = env.loop loop = env.loop
Path("config").mkdir(parents=True, exist_ok=True)
bot: Optional[TelegramClient] = None bot: Optional[TelegramClient] = None
if not env.API_ID or not env.API_HASH: if not env.API_ID or not env.API_HASH:
logger.info('API_ID and/or API_HASH not set, use sample APIs instead. API_ID_PUBLISHED_FLOOD_ERROR may occur.') logger.info('API_ID and/or API_HASH not set, use sample APIs instead. API_ID_PUBLISHED_FLOOD_ERROR may occur.')
@ -44,7 +43,8 @@ while API_KEYs:
sleep_for += 10 sleep_for += 10
API_ID, API_HASH = API_KEYs.popitem() API_ID, API_HASH = API_KEYs.popitem()
try: try:
bot = TelegramClient('config/bot', API_ID, API_HASH, proxy=env.TELEGRAM_PROXY_DICT, request_retries=2, bot = TelegramClient(path.join(env.config_folder_path, 'bot'),
API_ID, API_HASH, proxy=env.TELEGRAM_PROXY_DICT, request_retries=2,
raise_last_call_error=True, loop=loop).start(bot_token=env.TOKEN) raise_last_call_error=True, loop=loop).start(bot_token=env.TOKEN)
break break
except ApiIdPublishedFloodError: except ApiIdPublishedFloodError:

View File

@ -19,7 +19,7 @@ from ...parsing.utils import html_space_stripper
FeedSnifferCache = TTLCache(maxsize=256, ttl=60 * 60 * 24) FeedSnifferCache = TTLCache(maxsize=256, ttl=60 * 60 * 24)
with open(path.join(path.dirname(__file__), '../..', 'opml_template.opml'), 'r') as __template: with open(path.normpath(path.join(path.dirname(__file__), '../..', 'opml_template.opml')), 'r') as __template:
OPML_TEMPLATE = __template.read() OPML_TEMPLATE = __template.read()

View File

@ -8,7 +8,7 @@ TORTOISE_ORM = {
}, },
"apps": { "apps": {
"models": { "models": {
"models": ["aerich.models", "src.db.models"], "models": ["aerich.models", f"{env.self_module_name}.db.models"],
"default_connection": "default", "default_connection": "default",
}, },
}, },

View File

View File

View File

@ -4,12 +4,19 @@ from .compat import Final
import asyncio import asyncio
import os import os
import sys
import logging import logging
import re import re
import argparse
from telethon import TelegramClient from telethon import TelegramClient
from telethon.tl.types import User, InputPeerUser from telethon.tl.types import User, InputPeerUser
from python_socks import parse_proxy_url from python_socks import parse_proxy_url
from dotenv import load_dotenv from dotenv import load_dotenv
from pathlib import Path
from .version import __version__
logging.basicConfig(level=logging.INFO)
# ----- utils ----- # ----- utils -----
@ -36,36 +43,73 @@ def __list_parser(var: Optional[str]) -> list[str]:
return var_t return var_t
# ----- determine the environment -----
__arg_parser = argparse.ArgumentParser(
description='RSS to Telegram Bot, a Telegram RSS bot that cares about your reading experience.')
__arg_parser.add_argument('-c', '--config', metavar='/path/to/config/folder', type=str, nargs=1,
help='path to the config folder')
cli_args = __arg_parser.parse_args()
cli_entry = sys.argv[0] # expect `-m` or `/path/to/telegramRSSbot.py`
custom_config_path = cli_args.config[0] if cli_args.config else None
is_self_run_as_a_whole_package = cli_entry.endswith('telegramRSSbot.py')
user_home = os.path.expanduser('~')
self_path = os.path.dirname(__file__)
self_module_name = os.path.basename(self_path)
if custom_config_path:
config_folder_path = os.path.normpath(os.path.abspath(custom_config_path))
elif is_self_run_as_a_whole_package:
config_folder_path = os.path.normpath(os.path.join(self_path, '..', 'config'))
else:
config_folder_path = os.path.join(user_home, '.rsstt')
Path(config_folder_path).mkdir(parents=True, exist_ok=True)
logging.info(f'Config folder: {config_folder_path}')
# ----- load .env ----- # ----- load .env -----
load_dotenv(override=True) dot_env_paths = (os.path.join(config_folder_path, '.env'),
os.path.join(os.path.abspath('.'), '.env'))
if is_self_run_as_a_whole_package:
dot_env_paths = (os.path.normpath(os.path.join(self_path, '..', '.env')),) + dot_env_paths
for dot_env_path in sorted(set(dot_env_paths), key=dot_env_paths.index):
if os.path.isfile(dot_env_path):
load_dotenv(dot_env_path, override=True)
logging.info(f'Found .env file at "{dot_env_path}", loaded')
# ----- get version ----- # ----- get version -----
# noinspection PyBroadException if is_self_run_as_a_whole_package:
try:
with open('.version', 'r') as v:
_version = v.read().strip()
except Exception:
_version = 'dirty'
if _version == 'dirty':
from subprocess import Popen, PIPE, DEVNULL
# noinspection PyBroadException # noinspection PyBroadException
try: try:
with Popen(['git', 'describe', '--tags'], shell=False, stdout=PIPE, stderr=DEVNULL, bufsize=-1) as __: with open(os.path.normpath(os.path.join(self_path, '..', '.version')), 'r') as v:
__.wait(3) _version = v.read().strip()
_version = __.stdout.read().decode().strip()
with Popen(['git', 'branch', '--show-current'], shell=False, stdout=PIPE, stderr=DEVNULL, bufsize=-1) as __:
__.wait(3)
__ = __.stdout.read().decode().strip()
if __:
_version += f'@{__}'
except Exception: except Exception:
_version = 'dirty' _version = 'dirty'
if not _version or _version == '@': if _version == 'dirty':
from subprocess import Popen, PIPE, DEVNULL
# noinspection PyBroadException
try:
with Popen(['git', 'describe', '--tags'], shell=False, stdout=PIPE, stderr=DEVNULL, bufsize=-1) as __:
__.wait(3)
_version = __.stdout.read().decode().strip()
with Popen(['git', 'branch', '--show-current'], shell=False, stdout=PIPE, stderr=DEVNULL, bufsize=-1) as __:
__.wait(3)
__ = __.stdout.read().decode().strip()
if __:
_version += f'@{__}'
except Exception:
_version = 'dirty'
if not _version or _version == '@':
_version = 'dirty'
else:
_version = 'dirty' _version = 'dirty'
if not re.match(r'v?\d+\.\d+(\.\d+)?', _version):
_version = 'v' + (__version__ + '-' + _version if not _version == 'dirty' else __version__)
VERSION: Final = _version VERSION: Final = _version
del _version del _version
@ -152,7 +196,7 @@ else:
PROXY_BYPASS_PRIVATE: Final = __bool_parser(os.environ.get('PROXY_BYPASS_PRIVATE')) PROXY_BYPASS_PRIVATE: Final = __bool_parser(os.environ.get('PROXY_BYPASS_PRIVATE'))
PROXY_BYPASS_DOMAINS: Final = __list_parser(os.environ.get('PROXY_BYPASS_DOMAINS')) PROXY_BYPASS_DOMAINS: Final = __list_parser(os.environ.get('PROXY_BYPASS_DOMAINS'))
USER_AGENT: Final = os.environ.get('USER_AGENT') or 'RSStT/2.2 RSS Reader' USER_AGENT: Final = os.environ.get('USER_AGENT') or f'RSStT/{__version__} RSS Reader'
IPV6_PRIOR: Final = __bool_parser(os.environ.get('IPV6_PRIOR')) IPV6_PRIOR: Final = __bool_parser(os.environ.get('IPV6_PRIOR'))
# ----- img relay server config ----- # ----- img relay server config -----
@ -170,7 +214,7 @@ IMAGES_WESERV_NL: Final = ('https://' if not _images_weserv_nl.startswith('http'
del _images_weserv_nl del _images_weserv_nl
# ----- db config ----- # ----- db config -----
_database_url = os.environ.get('DATABASE_URL') or 'sqlite://config/db.sqlite3?journal_mode=OFF' _database_url = os.environ.get('DATABASE_URL') or f'sqlite://{config_folder_path}/db.sqlite3?journal_mode=OFF'
DATABASE_URL: Final = (_database_url.replace('postgresql', 'postgres', 1) if _database_url.startswith('postgresql') DATABASE_URL: Final = (_database_url.replace('postgresql', 'postgres', 1) if _database_url.startswith('postgresql')
else _database_url) else _database_url)
del _database_url del _database_url
@ -204,8 +248,8 @@ if any((os.environ.get('REDISHOST'), os.environ.get('REDISUSER'), os.environ.get
'REDISPORT\n' 'REDISPORT\n'
'REDIS_NUM') 'REDIS_NUM')
if os.path.exists('config/rss.db'): if is_self_run_as_a_whole_package and os.path.exists(os.path.join(config_folder_path, 'rss.db')):
os.rename('config/rss.db', 'config/rss.db.bak') os.rename(os.path.join(config_folder_path, 'rss.db'), os.path.join(config_folder_path, 'rss.db.bak'))
logging.warning('Sqlite DB "rss.db" with old schema is DEPRECATED and renamed to "rss.db.bak" automatically!\n' logging.warning('Sqlite DB "rss.db" with old schema is DEPRECATED and renamed to "rss.db.bak" automatically!\n'
'ALL SUBS IN THE OLD DB WILL NOT BE MIGRATED. ' 'ALL SUBS IN THE OLD DB WILL NOT BE MIGRATED. '
'IF YOU NEED TO BACKUP YOUR SUBS, DOWNGRADE AND USE "/export" COMMAND TO BACKUP.') 'IF YOU NEED TO BACKUP YOUR SUBS, DOWNGRADE AND USE "/export" COMMAND TO BACKUP.')

1
src/parsing/__init__.py Normal file
View File

@ -0,0 +1 @@
from __future__ import annotations

1
src/version.py Normal file
View File

@ -0,0 +1 @@
__version__ = "2.2.1.dev0"