mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
Continue
This commit is contained in:
parent
cb9ff43a6c
commit
839ae802e2
5 changed files with 119 additions and 78 deletions
|
@ -1,54 +1,48 @@
|
|||
[tool.poetry]
|
||||
name = "royalnet"
|
||||
version = "5.1a1"
|
||||
description = "A multipurpose bot and web framework"
|
||||
authors = ["Stefano Pigozzi <ste.pigozzi@gmail.com>"]
|
||||
license = "AGPL-3.0+"
|
||||
readme = "README.md"
|
||||
homepage = "https://github.com/Steffo99/royalnet"
|
||||
documentation = "https://gh.steffo.eu/royalnet/"
|
||||
classifiers = [
|
||||
name = "royalnet"
|
||||
version = "5.1a1"
|
||||
description = "A multipurpose bot and web framework"
|
||||
authors = ["Stefano Pigozzi <ste.pigozzi@gmail.com>"]
|
||||
license = "AGPL-3.0+"
|
||||
readme = "README.md"
|
||||
homepage = "https://github.com/Steffo99/royalnet"
|
||||
documentation = "https://gh.steffo.eu/royalnet/"
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3.7",
|
||||
"License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)"
|
||||
]
|
||||
]
|
||||
|
||||
# Library dependencies
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.8"
|
||||
|
||||
dateparser = "^0.7.2"
|
||||
|
||||
python_telegram_bot = {version="^12.2.0", optional=true}
|
||||
|
||||
discord_py = {git = "https://github.com/Rapptz/discord.py", optional=true} # discord.py 1.2.4 is missing Go Live related methods
|
||||
pynacl = {version="^1.3.0", optional=true} # This requires libffi-dev and python3.*-dev to be installed on Linux systems
|
||||
|
||||
ffmpeg_python = {version="~0.2.0", optional=true}
|
||||
youtube_dl = {version="*", optional=true}
|
||||
|
||||
sqlalchemy = {version="^1.3.10", optional=true}
|
||||
|
||||
psycopg2 = {version="^2.8.4", optional=true} # Requires quite a bit of stuff http://initd.org/psycopg/docs/install.html#install-from-source
|
||||
psycopg2_binary = {version="^2.8.4", optional=true} # Prebuilt alternative to psycopg2, not recommended
|
||||
|
||||
starlette = {version="0.12.13", optional=true}
|
||||
python = "^3.8"
|
||||
dateparser = "^0.7.2"
|
||||
python_telegram_bot = {version="^12.2.0", optional=true}
|
||||
discord_py = {git = "https://github.com/Rapptz/discord.py", optional=true} # discord.py 1.2.4 is missing Go Live related methods
|
||||
pynacl = {version="^1.3.0", optional=true} # This requires libffi-dev and python3.*-dev to be installed on Linux systems
|
||||
ffmpeg_python = {version="~0.2.0", optional=true}
|
||||
youtube_dl = {version="*", optional=true}
|
||||
sqlalchemy = {version="^1.3.10", optional=true}
|
||||
psycopg2 = {version="^2.8.4", optional=true} # Requires quite a bit of stuff http://initd.org/psycopg/docs/install.html#install-from-source
|
||||
psycopg2_binary = {version="^2.8.4", optional=true} # Prebuilt alternative to psycopg2, not recommended
|
||||
starlette = {version="^0.12.13", optional=true}
|
||||
sentry_sdk = {version="~0.13.2", optional=true}
|
||||
|
||||
# Optional dependencies
|
||||
[tool.poetry.extras]
|
||||
telegram = ["python_telegram_bot"]
|
||||
discord = ["discord_py", "pynacl"]
|
||||
alchemy_easy = ["sqlalchemy", "psycopg2_binary"]
|
||||
alchemy_hard = ["sqlalchemy", "psycopg2"]
|
||||
bard = ["ffmpeg_python", "youtube_dl"]
|
||||
constellation = ["starlette"]
|
||||
telegram = ["python_telegram_bot"]
|
||||
discord = ["discord_py", "pynacl"]
|
||||
alchemy_easy = ["sqlalchemy", "psycopg2_binary"]
|
||||
alchemy_hard = ["sqlalchemy", "psycopg2"]
|
||||
bard = ["ffmpeg_python", "youtube_dl"]
|
||||
constellation = ["starlette"]
|
||||
sentry = ["sentry_sdk"]
|
||||
|
||||
# Development dependencies
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = "^5.2.2"
|
||||
|
||||
# There are none
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry>=0.12"]
|
||||
build-backend = "poetry.masonry.api"
|
||||
requires = ["poetry>=0.12"]
|
||||
build-backend = "poetry.masonry.api"
|
||||
|
|
|
@ -35,12 +35,26 @@ class Constellation:
|
|||
exc_stars = []
|
||||
|
||||
self.secrets_name: str = secrets_name
|
||||
"""The secrets_name this Constellation is currently using."""
|
||||
|
||||
self.running: bool = False
|
||||
"""Is the Constellation currently running?"""
|
||||
|
||||
log.info(f"Creating Starlette in {'Debug' if __debug__ else 'Production'} mode...")
|
||||
self.starlette = Starlette(debug=debug)
|
||||
"""The :class:`Starlette` app."""
|
||||
|
||||
log.info(f"Creating Alchemy with Tables: {' '.join([table.__name__ for table in tables])}")
|
||||
log.debug("Finding required Tables...")
|
||||
tables = set()
|
||||
for SelectedPageStar in page_stars:
|
||||
tables = tables.union(SelectedPageStar.tables)
|
||||
for SelectedExcStar in exc_stars:
|
||||
tables = tables.union(SelectedExcStar.tables)
|
||||
log.debug(f"Found Tables: {' '.join([table.__name__ for table in tables])}")
|
||||
|
||||
log.info(f"Creating Alchemy...")
|
||||
self.alchemy: royalnet.database.Alchemy = royalnet.database.Alchemy(database_uri=database_uri, tables=tables)
|
||||
"""The :class:`Alchemy: of this Constellation."""
|
||||
|
||||
log.info("Registering PageStars...")
|
||||
for SelectedPageStar in page_stars:
|
||||
|
@ -82,17 +96,25 @@ class Constellation:
|
|||
if sentry_dsn:
|
||||
# noinspection PyUnreachableCode
|
||||
if __debug__:
|
||||
release = "DEV"
|
||||
release = f"Dev"
|
||||
else:
|
||||
release = royalnet.version.semantic
|
||||
log.info(f"Sentry: enabled (Royalnet {release})")
|
||||
release = f"{royalnet.version.semantic}"
|
||||
log.debug("Initializing Sentry...")
|
||||
sentry_sdk.init(sentry_dsn,
|
||||
integrations=[AioHttpIntegration(),
|
||||
SqlalchemyIntegration(),
|
||||
LoggingIntegration(event_level=None)],
|
||||
release=release)
|
||||
log.info(f"Sentry: enabled (Royalnet {release})")
|
||||
else:
|
||||
log.info("Sentry: disabled")
|
||||
# Run the server
|
||||
log.info(f"Running constellation server on {address}:{port}...")
|
||||
log.info(f"Running Constellation on {address}:{port}...")
|
||||
self.running = True
|
||||
try:
|
||||
uvicorn.run(self.starlette, host=address, port=port)
|
||||
finally:
|
||||
self.running = False
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__qualname__}: {'running' if self.running else 'inactive'}>"
|
||||
|
|
|
@ -36,6 +36,9 @@ class Star:
|
|||
"""A shortcut for the session :func:`asynccontextmanager` of the :class:`Constellation`."""
|
||||
return self.constellation.alchemy.session_acm
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__qualname__}>"
|
||||
|
||||
|
||||
class PageStar(Star):
|
||||
"""A PageStar is a class representing a single route of the website (for example, ``/api/user/get``).
|
||||
|
@ -64,6 +67,9 @@ class PageStar(Star):
|
|||
|
||||
"""
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__qualname__}: {self.path}>"
|
||||
|
||||
|
||||
class ExceptionStar(Star):
|
||||
"""An ExceptionStar is a class that handles an :class:`Exception` raised by another star by returning a different
|
||||
|
@ -79,3 +85,6 @@ class ExceptionStar(Star):
|
|||
error: Union[Type[Exception], int]
|
||||
"""The error that should be handled by this star. It should be either a subclass of :exc:`Exception`,
|
||||
or the :class:`int` of an HTTP error code."""
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__qualname__}: handles {self.error}>"
|
||||
|
|
|
@ -5,7 +5,7 @@ from .escaping import telegram_escape, discord_escape
|
|||
from .safeformat import safeformat
|
||||
from .classdictjanitor import cdj
|
||||
from .sleepuntil import sleep_until
|
||||
from .formatters import andformat, plusformat, fileformat, ytdldateformat, numberemojiformat, splitstring, ordinalformat
|
||||
from .formatters import andformat, plusformat, underscorize, ytdldateformat, numberemojiformat, splitstring, ordinalformat
|
||||
from .urluuid import to_urluuid, from_urluuid
|
||||
|
||||
__all__ = [
|
||||
|
@ -16,7 +16,7 @@ __all__ = [
|
|||
"plusformat",
|
||||
"andformat",
|
||||
"plusformat",
|
||||
"fileformat",
|
||||
"underscorize",
|
||||
"ytdldateformat",
|
||||
"numberemojiformat",
|
||||
"telegram_escape",
|
||||
|
|
|
@ -2,16 +2,29 @@ import typing
|
|||
import re
|
||||
|
||||
|
||||
def andformat(l: typing.List[str], middle=", ", final=" and ") -> str:
|
||||
"""Convert a :py:class:`list` to a :py:class:`str` by adding ``final`` between the last two elements and ``middle`` between the others.
|
||||
def andformat(l: typing.Collection[str], middle=", ", final=" and ") -> str:
|
||||
"""Convert a iterable (such as a :class:`list`) to a :class:`str` by adding ``final`` between the last two elements and ``middle`` between the others.
|
||||
|
||||
Parameters:
|
||||
l: the input :py:class:`list`.
|
||||
middle: the :py:class:`str` to be added between the middle elements.
|
||||
final: the :py:class:`str` to be added between the last two elements.
|
||||
Args:
|
||||
l: the input iterable.
|
||||
middle: the :class:`str` to be added between the middle elements.
|
||||
final: the :class:`str` to be added between the last two elements.
|
||||
|
||||
Returns:
|
||||
The resulting :py:class:`str`."""
|
||||
The resulting :py:class:`str`.
|
||||
|
||||
Examples:
|
||||
::
|
||||
|
||||
>>> andformat(["Steffo", "Kappa", "Proto"])
|
||||
"Steffo, Kappa and Proto"
|
||||
|
||||
>>> andformat(["Viktya", "Sensei", "Cate"], final=" e ")
|
||||
"Viktya, Sensei e Cate"
|
||||
|
||||
>>> andformat(["Paltri", "Spaggia", "Gesù", "Mallllco"], middle="+", final="+")
|
||||
"Paltri+Spaggia+Gesù+Mallllco"
|
||||
"""
|
||||
result = ""
|
||||
for index, item in enumerate(l):
|
||||
result += item
|
||||
|
@ -22,42 +35,45 @@ def andformat(l: typing.List[str], middle=", ", final=" and ") -> str:
|
|||
return result
|
||||
|
||||
|
||||
def plusformat(i: int, empty_if_zero: bool = False) -> str:
|
||||
"""Convert an :py:class:`int` to a :py:class:`str`, prepending a ``+`` if it's greater than 0.
|
||||
def underscorize(string: str) -> str:
|
||||
"""Replace all non-word characters in a :class:`str` with underscores.
|
||||
|
||||
Parameters:
|
||||
i: the :py:class:`int` to convert.
|
||||
empty_if_zero: Return an empty string if ``i`` is zero.
|
||||
|
||||
Returns:
|
||||
The resulting :py:class:`str`."""
|
||||
if i == 0 and empty_if_zero:
|
||||
return ""
|
||||
if i > 0:
|
||||
return f"+{i}"
|
||||
return str(i)
|
||||
|
||||
|
||||
def fileformat(string: str) -> str:
|
||||
"""Ensure a string can be used as a filename by replacing all non-word characters with underscores.
|
||||
It is particularly useful when you want to use random strings from the Internet as filenames.
|
||||
|
||||
Parameters:
|
||||
string: the input string.
|
||||
|
||||
Returns:
|
||||
A valid filename string."""
|
||||
The resulting string.
|
||||
|
||||
Example:
|
||||
::
|
||||
>>> underscorize("LE EPIC PRANK [GONE WRONG!?!?]")
|
||||
"LE EPIC PRANK _GONE WRONG_____"
|
||||
|
||||
"""
|
||||
return re.sub(r"\W", "_", string)
|
||||
|
||||
|
||||
def ytdldateformat(string: typing.Optional[str], separator: str = "-") -> str:
|
||||
"""Convert the weird date string returned by ``youtube-dl`` into the ``YYYY-MM-DD`` format.
|
||||
"""Convert the date :class:`str` returned by :mod:`youtube-dl` into the ``YYYY-MM-DD`` format.
|
||||
|
||||
Parameters:
|
||||
string: the input string, in the ``YYYYMMDD`` format.
|
||||
string: the input string, in the ``YYYYMMDD`` format used by :mod:`youtube_dl`.
|
||||
separator: the string to add between the years, the months and the days. Defaults to ``-``.
|
||||
|
||||
Returns:
|
||||
The resulting string, in the format ``YYYY-MM-DD`` format."""
|
||||
The resulting string in the new format.
|
||||
|
||||
Example:
|
||||
::
|
||||
>>> ytdldateformat("20111111")
|
||||
"2011-11-11"
|
||||
|
||||
>>> ytdldateformat("20200202", separator=".")
|
||||
"2020.02.02"
|
||||
|
||||
"""
|
||||
if string is None:
|
||||
return ""
|
||||
return f"{string[0:4]}{separator}{string[4:6]}{separator}{string[6:8]}"
|
||||
|
|
Loading…
Reference in a new issue