mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2026-05-11 10:45:59 -04:00
Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 974aa71759 | |||
| c1372806e8 | |||
| 35ed817203 | |||
| 5e431b52bf | |||
| 0827fb0c33 | |||
| b5f240fdb8 | |||
| 970c3a5ef0 | |||
| ef05727477 | |||
| e207f09f40 | |||
| c36db5dad1 | |||
| d06345dbe2 | |||
| 1763c76d69 | |||
| 45e5886282 | |||
| d593c9d625 | |||
| 0862681078 | |||
| 7cef720350 | |||
| eb1b997fa6 | |||
| 2342016314 | |||
| d654bd9538 | |||
| dd223a1a1d | |||
| 44508e1492 | |||
| 15932f3e51 | |||
| 7be20e127b | |||
| 9ce74b6ec8 | |||
| c0f24ae663 | |||
| b8e7e97efe | |||
| a48d4e9374 | |||
| c3f7c8936e | |||
| c1d73c3038 | |||
| f4fd244554 | |||
| 76068f2393 | |||
| 9943d8472b | |||
| a4c001dd39 | |||
| c45acb65ca | |||
| e73e1f38d2 | |||
| aaae7fbfe0 | |||
| 2a073bbd50 | |||
| 33f5114666 | |||
| f494bac4d9 | |||
| 9830e1d8c3 | |||
| 1dc8f937f5 | |||
| 95313ae446 | |||
| 706b4e63a2 | |||
| 1162df4157 | |||
| 797ac6d76a | |||
| b6447e68ec | |||
| 96fb81581e | |||
| d86adc4509 | |||
| 15e727ef4c | |||
| 4bce1994d0 | |||
| a3482f939a | |||
| 8cd50a1cbb | |||
| 761bd7eb2c | |||
| 2e78a3f829 | |||
| 03332be3aa | |||
| 385ee1b409 | |||
| e293d0546c | |||
| be4ccc4bfc | |||
| cc8b4b0585 | |||
| e1c4edba9f | |||
| 7a82c9ec68 | |||
| c722c9e117 | |||
| cd597b1665 | |||
| 47e9c657b2 | |||
| 0ac2a02968 | |||
| 2d312292ea | |||
| 9eafd44ec8 | |||
| fbea3e91dd | |||
| a6193e1f37 | |||
| 1e8b9ab681 | |||
| cf5e07851b | |||
| bb96050eaf | |||
| a871267b11 | |||
| d5eb0a9db1 | |||
| 6f6963b1af | |||
| 6e3fa6b73f | |||
| 01a69d2ebc | |||
| 71eade46f8 | |||
| cb2451c04e | |||
| 179feb155f | |||
| 94b98c2535 | |||
| 18061321cb | |||
| 4d6930c3a7 |
@@ -0,0 +1,17 @@
|
||||
# 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
|
||||
@@ -1,58 +0,0 @@
|
||||
# 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
|
||||
redbot/core/utils/data_converter.py @mikeshardmind
|
||||
redbot/core/utils/antispam.py @mikeshardmind
|
||||
redbot/core/utils/tunnel.py @mikeshardmind
|
||||
|
||||
# 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
|
||||
redbot/cogs/dataconverter/* @mikeshardmind
|
||||
redbot/cogs/reports/* @mikeshardmind
|
||||
|
||||
# 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
|
||||
|
||||
# Others
|
||||
.travis.yml @Kowlin
|
||||
crowdin.yml @Kowlin
|
||||
@@ -1,75 +0,0 @@
|
||||
# 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).
|
||||
@@ -1,20 +0,0 @@
|
||||
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.
|
||||
@@ -1,25 +0,0 @@
|
||||
# Command bugs
|
||||
|
||||
<!--
|
||||
Did you find a bug with a command? Fill out the following:
|
||||
-->
|
||||
|
||||
#### Command name
|
||||
|
||||
<!-- Replace this line with the name of the command -->
|
||||
|
||||
#### What cog is this command from?
|
||||
|
||||
<!-- Replace this line with the name of the cog -->
|
||||
|
||||
#### What were you expecting to happen?
|
||||
|
||||
<!-- Replace this line with a description of what you were expecting to happen -->
|
||||
|
||||
#### What actually happened?
|
||||
|
||||
<!-- Replace this line with a description of what actually happened. Include any error messages -->
|
||||
|
||||
#### How can we reproduce this issue?
|
||||
|
||||
<!-- Replace with numbered steps to reproduce the issue -->
|
||||
@@ -1,35 +0,0 @@
|
||||
# Feature request
|
||||
|
||||
<!-- This template is for feature requests. Please fill out the following: -->
|
||||
|
||||
|
||||
#### Select the type of feature you are requesting:
|
||||
|
||||
<!-- To check a box, replace the space between the [] with a x -->
|
||||
|
||||
- [ ] Cog
|
||||
- [ ] Command
|
||||
- [ ] API functionality
|
||||
|
||||
#### Describe your requested feature
|
||||
|
||||
<!--
|
||||
Feel free to describe in as much detail as you wish.
|
||||
|
||||
If you are requesting a cog to be included in core:
|
||||
- Describe the functionality in as much detail as possible
|
||||
- Include the command structure, if possible
|
||||
- Please note that unless it's something that should be core functionality,
|
||||
we reserve the right to reject your suggestion and point you to our cog
|
||||
board to request it for a third-party cog
|
||||
|
||||
If you are requesting a command:
|
||||
- Include what cog it should be in and a name for the command
|
||||
- Describe the intended functionality for the command
|
||||
- Note any restrictions on who can use the command or where it can be used
|
||||
|
||||
If you are requesting API functionality:
|
||||
- Describe what it should do
|
||||
- Note whether it is to extend existing functionality or introduce new functionality
|
||||
|
||||
-->
|
||||
@@ -1,21 +0,0 @@
|
||||
# Other bugs
|
||||
|
||||
<!--
|
||||
Did you find a bug with something other than a command? Fill out the following:
|
||||
-->
|
||||
|
||||
#### What were you trying to do?
|
||||
|
||||
<!-- Replace this line with a description of what you were trying to do -->
|
||||
|
||||
#### What were you expecting to happen?
|
||||
|
||||
<!-- Replace this line with a description of what you were expecting to happen -->
|
||||
|
||||
#### What actually happened?
|
||||
|
||||
<!-- Replace this line with a description of what actually happened. Include any error messages -->
|
||||
|
||||
#### How can we reproduce this issue?
|
||||
|
||||
<!-- Replace with numbered steps to reproduce the issue -->
|
||||
@@ -1,7 +0,0 @@
|
||||
### Type
|
||||
|
||||
- [ ] Bugfix
|
||||
- [ ] Enhancement
|
||||
- [ ] New feature
|
||||
|
||||
### Description of the changes
|
||||
@@ -1,14 +0,0 @@
|
||||
# Bugfix request
|
||||
|
||||
<!--
|
||||
To be used for pull requests that fix a bug
|
||||
-->
|
||||
|
||||
#### Describe the bug being fixed
|
||||
|
||||
<!--
|
||||
If an issue exists for the bug, mention
|
||||
that this PR fixes that issue
|
||||
-->
|
||||
|
||||
#### Anything we need to know about this fix?
|
||||
@@ -1,20 +0,0 @@
|
||||
# Enhancement request
|
||||
|
||||
<!--
|
||||
To be used for PRs which enhance existing features
|
||||
-->
|
||||
|
||||
#### Describe the enhancement
|
||||
|
||||
<!--
|
||||
Describe what your changes do.
|
||||
If adding commands, describe any restrictions on their usage.
|
||||
- For example, who can use the command? Where can it be used?
|
||||
-->
|
||||
|
||||
#### Does this enhancement break existing functionality?
|
||||
|
||||
<!-- To check a box, replace the space between the [] with a x -->
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
@@ -1,21 +0,0 @@
|
||||
# New feature addition
|
||||
|
||||
<!--
|
||||
To be used for PRs which add a new feature
|
||||
Examples of this include new APIs, new core cogs, etc.
|
||||
-->
|
||||
|
||||
#### What type of feature is this?
|
||||
|
||||
<!-- To check a box, replace the space between the [] with a x -->
|
||||
|
||||
- [ ] New core cog
|
||||
- [ ] New API
|
||||
- [ ] Other
|
||||
|
||||
#### Describe the feature
|
||||
|
||||
<!--
|
||||
If you are adding a cog, describe its commands in detail (functionality, usage restrictions, etc).
|
||||
If the new feature introduces new requirements, please try to explain why they are necessary.
|
||||
-->
|
||||
@@ -1,16 +0,0 @@
|
||||
# New release
|
||||
|
||||
<!--
|
||||
To be used by collaborators for doing releases.
|
||||
Most contributors will not need to use this.
|
||||
-->
|
||||
|
||||
#### Version
|
||||
|
||||
|
||||
|
||||
#### Has a draft release been created for this?
|
||||
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Translations update
|
||||
|
||||
<!--
|
||||
Used for PRs updating translations from Crowdin
|
||||
-->
|
||||
+40
-150
@@ -1,160 +1,50 @@
|
||||
# Trivia list repo injection
|
||||
redbot/trivia/
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
|
||||
*.json
|
||||
*.exe
|
||||
*.dll
|
||||
.data
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
### 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
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# User-specific stuff:
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/dictionaries
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# 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
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# Gradle:
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
# =========================
|
||||
# Operating System Files
|
||||
# =========================
|
||||
|
||||
# CMake
|
||||
cmake-build-debug/
|
||||
# OSX
|
||||
# =========================
|
||||
|
||||
# Mongo Explorer plugin:
|
||||
.idea/**/mongoSettings.xml
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
## File-based project format:
|
||||
*.iws
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
## Plugin-specific files:
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
|
||||
# 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/
|
||||
|
||||
# pytest
|
||||
.pytest_cache/
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
__pycache__
|
||||
json
|
||||
cache
|
||||
@@ -1,14 +0,0 @@
|
||||
formats:
|
||||
- pdf
|
||||
|
||||
build:
|
||||
image: latest
|
||||
|
||||
requirements_file: docs/requirements.txt
|
||||
|
||||
python:
|
||||
version: 3.6
|
||||
pip_install: true
|
||||
extra_requirements:
|
||||
- docs
|
||||
- mongo
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
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: PyPi Deployment
|
||||
if: tag IS present
|
||||
python: 3.5.3
|
||||
env:
|
||||
- DEPLOYING=true
|
||||
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
|
||||
- stage: Crowdin 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: script
|
||||
script: python3 ./generate_strings.py
|
||||
skip_cleanup: true
|
||||
on:
|
||||
repo: Cog-Creators/Red-DiscordBot
|
||||
branch: V3/develop
|
||||
python: 3.5.3
|
||||
tags: true
|
||||
@@ -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.
|
||||
|
||||
Red - A fully customizable Discord bot
|
||||
Copyright (C) 2015-2018 Twentysix
|
||||
{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (C) {year} {name of author}
|
||||
|
||||
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:
|
||||
|
||||
Red-DiscordBot Copyright (C) 2015-2018 Twentysix
|
||||
{project} Copyright (C) {year} {fullname}
|
||||
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.
|
||||
@@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -1,5 +0,0 @@
|
||||
include README.rst
|
||||
include LICENSE
|
||||
include requirements.txt
|
||||
include discord/bin/*.dll
|
||||
include redbot/cogs/audio/application.yml
|
||||
@@ -0,0 +1,144 @@
|
||||
# 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
@@ -1,42 +0,0 @@
|
||||
.. 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``.
|
||||
@@ -1,5 +0,0 @@
|
||||
api_key_env: CROWDIN_API_KEY
|
||||
project_identifier_env: CROWDIN_PROJECT_ID
|
||||
files:
|
||||
- source: /**/*.pot
|
||||
translation: /%original_path%/%locale%.po
|
||||
@@ -0,0 +1,132 @@
|
||||
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")
|
||||
@@ -1,20 +0,0 @@
|
||||
# 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)
|
||||
@@ -1,48 +0,0 @@
|
||||
.. systemd service guide
|
||||
|
||||
==========================
|
||||
Setting up auto-restart using systemd on Linux
|
||||
==========================
|
||||
|
||||
---------------------------
|
||||
Creating the service file
|
||||
---------------------------
|
||||
|
||||
Create the new service file:
|
||||
|
||||
:code:`sudo nano /etc/systemd/system/red@.service`
|
||||
|
||||
Paste the following and replace all instances of :code:`username` with the username your bot is running under (hopefully not root):
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[Unit]
|
||||
Description=%I redbot
|
||||
After=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/home/username/.local/bin/redbot %I --no-prompt
|
||||
User=username
|
||||
Group=username
|
||||
Type=idle
|
||||
Restart=always
|
||||
RestartSec=15
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Save and exit :code:`ctrl + O; enter; ctrl + x`
|
||||
|
||||
---------------------------
|
||||
Starting and enabling the service
|
||||
---------------------------
|
||||
|
||||
To start the bot, run the service and add the instance name after the **@**:
|
||||
|
||||
:code:`sudo systemctl start red@instancename`
|
||||
|
||||
To set the bot to start on boot, you must enable the service, again adding the instance name after the **@**:
|
||||
|
||||
:code:`sudo systemctl enable red@instancename`
|
||||
|
||||
.. note:: This same file can be used to start as many instances of the bot as you wish, without creating more service files, just start and enable more services and add any bot instance name after the **@**
|
||||
@@ -1,62 +0,0 @@
|
||||
.. Importing data from a V2 install
|
||||
|
||||
================================
|
||||
Importing data from a V2 install
|
||||
================================
|
||||
|
||||
----------------
|
||||
What you'll need
|
||||
----------------
|
||||
|
||||
1. A Running V3 bot
|
||||
2. The path where your V2 bot is installed
|
||||
|
||||
--------------
|
||||
Importing data
|
||||
--------------
|
||||
|
||||
.. important::
|
||||
|
||||
Unless otherwise specified, the V2 data will take priority over V3 data for the same entires
|
||||
|
||||
.. important::
|
||||
|
||||
For the purposes of this guide, your prefix will be denoted as
|
||||
[p]
|
||||
|
||||
You should swap whatever you made your prefix in for this.
|
||||
All of the below are commands to be entered in discord where the bot can
|
||||
see them.
|
||||
|
||||
The dataconverter cog is not loaded by default. To start, load it with
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]load dataconverter
|
||||
|
||||
Next, you'll need to give it the path where your V2 install is.
|
||||
|
||||
On linux and OSX, it may look something like:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
/home/username/Red-DiscordBot/
|
||||
|
||||
On Windows it will look something like:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
C:\Users\yourusername\Red-DiscordBot
|
||||
|
||||
Once you have that path, give it to the bot with the following command
|
||||
(make sure to swap your own path in)
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
[p]convertdata /home/username/Red-DiscordBot/
|
||||
|
||||
|
||||
From here, if the path is correct, you will be prompted with an interactive menu asking you
|
||||
what data you would like to import
|
||||
|
||||
You can select an entry by number, or quit with any of 'quit', 'exit', 'q', '-1', or 'cancel'
|
||||
@@ -1,9 +0,0 @@
|
||||
.. Downloader Cog Reference
|
||||
|
||||
Downloader Cog Reference
|
||||
========================
|
||||
|
||||
.. automodule:: redbot.cogs.downloader
|
||||
|
||||
.. autoclass:: redbot.cogs.downloader.downloader.Downloader
|
||||
:members:
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
#!/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 = '2018, 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.
|
||||
#
|
||||
from redbot.core import __version__
|
||||
# The short X.Y version.
|
||||
version = __version__
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = __version__
|
||||
|
||||
# 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)}
|
||||
@@ -1,42 +0,0 @@
|
||||
.. 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:
|
||||
@@ -1,19 +0,0 @@
|
||||
.. bot module docs
|
||||
|
||||
===
|
||||
Bot
|
||||
===
|
||||
|
||||
.. automodule:: redbot.core.bot
|
||||
|
||||
RedBase
|
||||
^^^^^^^
|
||||
|
||||
.. autoclass:: RedBase
|
||||
:members:
|
||||
|
||||
Red
|
||||
^^^
|
||||
|
||||
.. autoclass:: Red
|
||||
:members:
|
||||
@@ -1,8 +0,0 @@
|
||||
.. cog manager docs
|
||||
|
||||
===========
|
||||
Cog Manager
|
||||
===========
|
||||
|
||||
.. automodule:: redbot.core.cog_manager
|
||||
:members:
|
||||
@@ -1,388 +0,0 @@
|
||||
.. 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:
|
||||
@@ -1,10 +0,0 @@
|
||||
.. red invocation context documentation
|
||||
|
||||
==========================
|
||||
Command Invocation Context
|
||||
==========================
|
||||
|
||||
.. automodule:: redbot.core.context
|
||||
|
||||
.. autoclass:: redbot.core.RedContext
|
||||
:members:
|
||||
@@ -1,11 +0,0 @@
|
||||
.. 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:
|
||||
@@ -1,76 +0,0 @@
|
||||
.. 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:
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
.. framework events list
|
||||
|
||||
=============
|
||||
Custom Events
|
||||
=============
|
||||
|
||||
RPC Server
|
||||
^^^^^^^^^^
|
||||
|
||||
.. py:method:: Red.on_shutdown()
|
||||
|
||||
Dispatched when the bot begins it's shutdown procedures.
|
||||
@@ -1,54 +0,0 @@
|
||||
.. 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
|
||||
@@ -1,95 +0,0 @@
|
||||
.. 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:
|
||||
@@ -1,8 +0,0 @@
|
||||
.. rpc docs
|
||||
|
||||
===
|
||||
RPC
|
||||
===
|
||||
|
||||
.. automodule:: redbot.core.rpc
|
||||
:members:
|
||||
@@ -1,41 +0,0 @@
|
||||
.. red's core utils documentation
|
||||
|
||||
=================
|
||||
Utility Functions
|
||||
=================
|
||||
|
||||
Chat Formatting
|
||||
===============
|
||||
|
||||
.. automodule:: redbot.core.utils.chat_formatting
|
||||
:members:
|
||||
|
||||
Embed Helpers
|
||||
=============
|
||||
|
||||
.. automodule:: redbot.core.utils.embed
|
||||
:members:
|
||||
|
||||
Menu Helpers
|
||||
============
|
||||
|
||||
.. automodule:: redbot.core.utils.menus
|
||||
:members:
|
||||
|
||||
Mod Helpers
|
||||
===========
|
||||
|
||||
.. automodule:: redbot.core.utils.mod
|
||||
:members:
|
||||
|
||||
V2 Data Conversion
|
||||
==================
|
||||
|
||||
.. automodule:: redbot.core.utils.data_converter
|
||||
:members: DataConverter
|
||||
|
||||
Tunnel
|
||||
======
|
||||
|
||||
.. automodule:: redbot.core.utils.tunnel
|
||||
:members: Tunnel
|
||||
@@ -1,95 +0,0 @@
|
||||
.. 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 :doc:`/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.
|
||||
@@ -1,154 +0,0 @@
|
||||
.. Converting Data from a V2 cog
|
||||
|
||||
.. role:: python(code)
|
||||
:language: python
|
||||
|
||||
============================
|
||||
Importing Data From a V2 Cog
|
||||
============================
|
||||
|
||||
This guide serves as a tutorial on using the DataConverter class
|
||||
to import settings from a V2 cog.
|
||||
|
||||
------------------
|
||||
Things you'll need
|
||||
------------------
|
||||
|
||||
1. The path where each file holding related settings in v2 is
|
||||
2. A conversion function to take the data and transform it to conform to Config
|
||||
|
||||
-----------------------
|
||||
Getting your file paths
|
||||
-----------------------
|
||||
|
||||
You should probably not try to find the files manually.
|
||||
Asking the user for the base install path and using a relative path to where the
|
||||
data should be, then testing that the file exists there is safer. This is especially
|
||||
True if your cog has multiple settings files
|
||||
|
||||
Example
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from discord.ext import commands
|
||||
from pathlib import Path
|
||||
|
||||
@commands.command(name="filefinder")
|
||||
async def file_finding_command(self, ctx, filepath):
|
||||
"""
|
||||
this finds a file based on a user provided input and a known relative path
|
||||
"""
|
||||
|
||||
base_path = Path(filepath)
|
||||
fp = base_path / 'data' / 'mycog' / 'settings.json'
|
||||
if not fp.is_file():
|
||||
pass
|
||||
# fail, prompting user
|
||||
else:
|
||||
pass
|
||||
# do something with the file
|
||||
|
||||
---------------
|
||||
Converting data
|
||||
---------------
|
||||
|
||||
Once you've gotten your v2 settings file, you'll want to be able to import it
|
||||
There are a couple options available depending on how you would like to convert
|
||||
the data.
|
||||
|
||||
The first one takes a data path, and a conversion function and does the rest for you.
|
||||
This is great for simple data that just needs to quickly be imported without much
|
||||
modification.
|
||||
|
||||
|
||||
Here's an example of that in use:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pathlib import Path
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core.utils.data_converter import DataConverter as dc
|
||||
from redbot.core.config import Config
|
||||
|
||||
...
|
||||
|
||||
|
||||
async def import_v2(self, file_path: Path):
|
||||
"""
|
||||
to be called from a command limited to owner
|
||||
|
||||
This should be a coroutine as the convert function will
|
||||
need to be awaited
|
||||
"""
|
||||
|
||||
# First we give the converter our cog's Config instance.
|
||||
converter = dc(self.config)
|
||||
|
||||
# next we design a way to get all of the data into Config's internal
|
||||
# format. This should be a generator, but you can also return a single
|
||||
# list with identical results outside of memory usage
|
||||
def conversion_spec(v2data):
|
||||
for guild_id in v2.data.keys():
|
||||
yield {(Config.GUILD, guild_id): {('blacklisted',): True}}
|
||||
# This is yielding a dictionary that is designed for config's set_raw.
|
||||
# The keys should be a tuple of Config scopes + the needed Identifiers. The
|
||||
# values should be another dictionary whose keys are tuples representing
|
||||
# config settings, the value should be the value to set for that.
|
||||
|
||||
# Then we pass the file and the conversion function
|
||||
await converter.convert(file_path, conversion_spec)
|
||||
# From here, our data should be imported
|
||||
|
||||
|
||||
You can also choose to convert all of your data and pass it as a single dict
|
||||
This can be useful if you want finer control over the dataconversion or want to
|
||||
preserve any data from v3 that may share the same entry and set it aside to prompt
|
||||
a user
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pathlib import Path
|
||||
from discord.ext import commands
|
||||
|
||||
from redbot.core.utils.data_converter import DataConverter as dc
|
||||
from redbot.core.config import Config
|
||||
|
||||
...
|
||||
|
||||
await dc(config_instance).dict_import(some_processed_dict)
|
||||
|
||||
|
||||
The format of the items of the dict is the same as in the above example
|
||||
|
||||
|
||||
-----------------------------------
|
||||
Config Scopes and their Identifiers
|
||||
-----------------------------------
|
||||
|
||||
This section is provided as a quick reference for the identifiers for default
|
||||
scopes available in Config. This does not cover usage of custom scopes, though the
|
||||
data converter is compatible with those as well.
|
||||
|
||||
Global::
|
||||
:code:`(Config.GLOBAL,)`
|
||||
Guild::
|
||||
:code:`(Config.GUILD, guild_id)`
|
||||
Channel::
|
||||
:code:`(Config.CHANNEL, channel_id)`
|
||||
User::
|
||||
:code:`(Config.USER, user_id)`
|
||||
Member::
|
||||
:code:`(Config.MEMBER, guild_id, user_id)`
|
||||
Role::
|
||||
:code:`(Config.ROLE, role_id)`
|
||||
|
||||
|
||||
-----------------------------
|
||||
More information and Examples
|
||||
-----------------------------
|
||||
|
||||
For a more in depth look at how all of these commands function
|
||||
You may want to take a look at how core data is being imported
|
||||
|
||||
:code:`redbot/cogs/dataconverter/core_specs.py`
|
||||
@@ -1,56 +0,0 @@
|
||||
.. 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`
|
||||
@@ -1,56 +0,0 @@
|
||||
.. 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_arch
|
||||
install_raspbian
|
||||
cog_dataconverter
|
||||
autostart_systemd
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Cog Reference:
|
||||
|
||||
cog_downloader
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Red Development Framework Reference:
|
||||
|
||||
guide_migration
|
||||
guide_cog_creation
|
||||
guide_data_conversion
|
||||
framework_bank
|
||||
framework_bot
|
||||
framework_cogmanager
|
||||
framework_config
|
||||
framework_context
|
||||
framework_datamanager
|
||||
framework_downloader
|
||||
framework_events
|
||||
framework_i18n
|
||||
framework_modlog
|
||||
framework_rpc
|
||||
framework_utils
|
||||
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
@@ -1,55 +0,0 @@
|
||||
.. arch install guide
|
||||
|
||||
==============================
|
||||
Installing Red on Arch Linux
|
||||
==============================
|
||||
|
||||
.. warning:: For safety reasons, DO NOT install Red with a root user. Instead, make a new one.
|
||||
|
||||
:code:`https://wiki.archlinux.org/index.php/Users_and_groups`
|
||||
|
||||
-------------------------------
|
||||
Installing the pre-requirements
|
||||
-------------------------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
sudo pacman -Syu python-pip git base-devel jre8-openjdk
|
||||
|
||||
------------------
|
||||
Installing the bot
|
||||
------------------
|
||||
|
||||
To install without audio:
|
||||
|
||||
:code:`pip3 install -U --process-dependency-links red-discordbot --user`
|
||||
|
||||
To install with audio:
|
||||
|
||||
:code:`pip3 install -U --process-dependency-links red-discordbot[voice] --user`
|
||||
|
||||
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 --user`
|
||||
|
||||
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] --user`
|
||||
|
||||
------------------------
|
||||
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.
|
||||
@@ -1,56 +0,0 @@
|
||||
.. centos install guide
|
||||
|
||||
==========================
|
||||
Installing Red on CentOS 7
|
||||
==========================
|
||||
|
||||
.. warning:: For safety reasons, DO NOT install Red with a root user. Instead, `make a new one <https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Step_by_Step_Guide/s1-starting-create-account.html>`_.
|
||||
|
||||
---------------------------
|
||||
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 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 --user`
|
||||
|
||||
With audio:
|
||||
|
||||
:code:`pip3 install -U --process-dependency-links red-discordbot[voice] --user`
|
||||
|
||||
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 --user`
|
||||
|
||||
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] --user`
|
||||
|
||||
----------------------
|
||||
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.
|
||||
@@ -1,55 +0,0 @@
|
||||
.. 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 <https://manpages.debian.org/stretch/adduser/adduser.8.en.html>`_.
|
||||
|
||||
---------------------------
|
||||
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 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.
|
||||
@@ -1,53 +0,0 @@
|
||||
.. 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 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).
|
||||
@@ -1,56 +0,0 @@
|
||||
.. raspbian install guide
|
||||
|
||||
==================================
|
||||
Installing Red on Raspbian Stretch
|
||||
==================================
|
||||
|
||||
.. warning:: For safety reasons, DO NOT install Red with a root user. Instead, `make a new one <https://www.raspberrypi.org/documentation/linux/usage/users.md>`_.
|
||||
|
||||
---------------------------
|
||||
Installing pre-requirements
|
||||
---------------------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
sudo apt-get install python3.5-dev python3-pip build-essential libssl-dev libffi-dev git unzip default-jre -y
|
||||
|
||||
|
||||
--------------
|
||||
Installing Red
|
||||
--------------
|
||||
|
||||
Without audio:
|
||||
|
||||
:code:`pip3 install -U --process-dependency-links red-discordbot --user`
|
||||
|
||||
With audio:
|
||||
|
||||
:code:`pip3 install -U --process-dependency-links red-discordbot[voice] --user`
|
||||
|
||||
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 --user`
|
||||
|
||||
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] --user`
|
||||
|
||||
----------------------
|
||||
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.
|
||||
@@ -1,54 +0,0 @@
|
||||
.. 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 <http://manpages.ubuntu.com/manpages/artful/man8/adduser.8.html>`_.
|
||||
|
||||
-------------------------------
|
||||
Installing the pre-requirements
|
||||
-------------------------------
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
sudo apt install python3.5-dev python3-pip build-essential libssl-dev libffi-dev git unzip default-jre -y
|
||||
|
||||
|
||||
------------------
|
||||
Installing the bot
|
||||
------------------
|
||||
|
||||
To install without audio:
|
||||
|
||||
:code:`pip3 install -U --process-dependency-links red-discordbot --user`
|
||||
|
||||
To install with audio:
|
||||
|
||||
:code:`pip3 install -U --process-dependency-links red-discordbot[voice] --user`
|
||||
|
||||
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 --user`
|
||||
|
||||
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] --user`
|
||||
|
||||
------------------------
|
||||
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.
|
||||
@@ -1,47 +0,0 @@
|
||||
.. 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
|
||||
@@ -1,36 +0,0 @@
|
||||
@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
|
||||
@@ -1,4 +0,0 @@
|
||||
sphinx==1.6.5
|
||||
sphinxcontrib-asyncio
|
||||
sphinx_rtd_theme
|
||||
git+https://github.com/Rapptz/discord.py@rewrite#egg=discord.py[voice]
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
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
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -1,33 +0,0 @@
|
||||
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()
|
||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
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.
|
||||
@@ -0,0 +1 @@
|
||||
{"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"}
|
||||
@@ -0,0 +1 @@
|
||||
{"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"}
|
||||
@@ -0,0 +1 @@
|
||||
{"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"}
|
||||
@@ -0,0 +1 @@
|
||||
{"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
@@ -0,0 +1 @@
|
||||
{"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"}
|
||||
@@ -0,0 +1 @@
|
||||
{"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"}
|
||||
@@ -0,0 +1 @@
|
||||
{"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"]}
|
||||
@@ -0,0 +1 @@
|
||||
{"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"}
|
||||
@@ -0,0 +1 @@
|
||||
{"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"}
|
||||
@@ -0,0 +1 @@
|
||||
{"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
@@ -0,0 +1,551 @@
|
||||
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
|
||||
@@ -1,11 +0,0 @@
|
||||
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)
|
||||
@@ -1,170 +0,0 @@
|
||||
#!/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():
|
||||
description = "Red - Version {}".format(__version__)
|
||||
cli_flags = parse_cli_flags(sys.argv[1:])
|
||||
if cli_flags.list_instances:
|
||||
list_instances()
|
||||
elif cli_flags.version:
|
||||
print(description)
|
||||
sys.exit(0)
|
||||
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)
|
||||
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()
|
||||
@@ -1,5 +0,0 @@
|
||||
from .admin import Admin
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Admin())
|
||||
@@ -1,391 +0,0 @@
|
||||
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 its 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
|
||||
@@ -1,74 +0,0 @@
|
||||
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 server: {}".format(
|
||||
g.id
|
||||
))
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
self.active = False
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
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
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:41-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:41-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:41-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\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"
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# 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"
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:42-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\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"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: red-discordbot\n"
|
||||
"POT-Creation-Date: 2018-02-18 14:42+AKST\n"
|
||||
"PO-Revision-Date: 2018-04-15 16:43-0400\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"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user