diff --git a/.gitignore b/.gitignore index 68d69529..353da69f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,13 @@ -config.ini -.idea/ -.vscode/ -__pycache__ -*.egg-info/ -.pytest_cache/ +# Royalnet ignores +config*.toml +downloads/ + + +# Python ignores +**/__pycache__/ dist/ -build/ -venv/ +*.egg-info/ +**/*.pyc + +# PyCharm ignores +.idea/ diff --git a/README.md b/README.md index aef4366f..a988ebbf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# `{packname}` [![PyPI](https://img.shields.io/pypi/v/{packname}.svg)](https://pypi.org/project/{packname}/) +# `examplepack` -{Replace everything surrounded by braces with your own data, including this description!} +This is an example Pack for [Royalnet](https://github.com/Steffo99/royalnet)! -{Files to be changed are the package folder, setup.py and this README!} +> To be updated with more info on how to create your own pack. \ No newline at end of file diff --git a/examplepack/commands/__init__.py b/examplepack/commands/__init__.py new file mode 100644 index 00000000..c9ffb60c --- /dev/null +++ b/examplepack/commands/__init__.py @@ -0,0 +1,12 @@ +# Imports go here! +# TODO: If you create a new command, remember to import it here... +# from .example import ExampleCommand + +# Enter the commands of your Pack here! +# TODO: and add it to the list here! +available_commands = [ + # ExampleCommand, +] + +# Don't change this, it should automatically generate __all__ +__all__ = [command.__name__ for command in available_commands] diff --git a/examplepack/commands/example.py b/examplepack/commands/example.py new file mode 100644 index 00000000..f98652ba --- /dev/null +++ b/examplepack/commands/example.py @@ -0,0 +1,12 @@ +from typing import * +from royalnet.commands import * +from royalnet.utils import * + + +class ExampleCommand(Command): + name: str = "example" + + description: str = "Say Hello to the world!" + + async def run(self, args: CommandArgs, data: CommandData) -> None: + await data.reply("Hello world!") diff --git a/examplepack/events/__init__.py b/examplepack/events/__init__.py new file mode 100644 index 00000000..8bafb696 --- /dev/null +++ b/examplepack/events/__init__.py @@ -0,0 +1,12 @@ +# Imports go here! +# TODO: If you create a new event, remember to import it here... +# from .example import ExampleEvent + +# Enter the commands of your Pack here! +# TODO: and add it to the list here! +available_events = [ + # ExampleEvent, +] + +# Don't change this, it should automatically generate __all__ +__all__ = [command.__name__ for command in available_events] diff --git a/examplepack/events/example.py b/examplepack/events/example.py new file mode 100644 index 00000000..866abc7a --- /dev/null +++ b/examplepack/events/example.py @@ -0,0 +1,10 @@ +from typing import * +from royalnet.commands import * +from royalnet.utils import * + + +class ExampleEvent(Event): + name = "example" + + async def run(self, **kwargs) -> dict: + return {"hello": "world"} diff --git a/examplepack/stars/__init__.py b/examplepack/stars/__init__.py new file mode 100644 index 00000000..8193b6d8 --- /dev/null +++ b/examplepack/stars/__init__.py @@ -0,0 +1,14 @@ +# Imports go here! +# TODO: If you create a new star, remember to import it here... +# from .example import ExampleStar +# from .api_example import ApiExampleStar + +# Enter the PageStars of your Pack here! +# TODO: and to add it either to the list here if it is a PageStar... +available_page_stars = [ + # ExampleStar, + # ApiExampleStar, +] + +# Don't change this, it should automatically generate __all__ +__all__ = [command.__name__ for command in available_page_stars] diff --git a/examplepack/stars/api_example.py b/examplepack/stars/api_example.py new file mode 100644 index 00000000..80b03165 --- /dev/null +++ b/examplepack/stars/api_example.py @@ -0,0 +1,70 @@ +import royalnet.utils as ru +import royalnet.constellation.api as rca +import royalnet.constellation.api.apierrors as rcae + + +# View autogenerated docs for all ApiStars at the HTTP path `/docs` + + +class EchoStar(rca.ApiStar): + # What does this ApiStar do? + summary = "Returns the same string entered as input." + + # Optional: A longer description of what the ApiStar should do. + description = """ + NOTE: This method can only be used by Royalnet Admins. + """ + + # The HTTP methods that can be used with this ApiStar. + methods = ["GET", "POST"] + # You can disambiguate between methods using the `data.method` variable. + + # The HTTP path this ApiStar should bind to. + path = "/api/example/echo/v1" + + # Does this method require any auth? + # Only for documentation purposes, it doesn't do any check on it's own. + requires_auth = True + # To authenticate an user through their token, use the `await data.user()` method. + # If the user isn't logged in, the method authomatically returns 403 Forbidden, unless `rcae.ForbiddenError` + # is caught. + + # A dict of paramenters accepted by this method, with a description of their purpose. + parameters = { + "echo": "What should the method return? " + "(Optional: if nothing is passed, the ApiStar will return the username of the caller.)", + "error": "Should the method return a sample error?" + } + # You can access parameters by using `data` as a dict with the parameter name as key. + # If a missing parameter is accessed, a `rcae.MissingParameterError` will be raised, which will lead to a + # 400 Bad Request error if not caught. + + # The autodoc categories this ApiStar should fall in. + tags = ["example"] + + # The actual method called when the ApiStar received a HTTP request. + # It must return a JSON-compatible object, such as a str, a int, a float, a list, a dict or None. + async def api(self, data: rca.ApiData) -> ru.JSON: + + # If "true" is passed as the "error" parameter in the query string... + if data["error"] == "true": + # ...return an example error + raise Exception("Example error! Everything works as intended.") + # If the "error" parameter is missing, the ApiStar will respond with 400 Bad Request + + # Ensure the user is logged in + user = await data.user() + # Check if the user has the role "admin" + if "admin" not in user.roles: + raise Exception("Only admins can call this method!") + + # Get the value of the "echo" parameter, without raising an exception if it doesn't exist + echo = data.get("echo") + + if echo is None: + # Find the username of the logged in user + # user is a SQLAlchemy ORM object generated from the Users table defined in `royalnet.backpack.tables.users` + echo = user.username + + # Return a 200 OK successful response containing the value of the echo variable and the HTTP method used + return {"echo": echo, "method_used": data.method} diff --git a/examplepack/stars/example.py b/examplepack/stars/example.py new file mode 100644 index 00000000..6b044cea --- /dev/null +++ b/examplepack/stars/example.py @@ -0,0 +1,11 @@ +from starlette.requests import Request +from starlette.responses import * +from royalnet.constellation import * +from royalnet.utils import * + + +class ExampleStar(PageStar): + path = "/example" + + async def page(self, request: Request) -> JSONResponse: + return HTMLResponse("""

henlo!

""") diff --git a/{packname}/tables/__init__.py b/examplepack/tables/__init__.py similarity index 58% rename from {packname}/tables/__init__.py rename to examplepack/tables/__init__.py index 23bc7c24..e417ff16 100644 --- a/{packname}/tables/__init__.py +++ b/examplepack/tables/__init__.py @@ -1,10 +1,10 @@ # Imports go here! - +# from .example import Example # Enter the tables of your Pack here! available_tables = [ - + # Example ] # Don't change this, it should automatically generate __all__ -__all__ = [table.__class__.__qualname__ for table in available_tables] +__all__ = [table.__name__ for table in available_tables] diff --git a/examplepack/tables/example.py b/examplepack/tables/example.py new file mode 100644 index 00000000..83078e7e --- /dev/null +++ b/examplepack/tables/example.py @@ -0,0 +1,19 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr + + +class Example: + __tablename__ = "examples" + + @declared_attr + def creator_id(self): + return Column(Integer, ForeignKey("users.uid"), primary_key=True) + + @declared_attr + def creator(self): + return relationship("User", backref=backref("examples_createdx")) + + @declared_attr + def example(self): + return Column(String, nullable=False, default="Hello world!") diff --git a/examplepack/version.py b/examplepack/version.py new file mode 100644 index 00000000..422feb95 --- /dev/null +++ b/examplepack/version.py @@ -0,0 +1,2 @@ +# TODO: Increment this every new version of your pack! +semantic = "0.1.0" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..cc9bf31d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,58 @@ +# Remember to run `poetry update` after you edit this file! + +[tool.poetry] + # TODO: Insert here your Pack name! + name = "examplepack" + # TODO: Insert here your Pack description! + description = "An example pack for Royalnet." + # TODO: Increment this every new version of your pack! + version = "0.1.0" + # TODO: Set this to your full name and email! + authors = ["Name Surname "] + # TODO: Set this to the license you want to use for your Pack! + license = "" + # TODO: Set this to the GitHub page of your pack (or another website) + homepage = "https://github.com/your-username/" + # TODO: Set this to a link to the Pack documentation (if there's any) + documentation = "https://gh.steffo.eu/royalpack/" + # TODO: Pick some classifiers to include your Pack in: https://pypi.org/classifiers/ + classifiers = [ + "Development Status :: 3 - Alpha", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.8", + "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)" + ] + readme = "README.md" + +# Library dependencies +[tool.poetry.dependencies] + python = "^3.8" + + [tool.poetry.dependencies.royalnet] + version = "^5.1.6" + # TODO: select the Royalnet modules required by your pack + extras = [ + "telegram", + "discord", + "alchemy_easy", + "bard", + "constellation", + "sentry", + "herald", + "coloredlogs" + ] + +# Development dependencies +[tool.poetry.dev-dependencies] + + + +# Optional dependencies +[tool.poetry.extras] + + +# Poetry stuff +# Leave it alone! +[build-system] + requires = ["poetry>=0.12"] + build-backend = "poetry.masonry.api" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/setup.py b/setup.py deleted file mode 100644 index e625dbff..00000000 --- a/setup.py +++ /dev/null @@ -1,24 +0,0 @@ -import setuptools - -with open("README.md", "r") as f: - long_description = f.read() - -with open("requirements.txt", "r") as f: - install_requires = f.readlines() - -setuptools.setup( - name="{packname}", - version="0.1", - author="{packauthorname}", - author_email="{packauthoremail}", - description="{packdescription}", - long_description=long_description, - long_description_content_type="text/markdown", - url="{packgithublink}", - packages=setuptools.find_packages(), - install_requires=install_requires, - python_requires=">=3.7", - classifiers=[ - "Programming Language :: Python :: 3.7", - ], -) diff --git a/to_pypi.bat b/to_pypi.bat deleted file mode 100644 index beb035bc..00000000 --- a/to_pypi.bat +++ /dev/null @@ -1,3 +0,0 @@ -del /f /q /s dist\*.* -python setup.py sdist bdist_wheel -twine upload dist/* diff --git a/{packname}/__init__.py b/{packname}/__init__.py deleted file mode 100644 index 4d839b28..00000000 --- a/{packname}/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# This is a template Pack __init__. You can use this without changing anything in other packages too! - -from .commands import available_commands -from .tables import available_tables - -__all__ = ["commands", "tables", "available_commands", "available_tables"] - diff --git a/{packname}/commands/__init__.py b/{packname}/commands/__init__.py deleted file mode 100644 index 3e6d10ca..00000000 --- a/{packname}/commands/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# Imports go here! - - -# Enter the commands of your Pack here! -available_commands = [ - -] - -# Don't change this, it should automatically generate __all__ -__all__ = [command.__class__.__qualname__ for command in available_commands]