From 6024b2a7b61e5ff856afa6eea8588073b102be8b Mon Sep 17 00:00:00 2001 From: Zeroji Date: Sun, 17 Jun 2018 03:32:31 +0200 Subject: [PATCH] Cleaned up documentation --- .gitignore | 1 + CHANGELOG.md | 17 ++- INSTALL.md | 21 ++-- README.md | 29 +++--- TODO.md | 21 ++-- doc/cogs.md | 246 ++++++++++++++++++++++++++------------------ doc/translations.md | 8 +- requirements | 2 +- 8 files changed, 205 insertions(+), 140 deletions(-) diff --git a/.gitignore b/.gitignore index edfbe6c..4e6b908 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ __pycache__/ # Environment .idea .python-version +.vscode todo.md notes diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ac87c0..dd09d5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ## Change Log + All notable changes to this project will be documented in this file. ### [[Unreleased](https://github.com/Zeroji/semicolon/releases/latest)] @@ -21,6 +22,7 @@ All notable changes to this project will be documented in this file. you will need to modify manually if you had changed it * Configuration files containing string IDs will have to be changed to numeric (integer) IDs +* Cleaner Markdown doc files #### Removed @@ -110,17 +112,20 @@ All notable changes to this project will be documented in this file. + Changelog file ;) + Added type checking on command arguments, done with type hints + Possibility to to regex checks on arguments -+ Added basic support for argument documentation (you can add it without errors, but it's not used yet) ++ Added basic support for argument documentation (you can add it without errors, + but it's not used yet) + Added reaction support via `@cog.on_reaction` (more in doc) + `help` command, finally! #### Changed -* Flags in `@cog.command` can now be either a string or a dictionary `{flag: description}` (for future documentation) +* Flags in `@cog.command` can now be either a string or a dictionary + `{flag: description}` (for future documentation) #### Fixed -* `Invalid argument count` when passing no arguments to a command using positional arguments +* `Invalid argument count` when passing no arguments to a command using + positional arguments * Private message channels are now considered as servers (regarding settings) ### [[v0.1.1](https://github.com/Zeroji/semicolon/releases/tag/v0.1.1)] @@ -144,8 +149,10 @@ All notable changes to this project will be documented in this file. * Switched from Python 3.5 to 3.6 * Improved logging * Argument parsing system - * Commands needing all the message as one argument (like `;say`) must be declared with `@cog.command(fulltext=True)` - * Commands can be passed positional arguments if they are declared like `def function(*pos_args)` + * Commands needing all the message as one argument (like `;say`) must be + declared with `@cog.command(fulltext=True)` + * Commands can be passed positional arguments if they are declared like + `def function(*pos_args)` * Command arguments can have default values * Commands can be passed bash-like flags diff --git a/INSTALL.md b/INSTALL.md index 5695de0..0cabc4f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,6 +1,6 @@ ## Installation -#### Which version to choose +### Which version to choose If you want to have a copy of `;;` for yourself to run on your own server, it's recommended you download a *stable release*, see for example the @@ -10,7 +10,7 @@ If you'd rather have the latest update, no matter the possible bugs, and you like to tinker around and play with the new stuff, you'll prefer the [direct Github link](https://github.com/Zeroji/semicolon), aka dev version. -#### Requirements +### Requirements - Python 3.6 (a virtual environment is recommended) - PIP for Python @@ -20,24 +20,25 @@ like to tinker around and play with the new stuff, you'll prefer the > active effort towards the support of it. Reported issues will be taken > care of, but with a low priority level. -#### Downloading the code +### Downloading the code To get the source code, you can either download it from Github or use -`git` to clone it locally (this is the recommended way). +`git` to clone it locally (this is the recommended way). + - Download the [latest stable build](https://github.com/Zeroji/semicolon/releases/latest) - (just click the "Download ZIP" button) -- Download the [latest source code](https://github.com/Zeroji/semicolon/archive/master.zip) -- Clone a specific version: `git clone --branch v0.1.0 https://github.com/Zeroji/semicolon.git` + (just click the "Download ZIP" button) +- Download the [latest source code](https://github.com/Zeroji/semicolon/archive/master.zip) +- Clone a specific version: `git clone --branch v0.1.0 https://github.com/Zeroji/semicolon.git` - Clone the latest version: `git clone https://github.com/Zeroji/semicolon.git` -#### Installation +### Installation Start by navigating to the directory where you downloaded the source code. Install the required Python packages: `pip install -r requirements` -#### Required files +### Required files You'll need to create a `data` folder to store some required information. @@ -60,7 +61,7 @@ Inside the `data` folder, create the following folder and files: - If you want `;;` to completely ignore some users, put their IDs in the `banned` file, separated by newlines. -#### Running `;;` +### Running `;;` Assuming you have done everything correctly, you should be able to run the bot by simply typing `python core.py` from the `semicolon` folder. diff --git a/README.md b/README.md index 2fe7d26..a7e9501 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ This is the repository for the *new* version of `;;`, a nice Discord bot with currently very few features. [Old version here.](http://github.com/Zeroji/semicold) -If you want to add features, feel free to [write a cog](https://github.com/Zeroji/semicolon/blob/master/doc/cogs.md)! +If you want to add features, feel free to +[write a cog](https://github.com/Zeroji/semicolon/blob/master/doc/cogs.md)! -#### How to use +### How to use Clone this repo, then run `pip install -r requirements` Edit `config.yaml` if you need to, or create another config file @@ -17,24 +18,26 @@ Edit `config.yaml` if you need to, or create another config file > Alternatively, you can run `./install.py` for a minimalistic setup To run the bot, type `./core.py` or `./core.py -c your_config.yaml` -Since [v0.1.1](https://github.com/Zeroji/semicolon/releases/tag/v0.1.1) you'll need Python 3.6. +Since [v0.1.1](https://github.com/Zeroji/semicolon/releases/tag/v0.1.1) you'll +need Python 3.6. -#### How to use (Discord side) +### How to use (Discord side) When the bot status gets yellow (idle), it means everything is properly loaded. You can then call commands by typing `;command whatever arguments it takes`. If two cogs have the same command, type `;cog.command` to differentiate them. -Since multiple bots may use the `;` prefix, you can also mention `;;` instead of using the prefix: -`@;; cog.command arguments`. You can also change the prefix to your liking if you have -the `Manage Server` permission, check `@;; help prefix`. +Since multiple bots may use the `;` prefix, you can also mention `;;` instead of +using the prefix: `@;; cog.command arguments`. You can also change the prefix to +your liking if you have the `Manage Server` permission, check `@;; help prefix`. -#### Fancy ways to use commands +### Fancy ways to use commands -`;;` can now interpret commands inside other messages, if you use a "breaker" character. -This character defaults to `|` and can be changed with the `breaker` command. +`;;` can now interpret commands inside other messages, if you use a "breaker" +character. This character defaults to `|` and can be changed with the `breaker` +command. A quick how-to: `Hello, can you say |;hi| ?` is equivalent to `;hi` `Hello, can you ||;say hi | test` is equivalent to `;say hi | test` -Basically, this splits your messages in chunks delimited by `|` and evaluates them separately. -If `;;` encounters `||`, it stops splitting and sends all the remaining text as one chunk: useful -when said text contains a `|` \ No newline at end of file +Basically, this splits your messages in chunks delimited by `|` and evaluates +them separately. If `;;` encounters `||`, it stops splitting and sends all the +remaining text as one chunk: useful when said text contains `|`. diff --git a/TODO.md b/TODO.md index bafe313..cf8369e 100644 --- a/TODO.md +++ b/TODO.md @@ -5,28 +5,37 @@ which may or may not be implemented in future versions. ### To be implemented -##### Next things to work on +#### Next things to work on -1. Additional permissions (bot owner/admin & bots) +1. Better PEP8/Pylint correctness +2. Additional permissions (bot owner/admin & bots) ### Might be implemented -##### Miscellaneous +#### Miscellaneous Server-specific owner-defined ranks & all Fine-tuning of commands permissions, possible blacklist/whitelist of commands/users/roles cron-like asynchronous tasks -webserver to receive webhooks +webserver to receive webhooks +possible rST documentation -##### Commands +#### Commands - Private only - Channel B/W list (per server) - Hidden -##### Arguments +#### Arguments Special arguments: + - private (message.channel.is_private) - rank (server-specific author rank) + +#### Cogs + +- annotation for pip requirements +- ability to hide from a server (func->bool) +- per server/channel data/config files (FDs) \ No newline at end of file diff --git a/doc/cogs.md b/doc/cogs.md index 9e99ade..c3441cf 100644 --- a/doc/cogs.md +++ b/doc/cogs.md @@ -5,17 +5,23 @@ Writing one is rather straightforward, but a couple rules have to be respected. ### Match `[a-z][a-z_0-9]*\.py` -Don't run away ~~yet~~! This simply means that the name of your file must be **full lowercase** and it has to start by a letter (any file starting with `_` or a digit will be ignored). Once you have that file, just drop it in the `cogs` folder and that's all. +Don't run away ~~yet~~! This simply means that the name of your file must be +**full lowercase** and it has to start by a letter (any file starting with `_` +or a digit will be ignored). Once you have that file, just drop it in the +`cogs` folder and that's all. > Also, don't erase `base.py` - you can rename it if needed, but it's quite essential. ### Don't forget your tools -Every cog must contain a `cog` variable, which has to be an instance of `gearbox.Cog`. Here's what a standard cog header looks like: +Every cog must contain a `cog` variable, which has to be an instance of +`gearbox.Cog`. Here's what a standard cog header looks like: + ```python import gearbox cog = gearbox.Cog() ``` + By default, your cog's name will be the file name, minus the `.py` part. To change this, simply pass a new name as an argument to `gearbox.Cog()`. @@ -24,9 +30,8 @@ import gearbox cog = gearbox.Cog('my_awesome_cog') ``` -> Since [v0.1.4](https://github.com/Zeroji/semicolon/releases/tag/v0.1.4), -> you can have a specific config file just for your cog, just add a `config` -> argument with the value `json` or `yaml`: +> Since [v0.1.4], you can have a specific config file just for your cog, +> just add a `config` argument with the value `json` or `yaml`: > ```python > import gearbox > cog = gearbox.Cog('my_awesome_cog', config='yaml') @@ -39,9 +44,10 @@ cog = gearbox.Cog('my_awesome_cog') If you're an organized person, you might dislike the "drop it in the folder" part. That's why `;;` has sub-cogs! Start by creating a cog that can accept sub-cogs: + - Make a new folder with the name of your cog - Inside it, create an `__init__.py` file - this will be your source code, -use it like a regular cog source file + use it like a regular cog source file Now you can drop other cogs in that folder, and they'll be all neatly organized! Note that disabling a cog also disables its sub-cogs. @@ -52,9 +58,12 @@ Note that disabling a cog also disables its sub-cogs. #### The basics -If you're familiar with `discord.py`, then you probably know about `async`, `await` and all that stuff. If not, don't worry! You don't need that to write stuff. +If you're familiar with `discord.py`, then you probably know about `async`, `await` +and all that stuff. If not, don't worry! You don't need that to write stuff. -Every command must be "decorated" by placing `@cog.command` before its definition. After that step, it'll be recognized by `;;` as a command - as long as it has a valid name (see above). Here's a really simple command: +Every command must be "decorated" by placing `@cog.command` before its definition. +After that step, it'll be recognized by `;;` as a command - as long as it has a +valid name (see above). Here's a really simple command: ```python @cog.command @@ -62,7 +71,8 @@ def hello(): return 'Hello, world!' ``` -Straightforward, right? Your command just has to return something, and `;;` will send it in the good channel. If you return nothing... Well, nothing happens. +Straightforward, right? Your command just has to return something, and `;;` will +send it in the good channel. If you return nothing... Well, nothing happens. But what if you want it to greet someone specifically? #### Special arguments @@ -72,18 +82,22 @@ Greeting a user can be done very simply: ```python @cog.command def hello(author): - return f'Hello, {author.name}!' + return f'Hello, {author.name}!' ``` -> If you really aren't familiar with `discord.py`, have a look at [their documentation](http://discordpy.readthedocs.io/en/latest/). For very simple usage, you can get a user/channel/server name with `.name`. +> If you really aren't familiar with `discord.py`, have a look at +> [their documentation](http://discordpy.readthedocs.io/en/latest/). For very +> simple usage, you can get a user/channel/server name with `.name`. -> Wondering what this `f'{}'` thing does? Basically, it's the same as `'Hello, ' + author.name + '!'` but shorter and fancier. -[Learn more here](https://www.python.org/dev/peps/pep-0498/) +> Wondering what this `f'{}'` thing does? Basically, it's the same as +> `'Hello, ' + author.name + '!'` but shorter and fancier. +> [Learn more here](https://www.python.org/dev/peps/pep-0498/) -As you can see, simply putting `author` in the function definition will give you the corresponding object. -Why? Because `;;` is made in such a way that it'll look at what you want, -and attempt to provide it to you so you don't need to write extra pieces of code. -Here's a list of those "special" arguments: *(as of [v0.2.0](https://github.com/Zeroji/semicolon/releases/tag/v0.2.0))* +As you can see, simply putting `author` in the function definition will give you +the corresponding object. Why? Because `;;` is made in such a way that it'll +look at what you want, and attempt to provide it to you so you don't need to +write extra pieces of code. Here's a list of those "special" arguments: +*(as of [v0.2.0])* |Argument | Description | --- | --- @@ -95,24 +109,28 @@ Here's a list of those "special" arguments: *(as of [v0.2.0](https://github.com/ |`server_ex` | Special bot object including things like server config |`flags` | Flags specified by the user, if your command uses flags -*Remember that using those will give you special values, which might not correspond to your expectations.* +*Remember that using those will give you special values, +which might not meet your expectations.* > **Side note about flags** -Flags with `;;` are like flags in Bash: if the first argument of your command -starts with a dash (`-`), the letters behind it, called "flags", will be sent to the command. -You can specify which flags your command accept. Flags are case-sensitive. Quick example: +> Flags with `;;` are like flags in Bash: if the first argument of your command +> starts with a dash (`-`), the letters behind it, called "flags", will be sent +> to the command. You can specify which flags your command accept. Flags are +> case-sensitive. Quick example: +> > ```python > @cog.command(flags='abc') > def flag(flags): > return f'I got {flags}' > ``` +> > Now if you call `;flag -ab`, it'll reply `I got ab`. -> Since [v0.1.3](https://github.com/Zeroji/semicolon/releases/tag/v0.1.3), writing `;flag -a-b` or `;flag -a -b` is also accepted. - +> Since [v0.1.3], writing `;flag -a-b` or `;flag -a -b` is also accepted. #### Normal arguments -Now maybe you simply want to write a `repeat` command, but you don't know how to get the text? Just ask for it! +Now maybe you simply want to write a `repeat` command, but you don't know how +to get the text? Just ask for it! ```python @cog.command @@ -120,8 +138,9 @@ def repeat(what_they_said): return what_they_said ``` -Now, this may lead to an `Invalid argument count` error. That's because since [v0.1.1](https://github.com/Zeroji/semicolon/releases/tag/v0.1.1), -`;;` has to be told explicitly when you want all the remaining text to be sent to your function: +Now, this may lead to an `Invalid argument count` error. That's because since +[v0.1.1], `;;` has to be told explicitly when you want all the remaining text +to be sent to your function: ```python @cog.command(fulltext=True) # Adding this bit allows the command to work nicely @@ -129,7 +148,9 @@ def repeat(what_they_said): return what_they_said ``` -When sending arguments to commands, `;;` will take care of special arguments, then send the rest of the message to the other arguments. If you need multiple arguments, just define them! +When sending arguments to commands, `;;` will take care of special arguments, +then send the rest of the message to the other arguments. If you need multiple +arguments, just define them! ```python @cog.command @@ -137,12 +158,15 @@ def add(number_a, number_b): return str(int(number_a) + int(number_b)) ``` -> *May change in future versions (last changed [v0.1.1](https://github.com/Zeroji/semicolon/releases/tag/v0.1.1))* -If the user doesn't provide the arguments you need, for example if they type `add 4`, `;;` will print an error message in the chat, and your command won't be executed. -If the user sends too many arguments, for example by typing `add 1 2 3`, the same thing will happen. +> *May change in future versions (last changed [v0.1.1])* +If the user doesn't provide the arguments you need, for example if they type +`add 4`, `;;` will print an error message in the chat, and your command won't +be executed. If the user sends too many arguments, for example by typing +`add 1 2 3`, the same thing will happen. -Now what if you'd like to have default arguments? Let's say you want `add` to add 1 if `number_b` isn't specified: -since [v0.1.1](https://github.com/Zeroji/semicolon/releases/tag/v0.1.1), just do like you'd do with regular Python functions! +Now what if you'd like to have default arguments? Let's say you want `add` to +add 1 if `number_b` isn't specified: since [v0.1.1], just do like you'd do with +regular Python functions! ```python @cog.command @@ -152,8 +176,13 @@ def add(number_a, number_b=1): # If number_b isn't specified, it'll be 1 #### More arguments! -Let's say you want to have a command that takes a string, then a series of strings, and inserts that first string between all the others, i.e. `, 1 2 3` would give `1,2,3` - wow, that's just like `str.join()`! -You'll want to have the first argument, then "all the rest". Of course, you could be using `def join(my_string, all_the_rest):` along with `fulltext=True` and then use `.split()`, but ;; can do that for you! Simply add `*` before your last argument, and it'll receive a nice little list of whatever was sent: +Let's say you want to have a command that takes a string, then a series of +strings, and inserts that first string between all the others, i.e. `, 1 2 3` +would give `1,2,3` - wow, that's just like `str.join()`! +You'll want to have the first argument, then "all the rest". Of course, you +could be using `def join(my_string, all_the_rest):` along with `fulltext=True` +and then use `.split()`, but ;; can do that for you! Simply add `*` before your +last argument, and it'll receive a nice little list of whatever was sent: ```python @cog.command @@ -163,21 +192,25 @@ def join(my_string, *all_the_rest): #### About `async` and `await` -What if you're an advanced user and you know all that async stuff already and just want to add your tasks to the event loop while awaiting coroutines? +What if you're an advanced user and you know all that async stuff already and +just want to add your tasks to the event loop while awaiting coroutines? ```python async def command(client): ``` -It's that simple. If your command is a coroutine, then `;;` will simply `await` it (if you want to send a message, do it yourself!); and the `client` argument will give you access to the main client. Hint, the loop is at `client.loop` +It's that simple. If your command is a coroutine, then `;;` will simply `await` +it (if you want to send a message, do it yourself!); and the `client` argument +will give you access to the main client. Hint, the loop is at `client.loop` ### Documenting your command -###### a.k.a. adding a cute little ribbon on it + +> a.k.a. adding a cute little ribbon on it You may have seen this wonderful `help` command in the `base` cog, which does some really neat stuff, like displaying what a command does, which arguments -to use and all. Sadly, those informations aren't magically generated: you have -to add them to your command or it won't work. +to use and all. Sadly, this information isn't magically generated: you have +to add it to your command or it won't work. #### What your command does @@ -188,7 +221,7 @@ very beginning of your command: @cog.command def documentation(): """Print documentation about how to document. - + This is an additional **text message**, feel free to use some __fancy__ Discord formatting! Newlines are respected, *don't worry*! You can even put some `code blocks`.""" ``` @@ -201,7 +234,8 @@ It is recommended you avoid using Discord formatting in the first line. #### Flags documentation You may have seen flags earlier, they are some kind of one-letter arguments that are -either present or absent: +either present or absent: + ```python @cog.command(flags='abc') def show_flags(flags): @@ -230,7 +264,7 @@ for a certain flag, set it to `''` (empty string). First of all, any "special" argument to your command will *not* be displayed: that's normal, because those are supposed to be internal arguments. Normal arguments can have two values added to them: a *type*, for example -your `add(x, y)` function generally takes `int` objectss; and a *documentation +your `add(x, y)` function generally takes `int` objects; and a *documentation string* which `help` uses to display even more information. Now, both those values are optional, and you can write one without the other, but here how it's done: @@ -296,44 +330,58 @@ string set, an error is displayed. *Technically, this adds features to the cog rather than to the command.* -You've already used the decorator `@cog.command` to indicate that your function was a `;;` command and not a random function. +You've already used the decorator `@cog.command` to indicate that your function +was a `;;` command and not a random function. You can do a bit more, here, have a list: -##### `@cog.rename(name)` -This will change the name of your command. It's useful, for example, if you want your command to be called `str` but you can't because of Python's `str()` function. Just call your function `asdf` and put `@cog.rename('str')` before it. +#### `@cog.rename(name)` + +This will change the name of your command. It's useful, for example, if you want +your command to be called `str` but you can't because of Python's `str()` +function. Just call your function `asdf` and put `@cog.rename('str')` before it. + +#### `@cog.alias(alias, ...)` -##### `@cog.alias(alias, ...)` -This creates aliases for your command. Let's say you find `encrypt` is a quite long name, just add `@cog.alias('en')` and you'll be able to call your command with `encrypt` *and* `en`. +This creates aliases for your command. Let's say you find `encrypt` is a quite +long name, just add `@cog.alias('en')` and you'll be able to call your command +with `encrypt` *and* `en`. + +#### `cog.hide` -##### `cog.hide` This will simply hide your command. This means that anything which, like `help`, gives a list of commands, won't show this one. Very useful for hiding your fallback commands (see below). ### Getting the best out of `@cog.command` -If you've read all the above doc, you saw `@cog.command(fulltext=True)`: -indeed, the `@cog.command` decorator can take a couple special parameters, here's the list +If you've read all the above doc, you saw `@cog.command(fulltext=True)`: indeed, +the `@cog.command` decorator can take a couple special parameters, here's the list + +#### `fulltext` (boolean, defaults to `False`) -##### `fulltext` (boolean, defaults to `False`) +This argument, when set to `True`, will allow your command to receive all the +text the user wrote, for example: -This argument, when set to `True`, will allow your command to receive all the text the user wrote, for example: ```python @cog.command(fulltext=True) def say(text): return text ``` -If you call `;say Hello world!` it'll repeat it, but if `fulltext` was set to `False` it would have resulted in an `Invalid argument count` error. +If you call `;say Hello world!` it'll repeat it, but if `fulltext` was set to +`False` it would have resulted in an `Invalid argument count` error. -##### `delete_message` (boolean, defaults to `False`) +#### `delete_message` (boolean, defaults to `False`) -If this option is enabled, `;;` will try to delete the user's message after the command was executed. +If this option is enabled, `;;` will try to delete the user's message after the +command was executed. -##### `permissions` (string, tuple or list, defaults to `None`) +#### `permissions` (string, tuple or list, defaults to `None`) + +This one is a bit trickier: it allows you to specify that a user needs certain +permissions for running a command. Say you want only users with `manage_server` +permission to use your command, you could use one of the following: -This one is a bit trickier: it allows you to specify that a user needs certain permissions for running a command. -Say you want only users with `manage_server` permission to use your command, you could use one of the following: ```python @cog.command(permissions='manage_server') @cog.command(permissions=('manage_server', True)) @@ -341,14 +389,14 @@ Say you want only users with `manage_server` permission to use your command, you @cog.command(permissions=[('manage_server', True)]) ``` -The more complex forms are useful, because you can set complicated behaviour: what if you want your command to be -available only to non-admins who can delete messages? +The more complex forms are useful, because you can set complicated behaviour: what +if you want your command to be available only to non-admins who can delete messages? ```python @cog.command(permissions=[('manage_server', False), 'manage_messages']) ``` -##### `fallback` (string) (optional) +#### `fallback` (string) (optional) > Please read the paragraph above about the `permissions` argument if you haven't already. @@ -371,55 +419,37 @@ def delete2(number=1): > You can use `@cog.hide` to prevent `delete2` from being listed. -##### `flags` (string or dictionary, defaults to `''`) +#### `flags` (string or dictionary, defaults to `''`) -This allows you to tell `;;` which flags can be used by the command. -An error message will be printed if the user tries to use an invalid flag. -See the [Special arguments](#special-arguments) section above for more information about flags. +This allows you to tell `;;` which flags can be used by the command. An error +message will be printed if the user tries to use an invalid flag. See the +[Special arguments](#special-arguments) section above for more information about flags. You can use a string, like `'ab'`, or a dictionary if you'd like to add information: `{'a': 'Does a certain action', 'b': 'Executes plan B'}` -See the [Documenting your command](#documenting-your-command) for details about documentation. +See the [Documenting your command](#documenting-your-command) for details about documentation. ### Special functions -Cogs aren't made of commands only: you can have functions execute upon loading/unloading of a cog, -have another function being called when a reaction is added, when a message is deleted, and so on. +Cogs aren't made of commands only: you can have functions execute upon +loading/unloading of a cog, or even based on events (see below). This is done by using special decorators: #### `@cog.init` + Any function decorated with this will be called when the cog is loaded. You can only have one init function. -#### `@cog.exit` +#### `@cog.exit` + Any function decorated with this will be called when the cog is unloaded. You can only have one exit function. -#### `@cog.on_reaction` -Any function decorated with this will be called when a reaction is added to / removed from a message. -You can add arguments to the decorator to specify a reaction whitelist, -by default it will match any reaction. The blacklist can either be a string (one reaction), -or a tuple of strings for multiple reactions: - -```python -@cog.on_reaction(('😃', '❤')) -async def my_reaction_function(client, added, reaction, user): - await reaction.message.channel.send( - f'User {user.mention} {"added" if added else "removed"} reaction {reaction.emoji}') -``` - -A reaction function has to be defined as `async`, -and must take four arguments, in this order: -- `client` The `discord.py` `Client` object, otherwise you can't do anything -- `added` A boolean, set to `True` if the reaction was added and `False` if it was removed -- `reaction` The `Reaction` object. You can use `reaction.emoji` to get the `Emoji` object or Unicode emoji string, - and `reaction.message` to get the associated `Message` object. -- `user` The `User` who added or removed the reaction. - ### Event handlers -You want to do even more stuff? As of [v0.2.1](https://github.com/Zeroji/semicolon/releases/tag/v0.2.1), you can -write custom event handlers! Those are the same events you can use in a `discord.py` client, except you register -them using `@cog.event`. The best part is, you can use a bunch of special arguments and it'll likely +You want to do even more stuff? As of [v0.2.1], you can write custom event +handlers! Those are the same events you can use in a `discord.py` client, except +you register them using `@cog.event`. The best part is, you can use a bunch of +special arguments and it'll likely work as intended! ```python @@ -428,16 +458,30 @@ def on_typing(user): return 'I see you, ' + user.display_name ``` -The standard `on_typing` event uses `(channel, user, when)` but you can directly ask for whatever you need! -And just like commands, you can simply return what you want to send. +The standard `on_typing` event uses `(channel, user, when)` but you can directly +ask for whatever you need! And just like commands, you can simply return what +you want to send. -> Side note: returning a message will only work if the event takes place in a specific channel. For -> example, on_reaction_add will work but not on_member_update. +> Side note: returning a message will only work if the event takes place in a +> specific channel. For example, on_reaction_add will work but not on_member_update. ### Using your cog -As written above, you just need to drop it in the `cogs` folder! -> Side note: make sure you have the `import gearbox; cog = gearbox.Cog('name')` part, otherwise `;;` will consider the file broken and won't load it until it restarts. +As written above, you just need to drop it in the `cogs` folder! + +> Side note: make sure you have the `import gearbox; cog = gearbox.Cog('name')` part, +> otherwise `;;` will consider the file broken and won't load it until it restarts. + +If `;;` is running, it'll automatically load it within a couple of seconds, and +reload it when you edit it. Don't worry, if you break stuff, it'll keep running +the old code until the new one is working. +If you have name conflicts with another module, call your commands +with `cog_name.command_name` to avoid collisions. -If `;;` is running, it'll automatically load it within a couple of seconds, and reload it when you edit it. Don't worry, if you break stuff, it'll keep running the old code until the new one is working. -If you have name conflicts with another module, call your commands with `cog_name.command_name` to avoid collisions. +[v0.1.0]: https://github.com/Zeroji/semicolon/releases/tag/v0.1.0 +[v0.1.1]: https://github.com/Zeroji/semicolon/releases/tag/v0.1.1 +[v0.1.2]: https://github.com/Zeroji/semicolon/releases/tag/v0.1.2 +[v0.1.3]: https://github.com/Zeroji/semicolon/releases/tag/v0.1.3 +[v0.1.4]: https://github.com/Zeroji/semicolon/releases/tag/v0.1.4 +[v0.2.0]: https://github.com/Zeroji/semicolon/releases/tag/v0.2.0 +[latest]: https://github.com/Zeroji/semicolon/releases/latest diff --git a/doc/translations.md b/doc/translations.md index 6780e0c..09312f2 100644 --- a/doc/translations.md +++ b/doc/translations.md @@ -30,7 +30,7 @@ Once this is done, start `;;` and `lang` should show the language you added. If you switch to it, messages from the cog you translated should be in your language! -##### Contributing +#### Contributing If you want to push your translations to GitHub, fine, but make sure you follow those guidelines: @@ -47,7 +47,7 @@ follow those guidelines: Now, if as a developer you want to make your cog translatable by other people, it's fairly easy. -##### Translation functions +#### Translation functions `;;` uses the `gettext` module for translations. It's quite very simplified here, so just use the following at the top of your cog: @@ -65,7 +65,7 @@ the following line: ngettext = cog.ngettext ``` -##### Mark strings to be translated +#### Mark strings to be translated The `_` function performs white magic to translate your strings into whatever is currently needed. When you have some translatable text, just wrap it with it: @@ -90,7 +90,7 @@ def apples(count: int): This will pick one of the other string depending on `count`, and format it to insert the number `count` inside it. It's mostly required for grammatical reasons. -##### Generate translation templates +#### Generate translation templates If you have a Linux-based bash with `xgettext` on your system, just navigate to the folder containing `;;` and execute `./templates.sh`: it will generate translation diff --git a/requirements b/requirements index f697834..03c3cc0 100644 --- a/requirements +++ b/requirements @@ -1,3 +1,3 @@ -git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py[voice] +git+https://github.com/Rapptz/discord.py@rewrite PyYAML==3.12 arrow