diff --git a/.gitignore b/.gitignore index e2b3615..632e35f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ docs/_build boticordpy.egg-info test.py /.pytest_cache +/docs/build/ diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 0000000..75f6a6c --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,13 @@ +version: 2 + +sphinx: + configuration: docs/source/conf.py + +build: + image: latest + +python: + version: "3.8" + install: + - requirements: requirements.txt + - requirements: requirements-docs.txt \ No newline at end of file diff --git a/README.md b/README.md index 534bb58..699e3bf 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,84 @@ -

Boticordpy 2.0

+

+ +

-

Currently in development

\ No newline at end of file +

+ + The easiest way to use Boticord API in Python. + ยท + Docs + +

+ +

+ + + +

+ + +

Features

+* Object-oriented +* Full Boticord API Coverage +* Modern Pythonic API using `async`/`await` syntax +* Boticord Webhooks +* It is not necessary to use any particular library to interact with the Discord API. + +

Installation

+ +Python 3.6 or newer is required. + +Enter one of these commands to install the library: + +``` + pip install boticordpy +``` + +``` + python3 -m pip install boticordpy +``` + +Or just clone the repo: https://github.com/boticord/boticordpy + +

Examples

+ +You can find other examples in an examples folder. + +**Discord.py Autopost example** + +```py + from discord.ext import commands + + from boticordpy import BoticordClient + + bot = commands.Bot(command_prefix="!") + + + async def get_stats(): + return {"servers": len(bot.guilds), "shards": 0, "users": len(bot.users)} + + + async def on_success_posting(): + print("stats posting successfully") + + boticord_client = BoticordClient("your_api_token") + autopost = ( + boticord_client.autopost() + .init_stats(get_stats) + .on_success(on_success_posting) + ) + + bot.run("bot token") +``` + +

Links

+ +* [PyPi](https://pypi.org/project/boticordpy) +* [Documentation](https://py.boticord.top) +* [Github](https://github.com/boticord/boticordpy) +* [Boticord](https://boticord.top/) +* [Support](https://boticord.top/boticord) + +

Help

+ +If You need any help we recommend you to check the documentation. You can find us [here](https://boticord.top/boticord). Main developer `Marakarka#0575` diff --git a/boticordpy/__init__.py b/boticordpy/__init__.py index e9ecb32..64f0722 100644 --- a/boticordpy/__init__.py +++ b/boticordpy/__init__.py @@ -13,5 +13,6 @@ __copyright__ = 'Copyright 2022 Marakarka' __version__ = '2.0.1a' from .client import BoticordClient +from .webhook import Webhook from .types import * diff --git a/boticordpy/autopost.py b/boticordpy/autopost.py index 2c0a2a1..131e292 100644 --- a/boticordpy/autopost.py +++ b/boticordpy/autopost.py @@ -5,6 +5,14 @@ from . import exceptions as bexc class AutoPost: + """ + You can use this class to post stats automatically. + + Args: + client (:obj:`~.client.BoticordClient`) + An instance of BoticordClient. + """ + __slots__ = ( "client", "_interval", @@ -28,9 +36,24 @@ class AutoPost: @property def is_running(self) -> bool: + """ + Is autopost running? + """ return self._task is not None and not self._task.done() def on_success(self, callback: typing.Any = None): + """ + Registers success callback. + + .. warning:: + + Callback functions must be a **coroutine**. If they aren't, then you might get unexpected + errors. In order to turn a function into a coroutine they must be ``async def`` + functions. + + This method can be used as a decorator (if you want). + """ + if callback is not None: self._success = callback return self @@ -45,6 +68,18 @@ class AutoPost: return inner def on_error(self, callback: typing.Any = None): + """ + Registers error callback. + + .. warning:: + + Callback functions must be a **coroutine**. If they aren't, then you might get unexpected + errors. In order to turn a function into a coroutine they must be ``async def`` + functions. + + The callback function requires to take Exception argument. + This method can be used as a decorator (if you want). + """ if callback is not None: self._error = callback return self @@ -59,6 +94,17 @@ class AutoPost: return inner def init_stats(self, callback: typing.Any = None): + """ + Registers a function that will return stats. Registered Function Must return dictionary. + + .. warning:: + + Callback functions must be a **coroutine**. If they aren't, then you might get unexpected + errors. In order to turn a function into a coroutine they must be ``async def`` + functions. + + This method can be used as a decorator (if you want). + """ if callback is not None: self._stats = callback return self @@ -74,9 +120,19 @@ class AutoPost: @property def interval(self) -> float: + """The interval between posting stats.""" return self._interval def set_interval(self, seconds: int) -> "AutoPost": + """ + Sets the interval between posting stats. + Args: + seconds (:obj:`int`) + The interval. + Raises: + :obj:`ValueError` + Boticord recommends not to set interval lower than 900 seconds! + """ if seconds < 900: raise ValueError("no. Boticord recommends not to set interval lower than 900 seconds!") @@ -103,6 +159,13 @@ class AutoPost: await asyncio.sleep(self._interval) def start(self): + """ + Starts the loop. + + Raises: + :obj:`~.exceptions.InternalException` + If there's no callback (for getting stats) provided or the autopost is already running. + """ if not hasattr(self, "_stats"): raise bexc.InternalException("You must provide stats") @@ -114,6 +177,9 @@ class AutoPost: return task def stop(self) -> None: + """ + Stops the autopost. + """ if not self.is_running: return None diff --git a/boticordpy/client.py b/boticordpy/client.py index 28b90ef..7226524 100644 --- a/boticordpy/client.py +++ b/boticordpy/client.py @@ -6,6 +6,15 @@ from .autopost import AutoPost class BoticordClient: + """Represents a client that can be used to interact with the Boticord API. + + Note: + Remember that every http method can return http exception. + + Args: + token (:obj:`str`) + Your bot's Boticord API Token. + """ __slots__ = ( "http", "_autopost", @@ -14,20 +23,53 @@ class BoticordClient: http: HttpClient - def __init__(self, token=None, **kwargs): + def __init__(self, token=None): self._token = token self._autopost: typing.Optional[AutoPost] = None self.http = HttpClient(token) async def get_bot_info(self, bot_id: int) -> boticord_types.Bot: + """Gets information about specified bot. + + Args: + bot_id (:obj:`int`) + Id of the bot + + Returns: + :obj:`~.types.Bot`: + Bot object. + """ response = await self.http.get_bot_info(bot_id) return boticord_types.Bot(**response) async def get_bot_comments(self, bot_id: int) -> list: + """Gets list of comments of specified bot. + + Args: + bot_id (:obj:`int`) + Id of the bot + + Returns: + :obj:`list` [ :obj:`~.types.SingleComment` ]: + List of comments. + """ response = await self.http.get_bot_comments(bot_id) return [boticord_types.SingleComment(**comment) for comment in response] async def post_bot_stats(self, servers: int = 0, shards: int = 0, users: int = 0) -> dict: + """Post Bot's stats. + + Args: + servers ( :obj:`int` ) + Bot's servers count + shards ( :obj:`int` ) + Bot's shards count + users ( :obj:`int` ) + Bot's users count + Returns: + :obj:`dict`: + Boticord API Response status + """ response = await self.http.post_bot_stats({ "servers": servers, "shards": shards, @@ -36,30 +78,94 @@ class BoticordClient: return response async def get_server_info(self, server_id: int) -> boticord_types.Server: + """Gets information about specified server. + + Args: + server_id (:obj:`int`) + Id of the server + + Returns: + :obj:`~.types.Server`: + Server object. + """ response = await self.http.get_server_info(server_id) return boticord_types.Server(**response) async def get_server_comments(self, server_id: int) -> list: + """Gets list of comments of specified server. + + Args: + server_id (:obj:`int`) + Id of the server + + Returns: + :obj:`list` [ :obj:`~.types.SingleComment` ]: + List of comments. + """ response = await self.http.get_server_comments(server_id) return [boticord_types.SingleComment(**comment) for comment in response] async def post_server_stats(self, payload: dict) -> dict: + """Post Server's stats. You must be Boticord-Service bot. + + Args: + payload (:obj:`dict`) + Custom data (Use Boticord API docs.) + Returns: + :obj:`dict`: + Boticord API Response. + """ response = await self.post_server_stats(payload) return response async def get_user_info(self, user_id: int) -> boticord_types.UserProfile: + """Gets information about specified user. + + Args: + user_id (:obj:`int`) + Id of the user + + Returns: + :obj:`~.types.UserProfile`: + User Profile object. + """ response = await self.get_user_info(user_id) return boticord_types.UserProfile(**response) async def get_user_comments(self, user_id: int) -> boticord_types.UserComments: + """Gets comments of specified user. + + Args: + user_id (:obj:`int`) + Id of the user + + Returns: + :obj:`~.types.UserComments`: + User comments on Bots and Servers pages. + """ response = await self.get_user_comments(user_id) return boticord_types.UserComments(**response) async def get_user_bots(self, user_id: int) -> list: + """Gets list of bots of specified user. + + Args: + user_id (:obj:`int`) + Id of the user + + Returns: + :obj:`list` [ :obj:`~.types.SimpleBot` ]: + List of simple information about users bots. + """ response = await self.get_user_bots(user_id) return [boticord_types.SimpleBot(**bot) for bot in response] def autopost(self) -> AutoPost: + """Returns a helper instance for auto-posting. + + Returns: + :obj:`~.autopost.AutoPost`: An instance of AutoPost. + """ if self._autopost is not None: return self._autopost diff --git a/boticordpy/http.py b/boticordpy/http.py index 202552d..b871a94 100644 --- a/boticordpy/http.py +++ b/boticordpy/http.py @@ -6,6 +6,19 @@ from . import exceptions class HttpClient: + """ + Represents an HTTP client sending HTTP requests to the Top.gg API. + + Args: + token (:obj:`str`) + Your bot's Boticord API Token. + + Keyword Arguments: + session: `aiohttp session`_ + The `aiohttp session`_ used for requests to the API. + loop: `asyncio loop` + """ + def __init__(self, auth_token, **kwargs): self.token = auth_token self.API_URL = "https://api.boticord.top/v1/" @@ -18,6 +31,8 @@ class HttpClient: method: str, endpoint: str, **kwargs): + """Send requests to the API""" + kwargs["headers"] = { "Content-Type": "application/json", "Authorization": self.token @@ -48,28 +63,37 @@ class HttpClient: raise exceptions.HTTPException(response) def get_bot_info(self, bot_id: int): + """Get information about the specified bot""" return self.make_request("GET", f"bot/{bot_id}") def get_bot_comments(self, bot_id: int): + """Get list of specified bot comments""" return self.make_request("GET", f"bot/{bot_id}/comments") def post_bot_stats(self, stats: dict): + """Post bot's stats""" return self.make_request("POST", "stats", json=stats) def get_server_info(self, server_id: int): + """Get information about specified server""" return self.make_request("GET", f"server/{server_id}") def get_server_comments(self, server_id: int): + """Get list of specified server comments""" return self.make_request("GET", f"server/{server_id}/comments") def post_server_stats(self, payload: dict): + """Post server's stats""" return self.make_request("POST", "server", json=payload) def get_user_info(self, user_id: int): + """Get information about the user""" return self.make_request("GET", f"profile/{user_id}") def get_user_comments(self, user_id: int): + """Get specified user's comments""" return self.make_request("GET", f"user/{user_id}/comments") def get_user_bots(self, user_id: int): + """Get bots of specified user""" return self.make_request("GET", f"bots/{user_id}") diff --git a/boticordpy/types.py b/boticordpy/types.py index a3c3303..1a1f549 100644 --- a/boticordpy/types.py +++ b/boticordpy/types.py @@ -109,9 +109,12 @@ class Bot(ApiData): bumps: int """Bumps count""" - prefix: str + added: str """How many times users have added the bot?""" + prefix: str + """Bot's commands prefix""" + permissions: int """Bot's permissions""" @@ -256,6 +259,7 @@ class SimpleBot(ApiData): """Bot's Id""" short_code: typing.Optional[str] + """Bot's page short code""" def __init__(self, **kwargs): super().__init__(**parse_response_dict(kwargs)) @@ -265,8 +269,13 @@ class CommentData(ApiData): """This model represents comment data (from webhook response)""" vote: dict + """Comment vote data""" + old: typing.Optional[str] + """Old content of the comment""" + new: typing.Optional[str] + """New content of the comment""" def __init__(self, **kwargs): super().__init__(**parse_response_dict(kwargs)) @@ -298,8 +307,13 @@ class BumpResponse(ApiData): """This model represents a webhook response (`bot bump`).""" type: str + """Type of response (`bump`)""" + user: str + """Id of user who did the action""" + at: int + """Timestamp of the action""" def __init__(self, **kwargs): super().__init__(**parse_webhook_response_dict(kwargs)) @@ -309,10 +323,19 @@ class CommentResponse(ApiData): """This model represents a webhook response (`comment`).""" type: str + """Type of response (`comment`)""" + user: str + """Id of user who did the action""" + comment: CommentData + """Information about the comment""" + reason: typing.Optional[str] + """Is comment deleted? so, why?""" + at: int + """Timestamp of the action""" def __init__(self, **kwargs): super().__init__(**parse_webhook_response_dict(kwargs)) diff --git a/boticordpy/webhook.py b/boticordpy/webhook.py index 9dfd727..75d3531 100644 --- a/boticordpy/webhook.py +++ b/boticordpy/webhook.py @@ -8,6 +8,18 @@ import aiohttp class Webhook: + """Represents a client that can be used to work with Boticord Webhooks. + IP of the server - your machine IP. (`0.0.0.0`) + + Args: + x_hook_key (:obj:`str`) + X-hook-key to check the auth of incoming request. + endpoint_name (:obj:`str`) + Name of endpoint (for example: `/bot`) + + Keyword Arguments: + loop: `asyncio loop` + """ __slots__ = ( "_webserver", "_listeners", @@ -30,6 +42,11 @@ class Webhook: self._loop = kwargs.get('loop') or asyncio.get_event_loop() def listener(self, response_type: str): + """Decorator to set the listener. + Args: + response_type (:obj:`str`) + Type of response (Check reference page) + """ def inner(func): if not asyncio.iscoroutinefunction(func): raise TypeError(f"<{func.__qualname__}> must be a coroutine function") @@ -39,6 +56,13 @@ class Webhook: return inner def register_listener(self, response_type: str, callback: typing.Any): + """Method to set the listener. + Args: + response_type (:obj:`str`) + Type of response (Check reference page) + callback (:obj:`function`) + Coroutine Callback Function + """ if not asyncio.iscoroutinefunction(callback): raise TypeError(f"<{func.__qualname__}> must be a coroutine function") @@ -46,6 +70,7 @@ class Webhook: return self async def _interaction_handler(self, request: aiohttp.web.Request) -> web.Response: + """Interaction handler""" auth = request.headers.get("X-Hook-Key") if auth == self._x_hook_key: @@ -74,21 +99,31 @@ class Webhook: self._is_running = True def start(self, port: int) -> None: + """Method to start the webhook server + + Args: + port (:obj:`int`) + Port to start the webserver + """ self._loop.create_task(self._run(port)) @property def is_running(self) -> bool: + """If the server running?""" return self._is_running @property def listeners(self) -> dict: + """Dictionary of listeners (`type`: `callback function`)""" return self._listeners @property def app(self) -> web.Application: + """Web application that handles incoming requests""" return self.__app async def close(self) -> None: + """Stop the webhooks server""" await self._webserver.stop() self._is_running = False diff --git a/docs-requirements.txt b/docs-requirements.txt new file mode 100644 index 0000000..e1aaddb --- /dev/null +++ b/docs-requirements.txt @@ -0,0 +1,2 @@ +sphinx_rtd_theme +sphinx \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile index d4bb2cb..d0c3cbf 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,8 +5,8 @@ # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build -SOURCEDIR = . -BUILDDIR = _build +SOURCEDIR = source +BUILDDIR = build # Put it first so that "make" without argument is like "make help". help: diff --git a/docs/exceptions.rst b/docs/exceptions.rst deleted file mode 100644 index 4fe3279..0000000 --- a/docs/exceptions.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. currentmodule:: boticordpy - -.. exceptions: - -Exceptions -============== - -This page describes all the exceptions of boticordpy module. - -.. automodule:: boticordpy.exceptions - :members: - diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index db5435c..0000000 --- a/docs/index.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. BoticordPy documentation master file, created by - sphinx-quickstart on Sat Aug 7 21:14:56 2021. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to BoticordPy's documentation! -====================================== - -This is a documentation for simple python module to work with the boticord api. - -====================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - quickstart - main - modules - webhook - reference - exceptions - -Links -===== - -* :ref:`search` -* `PyPi `_ -* `GitHub `_ -* `Boticord `_ - diff --git a/docs/main.rst b/docs/main.rst deleted file mode 100644 index eed81c8..0000000 --- a/docs/main.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. currentmodule:: boticordpy - -.. main: - -Main -=================== - -This class is used to make it much easier to use the Boticord API. - -BoticordClient ---------------- -.. autoclass:: boticordpy.BoticordClient - :members: \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..061f32f --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/modules.rst b/docs/modules.rst deleted file mode 100644 index 6fc064e..0000000 --- a/docs/modules.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. currentmodule:: boticordpy - -.. modules: - -Modules -============== - -This page describes all the modules of boticordpy. - -Bots ------------- -.. autoclass:: boticordpy.modules.Bots - :members: - -Servers ------------- -.. autoclass:: boticordpy.modules.Servers - :members: - -Users ------------- -.. autoclass:: boticordpy.modules.Users - :members: diff --git a/docs/quickstart.rst b/docs/quickstart.rst deleted file mode 100644 index e0725ef..0000000 --- a/docs/quickstart.rst +++ /dev/null @@ -1,84 +0,0 @@ -.. currentmodule:: boticordpy - -.. quickstart: - -Quickstart -========== - -Installation ------------- - -Enter one of these commands to install the library: - -:: - - pip install boticordpy - - -:: - - python3 -m pip install boticordpy - - -Or just clone the repo: https://github.com/grey-cat-1908/boticordpy - - - -Examples -------------------------- - -**Without Using Cogs System** - -Post bot stats when bot is ready. - -:: - - from discord.ext import commands - - from boticordpy import BoticordClient - - bot = commands.Bot(command_prefix="!") - boticord = BoticordClient(bot, "your-boticord-token") - - - @bot.event - async def on_ready(): - stats = {"servers": len(bot.guilds), "shards": bot.shard_count, "users": len(bot.users)} - await boticord.Bots.post_stats(stats) - - - bot.run("your-bot-token") - -.. - -**Using Cogs System** - -Cog with automatically stats post (every 15 minutes) + bot's owner command that can be used to post stats. - -:: - - from discord.ext import commands - - from boticordpy import BoticordClient - - - class BoticordCog(commands.Cog): - def __init__(self, bot): - self.bot = bot - self.boticord = BoticordClient(self.bot, "your-boticord-token") - self.boticord.start_loop() - - @commands.command(name="boticord-update") - @commands.is_owner() - async def boticord_update(self, ctx): - """ - This commands can be used by owner to post stats to boticord - """ - stats = {"servers": len(self.bot.guilds), "shards": 0, "users": len(self.bot.users)} - await self.boticord.Bots.post_stats(stats) - - - def setup(bot): - bot.add_cog(BoticordCog(bot)) - -.. diff --git a/docs/reference.rst b/docs/reference.rst deleted file mode 100644 index 98a1ca9..0000000 --- a/docs/reference.rst +++ /dev/null @@ -1,64 +0,0 @@ -.. currentmodule:: boticordpy - -.. reference: - -Reference -============== - -Event Reference ---------------- -Example of event creation: - -:: - - from discord.ext import commands - - from boticordpy import BoticordWebhook, BoticordClient - - bot = commands.Bot(command_prefix="!") - boticord = BoticordClient(bot, "boticord-api-token") - - boticord_webhook = BoticordWebhook(bot, boticord).bot_webhook("/bot", "X-Hook-Key") - boticord_webhook.run(5000) - - - @boticord.event("edit_bot_comment") - async def on_boticord_comment_edit(data): - print(data) - - -You can name the function whatever you want, but the decorator must always specify an existing event as an argument. - -.. warning:: - - All the events must be a **coroutine**. If they aren't, then you might get unexpected - errors. In order to turn a function into a coroutine they must be ``async def`` - functions. - -Here you can find some information about events: - -+------------------------+----------------------------------+ -| Boticord Events | Returns Type | -+========================+==================================+ -| new_bot_comment | types.Comment | -+------------------------+----------------------------------+ -| edit_bot_comment | types.EditedComment | -+------------------------+----------------------------------+ -| delete_bot_comment | types.Comment | -+------------------------+----------------------------------+ -| new_bot_bump | types.BotVote | -+------------------------+----------------------------------+ -| new_server_comment | Raw Data | -+------------------------+----------------------------------+ -| edit_server_comment | Raw Data | -+------------------------+----------------------------------+ -| delete_server_comment | Raw Data | -+------------------------+----------------------------------+ - -You can find more events in Boticord Documentation. - - -Types ------------- -.. automodule:: boticordpy.types - :members: diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index a8a7a9f..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -boticordpy \ No newline at end of file diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css new file mode 100644 index 0000000..199e56e --- /dev/null +++ b/docs/source/_static/custom.css @@ -0,0 +1,5 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400&display=swap'); + +* { + font-family: 'Roboto', sans-serif!important; +} \ No newline at end of file diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000..3ccb5b2 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,20 @@ +.. currentmodule:: boticordpy + +.. api: + +############# +API Reference +############# + +API Reference for the BoticordPY Module + +Index: + + .. toctree:: + :maxdepth: 2 + + api/client + api/autopost + api/exceptions + api/types + api/webhook \ No newline at end of file diff --git a/docs/source/api/autopost.rst b/docs/source/api/autopost.rst new file mode 100644 index 0000000..82e9f81 --- /dev/null +++ b/docs/source/api/autopost.rst @@ -0,0 +1,7 @@ +#################### +AutoPost API Reference +#################### + +.. automodule:: boticordpy.autopost + :members: + :inherited-members: diff --git a/docs/source/api/client.rst b/docs/source/api/client.rst new file mode 100644 index 0000000..cb589f2 --- /dev/null +++ b/docs/source/api/client.rst @@ -0,0 +1,7 @@ +#################### +Client API Reference +#################### + +.. automodule:: boticordpy.client + :members: + :inherited-members: diff --git a/docs/source/api/exceptions.rst b/docs/source/api/exceptions.rst new file mode 100644 index 0000000..5fbedef --- /dev/null +++ b/docs/source/api/exceptions.rst @@ -0,0 +1,7 @@ +#################### +Exceptions API Reference +#################### + +.. automodule:: boticordpy.exceptions + :members: + :inherited-members: diff --git a/docs/source/api/types.rst b/docs/source/api/types.rst new file mode 100644 index 0000000..3fc4460 --- /dev/null +++ b/docs/source/api/types.rst @@ -0,0 +1,6 @@ +#################### +Models API Reference +#################### + +.. automodule:: boticordpy.types + :members: diff --git a/docs/source/api/webhook.rst b/docs/source/api/webhook.rst new file mode 100644 index 0000000..59198b0 --- /dev/null +++ b/docs/source/api/webhook.rst @@ -0,0 +1,7 @@ +#################### +Webhook API Reference +#################### + +.. automodule:: boticordpy.webhook + :members: + :inherited-members: diff --git a/docs/conf.py b/docs/source/conf.py similarity index 67% rename from docs/conf.py rename to docs/source/conf.py index ac04efe..01bed7b 100644 --- a/docs/conf.py +++ b/docs/source/conf.py @@ -10,27 +10,24 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -import os -import sys -import re - -sys.path.insert(0, os.path.abspath('..')) +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) # -- Project information ----------------------------------------------------- +import sys +import os + +sys.path.insert(0, os.path.abspath("../..")) + project = 'BoticordPY' -copyright = '2021, Grey Cat' -author = 'Grey Cat' +copyright = '2022, Victor Kotlin (Marakarka)' +author = 'Victor Kotlin (Marakarka)' -with open('../discord/__init__.py') as f: - version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read(), re.MULTILINE).group(1) - -# The full version, including alpha/beta/rc tags. -release = version - -# This assumes a tag is available for final releases -branch = 'master' if version.endswith('a') else 'v' + version +# The full version, including alpha/beta/rc tags +release = '2.0.0' # -- General configuration --------------------------------------------------- @@ -39,9 +36,11 @@ branch = 'master' if version.endswith('a') else 'v' + version # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.napoleon', - 'sphinx.ext.ifconfig', - 'sphinx_rtd_theme' + "sphinx.ext.napoleon", + "sphinx.ext.autodoc", + "sphinx.ext.viewcode", + "sphinx.ext.autosectionlabel", + "sphinx.ext.extlinks", ] # Add any paths that contain templates here, relative to this directory. @@ -50,8 +49,13 @@ templates_path = ['_templates'] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = [] +intersphinx_mapping = { + "py": ("https://docs.python.org/3", None), + "discord": ("https://discordpy.readthedocs.io/en/latest/", None), + "aiohttp": ("https://docs.aiohttp.org/en/stable/", None), +} # -- Options for HTML output ------------------------------------------------- @@ -59,9 +63,16 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # a list of builtin themes. # html_theme = "sphinx_rtd_theme" -html_show_sourcelink = False + +html_theme_options = { + +} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". +# so a file named "custom.css" will overwrite the builtin "custom.css". html_static_path = ['_static'] + + +def setup(app): + app.add_css_file('custom.css') diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..cd343cf --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,23 @@ +Welcome to BoticordPy's documentation! +====================================== + +This is a documentation for wrapper for Boticord API. + +====================================== + +.. toctree:: + :maxdepth: 2 + :caption: Documentation: + + quickstart + api + other + +Links +===== + +* :ref:`search` +* `PyPi `_ +* `GitHub `_ +* `Boticord `_ +* `Boticord Support `_ diff --git a/docs/source/other.rst b/docs/source/other.rst new file mode 100644 index 0000000..0e9eede --- /dev/null +++ b/docs/source/other.rst @@ -0,0 +1,41 @@ +.. currentmodule:: boticordpy + +.. other: + +Other Information +================= + +########## +Listeners +########## + +List of listeners for webhooks + ++------------------------+----------------------------------+ +| Boticord Events | Meaning | ++========================+==================================+ +| new_bot_comment | On new bot comment | ++------------------------+----------------------------------+ +| edit_bot_comment | On bot comment edit | ++------------------------+----------------------------------+ +| delete_bot_comment | On bot comment delete | ++------------------------+----------------------------------+ +| new_bot_bump | On new bot bump | ++------------------------+----------------------------------+ +| new_server_comment | On new server comment | ++------------------------+----------------------------------+ +| edit_server_comment | On server comment edit | ++------------------------+----------------------------------+ +| delete_server_comment | On server comment delete | ++------------------------+----------------------------------+ + + +################## +Callback functions +################## + +.. warning:: + + Callback functions must be a **coroutine**. If they aren't, then you might get unexpected + errors. In order to turn a function into a coroutine they must be ``async def`` + functions. diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst new file mode 100644 index 0000000..6bf7675 --- /dev/null +++ b/docs/source/quickstart.rst @@ -0,0 +1,85 @@ +.. currentmodule:: boticordpy + +.. quickstart: + +Quickstart +========== + +**For more examples or information about other features check Github-Repo.** + +Installation +------------ + +Enter one of these commands to install the library: + +:: + + pip install boticordpy + + +:: + + python3 -m pip install boticordpy + + +Or just clone the repo: https://github.com/boticord/boticordpy + + + +Examples +------------------------- + +**Discord.py Autopost example** + +:: + + from discord.ext import commands + + from boticordpy import BoticordClient + + bot = commands.Bot(command_prefix="!") + + + async def get_stats(): + return {"servers": len(bot.guilds), "shards": 0, "users": len(bot.users)} + + + async def on_success_posting(): + print("stats posting successfully") + + boticord_client = BoticordClient("your_api_token") + autopost = ( + boticord_client.autopost() + .init_stats(get_stats) + .on_success(on_success_posting) + ) + + bot.run("bot token") + + +.. + + +**Discord.py Webhooks example** + +:: + + from discord.ext import commands + + from boticordpy import webhook + + bot = commands.Bot(command_prefix="!") + + + async def edit_bot_comment(data): + print(data.comment.new) + + boticord_webhook = webhook.Webhook("x-hook-key", "bot").register_listener("edit_bot_comment", edit_bot_comment) + boticord_webhook.start(5000) + + bot.run("bot token") + + +.. + + diff --git a/docs/webhook.rst b/docs/webhook.rst deleted file mode 100644 index 0497c15..0000000 --- a/docs/webhook.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. currentmodule:: boticordpy - -.. webhook: - -Webhooks ---------------- -.. autoclass:: boticordpy.BoticordWebhook - :members: \ No newline at end of file diff --git a/examples/autopost.py b/examples/autopost.py new file mode 100644 index 0000000..849d1ae --- /dev/null +++ b/examples/autopost.py @@ -0,0 +1,25 @@ +# You can use disnake or nextcord or something like this. +# (THIS EXAMPLE IS NOT TESTED. IF YOU HAVE ANY PROBLEMS - ASK DEVELOPER PLEASE) + +from discord.ext import commands + +from boticordpy import BoticordClient + +bot = commands.Bot(command_prefix="!") + + +async def get_stats(): + return {"servers": len(bot.guilds), "shards": 0, "users": len(bot.users)} + + +async def on_success_posting(): + print("stats posting successfully") + +boticord_client = BoticordClient("your_api_token") +autopost = ( + boticord_client.autopost() + .init_stats(get_stats) + .on_success(on_success_posting) +) + +bot.run("bot token") diff --git a/setup.py b/setup.py index 023904c..bf5bb4a 100644 --- a/setup.py +++ b/setup.py @@ -1,15 +1,13 @@ import pathlib -from setuptools import setup +from setuptools import setup, find_packages import re HERE = pathlib.Path(__file__).parent -requirements = [] with open('requirements.txt') as f: requirements = f.read().splitlines() -version = '' with open('boticordpy/__init__.py') as f: version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read(), re.MULTILINE).group(1) @@ -33,23 +31,19 @@ if version.endswith(('a', 'b', 'rc')): README = (HERE / "README.md").read_text(encoding="utf8") -packages = [ - 'boticordpy', - 'boticordpy.modules' -] - setup( name="boticordpy", project_urls={ "Documentation": "https://py.boticord.top/en/stable", "Issue tracker": "https://github.com/boticord/boticordpy/issues", }, - packages=packages, + packages=find_packages(), version=version, - description="A Python wrapper for Boticord api", + python_requires=">= 3.6", + description="A Python wrapper for Boticord API", long_description=README, long_description_content_type="text/markdown", - url="https://github.com/grey-cat-1908/boticordpy", + url="https://github.com/boticord/boticordpy", author="KerdokuCat", author_email="support@kerdoku.top", license="MIT",