├── .dockerignore ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE │ └── pull_request.md ├── README.md └── workflows │ ├── build.yml │ ├── contributors.yml │ └── lint.yml ├── .gitignore ├── LICENSE ├── README.md ├── SECURITY.MD ├── bot.py ├── cog ├── actionlogs │ ├── __init__.py │ └── actionlog.py ├── admin │ ├── __init__.py │ └── admin.py ├── hypixel │ ├── __init__.py │ ├── bedwars.py │ ├── duels.py │ ├── guild.py │ └── hypixel.py ├── messagelogs │ ├── __init__.py │ └── messageslog.py ├── misc │ ├── games.py │ ├── morse.py │ └── poll.py ├── modlog │ ├── __init__.py │ ├── modlog.py │ └── music │ │ └── music.py ├── premium │ ├── __init__.py │ ├── helpers │ │ └── premium_check.py │ └── premium.py ├── serverSafety │ ├── __init__.py │ └── lock.py └── topgg │ └── topgg.py ├── command ├── about.py ├── avatar.py ├── botinfo.py ├── channelinfo.py ├── color.py ├── github.py ├── invite.py ├── meme.py ├── ping.py ├── server_icon.py ├── server_info.py ├── talk.py ├── twitter.py └── userinfo.py ├── dev.Dockerfile ├── events ├── Guild │ ├── guild_join.py │ ├── on_guild_channel_create.py │ ├── on_guild_role_create.py │ ├── on_guild_role_delete.py │ └── on_guild_voice_channel_create.py ├── Join │ └── on_member_join.py ├── User │ ├── on_member_ban.py │ ├── on_member_remove.py │ └── on_member_unban.py ├── command_error.py ├── guild_join.py └── ready.py ├── logs └── .keepfile ├── plugins └── database │ ├── database.py │ └── sql │ └── schema.sql ├── requirements.txt ├── tests ├── .gitignore ├── requirements.txt └── test_commands │ ├── test_avatar.py │ ├── test_bot_info.py │ ├── test_bot_status.py │ ├── test_github.py │ ├── test_help.py │ ├── test_invite.py │ └── test_twitter.py ├── utilitybot.py └── utils ├── __init__.py ├── context.py ├── errors.py ├── permissions.py ├── prefix.py ├── status.py └── unload_cog.py /.dockerignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # Private .env stuff where data is stored 7 | *secrets.py 8 | *database.sql 9 | models/ 10 | 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Translations 38 | *.mo 39 | *.pot 40 | 41 | 42 | # Flask stuff: 43 | .webassets-cache 44 | 45 | # Scrapy stuff: 46 | .scrapy 47 | 48 | # Sphinx documentation 49 | docs/_build/ 50 | 51 | # PyBuilder 52 | target/ 53 | 54 | # Jupyter Notebook 55 | .ipynb_checkpoints 56 | 57 | # pyenv 58 | .python-version 59 | 60 | # celery beat schedule file 61 | celerybeat-schedule 62 | 63 | # SageMath parsed files 64 | *.sage.py 65 | 66 | # virtualenv when creating piplock 67 | .venv 68 | venv/ 69 | ENV/ 70 | 71 | # Spyder project settings 72 | .spyderproject 73 | .spyproject 74 | 75 | # Rope project settings 76 | .ropeproject 77 | 78 | # mkdocs documentation 79 | /site 80 | 81 | # mypy 82 | .mypy_cache/ 83 | 84 | # jetbrains 85 | .idea/ 86 | .iml 87 | 88 | # VSCode 89 | .vscode/ 90 | 91 | 92 | # Mac OS .DS_Store, which is a file that stores custom attributes of its containing folder (this is for fellow mac users.) 93 | .DS_Store 94 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: discordutilitybot 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | 27 | **Additional context** 28 | Add any other context about the problem here. 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this bot/project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the command/feature is 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen with the command 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/pull_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Pull request 3 | about: Create a pull request to request a change or a fix in code 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | d 10 | ** How to create a pull request** 11 | 1. fork the repository and make the changes there 12 | 2. once your down compare both repos and create a pull request 13 | 14 | ** Describe the change/fix** 15 | And a clear and concise description of the change/fix 16 | 17 | **addition context** 18 | Add any other info here about the change 19 | -------------------------------------------------------------------------------- /.github/README.md: -------------------------------------------------------------------------------- 1 |

2 |
3 | Utility Bot 4 |
5 |

6 | 7 |

Moderation, Games, Utilites, Music and much more!

8 | 9 |

10 | 11 | Discord Server 12 | 13 | 14 | GitHub Actions 15 | 16 | 17 | discord.py 18 | 19 | 20 | 21 | 22 | 23 | Code Style: Black 24 | 25 | 26 | 27 | 28 | 29 |

30 | Overview 31 | • 32 | Setup 33 | • 34 | Plugins 35 | • 36 | Community 37 | • 38 | License 39 |

40 | 41 | # Overview 42 | The goal of UtilityBot is to make managing a server easy and convienent with many useful commands! 43 | 44 | # Plugins 45 | Utility Bot is a bot that makes managing servers of any size easy, with per-channel mutes, moderation, memes, premium features and lots more! 46 | 47 | Here are a few examples: 48 | 49 | - Ban 50 | - Soft Ban 51 | - Music 52 | - Moderation 53 | - Utilites 54 | - Purge 55 | - Edit roles 56 | - Logging categories e.g: moderation, action logs message logs. 57 | 58 | We are still working on **Utility Bot** and we appreciate constructive critiscm and feedback to better develop the bot. We also appreciate pull requests to update commands and more! So don't hesitate to contribute. 59 | 60 | # License 61 | Released under the [MIT License](https://opensource.org/licenses/MIT) license. 62 | 63 | Logo created by [PineappleRind](https://pineapplerind.github.io) 64 | 65 | # Contributors 66 | - Andrew Nijmeh 67 | - PineappleRind 68 | - Aditya Kapoor 69 | - flopana 70 | - svcodes 71 | - yak-fumblepack 72 | 73 | 74 | # Donators 75 | > Over here we will have a list of all our donators who have donated via patreon! you can donate via clicking on the sponsor button on the top of the repository and clicking on the patreon link. 76 | 77 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: 5 | - dev 6 | 7 | jobs: 8 | build: 9 | name: build 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | ubuntu-latest: [20.04, 18.04] 14 | python-version: [3.6] 15 | 16 | steps: 17 | - name: Git checkout 18 | uses: actions/checkout@v1 19 | 20 | - name: Python checkout 21 | uses: actions/setup-python@v2 22 | with: 23 | python-version: ${{ matrix.python-version }} 24 | 25 | - name: Install dependencies 26 | run: | 27 | python -m pip install --upgrade pip 28 | pip install flake8 pytest 29 | pip install -r requirements.txt 30 | -------------------------------------------------------------------------------- /.github/workflows/contributors.yml: -------------------------------------------------------------------------------- 1 | name: contributors 2 | 3 | on: 4 | push: 5 | branches: 6 | - dev 7 | 8 | jobs: 9 | contributors: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v1 13 | - uses: cjdenio/contributor_list@master 14 | with: 15 | commit_message: Update contributors list 16 | max_contributors: 20 -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Linting 2 | on: 3 | push: 4 | branches: [dev] 5 | pull_request: 6 | workflow_dispatch: 7 | jobs: 8 | lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Set up Python 3.6 13 | uses: actions/setup-python@v2 14 | with: 15 | python-version: 3.6.9 16 | - name: Install dependencies 17 | run: | 18 | python -m pip install --upgrade pip 19 | pip install flake8 20 | pip install pylint 21 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi 22 | - name: Lint with flake8 23 | run: | 24 | flake8 --count --select=E9,F63,F7,F82 --show-source --statistics 25 | flake8 --count --max-complexity=10 --max-line-length=79 --statistics 26 | - name: Lint 27 | run: | 28 | pylint command 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # Config file for private data 7 | *.env 8 | *config.env 9 | *secrets.py 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | 26 | # Logging 27 | *.log 28 | *utility.log 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Translations 41 | *.mo 42 | *.pot 43 | 44 | 45 | # Flask stuff: 46 | .webassets-cache 47 | 48 | # Scrapy stuff: 49 | .scrapy 50 | 51 | # Sphinx documentation 52 | docs/_build/ 53 | 54 | # PyBuilder 55 | target/ 56 | 57 | # Jupyter Notebook 58 | .ipynb_checkpoints 59 | 60 | # pyenv 61 | .python-version 62 | 63 | # celery beat schedule file 64 | celerybeat-schedule 65 | 66 | # SageMath parsed files 67 | *.sage.py 68 | 69 | # virtualenv when creating piplock 70 | .venv 71 | venv/ 72 | ENV/ 73 | 74 | # Spyder project settings 75 | .spyderproject 76 | .spyproject 77 | 78 | # Rope project settings 79 | .ropeproject 80 | 81 | # mkdocs documentation 82 | /site 83 | 84 | # mypy 85 | .mypy_cache/ 86 | 87 | # jetbrains 88 | .idea/ 89 | .iml 90 | 91 | # VSCode 92 | .vscode/ 93 | 94 | *.DS_Store 95 | 96 | 97 | *.json 98 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # utilitybot 2 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/bada33cda57a4ece9091fdf8068513c3)](https://app.codacy.com/gh/discordutilitybot/utilitybot?utm_source=github.com&utm_medium=referral&utm_content=discordutilitybot/utilitybot&utm_campaign=Badge_Grade) -------------------------------------------------------------------------------- /SECURITY.MD: -------------------------------------------------------------------------------- 1 | ### Reporting security vulnerabitlites 2 | 3 | if you have found a bug or a vunerability please report the vunerability to security@utilitybot.co -------------------------------------------------------------------------------- /bot.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | 26 | import utilitybot 27 | from utilitybot import Utilitybot 28 | 29 | import logging 30 | import datetime 31 | import asyncpg 32 | import asyncio 33 | import dotenv 34 | import os 35 | from os.path import join, dirname 36 | from dotenv import load_dotenv 37 | import json 38 | import datetime 39 | 40 | dotenv_path = join(dirname(__file__), 'config.env') 41 | load_dotenv(dotenv_path) 42 | 43 | POSTGRES_PASSWORD = os.environ.get("database_password") 44 | DATABASE = os.environ.get('database') 45 | token = os.environ.get('discord_token') 46 | 47 | def get_prefix(bot, message): 48 | with open('prefixes.json', 'r') as f: 49 | prefixes = json.load(f) 50 | 51 | return prefixes[str(message.guild.id)] 52 | 53 | bot = Utilitybot( 54 | command_prefix='u!', 55 | status=discord.Status.online, 56 | activity= discord.Game(name="utilitybot.co | u!invite", type=3), 57 | case_insensitive=False, 58 | ) 59 | 60 | @bot.event 61 | async def on_guild_join(guild): 62 | with open('prefixes.json', 'r') as f: 63 | prefixes = json.load(f) 64 | 65 | prefixes[str(guild.id)] = 'u!' 66 | 67 | with open('prefixes.json', 'w') as f: 68 | json.dump(prefixes, f) 69 | 70 | bot.remove_command("help") 71 | 72 | bot.load_extension("cog.serverSafety.lock") 73 | async def start_db(): 74 | try: 75 | login_data = { 76 | "user": "postgres", 77 | "password": POSTGRES_PASSWORD, 78 | "database": DATABASE, 79 | "host": '172.105.104.44' 80 | } 81 | 82 | bot.db = asyncpg.create_pool(**login_data) 83 | bot.logging.info("Connected to database pool.") 84 | except KeyboardInterrupt: 85 | pass 86 | 87 | 88 | bot.remove_command("help") 89 | bot.load_extension("command.twitter") 90 | bot.load_extension("command.avatar") 91 | bot.load_extension("command.github") 92 | bot.load_extension("cog.admin.admin") 93 | bot.load_extension("cog.hypixel.guild") 94 | bot.load_extension("cog.hypixel.hypixel") 95 | bot.load_extension("cog.hypixel.bedwars") 96 | bot.load_extension("cog.hypixel.duels") 97 | bot.load_extension("command.botinfo") 98 | bot.load_extension("command.server_info") 99 | bot.load_extension("command.server_icon") 100 | bot.load_extension("events.Guild.on_guild_channel_create") 101 | bot.load_extension("events.command_error") 102 | bot.load_extension("command.meme") 103 | bot.load_extension("cog.misc.games") 104 | bot.load_extension("command.invite") 105 | bot.load_extension("command.talk") 106 | bot.load_extension("command.ping") 107 | bot.load_extension('command.about') 108 | bot.load_extension("command.channelinfo") 109 | 110 | @bot.command(aliases = ['commands']) 111 | @commands.cooldown(1, 5, commands.BucketType.guild) 112 | async def help(ctx): 113 | embed = discord.Embed( 114 | title = 'List of available Commands, all Commands are case insensitive', 115 | colour = discord.Colour.orange(), 116 | description = '`Important links `https://utilitybot.co, https://discord.gg/3fBcFFsm6U, https://twitter.com/utilitybot1, https://top.gg/bot/790399381840068619#/ ', 117 | timestamp=datetime.datetime.utcnow() 118 | ) 119 | embed.add_field(name = 'Commands Categories 📖', value = '`Utility, Fun, Bot, Moderation`', inline = False) 120 | embed.add_field(name = 'Bot 🤖', value = '`help, botinfo, invite, ping`', inline = False) 121 | embed.add_field(name = 'Fun 🎉', value = '`eightball, coinflip`', inline = False) 122 | embed.add_field(name = 'Integrations 🎉', value = '`hypixel, bedwars, duels, guild, meme`', inline = False) 123 | embed.add_field(name = 'Utility ⚙️', value = '`servericon, avatar, channel_information`', inline = False) 124 | embed.add_field(name = 'Moderation ⚒️', value = '`poll, ban, unban, mute, unmute, warn, kick,purge, nick`', inline = False) 125 | embed.set_footer(text = 'Utility Bot, The ultimate server management bot') 126 | embed.set_thumbnail(url='https://cdn.discordapp.com/attachments/790349906648498219/805846213475827722/Screen_Shot_2021-01-04_at_7.png?size=2048') 127 | await ctx.send(embed=embed) 128 | 129 | bot.run('NzkwMzk5MzgxODQwMDY4NjE5.X-ACyQ.g9EGJ-VrLMbznPIH-WG2spJoDbI') 130 | -------------------------------------------------------------------------------- /cog/actionlogs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/cog/actionlogs/__init__.py -------------------------------------------------------------------------------- /cog/actionlogs/actionlog.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/cog/actionlogs/actionlog.py -------------------------------------------------------------------------------- /cog/admin/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/cog/admin/__init__.py -------------------------------------------------------------------------------- /cog/admin/admin.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from discord import utils 4 | from discord import TextChannel, Member 5 | from discord import Role 6 | from discord.ext import tasks 7 | import asyncpg 8 | import asyncio 9 | import re 10 | import datetime 11 | from discord import Member, TextChannel, Role 12 | 13 | class Admin(commands.Cog, name="Moderation"): 14 | 15 | def __init__(self, bot): 16 | self.bot = bot 17 | self.ban_list = [] 18 | self.day_list = [] 19 | self.server_list = [] 20 | 21 | @commands.command() 22 | @commands.cooldown(1, 5, commands.BucketType.guild) 23 | @commands.has_permissions(kick_members=True) 24 | async def kick(self, ctx, target : discord.Member = None, *, arg: str = None): 25 | arg2 = arg or 'No reason provided' 26 | embed = discord.Embed( 27 | title = str(target) + ' was kicked from ' + ctx.guild.name, 28 | description = 'Reason: ' + arg2, 29 | colour = discord.Colour.orange(), 30 | timestamp=datetime.datetime.utcnow() 31 | ) 32 | embed2 = discord.Embed( 33 | title = 'You were kicked from' + ctx.guild.name, 34 | description = 'Reason' + arg2, 35 | colour = discord.Colour.orange(), 36 | timestamp=datetime.datetime.utcnow() 37 | ) 38 | 39 | if target == None: 40 | embed = discord.Embed( 41 | title = 'You must specify a user to kick.', 42 | colour = discord.Colour.orange(), 43 | timestamp=datetime.datetime.utcnow() 44 | ) 45 | await ctx.send(embed=embed) 46 | else: 47 | try: 48 | await target.send(embed=embed2) 49 | except: 50 | embed = discord.Embed( 51 | title = 'Failed to DM user, user most likely has DMS off.', 52 | colour = discord.Colour.orange(), 53 | timestamp=datetime.datetime.utcnow() 54 | ) 55 | await ctx.send(embed=embed) 56 | try: 57 | await ctx.send(embed=embed) 58 | await target.kick(reason=arg2) 59 | except: 60 | pass 61 | 62 | @commands.command() 63 | @commands.cooldown(1, 5, commands.BucketType.guild) 64 | @commands.has_permissions(ban_members=True) 65 | async def ban(self, ctx, target: discord.Member = None, *, arg: str = None): 66 | arg2 = arg or 'No reason provided' 67 | embed = discord.Embed( 68 | title='ban', 69 | description='Reason: ' + arg2, 70 | colour = discord.Colour.orange(), 71 | timestamp=datetime.datetime.utcnow() 72 | ) 73 | embed2 = discord.Embed( 74 | title= 'You were banned from ' + ctx.guild.name, 75 | description='Reason' + arg2, 76 | colour=discord.Colour.orange(), 77 | timestamp=datetime.datetime.utcnow() 78 | ) 79 | 80 | if target == None: 81 | embed = discord.Embed( 82 | title = 'You must specify a user to ban.', 83 | colour = discord.Colour.orange(), 84 | timestamp=datetime.datetime.utcnow() 85 | ) 86 | await ctx.send(embed=embed) 87 | else: 88 | try: 89 | await target.send(embed=embed2) 90 | except: 91 | embed = discord.Embed( 92 | title='Failed to DM user, user most likely has DMs off.', 93 | timestamp=datetime.datetime.utcnow() 94 | ) 95 | await ctx.send(embed=embed) 96 | try: 97 | await ctx.send(embed=embed) 98 | await target.kick(reason=arg2) 99 | except: 100 | pass 101 | 102 | @commands.command() 103 | @commands.cooldown(1, 5, commands.BucketType.guild) 104 | @commands.has_permissions(ban_members=True) 105 | async def unban(self, ctx, *, member): 106 | bannedUsers = await ctx.guild.bans() 107 | name, discriminator = member.split("#") 108 | 109 | for ban in bannedUsers: 110 | user = ban.user 111 | 112 | if(user.name, user.discriminator) == (name, discriminator): 113 | await ctx.guild.unban(user) 114 | embed = discord.Embed( 115 | title=f'{user.mention} was unbanned.' 116 | ) 117 | await ctx.send(embed=embed) 118 | return 119 | 120 | @commands.command() 121 | @commands.cooldown(1, 5, commands.BucketType.guild) 122 | @commands.has_permissions(manage_messages=True) 123 | async def purge(self, ctx, arg: str=None): 124 | if arg == None: 125 | embed = discord.Embed( 126 | title='You must specify an amount to purge.' 127 | ) 128 | await ctx.send(embed=embed) 129 | try: 130 | if int(arg) > 400: 131 | embed = discord.Embed( 132 | title = "I can't purge over 400 messages!", 133 | colour = discord.Colour.red() 134 | ) 135 | await ctx.send(embed=embed) 136 | 137 | if int(arg) < 401: 138 | purge = int(arg) + 1 139 | await ctx.channel.purge(limit=purge) 140 | embed = discord.Embed( 141 | title = str(arg) + 'Messages were purged!', 142 | colour = discord.Colour.green() 143 | ) 144 | await ctx.send(embed=embed, delete_after=3) 145 | except: 146 | await ctx.send(":x: Failed to purge messages.") 147 | 148 | @commands.command() 149 | @commands.cooldown(1, 5, commands.BucketType.guild) 150 | @commands.has_permissions(kick_members=True) 151 | async def warn(self, ctx, target: discord.Member = None, *, arg: str = None): 152 | arg2 = arg or 'No reason provided' 153 | embed = discord.Embed( 154 | title = str(target) +' Has been warned by ' + str(ctx.author), 155 | description = 'Reason: ' + arg2, 156 | colour = discord.Colour.orange(), 157 | timestamp=datetime.datetime.utcnow() 158 | ) 159 | if target == None: 160 | await ctx.send('u!warn [member] [reason] (Optional)]') 161 | pass 162 | else: 163 | try: 164 | await target.send('You were warned in ' + ctx.guild.name), 165 | await ctx.send(embed=embed) 166 | except: 167 | await ctx.send('Failed to DM user :(.') 168 | 169 | @commands.command() 170 | @commands.cooldown(1, 5, commands.BucketType.guild) 171 | @commands.has_permissions(mute_members=True) 172 | async def mute(self, ctx, member: discord.Member = None, length: int = None, *, reason=None): 173 | guild = ctx.guild 174 | mutedRole = discord.utils.get(guild.roles, name="Muted") 175 | if member == None or reason == None: 176 | embed = discord.Embed( 177 | title = 'You must specify a user/reason to mute.' 178 | ) 179 | await ctx.send(embed=embed) 180 | pass 181 | else: 182 | if not mutedRole: 183 | await ctx.send('Create a muted role named Muted!') 184 | pass 185 | else: 186 | try: 187 | await member.add_roles(mutedRole, reason=reason) 188 | await ctx.send(f"Muted {member} for reason: {reason}\nMute Length: {length} seconds\nMute Command executed by: {ctx.author}") 189 | try: 190 | await member.send(f"You were muted in the server {guild.name} for {reason}\nMute Command executed by: {ctx.author}\nMute Length: {length} seconds") 191 | except: 192 | await ctx.send('diff\n-Failed to dm user') 193 | except: 194 | embed = discord.Embed( 195 | title='Failed to mute user.' 196 | ) 197 | await ctx.send(embed=embed) 198 | 199 | if ctx.guild.id == 751476973477560412: 200 | updates = ctx.guild.get_channel(785572711300464691) 201 | updates2 = ctx.guild.get_channel(797220475071496192) 202 | await updates.send(f'{member.mention} got sent to the **Shadow Realm**. ') 203 | await updates2.send(f'-------------------------------------------------------------------------------------------------------\nOh hi {member.mention}, looks like you got muted and sent to the shadow realm.... Sucks doesnt it?\n\nMaybe next time you should learn to behave and not act like a :clown:\n\nAnyway, enjoy your time in this dark place, and make sure react to your reason in #mute-reason') 204 | try: 205 | await asyncio.sleep(length) 206 | await member.remove_roles(mutedRole) 207 | await ctx.send(f'```{member} has been unmuted.\nMute command executed by: {ctx.author}\nMute Length: {length} seconds```') 208 | if ctx.guild.id == 751476973477560412: 209 | updates = ctx.guild.get_channel(756608398501347434) 210 | await updates.send(f'{member} got released from the **Shadow Realm**') 211 | except: 212 | await ctx.send('```diff\n- Failed to unmute member, check for the following:\n\n- Mute role not created\n- Member is a moderator/administrator\n- I do not have manage roles permissions```') 213 | 214 | @commands.cooldown(1, 5, commands.BucketType.guild) 215 | @commands.has_permissions(kick_members = True) 216 | async def unmute(self, ctx, member: discord.Member=None): 217 | if member == None: 218 | embed = discord.Embed( 219 | title='You specify a member to unmute' 220 | ) 221 | await ctx.send(embed=embed) 222 | else: 223 | try: 224 | mutedRole = discord.utils.get(ctx.guild.roles, name="Muted") 225 | await member.remove_roles(mutedRole) 226 | embed = discord.Embed( 227 | title=f' Unmuted {member.mention}.' 228 | ) 229 | await ctx.send(embed=embed) 230 | except: 231 | await ctx.send('') 232 | try: 233 | embed = discord.Embed( 234 | title = F'You were unmuted in {ctx.guild.name}.' 235 | ) 236 | await ctx.send(embed=embed) 237 | except: 238 | await ctx.send('Failed to DM user :(.') 239 | 240 | 241 | @commands.command() 242 | @commands.cooldown(1, 5, commands.BucketType.guild) 243 | @commands.has_permissions(manage_nicknames = True) 244 | async def nick(self, ctx, user: [Member], * , name: str = None): 245 | if name == None: 246 | await ctx.send('Specify a name to change! | Example: u!nick [Member (optional)] [name]') 247 | else: 248 | try: 249 | user == user or ctx.author 250 | await user.edit(nick = name) 251 | await ctx.send('Nickname changed for ' + str(user) + '.\nCurrent Name: ' + name + '') 252 | except: 253 | await ctx.send('\n-Failed to change users nickname.\nCheck if I have manage nicknames permissions or if the user is a higher rank than me.') 254 | 255 | def setup(bot): 256 | bot.add_cog(Admin(bot)) 257 | bot.logging.info('Loaded Admin cog!') -------------------------------------------------------------------------------- /cog/hypixel/__init__.py: -------------------------------------------------------------------------------- 1 | from .bedwars import Bedwars 2 | from .hypixel import Hypixel 3 | from .duels import Duels -------------------------------------------------------------------------------- /cog/hypixel/bedwars.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | import datetime 4 | import aiohttp 5 | 6 | 7 | class Bedwars(commands.Cog): 8 | def __init__(self, bot): 9 | self.bot = bot 10 | 11 | @commands.command(aliases=['bw', 'bws']) 12 | async def bedwars(self, ctx, user): 13 | channel = ctx.message.channel 14 | 15 | if 'error' in user: 16 | embed = discord.Embed(title=f"{user} is not a user", colour=color, 17 | timestamp=datetime.datetime.utcnow()) 18 | await ctx.send(embed=embed) 19 | async with channel.typing(): 20 | async with aiohttp.ClientSession() as session: 21 | async with session.get(f'https://api.slothpixel.me/api/players/{user}') as resp: 22 | player = await resp.json() 23 | 24 | color = ctx.author.color 25 | embed = discord.Embed(title=f'{user} Bedwars stats', colour=color, timestamp=datetime.datetime.utcnow()) 26 | embed.add_field(name="Stars:", value=player["stats"]["BedWars"]["level"]) 27 | embed.add_field(name="Wins:", value=player["stats"]["BedWars"]["wins"]) 28 | embed.add_field(name="Games played:", value=player["stats"]["BedWars"]["games_played"]) 29 | embed.add_field(name="W/l ratio:", value=player["stats"]["BedWars"]["w_l"]) 30 | embed.add_field(name="Final Kills:", value=player["stats"]["BedWars"]["final_kills"]) 31 | embed.add_field(name="Final Deaths:", value=player["stats"]["BedWars"]["final_deaths"]) 32 | embed.add_field(name="Normal Kills:", value=player["stats"]["BedWars"]["kills"]) 33 | embed.add_field(name="Normal Deaths:", value=player["stats"]["BedWars"]["deaths"]) 34 | embed.add_field(name="FKDR:", value=player["stats"]["BedWars"]["final_k_d"]) 35 | embed.add_field(name="Current Winstreak:", value=player["stats"]["BedWars"]["winstreak"]) 36 | await ctx.send(embed=embed) 37 | return 38 | 39 | def setup(bot): 40 | bot.add_cog(Bedwars(bot)) 41 | bot.logging.info("Loaded bedwars command!") -------------------------------------------------------------------------------- /cog/hypixel/duels.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | import aiohttp 4 | import datetime 5 | class Duels(commands.Cog): 6 | def __init__(self, bot): 7 | self.bot = bot 8 | 9 | @commands.command() 10 | async def duels(self, ctx, user: str): 11 | channel = ctx.message.channel 12 | async with channel.typing(): 13 | async with aiohttp.ClientSession() as session: 14 | async with session.get(f'https://api.slothpixel.me/api/guilds/{user}') as resp: 15 | player = await resp.json() 16 | color = ctx.author.color 17 | 18 | if 'error' in user: 19 | embed = discord.Embed(title=f"{user} is not a player", colour=color, 20 | timestamp=datetime.datetime.utcnow()) 21 | await ctx.send(embed=embed) 22 | else: 23 | embed = discord.Embed(title=f'{user} Duel stats', colour=color, timestamp=datetime.datetime.utcnow()) 24 | embed.add_field(name="Wins:", value=player["stats"]["Duels"]["wins"], inline=False) 25 | embed.add_field(name="Kills:", value=player["stats"]["Duels"]["kills"], inline=False) 26 | embed.add_field(name="Deaths:", value=player["stats"]["Duels"]["deaths"], inline=False) 27 | embed.add_field(name="Bow hits:", value=player["stats"]["Duels"]["bow_hits"], inline=False) 28 | embed.add_field(name="Melee hits:", value=player["stats"]["Duels"]["melee_hits"], inline=False) 29 | embed.add_field(name="Best winstreak:", value=player["stats"]["Duels"]["best_overall_winstreak"], 30 | inline=False) 31 | await ctx.send(embed=embed) 32 | def setup(bot): 33 | bot.add_cog(Duels(bot)) 34 | bot.logging.info("Loaded duels command") 35 | 36 | 37 | -------------------------------------------------------------------------------- /cog/hypixel/guild.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | import datetime 4 | import aiohttp 5 | 6 | class Guild(commands.Cog): 7 | def __init__(self, bot): 8 | self.bot = bot 9 | 10 | @commands.command(name="guild", aliases=['g']) 11 | async def guild(self, ctx, user: str = None): 12 | channel = ctx.author.channel 13 | color = ctx.author.color 14 | async with channel.typing(): 15 | async with aiohttp.ClientSession() as session: 16 | async with session.get(f'https://api.slothpixel.me/api/guilds/{user}') as resp: 17 | user == await resp.json() 18 | 19 | if "error" in user: 20 | embed = discord.Embed(title=f"{user} is not in a Guild", colour=color, timestamp=datetime.datetime.utcnow()) 21 | await ctx.send(embed=embed) 22 | else: 23 | embed = discord.Embed(title=f"{user} Guild", colour=color, timestamp=datetime.datetime.utcnow()) 24 | embed.add_field(name="Guild name:", value=user["name"], inline=False) 25 | embed.add_field(name="Guild tag:", value=user["tag"], inline=False) 26 | embed.add_field(name="Guild level:", value=user["level"], inline=False) 27 | embed.add_field(name="Guild legacy ranking:", value=user["legacy_ranking"], inline=False) 28 | embed.add_field(name="Guild description:", value=user["description"], inline=False) 29 | await ctx.send(embed=embed) 30 | 31 | def setup(bot): 32 | bot.add_cog(Guild(bot)) 33 | bot.logging.info('Loaded cog Guild') -------------------------------------------------------------------------------- /cog/hypixel/hypixel.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | import aiohttp 4 | import datetime 5 | from aiohttp import ClientSession 6 | 7 | class Hypixel(commands.Cog): 8 | def __init__(self, bot): 9 | self.bot = bot 10 | 11 | @commands.command(name="hypixel", aliases=['hy']) 12 | async def hypixel(self, ctx, user: str = None): 13 | channel = ctx.message.channel 14 | async with aiohttp.ClientSession() as session: 15 | async with session.get(f'https://api.slothpixel.me/api/players/{user}') as resp: 16 | player = await resp.json() 17 | 18 | if user is None: 19 | await ctx.send(f" :x: Please specifiy a valid username or uuid.", delete_after=6) 20 | return 21 | 22 | if 'error' in player: 23 | await ctx.send(f":x:{user} Is not a valid username.") 24 | return 25 | 26 | async with channel.typing(): 27 | async with aiohttp.ClientSession() as session: 28 | 29 | async with session.get(f'https://api.slothpixel.me/api/players/{user}') as resp: 30 | player = await resp.json() 31 | 32 | async with session.get(f'https://api.slothpixel.me/api/guilds/{user}') as resp: 33 | guild = await resp.json() 34 | 35 | color = ctx.author.color 36 | embed = discord.Embed(title=f'{user} Hypixel Stats', colour=color, timestamp=datetime.datetime.utcnow()) 37 | 38 | if player['rank'] == 'MVP_PLUS_PLUS': 39 | embed.add_field(name="PlayerRank", value="MVP++") 40 | 41 | elif player['rank'] == 'MVP_PLUS': 42 | embed.add_field(name="PlayerRank", value="MVP+") 43 | 44 | elif player['rank'] == "VIP_PLUS": 45 | embed.add_field(name="PlayerRank", value="VIP+") 46 | 47 | else: 48 | embed.add_field(name="PlayerRank", value=player['rank']) 49 | embed.add_field(name="Level:", value=player["level"]) 50 | if "error" in guild: 51 | embed.add_field(name="Guild:", value=f"{user} isn't in a guild") 52 | else: 53 | embed.add_field(name="Guild:", value=guild["name"]) 54 | embed.add_field(name="Discord:", value=player["links"]["DISCORD"]) 55 | embed.add_field(name="Online:", value=player['online']) 56 | embed.add_field(name="Minecraft version:", value=player['mc_version']) 57 | embed.add_field(name="Last game played:", value=player['last_game']) 58 | await ctx.send(embed=embed) 59 | await self.bot.logging.info({player}) 60 | 61 | 62 | def setup(bot): 63 | bot.add_cog(Hypixel(bot)) 64 | bot.logging.info('Loaded cog Hypixel!') 65 | -------------------------------------------------------------------------------- /cog/messagelogs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/cog/messagelogs/__init__.py -------------------------------------------------------------------------------- /cog/messagelogs/messageslog.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | import datetime 4 | 5 | -------------------------------------------------------------------------------- /cog/misc/games.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | import random 5 | 6 | class RNG(commands.Cog): 7 | def __init__(self, bot): 8 | self.bot = bot 9 | 10 | @commands.command() 11 | async def roll(self, ctx, num): 12 | final = random.randint(1, num) 13 | await ctx.send(final) 14 | 15 | @commands.command(aliases=["cf"]) 16 | async def coinflip(self, ctx): 17 | """ Flips a coin. """ 18 | choices = ["Heads","Tails"] 19 | result = random.choice(choices) 20 | await ctx.send(f"You got {result} \U0001fa99.") 21 | 22 | @commands.command(name="8ball", aliases=["8b"]) 23 | async def _8ball(self, ctx, *, question): 24 | """asks the magic 8ball a question""" 25 | responses = [ 26 | 'It is certain', 'It is decidedly so', 'Without a doubt', 27 | 'Yes – definitely', 'You may rely on it', 'As I see it, yes', 28 | 'Most likely', 'Outlook good', 'Yes', 'Signs point to yes', 29 | 'Reply hazy, try again', 'Ask again later', 'Better not tell you now', 30 | 'Better not tell you now', 'Concentrate and ask again', 'Very doubtful', 31 | "Don't count on it", 'My reply is no', 'My sources say no', 'Outlook not so good', 'Very doubtful' 32 | ] 33 | answer = random.choice(responses) 34 | await ctx.send(f"\U0001f3b1 Question for the magic 8ball: {question}\nAnswer: {answer}") 35 | 36 | def setup(bot): 37 | bot.add_cog(RNG(bot)) 38 | bot.logging.info('Loaded RNG Commands') 39 | -------------------------------------------------------------------------------- /cog/misc/morse.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import discord 3 | from discord.ext import commands 4 | from operator import itemgetter 5 | import base64 6 | import binascii 7 | import re 8 | 9 | 10 | 11 | class Morse(commands.Cog): 12 | 13 | def __init__(self, bot, settings): 14 | self.bot = bot 15 | self.settings = settings 16 | self.to_morse = { 17 | "a" : ".-", 18 | "b" : "-...", 19 | "c" : "-.-.", 20 | "d" : "-..", 21 | "e" : ".", 22 | "f" : "..-.", 23 | "g" : "--.", 24 | "h" : "....", 25 | "i" : "..", 26 | "j" : ".---", 27 | "k" : "-.-", 28 | "l" : ".-..", 29 | "m" : "--", 30 | "n" : "-.", 31 | "o" : "---", 32 | "p" : ".--.", 33 | "q" : "--.-", 34 | "r" : ".-.", 35 | "s" : "...", 36 | "t" : "-", 37 | "u" : "..-", 38 | "v" : "...-", 39 | "w" : ".--", 40 | "x" : "-..-", 41 | "y" : "-.--", 42 | "z" : "--..", 43 | "1" : ".----", 44 | "2" : "..---", 45 | "3" : "...--", 46 | "4" : "....-", 47 | "5" : ".....", 48 | "6" : "-....", 49 | "7" : "--...", 50 | "8" : "---..", 51 | "9" : "----.", 52 | "0" : "-----" 53 | } 54 | 55 | 56 | def suppressed(self, guild, msg): 57 | if self.settings.getServerStat(guild, "SuppressMentions"): 58 | return Nullify.clean(msg) 59 | else: 60 | return msg 61 | 62 | 63 | @commands.command(pass_context=True) 64 | async def morse(self, ctx, *, content = None): 65 | 66 | if content == None: 67 | await ctx.send("Usage `{}morse [content]`".format(ctx.prefix)) 68 | return 69 | 70 | word_list = content.split() 71 | morse_list = [] 72 | for word in word_list: 73 | letter_list = [] 74 | for letter in word: 75 | if letter.lower() in self.to_morse: 76 | letter_list.append(self.to_morse[letter.lower()]) 77 | if len(letter_list): 78 | morse_list.append(" ".join(letter_list)) 79 | 80 | if not len(morse_list): 81 | await ctx.send("There were no valid a-z/0-9 characters in the passed content.") 82 | return 83 | 84 | msg = " ".join(morse_list) 85 | msg = "```\n" + msg + "```" 86 | await ctx.send(self.suppressed(ctx.guild, msg)) 87 | 88 | 89 | @commands.command(pass_context=True) 90 | async def unmorse(self, ctx, *, content = None): 91 | """morse code to ascii""" 92 | 93 | if content == None: 94 | await ctx.send("Usage `{}unmorse [content]`".format(ctx.prefix)) 95 | return 96 | 97 | word_list = content.split(" ") 98 | ascii_list = [] 99 | for word in word_list: 100 | letter_list = word.split() 101 | letter_ascii = [] 102 | for letter in letter_list: 103 | for key in self.to_morse: 104 | if self.to_morse[key] == letter: 105 | letter_ascii.append(key.upper()) 106 | if len(letter_ascii): 107 | ascii_list.append("".join(letter_ascii)) 108 | 109 | if not len(ascii_list): 110 | await ctx.send("There were no valid morse characters in the passed content.") 111 | return 112 | 113 | msg = " ".join(ascii_list) 114 | msg = "```\n" + msg + "```" 115 | await ctx.send(self.suppressed(ctx.guild, msg)) 116 | 117 | def setup(bot): 118 | bot.add_cog(Morse(bot)) 119 | bot.logging.info("Loaded cog morse cog!") -------------------------------------------------------------------------------- /cog/misc/poll.py: -------------------------------------------------------------------------------- 1 | from discord.ext import commands 2 | import asyncio 3 | 4 | def to_emoji(c): 5 | base = 0x1f1e6 6 | return chr(base + c) 7 | 8 | class Polls(commands.Cog): 9 | 10 | def __init__(self, bot): 11 | self.bot = bot 12 | 13 | @commands.command() 14 | @commands.guild_only() 15 | async def poll(self, ctx, *, question): 16 | 17 | messages = [ctx.message] 18 | answers = [] 19 | 20 | def check(m): 21 | return m.author == ctx.author and m.channel == ctx.channel and len(m.content) <= 100 22 | 23 | for i in range(50): 24 | messages.append(await ctx.send(f"Say poll option or {ctx.prefix}cancel to publish poll.")) 25 | 26 | try: 27 | entry = await self.bot.wait_for("message", check=check, timeout=90.0) 28 | except asyncio.TimeoutError: 29 | break 30 | 31 | messages.append(entry) 32 | 33 | if entry.clean_content.startswith(f"{ctx.prefix}cancel"): 34 | break 35 | 36 | answers.append((to_emoji(i), entry.clean_content)) 37 | 38 | try: 39 | await ctx.channel.delete_messages(messages) 40 | except: 41 | pass 42 | 43 | answer = "\n".join(f"{keycap}: {content}" for keycap, content in answers) 44 | actual_poll = await ctx.send(f"{ctx.author} asks: {question}\n\n{answer}") 45 | for emoji, _ in answers: 46 | await actual_poll.add_reaction(emoji) 47 | 48 | @poll.error 49 | async def poll_error(self, ctx, error): 50 | if isinstance(error, commands.MissingRequiredArgument): 51 | return await ctx.send("Missing the question.") 52 | 53 | @commands.command() 54 | @commands.guild_only() 55 | async def quickpoll(self, ctx, *questions_and_choices: str): 56 | 57 | if len(questions_and_choices) < 3: 58 | return await ctx.send("Need at least 1 question with 2 choices.") 59 | elif len(questions_and_choices) > 21: 60 | return await ctx.send("You can only have up to 20 choices.") 61 | 62 | perms = ctx.channel.permissions_for(ctx.me) 63 | if not (perms.read_message_history or perms.add_reactions): 64 | return await ctx.send("Need Read Message History and Add Reactions permissions.") 65 | 66 | question = questions_and_choices[0] 67 | choices = [(to_emoji(e), v) for e, v in enumerate(questions_and_choices[1:])] 68 | 69 | try: 70 | await ctx.message.delete() 71 | except: 72 | pass 73 | 74 | body = "\n".join(f"{key}: {c}" for key, c in choices) 75 | poll = await ctx.send(f"{ctx.author} asks: {question}\n\n{body}") 76 | for emoji, _ in choices: 77 | await poll.add_reaction(emoji) 78 | 79 | def setup(bot): 80 | bot.add_cog(Polls(bot)) 81 | bot.logging.info("Loaded poll system!") -------------------------------------------------------------------------------- /cog/modlog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/cog/modlog/__init__.py -------------------------------------------------------------------------------- /cog/modlog/modlog.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | 5 | class Modlogcheck: 6 | pass 7 | 8 | class Modlog(commands.Cog): 9 | def __init__(self, bot): 10 | self.bot = bot 11 | 12 | @commands.command() 13 | async def modlog(self, ctx, channel: discord.TextChannel): 14 | await ctx.send(f"Configuring modlog channel to #{channel}", delete_after=3) 15 | 16 | await self.bot.db 17 | def setup(bot): 18 | bot.add_cog(Modlog(bot)) -------------------------------------------------------------------------------- /cog/modlog/music/music.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from discord.ext import commands 3 | import discord 4 | import youtube_dl 5 | import os 6 | from datetime import datetime 7 | 8 | youtube_dl.utils.bug_reports_message = lambda: '' 9 | 10 | 11 | ytdl_format_options = { 12 | 'format': 'bestaudio/best', 13 | 'outtmpl': '%(extractor)s-%(id)s-%(title)s.%(ext)s', 14 | 'restrictfilenames': True, 15 | 'noplaylist': True, 16 | 'nocheckcertificate': True, 17 | 'ignoreerrors': False, 18 | 'logtostderr': False, 19 | 'quiet': True, 20 | 'no_warnings': True, 21 | 'default_search': 'auto', 22 | 'source_address': '0.0.0.0' # bind to ipv4 since ipv6 addresses cause issues sometimes 23 | } 24 | 25 | ffmpeg_options = { 26 | 'options': '-vn' 27 | } 28 | 29 | ytdl = youtube_dl.YoutubeDL(ytdl_format_options) 30 | players = {} 31 | 32 | class YTDLSource(discord.PCMVolumeTransformer): 33 | def __init__(self, source, *, data, volume=0.5): 34 | super().__init__(source, volume) 35 | 36 | self.data = data 37 | 38 | self.title = data.get('title') 39 | self.url = data.get('url') 40 | 41 | @classmethod 42 | async def from_url(cls, url, *, loop=None, stream=False): 43 | loop = loop or asyncio.get_event_loop() 44 | data = await loop.run_in_executor(None, lambda: ytdl.extract_info(url, download=not stream)) 45 | 46 | if 'entries' in data: 47 | # take first item from a playlist 48 | data = data['entries'][0] 49 | 50 | filename = data['url'] if stream else ytdl.prepare_filename(data) 51 | return cls(discord.FFmpegPCMAudio(filename, **ffmpeg_options), data=data) 52 | 53 | class Music(commands.Cog): 54 | def __init__(self, bot): 55 | self.bot = bot 56 | @commands.command() 57 | async def play(self, ctx, *, url: str = None): 58 | 59 | if url == None: 60 | await ctx.send('```c!play [youtube title or URL]```') 61 | async with ctx.typing(): 62 | player = await YTDLSource.from_url(url, stream=True) 63 | ctx.voice_client.play(player, after=lambda e: print('Player error: %s' % e) if e else None) 64 | embed = discord.Embed( 65 | title = 'Song requested by: ' + str(ctx.author), 66 | description = '```Now playing: {}'.format(player.title) + '\n\nRequested by: ' + str(ctx.author) + '```', 67 | colour = discord.Colour.green(), 68 | timestamp=datetime.utcnow() 69 | ) 70 | embed.set_thumbnail(url = 'https://images-ext-1.discordapp.net/external/jM4yYJy0MXntKVzqbDTLUi72OfQneGULXCMZoBbFwhw/%3Fsize%3D1024/https/cdn.discordapp.com/avatars/739305861951782985/407c829335208d72834df10e45721c5b.webp?width=701&height=701') 71 | await ctx.send(embed = embed) 72 | players[ctx.guild.id]=player 73 | 74 | @commands.command() 75 | async def pause(self, ctx): 76 | state = ctx.get_voice_state(ctx.message.guild) 77 | if state.is_playing(): 78 | player = state.player 79 | player.pause() 80 | 81 | @commands.command() 82 | async def join(self, ctx): 83 | if ctx.author.voice and ctx.author.voice.channel: 84 | channel = ctx.author.voice.channel 85 | await channel.connect() 86 | embed = discord.Embed( 87 | title='I have joined the voice chat, say u!leave for me to leave the voice channel.', 88 | colour=discord.Colour.green() 89 | ) 90 | await ctx.send(embed=embed) 91 | else: 92 | embed = discord.Embed( 93 | title = ':musical_note: You have to be in a voice channel for me to join!', 94 | colour = discord.Colour.red() 95 | ) 96 | await ctx.send(embed=embed) 97 | 98 | @commands.command(pass_context = True) 99 | async def leave(self, ctx): 100 | 101 | if ctx.author.voice and ctx.author.voice.channel: 102 | await ctx.voice_client.disconnect() 103 | embed = discord.Embed( 104 | title='I have left the voice chat, say u!join for me to join again!', 105 | colour=discord.Colour.red() 106 | ) 107 | await ctx.send(embed = embed) 108 | else: 109 | embed = discord.Embed( 110 | title = 'You have to be in a voice channel for me to leave!', 111 | colour = discord.Colour.red() 112 | ) 113 | await ctx.send(embed = embed) 114 | 115 | @commands.command(pass_context=True) 116 | async def skip(self, ctx): 117 | channel = await ctx.voice_client.disconnect() 118 | if ctx.author.voice and ctx.author.voice.channel: 119 | channel = ctx.author.voice.channel 120 | await channel.connect() 121 | embed = discord.Embed( 122 | title = 'Skip requested by: ' + str(ctx.author), 123 | description = '```Previous song skipped```', 124 | colour = discord.Colour.green(), 125 | timestamp=datetime.utcnow() 126 | ) 127 | embed.set_thumbnail(url = 'https://images-ext-1.discordapp.net/external/jM4yYJy0MXntKVzqbDTLUi72OfQneGULXCMZoBbFwhw/%3Fsize%3D1024/https/cdn.discordapp.com/avatars/739305861951782985/407c829335208d72834df10e45721c5b.webp?width=701&height=701') 128 | await ctx.send(embed = embed) 129 | def setup(bot): 130 | bot.add_cog(Music(bot)) -------------------------------------------------------------------------------- /cog/premium/__init__.py: -------------------------------------------------------------------------------- 1 | import Premium from .premium -------------------------------------------------------------------------------- /cog/premium/helpers/premium_check.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/cog/premium/helpers/premium_check.py -------------------------------------------------------------------------------- /cog/premium/premium.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | import discord 23 | from discord.ext import commands 24 | 25 | 26 | class Premium(commands.Cog): 27 | def __init__(self, bot): 28 | self.bot = bot 29 | self.premium = {} 30 | 31 | def is_premium(self, ctx): 32 | return ctx.message.guilld.id == [702173174107996170, 800132845552271413, 467930052470767636, 751476973477560412] 33 | 34 | @commands.command() 35 | @has_premium() 36 | async def test(self, ctx): 37 | pass 38 | 39 | 40 | def setup(bot): 41 | bot.add_cog(Premium(bot)) 42 | bot.logging.info("Loaded premium cog!") 43 | -------------------------------------------------------------------------------- /cog/serverSafety/__init__.py: -------------------------------------------------------------------------------- 1 | from .lock import Lock -------------------------------------------------------------------------------- /cog/serverSafety/lock.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | import re 25 | from discord.ext import commands 26 | 27 | 28 | 29 | class Lock(commands.Cog): 30 | def __init__(self, bot): 31 | self.bot = bot 32 | self.states = {} 33 | 34 | 35 | 36 | def setup(bot): 37 | bot.add_cog(Lock(bot)) 38 | bot.logging.info("Loaded lock command!") -------------------------------------------------------------------------------- /cog/topgg/topgg.py: -------------------------------------------------------------------------------- 1 | import dbl 2 | import discord 3 | from discord.ext import commands 4 | 5 | class TopGG(commands.Cog): 6 | 7 | def __init__(self, bot): 8 | self.bot = bot 9 | self.token = '' 10 | 11 | self.dblpy = dbl.DBLClient(self.bot, self.token, autopost=True, # This posts guild every 30 minute intervalds) 12 | 13 | async def on_guild_post(): 14 | bot.logging.info("Server count posted!") 15 | 16 | def setup(bot): 17 | bot.add_cog(TopGG(bot)) 18 | bot.logging.info("Loaded TopGG cog") -------------------------------------------------------------------------------- /command/about.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import typing 24 | 25 | import discord 26 | from discord.ext import commands 27 | 28 | 29 | class Avatar(commands.Cog): 30 | def __init__(self, bot): 31 | self.bot = bot 32 | 33 | 34 | @commands.command() 35 | async def about(self, ctx): 36 | await ctx.send("https://cdn.discordapp.com/attachments/790349229833977897/796129026041315388/utiliybot_commercial.mp4") 37 | 38 | 39 | def setup(bot): 40 | bot.add_cog(Avatar(bot)) 41 | bot.logging.info('Loaded avatar command') -------------------------------------------------------------------------------- /command/avatar.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import typing 24 | 25 | import discord 26 | from discord.ext import commands 27 | 28 | 29 | class Avatar(commands.Cog): 30 | def __init__(self, bot): 31 | self.bot = bot 32 | 33 | @commands.command(name="avatar", aliases=["av", "pfp"]) 34 | @commands.max_concurrency(1, per=commands.BucketType.user) 35 | async def avatar(self, ctx, target: typing.Union[discord.Member, discord.User, str, None]): 36 | if isinstance(target, str): 37 | return await ctx.send(embed=discord.Embed( 38 | description=f"User \"{target}\" not found", 39 | color=ctx.author.color, 40 | timestamp=ctx.message.created_at 41 | )) 42 | if not target: 43 | target = ctx.author 44 | await ctx.send(embed=discord.Embed( 45 | color=target.color, 46 | timestamp=ctx.message.created_at, 47 | description=target.mention 48 | ).set_image( 49 | url=str(target.avatar_url_as(static_format="png", size=2048)) 50 | ).set_author( 51 | name=f"{target}'s Avatar" 52 | )) 53 | 54 | 55 | def setup(bot): 56 | bot.add_cog(Avatar(bot)) 57 | bot.logging.info('Loaded avatar command') -------------------------------------------------------------------------------- /command/botinfo.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | from discord.utils import get 26 | 27 | class Botinfo(commands.Cog): 28 | def __init__(self, bot): 29 | self.bot = bot 30 | 31 | @commands.command(aliases=['infobot, info']) 32 | async def botinfo(self, ctx): 33 | embed = discord.Embed( 34 | title = "All about Utility Bot!", 35 | description = "Hello! I am Utility Bot I'm here to help you manage and moderate your server with a touch of fun! I was written in Python by Flop#7234 using discord.py and python3.6! Type u!help to get a link to our website for a list of commands!", 36 | color = discord.Color.orange() 37 | ) 38 | 39 | embed.set_image(url="https://cdn.discordapp.com/attachments/790349906648498219/805846213475827722/Screen_Shot_2021-01-04_at_7.png?size=2048") 40 | embed.set_thumbnail(url="https://cdn.discordapp.com/attachments/790349906648498219/805846213475827722/Screen_Shot_2021-01-04_at_7.png?size=2048") 41 | embed.set_footer(text=f"Server: {len(self.bot.guilds)}. Utility Bot The Server Management Bot.") 42 | 43 | await ctx.send(embed=embed) 44 | 45 | def setup(bot): 46 | bot.add_cog(Botinfo(bot)) 47 | bot.logging.info(f'Loaded botinfo command') -------------------------------------------------------------------------------- /command/channelinfo.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | import datetime 4 | import asyncio 5 | from typing import Optional 6 | 7 | 8 | class Channelinfo(commands.Cog): 9 | def __init__(self, bot): 10 | self.bot = bot 11 | 12 | @commands.command() 13 | @commands.cooldown(1, 5, commands.BucketType.guild) 14 | async def channelinfo(self, ctx, chan: Optional[discord.TextChannel]): 15 | channel = chan 16 | if channel == None: 17 | channel = ctx.channel 18 | embed = discord.Embed( 19 | title = f'Stats for: {channel.name}', 20 | description = f'List of details about: {channel.name}', 21 | timestamp=datetime.datetime.utcnow(), 22 | colour = discord.Colour.blue() 23 | ) 24 | embed.add_field(name="Channel Guild", value=ctx.guild.name, inline=False) 25 | embed.add_field(name="Channel Id", value=channel.id, inline=False) 26 | embed.add_field(name="Channel Topic", value=f"{channel.topic if channel.topic else 'No topic.'}", inline=False) 27 | embed.add_field(name="Channel Position", value=channel.position, inline=False) 28 | embed.add_field(name="Channel Slowmode Delay", value=channel.slowmode_delay, inline=False) 29 | embed.add_field(name="Channel is NSFW?", value=channel.is_nsfw(), inline=False) 30 | embed.add_field(name="Channel is Announcement Channel?", value=channel.is_news(), inline=False) 31 | embed.add_field(name="Channel Creation Time", value=channel.created_at, inline=False) 32 | embed.add_field(name="Channel Permissions Synced", value=channel.permissions_synced, inline=False) 33 | embed.add_field(name = 'Channel ID', value = channel.id) 34 | embed.add_field(name="Channel Hash", value=hash(channel), inline=False) 35 | embed.set_thumbnail(url= ctx.guild.icon_url) 36 | await ctx.send(embed = embed) 37 | 38 | 39 | def setup(bot): 40 | bot.add_cog(Channelinfo(bot)) 41 | bot.logging.info("Loaded channelinfo command") 42 | -------------------------------------------------------------------------------- /command/color.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | import random 4 | 5 | class Color(commands.Cog): 6 | def __init__(self, bot): 7 | self.bot = bot 8 | 9 | @commands.command() 10 | async def Color(self, ctx): 11 | hexes = '0123456789ABCDEF' 12 | hexes_result = '#' + ''.join(random.choice(hexes) for _ in range(6)) 13 | embed = discord.Embed( 14 | title = 'Random Color', 15 | description = "Random Hex color:" + hexes_result, 16 | colour=0x + hexes_result 17 | ) 18 | await ctx.send(embed) 19 | 20 | 21 | def setup(bot): 22 | bot.add_cog(Color(bot)) 23 | bot.logging.info("Loaded color command") 24 | -------------------------------------------------------------------------------- /command/github.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | 26 | """Link to the github repo.""" 27 | class Github(commands.Cog): 28 | def __init__(self, bot): 29 | self.bot = bot 30 | 31 | 32 | @commands.command(aliases=['src, oss, source']) 33 | async def github(self, ctx): 34 | embed = discord.Embed( 35 | title='https://github.com/discordutilitybot/utilitybot', 36 | ) 37 | await ctx.send(embed=embed) 38 | 39 | 40 | 41 | def setup(bot): 42 | bot.add_cog(Github(bot)) 43 | bot.logging.info(f'Loaded github command!') -------------------------------------------------------------------------------- /command/invite.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | import logging 26 | 27 | 28 | class Invite(commands.Cog): 29 | def __init__(self, bot): 30 | self.bot = bot 31 | 32 | 33 | @commands.command(aliases=['inv, botinvite']) 34 | async def invite(self, ctx): 35 | embed = discord.Embed( 36 | title = 'https://discord.com/api/oauth2/authorize?client_id=790399381840068619&permissions=2147483639&scope=bot' 37 | 38 | ) 39 | await ctx.send(embed=embed) 40 | 41 | def setup(bot): 42 | bot.add_cog(Invite(bot)) 43 | bot.logging.info(f'Loaded invite command!') 44 | -------------------------------------------------------------------------------- /command/meme.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | import aiohttp 26 | from aiohttp import ClientSession 27 | import random 28 | 29 | class Memecommand(commands.Cog): 30 | def __init__(self, bot): 31 | self.bot = bot 32 | 33 | 34 | 35 | def setup(bot): 36 | bot.add_cog(Memecommand(bot)) 37 | bot.logging.info("Loaded meme command") 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /command/ping.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | class Latency(commands.Cog): 5 | def __init__(self, bot): 6 | self.bot = bot 7 | 8 | 9 | @commands.command(name="ping", aliases=['pong, latency']) 10 | async def ping(self, ctx): 11 | pong = round(self.bot.latency * 1000) 12 | await ctx.send(f":ping_pong: Pong in {pong}ms") 13 | 14 | 15 | def setup(bot): 16 | bot.add_cog(Latency(bot)) 17 | bot.logging.info('Loaded ping command') -------------------------------------------------------------------------------- /command/server_icon.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | class Servericon(commands.Cog): 5 | def __init__(self, bot) : 6 | self.bot = bot 7 | 8 | @commands.command() 9 | async def servericon(self, ctx): 10 | member = ctx.author.color 11 | guild = ctx.message.author 12 | 13 | await ctx.send(embed=discord.Embed( 14 | color=member.color if member else ctx.author.color.set_image( 15 | url=str(guild.avatar_url_as(static_format='png', size=2048)) 16 | ) 17 | )) 18 | 19 | def setup(bot): 20 | bot.add_cog(Servericon(bot)) 21 | bot.logging.info("Loaded Servericon command") -------------------------------------------------------------------------------- /command/server_info.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | import datetime 4 | class Serverinfo(commands.Cog): 5 | def __init__(self, bot): 6 | self.bot = bot 7 | 8 | @commands.command(aliases=['guildinfo, ginfo, serverinfo']) 9 | async def serverinfo(self, ctx): 10 | statuses = [len(list(filter(lambda m: str(m.status) == "online", ctx.guild.members))), 11 | len(list(filter(lambda m: str(m.status) == "idle", ctx.guild.members))), 12 | len(list(filter(lambda m: str(m.status) == "dnd", ctx.guild.members))), 13 | len(list(filter(lambda m: str(m.status) == "offline", ctx.guild.members)))] 14 | 15 | embed = discord.Embed( 16 | title = 'Server Stats', 17 | description = f'Stats for Guild: {ctx.guild.name}', 18 | colour=discord.Colour.blue() 19 | 20 | ) 21 | embed.add_field(name = 'Owner:', value = ctx.guild.owner) 22 | embed.add_field(name = 'Server ID:', value = ctx.guild.id) 23 | embed.add_field(name = 'Region:', value = ctx.guild.region) 24 | embed.add_field(name = 'Total Members:', value = len(ctx.guild.members)) 25 | embed.add_field(name = 'Humans:', value = len(list(filter(lambda m: not m.bot, ctx.guild.members)))) 26 | embed.add_field(name = 'Bots:', value = len(list(filter(lambda m: m.bot, ctx.guild.members)))) 27 | embed.add_field(name = 'Banned Members:', value = len(await ctx.guild.bans())) 28 | embed.add_field(name = 'Statuses:', value = f"🟢 {statuses[0]} :yellow_circle: {statuses[1]} 🔴 {statuses[2]} ⚪ {statuses[3]}") 29 | embed.add_field(name = 'Categories:', value = len(ctx.guild.categories)) 30 | embed.add_field(name = 'Channels:', value = len(ctx.guild.text_channels) + len(ctx.guild.voice_channels)) 31 | embed.add_field(name = 'Text Channels:', value = len(ctx.guild.text_channels)) 32 | embed.add_field(name = 'Voice Channels:', value = len(ctx.guild.voice_channels)) 33 | embed.add_field(name = 'Roles:', value = len(ctx.guild.roles)) 34 | embed.add_field(name = 'Invites:', value = len(await ctx.guild.invites())) 35 | embed.add_field(name = 'Moderators', value = len([i for i in ctx.guild.members if i.guild_permissions.administrator])) 36 | embed.add_field(name = 'Server Created At:', value = ctx.guild.created_at.strftime("%d/%m/%Y %H:%M:%S")) 37 | embed.set_thumbnail(url= ctx.guild.icon_url) 38 | await ctx.send(embed=embed) 39 | 40 | def setup(bot): 41 | bot.add_cog(Serverinfo(bot)) 42 | bot.logging.info("Loaded serverinfo command") -------------------------------------------------------------------------------- /command/talk.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | class Talk(commands.Cog): 5 | def __init__(self, bot): 6 | self.bot = bot 7 | 8 | @commands.command() 9 | async def talk(self, ctx, delete, *, text): 10 | if delete == 'y': 11 | await ctx.channel.purge(limit=1) 12 | await ctx.send(text) 13 | if delete == 'n': 14 | await ctx.send(text) 15 | 16 | def setup(bot): 17 | bot.add_cog(Talk(bot)) 18 | bot.logging.info("Loaded talk command") 19 | -------------------------------------------------------------------------------- /command/twitter.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | 26 | 27 | class Twitter(commands.Cog): 28 | def __init__(self, bot): 29 | self.bot = bot 30 | 31 | @commands.command() 32 | async def twitter(self, ctx): 33 | embed = discord.Embed( 34 | title = 'https://twitter.com/utilitybot1' 35 | ) 36 | await ctx.send(embed=embed) 37 | 38 | def setup(bot): 39 | bot.add_cog(Twitter(bot)) 40 | bot.logging.info("Loaded twitter command") -------------------------------------------------------------------------------- /command/userinfo.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | 5 | class Userinfo(commands.Cog): 6 | def __init__(self, bot: 7 | self.bot = bot 8 | 9 | @commands.command() 10 | async def userinfo(ctx, target: Optional[Member]): 11 | if ctx.author.guild_permissions.administrator: 12 | x = ctx.guild.members 13 | if target in x: 14 | roles = [role for role in target.roles] 15 | embed = discord.Embed(title="User information", colour=discord.Color.gold(), timestamp=datetime.utcnow()) 16 | 17 | embed.set_author(name=target.name, icon_url=target.avatar_url) 18 | 19 | embed.set_thumbnail(url=target.avatar_url) 20 | 21 | fields = [("Name", str(target), False), 22 | ("ID", target.id, False), 23 | ("Status", str(target.status).title(), False), 24 | (f"Roles ({len(roles)})", " ".join([role.mention for role in roles]), False), 25 | ("Created at", target.created_at.strftime("%d/%m/%Y %H:%M:%S"), False), 26 | ("Joined at", target.joined_at.strftime("%d/%m/%Y %H:%M:%S"), False)] 27 | 28 | for name, value, inline in fields: 29 | embed.add_field(name=name, value=value, inline=inline) 30 | 31 | await ctx.send(embed=embed) 32 | else: 33 | await ctx.send(f'You have to ping soneone from this server') 34 | else: 35 | await ctx.send(f'Not enough permissions') 36 | 37 | def setup(Userinfo): 38 | bot.add_cog(Userinfo(bot)) 39 | bot.logging.info("Loaded userinfo command") -------------------------------------------------------------------------------- /dev.Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | ARG version=3.6 3 | ARG file="./bot.py" 4 | ARG entrypoint="python3" 5 | 6 | FROM python:$version 7 | 8 | WORKDIR /utilitybot / 9 | 10 | # Update system packages and pip 11 | RUN pip3 install --upgrade pip 12 | 13 | RUN git clone https://github.com/discordutilitybot/utilitybot.git 14 | COPY requirements.txt . 15 | RUN pip3 install -r requirements.txt 16 | 17 | COPY /utils / 18 | COPY /cogs / 19 | COPY /events / 20 | COPY /tests / 21 | COPY /command / 22 | 23 | ENTRYPOINT [ $entrypoint ] 24 | CMD [${file}] 25 | -------------------------------------------------------------------------------- /events/Guild/guild_join.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | from discord import Guild, User 26 | from discord.utils import get 27 | 28 | import asyncpg 29 | import logging 30 | 31 | class GuildJoin(commands.Cog): 32 | def __init__(self, bot): 33 | self.bot = bot 34 | 35 | 36 | @commands.Cog.listener() 37 | async def on_guild_join(self, guild): 38 | 39 | permissions = discord.Permissions(send_messages=False, speak=False, read_messages=True) 40 | await self.bot.create_role( 41 | name="Muted", 42 | reason="Utility bot's Default Muted Role on join. (used for muting)", 43 | permissions=permissions, 44 | color=discord.Color.orange()) 45 | 46 | # Insert global guild data 47 | self.bot.db.execute("INSERT INTO guilds (guild_id, guild_roles, guild_channels, guild_messages, guild_voice_channels, guild_categorys)") 48 | 49 | # Insert data for guild settings and prefix's.. 50 | self.bot.db.execute(f"INSERT INTO guild_settings (guild_id, muted_role, guild_prefix, logging_moderation, logging_action, logging_join, logging_leave, logging_messages) VALUES ({guild.id}, Muted,") 51 | 52 | 53 | 54 | 55 | def setup(bot): 56 | bot.add_cog(GuildJoin(bot)) 57 | bot.logging.info("Loaded event GuildJoin") 58 | -------------------------------------------------------------------------------- /events/Guild/on_guild_channel_create.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | from discord.utils import get 26 | 27 | class ChannelCreate(commands.Cog): 28 | def __init__(self, bot): 29 | self.bot = bot 30 | 31 | @commands.Cog.listener() 32 | async def on_guild_channel_create(self, channel): 33 | actionlogch = self.bot.get_channel(742195223664394310) 34 | 35 | if actionlogch: 36 | createdby = None 37 | if channel.guild.me.guild_permissions.view_audit_log: 38 | async for e in channel.guild.audit_logs(action=discord.AuditLogAction.channel_create, limit=5): 39 | if e.target.id == channel.id: 40 | createdby = e.user 41 | break 42 | 43 | embed = discord.Embed(color=discord.Color.green( 44 | 45 | ), timestamp=channel.created_at, description=f"**New Channel created #{channel.name}**") 46 | 47 | if createdby: 48 | embed.add_field( 49 | name='Created by', value=f'{createdby} ({createdby.id})', inline=False 50 | ) 51 | embed.set_author(name=channel.guild.name, 52 | icon_url=str(channel.guild.icon_url, size=2048) 53 | ) 54 | embed.set_footer( 55 | text=f"Channel ID: {channel.id} | Guild ID: {channel.guild.id}") 56 | 57 | try: 58 | await actionlogch.send(embed=embed) 59 | except Exception: 60 | pass 61 | 62 | def setup(bot): 63 | bot.add_cog(ChannelCreate(bot)) 64 | bot.logging.info("$GREENLoaded event $CYANChannelCreate") 65 | 66 | 67 | -------------------------------------------------------------------------------- /events/Guild/on_guild_role_create.py: -------------------------------------------------------------------------------- 1 | # When adding new events or enhancing them ALWAYS import datetime for time functions. This applys to everything in /events (Basically) 2 | import discord 3 | from discord.ext import commands 4 | import datetime 5 | 6 | class RoleCreate(commands.Cog): 7 | def __init__(self, bot): 8 | self.bot = bot 9 | 10 | @commands.Cog.listener() 11 | async def on_guild_role_create(self, role): 12 | logch = self.bot.db.execute("SELECT logging_action FROM guild_settings WHERE id = ?") 13 | if logch: 14 | embed = discord.Embed(color=discord.Color.green(), timestamp=datetime.datetime.now( 15 | datetime.timezone.utc), description=f'**A new role was created**\n{role.mention}') 16 | embed.set_author(name=role.guild.name, 17 | icon_url=str(role.guild.icon_url)) 18 | embed.set_footer(text=f"Role ID: {role.id}") 19 | try: 20 | await logch.send(embed=embed) 21 | except Exception: 22 | pass 23 | 24 | def setup(bot): 25 | bot.add_cog(RoleCreate(bot)) 26 | bot.logging.info("Loaded event RoleCreate") -------------------------------------------------------------------------------- /events/Guild/on_guild_role_delete.py: -------------------------------------------------------------------------------- 1 | import discord 2 | import discord.ext 3 | from discord.ext import commands 4 | import datetime 5 | 6 | class RoleDelete(commands.Cog): 7 | def __init__(self, bot): 8 | self.bot = bot 9 | 10 | @commands.Cog.listener() 11 | async def on_guild_role_delete(self, role): 12 | logch = self.bot.db.execute("SELECT logging_action FROM guild_settings WHERE id = ?") 13 | if logch: 14 | embed = discord.Embed(color=role.color, timestamp=datetime.datetime.now( 15 | datetime.timezone.utc), description=f'**The role** `{role.name}` **was deleted**') 16 | embed.set_author(name=role.guild.name, 17 | icon_url=str(role.guild.icon_url)) 18 | embed.set_footer(text=f"Role ID: {role.id}") 19 | try: 20 | await logch.send(embed=embed) 21 | except Exception: 22 | pass 23 | 24 | 25 | def setup(bot): 26 | bot.add_cog(RoleDelete(bot)) 27 | bot.logging.info("Loaded event RoleDelete") -------------------------------------------------------------------------------- /events/Guild/on_guild_voice_channel_create.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | 24 | import discord 25 | from discord.ext import commands 26 | 27 | class GuildVoice(commands.Cog): 28 | def __init__(self, bot): 29 | self.bot = bot 30 | @commands.Cog.listener() 31 | async def on_guild_voice_channel_create(self, channel): 32 | actionlogch = self.bot.db.execute(f"SELECT logging_action FROM guild_settings WHERE id = ?") 33 | 34 | if actionlogch: 35 | createdby = None 36 | if channel.guild.me.guild_permissions.view_audit_log: 37 | async for e in channel.guild.audit_logs(action=discord.AuditLogAction.voice_channel_create, limit=5): 38 | if e.target.id == channel.id: 39 | createdby = e.user 40 | break 41 | 42 | 43 | embed = discord.Embed(color=discord.Color.green 44 | ), timestamp=voice_channel.created_at, description=f"**New voice channel created #{voice_channel.name}" 45 | 46 | if createdby: 47 | embed.add_field( 48 | name='Created by', value=f'{createdby} ({createdby.id})', inline=False 49 | ) 50 | embed.set_footer( 51 | text=f"Channel ID: {voice_channel.id} | Guild ID: {voice_channel.guild.id}" 52 | ) 53 | try: 54 | await actionlogch.send(embed=embed) 55 | except Exception: 56 | pass 57 | 58 | def setup(bot): 59 | bot.add_cog(GuildVoice(bot)) 60 | bot.logging.info("Loaded event GuildVoice") -------------------------------------------------------------------------------- /events/Join/on_member_join.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from discord.utils import get 4 | import datetime 5 | from discord import Member 6 | 7 | class Joinlog(commands.Cog): 8 | def __init__(self, bot): 9 | self.bot = bot 10 | 11 | @commands.Cog.listener() 12 | async def on_member_join(self, member): 13 | 14 | usedinvite = Noneg 15 | logch = self.bot.db.execute("SELECT logging_join FROM guild_settings WHERE id = ?") 16 | channel = discord.utils.get(guild.text_channels, name="logs") 17 | 18 | vars = { 19 | '{user.mention}': member.mention, 20 | '{user}': str(member), 21 | '{user.name}': member.name, 22 | } 23 | 24 | if logch: 25 | embed = discord.Embed(title="Member Joined", url="https://tenor.com/view/penguin-hello-hi-hey-there-cutie-gif-3950966") 26 | 27 | embed.set_author(name=f"{member}", icon_url=str( 28 | member.avatar_url_as(static_format='png', size=2048)) 29 | 30 | embed.add_field(name='Account Created', value=datetime.datetime.utcnow() - member.created_at), + 'ago', inline=False) 31 | if used invite: 32 | embed.add_field(name="Invite used:", value=used_invite, inline=False) 33 | 34 | embed.add_footer(name="Member Count:", value=f"{guild.members}") 35 | 36 | try: 37 | await logch.send(embed) 38 | except Exception: 39 | pass 40 | 41 | 42 | def setup(bot): 43 | bot.add_cog(Greetmsg(bot)) 44 | bot.logging.info("Event Loaded Joinlog!") -------------------------------------------------------------------------------- /events/User/on_member_ban.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/events/User/on_member_ban.py -------------------------------------------------------------------------------- /events/User/on_member_remove.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | 24 | 25 | import discord 26 | from discord.ext import commands 27 | import datetime 28 | import humanfriendly 29 | 30 | class MemberRemove(commands.Cog): 31 | def __init__(self, bot): 32 | self.bot = bot 33 | 34 | @commands.Cog.listener() 35 | # For kick, ban it will be more specific in the log this is just a global event for kick ban etc 36 | async def on_member_remove(self, member): 37 | query = f"""SELECT logging FROM guild_settings WHERE id = {self.bot} """ 38 | leavech = self.bot.db.execute(query) 39 | if leavech: 40 | moderator = None 41 | action = None 42 | reason = None 43 | 44 | if member.guild.me.guild_permissions.view_audit_log: 45 | async for e in member.guild.audit_logs(limit=5): 46 | if e.action in [discord.AuditLogAction.kick, discord.AuditLogAction.ban] and e.target.id == member.id: 47 | moderator = e.user 48 | if moderator == member.guild.me: 49 | moderator = None 50 | 51 | break 52 | 53 | if e.action == discord.AuditLogAction.kick: 54 | action = 'kick' 55 | reason = e.reason 56 | break 57 | 58 | 59 | if e.action == discord.AuditLogAction.ban: 60 | action = 'ban' 61 | reason = e.reason 62 | break 63 | 64 | embed = discord.Embed(title="Member Left", url="https://tenor.com/view/bear-hug-wave-bye-gif-12388210") 65 | 66 | 67 | embed.set_author(name=f'{member}', icon_url=str( 68 | member.avatar_url_as(static_format='png', size=2048))) 69 | 70 | delta = humanfriendly.format_timespan( 71 | datetime.datetime.utcnow() - member.joined_at, 72 | max_units=2 73 | ) 74 | 75 | embed.add_field(name="Stayed for", value=delta, inline=False) 76 | 77 | if member.nick: 78 | embed.add_field(name="Nickname", value=member.nick) 79 | roles = [role.mention for role in member.roles if role != 80 | member.guild.default_role] 81 | 82 | if roles: 83 | embed.add_field( 84 | name='Roles', value=', '.join(roles), inline=False) 85 | 86 | try: 87 | await leavech.send(embed=embed) 88 | except Exception: 89 | pass 90 | 91 | 92 | def setup(bot): 93 | bot.add_cog(MemberRemove(bot)) 94 | bot.logging.info(f'Loaded event MemberRemove') 95 | 96 | -------------------------------------------------------------------------------- /events/User/on_member_unban.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/events/User/on_member_unban.py -------------------------------------------------------------------------------- /events/command_error.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | from discord import Guild 26 | 27 | import datetime 28 | import logging 29 | from logging import log 30 | 31 | import aiohttp 32 | import random 33 | import os 34 | 35 | 36 | class Commanderror(commands.Cog): 37 | 38 | def __init__(self, bot): 39 | self.bot = bot 40 | 41 | 42 | @commands.Cog.listener() 43 | async def on_command_error(self, ctx, error): 44 | 45 | """checks the discord errors vs the python exceptions/errors and returns true if there is none""" 46 | if hasattr(ctx.command, "on_error"): 47 | return 48 | 49 | if isinstance(error, commands.CommandNotFound): 50 | return await ctx.send('Command not found, there may be a typo in the command.') 51 | 52 | if isinstance(error, commands.NoPrivateMessage): 53 | return await ctx.send("You cannot use commands in a private message please go to a server to run commands.") 54 | 55 | if isinstance(error, commands.MissingPermissions): 56 | return await ctx.send("You dont have the permissions to perform this command") 57 | 58 | if isinstance(error, commands.BotMissingPermissions): 59 | return await ctx.send("You dont have the permissions to perform this command") 60 | 61 | if isinstance(error, commands.NoPrivateMessage): 62 | return await ctx.send("You can't run this command here!") 63 | 64 | if isinstance(error, commands.CommandNotFound): 65 | return await ctx.send(f"Command not found! :( Please try again") 66 | def setup(bot): 67 | 68 | bot.add_cog(Commanderror(bot)) 69 | bot.logging.info("Loaded event CommandError") 70 | 71 | -------------------------------------------------------------------------------- /events/guild_join.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | from discord import Guild, User 26 | from discord.utils import get 27 | 28 | import asyncpg 29 | import logging 30 | 31 | class GuildJoin(commands.Cog): 32 | def __init__(self, bot): 33 | self.bot = bot 34 | 35 | 36 | @commands.Cog.listener() 37 | async def on_guild_join(self, guild): 38 | 39 | permissions = discord.Permissions(send_messages=False, speak=False, read_messages=True) 40 | await self.bot.create_role( 41 | name="Muted", 42 | reason="Utility bot's Default Muted Role on join.", 43 | permissions=permissions, 44 | color=discord.Color.orange()) 45 | 46 | await self.channel.send("**Thank you for adding me!** :white_check_mark:\n - My prefix is u! but you can change it using u!prefix [prefix]\n - You can see a list of commands by typing u!help\n - If you need help, feel free to join our support server https://utilitybot.co/suppor") 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | def setup(bot): 56 | bot.add_cog(GuildJoin(bot)) 57 | bot.logging.info("Loaded event GuildJoin") 58 | -------------------------------------------------------------------------------- /events/ready.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | 5 | class Ready(commands.Cog): 6 | def __init__(self, ): 7 | self.bot = bot 8 | 9 | @commands.Cog.listener() 10 | async def on_ready(self, guild, channel): 11 | try: 12 | self.bot.load_extension("events.ready") 13 | except Exception: 14 | pass 15 | 16 | self.bot.logging(f"Bot:{self.bot.user}") 17 | self.bot.logging.info(f"D: {self.bot.user.id}") 18 | self.bot.logging.info(f"Guilds: {len(self.bot.guilds)}") 19 | self.bot.logging.info(f"Users: {len(self.bot.users)}") 20 | 21 | 22 | def setup(bot): 23 | bot.add_cog(Ready(bot)) 24 | bot.logging.info(f"Loaded event Ready!") 25 | -------------------------------------------------------------------------------- /logs/.keepfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/logs/.keepfile -------------------------------------------------------------------------------- /plugins/database/database.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import asyncpg 3 | import json 4 | import discord 5 | 6 | from discord import User 7 | from discord import Guild 8 | from discord import Message 9 | 10 | 11 | class Database(object): 12 | def __init__(self, bot, pool, loop=None, timeout: float = 60.0): 13 | self.bot = bot 14 | self.pool = pool 15 | self._loop = loop or asyncio 16 | self.timeout = timeout 17 | self._rate_limit = asyncio.Semaphore(value=self.pool._maxsize, loop=self._loop) 18 | 19 | @classmethod 20 | async def create_pool(cls, bot, uri=None, *, min_connections=None, max_connections=None, 21 | timeout=60.0, loop=None, **kwargs): 22 | pool = await asyncpg.create_pool(uri, min_size=min_connections, max_size=max_connections, **kwargs) 23 | self = cls(bot=bot, pool=pool, loop=loop, timeout=timeout) 24 | return self 25 | 26 | async def fetchrow(self, query, *args): 27 | async with self._rate_limit: 28 | async with self.pool.acquire() as con: 29 | return await con.fetchrow(query, *args) 30 | 31 | async def fetch(self, query, *args): 32 | async with self._rate_limit: 33 | async with self.pool.acquire() as con: 34 | return await con.fetch(query, *args, timeout=self.timeout) 35 | 36 | """"Execute querys""" 37 | async def execute(self, query, *args): 38 | async with self._rate_limit: 39 | async with self.pool.acquire() as con: 40 | return await con.execute(query *args) 41 | -------------------------------------------------------------------------------- /plugins/database/sql/schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE guilds 2 | ( 3 | guild_id int NOT NULL, 4 | guild_name VARCHAR(25) NOT NULL, 5 | premium BOOLEAN, 6 | PRIMARY KEY (guild_id) 7 | 8 | ) 9 | 10 | CREATE TABLE guild_settings 11 | ( 12 | /* Default muted role is generated everytime the bot joins the guild although this can be updated*/ 13 | guild_id INT(20) NOT NULL DEFAULT 0, 14 | muted_role INT(20) DEFAULT 'Muted', 15 | guild_prefix VARCHAR(15) DEFAULT 'u!', 16 | /* These are different types of logging you can have moderation logs e.g: a ban log or just action logs..*/ 17 | logging_moderation BIGINT DEFAULT NULL, 18 | logging_action BIGINT DEFAULT NULL, 19 | /* You can toggle join logs but action logs already toggles it on but if you want less logs you can toggle logging_leave or logging_join.*/ 20 | logging_join BIGINT DEFAULT NULL, 21 | logging_leave BIGINT DEFAULT NULL, 22 | logging_leave BIGINT DEFAULT NULL, 23 | PRIMARY KEY (muted_role, guild_prefix, logging_moderation, logging_action, logging_leave, logging_join, logging_leave), 24 | guild_id int FOREIGN KEY REFERENCES guilds(guild_id) 25 | 26 | ); 27 | 28 | CREATE TABLE premium 29 | ( 30 | guild_id int NOT NULL, 31 | premium BOOLEAN, 32 | FOREIGN KEY (premium) REFERENCES guilds(premium), 33 | FOREIGN KEY (guild_id) REFERENCES guilds(guild_id) 34 | ); -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | discord.py==1.5.1 2 | asyncpg==0.21.0 3 | async-timeout==3.0.1 4 | aiofiles==0.5.0 5 | python-dotenv==0.14.0 6 | humanfriendly==8.2 7 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | .pytest_cache/ 2 | __pycache__/ -------------------------------------------------------------------------------- /tests/requirements.txt: -------------------------------------------------------------------------------- 1 | discord.py==1.5.1 2 | pytest==6.1.2 3 | -------------------------------------------------------------------------------- /tests/test_commands/test_avatar.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import unittest.mock 3 | 4 | from .command import avatar 5 | 6 | class TestAvatar(unittest.TestCase): 7 | async def setUp(self): 8 | self.app = avatar.app.setup() 9 | self.app.testing = True 10 | 11 | async def testavatar(self): 12 | logmsg = "Testing avatae" 13 | self.assertTrue(self.app.avatar(), logmsg) 14 | 15 | if __name__ == "__main__": 16 | unittest.main() -------------------------------------------------------------------------------- /tests/test_commands/test_bot_info.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import unittest.mock 3 | from .command import botinfo 4 | 5 | class TestBotInfo(unittest.TestCase): 6 | 7 | async def setUp(self): 8 | self.app = botinfo.app.setup() 9 | self.app.testing = True 10 | 11 | async def test_bot_info(self): 12 | logmsg = "Testing bot info." 13 | self.assertEqual(self.app.botinfo(), logmsg) 14 | 15 | 16 | if __name__ == "__main__": 17 | unittest.main() 18 | -------------------------------------------------------------------------------- /tests/test_commands/test_bot_status.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/tests/test_commands/test_bot_status.py -------------------------------------------------------------------------------- /tests/test_commands/test_github.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import unittest.mock 3 | import discord 4 | from discord.ext import commands 5 | import .command 6 | from .command import github 7 | 8 | class TestGithub(unittest.TestCase): 9 | 10 | async def setUp(self): 11 | self.app = github.app.setup() 12 | self.app.testing = True 13 | 14 | async def test_github(self): 15 | logmsg = "Testing github" 16 | self.assertEqual(self.app.github(), logmsg) 17 | 18 | if __name__ == "__main__": 19 | unittest.main() -------------------------------------------------------------------------------- /tests/test_commands/test_help.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import unittest.mock -------------------------------------------------------------------------------- /tests/test_commands/test_invite.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import unittest.mock 3 | import .command 4 | from .command import github 5 | 6 | class Testinvite(unittest.TestCase): 7 | 8 | async def setUp(self): 9 | self.app = invite.app.setup() 10 | self.app.testing = True 11 | 12 | async def testinvite(self): 13 | logmsg = "Testing invite." 14 | self.assertTrue(self.app.invite(), logmsg) 15 | 16 | if __name__ == "__main__": 17 | unittest.main()- 18 | -------------------------------------------------------------------------------- /tests/test_commands/test_twitter.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import unittest.mock 3 | import discord 4 | from discord.ext import commands 5 | 6 | #import .command 7 | #from .command import twitter 8 | 9 | class TestTwitter(unittest.TestCase): 10 | 11 | async def setUp(self): 12 | self.app = twitter.app.set() 13 | self.app.testing = True 14 | 15 | 16 | async def test_twitter(self): 17 | logmsg = "Testing twitter" 18 | self.assertEqual(self.app.twitter(), logmsg) 19 | 20 | if __name__ == "__main__": 21 | unittest.main() -------------------------------------------------------------------------------- /utilitybot.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | import datetime 26 | import aiohttp 27 | import async_timeout 28 | import logging 29 | import asyncio 30 | import sys 31 | 32 | class Utilitybot(commands.AutoShardedBot): 33 | 34 | 35 | def __init__(self, *args, **kwargs): 36 | super().__init__(*args, **kwargs) 37 | 38 | self.launchtime = datetime.datetime.now(datetime.timezone.utc) 39 | self.started = False 40 | 41 | logging.basicConfig(filename='./logs/utilitybot.log', level=logging.INFO) 42 | self.logging = logging.getLogger('Bot') 43 | 44 | stdout = logging.StreamHandler(sys.stdout) 45 | self.logging.addHandler(stdout) 46 | gateway = logging.getLogger('discord.gateway') 47 | gateway.addHandler(stdout) 48 | 49 | self.premium_guilds ={} 50 | 51 | 52 | -------------------------------------------------------------------------------- /utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .permissions import has_permission 2 | -------------------------------------------------------------------------------- /utils/context.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | import discord 23 | from discord.ext import commands 24 | 25 | 26 | 27 | class Context(commands.Context): 28 | def __init__(self, **kwargs): 29 | super().__init__(**kwargs) 30 | self.colors = [ 31 | discord.Color.blue(), 32 | discord.Color.blurple(), 33 | discord.Color.dark_blue(), 34 | discord.Color.dark_gold(), 35 | discord.Color.dark_green(), 36 | discord.Color.dark_magenta(), 37 | discord.Color.dark_orange(), 38 | discord.Color.dark_purple(), 39 | discord.Color.dark_red(), 40 | discord.Color.dark_teal(), 41 | discord.Color.gold(), 42 | discord.Color.green(), 43 | discord.Color.magenta(), 44 | discord.Color.orange(), 45 | discord.Color.purple(), 46 | discord.Color.red(), 47 | discord.Color.teal() 48 | ] 49 | 50 | async def modlog(self, embed: discord.Embed): 51 | pass 52 | 53 | async actionlog(self, embed: discord.Embed) -------------------------------------------------------------------------------- /utils/errors.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import os 24 | 25 | class OptionConfigErorr(Exception): 26 | def __init__(self, *args): 27 | self.config = args[0] 28 | 29 | def __str__(self): 30 | return f'{self.config} has an invalid config' 31 | 32 | # Used when a module/cog is not found in local directores 33 | class InvalidModuleErorr(Exception): 34 | def __init__(self, *args): 35 | self.module = args[0] 36 | 37 | def __str__(self): 38 | return f'{self.module} is invalid. and or does not exist' -------------------------------------------------------------------------------- /utils/permissions.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord.ext import commands 25 | from discord.utils import get 26 | 27 | """Simple function to check whether the bot has permissions to perform events or actions.""" 28 | def has_permission(permission : str, **kwargs): 29 | def predicate(ctx): 30 | if ctx.bot.has_permission(ctx.author, permission): 31 | return True 32 | else: 33 | return commands.has_permissions(**kwargs) 34 | 35 | return commands.check(predicate) -------------------------------------------------------------------------------- /utils/prefix.py: -------------------------------------------------------------------------------- 1 | """MIT License 2 | 3 | Copyright (c) 2020 utilitybot.co 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE.""" 22 | 23 | import discord 24 | from discord import Guild 25 | from discord.ext import commands 26 | 27 | 28 | # Make sure its always asynchronous (since dpy is async duh) 29 | async def get_prefix(ctx, bot, message): 30 | prefix = await (await bot.db.execute(f"SELECT guild_prefix FROM guild_settings WHERE id = {ctx.guild.id}", message.guild.id)).fetchone() 31 | if bot.dev: 32 | return commands.when_mentioned_or(prefix, 'u!')(bot, message) 33 | return commands.when_mentioned_or(prefix, 'u!')(bot, message) -------------------------------------------------------------------------------- /utils/status.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discordutilitybot/utilitybot/8f981d198c46438a1a285838fcb8d21e425d06e3/utils/status.py -------------------------------------------------------------------------------- /utils/unload_cog.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | 5 | def unload_cog(cog_name): 6 | bot.unload_extension(cog_name) --------------------------------------------------------------------------------