Compare commits

..

291 Commits

Author SHA1 Message Date
palmtree5 c4b641e62a [V3] Bump version to 3.0.0b10 (#1418) 2018-03-20 16:36:32 -08:00
James 153d710eb4 [V3] Allow load, unload and reload to deal with multiple packages (#1441)
* [V3] Allow load, unload and reload to deal with multiple packages

This PR allows multiple packages to be loaded, unloaded or reloaded with the one command, the packages are delimited by the space character as suggested by Will
This is just the functionality, I'm sure the code could be better

* introduced helper function for getting package load strings

* missed characters

* forgotten import 👀

Forgot to include the import `inline` method from chat_formatting
2018-03-20 16:32:54 -08:00
palmtree5 83471e0866 [V3 Core] implement commands and settings for embeds (#1437)
* [V3 Core] add settings for whether to use embeds or not

* Implement commands to toggle embed settings

* Add a function to context for finding whether to use embeds or not

* Hide [p]embedset for now

* Move embed_requested to bot

* Add a simple helper in context
2018-03-21 01:17:40 +01:00
Michael H 01b9843883 [V3] Change presence (continued fixes) (#1438)
* This better fixes the root issue rather than attempting to work around it

* move bot_in_guild to checks, and use the correct syntax
2018-03-21 01:12:40 +01:00
retke 749af89e9f [V3] Set token command (#1425)
* [V3] Add set token command

* DM check

* warning message + delete if token isn't send in DM

* Update string formatting
2018-03-21 01:08:36 +01:00
palmtree5 27b61a2770 [V3 Streams] Fix community alerts (#1426)
* [V3 Streams] fix community alerts

* drop unneeded parentheses + delete messages when removing from cache

* move to one embed for a community

* fix adding image to embed

* Remove unneeded params

* Really helps to point to the right place

* drop the game, move channel name+link to value

* Use stream title in embeds

* Increase number of streams to grab to 100

* filter out streams with existing individual alerts in the channel

* need channel id, not stream id in filtering function

* sample from the list

* we only want to break out if the alert is a TwitchStream alert

* drop off sending the mentions if there are none
2018-03-20 19:25:23 -04:00
palmtree5 eb3b6346bb [V3] Set r/w access before deleting files (#1412)
* [V3] set access before deleting

* [V3] move+rename do_delete and use in repo removal in downloader
2018-03-20 18:46:15 -04:00
aikaterna 2e9a0de4a1 [V3 Audio] Update audio to use Red-Lavalink (#1440)
* [V3 Audio] Update audio for Red-Lavalink

* Update requirements for new library

* Fix logic for connect time storage for audiostats

Only store time when connecting to the voice channel.
2018-03-20 23:28:31 +01:00
palmtree5 f83e3cc3e7 [V3 Economy] Expand payday output (#1386)
* [V3 Economy] implement suggestions from #1371

* Fix a typo

* Add functions for getting leaderboard and leaderboard position

* Use the new functions to get leaderboard position and leaderboard (overrides https://github.com/Cog-Creators/Red-DiscordBot/pull/1435)

* Actually implement showing only guild members on leaderboard when bank is global

* get_leaderboard_position needs to be awaited

* For global bank, pass None for guild to get_leaderboard when trying to find position

* Remove some unneeded code

* Wrong index...

* Combine 3 messages into 1

* Fix guild leaderboard while bank is global

* add missing parentheses

* Modify the leaderboard formatting

* More work on leaderboard formatting

* no subtraction
2018-03-20 18:22:10 -04:00
palmtree5 a8f4659552 [V3 Instance Setup] Storage swapping (#1421)
* [V3 Instance Setup] start work on storage swapping

* This should do the trick for Mongo -> JSON

* Fix typo

* Fix a few more typos

* resolve the data path

* Upsert the imported data

* need a list of the documents

* to_list is a coro
2018-03-16 13:37:12 -08:00
Will 25a5c3dec9 Pip install to library dir (#1432) 2018-03-16 16:12:05 +01:00
Wyn c49cb4a213 [V3 Readme] Update Patreon link (#1434)
Add on to #1431
2018-03-14 19:22:50 -04:00
palmtree5 c4dbbc2d1e [V3 Warnings] Action list isn't a dict (fix #1382) (#1408) 2018-03-14 19:10:07 -04:00
palmtree5 fe3d6f57af [V3 Streams] Add support for Youtube streams (#1385) 2018-03-14 19:07:14 -04:00
palmtree5 052af2f9bf [V3 Cleanup] Code consolidation (#1347)
* [V3 Cleanup] refactor to consolidate duplicate code

* [V3 Cleanup] make the prompting function a staticmethod

* Drop continuing message + add punctuation to docstrings
2018-03-14 19:03:11 -04:00
Adam 16da9f52ac [V3 Audio] update Lavalink build (#1427) 2018-03-12 21:48:13 -08:00
palmtree5 22a342d36d [V3 Bank/Economy] Fix #1404 and an issue with [p]bank reset (#1407)
* [V3 Bank] fix an issue with checks

* [V3 Economy] fix issues with [p]bank reset
2018-03-12 19:10:46 -04:00
palmtree5 4fcf32b5e9 [V3 Bank] Add confirmation prompt on [p]bankset toggleglobal (#1402) 2018-03-12 19:05:21 -04:00
palmtree5 5bdb455bc0 [V3 Instance setup] Change backup time separator for Windows (#1419) 2018-03-12 18:48:13 -04:00
BaIthamel 1cb74f0ea7 [V3] Fix for issue #1363 (#1424)
[p]cogs and [p]repo now print alphabetically
2018-03-12 18:44:30 -04:00
Tobotimus c7e8c95640 [V3] discord.Game -> discord.Activity (#1397)
* [V3] discord.Game -> discord.Activity

* Update userinfo to reference new enum
2018-03-12 18:41:37 -04:00
Will ccb322d08e [Audio] V3/auto autostart only (#1420)
* Download jar at audio load

* Messy...

* Remove leftover log file stuff

* Keep application.yml

* Damn you windows
2018-03-12 00:49:08 +01:00
Wyn b27e0f2d21 [V3 Audio] Rename Game to Activity (#1409)
* Rename `Game` to `Activity` for audio

Add on to pull #1397

* Update audio.py

Whoops, don't need this here

* Update audio.py

Now fixed
2018-03-08 20:55:03 -05:00
aikaterna 6a715d87dd [V3 Audio] Add prev command, bugfixes for audiostats, search (#1405)
* Update audiostats to display days in timer

* Add prev command

* Update search button to play enqueued song
2018-03-08 20:50:54 -05:00
Tobotimus 6138b78c07 [V3 Admin] Make [p]announce consume all args into the message (#1394)
* Fix announce (resolves #1390)

* Make other commands consume all args

Also fixes [p]announce channel
2018-03-08 20:45:41 -05:00
palmtree5 f84ef48819 [V3 Docs] add java install to install docs (#1389) 2018-03-08 20:06:27 +01:00
palmtree5 cda27944b6 [V3 Mod] fix #1401 (#1403) 2018-03-07 09:48:22 +11:00
Will c9281f734b [V3 Config] Fix clear throwing errors (#1374) 2018-03-06 10:28:37 +11:00
palmtree5 f378ea0d2e [V3 Core] add update check (#1388)
* [V3 Core] add update check

* [V3 Core] have it DM the owner if out of date
2018-03-06 10:21:01 +11:00
James 40c37b5c06 [V3 Help][ fix help_formatter to obey length limits (#1375)
Help didn't account for docstrings passing length limits which I noticed a while ago and as noticed again when Palm forgot a dual newline in a command docstring.
This PR sees to fix this by enforcing length limits on description, field names and field values
2018-03-06 10:10:56 +11:00
Will 57b7db6956 [V3 Admin] Remove guild default channel (#1381)
* Remove guild default channel

* Fix weird set thing
2018-03-06 09:52:26 +11:00
Michael H b4f5c2c0a1 Revert "[V3]Encoding issue fix" (#1392)
* Revert "[V3 Core] Encoding issue fix (#1365)"

This reverts commit f6903cf582.

* Don't let the system encoding screw with things,
specify opens as happening with utf-8 encoding

(cherry picked from commit c10e4dddca)
2018-03-06 08:18:41 +11:00
Michael H f6903cf582 [V3 Core] Encoding issue fix (#1365)
* Don't let the system encoding screw with things,
specify opens as happening with utf-8 encoding

* And also deal with encoding issues because windows is a special snowflake
(see: #1366)

* let's just use the encoding param in str() rather than encode/decode...
2018-03-04 13:02:04 -05:00
aikaterna 3816385228 [V3 Audio] Fix repeat, Message deletions (#1379)
* Fix repeat

Also remove restriction on if the player is playing.

* Auto-delete existing Now Playing message

* Auto-delete existing notify message

* Wrap line on Now Playing message

* Add connected duration to audiostats

_dynamic_time based on a function written by Redjumpman

* Return negative seek past song start as 00:00:00

* Version number
2018-03-03 18:55:24 -05:00
Will f65085946c [V3 Audio] Initial V3 addition (#1373)
* Initial audio

* Add application data and modify port

* Modify codeowners

* Need extra newline

* add yml to manifest

* lock lavalink version
2018-03-03 15:42:20 +11:00
Thomas Mercurio b10b746d9e [V3 Config] Correct Mongo connection URI without credentials (#1362)
* Correct connection string without credentials

* Remove extra whitespace.
2018-03-02 18:39:45 +01:00
James ed5945e182 fixed exception (#1372)
`requirements.remove` will raise a ValueError if the item is not there, not `IndexError`
2018-03-02 18:35:28 +01:00
Will cf48a13fc7 Potentially fix auto deploy issues (#1357) 2018-02-28 13:08:47 +01:00
palmtree5 29d9bbad32 [V3] Bump version to 3.0.0b9 (#1348) 2018-02-26 11:49:48 -09:00
Will 004f42bf6e [V3 Config] Limit connections to Mongo DB (#1356) 2018-02-26 15:34:30 -05:00
Will 41e0d105f6 [V3 Config] Make Mongo work with any db (#1355) 2018-02-26 15:28:20 -05:00
Will fdd61963e6 Add pip install command (#1354) 2018-02-26 11:21:41 -09:00
Will 10cbd4d3c4 [V3 Sentry] Only log errors that come from core code (#1353)
* Do not load core cogs as extensions

* Filter this shit
2018-02-26 15:16:49 -05:00
Will 64af7800dc [V3 Config] Adjust functionality of get_attr (#1342)
* Intermediate commit

* Add defaulting stuff to config

* Remove set_attr in favor of set_raw

* Modify get_attr

* Fix issue with clearing data
2018-02-26 11:13:01 -09:00
palmtree5 c428982c00 [V3 Core] Add listlocales command (#1351)
* [V3] Add listlocales command + remove a hanging 2 letter translation

* Sort the locales list

* Doc info in set locale
2018-02-26 15:05:06 -05:00
Will 1363bc3f43 [V3] Disregard limitations on repo names (#1349) 2018-02-25 21:21:13 -09:00
Michael H 09ddfe4250 [V3] Re-allow using presence modifying commands without being in a guild (#1345)
Actually update on all shards (we need to do this even with autoshardedbot as base)
2018-02-25 21:10:59 -09:00
Will e13de0950c [V3 Config] Implement a true clear method (#1344)
* Add clear methods to drivers

* Update config clear methods, add to Value

* Add test
2018-02-25 21:07:28 -09:00
palmtree5 c1ac78eea4 [V3] Warning system (#1173)
* [V3 Warning] initial work on a warning system for v3

* [V3 Warning] rename some stuff and add a case type

* [V3 Warnings] rename package from warning

* [V3 Warnings] restructuring commands

* [V3 Warnings] remove expiry stuff + other refactoring

* [V3 Warnings] refactoring action logic

* [V3 Warnings] rewrites to action logic

* [V3 Warnings] add regen_messages.py
2018-02-25 20:14:38 -09:00
Kowlin 21de95e0a6 [CI] Added support for conditional builds and env vars (#1320)
* Changed travis deploy scheme

* Fixed indentation

* Okay NOW I did fix indentation (hopefully)

* Conditional deployment tests

* Fixed a 7:35 AM typo

* Fixed builds not building.
2018-02-25 20:10:55 -09:00
palmtree5 0593bb9c53 [V3 i18n] Update translations from Crowdin (#1350) 2018-02-25 21:57:14 -05:00
Will bd1ce26dc7 Fix missing repos folder (#1330) 2018-02-25 16:40:09 +01:00
Will 2612e7c23a [V3 Config] Add more information to the docs (#1343)
* Attempt to determine the registered default...if any

* Intermediate commit

* Add more doc information
2018-02-25 14:56:12 +01:00
Will 93ca7abc1a [V3 Core Commands] Limit status modifying commands to be run in guild only (#1331)
* Limit status modifying commands to be run in guild only

* JK let em run.

* Add a space
2018-02-23 02:44:06 +01:00
Will de4af14676 Fix unreferenced tmp variable (#1334) 2018-02-23 02:29:04 +01:00
Will c9a6c0ffcc Converters don't work the way I think they do (#1336)
(No they don't Will -- Kowlin)
2018-02-23 02:21:39 +01:00
Will d414806fa2 Close aiohttp ClientSession (#1340) 2018-02-23 02:08:49 +01:00
Will d54c129c57 [V3 Config] Allow users to directly specify a cog name with config (#1339) 2018-02-22 19:42:30 -05:00
Will 7c848153f8 [V3 Config] Limit config objects to a single one per cog (#1337)
* Limit config objects to a single one per cog

* do it correctly

* Do nicer thing

* do it right...

* I will get this right eventually
2018-02-22 19:36:07 -05:00
Will 4e36c2f82d [V3 Config] Add helper methods for advanced data access (#1335)
* Add get_raw/set_raw

* Add default to get_raw

* Add custom group method to the config object

* Add more methods for custom groups

* Add some docstrings

* Deepcopy the result of get_raw, throw TypeError if no value is passed to set_raw

* Do it right..

* Better way to require kwarg
2018-02-23 11:29:37 +11:00
Sebass13 b5c71bc59c [V3 Mod/Filter] Fix #1202 (#1327)
* Fix #1326

Checks to see if `author` is a `valid_user` (of `Member` class) before checking to see if the bot `is_mod_or_superior` to the `author`.

* Fix #1202

Raises `TypeError` when `User` objects are passed into `is_mod_or_superior` or `is_admin_or_superior`, as only `Member` objects have a `guild` attribute.

* Fixes #1202

Checks to see if `author` is a `valid_user` (of `Member` class) before checking to see if the bot `is_mod_or_superior` to the `author`.
2018-02-21 18:36:13 -05:00
Sebass13 d20724d7b2 [V3 General] Fix error in [p]userinfo when game is not set (#1325)
* Fix #1321

Modifies the game-checking lines so that they don't assume `user.game` is not a NoneType object.

* Fix #1321

Modifies the game-checking lines so that they don't assume user.game is not a NoneType object. Also alerts the user to go bother @tekulvw if somehow the invariants of `user` having a `game` attribute and the `game` attribute either being `None` of having a `type` attribute in `[0, 1, 2, 3]` are broken.

* Update general.py
2018-02-20 18:06:06 -05:00
Sebass13 1cca5ee5cb [V3 Downloader] Fixes issue #1323 (#1324)
The use of `popitem` makes the right side of line 642 return a tuple of the form `(repo, (old, new))` instead of a dictionary of the form `{repo: (old, new)}`, as expected by the left hand side of the same line.
2018-02-19 22:41:19 -05:00
palmtree5 95acf7402d Fix pip install in .travis.yml (#1319) 2018-02-18 18:56:09 -09:00
palmtree5 c8f3734569 [V3] bump version to 3.0.0b8 (#1296) 2018-02-19 04:45:24 +01:00
Will f9d846a704 [V3 Config] Driver code initial cleanup (#1315)
* Remove get_driver

* Rename self.driver to self._driver

* Do not unnecessarily pass the cog identifier

* Remove unused import

* Fix type annotation

* Missed a keyword rename

* Modify signature of get/set methods in drivers
2018-02-18 18:30:32 -09:00
retke 3984cb8f48 load and reload command errors available with the [p]traceback command (#1307) 2018-02-19 04:18:56 +01:00
Bakersbakebread a0327a62dd move [p]cogs to embeds (#1299)
* move [p]cogs to embeds

Fancy embeds for the masses

* pagify
2018-02-18 18:03:27 -09:00
palmtree5 a388d07f30 [V3 Events] modify CommandInvokeError handler to use the vague message as a fallback if a cog doesn't provide its own __error function (#1279) 2018-02-19 03:59:46 +01:00
Michael H 7f0cca1baf pin all dependencies except youtube-dl, and Red-Trivia. (#1317)
* pin all dependencies except youtube-dl, and Red-Trivia.
The ranges on these might be expandable, but I can personally confirm these versions
to work

* this is what I get for copy/pasting version and not double checking

* and this is what I get for manually typing it
2018-02-19 03:52:32 +01:00
Will 249756e0d2 [V3 Downloader] Make shared libraries work and make repo handling smarter (#1313)
* Make stuff stateless

* Update shared lib stuff
2018-02-19 03:49:43 +01:00
Bakersbakebread d2e841f681 [V3] Add prompt if message deletion > 100 (#1304)
* Add prompt if message deletion > 100

As per issue #1295. 

Add's the prompt "Are you sure you want to delete {number} messages? (y/n)"

* added checks and deletes "Continuing" message

phew

* removed unneeded delete()

Removed the unneeded code
2018-02-18 17:44:45 -09:00
Will b871241eac [V3 Core] Add optional async setup function (#1314) 2018-02-18 21:12:58 -05:00
palmtree5 86b5932c8f [V3] add a script for regenerating all strings (#1318)
* [V3] add a script for regenerating all strings

* Edits to the yml files

* Fix up deploy section

* Make generate_strings upload to Crowdin
2018-02-19 03:02:22 +01:00
palmtree5 39dbe2805b [V3] Pin aiohttp-json-rpc due to conflicts (#1312) 2018-02-16 18:51:55 +01:00
William 263e94454c [V3 Core] Adds listening and watching games. (#1284)
* Adds listening and watching games.

* Remove guild check

* Fix typos

* Fix more typos.
2018-02-14 16:55:18 -09:00
palmtree5 01e8579215 [V3 instance setup] allow removing instances without taking a backup + error handling for missing data path (#1277) 2018-02-15 02:39:29 +01:00
palmtree5 e00fa2df26 [V3] move 'distro' out of requirements.txt (blame Windows) (#1298) 2018-02-15 02:30:30 +01:00
aikaterna 78615b5dc8 [V3 Core] Add timeout exceptions to [p]servers (#1305) 2018-02-14 16:21:51 -09:00
Haruki N. Grande 9f8a008442 [V3 CogManager] Fixed typo (#1285) 2018-02-14 15:57:17 -09:00
Will 6678b29396 [V3 Config] Fix async context manager bug and add test (#1308)
* Fix config bug and add test

* Fix the full bug

* Extra safeness
2018-02-14 19:12:13 -05:00
Kowlin 11636b16d2 [V3 General] Updated userinfo (#1289)
Updated userinfo to include new statuses
2018-02-09 13:18:06 -09:00
palmtree5 194981cd8b [V3] Bump version to 3.0.0b7 (#1271) 2018-01-28 19:10:01 -09:00
palmtree5 0c85e0fe22 [V3] Add support for removing instances (#1270)
* [V3 Instance Setup] add a way of removing instances

* [V3 Launcher] add instance removal support to the launcher
2018-01-29 04:56:28 +01:00
Michael H de3a057e6e [V3] Allow root to own data (#1264) 2018-01-28 18:41:01 -09:00
palmtree5 f36ed2f8c8 [V3 Core] add restart command (#1272) 2018-01-29 04:29:56 +01:00
palmtree5 1d1f2c9f12 [V3 Core] add uptime command (#1273) 2018-01-29 04:25:17 +01:00
Redjumpman 9feb7ad876 Config Fix (#1267)
Added helper function to fix all() method
2018-01-29 04:19:41 +01:00
Michael H 1b45397e67 [V3 Core] Mentionable prefix (#1256)
* allow mentioning the bot as a fallback to a prefix

* make this toggleable
2018-01-24 10:43:51 +11:00
palmtree5 55bbbe6268 [V3] pin yarl to 0.18.0 (#1262) 2018-01-19 23:24:21 +01:00
palmtree5 eeba454dbb [V3] bump version to 3.0.0b6 (#1254) 2018-01-14 19:51:05 -09:00
Michael H b80c327e35 For Linux service users, (#1236)
* For Linux service users,
use `appdirs.AppDirs().site_data_dir`
instead of `appdirs.AppDirs().user_config_dir

* somewhat important for this to be changed consistently

* need to import os to use it

* travis doesn't like how I was checking in config_dir had been set.
2018-01-15 05:35:33 +01:00
Aioxas eb10508c5f [V3 Alias] Allow wider range of aliases (#1201)
* [V3 Alias] Allow wider range of aliases

Possible fix for #1118

Makes it so that the only non-valid names are the ones that can't be printed by something.

* [V3 Alias] Edit Check & Error Message

Reflects the wider range of aliases that can be created.

* [V3 Alias] Fix wrong slash in regex

* [V3 Alias] Fix Wrong Closing Parenthesis Position

Can't believe I'm messing it up
2018-01-14 19:28:57 -09:00
Tobotimus 73c08da037 [V3 Sentry] Allow toggling of Sentry logging (#1214)
* Refactor sentry to allow toggle

* Rename sentry module

* Protect sentry manager

* Fix tests

* Fix EOF newlines

* Add docstrings
2018-01-15 15:26:26 +11:00
Tobotimus e18f94c17d Fix [p]cleanup bot (#1205) 2018-01-15 05:20:54 +01:00
Michael H f1a20e1677 [V3 Streams] Duplicate stream alerts fix (#1244)
case insensitive on twitch streams, with a fast dedupe on load toany prior bad entries.
2018-01-14 19:17:57 -09:00
Tobotimus 4ac606b468 [V3 Launcher] Fix asking for cli flags after invalid instance selection (#1200) 2018-01-14 19:11:24 -09:00
Tobotimus 980e8eeb3e [V3 Core] Catch errors when reloading (#1225) 2018-01-14 19:04:09 -09:00
Tobotimus ffea55265d [V3] Fix UnicodeEncodeError on startup (#1248)
Fixes case where encoder can't support border characters
2018-01-14 18:57:28 -09:00
Tobotimus fb0190f826 [V3 Trivia] Allow crediting the author of trivia lists (#1197)
* Credit author of trivia lists

* Use proper sentences

* Remove unwanted traceback print
2018-01-15 14:50:14 +11:00
Tobotimus 68800d28fc [V3 Streams] Replace instances of ClientSession assignment with async context manager (#1238) 2018-01-14 18:43:06 -09:00
Tobotimus 05c5c58eaf [V3 Utils] Improve bordered function and add tests (#1206) 2018-01-13 11:15:34 +11:00
Redjumpman 1c504f681e [V3 Config] Fixed raised Attribute Error Message (#1247)
Added space in raised Attribute Error message
2018-01-13 10:57:37 +11:00
Redjumpman 5bd7a23864 [V3 Bank] Fix can_spend and withdraw_credits (#1234)
* Fixed equality operator

can_spend function should be using a >= instead > so that you can spend all of your currency.

* Update bank.py

Fix for withdraw using the wrong equality operator.

* Revert withdraw_credits

Reverted withdraw_credits back to original operator.
2018-01-11 20:26:34 +01:00
William 7aa829fa8c [V3] Update year in license (#1242) 2018-01-09 16:20:05 -09:00
Michael H de1b135dec [V3 Help Formatter] Fix help command's error handler (#1237) 2018-01-07 11:26:21 +11:00
Tobotimus d83f14d1b6 [V3 Streams] Fix preceding comma in streamalert messages (#1224)
* Refactor getting mentions for streamalerts

* Add missing await

Fixes #1192
2018-01-01 18:24:36 +11:00
Kowlin 0a705071c2 [Core] QoL for argparser (#1217)
* Made Argparser more QoL

* Edited the usage command.
2017-12-31 14:19:56 +11:00
Tobotimus 80d68684fb [V3 Context] Fix ctx.send_interactive in DM (#1221)
Fixes #1220
2017-12-31 11:29:07 +11:00
palmtree5 c737785114 Bump version to 3.0.0b5 (#1189) 2017-12-17 19:12:50 -09:00
Tobotimus 76ae62cb84 [V3 Streams] Improve command responses and help, rename modules (#1194)
* Command response improvements for streams

Fix #1182

Fix #1183

Various other command response improvements

* Rename main to streams, streams to streamtypes

* Raise errors for communities
2017-12-17 18:56:17 -09:00
palmtree5 103f79eca5 [V3 Mod] Fix helpers compatibility with User objects (#1185) 2017-12-17 22:23:54 -05:00
Will 0979231435 [V3 Sentry] Modify error logging cases (#1193)
* Fix duplicate on_

* Make better use of sentry error handler
2017-12-17 21:21:41 -05:00
palmtree5 f3da10ec98 [V3 Utils] add embed utils with a random_colour function (#1164)
* [V3 Utils] add embed utils with a random_colour function

* [V3 Utils] random_colour -> randomize_colour + make it take an embed

* [V3 Utils] decomplicate the random color selection
2017-12-17 20:45:08 -05:00
Will 0debc0a4d3 [V3 Core] Add blacklist/whitelist commands (#1160)
* Add blacklist/whitelist

* Don't let owners add themselves to the blacklist
2017-12-18 12:41:11 +11:00
Will bc8b9d32db [V3 Launcher] Use existing logic, fix bugs (#1168) 2017-12-18 12:31:05 +11:00
palmtree5 73d68e926d [V3 Mod] fix error with [p]names (#1188)
* [V3 Mod] fix error with [p]names

* [V3 Mod] add null cleaner to names command
2017-12-17 20:23:35 -05:00
palmtree5 ba5b18dfe8 [V3 Filter] Fix typo (#1186) 2017-12-17 20:10:36 -05:00
Will be591d7c65 [V3 Sentry] Fix sentry logging (#1169) 2017-12-12 22:34:34 -05:00
Will b34a58e521 [V3 Dev] Fix REPL output (#1170) 2017-12-13 14:30:13 +11:00
palmtree5 4f0043b805 [V3 Mod] fix some issues relating to ignore (#1166)
* [V3 Mod] remove unnecessary decos from ignore/unignore

* [V3 Core] fix is_mod and is_admin so they don't return True if the mod/admin roles aren't set
2017-12-12 20:31:12 -05:00
aikaterna 0a0f2a9dcc [V3 CustomCom] Update cc list for V3 (#1149)
Fix for #1087.
2017-12-09 19:55:09 -05:00
Will 50c9e7767d [V3 Dev] Fix mock command (#1156) 2017-12-09 19:44:34 -05:00
retke a53f284c88 [V3] Fix typo in launcher menu (#1153) 2017-12-09 19:03:40 -05:00
Vicente Rivera ee0d1d269c [V3 Streams] Fix race issue on init (#1135)
* Fix for #1132

Fixes `self.streams` being a `Task` object instead of a list. 
Also replicated for `self.communities`, since the issue is the same 
(although untested, it can be inferred).

* Implement sub-method to avoid init errors

The new method waits for `streams` and `communities` to be initialized
before running the `_stream_alerts` method, avoiding possible errors
due to lists being uninitialized

* Fix streams and communities loading

* Delete IDE config file
2017-12-09 18:58:01 -05:00
Will 6d1d699059 [V3] Actually add compatibility with 3.5.1 (#1155)
* Fix 3.5.1 issue with TYPE_CHECKING

* I hate you

* Smarter...
2017-12-09 18:51:35 -05:00
Will 02d7193a92 [V3 Downloader] Fix non relative data path (#1150) 2017-12-08 20:09:23 -05:00
Tobotimus ef7216722f [V3] Clean up shutdown exceptions (#1141) 2017-12-08 19:24:57 -05:00
palmtree5 878d10a1e2 [V3 Core] allow set game to unset the game (#1146) 2017-12-07 16:17:47 +01:00
Kowlin d8bb18c07d [V3 Docs] Removal of Static CSS to fix Sphinx theme (#1144) 2017-12-06 08:45:20 -05:00
palmtree5 18853d0c86 [V3] bump version to 3.0.0b4 (#1139) 2017-12-03 22:11:30 -09:00
palmtree5 648a1a1893 [V3 Launcher] add launcher (#1110)
* [V3 Launcher] add launcher

* [V3 Launcher] move extras selection to its own function

* Add distro to requirements

* [V3 Launcher] platform.linux_distribution -> distro.linux_distribution

* [V3 Launcher] add methods of setting cli flags to be passed

* [V3 Launcher] pass remaining args not known to launcher's argument parser to redbot

* [V3 Launcher] handle KeyboardInterrupt in launcher

* [V3 Launcher] undo something that would break stuff

* [V3 Launcher] remove co-owners from interactive mode redbot cli flag selection

* [V3 Launcher] clarify the disable console interaction option
2017-12-03 22:09:22 -09:00
palmtree5 52f264dae6 [V3 Streams] Update picarto stream thumbnail URIs for new load-balanced thumbnails (#1130) 2017-12-03 22:04:42 -09:00
Tobotimus 9dbf56f942 [Config] Retrieve/save values with async context manager (#1131)
* [Config] Retrieve/save values with async context manager

* Add a little docstring

* Documentation

* Implement async with syntax in existing modules
2017-12-03 18:07:34 -09:00
Tobotimus 9b1018fa96 [V3 JSON Driver] Don't save json if it exists (#1133) 2017-12-03 17:54:24 -09:00
palmtree5 5ebde77747 [V3 Core] add traceback, invite, leave, and servers commands (#1125)
* [V3 Core] add traceback, join, leave, and servers commands

* [V3 Core] rename join to invite
2017-12-03 17:42:00 -09:00
renebulous 66d8ded924 Fixed cleanup pulling more logs than required. (#1128)
Added conditional statement to break loop once number of messages to be deleted has been reached.
2017-12-03 17:30:41 -09:00
palmtree5 183572f312 [V3 Mod&Filter] add tempbans and filtering names/nicknames (#1123)
* [V3 Mod] add tempban command

* [V3 Filter] add name filtering

* [V3 Mod] Modify invite finding to have a max_age param

* [V3 Mod and Filter] regen messages.pot

* [V3 Mod] fill in formatting on tban invite

* [V3 Filter] add on_member_join + refactor logic on_member_update
2017-12-03 17:27:48 -09:00
Kowlin de09a8b7ca [Sentry] Changed logging URL (#1138)
* [Sentry] Changed logging URL

* [Sentry] Updated URL (again, but without a free submodule)
2017-12-03 15:29:06 -09:00
Will 9a98d5aa8f [V3 Help] Fix help for unknown commands (#1137) 2017-12-03 18:02:03 -05:00
palmtree5 e6086bb7b3 [V3 Core] add info command (#1124) 2017-12-03 17:31:20 -05:00
Will 064e9b6bd0 [V3 Help] Convert help command to support embeds (#1106)
* Replace built in help with embedded help

* Make embeds pagify

* Fix thingy

* Fix missing embed permissions
2017-11-26 20:04:26 -05:00
Tobotimus 09ed5e67a6 Handle inability do delete others' messages (#1111) 2017-11-22 21:21:53 -09:00
Tobotimus 2c96844209 Make audit_type optional in casetypes (#1119) 2017-11-22 21:17:42 -09:00
palmtree5 acbb5b1720 Bump version to 3.0.0b3 (#1105) 2017-11-19 14:55:29 -09:00
palmtree5 9bfa390d0c [V3 Filter] handle exception when registering case type (#1108) 2017-11-19 14:49:37 -09:00
palmtree5 69c50591b2 [V3 Mod] Fix unban and case numbering problems (#1101)
* [ModLog] fix case numbering issue

* [Mod] fix unban command
2017-11-19 18:47:30 -05:00
Will 02d3aec33e [V3 Dependencies] Fix travis/gh 429s (#1109)
* Fix travis/gh 429s

* JK this fixes it

* Keep pip updated

* Ok lets just use pip

* ONE...MORE...
2017-11-19 14:43:35 -09:00
Will e983e1cefb Fix shutdown issue with streams (#1107) 2017-11-19 14:32:00 -09:00
Tobotimus b94bad38e7 [V3 Context] Interactive sending of multiple messages (#1081)
* Interactive pages method for context

* Use new methods in dev

* Undo code formatting

* Rename method to be more generalised

* More general arg
2017-11-19 14:21:40 -09:00
palmtree5 8dcace4bfd [Core V3] add instance listing cli flag (#1079)
* [Core] add instance listing cli flag

* Alphabetically sort instance names
2017-11-19 14:17:01 -09:00
Tobotimus 1b6065bb46 [V3 Economy] Update from config changes (#1084) 2017-11-19 18:01:09 -05:00
Will 89981f46b0 Fix reload error handling (#1104) 2017-11-19 13:33:33 -09:00
Tobotimus 7322f0c676 [V3 Mod/ModLog] Fix duplicate cases and allow case creation without audit log perms (#1102)
* Use ban/unban queue

* Refactor unban's cmd help

* Better support for no audit log perms
2017-11-19 13:23:47 -09:00
Tobotimus 5cef3e13e1 [V3 Docs] Docs for utils package (#1085)
* Docstrings for chat formatting

* Docstrings for mod utils

* Type checking

* Override CSS to highlight object name in definition

* More typing

* Utils docs pages

* Fix typo here
2017-11-19 13:14:05 -09:00
Twentysix b141729830 [V3 Mod] Fix DMs not being handled on_command (#1086) 2017-11-17 20:43:49 +01:00
Tobotimus b348a879c3 [V3] Remove mentions of Red being in Alpha and update README (#1083)
* Remove mentions of alpha version

* Update README.rst

* Give the option for git build in README
2017-11-16 14:12:18 -09:00
SML d2742cbe6e [V3 Docs] Fixed incorrect link in description for Cog-Creators/Red-DiscordBot#47 (#1092) 2017-11-14 14:08:01 -09:00
Tobotimus fb0be051aa [V3 Modlog] Modlog layout and formatting changes (#1089)
* Modlog layout and formatting changes

* Remove unused import
2017-11-14 13:59:34 -09:00
Tobotimus 14ba572acd [V3] Update CODEOWNERS (#1090)
* Update CODEOWNERS

* Add rpc.py entry

* fill in files with no entry in codeowners
2017-11-13 19:41:06 -09:00
Will 46e37d5ff5 Fix typing module for 3.5.1 (#1080) 2017-11-07 13:15:47 -09:00
palmtree5 1ef62b5e32 Bump version to 3.0.0b2 (#1078) 2017-11-05 16:05:47 -09:00
palmtree5 d6fce3c145 [Mod] fix duplicate cases on ban/unban (fixes Cog-Creators/Red-DiscordBot/issues/1052) (#1064) 2017-11-05 16:02:45 -09:00
Tobotimus 897adbf5ac [Trivia] [WIP] V3 Rewrite (#915)
* Rewritten basic settings

* Ported to V3

* Will saves the dicts

* TriviaSession uses Config

* wait_for is the future

* Out with recursion and redundancy

* Remove typing before first question

* Added payout multiplier setting

* Payout setting uses appropriate check

* Implement actual paying of winner

* Removed trivia lists from repository

* Added payout confirmation message

Also rearranged the order of methods in TriviaSession to better represent the sequential order of running trivia

* Contestant count fixed

Also fixed error when lists folder is missing

* Support for multiple categories per session

* Extra error handling

* Update from rebase

* Use of task cancel

* Nicer docstrings

* Oops

* Better imports

* YAML lists

* Using the trivia list repo (YAY)

* Cast all answers to string since YAML is dumb

* session.stop() is not an async function

* Remove redundant attribute from session

* Sessions manage their own tasks

* Add `redbot/trivia` to .gitignore

* Add PyYAML to requirements.txt

* Parse answers properly before checking

* Add Red-Trivia to reqs

* Better task management and some optimisations

Sessions now just use a flat dict for settings instead of config. This means the settings can't be changed after the session is started, but it removes the need for config to be read for every question.

* Allow lists to override settings

* Fix config logic

* Iteration fixes, config override fixes, task management fixes

* Don't hide dict abuse

* Stats tracking

* Leaderboard implemented

* [leaderboard] ignore self and reverse list

* [leaderboard] Handle empty score counter

* Only count win when max score is reached
2017-11-05 15:56:55 -09:00
aikaterna 0959aebd10 Update userinfo to display webp avatar images (#1075) 2017-11-05 15:20:17 -09:00
zephyrkul 33f124263d [V3] Add pagify priority option (#1069)
Allows setting pagify to prioritize earlier delims over later ones.
2017-11-05 13:20:22 -05:00
Will 73469f070c [V3] Fix Windows start screen issue (#1058)
* Add colorama init

* Remove sqrts in favour of crossed boxes (#3)

* Detect stdout encoder's support for sqrt sign (#4)
2017-11-05 13:13:48 -05:00
palmtree5 32372ea237 [V3] Standardize to ctx.send_help() (#1077) 2017-11-05 13:09:02 -05:00
aikaterna ef6dbee516 [V3 Core] Moved [p]cogs command to CogManager (#1076)
* Move cogs command to CogManager

* Move cogs command to CogManager

* self.bot -> ctx.bot

* Typing

* Missing import
2017-11-05 13:05:29 -05:00
aikaterna 2c6af90703 [V3 Downloader] Pagify cog and repo lists (#1072) 2017-11-03 19:11:36 -04:00
Jay Turner dc4fb6d7c3 Added "git+" to install command under "Create a cog" docs (#1073) 2017-11-02 16:43:21 +01:00
Will 1a89eba9e6 [V3] Explicitly define aiohttp version to avoid conflicts (#1070) 2017-11-01 21:44:05 -04:00
Will 1490b0dcbe [V3 RPC] Handle shutdown gracefully (#1071) 2017-11-01 21:40:44 -04:00
palmtree5 edabd07719 [V3 Customcom] i18n support (fix Cog-Creators/Red-DiscordBot/issues/1018) (#1065) 2017-10-29 11:32:05 -04:00
palmtree5 ad0c75866f [Modlog] bugfix for case type enabled/disabled status (#1046) 2017-10-27 16:58:05 -08:00
Will f459a21bef [V3 RPC] Add basic RPC functionality (#1017)
* Add basic RPC functionality

* Add load/unload/reload rpc commands

* Reorganize without rpc_ready event

* Remove rpc ready event

* Removed bot reference from rpc module

* Close RPC server cleanly

* refactor bot

* Refactor a bit and make RPC server initialization based on a cli flag

* Fix version resolver

* standardize version getters

* Pick a new port number
2017-10-27 20:55:41 -04:00
palmtree5 8d8e1c61d8 [V3 Mod] Fix exception registering unchanged case types (#1059)
* [V3 Mod] handle RuntimeError from registering unchanged case types

* [Mod] drop unnecessary except
2017-10-27 20:43:42 -04:00
Twentysix cee92e1cd2 [Streams] [WIP] Rewrite (#782)
* [Streams] [WIP] Rewrite

* [Streams] [WIP] Settings related commands

* [Streams] Moved to Config

* [Streams] Added [p]streamalert stop

* [Streams] Added toggleable autodeletion

* [Streams] Added [p]streamalert list

* [Streams] beam.pro -> Mixer

* V3 streams modifications (#847)

* [Streams] implement mention command

* [Streams] implement mentions in stream alert check

* [Streams] move to 3 separate commands for alert mentions

* [Streams] implement support for alerting for twitch community streams… (#849)

* [Streams] implement support for alerting for twitch community streams (Twentysix26/Red-DiscordBot/issues/824)

* [Streams] async getter implementation

* [Streams] repr for TwitchCommunity class

* [Streams] move and fix imports (#994)

* [Streams] function rename due to duplicate names

* [Streams] drop force_registration

* [Streams] fix command not displaying help
2017-10-27 16:28:51 -08:00
Jori van Ee 2ab910e3e9 Update economy.py (#954)
* Update economy.py

* Update README.md

Add crowdin badge to readme
2017-10-27 16:15:16 -08:00
Will 09b3642559 [V3 Cog/Data Manager] Bundled Cog Data (#1063)
* Refactor find_spec out of core_commands

* Fix version error when not installed

* initial

* Fix find_cogs call

* Enable copying

* Add helper method for cog creators

* Add warning

* My dpy skillz need work
2017-10-27 20:06:47 -04:00
palmtree5 77e29ff43b Add issue and pull request template (#1012)
* Add issue and pull request template

* Remove 'no support questions' from issue template

* Remove 'no support questions' from CONTRIBUTING.md
2017-10-25 18:46:08 -08:00
Will 9394b4880e [V3 Docs] Add data manager information (#1056)
* Add Data Manager docs

* Add rst file

* Add note on data manager's purpose
2017-10-24 20:38:27 -08:00
Will 923913f63d Fix image loading issue (#1057) 2017-10-24 20:35:05 -08:00
Will fed115996c Fix missing awaits (#1055) 2017-10-24 18:53:10 -08:00
Redjumpman 10647f14b2 Fix for Start Screen (#1050)
Fixes #1045
2017-10-24 12:27:13 -08:00
Will 6f0b3fb669 [V3] Bump version to 3.0.0b1 (#1044) 2017-10-22 21:53:58 -04:00
palmtree5 afc30dd1c3 [V3 Docs] Add docs on i18n (#1030) 2017-10-22 21:24:24 -04:00
Will d346216fa2 [V3 Downloader] List all loaded and unloaded cogs (#1019)
* Working without core cogs

* Working with core cogs

* Fix path search logic

* Fix docstring

* Type fix
2017-10-22 21:13:23 -04:00
palmtree5 3febc94871 [V3] migration docs (#992)
* [Docs] start on migration guide

* [Docs] add more to migration docs

* [Docs] fix imports in examples

* [Docs] add migration guide to toctree

* [Docs] add a cog creation guide

* [Docs] expand on cog packages in migration guide

* Fix typo

* [Docs] add link for modlog docs
2017-10-22 21:05:47 -04:00
palmtree5 fb125ef619 [V3] Mod initial rewrite (#1034)
* Readd work due to redoing branch

* [modlog] Move to core and start work on separating it from cogs

* More work on modlog separation

* [Core] Finish logic for modlog, do docstrings, async getters

* [Core] Add stuff to dunder all

* [Docs] Add mod log docs

* [Core] Move away from dunder str for Case class

* [Docs] don't need to doc special members in modlog docs

* More on mod log to implement commands

* More work on Mod

* [Mod] compatibility with async getters

* [Tests] start tests for mod

* [Tests] attempted fix

* [Tests] mod tests passing now!

* [ModLog] update for i18n

* modlog.pot -> messages.pot

* [Mod] i18n

* fix getting admin/mod roles

* Fix doc building

* [Mod/Modlog] redo imports

* [Tests] fix imports in mod tests

* [Mod] fix logger problem

* [Mod] cleanup errors

* A couple of bug fixes

Async getters, some old `config.set` syntax

* Filter ignores private channels

* Fix softban

Was still relying on default channels

* Actually ignore private channels

* Add check for ignored channels

* Fix logic for ignore check

* Send confirm messages before making case

* Pass in guild when setting modlog

* Thanks autocomplete

* Maintain all data for case

* Properly ignore softbans in events

* [Mod] bugfixes

* [Mod] more changes

* [ModLog] timestamp change

* [Mod] split filter and cleanup to their own cogs + regen messages.pot

* [Cleanup] change logic

* [Cleanup] increase limit for channel.history

* [Mod] await getter in modset banmentionspam

* [Mod] attempt duplicate modlog message fix

* [Mod] get_user -> get_user_info

* [Modlog] change reason command so the case author can edit their cases (#806)

* [Modlog] make reason command guild only

* [Modlog] clarify the reason command's help

* [Mod] package path changes + numpy style docstrings for modlog

* [Mod] change ban and unban events to need view audit log perms to find/create a case

* [Modlog] refactoring

* [Filter] add autoban feature

* [Mod] update case types + event changes

* [Mod/Modlog] fix tests, fix permissions things

* [Docs] fix up modlog docs

* Regenerate messages.pot
2017-10-22 21:02:16 -04:00
Tobotimus fe61ef167e [V3 Config] Remove redundancies and update old docs Re:#1033 (#1039)
* Remove MemberGroup class and _super_group method

Also found some docstrings which were missing stuff

* Update documentation
2017-10-22 20:57:06 -04:00
palmtree5 3b96e94992 [V3 Docs] fix install commands (#1043)
* [Docs] fix install commands

* [Docs] update with option of installing from github
2017-10-22 20:40:12 -04:00
Will 5d48e6f3b1 [V3 Config] Add MongoDB driver (#972)
* Basic Mongo Driver

* Update docstrings

* WIP motor support

* Use motor

* Update docs, add selective importer

* Make use of selective importer

* Fix docs

* Fix config storage location for JSON

* Add delimiters in the drivers doc section

* Make async things async

* Add basic config information for mongo driver

* get info from basic setup into config

* IT WORKS

* Add dependency for RJM's PR.
2017-10-20 19:12:45 -04:00
Redjumpman 6f103174aa V3/start screen (#1038)
* Added new start screen

* Added Bordered util

Bordered function required for boxes in start screen

* Update events.py

Added Color to the Title
Added Shard count

* Update events.py

Added Discord.py version
Added package checking for docs and tests
Added package checking for voice

* Update chat_formatting.py

Cleaned up the border function a bit.
2017-10-20 11:29:55 -08:00
Tobotimus 815678584f [V3 Config] Redesign "all_from_XXX" and "clear_all" methods (#1033)
* Added alternative to all_from_kind

* Returned dicts include default values

Also added docstrings

Also removed all_globals since it's kind of redundant and it wasn't working out for me

* Refactored clear_all

* Tests

* Tests again..

* Make all new methods coroutines
2017-10-19 23:22:58 -04:00
Redjumpman 13fef45e06 [V3] Fix for pagify (#1036) 2017-10-19 23:13:01 -04:00
Will 5cfa7b6ed1 [V3 DataManager] Add some helper methods for interacting with bootstrapping configuration (#1029)
* Some helpers

* Add dunder all
2017-10-17 22:05:49 -04:00
Tobotimus c80684a129 [V3] NumPy Docstrings (#1032)
* ALL THE DOCSTRINGS

* Remove imports in drivers package

* Fixed build warnings
2017-10-17 22:01:59 -04:00
Will 684004d614 [V3] Add sharding (#1027)
* EZ PZ sharding

* Add this little nugget
2017-10-16 19:54:55 -04:00
Aioxas 4d7f065b10 [Alias V3] Corrected functions & spelling (#1023)
As discussed with Will in Discord.
2017-10-16 18:27:02 -04:00
Kowlin d1d8711f60 Updated Codeowners (#1026)
* Updated Codeowners

* Added new cogs to Codeowners
2017-10-16 14:14:15 -08:00
Nick Rodriguez f0821776a9 Fix #936 (#1022) 2017-10-16 14:03:27 -08:00
Kowlin 5c7361b95f Attempt at fixing build errors. (#1025) 2017-10-16 11:27:27 -08:00
Tobotimus 980a1a452c [V3 Dev] Various fixes and improvements to Dev (#981)
* Include discord in [p]debug env

* Typecast eval output to string

* Use globals instead of locals for debug

* Fix up storing last result and non-string results

* Cleanup code and better help messages
2017-10-15 22:45:09 -04:00
palmtree5 4993c5a675 [V3 Docs] Add install guides to the documentation (#1005)
* [Docs] add install guides to the documentation

* formatting changes
2017-10-15 22:40:57 -04:00
Tobotimus 86b18c702c [V3] Custom context class (#988)
* Create custom context class

* Documentation

* Remove old help method, replace with new

* Update from rebase
2017-10-15 21:02:50 -04:00
palmtree5 36b3fbd5bc [V3 CustomCom] Initial V3 implementation (#1003) 2017-10-15 20:50:55 -04:00
Will d9a63b45d4 [Docs] Fix imports in Config (#1015) 2017-10-15 20:13:25 -04:00
Will 4ddd576315 [V3 Admin] Rewrite of Squid-Plugins Admin cog (#825)
* Add/remove roles

* Announcement

* Edit role stuff

A bit of refactoring

* Selfrole stuff

* Add announce ignore capabilities

* announce configurations

Announcement fixes

* Serverlock initial commit

* Add some admin tests

better test

* Update for new config

* Add user hierarchy checks

* Fix tests

* Update from rebase

* Fix config getter

* Fix async getters/selfrole
2017-10-14 18:05:08 -04:00
palmtree5 fc36dae54f [V3] Add voice install option and instructions in README (#979)
* [V3] add voice option to setup.py + instructions in readme

* Fix typo
2017-10-01 13:25:32 -04:00
Tobotimus 31395d9efc [V3 Core] Fix reload of core cogs (#980)
* Fix reload of core cogs

* Remove trailing whitespace
2017-10-01 13:20:21 -04:00
Will ea4aaf61c1 [Cog Manager] Fix cog manager paths command (#976) 2017-09-27 22:01:35 -04:00
Will cf77eb2e47 [Core] Fix loading of cogs on initial startup (#971) 2017-09-09 15:27:05 -04:00
Will 5ae6fe2dda Potential docs fix #2 (#970) 2017-09-08 19:45:40 -08:00
Will 7c3b2673a5 [Docs] Fix docs post pip install refactor (#969)
* Fix downloader

* Fix bank

* Fix cog manager

* Fix config

* Fix readme

* Add docs/test link to readme

* Add docs codeowners
2017-09-08 23:31:32 -04:00
Will d69fd63da7 [V3 Everything] Package bot and write setup scripts (#964)
Ya'll are gonna hate me.

* Initial modifications

* Add initial setup.py

* working setup py help

* Modify setup file to package stuff

* Move a bunch of shit and fix imports

* Fix or skip tests

* Must add init files for find_packages to work

* Move main to scripts folder and rename

* Add shebangs

* Copy over translation files

* WORKING PIP INSTALL

* add dependency information

* Hardcoded version for now, will need to figure out a better way to do this

* OKAY ITS FINALLY FUCKING WORKING

* Add this guy

* Fix stuff

* Change readme to rst

* Remove double sentry opt in

* Oopsie

* Fix this thing

* Aaaand fix test

* Aaaand fix test

* Fix core cog importing and default cog install path

* Adjust readme

* change instance name from optional to required

* Ayyy let's do more dependency injection
2017-09-08 23:14:32 -04:00
Tobotimus 6b1fc786ee [Dev V3] mockmsg command (#928) 2017-09-04 01:49:49 -04:00
palmtree5 48e36d3ca1 [V3 docs] Add a tutorial for Config and fix Bank docs (#959)
* [V3 docs] Add a tutorial for Config

* fix missing colon

* Add some links to the actual methods

* Fix bank docs
2017-09-04 01:13:33 -04:00
Will ff1864779a [i18n] Make locale switching permanent (#962)
* remove unused import

* Make set locale permanent

* Add codeowner
2017-09-03 20:36:01 -08:00
Will 73643f84ae Logic error (#960) 2017-09-03 19:12:28 -08:00
Pier-Angelo Gaetani 51fe1411cd [i18n] Spanish translation (#949)
* [i18n] Initial spanish translations.

* [i18n] Minor correction.

* [i18n] Character corrupted fix.

* [i18n] File info filled, author name corrected.

* [i18n] Economy corrections.

* [i18n] General, corrupted character and question/exclamation mark corrections.

* [i18n] Economy, question/exclamation mark corrections.

* [i18n] Core translations added.

* [i18n] One too many newlines.
2017-09-01 23:38:36 -04:00
Kowlin 409ac569b2 Update Crowdin configuration file 2017-08-30 18:18:32 +02:00
Will 118df46630 [i18n] Basic Implementation (#948)
* Initial commit

* Beginning of working i18n

* Add some translation files

* Add more strings to translate

* Update and add some more translations

* Update spanish translation

* Update french translation

* Add alias translation templates

* Add bank translations

* Add economy translations

* Add general translations

* Add image translations

* Add core translations
2017-08-26 18:54:51 -04:00
Will 3d76f3a787 [Core V3] Make the bot data path configurable (#879)
* Initial commit

* Fix sentry

* Make cog manager install path work relative to the bot's dir

* Fix downloader to save data relative to the defined data folder

* Fix sentry test

* Fix downloader tests

* Change logfile location

* Add another line to codeowners

* Basic tests

* Fix versioning

* Add in FutureWarning for config file changes

* Add reference to issue
2017-08-20 15:49:51 -04:00
Jori van Ee b7f1d9ed1a Update main.py (#934)
* Update main.py

Move discord import to the beginning of file, aswell as the version check, if the version wasn't atleast major_version 1 it would give an exception in the core imports (bot.Guilds isn't defined)!

* Move sys import up
2017-08-19 11:09:28 -08:00
aikaterna cd32932b75 Added await to set for currency name (#935) 2017-08-19 10:36:11 -08:00
Tobotimus 2700a005d4 [Core V3] Fix reload (#927) 2017-08-15 19:46:31 -08:00
Tobotimus 115418d323 [Core V3] Fix checks (#924)
* Fix global checks

* Fix bank's checks

Predicates for decorators return true or false, they don't return other decorators

* Async getters in core checks
2017-08-15 14:09:57 -08:00
zephyrkul 2a19f151fc [Core V3] Fix pagify bug (#920)
* Let's try this again...

* accidentally a colon
2017-08-15 00:42:48 -04:00
Will fa5a1f9c19 [Docs] Config fix (#921) 2017-08-14 14:53:11 -08:00
Will da28630644 [Config] Modify config's all methods to provide default values (#916)
* Add in functionality for Tobotimus

* Cover all_guilds

* Make it obvious

* Fix auto rename of docstrings

* Fix downloader docs warning
2017-08-14 11:56:53 -08:00
Will 248d2baa2a [Config] Fix get_attr with awaited getters (#912) 2017-08-13 19:02:38 -04:00
Will c6762234e6 [Docs] Update downloader framework docs (#914)
* Update installable

* Update Repo manager
2017-08-13 19:00:10 -04:00
palmtree5 0ba6d9a5af [Image] Rewrite for V3 (#768)
* [Core] add imgurpython to requirements

* [Image] v3 rewrites

* remove imgurpython from requirements

* [Image] switch to Config, add in instructions for getting imgur client id

* Add default register
2017-08-13 16:14:45 -04:00
palmtree5 680a44c4b4 [Core] Add shutdown command (#911) 2017-08-12 16:41:25 -08:00
Will f78c33445c [Docs] Cog Manager (#901)
* Cog manager docs

* Oops, kinda need this
2017-08-12 14:03:28 -08:00
Will 85b0f34395 This is actually awesome! (#909) 2017-08-11 19:53:05 -08:00
Will f6cbe82848 Damnit (#908) 2017-08-11 18:55:35 -08:00
palmtree5 fd684bdb58 [Docs] Add bank docs (#900)
* Add bank docs

* [Docs] fix bank docstrings for formatting

* [Docs] add bank to toctree

* rename and make bank rst use members

* Formatting changes

* Add account to dunder all
2017-08-11 21:59:27 -04:00
Will 96a93e00aa Fix Edit on Github button (#904) 2017-08-11 17:51:17 -08:00
Will de912a3cfb [Config] Asynchronous getters (#907)
* Make config get async

* Asyncify alias

* Asyncify bank

* Asyncify cog manager

* IT BOOTS

* Asyncify core commands

* Asyncify repo manager

* Asyncify downloader

* Asyncify economy

* Asyncify alias TESTS

* Asyncify economy TESTS

* Asyncify downloader TESTS

* Asyncify config TESTS

* A bank thing

* Asyncify Bank cog

* Warning message in docs

* Update docs with await syntax

* Update docs with await syntax
2017-08-11 21:43:21 -04:00
Will cf8e11238c [Docs] Copy over config docs from red-api-docs (#899)
* Update config.Config docs

* Set group docstrings

* Update Value docs
2017-08-11 01:39:43 -04:00
Will 7e05903c61 [Docs] The beginning of the reign of autodoc (#898)
* Update gitignore

* Add docs basic config

* Add config options for rtd and autodoc

* Add requirements.txt and update conf to support coros

* Add downloader cog docs

* Add downloader reference docs

* Add config, apparently invalid rst syntax breaks a lot of shit
2017-08-11 00:14:42 -04:00
Will 13cabfbad7 [Core] Add multiple/external cog paths support (#853)
* WIP cog path manager

* Initial working state

* Get real reloading working

* Type error thingy

* And fix the tests

* Start UI shit

* path reordering

* Add install path getter/setter and fix config syntax

* Determine bot directory at runtime

* Add UI commands for install path

* Update downloader to use install path

* Add sane install path default

* Make evaluation of cog install path lazy

* Some typing fixes

* Add another line to codeowners

* Conditionally put install path in paths

* Always put install path first

* Dont allow people to add the installdir as an additional path, guarantee install dir isn't shown with paths command

* Make shit update loaded cogs

* Add tests

* Another one
2017-08-10 23:09:49 -04:00
Will 0651a6ddc3 [Bank/Economy] Fix leaderboard bug due to previous config PR (#894) 2017-08-09 22:00:30 -04:00
Twentysix 9a1064c81d [Core] Added [p]contact and [p]dm (#875)
* [Core] Added [p]contact and a way to DM users through Red

* Turned reply feature into [p]dm command

* Better docstring
2017-08-09 21:48:50 -04:00
Will d4da9edb3e [Config] Fix 'all' handling to match docs (#889)
* Fix some stuff to match docs

* For Palm__ <3
2017-08-09 21:39:19 -04:00
palmtree5 4923ffe98a [Economy] [WIP] rewrite (#781)
* [Economy][Bank] redo branch

* WIP

WIP

* Implement all current bank commands API calls

* Set dunder all and put into bot

* make core change to economy

* Add is_global method to bank

WIP

* Add extra bank API commands

* Update bank UI

Update some imports

Remove bank UI errors file

Typing thing

* Update bank get_global_accounts and touch up economy some more

Do some more economy updates

* Remove bank from bot

* Another passing test

FINALLY

* Fixy type things

Last fixes for now

Fix arg to toggle global

RJM

Invalid bid amount handler

cooldown msg

currency name fix

Fix fun bug

ANother bug

And payday limit

* PEP8 stuff

* Docstring change

* Fix this thing

* [Economy][Bank] redo branch

* [Economy][Bank] modify guild owner or bot owner check, add admin or bot owner check for global vs local bank

* [Economy] apply admin or bot owner check to [p]economyset

* Make some public things private

* [Economy] lots of refactoring for conditional permission checks and guild checks + supporting global economy

* And working stuff

* Fix Kowlin's bug

* Fix slot bugs
2017-08-09 17:23:41 -08:00
Will 99bfb2fc7a [Config] Rewrite (#869) 2017-07-31 01:40:31 +02:00
Kowlin 5c2be25dfc [Sentry] Cleared out websocket breadcrumbs (#870)
This adds additional protections to make sure no sensitive information gets caught in our Sentry error logger.
2017-07-28 00:24:09 -04:00
Twentysix b1601b1bf0 [Dev] server -> guild in dev commands 2017-07-27 01:33:40 +02:00
Twentysix be5c7f4592 [Core] Co-owners cli flag only, implemented owner cli flag
After giving it further thought, I don't believe co-owners really need to be a command, as it is unlikely that co-owners will need to be changed often enough.
Furthermore, this gives a further layer of protection to people who like to gloss over warnings.
2017-07-25 01:48:13 +02:00
Will 2fa5792f69 [GitHub] Contributing guidelines (#864)
Add `CONTRIBUTING.md` to the project.
2017-07-22 22:55:47 -04:00
Twentysix26 74910a490b [Core] Fixed [p]set owner 2017-07-19 11:30:40 +02:00
Will 19c69aaca6 Added CODEOWNERS file (#848) 2017-07-15 14:59:51 +02:00
Will d8710f0c7d [Downloader] [p]findcog: Find a cog from a command (#855) 2017-07-12 23:41:22 +02:00
Kowlin 150de9ed6f Revert "Added Dev_commands to the Sentry logger (#826)" (#831)
This reverts commit b483e24e33.
2017-06-30 17:03:09 +02:00
Kowlin b483e24e33 Added Dev_commands to the Sentry logger (#826) 2017-06-30 16:55:30 +02:00
Twentysix 2d02dcf682 [Dev] Cast repl output to str before sending 2017-06-24 20:41:02 +02:00
Will 8fa967cb91 Added Alias cog (#780) 2017-06-21 22:59:26 +02:00
Will 80756ba490 [Core] Add dynamic versioning based on git tag (#790) 2017-06-18 02:18:08 +02:00
Twentysix 03791b9fbc [Downloader] Cleaned up commands' docstrings, del -> delete 2017-06-18 01:50:41 +02:00
Twentysix feffb56847 Fill out license info 2017-06-18 01:32:51 +02:00
Will 53810b2262 Added Downloader cog (#786) 2017-06-18 01:31:32 +02:00
Twentysix b12a41cd77 [Dev] Fixed [p]repl, sanitize [p]eval output 2017-06-17 19:12:53 +02:00
Will 9b4581a781 [Core] Fixed [p]set owner and [p]set avatar (#817) 2017-06-17 17:31:44 +02:00
Will 7b91bc0633 [Dev] Added [p]repl and [p]eval (#814) 2017-06-16 21:00:32 +02:00
Will 94cfd23c00 [Core] Add Sentry logger for core cogs data gathering only (#813) 2017-06-16 20:48:00 +02:00
Will 422bbba7f6 [Config] Fix get() functionality (#815) 2017-06-16 20:35:32 +02:00
Will 68bc6e3325 [Core] Check for correct discord.py version at boot (#799)
Fixes #798
2017-06-09 19:22:36 +02:00
Twentysix c5ab97ce0d [Core] Fixed owner request's author not showing up 2017-06-04 19:53:12 +02:00
Twentysix 35c88084ba [Core] Ported [p]set commands, added [p]set coowners 2017-06-04 19:37:39 +02:00
Twentysix 0fc4939a07 [Utils] Fixed pagify 2017-06-03 05:34:48 +02:00
Will 82d9457647 Sentry error logging (#784) 2017-05-29 22:43:00 +02:00
Twentysix e469ee201b Added .tmp and .data to .gitignore 2017-05-28 23:26:52 +02:00
Will 3988fbbc09 [Core] Replaced JsonDB with Config (#770) 2017-05-28 04:28:59 +02:00
palmtree5 a8745297dc [General] Initial porting (#757)
Polls have been removed for now and they will be remade in the future (maybe even as a separate cog)
2017-05-14 17:12:32 +02:00
Twentysix 311339240f [Core] Added separate dev cog
This is enabled with the cli flag --dev
2017-05-14 03:20:54 +02:00
Twentysix cf2925978b [Core] Interactive configuration 2017-05-13 23:55:14 +02:00
Twentysix 592751884e [Core] Reworked intro and added oauth url 2017-05-01 03:23:05 +02:00
Twentysix 51ce2d82d6 [Core] Added relative_path parameter to json helpers
Since these helpers will mostly be used by packages, it's important to make sure that the data they create stays contained inside them. This also brings the additional benefit of being able to manipulate data inside a package without knowing the name of the package's folder itself
2017-04-30 05:12:00 +02:00
Twentysix ba9d4b7f0f [Core] Implemented missing checks, extended DB
The DB has been extended and now covers the functionality of the old Settings class of the previous version
2017-04-30 00:28:56 +02:00
Twentysix 9fc4e54ece [Core] Removed flusher, helpers now save on changes
After some considerations, while the flusher was an interesting experiment, it doesn't seem to be reliable enough. It's been removed in favor of the helpers autosaving on any change in a threadsafe way.
2017-04-29 19:26:34 +02:00
Twentysix bd341f1875 [Core] Properly end tasks and process flusher's queue on quit 2017-04-28 18:13:02 +02:00
Twentysix b113a94c52 Added requirements.txt and LICENSE, removed duplicate file 2017-04-28 09:16:10 +02:00
Twentysix 294adf270f [Core] Save package status and restore it on boot
Also better error handling on package loading
2017-04-28 09:16:10 +02:00
Twentysix 1d3b541e8f [Core] Handle connection errors, fetch token from env var / db
Also reimplemented the old status codes
2017-04-28 09:16:10 +02:00
Twentysix cc1d7b2b59 [Core] Check for coowners in the db 2017-04-28 09:16:10 +02:00
Twentysix 36b19de9da [Core] Moved checks.py to main core package 2017-04-28 09:16:10 +02:00
Twentysix 2063decbe7 First commit 2017-04-28 09:16:10 +02:00
Twentysix 6251c585e4 Empty commit 2017-04-28 09:15:36 +02:00
578 changed files with 59701 additions and 5276 deletions
-17
View File
@@ -1,17 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
+49
View File
@@ -0,0 +1,49 @@
# Default
* @Twentysix26
# Core
redbot/core/bank.py @palmtree5
redbot/core/checks.py @tekulvw
redbot/core/cli.py @tekulvw
redbot/core/config.py @tekulvw
redbot/core/cog_manager.py @tekulvw
redbot/core/core_commands.py @tekulvw
redbot/core/context.py @Tobotimus
redbot/core/data_manager.py @tekulvw
redbot/core/dev_commands.py @tekulvw
redbot/core/drivers/* @tekulvw
redbot/core/events.py @tekulvw
redbot/core/global_checks.py @tekulvw
redbot/core/i18n.py @tekulvw
redbot/core/json_io.py @tekulvw
redbot/core/modlog.py @palmtree5
redbot/core/rpc.py @tekulvw
redbot/core/sentry_setup.py @Kowlin @tekulvw
redbot/core/utils/chat_formatting.py @tekulvw
redbot/core/utils/mod.py @palmtree5
# Cogs
redbot/cogs/admin/* @tekulvw
redbot/cogs/alias/* @tekulvw
redbot/cogs/audio/* @aikaterna @atiwiex
redbot/cogs/bank/* @tekulvw
redbot/cogs/cleanup/* @palmtree5
redbot/cogs/customcom/* @palmtree5
redbot/cogs/downloader/* @tekulvw
redbot/cogs/economy/* @palmtree5
redbot/cogs/filter/* @palmtree5
redbot/cogs/general/* @palmtree5
redbot/cogs/image/* @palmtree5
redbot/cogs/mod/* @palmtree5
redbot/cogs/modlog/* @palmtree5
redbot/cogs/streams/* @Twentysix26 @palmtree5
redbot/cogs/trivia/* @Tobotimus
# Docs
docs/* @tekulvw @palmtree5
# Setup, instance setup, and running the bot
setup.py @tekulvw
redbot/__init__.py @tekulvw
redbot/__main__.py @tekulvw
redbot/setup.py @tekulvw
+75
View File
@@ -0,0 +1,75 @@
# Introduction
### Welcome!
First off, thank you for contributing to the further development of Red. We're always looking for new ways to improve our project and we appreciate any help you can give us.
### Why do these guidelines exist?
Red is an open source project. This means that each and every one of the developers and contributors who have helped make Red what it is today have done so by volunteering their time and effort. It takes a lot of time to coordinate and organize issues and new features and to review and test pull requests. By following these guidelines you will help the developers streamline the contribution process and save them time. In doing so we hope to get back to each and every issue and pull request in a timely manner.
### What kinds of contributions are we looking for?
We love receiving contributions from our community. Any assistance you can provide with regards to bug fixes, feature enhancements, and documentation is more than welcome.
# Ground Rules
We've made a point to use [ZenHub](https://www.zenhub.com/) (a plugin for GitHub) as our main source of collaboration and coordination. Your experience contributing to Red will be greatly improved if you go get that plugin.
1. Ensure cross compatibility for Windows, Mac OS and Linux.
2. Ensure all Python features used in contributions exist and work in Python 3.5 and above.
3. Create new tests for code you add or bugs you fix. It helps us help you by making sure we don't accidentally break anything :grinning:
4. Create any issues for new features you'd like to implement and explain why this feature is useful to everyone and not just you personally.
5. Don't add new cogs unless specifically given approval in an issue discussing said cog idea.
6. Be welcoming to newcomers and encourage diverse new contributors from all backgrounds. See [Python Community Code of Conduct](https://www.python.org/psf/codeofconduct/).
# Your First Contribution
Unsure of how to get started contributing to Red? Please take a look at the Issues section of this repo and sort by the following labels:
* beginner - issues that can normally be fixed in just a few lines of code and maybe a test or two.
* help-wanted - issues that are currently unassigned to anyone and may be a bit more involved/complex than issues tagged with beginner.
**Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github)
At this point you're ready to start making changes. Feel free to ask for help; everyone was a beginner at some point!
# Getting Started
### Testing
We've recently started adding unit-testing into Red. All current tests can be found in the `tests/` directory at the root level of the repository. You will need `py.test` installed in order to run them (which is already in `requirement.txt`). Tests can be run by simply calling `pytest` once you've `cd`'d into the Red repository folder.
### To contribute changes
1. Create your own fork of the Red repository.
2. Make the changes in your own fork.
3. If you like the changes and think the main Red project could use it:
* Ensure your code follows (generally) the PEP8 Python style guide
* Create a Pull Request on GitHub with your changes
### How To Report A Bug
Please see our **ISSUES.MD** for more information.
### How To Suggest A Feature Or Enhancement
The goal of Red is to be as useful to as many people as possible, this means that all features must be useful to anyone and any server that uses Red.
If you find yourself wanting a feature that Red does not already have, you're probably not alone. There's bound to be a great number of users out there needing the same thing and a lot of the features that Red has today have been added because of the needs of our users. Open an issue on our issues list and describe the feature you would like to see, how you would use it, how it should work, and why it would be useful to the Red community as a whole.
# Code Review Process
We have a core team working tirelessly to implement new features and fix bugs for the Red community. This core team looks at and evaluates new issues and PRs on a daily basis.
The decisions we make are based on a simple majority of that team or by decree of the project owner.
### Issues
Any new issues will be looked at and evaluated for validity of a bug or for the usefulness of a suggested feature. If we have questions about your issue we will get back as soon as we can (usually in a day or two) and will try to make a decision within a week.
### Pull Requests
Pull requests are evaluated by their quality and how effectively they solve their corresponding issue. The process for reviewing pull requests is as follows:
1. A pull request is submitted
2. Core team members will review and test the pull request (usually within a week)
3. After a majority of the core team approves your pull request:
* If your pull request is considered an improvement or enhancement the project owner will have 1 day to veto or approve your pull request.
* If your pull request is considered a new feature the project owner will have 1 week to veto or approve your pull request.
4. If any feedback is given we expect a response within 1 week or we may decide to close the PR.
5. If your pull request is not vetoed and no core member requests changes then it will be approved and merged into the project.
### Differences between "new features" and "improvements"
The difference between a new feature and improvement can be quite fuzzy and the project owner reserves all rights to decide under which category your PR falls.
At a very basic level a PR is a new feature if it changes the intended way any part of the Red project currently works or if it modifies the user experience (UX) in any significant way. Otherwise, it is likely to be considered an improvement.
# Community
You can chat with the core team and other community members about issues or pull requests in the #coding channel of the Red support server located [here](https://discord.gg/red).
+20
View File
@@ -0,0 +1,20 @@
Please be sure to read through other issues as well to make sure what you are suggesting/reporting has not already
been suggested/reported
### Type:
- [ ] Suggestion
- [ ] Bug
### Brief description of the problem
### Expected behavior
### Actual behavior
### Steps to reproduce
1.
2.
3.
4.
+7
View File
@@ -0,0 +1,7 @@
### Type
- [ ] Bugfix
- [ ] Enhancement
- [ ] New feature
### Description of the changes
+148 -40
View File
@@ -1,50 +1,158 @@
# Windows image file caches
Thumbs.db
ehthumbs.db
# Trivia list repo injection
redbot/trivia/
# Folder config file
Desktop.ini
*.json
*.exe
*.dll
.data
# Recycle Bin used on file shares
$RECYCLE.BIN/
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Windows shortcuts
*.lnk
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# =========================
# Operating System Files
# =========================
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# OSX
# =========================
# CMake
cmake-build-debug/
.DS_Store
.AppleDouble
.LSOverride
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
# Thumbnails
._*
## File-based project format:
*.iws
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
## Plugin-specific files:
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
__pycache__
json
cache
+48
View File
@@ -0,0 +1,48 @@
dist: trusty
language: python
cache: pip
notifications:
email: false
python:
- 3.5.3
- 3.6.1
install:
- echo "git+https://github.com/Rapptz/discord.py.git@rewrite#egg=discord.py[voice]" >> requirements.txt
- pip install -r requirements.txt
- pip install .[test]
script:
- python -m compileall ./redbot/cogs
- python -m pytest
jobs:
include:
- stage: Deployment
if: tag IS present
python: 3.5.3
env:
- DEPLOYING=true
before_deployment:
- curl https://artifacts.crowdin.com/repo/GPG-KEY-crowdin | sudo apt-key add -
- echo "deb https://artifacts.crowdin.com/repo/deb/ /" | sudo tee -a /etc/apt/sources.list
- sudo apt-get update -qq
- sudo apt-get install -y crowdin
deploy:
- provider: pypi
user: Red-DiscordBot
password:
secure: Ty9vYnd/wCuQkVC/OsS4E2jT9LVDVfzsFrQc4U2hMYcTJnYbl/3omyObdCWCOBC40vUDkVHAQU8ULHzoCA+2KX9Ds/7/P5zCumAA0uJRR9Smw7OlRzSMxJI+/lGq4CwXKzxDZKuo5rsxXEbW5qmYjtO8Mk6KuLkvieb1vyr2DcqWEFzg/7TZNDfD1oP8et8ITQ26lLP1dtQx/jlAiIBzgK9wziuwj1Divb9A///VsGz43N8maZ+jfsDjYqrfUVWTy3ar7JPUplletenYCR1PmQ5C46XfV0kitKd1aITJ48YPAKyYgKy8AIT+Uz1JArTnqdzLSFRNELS57qS00lzgllbteCyWQ8Uzy0Zpxb/5DDH8/mL1n0MyJrF8qjZd2hLNAXg3z/k9bGXeiMLGwoxRlGXkL2XpiVgI93UKKyVyooGNMgPTc/QdSc7krjAWcOtX/HgLR34jxeLPFEdzJNAFIimfDD8N+XTFcNBw6EvOYm/n5MXkckNoX/G+ThNobHZ7VKSASltZ9zBRAJ2dDh35G3CYmVEk33U77RKbL9le/Za9QVBcAO8i6rqVGYkdO7thHHKHc/1CB1jNnjsFSDt0bURtNfAqfwKCurQC8487zbEzT+2fog3Wygv7g3cklaRg4guY8UjZuFWStYGqbroTsOCd9ATNqeO5B13pNhllSzU=
skip_cleanup: true
on:
repo: Cog-Creators/Red-DiscordBot
branch: V3/develop
python: 3.5.3
tags: true
- provider: script
script: python3 ./generate_strings.py
skip_cleanup: true
on:
repo: Cog-Creators/Red-DiscordBot
branch: V3/develop
python: 3.5.3
tags: true
+3 -3
View File
@@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
Red - A fully customizable Discord bot
Copyright (C) 2015-2018 Twentysix
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
Red-DiscordBot Copyright (C) 2015-2018 Twentysix
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
+5
View File
@@ -0,0 +1,5 @@
include README.rst
include LICENSE
include requirements.txt
include discord/bin/*.dll
include redbot/cogs/audio/application.yml
-144
View File
@@ -1,144 +0,0 @@
# Red - A multifunction Discord bot
#### *Fun bringer, admin helper and music bot*
[<img align="right" title="Art by Supergiant Games" src="https://www.supergiantgames.com/static/images/transistor/cartoon_red.png">](https://www.supergiantgames.com/games/transistor/)
[<img src="https://img.shields.io/badge/Support-me!-orange.svg">](https://www.patreon.com/Twentysix26) [<img src="https://img.shields.io/badge/Official-Server-green.svg">](https://discord.gg/0k4npTwMvTpv9wrh) **< Announcements & Help!**
##**[ [This version is obsolete and no longer being supported. Use the current one] ](https://github.com/Twentysix26/Red-DiscordBot/)**
### Cool title, but what does it do exactly?
A bit of everything. Seriously though:
It has the [most common features](#general-commands) of many chatbots (!flip, !8, stopwatch, etc.), **custom commands** (inspired by Twitch's [Nightbot](https://www.nightbot.tv/)), memes.
It features some games such as **Trivia**, rock paper scissors, [users can earn and play with credits](#economy-commands) in the slot machine.
[The audio part is quite fleshed out](#audio-commands). Users can **stream youtube videos**, create **playlists** that everyone will be able to play and control (previous/next song, pause/resume, shuffle...).
**MP3 and flac files can also be streamed** (see [FAQ](#faq) for details on local playlists)
**Twitch's online notifications**: Red will notify the channels you want whenever you favorite Twitch streamers are online.
As for the moderation tools, it includes a **powerful message filter with regular expression capabilities** and **mass messages cleanup**.
[I'm planning to expand all this much more](#todo-list).
See the [command list](#general-commands) for an even better idea of what this bot can do.
### I don't even know what I'm looking at. How do I install this?
Do not panic. [Enter the wiki and follow the tutorials](https://github.com/Twentysix26/Red-DiscordBot/wiki)!
If you have any issue, consult the [troubleshooting](https://github.com/Twentysix26/Red-DiscordBot/wiki/Troubleshooting) page, and if you're still stuck, [join the official server](https://discord.gg/0k4npTwMvTpv9wrh) so you can get some help.
Once you're done, take a look at the command list and have fun.
### General commands
| Command | Description |
|-----------------------------------------------|--------------------------------------------|
| !flip | Flip a coin |
| !rps [rock/paper/scissors] | Play RPS |
| !proverb | Random proverb |
| !choose [option1 or option2 or option3 (...)] | Random choice. Supports multiple words |
| !8 [question?] | Ask 8 ball a question |
| !sw | Start/stop the stopwatch |
| !trivia | Trivia help and lists |
| !trivia [list] | Start a trivia session |
| !trivia stop | Stop a trivia session |
| !twitch [stream] | Check if stream is online |
| !twitchalert [stream] | Red sends an alert in the channel when the stream is online (admin only)|
| !stoptwitchalert [stream] | Stop stream alerts (admin only) |
| !roll [number] | Random number between 0 and chosen number. |
| !gif [text] | GIF search |
| !imdb [movie/etc] | Retrieve information from IMDB |
| !meme [id;text1;text2] | Create a meme |
| !poll [question;answer1;answer2 (...)] | Start poll in the current channel |
| !endpoll | Stop poll |
| !addcom [command] [text] | Add a custom command |
| !editcom [command] [text] | Edit a custom command |
| !delcom [command] | Delete a custom command |
| !customcommands | Custom commands' list |
| !help | Command list |
| !audio help | Audio command list and playlist explanation.|
| !economy | Explanation of the economy module |
| !admin help | Admin commands list |
| !meme help | Explanation of !meme |
### Audio commands
| Command | Description |
|----------------------------|---------------------------------------------------------------------|
| !youtube [link] | Play a youtube video in a voice channel |
| !sing | Make Red sing |
| !stop | Stop any voice channel activity |
| !play [playlist_name] | Play chosen playlist |
| !playlists | Playlist's list |
| !next or !skip | Next song |
| !prev | Previous song |
| !pause | Pause song |
| !resume | Resume song |
| !replay or !repeat | Replay current song |
| !title or !song | Current song's title + link |
| !shuffle | Mix current playlist |
| !volume [0-1] | Sets Red's output volume |
| !addplaylist [name] [link] | Add a youtube playlist |
| !delplaylist [name] | Delete a youtube playlist. Limited to author and admins |
| !getplaylist | Get the current playlist through DM. This also works with favorites |
| !addfavorite | Add song to your favorites |
| !delfavorite | Remove song from your favorites |
| !playfavorites | Play your favorites |
| !local [playlist_name] | Play chosen local playlist |
| !local or !locallist | Local playlists' list |
| !downloadmode | Enables or disables download mode. (admin only) |
### Admin commands
| Command | Description |
|-----------------------------------------------------------|---------------------------------------------------|
| !addwords [word1 word2 (...)] [phrase/with/many/words] | Add words to message filter |
| !removewords [word1 word2 (...)] [phrase/with/many/words] | Remove words from message filter |
| !addregex [regex] | Add regular expression to message filter |
| !removeregex [regex] | Remove regular expression from message filter |
| !shutdown | Close the bot |
| !join [invite] | Join another server |
| !leaveserver | Leave server |
| !shush | Ignore the current channel |
| !talk | Stop ignoring the current channel |
| !reload | Reload most files. Useful in case of manual edits |
| !name [name] | Change the bot's name |
| !cleanup [number] | Delete the last [number] messages |
| !cleanup [name/mention] [number] | Delete the last [number] of messages by [name] |
| !blacklist [name/mention] | Add user to blacklist. Red will ignore that user |
| !forgive [name/mention] | Remove user from blacklist |
| !setting [setting] [value] | Modify setting |
### Economy commands
| Command | Description |
|-------------|--------------------------------------|
| !register | Register a new account |
| !balance | Check your balance |
| !slot [bid] | Play the slot machine |
| !slot help | Slot machine explanation and payouts |
| !payday | Receive credits |
### FAQ
>I've done everything the README asked me to and it still doesn't work! Were you drunk when you coded this?
You're probably missing something.
Feel free to join [my server](https://discord.gg/0k4npTwMvTpv9wrh) and head to #support to get some help! Oh, and my drinking habits are none of your business.
>Does this bot work on multiple servers?
Sure it does. Should you do it? Maybe. The permissions system is not that great at the moment but if you trust the people running the server it's ok. It's not advisable to send the bot in random servers at the moment.
Custom commands only work in the server they were created in. Same for the message filter. This is by design. Also, remember that the bot can only be in one voice channel at once.
>Will you implement [feature]?
Suggestions are always very welcome.
>How do local playlists work?
Make as many folders as you want inside the localtracks folder. Names must be without spaces. Every folder counts as a different playlist. Every playlist can contain mp3 and flac files. Users can stream them by doing !local [playlist_name] and see the full list
with !local or !locallist. They can also add tracks to their favorites.
>What's download mode?
Everytime you play the audio of a youtube video with download mode on the audio will be first downloaded and stored into the "cache" folder. It is recommended that you use this mode to avoid streaming problems. This is the default mode, you can switch between modes with !downloadmode.
>Why is this bot called Red and the admin role "Transistor"? What's the meaning of !sing?
They're all references to [Transistor](https://www.supergiantgames.com/games/transistor/), a videogame by Supergiant Games.
### TODO List
- [x] [Start rewriting Red](https://github.com/Twentysix26/Red-DiscordBot/tree/develop)
- [ ] ~~Bundle some malware and slowly build up a botnet for world domination~~
+42
View File
@@ -0,0 +1,42 @@
.. image:: https://readthedocs.org/projects/red-discordbot/badge/?version=v3-develop
:target: http://red-discordbot.readthedocs.io/en/v3-develop/?badge=v3-develop
:alt: Documentation Status
.. image:: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
:target: http://makeapullrequest.com
:alt: PRs Welcome
.. image:: https://d322cqt584bo4o.cloudfront.net/red-discordbot/localized.svg
:target: https://crowdin.com/project/red-discordbot
:alt: Crowdin
.. image:: https://img.shields.io/badge/Support-Red!-orange.svg
:target: https://www.patreon.com/Red_Devs
:alt: Patreon
********************
Red - Discord Bot v3
********************
**This is in beta and very much a work in progress. Regular use is not recommended.
There will not be any effort made to prevent the breaking of current installations.**
How to install
^^^^^^^^^^^^^^
Using python3 pip::
pip install --process-dependency-links -U Red-DiscordBot
redbot-setup
redbot <name>
To install requirements for voice::
pip install --process-dependency-links -U Red-DiscordBot[voice]
To install all requirements for docs and tests::
pip install --process-dependency-links -U Red-DiscordBot[test,docs]
For the latest git build, replace ``Red-DiscordBot`` in the above commands with
``git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop``.
+5
View File
@@ -0,0 +1,5 @@
api_key_env: CROWDIN_API_KEY
project_identifier_env: CROWDIN_PROJECT_ID
files:
- source: /**/*.pot
translation: /%original_path%/%locale%.po
-132
View File
@@ -1,132 +0,0 @@
import json
import logging
import os
import glob
default_settings = ('{"TRIVIA_ADMIN_ONLY": false, "EDIT_CC_ADMIN_ONLY": false, "PASSWORD": "PASSWORDHERE", "FILTER": true, "CUSTOMCOMMANDS": true, ' +
'"TRIVIA_MAX_SCORE": 10, "TRIVIA_DELAY": 15, "LOGGING": true, "EMAIL": "EMAILHERE", "ADMINROLE": "Transistor", "DOWNLOADMODE" : true, ' +
'"VOLUME": 0.20, "TRIVIA_BOT_PLAYS" : false, "TRIVIA_TIMEOUT" : 120, "DEBUG_ID" : "IgnoreThis", "POLL_DURATION" : 60, "PREFIX" : "!"}')
default_apis = ('{"IMGFLIP_USERNAME": "USERNAMEHERE", "IMGFLIP_PASSWORD": "PASSWORDHERE", "MYAPIFILMS_TOKEN" : "TOKENHERE"}')
logger = logging.getLogger("__main__")
def fileIO(filename, IO, data=None):
if IO == "save" and data != None:
with open(filename, encoding='utf-8', mode="w") as f:
f.write(json.dumps(data))
elif IO == "load" and data == None:
with open(filename, encoding='utf-8', mode="r") as f:
return json.loads(f.read())
elif IO == "check" and data == None:
try:
with open(filename, encoding='utf-8', mode="r") as f:
return True
except:
return False
else:
logger.info("Invalid fileIO call")
def loadProverbs():
with open("proverbs.txt", encoding='utf-8', mode="r") as f:
data = f.readlines()
return data
def loadAndCheckSettings():
to_delete = []
try:
current_settings = fileIO("json/settings.json", "load")
default = json.loads(default_settings)
if current_settings.keys() != default.keys():
logger.warning("Something wrong detected with settings.json. Starting check...")
for field in default:
if field not in current_settings:
logger.info("Adding " + field + " field.")
current_settings[field] = default[field]
for field in current_settings:
if field not in default:
logger.info("Removing " + field + " field.")
to_delete.append(field)
for field in to_delete:
del current_settings[field]
logger.warning("Your settings.json was deprecated (missing or useless fields detected). I fixed it. " +
"If the file was missing any field I've added it and put default values. You might want to check it.")
fileIO("json/settings.json", "save", current_settings)
return current_settings
except IOError:
fileIO("json/settings.json", "save", json.loads(default_settings))
logger.error("Your settings.json is missing. I've created a new one. Edit it with your settings and restart me.")
exit(1)
except:
logger.error("Your settings.json seems to be invalid. Check it. If you're unable to fix it delete it and I'll create a new one the next start.")
exit(1)
def migration():
if not os.path.exists("json/"):
os.makedirs("json")
logger.info("Creating json folder...")
if not os.path.exists("cache/"): #Stores youtube audio for DOWNLOADMODE
os.makedirs("cache")
if not os.path.exists("trivia/"):
os.makedirs("trivia")
files = glob.glob("*.json")
if files != []:
logger.info("Moving your json files into the json folder...")
for f in files:
logger.info("Moving {}...".format(f))
os.rename(f, "json/" + f)
def createEmptyFiles():
files = {"twitch.json": [], "commands.json": {}, "economy.json" : {}, "filter.json" : {}, "regex_filter.json" : {}, "shushlist.json" : [], "blacklist.json" : []}
games = ["Multi Theft Auto", "her Turn()", "Tomb Raider II", "some music.", "NEO Scavenger", "Python", "World Domination", "with your heart."]
files["games.json"] = games
for f, data in files.items() :
if not os.path.isfile("json/" + f):
logger.info("Missing {}. Creating it...".format(f))
fileIO("json/" + f, "save", data)
if not os.path.isfile("json/settings.json"):
logger.info("Missing settings.json. Creating it...\n")
fileIO("json/settings.json", "save", json.loads(default_settings))
print("You have to configure your settings. If you'd like to do it manually, close this window.\nOtherwise type your bot's account email. DO NOT use your own account for the bot, make a new one.\n\nEmail:")
email = input(">")
print("Now enter the password.")
password = input(">")
print("Admin role? Leave empty for default (Transistor)")
admin_role = input(">")
if admin_role == "":
admin_role = "Transistor"
print("Command prefix? Leave empty for default, '!'. Maximum 1 character.")
prefix = input(">")
if len(prefix) != 1 or prefix == " ":
print("Invalid prefix. Setting prefix as '!'...")
prefix = "!"
new_settings = json.loads(default_settings)
new_settings["EMAIL"] = email
new_settings["PASSWORD"] = password
new_settings["ADMINROLE"] = admin_role
new_settings["PREFIX"] = prefix
fileIO("json/settings.json", "save", new_settings )
logger.info("Settings have been saved.")
if not os.path.isfile("json/apis.json"):
logger.info("Missing apis.json. Creating it...\n")
fileIO("json/apis.json", "save", json.loads(default_apis))
print("\nIt's now time to configure optional services\nIf you're not interested, leave empty and keep pressing enter.\nMemes feature: create an account on https://imgflip.com/.\nimgflip username:")
imgflip_username = input(">")
print("Now enter the imgflip password.")
imgflip_password = input(">")
if imgflip_username == "": imgflip_username = "USERNAMEHERE"
if imgflip_password == "": imgflip_password = "PASSWORDHERE"
print("\n!imdb configuration. Get your token here http://www.myapifilms.com/token.do\nOr just press enter if you're not interested.")
imdb_token = input(">")
if imdb_token == "": imdb_token = "TOKENHERE"
new_settings = json.loads(default_apis)
new_settings["IMGFLIP_USERNAME"] = imgflip_username
new_settings["IMGFLIP_PASSWORD"] = imgflip_password
new_settings["MYAPIFILMS_TOKEN"] = imdb_token
fileIO("json/apis.json", "save", new_settings )
logger.info("API Settings have been saved.\n")
+20
View File
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = python -msphinx
SPHINXPROJ = Red-DiscordBot
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+9
View File
@@ -0,0 +1,9 @@
.. Downloader Cog Reference
Downloader Cog Reference
========================
.. automodule:: redbot.cogs.downloader
.. autoclass:: redbot.cogs.downloader.downloader.Downloader
:members:
+196
View File
@@ -0,0 +1,196 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Red - Discord Bot documentation build configuration file, created by
# sphinx-quickstart on Thu Aug 10 23:18:25 2017.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# 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
sys.path.insert(0, os.path.abspath('..'))
os.environ['BUILDING_DOCS'] = "1"
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.viewcode',
'sphinx.ext.napoleon',
'sphinxcontrib.asyncio'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Red - Discord Bot'
copyright = '2017, Cog Creators'
author = 'Cog Creators'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '3.0.0a1'
# The full version, including alpha/beta/rc tags.
release = '3.0.0a1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# Role which is assigned when you make a simple reference within backticks
default_role = "any"
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
html_context = {
# Enable the "Edit in GitHub link within the header of each page.
'display_github': True,
'github_user': 'Cog-Creators',
'github_repo': 'Red-DiscordBot',
'github_version': 'V3/develop/docs/'
}
# 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".
html_static_path = ['_static']
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
#
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
'**': [
'about.html',
'navigation.html',
'relations.html', # needs 'show_related': True theme option to display
'searchbox.html',
'donate.html',
]
}
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'Red-DiscordBotdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Red-DiscordBot.tex', 'Red - Discord Bot Documentation',
'Cog Creators', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'red-discordbot', 'Red - Discord Bot Documentation',
[author], 1)
]
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Red-DiscordBot', 'Red - Discord Bot Documentation',
author, 'Red-DiscordBot', 'One line description of project.',
'Miscellaneous'),
]
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('https://docs.python.org/3.5', None),
'dpy': ('https://discordpy.readthedocs.io/en/rewrite/', None),
'motor': ('https://motor.readthedocs.io/en/stable/', None)}
+42
View File
@@ -0,0 +1,42 @@
.. V3 Bank
.. role:: python(code)
:language: python
====
Bank
====
Bank has now been separated from Economy for V3. New to bank is support for
having a global bank.
***********
Basic Usage
***********
.. code-block:: python
from redbot.core import bank
class MyCog:
@commands.command()
async def balance(self, ctx, user: discord.Member=None):
if user is None:
user = ctx.author
bal = bank.get_balance(user)
currency = bank.get_currency_name(ctx.guild)
await ctx.send(
"{}'s balance is {} {}".format(
user.display_name, bal, currency
)
)
*************
API Reference
*************
Bank
======
.. automodule:: redbot.core.bank
:members:
+8
View File
@@ -0,0 +1,8 @@
.. cog manager docs
===========
Cog Manager
===========
.. automodule:: redbot.core.cog_manager
:members:
+388
View File
@@ -0,0 +1,388 @@
.. config shite
.. role:: python(code)
:language: python
======
Config
======
Config was introduced in V3 as a way to make data storage easier and safer for all developers regardless of skill level.
It will take some getting used to as the syntax is entirely different from what Red has used before, but we believe
Config will be extremely beneficial to both cog developers and end users in the long run.
***********
Basic Usage
***********
.. code-block:: python
from redbot.core import Config
class MyCog:
def __init__(self):
self.config = Config.get_conf(self, identifier=1234567890)
self.config.register_global(
foo=True
)
@commands.command()
async def return_some_data(self, ctx):
await ctx.send(await config.foo())
********
Tutorial
********
.. py:currentmodule:: redbot.core.config
This tutorial will walk you through how to use Config.
First, you need to import Config:
.. code-block:: python
from redbot.core import Config
Then, in the class's :code:`__init__` function, you need to get a config instance:
.. code-block:: python
class MyCog:
def __init__(self):
self.config = Config.get_conf(self, identifier=1234567890)
The ``identifier`` in :py:meth:`Config.get_conf` is used to keep your cog's data separate
from that of another cog, and thus should be unique to your cog. For example: if we
have two cogs named :code:`MyCog` and their identifier is different, each will have
its own data without overwriting the other's data. Note that it is also possible
to force registration of a data key before allowing you to get and set data for
that key by adding :code:`force_registration=True` after identifier (that defaults
to :code:`False` though)
After we've gotten that, we need to register default values:
.. code-block:: python
class MyCog:
def __init__(self):
self.config = Config.get_conf(self, identifier=1234567890)
default_global = {
"foobar": True,
"foo": {
"bar": True,
"baz": False
}
}
default_guild = {
"blah": [],
"baz": 1234567890
}
self.config.register_global(**default_global)
self.config.register_guild(**default_guild)
As seen in the example above, we can set up our defaults in dicts and then use those in
the appropriate :code:`register` function. As seen above, there's :py:meth:`Config.register_global`
and :py:meth:`Config.register_guild`, but there's also :py:meth:`Config.register_member`,
:py:meth:`Config.register_role`, :py:meth:`Config.register_user`, and :py:meth:`Config.register_channel`.
Note that :code:`member` stores based on guild id AND the user's id.
Once we have our defaults registered and we have the object, we can now use those values
in various ways:
.. code-block:: python
@commands.command()
@checks.admin_or_permissions(manage_guild=True)
async def setbaz(self, ctx, new_value):
await self.config.guild(ctx.guild).baz.set(new_value)
await ctx.send("Value of baz has been changed!")
@commands.command()
@checks.is_owner()
async def setfoobar(self, ctx, new_value):
await self.config.foobar.set(new_value)
@commands.command()
async def checkbaz(self, ctx):
baz_val = await self.config.guild(ctx.guild).baz()
await ctx.send("The value of baz is {}".format("True" if baz_val else "False"))
Notice a few things in the above examples:
1. Global doesn't have anything in between :code:`self.config` and the variable.
2. Both the getters and setters need to be awaited because they're coroutines.
3. If you're getting the value, the syntax is::
self.config.<insert scope here, or nothing if global>.variable_name()
4. If setting, it's::
self.config.<insert scope here, or nothing if global>.variable_name.set(new_value)
It is also possible to use :code:`async with` syntax to get and set config
values. When entering the statement, the config value is retreived, and on exit,
it is saved. This puts a safeguard on any code within the :code:`async with`
block such that if it breaks from the block in any way (whether it be from
:code:`return`, :code:`break`, :code:`continue` or an exception), the value will
still be saved.
.. important::
Only mutable config values can be used in the :code:`async with` statement
(namely lists or dicts), and they must be modified *in place* for their
changes to be saved.
Here is an example of the :code:`async with` syntax:
.. code-block:: python
@commands.command()
async def addblah(self, ctx, new_blah):
guild_group = self.config.guild(ctx.guild)
async with guild_group.blah() as blah:
blah.append(new_blah)
await ctx.send("The new blah value has been added!")
.. important::
Please note that while you have nothing between ``config`` and the variable name for global
data, you also have the following commands to get data specific to each category.
* :py:meth:`Config.guild` for guild data which takes an object of type :py:class:`discord.Guild`.
* :py:meth:`Config.member` which takes :py:class:`discord.Member`.
* :py:meth:`Config.user` which takes :py:class:`discord.User`.
* :py:meth:`Config.role` which takes :py:class:`discord.Role`.
* :py:meth:`Config.channel` which takes :py:class:`discord.TextChannel`.
If you need to wipe data from the config, you want to look at :py:meth:`Group.clear`, or :py:meth:`Config.clear_all`
and similar methods, such as :py:meth:`Config.clear_all_guilds`.
Which one you should use depends on what you want to do.
If you're looking to clear data for a single guild/member/channel/role/user,
you want to use :py:meth:`Group.clear` as that will clear the data only for the
specified thing.
If using :py:meth:`Config.clear_all`, it will reset all data everywhere.
There are other methods provided to reset data from a particular scope. For
example, :py:meth:`Config.clear_all_guilds` resets all guild data. For member
data, you can clear on both a per-guild and guild-independent basis, see
:py:meth:`Config.clear_all_members` for more info.
**************
Advanced Usage
**************
Config makes it extremely easy to organize data that can easily fit into one of the standard categories (global,
guild, user etc.) but there may come a time when your data does not work with the existing categories. There are now
features within Config to enable developers to work with data how they wish.
This usage guide will cover the following features:
- :py:meth:`Group.get_raw`
- :py:meth:`Group.set_raw`
For this example let's suppose that we're creating a cog that allows users to buy and own multiple pets using
the built-in Economy credits::
from redbot.core import bank
from redbot.core import Config
from discord.ext import commands
class Pets:
def __init__(self):
self.conf = Config.get_conf(self, 1234567890)
# Here we'll assign some default costs for the pets
self.conf.register_global(
dog=100,
cat=100,
bird=50
)
self.conf.register_user(
pets={}
)
And now that the cog is set up we'll need to create some commands that allow users to purchase these pets::
# continued
@commands.command()
async def get_pet(self, ctx, pet_type: str, pet_name: str):
"""
Purchase a pet.
Pet type must be one of: dog, cat, bird
"""
# Now we need to determine what the cost of the pet is and
# if the user has enough credits to purchase it.
# We will need to use "get_raw"
try:
cost = await self.conf.get_raw(pet_type)
except KeyError:
# KeyError is thrown whenever the data you try to access does not
# exist in the registered defaults or in the saved data.
await ctx.send("Bad pet type, try again.")
return
After we've determined the cost of the pet we need to check if the user has enough credits and then we'll need to
assign a new pet to the user. This is very easily done using the V3 bank API and :py:meth:`Group.set_raw`::
# continued
if await bank.can_spend(ctx.author, cost):
await self.conf.user(ctx.author).pets.set_raw(
pet_name, value={'cost': cost, 'hunger': 0}
)
# this is equivalent to doing the following
pets = await self.conf.user(ctx.author).pets()
pets[pet_name] = {'cost': cost, 'hunger': 0}
await self.conf.user(ctx.author).pets.set(pets)
Since the pets can get hungry we're gonna need a command that let's pet owners check how hungry their pets are::
# continued
@commands.command()
async def hunger(self, ctx, pet_name: str):
try:
hunger = await self.conf.user(ctx.author).pets.get_raw(pet_name, 'hunger')
except KeyError:
# Remember, this is thrown if something in the provided identifiers
# is not found in the saved data or the defaults.
await ctx.send("You don't own that pet!")
return
await ctx.send("Your pet has {}/100 hunger".format(hunger))
We're responsible pet owners here, so we've also got to have a way to feed our pets::
# continued
@commands.command()
async def feed(self, ctx, pet_name: str, food: int):
# This is a bit more complicated because we need to check if the pet is
# owned first.
try:
pet = await self.conf.user(ctx.author).pets.get_raw(pet_name)
except KeyError:
# If the given pet name doesn't exist in our data
await ctx.send("You don't own that pet!")
return
hunger = pet.get("hunger")
# Determine the new hunger and make sure it doesn't go negative
new_hunger = max(hunger - food, 0)
await self.conf.user(ctx.author).pets.set_raw(
pet_name, 'hunger', value=new_hunger
)
# We could accomplish the same thing a slightly different way
await self.conf.user(ctx.author).pets.get_attr(pet_name).hunger.set(new_hunger)
await ctx.send("Your pet is now at {}/100 hunger!".format(new_hunger)
*************
V2 Data Usage
*************
There has been much conversation on how to bring V2 data into V3 and, officially, we recommend that cog developers
make use of the public interface in Config (using the categories as described in these docs) rather than simply
copying and pasting your V2 data into V3. Using Config as recommended will result in a much better experience for
you in the long run and will simplify cog creation and maintenance.
However.
We realize that many of our cog creators have expressed disinterest in writing converters for V2 to V3 style data.
As a result we have opened up config to take standard V2 data and allow cog developers to manipulate it in V3 in
much the same way they would in V2. The following examples will demonstrate how to accomplish this.
.. warning::
By following this method to use V2 data in V3 you may be at risk of data corruption if your cog is used on a bot
with multiple shards. USE AT YOUR OWN RISK.
.. code-block:: python
from redbot.core import Config
class ExampleCog:
def __init__(self):
self.conf = Config.get_conf(self, 1234567890)
self.data = {}
async def load_data(self):
self.data = await self.conf.custom("V2", "V2").all()
async def save_data(self):
await self.conf.custom("V2", "V2").set(self.data)
async def setup(bot):
cog = ExampleCog()
await cog.load_data()
bot.add_cog(cog)
*************
API Reference
*************
.. important::
Before we begin with the nitty gritty API Reference, you should know that there are tons of working code examples
inside the bot itself! Simply take a peek inside of the :code:`tests/core/test_config.py` file for examples of using
Config in all kinds of ways.
.. automodule:: redbot.core.config
Config
^^^^^^
.. autoclass:: Config
:members:
Group
^^^^^
.. autoclass:: Group
:members:
:special-members:
Value
^^^^^
.. autoclass:: Value
:members:
:special-members: __call__
****************
Driver Reference
****************
.. automodule:: redbot.core.drivers
:members:
Base Driver
^^^^^^^^^^^
.. autoclass:: redbot.core.drivers.red_base.BaseDriver
:members:
JSON Driver
^^^^^^^^^^^
.. autoclass:: redbot.core.drivers.red_json.JSON
:members:
Mongo Driver
^^^^^^^^^^^^
.. autoclass:: redbot.core.drivers.red_mongo.Mongo
:members:
+10
View File
@@ -0,0 +1,10 @@
.. red invocation context documentation
==========================
Command Invocation Context
==========================
.. automodule:: redbot.core.context
.. autoclass:: redbot.core.RedContext
:members:
+11
View File
@@ -0,0 +1,11 @@
.. data manager docs
============
Data Manager
============
Data manager is a module that handles all the information necessary to bootstrap
the bot into a state where more abstract data management systems can take over.
.. automodule:: redbot.core.data_manager
:members:
+76
View File
@@ -0,0 +1,76 @@
.. downloader framework reference
Downloader Framework
====================
Info.json
*********
The info.json file may exist inside every package folder in the repo,
it is optional however. This string describes the valid keys within
an info file (and maybe how the Downloader cog uses them).
KEYS (case sensitive):
- ``author`` (list of strings) - list of names of authors of the cog
- ``bot_version`` (list of integer) - Min version number of Red in the format ``(MAJOR, MINOR, PATCH)``
- ``description`` (string) - A long description of the cog that appears when a user executes ```!cog info``.
- ``hidden`` (bool) - Determines if a cog is available for install.
- ``install_msg`` (string) - The message that gets displayed when a cog is installed
- ``required_cogs`` (map of cogname to repo URL) - A map of required cogs that this cog depends on.
Downloader will not deal with this functionality but it may be useful for other cogs.
- ``requirements`` (list of strings) - list of required libraries that are
passed to pip on cog install. ``SHARED_LIBRARIES`` do NOT go in this
list.
- ``short`` (string) - A short description of the cog that appears when
a user executes `!cog list`
- ``tags`` (list of strings) - A list of strings that are related to the
functionality of the cog. Used to aid in searching.
- ``type`` (string) - Optional, defaults to ``COG``. Must be either ``COG`` or
``SHARED_LIBRARY``. If ``SHARED_LIBRARY`` then ``hidden`` will be ``True``.
API Reference
*************
.. automodule:: redbot.cogs.downloader.json_mixins
.. autoclass RepoJSONMixin
:members
.. automodule:: redbot.cogs.downloader.installable
Installable
^^^^^^^^^^^
.. autoclass:: Installable
:members:
.. automodule:: redbot.cogs.downloader.repo_manager
Repo
^^^^
.. autoclass:: Repo
:members:
Repo Manager
^^^^^^^^^^^^
.. autoclass:: RepoManager
:members:
Exceptions
^^^^^^^^^^
.. automodule:: redbot.cogs.downloader.errors
:members:
+12
View File
@@ -0,0 +1,12 @@
.. framework events list
=============
Custom Events
=============
RPC Server
^^^^^^^^^^
.. py:method:: Red.on_shutdown()
Dispatched when the bot begins it's shutdown procedures.
+54
View File
@@ -0,0 +1,54 @@
.. i18n framework reference
.. role:: python(code)
:language: python
==============================
Internationalization Framework
==============================
-----------
Basic Usage
-----------
.. code-block:: python
from discord.ext import commands
from redbot.core.i18n import CogI18n
_ = CogI18n("ExampleCog", __file__)
class ExampleCog:
"""description"""
@commands.command()
async def mycom(self, ctx):
"""command description"""
await ctx.send(_("This is a test command"))
--------
Tutorial
--------
After making your cog, generate a :code:`messages.pot` file
The process of generating this will depend on the operating system
you are using
In a command prompt in your cog's package (where yourcog.py is),
create a directory called "locales".
Then do one of the following:
Windows: :code:`python <your python install path>\Tools\i18n\pygettext.py -n -p locales`
Mac: ?
Linux: :code:`pygettext3 -n -p locales`
This will generate a messages.pot file with strings to be translated
-------------
API Reference
-------------
.. automodule:: redbot.core.i18n
+95
View File
@@ -0,0 +1,95 @@
.. V3 Mod log
.. role:: python(code)
:language: python
=======
Mod log
=======
Mod log has now been separated from Mod for V3.
***********
Basic Usage
***********
.. code-block:: python
from redbot.core import modlog
import discord
class MyCog:
@commands.command()
@checks.admin_or_permissions(ban_members=True)
async def ban(self, ctx, user: discord.Member, reason: str=None):
await ctx.guild.ban(user)
case = modlog.create_case(
ctx.guild, ctx.message.created_at, "ban", user,
ctx.author, reason, until=None, channel=None
)
await ctx.send("Done. It was about time.")
**********************
Registering Case types
**********************
To register a single case type:
.. code-block:: python
from redbot.core import modlog
import discord
class MyCog:
def __init__(self, bot):
ban_case = {
"name": "ban",
"default_setting": True,
"image": ":hammer:",
"case_str": "Ban",
"audit_type": "ban"
}
modlog.register_casetype(**ban_case)
To register multiple case types:
.. code-block:: python
from redbot.core import modlog
import discord
class MyCog:
def __init__(self, bot):
new_types = [
{
"name": "ban",
"default_setting": True,
"image": ":hammer:",
"case_str": "Ban",
"audit_type": "ban"
},
{
"name": "kick",
"default_setting": True,
"image": ":boot:",
"case_str": "Kick",
"audit_type": "kick"
}
]
modlog.register_casetypes(new_types)
.. important::
Image should be the emoji you want to represent your case type with.
*************
API Reference
*************
Mod log
=======
.. automodule:: redbot.core.modlog
:members:
+17
View File
@@ -0,0 +1,17 @@
.. red's core utils documentation
=================
Utility Functions
=================
Chat Formatting
===============
.. automodule:: redbot.core.utils.chat_formatting
:members:
Mod Helpers
===========
.. automodule:: redbot.core.utils.mod
:members:
+95
View File
@@ -0,0 +1,95 @@
.. Making cogs for V3
.. role:: python(code)
:language: python
====================
Creating cogs for V3
====================
This guide serves as a tutorial on creating cogs for Red V3.
It will cover the basics of setting up a package for your
cog and the basics of setting up the file structure. We will
also point you towards some further resources that may assist
you in the process.
---------------
Getting started
---------------
To start off, be sure that you have installed Python 3.5 or higher (if you
are on Windows, stick with 3.5). Open a terminal or command prompt and type
:code:`pip install --process-dependency-links -U git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=redbot[test]`
(note that if you get an error with this, try again but put :code:`python -m` in front of the command
This will install the latest version of V3.
--------------------
Setting up a package
--------------------
To set up a package, we would just need to create a new folder.
This should be named whatever you want the cog to be named (for
the purposes of this example, we'll call this :code:`mycog`).
In this folder, create three files: :code:`__init__.py`,
:code:`mycog.py`, and :code:`info.json`. Open the folder in
a text editor or IDE (examples include `Sublime Text 3 <https://www.sublimetext.com/>`_,
`Visual Studio Code <https://code.visualstudio.com/>`_, `Atom <https://atom.io/>`_, and
`PyCharm <http://www.jetbrains.com/pycharm/>`_).
--------------
Creating a cog
--------------
With your package opened in a text editor or IDE, open :code:`mycog.py`.
In that file, place the following code:
.. code-block:: python
from discord.ext import commands
class Mycog:
"""My custom cog"""
@commands.command()
async def mycom(self, ctx):
"""This does stuff!"""
# Your code will go here
await ctx.send("I can do stuff!")
Open :code:`__init__.py`. In that file, place the following:
.. code-block:: python
from .mycog import Mycog
def setup(bot):
bot.add_cog(Mycog())
Make sure that both files are saved.
----------------
Testing your cog
----------------
To test your cog, you will need a running instance of V3.
Assuming you installed V3 as outlined above, run :code:`redbot-setup`
and provide the requested information. Once that's done, run Red
by doing :code:`redbot <instance name> --dev` to start Red.
Complete the inital setup by providing a valid token and setting a
prefix. Once the bot has started up, use the link provided in the
console to add it to a server (note that you must have the
:code:`Manage Server` (or :code:`Administrator`) permission to add bots
to a server). Once it's been added to a server, find the full path
to the directory where your cog package is located. In Discord, do
:code:`[p]addpath <path_to_folder_containing_package>`, then do
:code:`[p]load mycog`. Once the cog is loaded, do :code:`[p]mycom`
The bot should respond with :code:`I can do stuff!`. If it did, you
have successfully created a cog!
--------------------
Additional resources
--------------------
Be sure to check out the `migration guide </guide_migration>`_ for some resources
on developing cogs for V3. This will also cover differences between V2 and V3 for
those who developed cogs for V2.
+56
View File
@@ -0,0 +1,56 @@
.. V3 Migration Guide
.. role:: python(code)
:language: python
====================
Migrating Cogs to V3
====================
First, be sure to read `discord.py's migration guide <http://discordpy.readthedocs.io/en/rewrite/migrating.html>`_
as that covers all of the changes to discord.py that will affect the migration process
----------------
Red as a package
----------------
V3 makes Red a package that is installed with :code:`pip`. Please
keep this in mind when writing cogs as this affects how imports
should be done (for example, to import :code:`pagify` in V2, one
would do :code:`from .utils.chat_formatting import pagify`; in
V3, this becomes :code:`from redbot.core.utils.chat_formatting import pagify`)
----------------
Cogs as packages
----------------
V3 makes cogs into packages. See :doc:`/guide_cog_creation`
for more on how to create packages for V3.
------
Config
------
Config is V3's replacement for :code:`dataIO`. Instead of fiddling with
creating config directories and config files as was done in V2, V3's
Config handles that whilst allowing for easy storage of settings on a
per-server/member/user/role/channel or global basis. Be sure to check
out :doc:`/framework_config` for the API docs for Config as well as a
tutorial on using Config.
----
Bank
----
Bank in V3 has been split out from Economy. V3 introduces the ability
to have a global bank as well as the ability to change the bank name
and the name of the currency. Be sure to checkout :doc:`/framework_bank`
for more on Bank
-------
Mod Log
-------
V3 introduces Mod Log as an API, thus allowing for cogs to add custom case
types that will appear in a server's mod log channel. Be sure to checkout
:doc:`/framework_modlog` for more on Mod Log`
+49
View File
@@ -0,0 +1,49 @@
.. Red - Discord Bot documentation master file, created by
sphinx-quickstart on Thu Aug 10 23:18:25 2017.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Red - Discord Bot's documentation!
=============================================
.. toctree::
:maxdepth: 1
:caption: Installation Guides:
install_windows
install_mac
install_ubuntu
install_debian
install_centos
install_raspbian
.. toctree::
:maxdepth: 2
:caption: Cog Reference:
cog_downloader
.. toctree::
:maxdepth: 2
:caption: Red Development Framework Reference:
guide_migration
guide_cog_creation
framework_bank
framework_cogmanager
framework_datamanager
framework_config
framework_downloader
framework_i18n
framework_modlog
framework_context
framework_utils
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+54
View File
@@ -0,0 +1,54 @@
.. centos install guide
==========================
Installing Red on CentOS 7
==========================
---------------------------
Installing pre-requirements
---------------------------
.. code-block:: none
yum -y groupinstall development
yum -y install https://centos7.iuscommunity.org/ius-release.rpm
yum -y install yum-utils wget which python35u python35u-pip python35u-devel openssl-devel libffi-devel git opus-devel java-1.8.0-openjdk
sh -c "$(wget https://gist.githubusercontent.com/mustafaturan/7053900/raw/27f4c8bad3ee2bb0027a1a52dc8501bf1e53b270/latest-ffmpeg-centos6.sh -O -)"
--------------
Installing Red
--------------
Without audio:
:code:`pip3 install -U --process-dependency-links red-discordbot`
With audio:
:code:`pip3 install -U --process-dependency-links red-discordbot[voice]`
To install the development version (without audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot`
To install the development version (with audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot[voice]`
----------------------
Setting up an instance
----------------------
Run :code:`redbot-setup` and follow the prompts. It will ask first for where you want to
store the data (the default is :code:`~/.local/share/Red-DiscordBot`) and will then ask
for confirmation of that selection. Next, it will ask you to choose your storage backend
(the default here is JSON). It will then ask for a name for your instance. This can be
anything as long as it does not contain spaces; however, keep in mind that this is the
name you will use to run your bot, and so it should be something you can remember.
-----------
Running Red
-----------
Run :code:`redbot <your instance name>` and run through the initial setup. This will ask for
your token and a prefix.
+55
View File
@@ -0,0 +1,55 @@
.. debian install guide
================================
Installing Red on Debian Stretch
================================
.. warning:: For safety reasons, DO NOT install Red with a root user. Instead, make a new one.
---------------------------
Installing pre-requirements
---------------------------
.. code-block:: none
echo "deb http://httpredir.debian.org/debian stretch-backports main contrib non-free" >> /etc/apt/sources.list
apt-get update
apt-get install python3.5-dev python3-pip build-essential libssl-dev libffi-dev git ffmpeg libopus-dev unzip default-jre -y
------------------
Installing the bot
------------------
To install without audio:
:code:`pip3 install -U --process-dependency-links red-discordbot`
To install with audio:
:code:`pip3 install -U --process-dependency-links red-discordbot[voice]`
To install the development version (without audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot`
To install the development version (with audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot[voice]`
------------------------
Setting up your instance
------------------------
Run :code:`redbot-setup` and follow the prompts. It will ask first for where you want to
store the data (the default is :code:`~/.local/share/Red-DiscordBot`) and will then ask
for confirmation of that selection. Next, it will ask you to choose your storage backend
(the default here is JSON). It will then ask for a name for your instance. This can be
anything as long as it does not contain spaces; however, keep in mind that this is the
name you will use to run your bot, and so it should be something you can remember.
-----------
Running Red
-----------
Run :code:`redbot <your instance name>` and run through the initial setup. This will ask for
your token and a prefix.
+55
View File
@@ -0,0 +1,55 @@
.. mac install guide
=====================
Installing Red on Mac
=====================
---------------------------
Installing pre-requirements
---------------------------
* Install Brew
* In Finder or Spotlight, search for and open terminal. In the window that will open, paste this:
:code:`/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
and press enter.
* After the installation, install the required packages by pasting the commands and pressing enter, one-by-one:
* :code:`brew install python3 --with-brewed-openssl`
* :code:`brew install git`
* :code:`brew install ffmpeg --with-ffplay`
* :code:`brew install opus`
* :code:`brew tap caskroom/versions`
* :code:`brew cask install java8`
--------------
Installing Red
--------------
Without audio:
:code:`pip3 install -U --process-dependency-links red-discordbot`
With audio:
:code:`pip3 install -U --process-dependency-links red-discordbot[voice]`
To install the development version (without audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot`
To install the development version (with audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot[voice]`
----------------------
Setting up an instance
----------------------
To set up an instance, run :code:`redbot-setup` and follow the steps there, providing the requested information
or accepting the defaults. Keep in mind that the instance name will be the one you use when running the bot, so
make it something you can remember
-----------
Running Red
-----------
Run :code:`redbot <your instance name>` and go through the initial setup (it will ask for the token and a prefix).
+53
View File
@@ -0,0 +1,53 @@
.. raspbian install guide
==================================
Installing Red on Raspbian Stretch
==================================
---------------------------
Installing pre-requirements
---------------------------
.. code-block:: none
sudo apt-get install python3.5-dev python3-pip build-essential libssl-dev libffi-dev git libav-tools libopus-dev unzip default-jre -y
--------------
Installing Red
--------------
Without audio:
:code:`pip3 install -U --process-dependency-links red-discordbot`
With audio:
:code:`pip3 install -U --process-dependency-links red-discordbot[voice]`
To install the development version (without audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot`
To install the development version (with audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot[voice]`
----------------------
Setting up an instance
----------------------
Run :code:`redbot-setup` and follow the prompts. It will ask first for where you want to
store the data (the default is :code:`~/.local/share/Red-DiscordBot`) and will then ask
for confirmation of that selection. Next, it will ask you to choose your storage backend
(the default here is JSON). It will then ask for a name for your instance. This can be
anything as long as it does not contain spaces; however, keep in mind that this is the
name you will use to run your bot, and so it should be something you can remember.
-----------
Running Red
-----------
Run :code:`redbot <your instance name>` and run through the initial setup. This will ask for
your token and a prefix.
.. warning:: Audio will not work on Raspberry Pi's **below** 2B. This is a CPU problem and *cannot* be fixed.
+53
View File
@@ -0,0 +1,53 @@
.. ubuntu install guide
==============================
Installing Red on Ubuntu 16.04
==============================
.. warning:: For safety reasons, DO NOT install Red with a root user. Instead, make a new one.
-------------------------------
Installing the pre-requirements
-------------------------------
.. code-block:: none
sudo apt install python3.5-dev python3-pip build-essential libssl-dev libffi-dev git ffmpeg libopus-dev unzip default-jre -y
------------------
Installing the bot
------------------
To install without audio:
:code:`pip3 install -U --process-dependency-links red-discordbot`
To install with audio:
:code:`pip3 install -U --process-dependency-links red-discordbot[voice]`
To install the development version (without audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot`
To install the development version (with audio):
:code:`pip3 install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot[voice]`
------------------------
Setting up your instance
------------------------
Run :code:`redbot-setup` and follow the prompts. It will ask first for where you want to
store the data (the default is :code:`~/.local/share/Red-DiscordBot`) and will then ask
for confirmation of that selection. Next, it will ask you to choose your storage backend
(the default here is JSON). It will then ask for a name for your instance. This can be
anything as long as it does not contain spaces; however, keep in mind that this is the
name you will use to run your bot, and so it should be something you can remember.
-----------
Running Red
-----------
Run :code:`redbot <your instance name>` and run through the initial setup. This will ask for
your token and a prefix.
+47
View File
@@ -0,0 +1,47 @@
.. windows installation docs
=========================
Installing Red on Windows
=========================
---------------
Needed Software
---------------
* `Python <https://python.org/downloads/>`_ - Red needs at least Python 3.5
.. attention:: Please note that 3.6 has issues on some versions of Windows.
If you try using Red with 3.6 and experience issues, uninstall
Python 3.6 and install the latest version of Python 3.5
.. note:: Please make sure that the box to add Python to PATH is CHECKED, otherwise
you may run into issues when trying to run Red
* `Git <https://git-scm.com/download/win>`_
.. attention:: Please choose the option to "Run Git from the Windows Command Prompt" in Git's setup
* `Java <https://java.com/en/download/manual.jsp>`_ - needed for Audio
.. attention:: Please choose the "Windows Online" installer
--------------
Installing Red
--------------
1. Open a command prompt (open Start, search for "command prompt", then click it)
2. Run the appropriate command, depending on if you want audio or not
* No audio: :code:`python -m pip install -U --process-dependency-links Red-DiscordBot`
* Audio: :code:`python -m pip install -U --process-dependency-links Red-DiscordBot[voice]`
* Development version (without audio): :code:`python -m pip install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot`
* Development version (with audio): :code:`python -m pip install -U --process-dependency-links git+https://github.com/Cog-Creators/Red-DiscordBot@V3/develop#egg=red-discordbot[voice]`
3. Once that has completed, run :code:`redbot-setup` to set up your instance
* This will set the location where data will be stored, as well as your
storage backend and the name of the instance (which will be used for
running the bot)
4. Once done setting up the instance, run :code:`redbot <your instance name>` to run Red.
It will walk through the initial setup, asking for your token and a prefix
+36
View File
@@ -0,0 +1,36 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=python -msphinx
)
set SOURCEDIR=.
set BUILDDIR=_build
set SPHINXPROJ=Red-DiscordBot
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The Sphinx module was not found. Make sure you have Sphinx installed,
echo.then set the SPHINXBUILD environment variable to point to the full
echo.path of the 'sphinx-build' executable. Alternatively you may add the
echo.Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd
+4
View File
@@ -0,0 +1,4 @@
sphinx==1.6.3
sphinxcontrib-asyncio
sphinx_rtd_theme
git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py[voice]
-249
View File
@@ -1,249 +0,0 @@
from random import randint, choice
import time
import dataIO
client = None
settings = []
#words = dataIO.loadWords()
#anagram_sessions_timestamps = {}
anagram_sessions = []
payday_register = {}
PAYDAY_TIME = 300 # seconds between each payday
PAYDAY_CREDITS = 120 # credits received
def initialize():
global bank
bank = dataIO.fileIO("json/economy.json", "load")
def loadHelp():
global slot_help, economy_exp
if settings == []: return False #first run
slot_help = """ Slot machine payouts:
:two: :two: :six: Bet * 5000
:four_leaf_clover: :four_leaf_clover: :four_leaf_clover: +1000
:cherries: :cherries: :cherries: +800
:two: :six: Bet * 4
:cherries: :cherries: Bet * 3
Three symbols: +500
Two symbols: Bet * 2
You need an account to play. {0}register one.
Bet range: 5 - 100
""".format(settings["PREFIX"])
economy_exp = """ **Economy. Get rich and have fun with imaginary currency!**
{0}register - Register an account at the Twentysix bank
{0}balance - Check your balance
{0}slot help - Slot machine explanation
{0}slot [bid] - Play the slot machine
{0}payday - Type it every {1} seconds to receive some credits.
""".format(settings["PREFIX"], str(PAYDAY_TIME))
async def checkCommands(message):
p = settings["PREFIX"]
cmd = message.content
user = message.author
if cmd == p + "balance":
if accountCheck(user.id):
await client.send_message(message.channel, "{} `Your balance is: {}`".format(user.mention, str(checkBalance(user.id))))
else:
await client.send_message(message.channel, "{} `You don't have an account at the Twentysix bank. Type !register to open one.`".format(user.mention, str(checkBalance(user.id))))
elif cmd == p + "register":
await registerAccount(user, message)
elif cmd == p + "slot help":
await client.send_message(message.author, slot_help)
await client.send_message(message.channel, "{} `Check your DMs for the slot machine explanation.`".format(message.author.mention))
elif cmd.startswith(p + "slot"):
await slotMachineCheck(message)
elif cmd == p + "economy":
await client.send_message(message.author, economy_exp)
await client.send_message(message.channel, "{} `Check your DMs for the economy explanation.`".format(message.author.mention))
elif cmd == p + "challenge":
#isChallengeOngoing(message)
pass
elif cmd == p + "payday":
await payday(message)
async def registerAccount(user, message):
if user.id not in bank:
bank[user.id] = {"name" : user.name, "balance" : 100}
dataIO.fileIO("json/economy.json", "save", bank)
await client.send_message(message.channel, "{} `Account opened. Current balance: {}`".format(user.mention, str(checkBalance(user.id))))
else:
await client.send_message(message.channel, "{} `You already have an account at the Twentysix bank.`".format(user.mention))
def accountCheck(id):
if id in bank:
return True
else:
return False
def checkBalance(id):
if accountCheck(id):
return bank[id]["balance"]
else:
return False
def withdrawMoney(id, amount):
if accountCheck(id):
if bank[id]["balance"] >= int(amount):
bank[id]["balance"] = bank[id]["balance"] - int(amount)
dataIO.fileIO("json/economy.json", "save", bank)
else:
return False
else:
return False
def addMoney(id, amount):
if accountCheck(id):
bank[id]["balance"] = bank[id]["balance"] + int(amount)
dataIO.fileIO("json/economy.json", "save", bank)
else:
return False
def enoughMoney(id, amount):
if accountCheck(id):
if bank[id]["balance"] >= int(amount):
return True
else:
return False
else:
return False
async def isChallengeOngoing(message): #Work in progress
global anagram_sessions, anagram_sessions_timestamps
id = message.channel.id
for session in anagram_sessions:
if time.perf_counter() - session.started >= 600:
if session.done:
anagram_sessions.remove(session)
anagram_sessions.append(Anagram(message))
return True
else:
await client.send_message(message.channel, "{} `A challenge is already ongoing.`".format(message.author.mention))
return True
else:
await client.send_message(message.channel, "{} `You have to wait 10 minutes before each challenge.`".format(message.author.mention))
return True
anagram_sessions.append(Anagram(message))
async def payday(message):
id = message.author.id
if accountCheck(id):
if id in payday_register:
if abs(payday_register[id] - int(time.perf_counter())) >= PAYDAY_TIME:
addMoney(id, PAYDAY_CREDITS)
payday_register[id] = int(time.perf_counter())
await client.send_message(message.channel, "{} `Here, take some credits. Enjoy! (+{} credits!)`".format(message.author.mention, str(PAYDAY_CREDITS)))
else:
await client.send_message(message.channel, "{} `Too soon. You have to wait {} seconds between each payday.`".format(message.author.mention, str(PAYDAY_TIME)))
else:
payday_register[id] = int(time.perf_counter())
addMoney(id, PAYDAY_CREDITS)
await client.send_message(message.channel, "{} `Here, take some credits. Enjoy! (+{} credits!)`".format(message.author.mention, str(PAYDAY_CREDITS)))
else:
await client.send_message(message.channel, "{} `You need an account to receive credits. (!economy)`".format(message.author.mention))
###############SLOT##############
async def slotMachineCheck(message):
p = settings["PREFIX"]
msg = message.content.split()
if len(msg) == 2:
if msg[1].isdigit():
bid = int(msg[1])
if enoughMoney(message.author.id, bid):
if bid > 4 and bid < 101:
await slotMachine(message, bid)
else:
await client.send_message(message.channel, "{} `Bid must be between 5 and 100.`".format(message.author.mention))
else:
await client.send_message(message.channel, "{0} `You need an account with enough funds to play the slot machine. ({1}economy)`".format(message.author.mention, settings["PREFIX"]))
else:
await client.send_message(message.channel, "{} `".format(message.author.mention) + p + "slot [bid]`")
else:
await client.send_message(message.channel, "{} `".format(message.author.mention) + p + "slot [bid]`")
async def slotMachine(message, bid):
reel_pattern = [":cherries:", ":cookie:", ":two:", ":four_leaf_clover:", ":cyclone:", ":sunflower:", ":six:", ":mushroom:", ":heart:", ":snowflake:"]
padding_before = [":mushroom:", ":heart:", ":snowflake:"] # padding prevents index errors
padding_after = [":cherries:", ":cookie:", ":two:"]
reel = padding_before + reel_pattern + padding_after
reels = []
for i in range(0, 3):
n = randint(3,12)
reels.append([reel[n - 1], reel[n], reel[n + 1]])
line = [reels[0][1], reels[1][1], reels[2][1]]
display_reels = " " + reels[0][0] + " " + reels[1][0] + " " + reels[2][0] + "\n"
display_reels += ">" + reels[0][1] + " " + reels[1][1] + " " + reels[2][1] + "\n"
display_reels += " " + reels[0][2] + " " + reels[1][2] + " " + reels[2][2] + "\n"
if line[0] == ":two:" and line[1] == ":two:" and line[2] == ":six:":
bid = bid * 5000
await client.send_message(message.channel, "{}{} `226! Your bet is multiplied * 5000! {}!` ".format(display_reels, message.author.mention, str(bid)))
elif line[0] == ":four_leaf_clover:" and line[1] == ":four_leaf_clover:" and line[2] == ":four_leaf_clover:":
bid += 1000
await client.send_message(message.channel, "{}{} `Three FLC! +1000!` ".format(display_reels, message.author.mention))
elif line[0] == ":cherries:" and line[1] == ":cherries:" and line[2] == ":cherries:":
bid += 800
await client.send_message(message.channel, "{}{} `Three cherries! +800!` ".format(display_reels, message.author.mention))
elif line[0] == line[1] == line[2]:
bid += 500
await client.send_message(message.channel, "{}{} `Three symbols! +500!` ".format(display_reels, message.author.mention))
elif line[0] == ":two:" and line[1] == ":six:" or line[1] == ":two:" and line[2] == ":six:":
bid = bid * 4
await client.send_message(message.channel, "{}{} `26! Your bet is multiplied * 4! {}!` ".format(display_reels, message.author.mention, str(bid)))
elif line[0] == ":cherries:" and line[1] == ":cherries:" or line[1] == ":cherries:" and line[2] == ":cherries:":
bid = bid * 3
await client.send_message(message.channel, "{}{} `Two cherries! Your bet is multiplied * 3! {}!` ".format(display_reels, message.author.mention, str(bid)))
elif line[0] == line[1] or line[1] == line[2]:
bid = bid * 2
await client.send_message(message.channel, "{}{} `Two symbols! Your bet is multiplied * 2! {}!` ".format(display_reels, message.author.mention, str(bid)))
# elif line[0] == ":cherries:" or line[1] == ":cherries:" or line[2] == ":cherries:":
# await client.send_message(message.channel, "{}{} `Cherries! Your bet is safe!` ".format(display_reels, message.author.mention))
else:
await client.send_message(message.channel, "{}{} `Nothing! Lost bet.` ".format(display_reels, message.author.mention))
withdrawMoney(message.author.id, bid)
await client.send_message(message.channel, "`Credits left: {}`".format(str(checkBalance(message.author.id))))
return True
addMoney(message.author.id, bid)
await client.send_message(message.channel, "`Current credits: {}`".format(str(checkBalance(message.author.id))))
#######################################
############### ANAGRAM ###############
# Work in progress
class Anagram():
def __init__(self, message):
self.channel = message.channel
self.word = choice(words).lower()
self.anagram = list(self.word)
shuffle(self.anagram)
self.anagram = "".join(self.anagram)
self.started = int(time.perf_counter())
self.MAX_TIME = 60
self.done = False
def checkWord(self, message):
if time.perf_counter() - self.Atimestamp <= self.MAX_TIME:
msg = message.content.lower()
if msg.find(self.word) != -1:
pass
else:
self.gameOver()
async def gameOver(self):
self.done = True
try:
await client.send_message(self.channel, "`Anagram session over! No one guessed the word!`")
except:
pass
######################################
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+33
View File
@@ -0,0 +1,33 @@
import subprocess
import os
import sys
def main():
interpreter = sys.executable
print(interpreter)
root_dir = os.getcwd()
cogs = [i for i in os.listdir("redbot/cogs") if os.path.isdir(os.path.join("redbot/cogs", i))]
for d in cogs:
if "locales" in os.listdir(os.path.join("redbot/cogs", d)):
os.chdir(os.path.join("redbot/cogs", d, "locales"))
if "regen_messages.py" not in os.listdir(os.getcwd()):
print("Directory 'locales' exists for {} but no 'regen_messages.py' is available!".format(d))
exit(1)
else:
print("Running 'regen_messages.py' for {}".format(d))
retval = subprocess.run([interpreter, "regen_messages.py"])
if retval.returncode != 0:
exit(1)
os.chdir(root_dir)
os.chdir("redbot/core/locales")
print("Running 'regen_messages.py' for core")
retval = subprocess.run([interpreter, "regen_messages.py"])
if retval.returncode != 0:
exit(1)
os.chdir(root_dir)
subprocess.run(["crowdin", "upload"])
if __name__ == "__main__":
main()
BIN
View File
Binary file not shown.
-2
View File
@@ -1,2 +0,0 @@
Insert your local playlists folders here. Every folder counts as a different playlist and can contain
.mp3 and .flac files. No spaces allowed in their filenames, use underscores instead.
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=6sxnXO2RjVg", "https://www.youtube.com/watch?v=gj0Rz-uP4Mk", "https://www.youtube.com/watch?v=_izUd1S1BX0", "https://www.youtube.com/watch?v=K39qFmvbdww", "https://www.youtube.com/watch?v=ZFo8-JqzSCM", "https://www.youtube.com/watch?v=zD80CostTV0", "https://www.youtube.com/watch?v=mWADuNREJnY", "https://www.youtube.com/watch?v=xelUdXAvDVU", "https://www.youtube.com/watch?v=A2ptDgMOzc0", "https://www.youtube.com/watch?v=YwHrx0r0t2s", "https://www.youtube.com/watch?v=jqxNSvFMkag", "https://www.youtube.com/watch?v=gHgphqx1KT4", "https://www.youtube.com/watch?v=6sxnXO2RjVg", "https://www.youtube.com/watch?v=inb1z-qjxIU", "https://www.youtube.com/watch?v=fZZD8ckwLJA", "https://www.youtube.com/watch?v=xFn9V-VpkQ4", "https://www.youtube.com/watch?v=X7pjP_XkK4U", "https://www.youtube.com/watch?v=QPwPDDz-5Uo", "https://www.youtube.com/watch?v=6jmNe77vces", "https://www.youtube.com/watch?v=dga_ds1bJKg", "https://www.youtube.com/watch?v=oPmaVT-P5Ds", "https://www.youtube.com/watch?v=Ud_JZcC0tHI", "https://www.youtube.com/watch?v=35Cy7DUltYo", "https://www.youtube.com/watch?v=ZvmGLV_GE0M", "https://www.youtube.com/watch?v=7CXFXB4uknI", "https://www.youtube.com/watch?v=4pgbJaKemic", "https://www.youtube.com/watch?v=Jp6j5HJ-Cok", "https://www.youtube.com/watch?v=lzQ8GDBA8Is", "https://www.youtube.com/watch?v=Jt0mg8Z09SY", "https://www.youtube.com/watch?v=I6JZW7zMDfY", "https://www.youtube.com/watch?v=V2u-6XkB9O4", "https://www.youtube.com/watch?v=-ziSLGVQOSg", "https://www.youtube.com/watch?v=XFuAeGdUXQE", "https://www.youtube.com/watch?v=kHmoO_a4dDw", "https://www.youtube.com/watch?v=5XXe_5k_kno", "https://www.youtube.com/watch?v=Rk6YDzmqZ0I", "https://www.youtube.com/watch?v=5MgRt8zdr1I", "https://www.youtube.com/watch?v=50blPXs_F94", "https://www.youtube.com/watch?v=UrGLNtZ0rEg", "https://www.youtube.com/watch?v=atCwKBeq76w", "https://www.youtube.com/watch?v=QdfRZXsqDvc", "https://www.youtube.com/watch?v=lXgzQQ5XsHc", "https://www.youtube.com/watch?v=MAGoqMZRLB4", "https://www.youtube.com/watch?v=T1Ond-OwgU8", "https://www.youtube.com/watch?v=J-gkchrZIOU", "https://www.youtube.com/watch?v=3jrIK7YB0tE", "https://www.youtube.com/watch?v=RFxRTLmtsbE", "https://www.youtube.com/watch?v=0XSaKQlBZuE", "https://www.youtube.com/watch?v=cN-nfmrbvno", "https://www.youtube.com/watch?v=cUWyODR1_sA", "https://www.youtube.com/watch?v=uZ1a6hqxyJo", "https://www.youtube.com/watch?v=_sRkoZ-rbys", "https://www.youtube.com/watch?v=wdEibF6PXKY", "https://www.youtube.com/watch?v=KssCCe6KWcg", "https://www.youtube.com/watch?v=j3e_y9Bc7hs", "https://www.youtube.com/watch?v=QaP2vOdltP0", "https://www.youtube.com/watch?v=-n4kcvGS_Lk", "https://www.youtube.com/watch?v=e65ofKU6X6A", "https://www.youtube.com/watch?v=RDQsAvmPuT8", "https://www.youtube.com/watch?v=AFFaEgk-zeg", "https://www.youtube.com/watch?v=6aEx2xL37lw", "https://www.youtube.com/watch?v=H2GxBxeQGqA", "https://www.youtube.com/watch?v=Q_eE0NPArEY", "https://www.youtube.com/watch?v=WR8sxX0GoFo", "https://www.youtube.com/watch?v=Z_oIZzvSxeE", "https://www.youtube.com/watch?v=xL4oPjTACPo", "https://www.youtube.com/watch?v=aIz1cPfTRW4", "https://www.youtube.com/watch?v=DHG5-GxI_Es", "https://www.youtube.com/watch?v=VdqL8nbNbKg", "https://www.youtube.com/watch?v=mc7oGWgeA8s", "https://www.youtube.com/watch?v=clBEj47wjJM", "https://www.youtube.com/watch?v=Dsagy_qrjwc"], "author": "0"}
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=fo-U2DVLt-I", "https://www.youtube.com/watch?v=2G5MPJ58yiM", "https://www.youtube.com/watch?v=-bQpAmqrUZ0", "https://www.youtube.com/watch?v=0I-zlOQFbJQ", "https://www.youtube.com/watch?v=4vcq3-CvUQo", "https://www.youtube.com/watch?v=0I-zlOQFbJQ", "https://www.youtube.com/watch?v=-bQpAmqrUZ0", "https://www.youtube.com/watch?v=2G5MPJ58yiM", "https://www.youtube.com/watch?v=fo-U2DVLt-I", "https://www.youtube.com/watch?v=gdOZ9TEeMT4", "https://www.youtube.com/watch?v=lxWeR2f_15Q", "https://www.youtube.com/watch?v=Kk9xQDYWtMo", "https://www.youtube.com/watch?v=SdKB8CT9eIM", "https://www.youtube.com/watch?v=HmyYe6P3zSk", "https://www.youtube.com/watch?v=CvCoE9Z_fy0", "https://www.youtube.com/watch?v=8vfbUXa7cF4", "https://www.youtube.com/watch?v=___m8qk9rKA", "https://www.youtube.com/watch?v=mu_37H-n_Nc", "https://www.youtube.com/watch?v=UCmiwCWqRYY", "https://www.youtube.com/watch?v=fyEJJkVDAAk"], "author": "0"}
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=sRa1i1_K_-c", "https://www.youtube.com/watch?v=JHSyrs66vpk", "https://www.youtube.com/watch?v=Q-XPOwMztEA", "https://www.youtube.com/watch?v=VHufKcnlvzI", "https://www.youtube.com/watch?v=XINoGyLIkcE", "https://www.youtube.com/watch?v=wJkrgJI_7WY", "https://www.youtube.com/watch?v=CyJY5CFa1CE", "https://www.youtube.com/watch?v=DRKG19-hAlc", "https://www.youtube.com/watch?v=HJABO6w0EyA", "https://www.youtube.com/watch?v=r0noyvMPXpc", "https://www.youtube.com/watch?v=CYTEy3s-QRI", "https://www.youtube.com/watch?v=UJ6xBHmsGkk", "https://www.youtube.com/watch?v=RXfzu32HEOY", "https://www.youtube.com/watch?v=i7Yrtto5d_4", "https://www.youtube.com/watch?v=gIS593evoyU", "https://www.youtube.com/watch?v=9ztnSmWIDA0", "https://www.youtube.com/watch?v=nLP4ScjE1Wo", "https://www.youtube.com/watch?v=X5iiToqvBZ4"], "author": "0"}
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=ezhFoRFTO1c&index=1&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=nznS-Tx2_ak&index=2&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=Op9IpbjV4yA&index=3&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=oHubvkHp5fc&index=4&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=9rN67kPp5tQ&index=5&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=3CCzW49z0hI&index=6&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=Z7GWyasxb5E&index=7&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=2Mahk4wS0XA&index=8&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=QaLF7Cqy-uA&index=9&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=H027APFs8vc&index=10&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=-jus1FrPILs&index=11&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=EAinJ8fVGGU&index=12&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=2H94C-MGM4M&index=13&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=raE7uP2L1Vo&index=14&list=PLA5F145C2D3E4A298", "https://www.youtube.com/watch?v=nCyh83oprvU&index=15&list=PLA5F145C2D3E4A298"], "author": "0"}
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=gziaF9VT2D4", "https://www.youtube.com/watch?v=7Okz5qov7Go", "https://www.youtube.com/watch?v=olmgSyTtiwI", "https://www.youtube.com/watch?v=tQFMDOQXW30", "https://www.youtube.com/watch?v=Q4lN5HRjWCQ", "https://www.youtube.com/watch?v=UMlnE9QWma0", "https://www.youtube.com/watch?v=ix6V-l-ro1o", "https://www.youtube.com/watch?v=PdjYXcQPbig", "https://www.youtube.com/watch?v=e9mcNVTpovE", "https://www.youtube.com/watch?v=v3bAw8G-qQ4", "https://www.youtube.com/watch?v=WczTbnB0_lE", "https://www.youtube.com/watch?v=e05sBkIz2h0", "https://www.youtube.com/watch?v=fklAh1ncxng", "https://www.youtube.com/watch?v=t6Xwj1lVZFc", "https://www.youtube.com/watch?v=0IfjbF8aY4o", "https://www.youtube.com/watch?v=sLZ7RCxMCO4"], "author": "0"}
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=_XDlWepXuaM", "https://www.youtube.com/watch?v=lJUq8jzU0CA", "https://www.youtube.com/watch?v=OD4hSJybyCY", "https://www.youtube.com/watch?v=g2GVOqG5jWs", "https://www.youtube.com/watch?v=kgOkwV5xX8w", "https://www.youtube.com/watch?v=r6g2Iz3vzgY", "https://www.youtube.com/watch?v=pPArO-OI_3U", "https://www.youtube.com/watch?v=VcLk3fQ3Zwg", "https://www.youtube.com/watch?v=8gJv_NdTyZ0", "https://www.youtube.com/watch?v=z1GJMJbZybQ", "https://www.youtube.com/watch?v=1Qye2uNicbY", "https://www.youtube.com/watch?v=9lrWx7-PiUM", "https://www.youtube.com/watch?v=DVzUAqbAaaw", "https://www.youtube.com/watch?v=ojwkRSGXkn8", "https://www.youtube.com/watch?v=gX89Y7AgoXw", "https://www.youtube.com/watch?v=Nz30L9NYFf8", "https://www.youtube.com/watch?v=DMjBnLN2_ME", "https://www.youtube.com/watch?v=58MZ8ECtPTw", "https://www.youtube.com/watch?v=hvN3zMPn4fk", "https://www.youtube.com/watch?v=Op8T7MltzbU", "https://www.youtube.com/watch?v=Kp9hIeC828o", "https://www.youtube.com/watch?v=eP9nD0TsqEI", "https://www.youtube.com/watch?v=7jKA8bKfIic", "https://www.youtube.com/watch?v=6OkQiVWIp_E", "https://www.youtube.com/watch?v=PemXuiZ0iAc", "https://www.youtube.com/watch?v=hXTT8ZkwJ_o", "https://www.youtube.com/watch?v=8dO4mV7fuhU", "https://www.youtube.com/watch?v=5K7Q409AWKk", "https://www.youtube.com/watch?v=Lqre-N_28Yo", "https://www.youtube.com/watch?v=1DD_NCM_RJs"], "author": "0"}
-1
View File
@@ -1 +0,0 @@
{"author": "0", "playlist": ["https://www.youtube.com/watch?v=cvaIgq5j2Q8", "https://www.youtube.com/watch?v=Q69_lnD6GhE", "https://www.youtube.com/watch?v=TEsJW9KXuOc", "https://www.youtube.com/watch?v=McfkDbjfllo", "https://www.youtube.com/watch?v=lN3psvKJNvQ", "https://www.youtube.com/watch?v=bOpLs6qfYoI", "https://www.youtube.com/watch?v=cd8e2ECUHL4", "https://www.youtube.com/watch?v=7DVGCs6kWmc", "https://www.youtube.com/watch?v=pUyjKFclkCY", "https://www.youtube.com/watch?v=G75WApUdYJ4", "https://www.youtube.com/watch?v=oSMCZ0Y1nUE", "https://www.youtube.com/watch?v=K8qLdz9GT-0", "https://www.youtube.com/watch?v=QYKFwX1l4Rw", "https://www.youtube.com/watch?v=GmbpUKp6J6M", "https://www.youtube.com/watch?v=FLzIEKz8F20", "https://www.youtube.com/watch?v=NSZFKDOs-yc", "https://www.youtube.com/watch?v=mdML5WPEhEY", "https://www.youtube.com/watch?v=gRdgASty-1g", "https://www.youtube.com/watch?v=zcI8_rLWk3g", "https://www.youtube.com/watch?v=rRh_d2qjavQ", "https://www.youtube.com/watch?v=afJnOSqbP8k", "https://www.youtube.com/watch?v=6xYaoyr0D6E", "https://www.youtube.com/watch?v=oV2lyc5UKXc", "https://www.youtube.com/watch?v=fzB-oRQiI-s", "https://www.youtube.com/watch?v=jSEnYAPEOEQ", "https://www.youtube.com/watch?v=AGWGmkouZxs", "https://www.youtube.com/watch?v=SByfHj_cBQ4", "https://www.youtube.com/watch?v=UQFrKtIFqd8", "https://www.youtube.com/watch?v=HYm3xJabxHw", "https://www.youtube.com/watch?v=mz3h93cH3Zo", "https://www.youtube.com/watch?v=cXWTFV8Z-i0", "https://www.youtube.com/watch?v=oedmZoHjlHE", "https://www.youtube.com/watch?v=x9WpVoAC3tk", "https://www.youtube.com/watch?v=SOg73IfyoFw", "https://www.youtube.com/watch?v=RAO1kWJdYz8", "https://www.youtube.com/watch?v=xkIytYlDD_o", "https://www.youtube.com/watch?v=c0mX-5q3mrY", "https://www.youtube.com/watch?v=OQktBoamgXc", "https://www.youtube.com/watch?v=7RGTFmF-brI", "https://www.youtube.com/watch?v=h2XTsWgN0CU", "https://www.youtube.com/watch?v=2yhhK_2HZzQ", "https://www.youtube.com/watch?v=jx5oOXZOiWc", "https://www.youtube.com/watch?v=Xh8uiKbT9_E", "https://www.youtube.com/watch?v=ksme1nbbTAc", "https://www.youtube.com/watch?v=cSpnJjM1H24", "https://www.youtube.com/watch?v=6_svEzbs15w", "https://www.youtube.com/watch?v=gbOuRQNwtN4", "https://www.youtube.com/watch?v=EWQpFKhEEgI", "https://www.youtube.com/watch?v=GpOv05A1nf0", "https://www.youtube.com/watch?v=cyW2ajAVyfA", "https://www.youtube.com/watch?v=R7IJC6nMons", "https://www.youtube.com/watch?v=bYlUbG01-wA", "https://www.youtube.com/watch?v=vu5Q5Fox2ng", "https://www.youtube.com/watch?v=9buluPWlkAA", "https://www.youtube.com/watch?v=hDNcUGd88Qo", "https://www.youtube.com/watch?v=w77inmTq04E", "https://www.youtube.com/watch?v=VUoH08wbZ9E", "https://www.youtube.com/watch?v=YxqwOq2hA-k", "https://www.youtube.com/watch?v=G8Gb1cwLO3s", "https://www.youtube.com/watch?v=EjoDnuoSDkg", "https://www.youtube.com/watch?v=lfwVMlBRlDY", "https://www.youtube.com/watch?v=bYDxqf2zR2Y", "https://www.youtube.com/watch?v=qbKz5nov1KU", "https://www.youtube.com/watch?v=ZMKWC3Hi8p0", "https://www.youtube.com/watch?v=wyNc0WtHw6I", "https://www.youtube.com/watch?v=19hhHW9C4FA", "https://www.youtube.com/watch?v=pUKmdDaYhL8", "https://www.youtube.com/watch?v=pkyLAWX5V30", "https://www.youtube.com/watch?v=oY1iMtBExOo", "https://www.youtube.com/watch?v=4ugZ7NMiW50", "https://www.youtube.com/watch?v=EPElX0cjm-w", "https://www.youtube.com/watch?v=535ONQFgu2M", "https://www.youtube.com/watch?v=O6NvsM49N6w", "https://www.youtube.com/watch?v=McRA3CKvJZ4", "https://www.youtube.com/watch?v=2pKAcywkr0s", "https://www.youtube.com/watch?v=OFDB9SV6ug8", "https://www.youtube.com/watch?v=tyaPqW0bO5M", "https://www.youtube.com/watch?v=eprDsre1tQo", "https://www.youtube.com/watch?v=vQMSdPgAj6Q", "https://www.youtube.com/watch?v=Tvj2Q--JMhA", "https://www.youtube.com/watch?v=b8cOZ6iJ5PY", "https://www.youtube.com/watch?v=-1-DE0lDATQ", "https://www.youtube.com/watch?v=wL-2Cu6zSNk", "https://www.youtube.com/watch?v=vjd5ndxjt-8", "https://www.youtube.com/watch?v=YTpgmqlX_OA", "https://www.youtube.com/watch?v=eUEtFvjrqMg", "https://www.youtube.com/watch?v=1zn-5YVG3Sw", "https://www.youtube.com/watch?v=oMuvGDUgLfw", "https://www.youtube.com/watch?v=bbDY5bRcZrw", "https://www.youtube.com/watch?v=-jcsoAO83X0", "https://www.youtube.com/watch?v=fU_Vm5dVHgc", "https://www.youtube.com/watch?v=-yShvzoWrsA", "https://www.youtube.com/watch?v=uI4Aj-KbhcY", "https://www.youtube.com/watch?v=TU-5jJnK_7o", "https://www.youtube.com/watch?v=rnP8JZkmN68", "https://www.youtube.com/watch?v=yOMkGjp_m1Q", "https://www.youtube.com/watch?v=NOgZ-XNOHhU", "https://www.youtube.com/watch?v=A2qJNZklnuQ", "https://www.youtube.com/watch?v=F0GcEI-R9mM", "https://www.youtube.com/watch?v=cON1VmHX1jE"]}
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=nU263Ud3LM4", "https://www.youtube.com/watch?v=m1KVDI7vbEM", "https://www.youtube.com/watch?v=D0j9AOEhzO8", "https://www.youtube.com/watch?v=pjGgfZ8JkyA", "https://www.youtube.com/watch?v=PK1yjBgxgho", "https://www.youtube.com/watch?v=eQdQ3ngu0n8", "https://www.youtube.com/watch?v=jFEOKz9-Xv8", "https://www.youtube.com/watch?v=rxqHQ9nOZcc", "https://www.youtube.com/watch?v=opXXFAl8lkY", "https://www.youtube.com/watch?v=mo_CY0HcIws", "https://www.youtube.com/watch?v=m1ud5-glY6M", "https://www.youtube.com/watch?v=fzcCjDb65QI", "https://www.youtube.com/watch?v=fbcjFvXGXYQ", "https://www.youtube.com/watch?v=TWrq8rY47Oo", "https://www.youtube.com/watch?v=9_H9rnqeDDU", "https://www.youtube.com/watch?v=jHxPVXfMjk4", "https://www.youtube.com/watch?v=gOg1sj1abyw", "https://www.youtube.com/watch?v=kFNHlJ6yvEA", "https://www.youtube.com/watch?v=JWsLm7mND1k", "https://www.youtube.com/watch?v=JbCtVIDMEAs", "https://www.youtube.com/watch?v=j2qWM1cnLrg", "https://www.youtube.com/watch?v=XLuSY7jTBxg", "https://www.youtube.com/watch?v=X7gHzu7SBlw", "https://www.youtube.com/watch?v=aP0m-PJozWo", "https://www.youtube.com/watch?v=4MNAktk9ei8", "https://www.youtube.com/watch?v=2XjouKSkSeM", "https://www.youtube.com/watch?v=0d1ZdB_f8h4", "https://www.youtube.com/watch?v=7Wmk58-o_r8", "https://www.youtube.com/watch?v=S1-VyHIx_SY", "https://www.youtube.com/watch?v=YZdy9-4KiEo", "https://www.youtube.com/watch?v=OuSzXP-Hj_A", "https://www.youtube.com/watch?v=epwA8VIbEFo", "https://www.youtube.com/watch?v=JuqZTPyzHfg", "https://www.youtube.com/watch?v=2YodHq4iZFc", "https://www.youtube.com/watch?v=_a3hoWJDXSs", "https://www.youtube.com/watch?v=-1KBQTGSDFA", "https://www.youtube.com/watch?v=4P4b_YTNC7c", "https://www.youtube.com/watch?v=AOZL3kkCUBQ", "https://www.youtube.com/watch?v=ul-brw07gJo", "https://www.youtube.com/watch?v=pEsQi6GRwhM", "https://www.youtube.com/watch?v=SWZvaWzdgek", "https://www.youtube.com/watch?v=HA9Ws-_iCEw", "https://www.youtube.com/watch?v=zUfJaqFV0hk", "https://www.youtube.com/watch?v=vdSA6waSFs8", "https://www.youtube.com/watch?v=g76W944CXzo", "https://www.youtube.com/watch?v=HwpJnvadoIQ", "https://www.youtube.com/watch?v=2Hw597sv7ZM", "https://www.youtube.com/watch?v=9ts_foHlT_w", "https://www.youtube.com/watch?v=B4u0FAJIvwg", "https://www.youtube.com/watch?v=3A_pI3UuMn8", "https://www.youtube.com/watch?v=AZl1LFtUQNA", "https://www.youtube.com/watch?v=ERy3UlFxFoc", "https://www.youtube.com/watch?v=txzD9iHBu-w", "https://www.youtube.com/watch?v=eaK564p5ksc", "https://www.youtube.com/watch?v=H9bDN_aZvNI", "https://www.youtube.com/watch?v=Gv9jl_vGb-w", "https://www.youtube.com/watch?v=xLD4J-qYf8k", "https://www.youtube.com/watch?v=h9SFxVFKZw0", "https://www.youtube.com/watch?v=txzD9iHBu-w", "https://www.youtube.com/watch?v=eaK564p5ksc", "https://www.youtube.com/watch?v=H9bDN_aZvNI", "https://www.youtube.com/watch?v=Gv9jl_vGb-w", "https://www.youtube.com/watch?v=xLD4J-qYf8k", "https://www.youtube.com/watch?v=h9SFxVFKZw0", "https://www.youtube.com/watch?v=exG220Mur04"], "author": "0"}
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=pfAuWjCXwnw", "https://www.youtube.com/watch?v=ToLBU-zJ2S0", "https://www.youtube.com/watch?v=Z-7OySB0Yb4", "https://www.youtube.com/watch?v=91jSk2G6Dr0", "https://www.youtube.com/watch?v=pbTgi_gLppQ", "https://www.youtube.com/watch?v=8keRZa7hAqM", "https://www.youtube.com/watch?v=XfHdXHqWZyE", "https://www.youtube.com/watch?v=NkYxsnWj8Ds", "https://www.youtube.com/watch?v=XSGxYnnwcLg", "https://www.youtube.com/watch?v=ieTtWb7oHIo", "https://www.youtube.com/watch?v=y2F1BL_p5jk", "https://www.youtube.com/watch?v=Waf_AcAfPWA", "https://www.youtube.com/watch?v=dcx3mzLySew", "https://www.youtube.com/watch?v=-VruEefJAHI", "https://www.youtube.com/watch?v=EUxNv_9Zxns", "https://www.youtube.com/watch?v=C3yP_-lOhzA", "https://www.youtube.com/watch?v=cpjh4_ReUCw", "https://www.youtube.com/watch?v=urmoWFQw4aE", "https://www.youtube.com/watch?v=TAzxVL-xWww", "https://www.youtube.com/watch?v=zve5kLOjITU", "https://www.youtube.com/watch?v=2QceNDYmbAo", "https://www.youtube.com/watch?v=DV8zA27UdVU", "https://www.youtube.com/watch?v=uPQMYfXLpKo"], "author": "0"}
-1
View File
@@ -1 +0,0 @@
{"playlist": ["https://www.youtube.com/watch?v=lG5aSZBAuPs", "https://www.youtube.com/watch?v=uf9WLPZK2AU", "https://www.youtube.com/watch?v=PMd9eYXT0mM", "https://www.youtube.com/watch?v=J3JNlHQ-hj8", "https://www.youtube.com/watch?v=d8Q5kzUlim8", "https://www.youtube.com/watch?v=6sQCATXFzsI", "https://www.youtube.com/watch?v=KrxJQAYdfXo", "https://www.youtube.com/watch?v=V18pa_VDw3I", "https://www.youtube.com/watch?v=h4dzCbjtyW8", "https://www.youtube.com/watch?v=Z_8zEMF3EaY", "https://www.youtube.com/watch?v=ODkX3x1SDHo", "https://www.youtube.com/watch?v=yV2Z62mSoOA", "https://www.youtube.com/watch?v=LgE7gqts_Kg", "https://www.youtube.com/watch?v=EizM69vZebg", "https://www.youtube.com/watch?v=fhOjNhRZ1Gc", "https://www.youtube.com/watch?v=ITjX9IOJdLA"], "author": "0"}
-551
View File
@@ -1,551 +0,0 @@
A bird in the hand is worth two in the bush
A chain is only as strong as its weakest link
A change is as good as a rest
A drowning man will clutch at a straw.
A fair day's work for a fair day's pay
A fool and his money are soon parted
A friend in need is a friend indeed
A golden key can open any door
A good beginning makes a good ending.
A good man is hard to find
A house divided against itself cannot stand
A house is not a home
A journey of a thousand miles begins with a single step
A leopard cannot change its spots
A little knowledge is a dangerous thing
A little of what you fancy does you good
A man who is his own lawyer has a fool for his client
A man with a hammer sees every problem as a nail
A miss is as good as a mile
A new broom sweeps clean, but an old one knows where the dirt is.
A nod is as good as a wink to a blind horse
A penny saved is a penny earned
A person is known by the company he keeps
A picture is worth a thousand words
A place for everything and everything in its place
A poor workman always blames his tools
A problem shared is a problem halved
A prophet is not recognized in his own land
A rising tide lifts all boats
A rolling stone gathers no moss
A soft answer turneth away wrath
A stitch in time saves nine
A swarm in May is worth a load of hay; a swarm in June is worth a silver spoon; but a swarm in July is not worth a fly.
A thing of beauty is a joy forever
A trouble shared is a trouble halved
A volunteer is worth twenty pressed men
A watched pot never boils
A woman's place is in the home
A man works from sun to sun but a woman's work is never done,
A word to the wise is enough,
Absence makes the heart grow fonder
Absolute power corrupts absolutely.
Accidents will happen (in the best-regulated families)
Actions speak louder than words.
Adversity makes strange bedfellows
All good things come to he who waits
All good things must come to an end,
All is grist that comes to the mill
All roads lead to Rome,
All that glitters is not gold,
All the world loves a lover
All things come to those who wait
All things must pass
All work and no play makes Jack a dull boy,
All you need is love
All is fair in love and war
All is for the best in the best of all possible worlds
All is well that ends well
An apple a day keeps the doctor away
An army marches on its stomach.
An Englishman's home is his castle
Another day, another dollar.
An ounce of prevention is worth a pound of cure
Any port in a storm,
Any publicity is good publicity
April showers bring forth May flowers,
As you make your bed, so you must lie upon it
As you sow so shall you reap
Ask a silly question and you will get a silly answer
Ask my companion if I be a thief
Ask no questions and hear no lies
Attack is the best form of defense
Bad news travels fast
Barking dogs seldom bite,
Beauty is in the eye of the beholder
Beauty is only skin deep,
Beggars should not be choosers,
Behind every great man, there is a great woman
Better late than never
Better safe than sorry
Better the Devil you know than the Devil you do not
Better to have loved and lost than never to have loved at all
Better to light one candle than to curse the darkness
Better to remain silent and be thought a fool than to speak and remove all doubt
Better wear out than rust out.
Beware of Greeks bearing gifts
Big fish eat little fish
Birds of a feather flock together
Blood is thicker than water
Boys will be boys
Brevity is the soul of wit
Business before pleasure
Caesar's wife must be above suspicion
Careless talk costs lives
Charity begins at home
Cheats never prosper
Children should be seen and not heard
Christmas comes but once a year
Cleanliness is next to godliness
Clothes make the man
Cold hands, warm heart
Comparisons are odious
Count your blessings
Courage is the measure of a Man, Beauty is the measure of a Woman
Cowards may die many times before their death
Crime does not pay
Cut your coat according to your cloth,
Curiosity killed the cat
Dead men tell no tales
Devil take the hindmost
Discretion is the better part of valour
Do as I say, not as I do
Do as you would be done by
Do unto others as you would have them do unto you
Do not bite the hand that feeds you
Do not burn your bridges behind you
Do not cast your pearls before swine
Do not cry over spilt milk
Do not change horses in midstream
Do not count your chickens before they are hatched
Do not cross the bridge till you come to it
Do not cut off your nose to spite your face
Do not keep a dog and bark yourself
Do not let the bastards grind you down
Do not look a gift horse in the mouth
Do not make a mountain of a mole hill
Do not meet troubles half-way
Do not put all your eggs in one basket
Do not put the cart before the horse
Do not put new wine into old bottles
Do not rock the boat
Do not spoil the ship for a ha'pworth of tar
Do not throw pearls to swine
Do not teach your Grandmother to suck eggs
Do not throw the baby out with the bathwater
Do not try to walk before you can crawl
Do not upset the apple-cart
Do not wash your dirty linen in public
Doubt is the beginning, not the end, of wisdom
Early to bed and early to rise, makes a man healthy, wealthy and wise
East is east, and west is west
East, west, home is best,
Easy come, easy go
Eat breakfast as a king, lunch as a merchant and supper as a beggar
Eat, drink and be merry, for tomorrow we die
Empty vessels make the most noise
Enough is as good as a feast
Enough is enough
Even a worm will turn
Every cloud has a silver lining
Every dog has his day
Every Jack has his Jill
Every little bit helps
Every man for himself, and the Devil take the hindmost
Every man has his price
Every picture tells a story
Every stick has two ends
Everybody wants to go to heaven but nobody wants to die
Everything comes to those who wait
Every tide has its ebb
Fact is stranger than fiction
Failing to plan is planning to fail
Faint heart never won fair lady
Fair exchange is no robbery
Faith will move mountains
Familiarity breeds contempt
Feed a cold and starve a fever
Fight fire with fire
Finders keepers, losers weepers
First come, first served
First impressions are the most lasting
First things first
Fish always stinks from the head downwards
Fish and guests smell after three days
Flattery will get you nowhere
Fools rush in where angels fear to tread
For want of a nail the shoe was lost; for want of a shoe the horse was lost; and for want of a horse the man was lost
Forewarned is forearmed
Fortune favours the brave
Genius is an infinite capacity for taking pains
Give a dog a bad name and hang him
Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime
Give a man rope enough and he will hang himself
Give credit where credit is due
Give him an inch and he will take a mile
God helps those who help themselves
Good fences make good neighbours
Good talk saves the food
Good things come to those who wait
Great minds think alike
Half a loaf is better than no bread
Handsome is as handsome does
Hard cases make bad law
Hard work never did anyone any harm
Haste makes waste
He that goes a-borrowing, goes a-sorrowing
He who can does, he who cannot, teaches
He who fights and runs away may live to fight another day
He who hesitates is lost
He who laughs last laughs best
He who lives by the sword shall die by the sword
He who loves the world as his body may be entrusted with the empire.
He who makes a beast out of himself gets rid of the pain of being a man
He who pays the piper calls the tune
He who knows does not speak. He who speaks does not know.
He who sups with the Devil should have a long spoon
Hell hath no fury like a woman scorned
Hindsight is always twenty-twenty
History repeats itself
Home is where the heart is
Honesty is the best policy
Hope springs eternal
Horses for courses
Hunger never knows the taste, sleep never knows the comfort
If anything can go wrong, it will
If a job is worth doing, it is worth doing well
If at first you do not succeed, try, try again
If God had meant us to fly, he would have given us wings
If ifs and ands were pots and pans, there would be no work for tinkers
When life gives you lemons, make lemonade
If the cap fits, wear it
If the mountain will not come to Mohammed, then Mohammed must go to the mountain
If we're not back by dawn, call the President.
If wealth is lost, nothing is lost. If health is lost, something is lost. If character is lost, everything is lost.
If wishes were horses, beggars would ride
If you're growing in Age,then you're nearing to the Graveyard
If you cannot be good, be careful
If you cannot beat them, join them
If you cannot stand the heat, get out of the kitchen
If you give a mouse a cookie, he'll always ask for a glass of milk
If you think that you know everything, then you're a Jack ass
If you lie down with dogs, you will get up with fleas
If you pay peanuts, you get monkeys
If you steal from one author, it is plagiarism; if you steal from many, it is research.
If you want a thing done well, do it yourself
If you have never seen the bottom of the tree, you cannot know how tall it stands
Imitation is the sincerest form of flattery
In for a penny, in for a pound
In the kingdom of the blind, the one eyed man is king
In the midst of life, we are in death
Into every life a little rain must fall
It goes without saying
It is all grist to the mill
It is an ill wind that blows no one any good
It is best to be on the safe side
It is better to give than to receive
It is better to have loved and lost than never to have loved at all
It is better to cultivate a Land with two Bulls, rather working under Boss who never gives Wage when asked
It is better to light a candle than curse the darkness
It is better to travel hopefully than to arrive
It is easy to be wise after the event
It is never too late
It is no use crying over spilt milk
It is no use locking the stable door after the horse has bolted
It is on
It is the early bird that gets the worm
It is the empty can that makes the most noise
It is the squeaky wheel that gets the grease
It never rains but it pours
It takes a thief to catch a thief
It needs a Hundred Lies to cover a Single Lie
It takes all sorts to make a world
It takes one to know one
It takes two to tango
I'm going to have to give you the pink slip
Jack of all trades, master of none
Jack of all trades, master of some
Judge not, that ye be not judged.
Keep your friends close and your enemies closer.
Trust in God and keep your powder dry
Kindness in words creates confidence. Kindness in thinking creates profoundness. Kindness in giving creates love.
Knowledge is power, guard it well.
Laugh before breakfast, cry before supper.
Laugh and the world laughs with you, weep and you weep alone
Laughter is the best medicine
Least said, soonest mended
Less is more
Let bygones be bygones
Let not the sun go down on your wrath
Let sleeping dogs lie
Let the buyer beware
Let the dead bury the dead
Let the punishment fit the crime
Let well alone
Let your hair down.
Life begins at forty
Life is not all beer and skittles
Life is what you make it
Lightning never strikes twice in the same place
Like father, like son,
Little pitchers have big ears
Little strokes fell great oaks
Little things please little minds
Live and let live
Live for today, for tomorrow never comes
Loose lips, sink ships
Look before you leap
Love is blind
Love of money is the root of all kinds of evil.
Love makes the world go around
Love will find a way
Make hay while the sun shines
Make love not war
Man does not live by bread alone
Manners maketh man
Many a little makes a mickle
Many a mickle makes a muckle
Many a true word is spoken in jest
Many hands make light work
March comes in like a lion and goes out like a lamb
Marriages are made in heaven
Marry in haste, repent at leisure
Memory is the treasure of the mind
Men get spoiled by staying, Women get spoiled by wandering
Might is right
Might makes right
Mighty oaks from little acorns grow
Milking the bull
Misery loves company
Moderation in all things
Monday's child is fair of face, Tuesday's child is full of grace, Wednesday's child is full of woe, Thursday's child has far to go, Friday's child is loving and giving, Saturday's child works hard for its living, and a child that is born on the Sabbath day is fair and wise and good and gay.
Money does not grow on trees
Money earned by deceit, goes by deceit
Money is not everything
Money makes the world go around
Money talks
Money makes many things, but also makes devil dance
More haste, less speed
Music has charms to soothe the savage beast
Nature abhors a vacuum,
Never reveal a man's wage, and woman's age
Necessity is the mother of invention
Needs must when the devil drives
Never cast a clout until May be out
Never give a sucker an even break
Never judge a book by its cover
Never let the sun go down on your anger
Never look a gift horse in the mouth
Never put off until tomorrow what you can do today
Never speak ill of the dead
Never say never
Never tell tales out of school
Nine tailors make a man,
No guts, no glory
No man can serve two masters
No man is an island
No names, no pack-drill
No news is good news
No one can make you feel inferior without your consent
No pain, no gain
No rest for the wicked
Nothing is certain but death and taxes
Nothing succeeds like success,
Nothing ventured, nothing gained
Once a witch always a witch
Oil and water do not mix
Old soldiers never die; they just fade away
Once a thief, always a thief
Once bitten, twice shy
One good turn deserves another
One half of the world does not know how the other half lives
One hand washes the other
One man's meat is another man's poison
One might as well be hanged for a sheep as a lamb
One law for the rich and another for the poor
One swallow does not make a summer
One who believes in Sword, dies by the Sword
One year's seeding makes seven years weeding
Only fools and horses work
Opportunity never knocks twice at any man's door
Out of sight, out of mind
Over greedy man, over wrathful woman will never flourish
Parsley seed goes nine times to the Devil
Patience is a virtue
Pearls of wisdom
Penny wise and pound foolish
People who live in glass houses should not throw stones
Physician, heal thyself
Possession is nine-tenths of the law
Power corrupts; absolute power corrupts absolutely
Practice makes perfect
Practice what you preach
Prevention is better than cure
Pride goes before a fall
Procrastination is the thief of time
Put your best foot forward
Put your money where your mouth is
Red sky at night shepherds delight; red sky in the morning, shepherds warning
Revenge is a dish best served cold
Revenge is sweet
Rome was not built in a day,
Right or wrong, my country
See a penny and pick it up, all the day you will have good luck; see a penny and let it lay, bad luck you will have all day
See no evil, hear no evil, speak no evil
Seeing is believing
Seek and ye shall find
Set a thief to catch a thief
Shiny are the distant hills
Shrouds have no pockets
Silence is golden
Slow and steady wins the race
Slow but sure
Softly, softly, catchee monkey
Sometimes we are the student. Sometimes we are the master. And sometimes we are merely the lesson
Spare the rod and spoil the child
Speak as you find
Speak softly and carry a big stick
Speech is silver
Sticks and stones may break my bones, but words will never hurt me
Still waters run deep
Strike while the iron is hot
Stupid is as stupid does
Success has many fathers, while failure is an orphan
Take care of the pennies, and the pounds will take care of themselves
Talk is cheap
Talk of the Devil, and he is bound to appear
Tell me who your friends are, and I'll tell you who you are
Tell the truth and shame the Devil
That which does not kill us makes us stronger
The age of miracles is past
The apple never falls far from the tree
The best defence is a good offence
The best-laid schemes of mice and men often go awry
The best things in life are free
The bigger they are, the harder they fall
The boy is father to the man
The bread never falls but on its buttered side
The child is the father of the man
The cobbler always wears the worst shoes
The course of true love never did run smooth
The customer is always right
The darkest hour is just before the dawn
The devil finds work for idle hands
The Devil looks after his own
The early bird catches the worm
The end justifies the means
The exception which proves the rule
The female of the species is more deadly than the male
The good die young
The grass is always greener on the other side of the fence
The hand that rocks the cradle rules the world
The husband is always the last to know
The innocent seldom find an uncomfortable pillow.
The labourer is worthy of his hire
The leopard does not change his spots
The longest day must have an end
The longest journey starts with a single step
The moon is made of green cheese
The more the merrier
The more things change, the more they stay the same
The only way to understand a woman is to love her
The pen is mightier than the sword
The proof of the pudding is in the eating
The road to Hell is paved with good intentions
The shoemaker's son always goes barefoot
The squeaking wheel gets the grease
The straw that broke the camel's back
The way to a man's heart is through his stomach
There ain't no such thing as a free lunch
There are more ways of killing a cat than choking it with cream
There are none so blind as those that will not see
There are two sides to every question
There but for the grace of God go I
There is an exception to every rule
There are always more fish in the sea
There is honour among thieves
There is many a good tune played on an old fiddle
There is many a slip 'twixt cup and lip
There is more than one way to skin a cat
There is no accounting for tastes
There is no fool like an old fool
There is no place like home
There is no smoke without fire
There is no such thing as a free lunch
There is no such thing as bad publicity
There is no time like the present
There is none so blind as those who will not see
There's none so deaf as those who will not hear
There is nowt so queer as folk
There is one born every minute
There is safety in numbers
They that sow the wind shall reap the whirlwind
Third time is a charm
Those who do not learn from history are doomed to repeat it
Those who live in glass houses should not throw stones
Those who sleep with dogs will rise with fleas
Time and tide wait for no man
Time flies
Time is a great healer
Time is money
Time will tell
Tis better to have loved and lost than never to have loved at all
To be worn out is to be renewed.
To each his own.
To err is human, to forgive divine
To the victor go the spoils
To travel hopefully is a better thing than to arrive
Tomorrow is another day
Tomorrow never comes
Too many cooks spoil the broth
Truth is stranger than fiction
Truth will out
Two blacks do not make a white
Two heads are better than one
Two is company, but three is a crowd
Two wrongs do not make a right
Variety is the spice of life.
Walk softly but carry a big stick.
Walnuts and pears you plant for your heirs
Waste not, want not
What cannot be cured must be endured
What goes around, comes around
What goes up must come down
What you lose on the swings you gain on the roundabouts
What is sauce for the goose is sauce for the gander
When in Rome, do as the Romans do.
When it rains it pours.
When the cat is away, the mice will play
When the going gets tough, the tough get going
When the oak is before the ash, then you will only get a splash; when the ash is before the oak, then you may expect a soak
When three women gather, it becomes noisy.
What the eye does not see, the heart does not grieve over
Where there is a will there is a way
Where there is muck there is brass
Whether you think you can, or you think you can't, you're right.
While there is life there is hope
Whom the Gods love die young
Why keep a dog and bark yourself?
With a responsibility comes great power
Woman is the root of both good and evil
Wonders will never cease
Work expands so as to fill the time available
Worrying never did anyone any good
You ain't seen nothing yet
You are never too old to learn
You are what you eat
You can have too much of a good thing
You can lead a horse to water, but you cannot make it drink
You cannot have your cake and eat it too
You cannot get blood out of a stone
You cannot make a silk purse from a sow's ear
You cannot make an omelette without breaking eggs
You cannot make bricks without straw
You cannot run with the hare and hunt with the hounds
You cannot teach an old dog new tricks
You cannot judge a book by its cover
You cannot win them all
You catch more flies with honey than with vinegar
You pay your money and you take your choice
Youth is wasted on the young
You must have rocks in your head
-2057
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
import sys
import typing
import discord
# Let's do all the dumb version checking in one place.
if discord.version_info.major < 1:
print("You are not running the rewritten version of discord.py.\n\n"
"In order to use Red v3 you MUST be running d.py version"
" >= 1.0.0.")
sys.exit(1)
+167
View File
@@ -0,0 +1,167 @@
#!/usr/bin/env python
# Discord Version check
import sys
import discord
from redbot.core.bot import Red, ExitCodes
from redbot.core.cog_manager import CogManagerUI
from redbot.core.data_manager import load_basic_configuration, config_file
from redbot.core.json_io import JsonIO
from redbot.core.global_checks import init_global_checks
from redbot.core.events import init_events
from redbot.core.cli import interactive_config, confirm, parse_cli_flags, ask_sentry
from redbot.core.core_commands import Core
from redbot.core.dev_commands import Dev
from redbot.core import rpc, __version__
import asyncio
import logging.handlers
import logging
import os
#
# Red - Discord Bot v3
#
# Made by Twentysix, improved by many
#
def init_loggers(cli_flags):
# d.py stuff
dpy_logger = logging.getLogger("discord")
dpy_logger.setLevel(logging.WARNING)
console = logging.StreamHandler()
console.setLevel(logging.WARNING)
dpy_logger.addHandler(console)
# Red stuff
logger = logging.getLogger("red")
red_format = logging.Formatter(
'%(asctime)s %(levelname)s %(module)s %(funcName)s %(lineno)d: '
'%(message)s',
datefmt="[%d/%m/%Y %H:%M]")
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setFormatter(red_format)
if cli_flags.debug:
os.environ['PYTHONASYNCIODEBUG'] = '1'
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.WARNING)
from redbot.core.data_manager import core_data_path
logfile_path = core_data_path() / 'red.log'
fhandler = logging.handlers.RotatingFileHandler(
filename=str(logfile_path), encoding='utf-8', mode='a',
maxBytes=10**7, backupCount=5)
fhandler.setFormatter(red_format)
logger.addHandler(fhandler)
logger.addHandler(stdout_handler)
# Sentry stuff
sentry_logger = logging.getLogger("red.sentry")
sentry_logger.setLevel(logging.WARNING)
return logger, sentry_logger
async def _get_prefix_and_token(red, indict):
"""
Again, please blame <@269933075037814786> for this.
:param indict:
:return:
"""
indict['token'] = await red.db.token()
indict['prefix'] = await red.db.prefix()
indict['enable_sentry'] = await red.db.enable_sentry()
def list_instances():
if not config_file.exists():
print("No instances have been configured! Configure one "
"using `redbot-setup` before trying to run the bot!")
sys.exit(1)
else:
data = JsonIO(config_file)._load_json()
text = "Configured Instances:\n\n"
for instance_name in sorted(data.keys()):
text += "{}\n".format(instance_name)
print(text)
sys.exit(0)
def main():
cli_flags = parse_cli_flags(sys.argv[1:])
if cli_flags.list_instances:
list_instances()
elif not cli_flags.instance_name:
print("Error: No instance name was provided!")
sys.exit(1)
load_basic_configuration(cli_flags.instance_name)
log, sentry_log = init_loggers(cli_flags)
description = "Red - Version {}".format(__version__)
red = Red(cli_flags, description=description, pm_help=None)
init_global_checks(red)
init_events(red, cli_flags)
red.add_cog(Core(red))
red.add_cog(CogManagerUI())
if cli_flags.dev:
red.add_cog(Dev())
loop = asyncio.get_event_loop()
tmp_data = {}
loop.run_until_complete(_get_prefix_and_token(red, tmp_data))
token = os.environ.get("RED_TOKEN", tmp_data['token'])
prefix = cli_flags.prefix or tmp_data['prefix']
if token is None or not prefix:
if cli_flags.no_prompt is False:
new_token = interactive_config(red, token_set=bool(token),
prefix_set=bool(prefix))
if new_token:
token = new_token
else:
log.critical("Token and prefix must be set in order to login.")
sys.exit(1)
loop.run_until_complete(_get_prefix_and_token(red, tmp_data))
if tmp_data['enable_sentry']:
red.enable_sentry()
cleanup_tasks = True
try:
loop.run_until_complete(red.start(token, bot=not cli_flags.not_bot))
except discord.LoginFailure:
cleanup_tasks = False # No login happened, no need for this
log.critical("This token doesn't seem to be valid. If it belongs to "
"a user account, remember that the --not-bot flag "
"must be used. For self-bot functionalities instead, "
"--self-bot")
db_token = red.db.token()
if db_token and not cli_flags.no_prompt:
print("\nDo you want to reset the token? (y/n)")
if confirm("> "):
loop.run_until_complete(red.db.token.set(""))
print("Token has been reset.")
except KeyboardInterrupt:
log.info("Keyboard interrupt detected. Quitting...")
loop.run_until_complete(red.logout())
red._shutdown_mode = ExitCodes.SHUTDOWN
except Exception as e:
log.critical("Fatal exception", exc_info=e)
sentry_log.critical("Fatal Exception", exc_info=e)
loop.run_until_complete(red.logout())
finally:
rpc.clean_up()
if cleanup_tasks:
pending = asyncio.Task.all_tasks(loop=red.loop)
gathered = asyncio.gather(
*pending, loop=red.loop, return_exceptions=True)
gathered.cancel()
sys.exit(red._shutdown_mode.value)
if __name__ == '__main__':
main()
+5
View File
@@ -0,0 +1,5 @@
from .admin import Admin
def setup(bot):
bot.add_cog(Admin())
+391
View File
@@ -0,0 +1,391 @@
from typing import Tuple
import discord
from discord.ext import commands
from redbot.core import Config, checks
import logging
from redbot.core.utils.chat_formatting import box
from .announcer import Announcer
from .converters import MemberDefaultAuthor, SelfRole
log = logging.getLogger("red.admin")
GENERIC_FORBIDDEN = (
"I attempted to do something that Discord denied me permissions for."
" Your command failed to successfully complete."
)
HIERARCHY_ISSUE = (
"I tried to add {role.name} to {member.display_name} but that role"
" is higher than my highest role in the Discord heirarchy so I was"
" unable to successfully add it. Please give me a higher role and "
"try again."
)
USER_HIERARCHY_ISSUE = (
"I tried to add {role.name} to {member.display_name} but that role"
" is higher than your highest role in the Discord heirarchy so I was"
" unable to successfully add it. Please get a higher role and "
"try again."
)
RUNNING_ANNOUNCEMENT = (
"I am already announcing something. If you would like to make a"
" different announcement please use `{prefix}announce cancel`"
" first."
)
class Admin:
def __init__(self, config=Config):
self.conf = config.get_conf(self, 8237492837454039,
force_registration=True)
self.conf.register_global(
serverlocked=False
)
self.conf.register_guild(
announce_ignore=False,
announce_channel=None, # Integer ID
selfroles=[] # List of integer ID's
)
self.__current_announcer = None
def __unload(self):
try:
self.__current_announcer.cancel()
except AttributeError:
pass
@staticmethod
async def complain(ctx: commands.Context, message: str,
**kwargs):
await ctx.send(message.format(**kwargs))
def is_announcing(self) -> bool:
"""
Is the bot currently announcing something?
:return:
"""
if self.__current_announcer is None:
return False
return self.__current_announcer.active or False
@staticmethod
def pass_heirarchy_check(ctx: commands.Context,
role: discord.Role) -> bool:
"""
Determines if the bot has a higher role than the given one.
:param ctx:
:param role: Role object.
:return:
"""
return ctx.guild.me.top_role > role
@staticmethod
def pass_user_heirarchy_check(ctx: commands.Context,
role: discord.Role) -> bool:
"""
Determines if a user is allowed to add/remove/edit the given role.
:param ctx:
:param role:
:return:
"""
return ctx.author.top_role > role
async def _addrole(self, ctx: commands.Context, member: discord.Member,
role: discord.Role):
try:
await member.add_roles(role)
except discord.Forbidden:
if not self.pass_heirarchy_check(ctx, role):
await self.complain(ctx, HIERARCHY_ISSUE, role=role,
member=member)
else:
await self.complain(ctx, GENERIC_FORBIDDEN)
else:
await ctx.send("I successfully added {role.name} to"
" {member.display_name}".format(
role=role, member=member
))
async def _removerole(self, ctx: commands.Context, member: discord.Member,
role: discord.Role):
try:
await member.remove_roles(role)
except discord.Forbidden:
if not self.pass_heirarchy_check(ctx, role):
await self.complain(ctx, HIERARCHY_ISSUE, role=role,
member=member)
else:
await self.complain(ctx, GENERIC_FORBIDDEN)
else:
await ctx.send("I successfully removed {role.name} from"
" {member.display_name}".format(
role=role, member=member
))
@commands.command()
@commands.guild_only()
@checks.admin_or_permissions(manage_roles=True)
async def addrole(self, ctx: commands.Context, rolename: discord.Role, *,
user: MemberDefaultAuthor=None):
"""
Adds a role to a user. If user is left blank it defaults to the
author of the command.
"""
if user is None:
user = ctx.author
if self.pass_user_heirarchy_check(ctx, rolename):
# noinspection PyTypeChecker
await self._addrole(ctx, user, rolename)
else:
await self.complain(ctx, USER_HIERARCHY_ISSUE, member=ctx.author)
@commands.command()
@commands.guild_only()
@checks.admin_or_permissions(manage_roles=True)
async def removerole(self, ctx: commands.Context, rolename: discord.Role, *,
user: MemberDefaultAuthor=None):
"""
Removes a role from a user. If user is left blank it defaults to the
author of the command.
"""
if user is None:
user = ctx.author
if self.pass_user_heirarchy_check(ctx, rolename):
# noinspection PyTypeChecker
await self._removerole(ctx, user, rolename)
else:
await self.complain(ctx, USER_HIERARCHY_ISSUE)
@commands.group()
@commands.guild_only()
@checks.admin_or_permissions(manage_roles=True)
async def editrole(self, ctx: commands.Context):
"""Edits roles settings"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
@editrole.command(name="colour", aliases=["color", ])
async def editrole_colour(self, ctx: commands.Context, role: discord.Role,
value: discord.Colour):
"""Edits a role's colour
Use double quotes if the role contains spaces.
Colour must be in hexadecimal format.
\"http://www.w3schools.com/colors/colors_picker.asp\"
Examples:
!editrole colour \"The Transistor\" #ff0000
!editrole colour Test #ff9900"""
author = ctx.author
reason = "{}({}) changed the colour of role '{}'".format(
author.name, author.id, role.name)
if not self.pass_user_heirarchy_check(ctx, role):
await self.complain(ctx, USER_HIERARCHY_ISSUE)
return
try:
await role.edit(reason=reason, color=value)
except discord.Forbidden:
await self.complain(ctx, GENERIC_FORBIDDEN)
else:
log.info(reason)
await ctx.send("Done.")
@editrole.command(name="name")
@checks.admin_or_permissions(administrator=True)
async def edit_role_name(self, ctx: commands.Context, role: discord.Role, *, name: str):
"""Edits a role's name
Use double quotes if the role or the name contain spaces.
Examples:
!editrole name \"The Transistor\" Test"""
author = ctx.message.author
old_name = role.name
reason = "{}({}) changed the name of role '{}' to '{}'".format(
author.name, author.id, old_name, name)
if not self.pass_user_heirarchy_check(ctx, role):
await self.complain(ctx, USER_HIERARCHY_ISSUE)
return
try:
await role.edit(reason=reason, name=name)
except discord.Forbidden:
await self.complain(ctx, GENERIC_FORBIDDEN)
else:
log.info(reason)
await ctx.send("Done.")
@commands.group(invoke_without_command=True)
@checks.is_owner()
async def announce(self, ctx: commands.Context, *, message: str):
"""
Announces a message to all servers the bot is in.
"""
if not self.is_announcing():
announcer = Announcer(ctx, message, config=self.conf)
announcer.start()
self.__current_announcer = announcer
await ctx.send("The announcement has begun.")
else:
prefix = ctx.prefix
await self.complain(ctx, RUNNING_ANNOUNCEMENT,
prefix=prefix)
@announce.command(name="cancel")
@checks.is_owner()
async def announce_cancel(self, ctx):
"""
Cancels a running announce.
"""
try:
self.__current_announcer.cancel()
except AttributeError:
pass
await ctx.send("The current announcement has been cancelled.")
@announce.command(name="channel")
@commands.guild_only()
@checks.guildowner_or_permissions(administrator=True)
async def announce_channel(self, ctx, *, channel: discord.TextChannel=None):
"""
Changes the channel on which the bot makes announcements.
"""
if channel is None:
channel = ctx.channel
await self.conf.guild(ctx.guild).announce_channel.set(channel.id)
await ctx.send("The announcement channel has been set to {}".format(
channel.mention
))
@announce.command(name="ignore")
@commands.guild_only()
@checks.guildowner_or_permissions(administrator=True)
async def announce_ignore(self, ctx, *, guild: discord.Guild=None):
"""
Toggles whether the announcements will ignore the given server.
Defaults to the current server if none is provided.
"""
if guild is None:
guild = ctx.guild
ignored = await self.conf.guild(guild).announce_ignore()
await self.conf.guild(guild).announce_ignore.set(not ignored)
verb = "will" if ignored else "will not"
await ctx.send("The server {} {} receive announcements.".format(
guild.name, verb
))
async def _valid_selfroles(self, guild: discord.Guild) -> Tuple[discord.Role]:
"""
Returns a list of valid selfroles
:param guild:
:return:
"""
selfrole_ids = set(await self.conf.guild(guild).selfroles())
guild_roles = guild.roles
valid_roles = tuple(r for r in guild_roles if r.id in selfrole_ids)
valid_role_ids = set(r.id for r in valid_roles)
if selfrole_ids != valid_role_ids:
await self.conf.guild(guild).selfroles.set(valid_role_ids)
# noinspection PyTypeChecker
return valid_roles
@commands.group(invoke_without_command=True)
async def selfrole(self, ctx: commands.Context, *, selfrole: SelfRole):
"""
Add a role to yourself that server admins have configured as
user settable.
"""
# noinspection PyTypeChecker
await self._addrole(ctx, ctx.author, selfrole)
@selfrole.command(name="remove")
async def selfrole_remove(self, ctx: commands.Context, *, selfrole: SelfRole):
"""
Removes a selfrole from yourself.
"""
# noinspection PyTypeChecker
await self._removerole(ctx, ctx.author, selfrole)
@selfrole.command(name="add")
@commands.has_permissions(manage_roles=True)
async def selfrole_add(self, ctx: commands.Context, *, role: discord.Role):
"""
Add a role to the list of available selfroles.
"""
async with self.conf.guild(ctx.guild).selfroles() as curr_selfroles:
if role.id not in curr_selfroles:
curr_selfroles.append(role.id)
await ctx.send("The selfroles list has been successfully modified.")
@selfrole.command(name="delete")
@commands.has_permissions(manage_roles=True)
async def selfrole_delete(self, ctx: commands.Context, *, role: SelfRole):
"""
Removes a role from the list of available selfroles.
"""
async with self.conf.guild(ctx.guild).selfroles() as curr_selfroles:
curr_selfroles.remove(role.id)
await ctx.send("The selfroles list has been successfully modified.")
@selfrole.command(name="list")
async def selfrole_list(self, ctx: commands.Context):
"""
Lists all available selfroles.
"""
selfroles = await self._valid_selfroles(ctx.guild)
fmt_selfroles = "\n".join(["+ " + r.name for r in selfroles])
msg = "Available Selfroles:\n{}".format(fmt_selfroles)
await ctx.send(box(msg, "diff"))
async def _serverlock_check(self, guild: discord.Guild) -> bool:
"""
Checks if serverlocked is enabled.
:param guild:
:return: True if locked and left server
"""
if await self.conf.serverlocked():
await guild.leave()
return True
return False
@commands.command()
@checks.is_owner()
async def serverlock(self, ctx: commands.Context):
"""
Locks a bot to it's current servers only.
"""
serverlocked = await self.conf.serverlocked()
await self.conf.serverlocked.set(not serverlocked)
verb = "is now" if not serverlocked else "is no longer"
await ctx.send("The bot {} serverlocked.".format(verb))
# region Event Handlers
async def on_guild_join(self, guild: discord.Guild):
if await self._serverlock_check(guild):
return
# endregion
+74
View File
@@ -0,0 +1,74 @@
import asyncio
import discord
from discord.ext import commands
class Announcer:
def __init__(self, ctx: commands.Context,
message: str,
config=None):
"""
:param ctx:
:param message:
:param config: Used to determine channel overrides
"""
self.ctx = ctx
self.message = message
self.config = config
self.active = None
def start(self):
"""
Starts an announcement.
:return:
"""
if self.active is None:
self.active = True
self.ctx.bot.loop.create_task(self.announcer())
def cancel(self):
"""
Cancels a running announcement.
:return:
"""
self.active = False
async def _get_announce_channel(self, guild: discord.Guild) -> discord.TextChannel:
channel_id = await self.config.guild(guild).announce_channel()
channel = None
if channel_id is not None:
channel = guild.get_channel(channel_id)
if channel is None:
channel = guild.system_channel
if channel is None:
channel = guild.text_channels[0]
return channel
async def announcer(self):
guild_list = self.ctx.bot.guilds
bot_owner = (await self.ctx.bot.application_info()).owner
for g in guild_list:
if not self.active:
return
if await self.config.guild(g).announce_ignore():
continue
channel = await self._get_announce_channel(g)
try:
await channel.send(self.message)
except discord.Forbidden:
await bot_owner.send("I could not announce to guild: {}".format(
g.id
))
await asyncio.sleep(0.5)
self.active = False
+33
View File
@@ -0,0 +1,33 @@
import discord
from discord.ext import commands
class MemberDefaultAuthor(commands.Converter):
async def convert(self, ctx: commands.Context, arg: str) -> discord.Member:
member_converter = commands.MemberConverter()
try:
member = await member_converter.convert(ctx, arg)
except commands.BadArgument:
if arg.strip() != "":
raise
else:
member = ctx.author
return member
class SelfRole(commands.Converter):
async def convert(self, ctx: commands.Context, arg: str) -> discord.Role:
admin = ctx.command.instance
if admin is None:
raise commands.BadArgument("Admin is not loaded.")
conf = admin.conf
selfroles = await conf.guild(ctx.guild).selfroles()
role_converter = commands.RoleConverter()
role = await role_converter.convert(ctx, arg)
if role.id not in selfroles:
raise commands.BadArgument("The provided role is not a valid"
" selfrole.")
return role
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:32-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Arabic\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: ar_SA\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Bulgarian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: bg_BG\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Danish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: da_DK\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: de_DE\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Greek\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: el_GR\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:34-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Pirate English\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: en-PT\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: en_PT\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:32-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: es_ES\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Finnish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: fi\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: fi_FI\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:32-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: fr_FR\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Hungarian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: hu_HU\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:34-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Indonesian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: id_ID\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Italian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: it_IT\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Japanese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: ja_JP\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Korean\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: ko_KR\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:34-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: LOLCAT\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: lol\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: lol_US\n"
+17
View File
@@ -0,0 +1,17 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Dutch\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: nl_NL\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Norwegian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: no\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: no_NO\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Polish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=4; plural=((n == 1) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || n%10 == 1 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 12 && n%100 <= 14)) ? 2 : 3));\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: pl_PL\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:34-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Portuguese, Brazilian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: pt_BR\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Portuguese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: pt_PT\n"
@@ -0,0 +1,15 @@
import subprocess
TO_TRANSLATE = [
'../admin.py'
]
def regen_messages():
subprocess.run(
['pygettext', '-n'] + TO_TRANSLATE
)
if __name__ == "__main__":
regen_messages()
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Russian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: ru_RU\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:34-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Swedish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: sv-SE\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: sv_SE\n"
+18
View File
@@ -0,0 +1,18 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:34-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Chinese Simplified\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /cogs/admin/locales/messages.pot\n"
"Language: zh_CN\n"
+6
View File
@@ -0,0 +1,6 @@
from .alias import Alias
from discord.ext import commands
def setup(bot: commands.Bot):
bot.add_cog(Alias(bot))
+356
View File
@@ -0,0 +1,356 @@
from copy import copy
from re import search
from typing import Generator, Tuple, Iterable
import discord
from redbot.core import Config
from redbot.core.i18n import CogI18n
from redbot.core.utils.chat_formatting import box
from discord.ext import commands
from redbot.core.bot import Red
from .alias_entry import AliasEntry
_ = CogI18n("Alias", __file__)
class Alias:
"""
Alias
Aliases are per server shortcuts for commands. They
can act as both a lambda (storing arguments for repeated use)
or as simply a shortcut to saying "x y z".
When run, aliases will accept any additional arguments
and append them to the stored alias
"""
default_global_settings = {
"entries": []
}
default_guild_settings = {
"enabled": False,
"entries": [] # Going to be a list of dicts
}
def __init__(self, bot: Red):
self.bot = bot
self._aliases = Config.get_conf(self, 8927348724)
self._aliases.register_global(**self.default_global_settings)
self._aliases.register_guild(**self.default_guild_settings)
async def unloaded_aliases(self, guild: discord.Guild) -> Generator[AliasEntry, None, None]:
return (AliasEntry.from_json(d) for d in (await self._aliases.guild(guild).entries()))
async def unloaded_global_aliases(self) -> Generator[AliasEntry, None, None]:
return (AliasEntry.from_json(d) for d in (await self._aliases.entries()))
async def loaded_aliases(self, guild: discord.Guild) -> Generator[AliasEntry, None, None]:
return (AliasEntry.from_json(d, bot=self.bot)
for d in (await self._aliases.guild(guild).entries()))
async def loaded_global_aliases(self) -> Generator[AliasEntry, None, None]:
return (AliasEntry.from_json(d, bot=self.bot) for d in (await self._aliases.entries()))
async def is_alias(self, guild: discord.Guild, alias_name: str,
server_aliases: Iterable[AliasEntry]=()) -> (bool, AliasEntry):
if not server_aliases:
server_aliases = await self.unloaded_aliases(guild)
global_aliases = await self.unloaded_global_aliases()
for aliases in (server_aliases, global_aliases):
for alias in aliases:
if alias.name == alias_name:
return True, alias
return False, None
def is_command(self, alias_name: str) -> bool:
command = self.bot.get_command(alias_name)
return command is not None
@staticmethod
def is_valid_alias_name(alias_name: str) -> bool:
return not bool(search(r'\s', alias_name)) and alias_name.isprintable()
async def add_alias(self, ctx: commands.Context, alias_name: str,
command: Tuple[str], global_: bool=False) -> AliasEntry:
alias = AliasEntry(alias_name, command, ctx.author, global_=global_)
if global_:
settings = self._aliases
else:
settings = self._aliases.guild(ctx.guild)
await settings.enabled.set(True)
async with settings.entries() as curr_aliases:
curr_aliases.append(alias.to_json())
return alias
async def delete_alias(self, ctx: commands.Context, alias_name: str,
global_: bool=False) -> bool:
if global_:
settings = self._aliases
else:
settings = self._aliases.guild(ctx.guild)
async with settings.entries() as aliases:
for alias in aliases:
alias_obj = AliasEntry.from_json(alias)
if alias_obj.name == alias_name:
aliases.remove(alias)
return True
return False
async def get_prefix(self, message: discord.Message) -> str:
"""
Tries to determine what prefix is used in a message object.
Looks to identify from longest prefix to smallest.
Will raise ValueError if no prefix is found.
:param message: Message object
:return:
"""
content = message.content
prefix_list = await self.bot.command_prefix(self.bot, message)
prefixes = sorted(prefix_list,
key=lambda pfx: len(pfx),
reverse=True)
for p in prefixes:
if content.startswith(p):
return p
raise ValueError(_("No prefix found."))
def get_extra_args_from_alias(self, message: discord.Message, prefix: str,
alias: AliasEntry) -> str:
"""
When an alias is executed by a user in chat this function tries
to get any extra arguments passed in with the call.
Whitespace will be trimmed from both ends.
:param message:
:param prefix:
:param alias:
:return:
"""
known_content_length = len(prefix) + len(alias.name)
extra = message.content[known_content_length:].strip()
return extra
async def maybe_call_alias(self, message: discord.Message,
aliases: Iterable[AliasEntry]=None):
try:
prefix = await self.get_prefix(message)
except ValueError:
return
try:
potential_alias = message.content[len(prefix):].split(" ")[0]
except IndexError:
return False
is_alias, alias = await self.is_alias(message.guild, potential_alias, server_aliases=aliases)
if is_alias:
await self.call_alias(message, prefix, alias)
async def call_alias(self, message: discord.Message, prefix: str,
alias: AliasEntry):
new_message = copy(message)
args = self.get_extra_args_from_alias(message, prefix, alias)
# noinspection PyDunderSlots
new_message.content = "{}{} {}".format(prefix, alias.command, args)
await self.bot.process_commands(new_message)
@commands.group()
@commands.guild_only()
async def alias(self, ctx: commands.Context):
"""Manage per-server aliases for commands"""
if ctx.invoked_subcommand is None:
await ctx.send_help()
@alias.group(name="global")
async def global_(self, ctx: commands.Context):
"""
Manage global aliases.
"""
if ctx.invoked_subcommand is None or \
isinstance(ctx.invoked_subcommand, commands.Group):
await ctx.send_help()
@alias.command(name="add")
@commands.guild_only()
async def _add_alias(self, ctx: commands.Context,
alias_name: str, *, command):
"""
Add an alias for a command.
"""
# region Alias Add Validity Checking
is_command = self.is_command(alias_name)
if is_command:
await ctx.send(_("You attempted to create a new alias"
" with the name {} but that"
" name is already a command on this bot.").format(alias_name))
return
is_alias, something_useless = await self.is_alias(ctx.guild, alias_name)
if is_alias:
await ctx.send(_("You attempted to create a new alias"
" with the name {} but that"
" alias already exists on this server.").format(alias_name))
return
is_valid_name = self.is_valid_alias_name(alias_name)
if not is_valid_name:
await ctx.send(_("You attempted to create a new alias"
" with the name {} but that"
" name is an invalid alias name. Alias"
" names may not contain spaces.").format(alias_name))
return
# endregion
# At this point we know we need to make a new alias
# and that the alias name is valid.
await self.add_alias(ctx, alias_name, command)
await ctx.send(_("A new alias with the trigger `{}`"
" has been created.").format(alias_name))
@global_.command(name="add")
async def _add_global_alias(self, ctx: commands.Context,
alias_name: str, *, command):
"""
Add a global alias for a command.
"""
# region Alias Add Validity Checking
is_command = self.is_command(alias_name)
if is_command:
await ctx.send(_("You attempted to create a new global alias"
" with the name {} but that"
" name is already a command on this bot.").format(alias_name))
return
is_alias, something_useless = await self.is_alias(ctx.guild, alias_name)
if is_alias:
await ctx.send(_("You attempted to create a new global alias"
" with the name {} but that"
" alias already exists on this server.").format(alias_name))
return
is_valid_name = self.is_valid_alias_name(alias_name)
if not is_valid_name:
await ctx.send(_("You attempted to create a new global alias"
" with the name {} but that"
" name is an invalid alias name. Alias"
" names may not contain spaces.").format(alias_name))
return
# endregion
await self.add_alias(ctx, alias_name, command, global_=True)
await ctx.send(_("A new global alias with the trigger `{}`"
" has been created.").format(alias_name))
@alias.command(name="help")
@commands.guild_only()
async def _help_alias(self, ctx: commands.Context, alias_name: str):
"""Tries to execute help for the base command of the alias"""
is_alias, alias = self.is_alias(ctx.guild, alias_name=alias_name)
if is_alias:
base_cmd = alias.command[0]
new_msg = copy(ctx.message)
new_msg.content = "{}help {}".format(ctx.prefix, base_cmd)
await self.bot.process_commands(new_msg)
else:
ctx.send(_("No such alias exists."))
@alias.command(name="show")
@commands.guild_only()
async def _show_alias(self, ctx: commands.Context, alias_name: str):
"""Shows what command the alias executes."""
is_alias, alias = await self.is_alias(ctx.guild, alias_name)
if is_alias:
await ctx.send(_("The `{}` alias will execute the"
" command `{}`").format(alias_name, alias.command))
else:
await ctx.send(_("There is no alias with the name `{}`").format(alias_name))
@alias.command(name="del")
@commands.guild_only()
async def _del_alias(self, ctx: commands.Context, alias_name: str):
"""
Deletes an existing alias on this server.
"""
aliases = await self.unloaded_aliases(ctx.guild)
try:
next(aliases)
except StopIteration:
await ctx.send(_("There are no aliases on this guild."))
return
if await self.delete_alias(ctx, alias_name):
await ctx.send(_("Alias with the name `{}` was successfully"
" deleted.").format(alias_name))
else:
await ctx.send(_("Alias with name `{}` was not found.").format(alias_name))
@global_.command(name="del")
async def _del_global_alias(self, ctx: commands.Context, alias_name: str):
"""
Deletes an existing global alias.
"""
aliases = await self.unloaded_global_aliases()
try:
next(aliases)
except StopIteration:
await ctx.send(_("There are no aliases on this bot."))
return
if await self.delete_alias(ctx, alias_name, global_=True):
await ctx.send(_("Alias with the name `{}` was successfully"
" deleted.").format(alias_name))
else:
await ctx.send(_("Alias with name `{}` was not found.").format(alias_name))
@alias.command(name="list")
@commands.guild_only()
async def _list_alias(self, ctx: commands.Context):
"""
Lists the available aliases on this server.
"""
names = [_("Aliases:"), ] + sorted(["+ " + a.name for a in (await self.unloaded_aliases(ctx.guild))])
if len(names) == 0:
await ctx.send(_("There are no aliases on this server."))
else:
await ctx.send(box("\n".join(names), "diff"))
@global_.command(name="list")
async def _list_global_alias(self, ctx: commands.Context):
"""
Lists the available global aliases on this bot.
"""
names = [_("Aliases:"), ] + sorted(["+ " + a.name for a in await self.unloaded_global_aliases()])
if len(names) == 0:
await ctx.send(_("There are no aliases on this server."))
else:
await ctx.send(box("\n".join(names), "diff"))
async def on_message(self, message: discord.Message):
aliases = list(await self.unloaded_global_aliases())
if message.guild is not None:
aliases = aliases + list(await self.unloaded_aliases(message.guild))
if len(aliases) == 0:
return
await self.maybe_call_alias(message, aliases=aliases)
+63
View File
@@ -0,0 +1,63 @@
from typing import Tuple
from discord.ext import commands
import discord
class AliasEntry:
def __init__(self, name: str, command: Tuple[str],
creator: discord.Member, global_: bool=False):
super().__init__()
self.has_real_data = False
self.name = name
self.command = command
self.creator = creator
self.global_ = global_
self.guild = None
if hasattr(creator, "guild"):
self.guild = creator.guild
self.uses = 0
def inc(self):
"""
Increases the `uses` stat by 1.
:return: new use count
"""
self.uses += 1
return self.uses
def to_json(self) -> dict:
try:
creator = str(self.creator.id)
guild = str(self.guild.id)
except AttributeError:
creator = self.creator
guild = self.guild
return {
"name": self.name,
"command": self.command,
"creator": creator,
"guild": guild,
"global": self.global_,
"uses": self.uses
}
@classmethod
def from_json(cls, data: dict, bot: commands.Bot=None):
ret = cls(data["name"], data["command"],
data["creator"], global_=data["global"])
if bot:
ret.has_real_data = True
ret.creator = bot.get_user(int(data["creator"]))
guild = bot.get_guild(int(data["guild"]))
ret.guild = guild
else:
ret.guild = data["guild"]
ret.uses = data.get("uses", 0)
return ret
+90
View File
@@ -0,0 +1,90 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:32-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Arabic\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /cogs/alias/locales/messages.pot\n"
"Language: ar_SA\n"
#: ../alias.py:129
msgid "No prefix found."
msgstr ""
#: ../alias.py:198
msgid "You attempted to create a new alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:205
msgid "You attempted to create a new alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:212
msgid "You attempted to create a new alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:224
msgid "A new alias with the trigger `{}` has been created."
msgstr ""
#: ../alias.py:236
msgid "You attempted to create a new global alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:243
msgid "You attempted to create a new global alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:250
msgid "You attempted to create a new global alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:259
msgid "A new global alias with the trigger `{}` has been created."
msgstr ""
#: ../alias.py:274
msgid "No such alias exists."
msgstr ""
#: ../alias.py:283
msgid "The `{}` alias will execute the command `{}`"
msgstr ""
#: ../alias.py:286
msgid "There is no alias with the name `{}`"
msgstr ""
#: ../alias.py:298
msgid "There are no aliases on this guild."
msgstr ""
#: ../alias.py:302 ../alias.py:320
msgid "Alias with the name `{}` was successfully deleted."
msgstr ""
#: ../alias.py:305 ../alias.py:323
msgid "Alias with name `{}` was not found."
msgstr ""
#: ../alias.py:316
msgid "There are no aliases on this bot."
msgstr ""
#: ../alias.py:331 ../alias.py:342
msgid "Aliases:"
msgstr ""
#: ../alias.py:333 ../alias.py:344
msgid "There are no aliases on this server."
msgstr ""
+90
View File
@@ -0,0 +1,90 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Bulgarian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /cogs/alias/locales/messages.pot\n"
"Language: bg_BG\n"
#: ../alias.py:129
msgid "No prefix found."
msgstr "Няма намерен префикс."
#: ../alias.py:198
msgid "You attempted to create a new alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:205
msgid "You attempted to create a new alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:212
msgid "You attempted to create a new alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:224
msgid "A new alias with the trigger `{}` has been created."
msgstr "Нов псевдоним със задействащия оператор `{}` беше създаден."
#: ../alias.py:236
msgid "You attempted to create a new global alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:243
msgid "You attempted to create a new global alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:250
msgid "You attempted to create a new global alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:259
msgid "A new global alias with the trigger `{}` has been created."
msgstr "Нов псевдоним, по всеобщо правило, със задействащия оператор `{}` беше създаден."
#: ../alias.py:274
msgid "No such alias exists."
msgstr "Този псевдоним не съществува."
#: ../alias.py:283
msgid "The `{}` alias will execute the command `{}`"
msgstr "`{}` псевдоним ще изпълни командата `{}`"
#: ../alias.py:286
msgid "There is no alias with the name `{}`"
msgstr "Псевдонимът под името `{}` не съществува"
#: ../alias.py:298
msgid "There are no aliases on this guild."
msgstr "Няма псевдоними положени към тази гилдия."
#: ../alias.py:302 ../alias.py:320
msgid "Alias with the name `{}` was successfully deleted."
msgstr "Псевдонимът с име `{}` беше успешно изтрит."
#: ../alias.py:305 ../alias.py:323
msgid "Alias with name `{}` was not found."
msgstr "Псевдонимът с името `{}` не е намерен."
#: ../alias.py:316
msgid "There are no aliases on this bot."
msgstr "Няма псевдоними положени към този бот."
#: ../alias.py:331 ../alias.py:342
msgid "Aliases:"
msgstr "Псевдоними:"
#: ../alias.py:333 ../alias.py:344
msgid "There are no aliases on this server."
msgstr "Няма използвани псевдоними на този сървър."
+90
View File
@@ -0,0 +1,90 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Danish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /cogs/alias/locales/messages.pot\n"
"Language: da_DK\n"
#: ../alias.py:129
msgid "No prefix found."
msgstr ""
#: ../alias.py:198
msgid "You attempted to create a new alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:205
msgid "You attempted to create a new alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:212
msgid "You attempted to create a new alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:224
msgid "A new alias with the trigger `{}` has been created."
msgstr ""
#: ../alias.py:236
msgid "You attempted to create a new global alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:243
msgid "You attempted to create a new global alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:250
msgid "You attempted to create a new global alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:259
msgid "A new global alias with the trigger `{}` has been created."
msgstr ""
#: ../alias.py:274
msgid "No such alias exists."
msgstr ""
#: ../alias.py:283
msgid "The `{}` alias will execute the command `{}`"
msgstr ""
#: ../alias.py:286
msgid "There is no alias with the name `{}`"
msgstr ""
#: ../alias.py:298
msgid "There are no aliases on this guild."
msgstr ""
#: ../alias.py:302 ../alias.py:320
msgid "Alias with the name `{}` was successfully deleted."
msgstr ""
#: ../alias.py:305 ../alias.py:323
msgid "Alias with name `{}` was not found."
msgstr ""
#: ../alias.py:316
msgid "There are no aliases on this bot."
msgstr ""
#: ../alias.py:331 ../alias.py:342
msgid "Aliases:"
msgstr ""
#: ../alias.py:333 ../alias.py:344
msgid "There are no aliases on this server."
msgstr ""
+90
View File
@@ -0,0 +1,90 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /cogs/alias/locales/messages.pot\n"
"Language: de_DE\n"
#: ../alias.py:129
msgid "No prefix found."
msgstr "Kein Präfix wurde gefunden."
#: ../alias.py:198
msgid "You attempted to create a new alias with the name {} but that name is already a command on this bot."
msgstr "Sie haben versucht, einen neuen Alias mit dem Namen {} zu erstellen, aber dieser Name ist bereits ein Command für diesen Bot."
#: ../alias.py:205
msgid "You attempted to create a new alias with the name {} but that alias already exists on this server."
msgstr "Sie haben versucht, einen neuen Alias mit dem Namen {} zu erstellen, aber dieser Alias existiert bereits auf diesem Server."
#: ../alias.py:212
msgid "You attempted to create a new alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr "Sie haben versucht, einen neuen Alias mit dem Namen {} zu erstellen, dieser Name ist jedoch ein ungültiger Aliasname. Alias-Namen dürfen keine Leerzeichen enthalten."
#: ../alias.py:224
msgid "A new alias with the trigger `{}` has been created."
msgstr "Ein neuer alias mit dem Trigger `{}` wurde hinzugefügt."
#: ../alias.py:236
msgid "You attempted to create a new global alias with the name {} but that name is already a command on this bot."
msgstr "Sie haben versucht, einen neuen globalen Alias mit dem Namen {} zu erstellen, aber dieser Name ist bereits ein Command für diesen Bot."
#: ../alias.py:243
msgid "You attempted to create a new global alias with the name {} but that alias already exists on this server."
msgstr "Sie haben versucht, einen neuen globalen Aliasnamen mit dem Namen {} zu erstellen, dieser Aliasname ist jedoch bereits auf diesem Server vorhanden."
#: ../alias.py:250
msgid "You attempted to create a new global alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr "Sie haben versucht, einen neuen globalen Aliasnamen mit dem Namen {} zu erstellen, dieser Name ist jedoch ein ungültiger Aliasname. Alias-Namen dürfen keine Leerzeichen enthalten."
#: ../alias.py:259
msgid "A new global alias with the trigger `{}` has been created."
msgstr "Ein neuer globaler Alias mit dem Trigger `{}` wurde erstellt."
#: ../alias.py:274
msgid "No such alias exists."
msgstr "Kein solcher alias ist vorhanden."
#: ../alias.py:283
msgid "The `{}` alias will execute the command `{}`"
msgstr "Der `{}` alias wird den Befehl `{}` ausführen"
#: ../alias.py:286
msgid "There is no alias with the name `{}`"
msgstr "Es gibt keinen alias mit dem Namen `{}`"
#: ../alias.py:298
msgid "There are no aliases on this guild."
msgstr "Es gibt keine Aliase auf diesem Server."
#: ../alias.py:302 ../alias.py:320
msgid "Alias with the name `{}` was successfully deleted."
msgstr "Der Alias mit dem Namen `{}` wurde erfolgreich gelöscht."
#: ../alias.py:305 ../alias.py:323
msgid "Alias with name `{}` was not found."
msgstr "Der Alias mit dem Namen `{}` wurde nicht gefunden."
#: ../alias.py:316
msgid "There are no aliases on this bot."
msgstr "Es gibt keine Aliase in diesem Bot."
#: ../alias.py:331 ../alias.py:342
msgid "Aliases:"
msgstr "Aliase:"
#: ../alias.py:333 ../alias.py:344
msgid "There are no aliases on this server."
msgstr "Es gibt keine Aliase in diesem Server."
+90
View File
@@ -0,0 +1,90 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Greek\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /cogs/alias/locales/messages.pot\n"
"Language: el_GR\n"
#: ../alias.py:129
msgid "No prefix found."
msgstr "Δεν βρέθηκε πρόθεμα."
#: ../alias.py:198
msgid "You attempted to create a new alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:205
msgid "You attempted to create a new alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:212
msgid "You attempted to create a new alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:224
msgid "A new alias with the trigger `{}` has been created."
msgstr ""
#: ../alias.py:236
msgid "You attempted to create a new global alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:243
msgid "You attempted to create a new global alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:250
msgid "You attempted to create a new global alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:259
msgid "A new global alias with the trigger `{}` has been created."
msgstr ""
#: ../alias.py:274
msgid "No such alias exists."
msgstr ""
#: ../alias.py:283
msgid "The `{}` alias will execute the command `{}`"
msgstr ""
#: ../alias.py:286
msgid "There is no alias with the name `{}`"
msgstr ""
#: ../alias.py:298
msgid "There are no aliases on this guild."
msgstr ""
#: ../alias.py:302 ../alias.py:320
msgid "Alias with the name `{}` was successfully deleted."
msgstr ""
#: ../alias.py:305 ../alias.py:323
msgid "Alias with name `{}` was not found."
msgstr ""
#: ../alias.py:316
msgid "There are no aliases on this bot."
msgstr ""
#: ../alias.py:331 ../alias.py:342
msgid "Aliases:"
msgstr ""
#: ../alias.py:333 ../alias.py:344
msgid "There are no aliases on this server."
msgstr ""
+90
View File
@@ -0,0 +1,90 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:34-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Pirate English\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: en-PT\n"
"X-Crowdin-File: /cogs/alias/locales/messages.pot\n"
"Language: en_PT\n"
#: ../alias.py:129
msgid "No prefix found."
msgstr "Arrr, no prefix found capt'n!"
#: ../alias.py:198
msgid "You attempted to create a new alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:205
msgid "You attempted to create a new alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:212
msgid "You attempted to create a new alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:224
msgid "A new alias with the trigger `{}` has been created."
msgstr "Arrr! A new alias with thee trigger `{}` has been created."
#: ../alias.py:236
msgid "You attempted to create a new global alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:243
msgid "You attempted to create a new global alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:250
msgid "You attempted to create a new global alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:259
msgid "A new global alias with the trigger `{}` has been created."
msgstr "Arrr! A new global alias with thee trigger `{}` has been created."
#: ../alias.py:274
msgid "No such alias exists."
msgstr "Yer scummy alias don't exist, matey!"
#: ../alias.py:283
msgid "The `{}` alias will execute the command `{}`"
msgstr "Blimey! Thee `{}` alias will execute thee command `{}`"
#: ../alias.py:286
msgid "There is no alias with the name `{}`"
msgstr "Thar is no alias with thee name `{}`"
#: ../alias.py:298
msgid "There are no aliases on this guild."
msgstr "Fool! Thar be no aliases on this guild."
#: ../alias.py:302 ../alias.py:320
msgid "Alias with the name `{}` was successfully deleted."
msgstr "Yo-ho-ho! Alias with thee name `{}` has been sent to Davy Jones' locker."
#: ../alias.py:305 ../alias.py:323
msgid "Alias with name `{}` was not found."
msgstr "Yo-ho-ho! Alias with thee name `{}`as been sent to Davy Jones' locker."
#: ../alias.py:316
msgid "There are no aliases on this bot."
msgstr "Shiver me timbers! Thar be no aliases on this bot."
#: ../alias.py:331 ../alias.py:342
msgid "Aliases:"
msgstr "Yar Aliases:"
#: ../alias.py:333 ../alias.py:344
msgid "There are no aliases on this server."
msgstr "Alas! Thar be no aliases on this guild."
+90
View File
@@ -0,0 +1,90 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:32-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /cogs/alias/locales/messages.pot\n"
"Language: es_ES\n"
#: ../alias.py:129
msgid "No prefix found."
msgstr "Prefijo no encontrado."
#: ../alias.py:198
msgid "You attempted to create a new alias with the name {} but that name is already a command on this bot."
msgstr "Has intentado crear un nuevo alias con el nombre {} pero ese nombre ya es un comando en este bot."
#: ../alias.py:205
msgid "You attempted to create a new alias with the name {} but that alias already exists on this server."
msgstr "Se ha intentado crear un nuevo alias con el nombre {} pero ese alias ya existe en este servidor."
#: ../alias.py:212
msgid "You attempted to create a new alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr "Has intentado crear un nuevo alias con el nombre {} pero ese nombre es un alias inválido. Los alias no deben contener espacios."
#: ../alias.py:224
msgid "A new alias with the trigger `{}` has been created."
msgstr "Un alias nuevo ha creado con el activación `{}`."
#: ../alias.py:236
msgid "You attempted to create a new global alias with the name {} but that name is already a command on this bot."
msgstr "Has intentado crear un nuevo alias global con el nombre {} pero ese nombre ya es un comando en este bot."
#: ../alias.py:243
msgid "You attempted to create a new global alias with the name {} but that alias already exists on this server."
msgstr "Se ha intentado crear un nuevo alias global con el nombre {} pero ese alias ya existe en este servidor."
#: ../alias.py:250
msgid "You attempted to create a new global alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr "Has intentado crear un nuevo alias global con el nombre {} pero ese nombre es un alias inválido. Los alias no deben contener espacios."
#: ../alias.py:259
msgid "A new global alias with the trigger `{}` has been created."
msgstr "Un alias nuevo global ha creado con el activación `{}`."
#: ../alias.py:274
msgid "No such alias exists."
msgstr "Un alias no existe."
#: ../alias.py:283
msgid "The `{}` alias will execute the command `{}`"
msgstr "El alias de `{}` va a ejecutar el comando`{}`"
#: ../alias.py:286
msgid "There is no alias with the name `{}`"
msgstr "No hay el alias con el nombre de `{}`"
#: ../alias.py:298
msgid "There are no aliases on this guild."
msgstr "No hay el alias dentro de este guild."
#: ../alias.py:302 ../alias.py:320
msgid "Alias with the name `{}` was successfully deleted."
msgstr "El alias con el nombre de `{}` satisfactoriamente se ha eliminado."
#: ../alias.py:305 ../alias.py:323
msgid "Alias with name `{}` was not found."
msgstr "Alias con el nombre `{}` no fue encontrado."
#: ../alias.py:316
msgid "There are no aliases on this bot."
msgstr "No hay el los alias dentro de este bot."
#: ../alias.py:331 ../alias.py:342
msgid "Aliases:"
msgstr "Alias:"
#: ../alias.py:333 ../alias.py:344
msgid "There are no aliases on this server."
msgstr "No hay los aliases en este servidor."
+90
View File
@@ -0,0 +1,90 @@
msgid ""
msgstr ""
"Project-Id-Version: red-discordbot\n"
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
"PO-Revision-Date: 2018-02-25 21:33-0500\n"
"Last-Translator: Kowlin <boxedpp@gmail.com>\n"
"Language-Team: Finnish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: crowdin.com\n"
"X-Crowdin-Project: red-discordbot\n"
"X-Crowdin-Language: fi\n"
"X-Crowdin-File: /cogs/alias/locales/messages.pot\n"
"Language: fi_FI\n"
#: ../alias.py:129
msgid "No prefix found."
msgstr ""
#: ../alias.py:198
msgid "You attempted to create a new alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:205
msgid "You attempted to create a new alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:212
msgid "You attempted to create a new alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:224
msgid "A new alias with the trigger `{}` has been created."
msgstr ""
#: ../alias.py:236
msgid "You attempted to create a new global alias with the name {} but that name is already a command on this bot."
msgstr ""
#: ../alias.py:243
msgid "You attempted to create a new global alias with the name {} but that alias already exists on this server."
msgstr ""
#: ../alias.py:250
msgid "You attempted to create a new global alias with the name {} but that name is an invalid alias name. Alias names may not contain spaces."
msgstr ""
#: ../alias.py:259
msgid "A new global alias with the trigger `{}` has been created."
msgstr ""
#: ../alias.py:274
msgid "No such alias exists."
msgstr ""
#: ../alias.py:283
msgid "The `{}` alias will execute the command `{}`"
msgstr ""
#: ../alias.py:286
msgid "There is no alias with the name `{}`"
msgstr ""
#: ../alias.py:298
msgid "There are no aliases on this guild."
msgstr ""
#: ../alias.py:302 ../alias.py:320
msgid "Alias with the name `{}` was successfully deleted."
msgstr ""
#: ../alias.py:305 ../alias.py:323
msgid "Alias with name `{}` was not found."
msgstr ""
#: ../alias.py:316
msgid "There are no aliases on this bot."
msgstr ""
#: ../alias.py:331 ../alias.py:342
msgid "Aliases:"
msgstr ""
#: ../alias.py:333 ../alias.py:344
msgid "There are no aliases on this server."
msgstr ""

Some files were not shown because too many files have changed in this diff Show More