├── .github ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md └── FUNDING.yml ├── .gitignore ├── LICENSE.md ├── Procfile ├── README.md ├── cogs ├── ajian.py ├── anime.py ├── bot.py ├── brainfuck.py ├── catify.py ├── cheatsheet.py ├── chess.py ├── cog_template ├── error_handling.py ├── events.py ├── fonts.json ├── fun.py ├── githubinfo.py ├── latex.py ├── libs │ ├── __pycache__ │ │ ├── attacks.cpython-38.pyc │ │ ├── board.cpython-38.pyc │ │ ├── boards.cpython-38.pyc │ │ ├── brainfuck.cpython-38.pyc │ │ ├── formatter.cpython-38.pyc │ │ ├── math.cpython-38.pyc │ │ ├── move.cpython-38.pyc │ │ ├── moves.cpython-38.pyc │ │ ├── repetitions.cpython-38.pyc │ │ ├── state.cpython-38.pyc │ │ └── svg.cpython-38.pyc │ ├── attacks.py │ ├── board.py │ ├── boards.py │ ├── brainfuck.py │ ├── formatter.py │ ├── math.py │ ├── move.py │ ├── moves.py │ ├── repetitions.py │ ├── state.py │ └── svg.py ├── math.py ├── minecraft.py ├── mod.py ├── modmail.py ├── money.py ├── news.py ├── owner.py ├── rules.py ├── stackoverflow.py └── user.py ├── data ├── beg_results.json ├── money.json ├── names.json └── names.txt ├── docs └── images │ └── icon.png ├── libs ├── config.py ├── data.py ├── help.py └── httpsession.py ├── main.py ├── requirements.txt ├── run.bat └── runtime.txt /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at billydevbusiness@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thank you for wanting to contribute to the RoboBilly project! Before you start, please take a quick look at the guidelines we set for contributors, to ensure a smooth collaboration! 4 | 5 | 1. [Issues](#issues) 6 | 2. [Pull Requests](#pull-requests) 7 | 3. [Coding Styles](#coding-styles) 8 | 9 | ## Issues 10 | 11 | If you want to suggest _enhancements_ or report _bugs_, please open an issue! We try to give each issue to individual attention it deserves, but still - be patient until we get to yours! 12 | 13 | We created a few issue templates (for example for features requests or bug reports), which you are intended to use. If the type of issue you want to create doesn't fit a template, feel free to create an issue from scratch, but still include sufficient information for us to understand it. 14 | 15 | At this time issues will persist forever - in the future we might close issues after a certain amount of inactivity. 16 | 17 | ## Pull Requests 18 | 19 | If you worked on a new feature or fixed an open issue, please create a **pull request** so we can merge your work into ours. 20 | 21 | If it is not immediately apparent which feature you added or which issue you addressed, please include an adequate description in your pull request. If you still need to work on the pull request before it can be merged please open it as a _draft_. 22 | 23 | Note that if you do successfully terminate an issue, include `Closes #issue-id` in your commit message so the issue is automatically referenced. 24 | 25 | Also do note that we try to enforce consistent coding styles among the repository, which we explain in the section [coding styles](#coding-styles). We review every pull request, and we would appreciate it if you would accept the changes that we propose during our reviews. 26 | 27 | ## Coding Styles 28 | 29 | In general we follow the standard [PEP 8](https://pep8.org/#naming-conventions). If you want insights to individual variable naming conventions, please refer to the existing code in the repository. 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [billydevyt, eddyedyt] 4 | patreon: billycookieman 5 | custom: ['https://billyeatcookies.github.io'] 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | venv/ 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 BillyDev 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 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: python main.py -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |
3 | RoboBilly 4 |

5 | 6 |

7 | Discord Bot with amazing features! (scroll down) 8 |

9 | 10 |
11 | 12 |

13 | Discord 14 | 15 | 16 | Release 17 | Heroku 18 | License 19 |

20 | 21 |

22 | Building & running • 23 | Features • 24 | License • 25 | Code of Conduct • 26 | Contributing 27 |

28 | 29 | ## Building & running 30 | The bot will work with **Python 3.8+**, make sure to install required packages using the following command 31 | ``` 32 | pip install -r requirements.txt 33 | ``` 34 | you can run the bot using the following command or just using the `run.bat` 35 | ``` 36 | python main.py 37 | ``` 38 | 39 | ## Configuration 40 | 41 | 1. `/lib/config.py` is where all of the bot configuration will be placed. You can modify current placeholder values as desired. 42 | 43 | 2. Make sure to run the `setup` command in the discord server.(for running this command, the user will need administrator permissions) 44 | 45 | ## Features 46 |

47 | Release 48 |

49 | 50 | ### ⛏ Minecraft 51 | #### Minecraft Module comes with most of the commands needed to check info of minecraft servers and the players online! 52 | - coord  53 | - **mc** 54 | - server info 55 | - players online 56 | - player info 57 | ### 🔰🔰 Stackoverflow 58 | #### Got a quick question? do a stackoverflow right from discord! 😉 59 | - **stackoverflow** 60 | ### **>.<** Weebs 61 | #### Get amazing news and info about anime, thanks to @DriftAsimov 62 | - **anime** 63 | ### 🐈Catify 64 | #### Catify me! ᓇᘏᗢ 65 | - catify 66 | ### 🐍 CheatSheet 67 | #### python cheatsheets from https://cheat.sh/python/ 68 | - cheat 69 | ### ♟ Chess 70 | #### Have a chess game right from discord! thanks to @billyeatcookies 71 | - chess 72 | - for more info on available commands, check [discord chess!](https://github.com/billyeatcookies/discord-chess) 73 | ### 🐙 GithubInfo 74 | #### Got a repository or github user to search up? well you can, right from discord! 75 | - github 76 | ### 📝 Latex 77 | #### Render your latex code right from discord! share it quickly! 78 | - latex 79 | ### 🎁 Fun! 80 | #### Buncha fun commands to keep the server entertained! 81 | - 8ball 82 | - clap 83 | - cursive 84 | - emojify 85 | - emojify2 86 | - epicgamerrate 87 | - greentext 88 | - hack  89 | - imagine 90 | - kill 91 | - lemmegoogle 92 | - lenny 93 | - owo 94 | - simprate 95 | - snipe 96 | - uselessweb  97 | - yasahiroify 98 | ### 👤 User 99 | #### Rest of the fun commands, with a lot of utilities! 100 | - ascii 101 | - make ascii arts from discord! 102 | - bing  103 | - codeblocks  104 | - dontasktoask  105 | - git 106 | - The holy git command set! *git push billy outerspace* 107 | - goodmorning! 108 | - goodnight! 109 | - google  110 | - let me google that for you! 111 | - hi  112 | - hi! 113 | - info 114 | - user info 115 | - pastemyst  116 | - say 117 | - repeat me!  118 | - weather 119 | - billy, hows the weather today! 120 | ### 💪🏻 Moderation 121 | #### Moderation shall be done! 122 | - activity  123 | - ban  124 | - kick  125 | - leaderboard  126 | - mute  127 | - myrep  128 | - purge  129 | - rep  130 | - reset  131 | - slowmode  132 | - thanks  133 | - unmute 134 | ### 📧 ModMail 135 | #### Modmail service to contact mods easily through bot's dms! 136 | - reply  137 | - setup 138 | ### 📜 Rules 139 | #### Show individual or whole rules as part of moderation, see `rules.json` to set it up! 140 | - rule  141 | - rules 142 | ## ⚙ Misc 143 | - brainfuck 144 | - billy's brainfuck interpreter! go crazy! 145 | - help 146 | - the holy help command 147 | ### 🤖 Bot 148 | - source 149 | - bot's repository, means rn where you are, here! 150 | ### 🔧 Jishaku 151 | - jishaku 152 | - management done pog! 153 | ### 🛠Owner 154 | - close_http_session 155 | - close http session used by some of the commands, recommended to use it before killing the bot's process 156 | 157 | ## Contributing 158 | 159 | contributions are accepted. Check out the [Contributing](./.github/CONTRIBUTING.md) for more info. 160 | RoboBilly is [MIT-licensed](./LICENSE.md). 161 | 162 | ## Visit 163 | 164 | Visit us here: https://basement-team.github.io 165 | -------------------------------------------------------------------------------- /cogs/ajian.py: -------------------------------------------------------------------------------- 1 | from discord.ext import commands 2 | import discord 3 | import random 4 | 5 | 6 | def find_in_message(content, target): 7 | info = "" 8 | for x in content: 9 | if x[0:len(target)] == target: 10 | info = x[len(target) + 1:] 11 | return info 12 | 13 | 14 | def colour(_random=False): 15 | if _random: 16 | return random.randint(0x100000, 0xFFFFFF) 17 | else: 18 | return 55807 19 | 20 | 21 | class Ajian(commands.Cog): 22 | """ 23 | Commands related to the bot. 24 | """ 25 | 26 | def __init__(self, bot): 27 | self.bot = bot 28 | 29 | @commands.group() 30 | async def ajian(self, ctx): 31 | """ 32 | >.< 33 | """ 34 | if ctx.invoked_subcommand is None: 35 | await ctx.send("no u") 36 | 37 | @ajian.command() 38 | async def bonk(self, ctx): 39 | if random.choice([True, False]): 40 | await ctx.send(f"*bonks ajian {('like hell wtf', '**gently**')[bool(random.randint(0, 10) == 5)]}*") 41 | else: 42 | await ctx.send("You got bonked by ajian, get got!") 43 | 44 | @ajian.command() 45 | async def hug(self, ctx): 46 | await ctx.send("*ajian hugs back* 🤍") 47 | 48 | @ajian.command() 49 | async def owo(self, ctx): 50 | await ctx.send("UwU") 51 | 52 | @ajian.command() 53 | async def embed(self, ctx, *args): 54 | await ctx.message.delete() 55 | args = list(args) 56 | title = find_in_message(args, "title") 57 | description = find_in_message(args, "description") 58 | try: 59 | _embed_colour = int(find_in_message(args, "colour")) 60 | except ValueError: 61 | _embed_colour = colour() 62 | if ctx.message.attachments: 63 | image_url = ctx.message.attachments[0].url 64 | else: 65 | image_url = find_in_message(args, "image_url") 66 | 67 | final = discord.Embed( 68 | title=title, 69 | description=description, 70 | colour=_embed_colour 71 | ) 72 | final.set_image(url=image_url) 73 | final.set_footer(text=f"Submitted by {ctx.message.author}") 74 | 75 | await ctx.send(embed=final) 76 | 77 | 78 | def setup(bot): 79 | bot.add_cog(Ajian(bot)) 80 | -------------------------------------------------------------------------------- /cogs/anime.py: -------------------------------------------------------------------------------- 1 | """ 2 | Anime module 3 | """ 4 | 5 | import discord 6 | import asyncio 7 | 8 | from discord.ext import commands 9 | from mal import * 10 | 11 | class AnimeList(commands.Cog): 12 | """ 13 | Anime module 14 | """ 15 | def __init__(self, bot): 16 | self.bot = bot 17 | 18 | @commands.command() 19 | async def anime(self, ctx, *, arg): 20 | try: 21 | await ctx.trigger_typing() 22 | 23 | search = AnimeSearch(arg) 24 | result = search.results[0] 25 | id = search.results[0].mal_id 26 | anime = Anime(str(id)) 27 | 28 | em = discord.Embed(title = f"{result.title} ({anime.title_japanese})", url = result.url, description = f"{result.synopsis}", color = 14834431) 29 | em.add_field(name = "▬▬▬▬▬▬▬", value = "__**Information**__", inline = False) 30 | em.add_field(name = ":scroll: | Ratings", value = result.score) 31 | em.add_field(name = ":military_medal: | Ranking", value = anime.rank) 32 | em.add_field(name = ":film_frames: | Episodes", value = result.episodes) 33 | em.add_field(name = ":flags: | Aired", value = anime.aired) 34 | em.add_field(name = ":ribbon: | Status", value = anime.status, inline = True) 35 | em.add_field(name = ":clipboard: | Rating", value = anime.rating, inline = True) 36 | em.add_field(name = ":clock1: | Broadcast", value = anime.broadcast) 37 | em.add_field(name= ":eyeglasses: | Source", value = anime.source, inline = True) 38 | em.add_field(name = ":classical_building: | Studios", value = anime.studios[0], inline = True) 39 | em.set_thumbnail(url = result.image_url) 40 | em.set_footer(text = f"{anime.premiered} • {result.type}") 41 | await ctx.send(embed = em) 42 | except Exception as e: 43 | embed = discord.Embed(description = e, color = discord.Color.dark_theme()) 44 | await ctx.send(embed = embed) 45 | 46 | def setup(bot): 47 | bot.add_cog(AnimeList(bot)) 48 | -------------------------------------------------------------------------------- /cogs/bot.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bot Module 3 | """ 4 | 5 | import discord 6 | import asyncio 7 | from discord.ext import commands 8 | 9 | 10 | class Bot(commands.Cog): 11 | """ 12 | Commands related to the bot. 13 | """ 14 | def __init__(self, bot): 15 | self.bot = bot 16 | 17 | @commands.command(aliases=["pong", "latency"]) 18 | async def ping(self, ctx): 19 | async with ctx.channel.typing(): 20 | ping = str(self.bot.latency * 1000) 21 | embed = discord.Embed(title="Pong!", description=f'Latency: {ping} ms', color = discord.Color.dark_theme()) 22 | await ctx.send(embed=embed) 23 | 24 | @commands.command() 25 | async def prefix(self, ctx): 26 | async with ctx.channel.typing(): 27 | prefix = str(ctx.prefix) 28 | embed = discord.Embed(title="Prefix", description=f"Bot's prefix is: `{prefix}`", color = discord.Color.dark_theme()) 29 | await ctx.send(embed=embed) 30 | 31 | @commands.command(aliases=["src", "sourcecode", "botsrc"]) 32 | async def source(self, ctx): 33 | async with ctx.channel.typing(): 34 | prefix = str(ctx.prefix) 35 | embed = discord.Embed(title="/src", description="[source code on github](https://github.com/basement-team/RoboBilly)", color = discord.Color.dark_theme()) 36 | await ctx.send(embed=embed) 37 | 38 | 39 | def setup(bot): 40 | bot.add_cog(Bot(bot)) 41 | -------------------------------------------------------------------------------- /cogs/brainfuck.py: -------------------------------------------------------------------------------- 1 | """ 2 | Brainfuck Module 3 | """ 4 | 5 | import discord 6 | import asyncio 7 | from discord.ext import commands 8 | 9 | from cogs.libs import brainfuck 10 | from libs import config 11 | 12 | 13 | class BrainFuck(commands.Cog): 14 | """ 15 | Commands related to the bot. 16 | """ 17 | def __init__(self, bot): 18 | self.bot = bot 19 | 20 | @commands.command(name='bf', aliases=['brainfuck', 'BrainFuck']) 21 | async def bf(self, ctx, *, source = None): 22 | """Brainfuck Interpreter""" 23 | await ctx.trigger_typing() 24 | 25 | if source is None: 26 | await ctx.send(f"> You need provide some input. see `{config.prefix}help brainfuck`") 27 | return 28 | 29 | result = brainfuck.evaluate(source) 30 | embed = discord.Embed(title="🧠 Billy's BrainFuck Interpreter", color = discord.Color.dark_theme()) 31 | 32 | if result is not None or result != "": 33 | embed.add_field(name='Output', value=f"> {result}") 34 | else: 35 | embed.add_field(name='Runtime Error', value="> Recheck what you typed.") 36 | 37 | embed.set_footer(text="Copyright (c) 2021 Basement Team") 38 | await ctx.send(embed=embed) 39 | 40 | def setup(bot): 41 | bot.add_cog(BrainFuck(bot)) 42 | -------------------------------------------------------------------------------- /cogs/catify.py: -------------------------------------------------------------------------------- 1 | import random 2 | import discord 3 | from discord import AllowedMentions, Embed, Forbidden 4 | from discord.ext import commands 5 | 6 | cats = ["ᓚᘏᗢ", "ᘡᘏᗢ", "🐈", "ᓕᘏᗢ", "ᓇᘏᗢ", "ᓂᘏᗢ", "ᘣᘏᗢ", "ᕦᘏᗢ", "ᕂᘏᗢ"] 7 | 8 | NEGATIVE_REPLIES = [ 9 | "Noooooo!!", 10 | "Nope.", 11 | "I'm sorry Dave, I'm afraid I can't do that.", 12 | "I don't think so.", 13 | "Not gonna happen.", 14 | "Out of the question.", 15 | "Huh? No.", 16 | "Nah.", 17 | "Naw.", 18 | "Not likely.", 19 | "No way, José.", 20 | "Not in a million years.", 21 | "Fat chance.", 22 | "Certainly not.", 23 | "NEGATORY.", 24 | "Nuh-uh.", 25 | "Not in my house!", 26 | ] 27 | 28 | class Catify(commands.Cog): 29 | """Cog for the catify command.""" 30 | def __init__(self, bot): 31 | self.bot = bot 32 | 33 | 34 | @commands.command(aliases=("ᓚᘏᗢify", "ᓚᘏᗢ")) 35 | @commands.cooldown(1, 5, commands.BucketType.user) 36 | async def catify(self, ctx) -> None: 37 | """ 38 | Convert the provided text into a cat themed sentence by interspercing cats throughout text. 39 | 40 | If no text is given then the users nickname is edited. 41 | """ 42 | display_name = ctx.author.display_name 43 | 44 | if len(display_name) > 26: 45 | embed = Embed( 46 | title=random.choice(NEGATIVE_REPLIES), 47 | description=( 48 | "Your display name is too long to be catified! " 49 | "Please change it to be under 26 characters." 50 | ), 51 | color=discord.Color.red() 52 | ) 53 | await ctx.send(embed=embed) 54 | return 55 | else: 56 | display_name += f" | {random.choice(cats)}" 57 | 58 | await ctx.send(f"Your catified nickname is: `{display_name}`", allowed_mentions=AllowedMentions.none()) 59 | await ctx.author.edit(nick=display_name) 60 | 61 | 62 | def setup(bot) -> None: 63 | bot.add_cog(Catify(bot)) 64 | -------------------------------------------------------------------------------- /cogs/cheatsheet.py: -------------------------------------------------------------------------------- 1 | import random 2 | import re 3 | import typing as t 4 | from urllib.parse import quote_plus 5 | 6 | from discord import Embed 7 | from discord.ext import commands 8 | from discord.ext.commands import BucketType, Context 9 | 10 | from libs.httpsession import http_session 11 | 12 | ERROR_REPLIES = [ 13 | "Please don't do that.", 14 | "You have to stop.", 15 | "Do you mind?", 16 | "In the future, don't do that.", 17 | "That was a mistake.", 18 | "You blew it.", 19 | "You're bad at computers.", 20 | "Are you trying to kill me?", 21 | "Noooooo!!", 22 | "I can't believe you've done this", 23 | ] 24 | 25 | ERROR_MESSAGE = f""" 26 | Unknown cheat sheet. Please try to reformulate your query. 27 | 28 | **Examples**: 29 | ```md 30 | []cht read json 31 | []cht hello world 32 | []cht lambda 33 | ``` 34 | """ 35 | 36 | URL = "https://cheat.sh/python/{search}" 37 | ESCAPE_TT = str.maketrans({"`": "\\`"}) 38 | ANSI_RE = re.compile(r"\x1b\[.*?m") 39 | # We need to pass headers as curl otherwise it would default to aiohttp which would return raw html. 40 | HEADERS = {"User-Agent": "curl/7.68.0"} 41 | 42 | 43 | class CheatSheet(commands.Cog): 44 | """Commands that sends a result of a cht.sh search in code blocks.""" 45 | 46 | def __init__(self, bot): 47 | self.bot = bot 48 | 49 | @staticmethod 50 | def fmt_error_embed() -> Embed: 51 | """ 52 | Format the Error Embed. 53 | 54 | If the cht.sh search returned 404, overwrite it to send a custom error embed. 55 | link -> https://github.com/chubin/cheat.sh/issues/198 56 | """ 57 | embed = Embed( 58 | title=random.choice(ERROR_REPLIES), 59 | description=ERROR_MESSAGE, 60 | colour=Colours.soft_red 61 | ) 62 | return embed 63 | 64 | def result_fmt(self, url: str, body_text: str) -> t.Tuple[bool, t.Union[str, Embed]]: 65 | """Format Result.""" 66 | if body_text.startswith("# 404 NOT FOUND"): 67 | embed = self.fmt_error_embed() 68 | return True, embed 69 | 70 | body_space = min(1986 - len(url), 1000) 71 | 72 | if len(body_text) > body_space: 73 | description = ( 74 | f"**Result from cht.sh**\n" 75 | f"```python\n{body_text[:body_space]}\n" 76 | f"... (truncated - too many lines)```\n" 77 | f"Full results: {url} " 78 | ) 79 | else: 80 | description = ( 81 | f"**Result Of cht.sh**\n" 82 | f"```python\n{body_text}```\n" 83 | f"{url}" 84 | ) 85 | return False, description 86 | 87 | @commands.command( 88 | name="cheat", 89 | aliases=("cht.sh", "cheatsheet", "cheat-sheet", "cht"), 90 | ) 91 | @commands.cooldown(1, 10, BucketType.user) 92 | async def cheat_sheet(self, ctx: Context, *search_terms: str) -> None: 93 | """ 94 | Search cheat.sh. 95 | 96 | Gets a post from https://cheat.sh/python/ by default. 97 | Usage: 98 | --> .cht read json 99 | """ 100 | async with ctx.typing(): 101 | search_string = quote_plus(" ".join(search_terms)) 102 | 103 | async with http_session.get( 104 | URL.format(search=search_string), headers=HEADERS 105 | ) as response: 106 | result = ANSI_RE.sub("", await response.text()).translate(ESCAPE_TT) 107 | 108 | is_embed, description = self.result_fmt( 109 | URL.format(search=search_string), 110 | result 111 | ) 112 | if is_embed: 113 | await ctx.send(embed=description) 114 | else: 115 | await ctx.send(content=description) 116 | 117 | 118 | def setup(bot) -> None: 119 | bot.add_cog(CheatSheet(bot)) 120 | -------------------------------------------------------------------------------- /cogs/chess.py: -------------------------------------------------------------------------------- 1 | from discord.ext import commands 2 | 3 | from libs.data import file 4 | 5 | from cogs.libs.board import init_board 6 | from cogs.libs.board import show_board 7 | from cogs.libs.board import fen 8 | 9 | from cogs.libs.moves import legal_moves 10 | from cogs.libs.moves import legal_move 11 | 12 | from cogs.libs.move import push_san 13 | from cogs.libs.move import undo 14 | 15 | from cogs.libs.state import checkmate 16 | from cogs.libs.state import stalemate 17 | from cogs.libs.state import insufficient_material 18 | from cogs.libs.state import game_over 19 | from cogs.libs.state import draw 20 | 21 | from cogs.libs.repetitions import threefold_repetition 22 | from cogs.libs.repetitions import halfmove_clock 23 | from cogs.libs.repetitions import fifty_moves 24 | from cogs.libs.repetitions import fivefold_repetition 25 | from cogs.libs.repetitions import seventyfive_moves 26 | 27 | from cogs.libs.attacks import check 28 | from cogs.libs.attacks import attacked_by 29 | from cogs.libs.attacks import attackers 30 | from cogs.libs.attacks import attacker 31 | from cogs.libs.attacks import attacks 32 | 33 | 34 | # TODO: aliases for commands. to keep it not too case sensitive. 35 | 36 | class Chess(commands.Cog): 37 | """ 38 | chess game for discord written in python. 39 | """ 40 | 41 | def __init__(self, _bot): 42 | self.bot = _bot 43 | 44 | @commands.group(name="chess", aliases=["Chess", "c"]) 45 | async def chess(self, _ctx): 46 | """ 47 | Main function group. 48 | """ 49 | pass 50 | 51 | @chess.command(name="create", aliases=["Create", "new", "New"]) 52 | async def create_board(self, _ctx, _value=None): 53 | """ 54 | create a new chess board. 55 | """ 56 | if _value: 57 | init_board(_ctx.author.id, _value) 58 | else: 59 | init_board(_ctx.author.id) 60 | await _ctx.send(file=file()) 61 | 62 | @chess.command(name="board", aliases=["Board", "chessboard", "showboard"]) 63 | async def board(self, _ctx): 64 | """ 65 | show user's current chess board. 66 | """ 67 | show_board(_ctx.author.id) 68 | await _ctx.send(file=file()) 69 | 70 | @chess.command(name="fen", aliases=["FEN", "notation"]) 71 | async def fen(self, _ctx): 72 | """ 73 | shows FEN notation of user's current chess board. 74 | """ 75 | await _ctx.send(fen(_ctx.author.id)) 76 | 77 | @chess.command(name="moves", aliases=["legalmoves", "possiblemoves"]) 78 | async def moves(self, _ctx): 79 | """ 80 | shows possible-legal moves for user's current chess board. 81 | """ 82 | await _ctx.send(legal_moves(_ctx.author.id)) 83 | 84 | @chess.group(name="is", aliases=["Is"]) 85 | async def _is(self, _ctx): 86 | """ 87 | Parent group of checks. 88 | """ 89 | pass 90 | 91 | @_is.command(name="legal_move", aliases=["legal", "possible"]) 92 | async def legal_move(self, _ctx, _move): 93 | """ 94 | Checks whether it is a legal move. 95 | """ 96 | await _ctx.send(legal_move(_ctx.author.id, _move)) 97 | 98 | @chess.command(name="move", aliases=["push", "Move", "push_san"]) 99 | async def move(self, _ctx, _move): 100 | """ 101 | Moves the piece. 102 | """ 103 | push_san(_ctx.author.id, _move) 104 | await _ctx.send(file=file()) 105 | 106 | @chess.command(name="undo", aliases=["Undo", "pop"]) 107 | async def undo(self, _ctx): 108 | """ 109 | Undoes the last move. 110 | """ 111 | undo(_ctx.author.id) 112 | await _ctx.send(file=file()) 113 | 114 | @_is.command(name="checkmate", aliases=["Checkmate", "cm"]) 115 | async def checkmate(self, _ctx): 116 | """ 117 | Checks whether it is a checkmate. 118 | """ 119 | await _ctx.send(checkmate(_ctx.author.id)) 120 | 121 | @_is.command(name="stalemate", aliases=["Stalemate", "sm"]) 122 | async def stalemate(self, _ctx): 123 | """ 124 | Checks whether it is a Stalemate 125 | """ 126 | await _ctx.send(stalemate(_ctx.author.id)) 127 | 128 | @_is.command(name="insufficient_material", aliases=["insufficientmaterial", "im"]) 129 | async def insufficient_material(self, _ctx): 130 | """ 131 | Checks whether neither of the sides have sufficient material to win. 132 | """ 133 | await _ctx.send(insufficient_material(_ctx.author.id)) 134 | 135 | @_is.command(name="game_over", aliases=["gameover", "over"]) 136 | async def game_over(self, _ctx): 137 | """ 138 | Checks whether the game is over. 139 | """ 140 | await _ctx.send(game_over(_ctx.author.id)) 141 | 142 | # claims group should be created. 143 | @_is.command(name="draw", aliases=["Draw"]) 144 | async def draw(self, _ctx): 145 | """ 146 | Checks whether the player can claim a draw. 147 | """ 148 | await _ctx.send(draw(_ctx.author.id)) 149 | 150 | @_is.command(name="threefold_repetition", aliases=["threefold", "threefoldrepetition"]) 151 | async def threefold_repetition(self, _ctx): 152 | """ 153 | Checks if the player to move can claim a draw by threefold repetition. 154 | """ 155 | await _ctx.send(threefold_repetition(_ctx.author.id)) 156 | 157 | @chess.command(name="halfmove_clock", aliases=["halfmoveclock"]) 158 | async def halfmove_clock(self, _ctx): 159 | """ 160 | The number of half-moves since the last capture or pawn move. 161 | """ 162 | await _ctx.send(halfmove_clock(_ctx.author.id)) 163 | 164 | @_is.command(name="fifty_moves", aliases=["fiftymoves"]) 165 | async def fifty_moves(self, ctx): 166 | """ 167 | Checks if the player to move can claim a draw by the fifty-move rule. 168 | """ 169 | await ctx.send(fifty_moves(ctx.author.id)) 170 | 171 | @_is.command(name="fivefold_repetition", aliases=["fivefoldrepetition"]) 172 | async def fivefold_repetition(self, _ctx): 173 | """ 174 | Checks whether user can claim a draw by fivefold repetition. 175 | """ 176 | await _ctx.send(fivefold_repetition(_ctx.author.id)) 177 | 178 | @_is.command(name="seventyfive_moves", aliases=["seventyfivemoves"]) 179 | async def seventyfive_moves(self, _ctx): 180 | """ 181 | Checks whether user can claim a draw by seventyfive-moves rule. 182 | """ 183 | await _ctx.send(seventyfive_moves(_ctx.author.id)) 184 | 185 | @_is.command() 186 | async def check(self, _ctx): 187 | """ 188 | Checks whether it is a check. 189 | """ 190 | await _ctx.send(check(_ctx.author.id)) 191 | 192 | @_is.command() 193 | async def attacked_by(self, _ctx, _color, _square): 194 | """ 195 | Checks whether a piece is attacked by another piece. 196 | """ 197 | await _ctx.send(attacked_by(_ctx.author.id, _color, _square)) 198 | 199 | @chess.command() 200 | async def attackers(self, _ctx, _color, _square): 201 | """ 202 | Displays attackers for a piece. 203 | """ 204 | attackers(_ctx.author.id, _color, _square) 205 | await _ctx.send(file=file()) 206 | 207 | @chess.command() 208 | async def attacks(self, _ctx, _square): 209 | """ 210 | Displays attacks on a piece. 211 | """ 212 | attacks(_ctx.author.id, _square) 213 | await _ctx.send(file=file()) 214 | 215 | @_is.command() 216 | async def attacker(self, _ctx, _attacker, _color, _square): 217 | """ 218 | Checks whether a piece is being attacked by another piece. 219 | """ 220 | await _ctx.send(attacker(_ctx.author.id, _attacker, _color, _square)) 221 | 222 | 223 | def setup(_bot): 224 | _bot.add_cog(Chess(_bot)) 225 | -------------------------------------------------------------------------------- /cogs/cog_template: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | class template(commands.Cog): 5 | def __init__(self, bot): 6 | self.bot = bot 7 | 8 | def setup(bot): 9 | bot.add_cog(template(bot)) -------------------------------------------------------------------------------- /cogs/error_handling.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | import difflib, math 5 | 6 | QUESTION_MARK_ICON = "https://cdn.discordapp.com/attachments/822420465250861096/893413947061964860/question.png" 7 | 8 | class ErrorHandling(commands.Cog): 9 | def __init__(self, bot): 10 | self.bot = bot 11 | 12 | @commands.Cog.listener() 13 | async def on_command_error(self, ctx, error): 14 | """Command error handler""" 15 | embed = discord.Embed(color=discord.Color.red()) 16 | if isinstance(error, commands.CommandNotFound): 17 | await self.send_command_suggestion(ctx, ctx.invoked_with) 18 | return 19 | 20 | elif isinstance(error, commands.CommandOnCooldown): 21 | embed.title = "Whoops Cooldown!" 22 | embed.description = f"Command is on cooldown. Try again after {math.ceil(error.retry_after)} seconds!" 23 | await ctx.send(embed=embed) 24 | else: 25 | raise error 26 | 27 | async def send_command_suggestion(self, ctx: commands.Context, command_name: str) -> None: 28 | """Sends user similar commands if any can be found.""" 29 | raw_commands = [] 30 | for cmd in self.bot.walk_commands(): 31 | if not cmd.hidden: 32 | raw_commands += (cmd.name, *cmd.aliases) 33 | if similar_command_data := difflib.get_close_matches(command_name, raw_commands, 1): 34 | similar_command_name = similar_command_data[0] 35 | similar_command = self.bot.get_command(similar_command_name) 36 | 37 | if not similar_command: 38 | return 39 | 40 | misspelled_content = ctx.message.content 41 | e = discord.Embed() 42 | e.set_author(name="Did you mean:", icon_url=QUESTION_MARK_ICON) 43 | e.description = misspelled_content.replace(command_name, similar_command_name, 1) 44 | await ctx.send(embed=e) 45 | 46 | 47 | def setup(bot): 48 | bot.add_cog(ErrorHandling(bot)) 49 | -------------------------------------------------------------------------------- /cogs/events.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | from libs import config 5 | 6 | class Events(commands.Cog): 7 | """ 8 | Bot events. 9 | """ 10 | def __init__(self, bot): 11 | self.bot = bot 12 | 13 | @commands.Cog.listener() 14 | async def on_ready(self): 15 | print(f'We have logged in as {self.bot.user}') 16 | await self.bot.change_presence(activity=discord.Game(name=config.special_event)) 17 | config.load_config(self.bot) 18 | 19 | print("Session started.") 20 | 21 | 22 | def setup(bot): 23 | bot.add_cog(Events(bot)) 24 | -------------------------------------------------------------------------------- /cogs/fonts.json: -------------------------------------------------------------------------------- 1 | { 2 | "fonts1":[ 3 | "alligator", 4 | "alligator2", 5 | "banner", 6 | "banner3-D", 7 | "basic", 8 | "bell", 9 | "binary", 10 | "block", 11 | "bubble" 12 | ], 13 | "fonts2":[ 14 | "catwalk", 15 | "dotmatrix", 16 | "hex", 17 | "lcd", 18 | "linux", 19 | "marquee", 20 | "os2", 21 | "pepper", 22 | "poison" 23 | ], 24 | "fonts3":[ 25 | "sblood", 26 | "script", 27 | "shadow", 28 | "short", 29 | "speed", 30 | "starwars", 31 | "thick", 32 | "thin", 33 | "tiles" 34 | ], 35 | "fonts4":[ 36 | "tombstone", 37 | "weird", 38 | "wavy" 39 | ] 40 | } -------------------------------------------------------------------------------- /cogs/fun.py: -------------------------------------------------------------------------------- 1 | # contributors : Hex 2 | import discord 3 | from discord import member 4 | from discord.ext import commands 5 | import random 6 | from PIL import Image, ImageFont, ImageDraw 7 | from io import BytesIO 8 | import asyncio 9 | 10 | links = [ 11 | "http://yeahlemons.com/", 12 | "http://imaninja.com/", 13 | "http://thatsthefinger.com/", 14 | "http://corndogoncorndog.com/", 15 | "http://iloveyoulikeafatladylovesapples.com/", 16 | "http://corndog.io/", 17 | "http://burnie.com/", 18 | "http://www.wutdafuk.com/", 19 | "http://www.infinitething.com/", 20 | "http://www.muchbetterthanthis.com/", 21 | "http://www.theendofreason.com/", 22 | "http://tunnelsnakes.com/", 23 | "http://www.coloursquares.com/", 24 | "http://crouton.net/", 25 | "http://eelslap.com/", 26 | "http://whitetrash.nl/", 27 | "http://metaphorsofinfinity.com/", 28 | "http://www.yesnoif.com/", 29 | "http://www.electricboogiewoogie.com/", 30 | "http://www.partridgegetslucky.com/", 31 | "http://buildshruggie.com/", 32 | "http://isitwednesdaymydudes.ml/", 33 | "http://heeeeeeeey.com/", 34 | "http://iamawesome.com/", 35 | "http://pixelsfighting.com/", 36 | ] 37 | 38 | emoji_list = { 39 | "a": ":regional_indicator_a:", 40 | "b": ":regional_indicator_b:", 41 | "c": ":regional_indicator_c:", 42 | "d": ":regional_indicator_d:", 43 | "e": ":regional_indicator_e:", 44 | "f": ":regional_indicator_f:", 45 | "g": ":regional_indicator_g:", 46 | "h": ":regional_indicator_h:", 47 | "i": ":regional_indicator_i:", 48 | "j": ":regional_indicator_j:", 49 | "k": ":regional_indicator_k:", 50 | "l": ":regional_indicator_l:", 51 | "m": ":regional_indicator_m:", 52 | "n": ":regional_indicator_n:", 53 | "o": ":regional_indicator_o:", 54 | "p": ":regional_indicator_p:", 55 | "q": ":regional_indicator_q:", 56 | "r": ":regional_indicator_r:", 57 | "s": ":regional_indicator_s:", 58 | "t": ":regional_indicator_t:", 59 | "u": ":regional_indicator_u:", 60 | "v": ":regional_indicator_v:", 61 | "w": ":regional_indicator_w:", 62 | "x": ":regional_indicator_x:", 63 | "y": ":regional_indicator_y:", 64 | "z": ":regional_indicator_z:", 65 | "0": ":zero", 66 | "1": ":one:", 67 | "2": ":two:", 68 | "3": ":three:", 69 | "4": ":four:", 70 | "5": ":five:", 71 | "6": ":six:", 72 | "7": ":seven:", 73 | "8": ":eight:", 74 | "9": ":nine:", 75 | "_": " ", 76 | } 77 | 78 | logins = [ 79 | "**Login:**\n**Email:** `starryhead@liar.com`\n**Password:** `passwot?`", 80 | "**Login:**\n**Email:** `blackismokes.com`\nPassword: `yeeehaaww`", 81 | "**Login:**\nEmail:** `ihateapplesxD@hotmail.com`\n**Password:** `pennydumb`", 82 | "**Login:**\n**Email:** `rooftopboi2@tired.com`\n**Password:** `lmao`", 83 | "**Login:**\n**Email:** `spicyhub69@flowervase.com`\n**Password:** `xyzk`", 84 | "**Login:**\n**Email:** `420Forbidden@NaN.com`\n**Password:** `NULL`", 85 | "**Login:**\n**Email:** `YourMom@exe.in`\n**Password:** `2 + 2 = 5`", 86 | ] 87 | 88 | dms = [ 89 | "Yeah she was your mom", 90 | "i love ~~you~~ washing machines", 91 | "man im tired", 92 | "tf was that bro", 93 | "i am 9 years old", 94 | "Wanna play Forknight?", 95 | "i just robbed my neighbour lmao", 96 | "do u like street lights?", 97 | ] 98 | 99 | words = ["lmao", "potato", "no u", "MOM", "its small", "i like it"] 100 | 101 | letters = ["e", "f", "s"] 102 | 103 | ips = [ 104 | "62.143.94.122", 105 | "37.111.208.88", 106 | "127.195.193.63", 107 | "172.249.219.149", 108 | "39.250.60.34", 109 | "191.184.2.171", 110 | "143.79.65.170", 111 | "17.36.141.6", 112 | "234.10.203.70", 113 | "115.107.247.111", 114 | ] 115 | 116 | cursive = { 117 | "a": "𝓪", 118 | "b": "𝓫", 119 | "c": "𝓬", 120 | "d": "𝓭", 121 | "e": "𝓮", 122 | "f": "𝓯", 123 | "g": "𝓰", 124 | "h": "𝓱", 125 | "i": "𝓲", 126 | "j": "𝓳", 127 | "k": "𝓴", 128 | "l": "𝓵", 129 | "m": "𝓶", 130 | "n": "𝓷", 131 | "o": "𝓸", 132 | "p": "𝓹", 133 | "q": "𝓺", 134 | "r": "𝓻", 135 | "s": "𝓼", 136 | "t": "𝓽", 137 | "u": "𝓾", 138 | "v": "𝓿", 139 | "w": "𝔀", 140 | "x": "𝔁", 141 | "y": "𝔂", 142 | "z": "𝔃", 143 | "_": " ", 144 | } 145 | 146 | emo2 = { 147 | "a": "🄰", 148 | "b": "🄱", 149 | "c": "🄲", 150 | "d": "🄳", 151 | "e": "🄴", 152 | "f": "🄵", 153 | "g": "🄶", 154 | "h": "🄷", 155 | "i": "🄸", 156 | "j": "🄹", 157 | "k": "🄺", 158 | "l": "🄻", 159 | "m": "🄼", 160 | "n": "🄽", 161 | "o": "🄾", 162 | "p": "🄿", 163 | "q": "🅀", 164 | "r": "🅁", 165 | "s": "🅂", 166 | "t": "🅃", 167 | "u": "🅄", 168 | "v": "🅅", 169 | "w": "🅆", 170 | "x": "🅇", 171 | "y": "🅈", 172 | "z": "🅉", 173 | "_": " ", 174 | } 175 | 176 | del_cache = {} 177 | 178 | 179 | class Fun(commands.Cog): 180 | """ 181 | Fun commands cog 182 | """ 183 | def __init__(self, bot): 184 | self.bot = bot 185 | 186 | @commands.Cog.listener() 187 | async def on_raw_message_delete(self, payload): 188 | msg = payload.cached_message 189 | try: 190 | if msg.author == self.bot.user: 191 | return 192 | temp = {msg.channel.id : { "content": msg.content, "author": msg.author}} 193 | del_cache.update(temp) 194 | except: 195 | pass 196 | 197 | @commands.command(aliases=['8ball', '8 ball']) 198 | async def _8ball(self, ctx, *, que=None): 199 | if que is None: 200 | await ctx.send("What should i answer, dumbo") 201 | return 202 | 203 | choices = ["not looking good bud sorry to say", 204 | "for sure", "my magics doesnt work at the moment", "100%", "ummmm not so sure", 205 | "NO", "100% no", "i wish i could change it but my magics says no", "yes you are right", 206 | "my reply is no", "i can tell you certainly, no", "sure, I literally couldn't care less", 207 | " no???", "yes!!!!", " im not sure but ur def stupid", " i can tell you certainly, no", 208 | "sure, I literally", "sure, why not", "can you not", "Is trump's skin orange?", "yes", 209 | "when you grow a braincell, yes", "that would be a hell no", " hell to the yes", 210 | "sure, why not", "yes, idiot"] 211 | 212 | await ctx.send(f":8ball:{random.choice(choices)}") 213 | 214 | # SIMP RATE 215 | # noinspection SpellCheckingInspection 216 | @commands.command(name="simprate") 217 | async def simp_rate(self, ctx, _member: discord.Member = None): 218 | if _member is None: 219 | _member = ctx.message.author 220 | 221 | value = random.randint(0, 100) 222 | em = discord.Embed( 223 | title="SimpRate Machine", 224 | description=f"{_member.name} is {value} Simp.", 225 | ) 226 | 227 | await ctx.send(embed=em) 228 | 229 | # GOOGLE 230 | @commands.command(name="lemmegoogle") 231 | async def lemmegoogle(self, ctx, *, q): 232 | await ctx.send(f"http://letmegooglethat.com/?q={q}".replace(" ", "+")) 233 | 234 | # GREEN TEXT 235 | # noinspection SpellCheckingInspection 236 | @commands.command(name="greentext", aliases=["Greentext"]) 237 | async def green_text(self, ctx, *, text): 238 | await ctx.send(f"```css\n{text}\n```") 239 | 240 | # noinspection SpellCheckingInspection 241 | @commands.command() 242 | async def uselessweb(self, ctx): 243 | await ctx.send(f"{random.choice(links)}") 244 | 245 | @commands.command(name="yasahiroify", aliases=["yasafy"]) 246 | async def yasahiroify(self, ctx, *, arguments="put something to get yasahiroified output!"): 247 | await ctx.send(''.join(random.choice((str.upper, str.lower))(c) for c in arguments)) 248 | 249 | # noinspection SpellCheckingInspection 250 | @commands.command(name="emojify") 251 | async def _emojify(self, ctx, msg): 252 | word = [] 253 | for i in str(msg).lower(): 254 | try: 255 | word.append(emoji_list[i]) 256 | except KeyError: 257 | pass 258 | space = " " 259 | message = space.join(word) 260 | await ctx.send(message) 261 | 262 | # noinspection SpellCheckingInspection 263 | @commands.command(name="epicgamerrate", aliases=["egamerrate", "egr", "egrate"]) 264 | async def epic_gamer_rate(self, ctx, _member: discord.Member = None): 265 | if _member is None: 266 | _member = ctx.message.author 267 | em = discord.Embed( 268 | title="EpicGamerRate Machine", 269 | description=f"You are {random.randint(0, 100)}% Epic Gamer 😎", 270 | ) 271 | 272 | await ctx.send(embed=em) 273 | else: 274 | em = discord.Embed( 275 | title="EpicGamerRate Machine", 276 | description=f"{_member.nick} is {random.randint(0, 100)}% Epic Gamer 😎", 277 | ) 278 | 279 | await ctx.send(embed=em) 280 | 281 | @commands.command(name="clap") 282 | async def clap(self, ctx, *, clap): 283 | await ctx.send(f"{clap}".replace(" ", "👏")) 284 | 285 | @commands.command(name="lenny") 286 | async def lenny(self, ctx): 287 | await ctx.send("( ͡° ͜ʖ ͡°)") 288 | 289 | @commands.command() 290 | async def imagine(self, ctx, *, ima): 291 | em = discord.Embed(title=f"{ima}") 292 | em.set_footer(text=f"{ctx.author.name} is trying really hard to imagine.") 293 | await ctx.send(embed=em) 294 | 295 | # noinspection SpellCheckingInspection 296 | @commands.command() 297 | async def hack(self, ctx, _member: discord.Member = None): 298 | if _member is None: 299 | await ctx.send("ok you did hack smthn, now mention someone else") 300 | return 301 | message = await ctx.send(f"Hacking {_member.name} now...") 302 | await asyncio.sleep(2) 303 | await message.edit(content="[▘]Getting Discord Login..(2FA bypassed)") 304 | await asyncio.sleep(2) 305 | await message.edit(content=f"[▖]**Found:**\n{random.choice(logins)}") 306 | await asyncio.sleep(2) 307 | await message.edit( 308 | content="[▝]Fetching DM's with closest friends(if there are any friends at all)" 309 | ) 310 | await asyncio.sleep(2) 311 | await message.edit(content=f"[▗]**Last DM:** {random.choice(dms)}") 312 | await asyncio.sleep(2) 313 | await message.edit(content="[▖]Finding most common word...") 314 | await asyncio.sleep(2) 315 | await message.edit(content=f"[▘]**most used word:** {random.choice(words)}") 316 | await asyncio.sleep(2) 317 | await message.edit( 318 | content=f"[▝]**constantly used letter:** {random.choice(letters)}" 319 | ) 320 | await asyncio.sleep(2) 321 | await message.edit( 322 | content=f"[▗]Injecting Trojan Virus into Discriminator #{_member.discriminator}" 323 | ) 324 | await asyncio.sleep(2) 325 | await message.edit( 326 | content=f"[▝]Virus Injected, Emotes Stolen" 327 | ) 328 | await asyncio.sleep(2) 329 | await message.edit(content=f"[▖]Setting up Epic Store Account..") 330 | await asyncio.sleep(2) 331 | await message.edit(content=f"[▘]Hacking Epic Store Account..") 332 | await asyncio.sleep(2) 333 | await message.edit( 334 | content=f"[▗]Uninstalling **Fortnight**..." 335 | ) 336 | await asyncio.sleep(2) 337 | await message.edit(content=f"[▖]Finding IP Address..") 338 | await asyncio.sleep(2) 339 | await message.edit(content=f"[▗]**IP Address:** {random.choice(ips)}") 340 | await asyncio.sleep(2) 341 | await message.edit(content=f"[▘]Selling Data to Government..") 342 | await asyncio.sleep(2) 343 | await message.edit(content=f"[▗]Reporting Account to Discord for breaking TOS..") 344 | await asyncio.sleep(2) 345 | await message.edit(content=f"[▘]Collecting Medical Records..") 346 | await asyncio.sleep(2) 347 | await message.edit(content=f"Finished hacking {_member.nick} \n" 348 | "The totally real and dangerous hack is complete...\n" 349 | "Now You Go To Jail.") 350 | 351 | @commands.command() 352 | async def kill(self, ctx, _member: discord.Member): 353 | deaths = [ 354 | f"{ctx.message.author}"[:-5] + f" shoots {_member.name} in the head.", 355 | f"{_member.name} dies due to Depression.", 356 | f"{ctx.message.author}"[:-5] 357 | + f" drags {_member.name}'s ears too hard and rips them off.", 358 | f"{ctx.message.author}"[:-5] 359 | + f" killed {_member.name} by ripping the skin off of their face and making a mask out of it.", 360 | f"{ctx.message.author}"[:-5] + f" ripped {_member.name}'s Heart.", 361 | f"{ctx.message.author}"[:-5] + f" Alt+F4'd {_member.name}.exe!", 362 | f"{ctx.message.author}"[:-5] + f" swallowed {_member.name}.", 363 | ] 364 | 365 | if _member == ctx.message.author: 366 | await ctx.send("Ok you killed yourself, now mention someone else...") 367 | else: 368 | await ctx.send(f"{random.choice(deaths)}") 369 | 370 | @commands.command() 371 | async def cursive(self, ctx, msg): 372 | word = [] 373 | for i in str(msg).lower(): 374 | try: 375 | word.append(cursive[i]) 376 | except KeyError: 377 | pass 378 | space = "" 379 | message = space.join(word) 380 | await ctx.send(message) 381 | 382 | # noinspection SpellCheckingInspection 383 | @commands.command() 384 | async def emojify2(self, ctx, msg): 385 | word = [] 386 | for i in str(msg).lower(): 387 | try: 388 | word.append(emo2[i]) 389 | except KeyError: 390 | pass 391 | space = "" 392 | message = space.join(word) 393 | await ctx.send(message) 394 | 395 | @commands.command(aliases=['OwO']) 396 | async def owo(self, ctx): 397 | await ctx.send("OwO") 398 | 399 | @commands.command() 400 | async def snipe(self, ctx): 401 | """ 402 | Shows the last deleted message from a specified channel 403 | """ 404 | channel = ctx.channel.id 405 | try: 406 | msg = del_cache[channel]['content'] 407 | author = del_cache[channel]['author'] 408 | await ctx.send(f"{msg} - {author}") 409 | except Exception as e: 410 | print(e) 411 | await ctx.send("No messages to snipe!") 412 | 413 | 414 | def setup(bot): 415 | bot.add_cog(Fun(bot)) 416 | -------------------------------------------------------------------------------- /cogs/githubinfo.py: -------------------------------------------------------------------------------- 1 | import random 2 | from datetime import datetime 3 | from urllib.parse import quote, quote_plus 4 | 5 | from libs.httpsession import http_session 6 | 7 | import discord 8 | from discord.ext import commands 9 | 10 | NEGATIVE_REPLIES = [ 11 | "Noooooo!!", 12 | "Nope.", 13 | "I'm sorry Dave, I'm afraid I can't do that.", 14 | "I don't think so.", 15 | "Not gonna happen.", 16 | "Out of the question.", 17 | "Huh? No.", 18 | "Nah.", 19 | "Naw.", 20 | "Not likely.", 21 | "No way, José.", 22 | "Not in a million years.", 23 | "Fat chance.", 24 | "Certainly not.", 25 | "NEGATORY.", 26 | "Nuh-uh.", 27 | "Not in my house!", 28 | ] 29 | 30 | GITHUB_API_URL = "https://api.github.com" 31 | 32 | 33 | class GithubInfo(commands.Cog): 34 | """Fetches info from GitHub.""" 35 | 36 | def __init__(self, bot): 37 | self.bot = bot 38 | 39 | async def fetch_data(self, url: str) -> dict: 40 | """Retrieve data as a dictionary.""" 41 | async with http_session.get(url) as r: 42 | return await r.json() 43 | 44 | @commands.group(name="github", aliases=("gh", "gitinfo")) 45 | @commands.cooldown(1, 10, commands.BucketType.user) 46 | async def github_group(self, ctx: commands.Context) -> None: 47 | """Commands for finding information related to GitHub.""" 48 | if ctx.invoked_subcommand is None: 49 | await ctx.send_help(ctx.command) 50 | 51 | @github_group.command(name="user", aliases=("userinfo",)) 52 | async def github_user_info(self, ctx: commands.Context, username: str) -> None: 53 | """Fetches a user's GitHub information.""" 54 | async with ctx.typing(): 55 | user_data = await self.fetch_data(f"{GITHUB_API_URL}/users/{quote_plus(username)}") 56 | 57 | # User_data will not have a message key if the user exists 58 | if "message" in user_data: 59 | embed = discord.Embed( 60 | title=random.choice(NEGATIVE_REPLIES), 61 | description=f"The profile for `{username}` was not found.", 62 | colour=Colours.soft_red 63 | ) 64 | 65 | await ctx.send(embed=embed) 66 | return 67 | 68 | org_data = await self.fetch_data(user_data["organizations_url"]) 69 | orgs = [f"[{org['login']}](https://github.com/{org['login']})" for org in org_data] 70 | orgs_to_add = " | ".join(orgs) 71 | 72 | gists = user_data["public_gists"] 73 | 74 | # Forming blog link 75 | if user_data["blog"].startswith("http"): # Blog link is complete 76 | blog = user_data["blog"] 77 | elif user_data["blog"]: # Blog exists but the link is not complete 78 | blog = f"https://{user_data['blog']}" 79 | else: 80 | blog = "No website link available" 81 | 82 | embed = discord.Embed( 83 | title=f"`{user_data['login']}`'s GitHub profile info", 84 | description=f"```{user_data['bio']}```\n" if user_data["bio"] else "", 85 | color=discord.Color.dark_theme(), 86 | url=user_data["html_url"], 87 | timestamp=datetime.strptime(user_data["created_at"], "%Y-%m-%dT%H:%M:%SZ") 88 | ) 89 | embed.set_thumbnail(url=user_data["avatar_url"]) 90 | embed.set_footer(text="Account created at") 91 | 92 | if user_data["type"] == "User": 93 | 94 | embed.add_field( 95 | name="Followers", 96 | value=f"[{user_data['followers']}]({user_data['html_url']}?tab=followers)" 97 | ) 98 | embed.add_field( 99 | name="Following", 100 | value=f"[{user_data['following']}]({user_data['html_url']}?tab=following)" 101 | ) 102 | 103 | embed.add_field( 104 | name="Public repos", 105 | value=f"[{user_data['public_repos']}]({user_data['html_url']}?tab=repositories)" 106 | ) 107 | 108 | if user_data["type"] == "User": 109 | embed.add_field( 110 | name="Gists", 111 | value=f"[{gists}](https://gist.github.com/{quote_plus(username, safe='')})" 112 | ) 113 | 114 | embed.add_field( 115 | name=f"Organization{'s' if len(orgs)!=1 else ''}", 116 | value=orgs_to_add if orgs else "No organizations." 117 | ) 118 | embed.add_field(name="Website", value=blog) 119 | 120 | await ctx.send(embed=embed) 121 | 122 | @github_group.command(name='repository', aliases=('repo',)) 123 | async def github_repo_info(self, ctx: commands.Context, *repo: str) -> None: 124 | """ 125 | Fetches a repositories' GitHub information. 126 | 127 | The repository should look like `user/reponame` or `user reponame`. 128 | """ 129 | repo = "/".join(repo) 130 | if repo.count("/") != 1: 131 | embed = discord.Embed( 132 | title=random.choice(NEGATIVE_REPLIES), 133 | description="The repository should look like `user/reponame` or `user reponame`.", 134 | color=discord.Color.dark_theme() 135 | ) 136 | 137 | await ctx.send(embed=embed) 138 | return 139 | 140 | async with ctx.typing(): 141 | repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{quote(repo)}") 142 | 143 | # There won't be a message key if this repo exists 144 | if "message" in repo_data: 145 | embed = discord.Embed( 146 | title=random.choice(NEGATIVE_REPLIES), 147 | description="The requested repository was not found.", 148 | color=discord.Color.dark_theme() 149 | ) 150 | 151 | await ctx.send(embed=embed) 152 | return 153 | 154 | embed = discord.Embed( 155 | title=repo_data["name"], 156 | description=repo_data["description"], 157 | color=discord.Color.dark_theme(), 158 | url=repo_data["html_url"] 159 | ) 160 | 161 | # If it's a fork, then it will have a parent key 162 | try: 163 | parent = repo_data["parent"] 164 | embed.description += f"\n\nForked from [{parent['full_name']}]({parent['html_url']})" 165 | except KeyError: 166 | print("Repository is not a fork.") 167 | 168 | repo_owner = repo_data["owner"] 169 | 170 | embed.set_author( 171 | name=repo_owner["login"], 172 | url=repo_owner["html_url"], 173 | icon_url=repo_owner["avatar_url"] 174 | ) 175 | 176 | repo_created_at = datetime.strptime(repo_data["created_at"], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y") 177 | last_pushed = datetime.strptime(repo_data["pushed_at"], "%Y-%m-%dT%H:%M:%SZ").strftime("%d/%m/%Y at %H:%M") 178 | 179 | embed.set_footer( 180 | text=( 181 | f"{repo_data['forks_count']} ⑂ " 182 | f"• {repo_data['stargazers_count']} ⭐ " 183 | f"• Created At {repo_created_at} " 184 | f"• Last Commit {last_pushed}" 185 | ) 186 | ) 187 | 188 | await ctx.send(embed=embed) 189 | 190 | 191 | def setup(bot) -> None: 192 | """Load the GithubInfo cog.""" 193 | bot.add_cog(GithubInfo(bot)) 194 | -------------------------------------------------------------------------------- /cogs/latex.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import hashlib 3 | import pathlib 4 | import re 5 | from concurrent.futures import ThreadPoolExecutor 6 | from io import BytesIO 7 | 8 | import discord 9 | import matplotlib.pyplot as plt 10 | from discord.ext import commands 11 | 12 | 13 | plt.rcParams.update( 14 | { 15 | "font.size": 16, 16 | "mathtext.fontset": "cm", 17 | "mathtext.rm": "serif", 18 | "figure.facecolor": "36393F", 19 | "text.color": "white", 20 | } 21 | ) 22 | 23 | FORMATTED_CODE_REGEX = re.compile( 24 | r"(?P(?P```)|``?)" 25 | r"(?(block)(?:(?P[a-z]+)\n)?)" 26 | r"(?:[ \t]*\n)*" 27 | r"(?P.*?)" 28 | r"\s*" 29 | r"(?P=delim)", 30 | re.DOTALL | re.IGNORECASE, 31 | ) 32 | 33 | CACHE_DIRECTORY = pathlib.Path("_latex_cache") 34 | CACHE_DIRECTORY.mkdir(exist_ok=True) 35 | 36 | 37 | class Latex(commands.Cog): 38 | """Renders latex.""" 39 | 40 | def __init__(self, bot): 41 | self.bot = bot 42 | 43 | @staticmethod 44 | def _render(text: str, filepath: pathlib.Path) -> BytesIO: 45 | """ 46 | Return the rendered image if latex compiles without errors, otherwise raise a BadArgument Exception. 47 | 48 | Saves rendered image to cache. 49 | """ 50 | fig = plt.figure() 51 | rendered_image = BytesIO() 52 | fig.text(0, 1, text, horizontalalignment="left", verticalalignment="top") 53 | 54 | try: 55 | plt.savefig(rendered_image, bbox_inches="tight", dpi=600) 56 | except ValueError as e: 57 | raise commands.BadArgument(str(e)) 58 | 59 | rendered_image.seek(0) 60 | 61 | with open(filepath, "wb") as f: 62 | f.write(rendered_image.getbuffer()) 63 | 64 | return rendered_image 65 | 66 | @staticmethod 67 | def _prepare_input(text: str) -> str: 68 | text = text.replace(r"\\", "$\n$") 69 | 70 | if match := FORMATTED_CODE_REGEX.match(text): 71 | return match.group("code") 72 | else: 73 | return text 74 | 75 | @commands.command() 76 | @commands.max_concurrency(1, commands.BucketType.guild, wait=True) 77 | async def latex(self, ctx: commands.Context, *, text: str) -> None: 78 | """Renders the text in latex and sends the image.""" 79 | text = self._prepare_input(text) 80 | query_hash = hashlib.md5(text.encode()).hexdigest() 81 | image_path = CACHE_DIRECTORY.joinpath(f"{query_hash}.png") 82 | async with ctx.typing(): 83 | if image_path.exists(): 84 | await ctx.send(file=discord.File(image_path)) 85 | return 86 | 87 | with ThreadPoolExecutor() as pool: 88 | image = await asyncio.get_running_loop().run_in_executor( 89 | pool, self._render, text, image_path 90 | ) 91 | 92 | await ctx.send(file=discord.File(image, "latex.png")) 93 | 94 | 95 | def setup(bot) -> None: 96 | bot.add_cog(Latex(bot)) 97 | -------------------------------------------------------------------------------- /cogs/libs/__pycache__/attacks.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/attacks.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/board.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/board.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/boards.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/boards.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/brainfuck.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/brainfuck.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/formatter.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/formatter.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/math.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/math.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/move.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/move.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/moves.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/moves.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/repetitions.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/repetitions.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/state.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/state.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/__pycache__/svg.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/cogs/libs/__pycache__/svg.cpython-38.pyc -------------------------------------------------------------------------------- /cogs/libs/attacks.py: -------------------------------------------------------------------------------- 1 | import chess 2 | import chess.svg 3 | 4 | from cogs.libs.svg import generate_image 5 | 6 | from cogs.libs.boards import boards 7 | 8 | 9 | def convert(_value): 10 | """ 11 | converts values white, black to booleans. 12 | """ 13 | values = [1, 0] 14 | if _value not in values: 15 | if _value.lower() == "white": 16 | return True 17 | elif _value.lower() == "black": 18 | return False 19 | else: 20 | return _value 21 | 22 | 23 | def check(_user_id): 24 | """ 25 | checks whether it is a check. 26 | """ 27 | _board = boards[_user_id] 28 | return _board.is_check() 29 | 30 | 31 | def attacked_by(_user_id, _color, _square): 32 | """ 33 | checks whether a piece is attacked by a side. 34 | """ 35 | _board = boards[_user_id] 36 | return _board.is_attacked_by(convert(_color), chess.parse_square(_square)) 37 | 38 | 39 | def attackers(_user_id, _color, _square): 40 | """ 41 | displays attackers for a piece. 42 | """ 43 | _board = boards[_user_id] 44 | squares = _board.attackers(convert(_color), chess.parse_square(_square)) 45 | generate_image(_board, _squares=squares) 46 | 47 | 48 | def attacker(_user_id, _attacker, _color, _square): 49 | """ 50 | checks whether a piece is being attacked by another piece. 51 | """ 52 | _board = boards[_user_id] 53 | _attackers = _board.attackers(convert(_color), chess.parse_square(_square)) 54 | return chess.parse_square(_attacker) in _attackers 55 | 56 | 57 | def attacks(_user_id, _square): 58 | """ 59 | displays attacks on a piece. 60 | """ 61 | _board = boards[_user_id] 62 | _attacks = _board.attacks(chess.parse_square(_square)) 63 | generate_image(_board, _squares=_attacks) 64 | -------------------------------------------------------------------------------- /cogs/libs/board.py: -------------------------------------------------------------------------------- 1 | import chess 2 | 3 | from cogs.libs.boards import boards 4 | 5 | from cogs.libs.formatter import format_content 6 | 7 | from cogs.libs.svg import generate_image 8 | 9 | 10 | def init_board(_user_id, _value=None): 11 | """ 12 | create and initialize new chess board. 13 | """ 14 | if _value: 15 | _board = chess.Board(_value) 16 | _new_board = { 17 | _user_id: _board 18 | } 19 | generate_image(_board) 20 | else: 21 | _board = chess.Board() 22 | _new_board = { 23 | _user_id: _board 24 | } 25 | generate_image(_board) 26 | boards.update(_new_board) 27 | 28 | 29 | def show_board(_user_id): 30 | """ 31 | displays the chess board. 32 | """ 33 | _board = boards[_user_id] 34 | generate_image(_board) 35 | 36 | 37 | def fen(_user_id): 38 | """ 39 | shows FEN for the current board. 40 | """ 41 | _board = boards[_user_id] 42 | return format_content(_board.fen()) 43 | -------------------------------------------------------------------------------- /cogs/libs/boards.py: -------------------------------------------------------------------------------- 1 | boards = { 2 | "user": "board" 3 | } 4 | -------------------------------------------------------------------------------- /cogs/libs/brainfuck.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | def evaluate(code): 4 | code = cleanup(list(code)) 5 | bracemap = buildbracemap(code) 6 | 7 | cells, codeptr, cellptr = [0], 0, 0 8 | wlist = [] 9 | while codeptr < len(code): 10 | command = code[codeptr] 11 | 12 | if command == ">": 13 | cellptr += 1 14 | if cellptr == len(cells): cells.append(0) 15 | 16 | if command == "<": 17 | cellptr = 0 if cellptr <= 0 else cellptr - 1 18 | 19 | if command == "+": 20 | cells[cellptr] = cells[cellptr] + 1 if cells[cellptr] < 255 else 0 21 | 22 | if command == "-": 23 | cells[cellptr] = cells[cellptr] - 1 if cells[cellptr] > 0 else 255 24 | 25 | if command == "[" and cells[cellptr] == 0: codeptr = bracemap[codeptr] 26 | if command == "]" and cells[cellptr] != 0: codeptr = bracemap[codeptr] 27 | if command == ".": 28 | wlist.append(chr(cells[cellptr])) 29 | #sys.stdout.write(chr(cells[cellptr])) 30 | if command == ",": cells[cellptr] = ord(getch.getch()) 31 | 32 | codeptr += 1 33 | wlist = ''.join(wlist) 34 | print(wlist) 35 | return wlist 36 | 37 | def cleanup(code): 38 | return ''.join(filter(lambda x: x in ['.', ',', '[', ']', '<', '>', '+', '-'], code)) 39 | 40 | def buildbracemap(code): 41 | temp_bracestack, bracemap = [], {} 42 | 43 | for position, command in enumerate(code): 44 | if command == "[": temp_bracestack.append(position) 45 | if command == "]": 46 | start = temp_bracestack.pop() 47 | bracemap[start] = position 48 | bracemap[position] = start 49 | return bracemap 50 | -------------------------------------------------------------------------------- /cogs/libs/formatter.py: -------------------------------------------------------------------------------- 1 | def format_content(_content, _language="brainfuck"): 2 | """ 3 | some fancy highlighting. 4 | """ 5 | return f"```{_language}\n{_content}```" 6 | -------------------------------------------------------------------------------- /cogs/libs/math.py: -------------------------------------------------------------------------------- 1 | from sly import Lexer 2 | from sly import Parser 3 | 4 | from datetime import datetime 5 | from datetime import date 6 | 7 | 8 | class BasicLexer(Lexer): 9 | tokens = { NAME, NUMBER, STRING } 10 | ignore = '\t ' 11 | literals = { '=', '+', '-', '/', 12 | '*', '(', ')', ',', ';'} 13 | 14 | 15 | # Define tokens as regular expressions 16 | # (stored as raw strings) 17 | NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' 18 | STRING = r'\".*?\"' 19 | 20 | # Number token 21 | @_(r'\d+') 22 | def NUMBER(self, t): 23 | 24 | # convert it into a python integer 25 | t.value = int(t.value) 26 | return t 27 | 28 | # Comment token 29 | @_(r'//.*') 30 | def COMMENT(self, t): 31 | pass 32 | 33 | # Newline token(used only for showing 34 | # errors in new line) 35 | @_(r'\n+') 36 | def newline(self, t): 37 | self.lineno = t.value.count('\n') 38 | 39 | class BasicParser(Parser): 40 | #tokens are passed from lexer to parser 41 | tokens = BasicLexer.tokens 42 | 43 | precedence = ( 44 | ('left', '+', '-'), 45 | ('left', '*', '/'), 46 | ('right', 'UMINUS'), 47 | ) 48 | 49 | def __init__(self): 50 | self.env = { } 51 | 52 | @_('') 53 | def statement(self, p): 54 | pass 55 | 56 | @_('var_assign') 57 | def statement(self, p): 58 | return p.var_assign 59 | 60 | @_('NAME "=" expr') 61 | def var_assign(self, p): 62 | return ('var_assign', p.NAME, p.expr) 63 | 64 | @_('NAME "=" STRING') 65 | def var_assign(self, p): 66 | return ('var_assign', p.NAME, p.STRING) 67 | 68 | @_('expr') 69 | def statement(self, p): 70 | return (p.expr) 71 | 72 | @_('expr "+" expr') 73 | def expr(self, p): 74 | return ('add', p.expr0, p.expr1) 75 | 76 | @_('expr "-" expr') 77 | def expr(self, p): 78 | return ('sub', p.expr0, p.expr1) 79 | 80 | @_('expr "*" expr') 81 | def expr(self, p): 82 | return ('mul', p.expr0, p.expr1) 83 | 84 | @_('expr "/" expr') 85 | def expr(self, p): 86 | return ('div', p.expr0, p.expr1) 87 | 88 | @_('"-" expr %prec UMINUS') 89 | def expr(self, p): 90 | return p.expr 91 | 92 | @_('NAME') 93 | def expr(self, p): 94 | return ('var', p.NAME) 95 | 96 | @_('NUMBER') 97 | def expr(self, p): 98 | return ('num', p.NUMBER) 99 | 100 | class BasicExecute: 101 | thing = 'none' 102 | def __init__(self, tree, env): 103 | self.Error = 0 104 | self.thing = 0 105 | self.env = env 106 | result = self.walkTree(tree) 107 | if result is not None and isinstance(result, int): 108 | self.thing = result 109 | if isinstance(result, str) and result[0] == '"': 110 | self.thing = result 111 | 112 | def walkTree(self, node): 113 | 114 | if isinstance(node, int): 115 | return node 116 | if isinstance(node, str): 117 | return node 118 | 119 | if node is None: 120 | return None 121 | 122 | if node[0] == 'program': 123 | if node[1] == None: 124 | self.walkTree(node[2]) 125 | else: 126 | self.walkTree(node[1]) 127 | self.walkTree(node[2]) 128 | 129 | if node[0] == 'num': 130 | return node[1] 131 | 132 | if node[0] == 'str': 133 | return node[1] 134 | 135 | if node[0] == 'add': 136 | return self.walkTree(node[1]) + self.walkTree(node[2]) 137 | elif node[0] == 'sub': 138 | return self.walkTree(node[1]) - self.walkTree(node[2]) 139 | elif node[0] == 'mul': 140 | return self.walkTree(node[1]) * self.walkTree(node[2]) 141 | elif node[0] == 'div': 142 | return self.walkTree(node[1]) / self.walkTree(node[2]) 143 | 144 | if node[0] == 'var_assign': 145 | self.env[node[1]] = self.walkTree(node[2]) 146 | return node[1] 147 | 148 | if node[0] == 'var': 149 | try: 150 | return self.env[node[1]] 151 | except LookupError: 152 | self.Error = ("Undefined variable '"+node[1]+"' found!") 153 | return 0 154 | 155 | lexer = BasicLexer() 156 | parser = BasicParser() 157 | env = {} 158 | 159 | def evaluate(text): 160 | tree = parser.parse(lexer.tokenize(text)) 161 | execution = BasicExecute(tree, env) 162 | if execution.Error == 0: 163 | return execution.thing 164 | else: 165 | return execution.Error -------------------------------------------------------------------------------- /cogs/libs/move.py: -------------------------------------------------------------------------------- 1 | from cogs.libs.boards import boards 2 | 3 | from cogs.libs.svg import generate_image 4 | 5 | 6 | def push_san(_user_id, _move): 7 | """ 8 | moves a piece. 9 | """ 10 | _board = boards[_user_id] 11 | _board.push_san(_move) 12 | generate_image(_board) 13 | 14 | 15 | def undo(_user_id): 16 | """ 17 | undoes a move. 18 | """ 19 | _board = boards[_user_id] 20 | _board.pop() 21 | generate_image(_board) 22 | -------------------------------------------------------------------------------- /cogs/libs/moves.py: -------------------------------------------------------------------------------- 1 | import chess 2 | 3 | from cogs.libs.formatter import format_content 4 | 5 | from cogs.libs.boards import boards 6 | 7 | 8 | def legal_moves(_user_id): 9 | """ 10 | shows possible legal moves. 11 | """ 12 | _board = boards[_user_id] 13 | 14 | list_moves = [] 15 | for move in _board.legal_moves: 16 | list_moves.append(str(move)) 17 | return format_content(", ".join(list_moves)) 18 | 19 | 20 | def legal_move(_user_id, _move): 21 | """ 22 | checks whether it is a legal move. 23 | """ 24 | _board = boards[_user_id] 25 | return chess.Move.from_uci(_move) in _board.legal_moves 26 | -------------------------------------------------------------------------------- /cogs/libs/repetitions.py: -------------------------------------------------------------------------------- 1 | from cogs.libs.boards import boards 2 | 3 | 4 | def threefold_repetition(_user_id): 5 | """ 6 | Checks if the player to move can claim a draw by threefold repetition. 7 | 8 | Draw by threefold repetition can be claimed if the position on the board occured for the third time 9 | or if such a repetition is reached with one of the possible legal moves. 10 | """ 11 | _board = boards[_user_id] 12 | return _board.can_claim_threefold_repetition() 13 | 14 | 15 | def halfmove_clock(_user_id): 16 | """ 17 | The number of half-moves since the last capture or pawn move. 18 | """ 19 | _board = boards[_user_id] 20 | return _board.halfmove_clock 21 | 22 | 23 | def fifty_moves(_user_id): 24 | """ 25 | Checks if the player to move can claim a draw by the fifty-move rule. 26 | 27 | Draw by the fifty-move rule can be claimed once the clock of halfmoves since the last capture 28 | or pawn move becomes equal or greater to 100, or if there is a legal move that achieves this. 29 | Other means of ending the game take precedence. 30 | """ 31 | _board = boards[_user_id] 32 | return _board.can_claim_fifty_moves() 33 | 34 | 35 | def fivefold_repetition(_user_id): 36 | """ 37 | Since the 1st of July 2014 a game is automatically drawn (without a claim by one of the players) 38 | if a position occurs for the fifth time. Originally this had to occur on consecutive alternating moves, 39 | but this has since been revised. 40 | """ 41 | _board = boards[_user_id] 42 | return _board.is_fivefold_repetition() 43 | 44 | 45 | def seventyfive_moves(_user_id): 46 | """ 47 | Since the 1st of July 2014, a game is automatically drawn (without a clain by one of the players) 48 | if the half-move clock since a capture or pawn move is equal to or greater than 150. 49 | Other means to end a game take precedence. 50 | """ 51 | _board = boards[_user_id] 52 | return _board.is_seventyfive_moves() 53 | -------------------------------------------------------------------------------- /cogs/libs/state.py: -------------------------------------------------------------------------------- 1 | from cogs.libs.boards import boards 2 | 3 | 4 | def checkmate(_user_id): 5 | """ 6 | Checks if the current position is a checkmate. 7 | """ 8 | _board = boards[_user_id] 9 | return _board.is_checkmate() 10 | 11 | 12 | def stalemate(_user_id): 13 | """ 14 | Checks if the current position is a stalemate. 15 | """ 16 | _board = boards[_user_id] 17 | return _board.is_stalemate() 18 | 19 | 20 | def insufficient_material(_user_id): 21 | """ 22 | Checks if neither side has sufficient winning material. 23 | """ 24 | _board = boards[_user_id] 25 | return _board.is_insufficient_material() 26 | 27 | 28 | def game_over(_user_id): 29 | """ 30 | Checks whether the game is over due to... 31 | - checkmate 32 | - stalemate 33 | - insufficient_material 34 | 35 | - seventyfive-move rule 36 | - fivefold repetition 37 | """ 38 | _board = boards[_user_id] 39 | return _board.is_game_over() 40 | 41 | 42 | def draw(_user_id): 43 | """ 44 | Checks if the player to move can claim a draw by the fifty-move rule 45 | or by threefold repetition. 46 | """ 47 | _board = boards[_user_id] 48 | return _board.can_claim_draw() 49 | -------------------------------------------------------------------------------- /cogs/libs/svg.py: -------------------------------------------------------------------------------- 1 | from chess import svg 2 | 3 | from cairosvg import svg2png 4 | 5 | 6 | def get_image(_svg_code): 7 | """ 8 | Convert the SVG string to PNG. 9 | """ 10 | svg2png(bytestring=_svg_code, write_to='output.png') 11 | 12 | 13 | def generate_image(_board, _squares=None): 14 | """ 15 | Generate SVG string of the board. 16 | """ 17 | if _squares: 18 | get_image(svg.board(_board, squares=_squares, size=350)) 19 | else: 20 | get_image(svg.board(_board, size=350)) 21 | -------------------------------------------------------------------------------- /cogs/math.py: -------------------------------------------------------------------------------- 1 | """ 2 | Math Module 3 | """ 4 | 5 | import discord 6 | import asyncio 7 | from discord.ext import commands 8 | 9 | from libs import config 10 | from cogs.libs.math import evaluate 11 | 12 | class Math(commands.Cog): 13 | """ 14 | Commands related to the bot. 15 | """ 16 | def __init__(self, bot): 17 | self.bot = bot 18 | 19 | @commands.command(name='math', aliases=['Math', 'eval', 'e']) 20 | async def math(self, ctx, *, source=None): 21 | """ 22 | Math Interpreter 23 | """ 24 | await ctx.trigger_typing() 25 | if source is None: 26 | await ctx.send(f"> You need provide some input. see `{config.prefix}help math`") 27 | return 28 | 29 | result = evaluate(source) 30 | embed = discord.Embed(title="💡 Billy's Math Interpreter", color = discord.Color.dark_theme()) 31 | 32 | if result is not None: 33 | embed.add_field(name='Output:', value=f"> {result}\n") 34 | else: 35 | embed.add_field(name='Runtime Error', value="> Recheck what you typed.\n") 36 | 37 | embed.set_footer(text="Copyright (c) 2021 Basement Team") 38 | await ctx.send(embed=embed) 39 | 40 | def setup(bot): 41 | bot.add_cog(Math(bot)) 42 | -------------------------------------------------------------------------------- /cogs/minecraft.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from discord import Embed, Color 4 | 5 | from mcstatus import MinecraftServer 6 | 7 | 8 | class Minecraft(commands.Cog): 9 | def __init__(self, bot): 10 | self.bot = bot 11 | 12 | @commands.group(name="mc") 13 | async def mc(self, ctx): 14 | pass 15 | 16 | @commands.command(name="coord", aliases=["coordinates", "pos", "coords"]) 17 | async def coord(self, ctx, x=0, y=0, z=0): 18 | await ctx.send(embed=Embed(title="", description=f"X: **{x}**, Y: **{y}**, Z: **{z}**", color=Color.dark_theme())) 19 | 20 | @mc.command(name="ip", aliases=["serverip", "mcip"]) 21 | async def ip(self, ctx): 22 | embed = Embed(title="Basement Minecraft Servers", description="__**Info**__\nYour Minecraft version should match **1.17**.", color=Color.dark_theme()) 23 | embed.add_field(name="Server 1", value="**IP Address**:`billysbasement.aternos.me`\n**OP**:<@!621397007332016145>", inline=False) 24 | embed.add_field(name="Server 2", value="**IP Address**:`51.79.163.221:25583`\n**OP**:<@!517998886141558786>", inline=False) 25 | await ctx.send(embed=embed) 26 | 27 | @mc.command(name="serverinfo", aliases=["sinfo", "mcinfo"]) 28 | async def serverinfo(self, ctx): 29 | status1 = None 30 | status2 = None 31 | try: 32 | server1 = MinecraftServer.lookup("billysbasement.aternos.me:54987") 33 | status1 = server1.status() 34 | except: 35 | pass 36 | try: 37 | server2 = MinecraftServer.lookup("147.135.71.70:25592") 38 | status2 = server2.status() 39 | except: 40 | pass 41 | 42 | embed = Embed(title="Basement Minecraft Servers Info", description="__**Info**__\nAsk the OP's for help if you can't join the server.\nPing them if the server is offline and you want to join, they will help you.", color=Color.dark_theme()) 43 | 44 | if status1 is None and status2 is None: 45 | embed.add_field(name="Servers are Offline", value="Sorry both of the servers are offline at the moment. Please Try asking server OP's.", inline=False) 46 | 47 | if status1 is not None: 48 | embed.add_field(name="Server 1", value="**IP Address**: `billysbasement.aternos.me`\n**OP**: <@!621397007332016145>\n**Status**: 🟢 Online\n**Players Online**: {0}\n**Minecraft Version:** {1}\n**Latency**: {2}".format(status1.players.online, status1.version.name, status1.latency), inline=False) 49 | else: 50 | embed.add_field(name="Server 1", value="IP Address: `billysbasement.aternos.me`\nOP: <@!621397007332016145>\nStatus: ⚫ Offline\n".format(), inline=False) 51 | 52 | if status2 is not None: 53 | embed.add_field(name="Server 2", value="**IP Address**: `51.79.163.221:25583`\n**OP**: <@!517998886141558786>\n**Status**: 🟢 Online\n**Players Online**: {0}\n**Minecraft Version:** {1}\n**Latency**: {2}".format(status2.players.online, status2.version.name, status2.latency), inline=False) 54 | else: 55 | embed.add_field(name="Server 2", value="IP Address: `51.79.163.221:25583`\nOP: <@!517998886141558786>\nStatus: ⚫ Offline\n".format(), inline=False) 56 | 57 | embed.set_footer(text = f"Requested by {ctx.author.name}", icon_url = ctx.author.avatar_url) 58 | 59 | await ctx.send(embed=embed) 60 | 61 | @mc.command(name="playerlist", aliases=['players', 'onlineplayers', 'playerslist']) 62 | async def playerlist(self, ctx): 63 | status1 = None 64 | status2 = None 65 | 66 | msg1 = "" 67 | msg2 = "" 68 | 69 | try: 70 | server = MinecraftServer.lookup("billysbasement.aternos.me") 71 | status1 = server.status() 72 | except Exception as e: 73 | print(e) 74 | # await ctx.send(e) 75 | 76 | try: 77 | server1 = MinecraftServer.lookup("147.135.71.70:25592") 78 | status2 = server1.status() 79 | except Exception as e: 80 | print(e) 81 | # await ctx.send(e) 82 | 83 | try: 84 | if status1 is None: 85 | msg1 += "Server Offline!" 86 | else: 87 | try: 88 | for x in status1.players.sample: 89 | msg1 += f"🔸 {x.name}\n" 90 | except: 91 | msg1 += "\nThere are no players online!" 92 | print(msg1) 93 | except: 94 | msg1 += "..." 95 | 96 | try: 97 | if status2 is None: 98 | msg2 += "Server Offline!" 99 | else: 100 | try: 101 | for x in status2.players.sample: 102 | msg2 += f"🔹 {x.name}\n" 103 | except: 104 | msg2 += "\nThere are no players online!" 105 | print(msg2) 106 | except: 107 | msg2 += "..." 108 | 109 | if msg1 == "" or msg1 is None: 110 | msg1 += "..." 111 | if msg2 == "" or msg2 is None: 112 | msg2 += "..." 113 | 114 | # await ctx.send(msg1) 115 | # await ctx.send(msg2) 116 | em = discord.Embed(title="Online Players", color=discord.Color.dark_theme()) 117 | em.add_field(name="billysbasement.aternos.me", value=msg1, inline=False) 118 | em.add_field(name="147.135.71.70:25592", value=msg2, inline=False) 119 | await ctx.send(embed=em) 120 | 121 | def setup(bot): 122 | bot.add_cog(Minecraft(bot)) 123 | -------------------------------------------------------------------------------- /cogs/mod.py: -------------------------------------------------------------------------------- 1 | """ 2 | Mod module 3 | """ 4 | 5 | import discord 6 | import asyncio 7 | from discord.ext import commands 8 | from discord.ext.commands import has_permissions 9 | from discord.ext.commands.cooldowns import BucketType 10 | import requests, json 11 | from datetime import datetime 12 | import pymongo 13 | from pymongo import MongoClient 14 | 15 | from libs import config 16 | 17 | cluster = MongoClient(config.MONGO_URL) 18 | repdb = cluster["ReputationData"] 19 | 20 | def rsetup(col): 21 | col = str(col) 22 | return repdb[col] 23 | 24 | def reputation(userid, collection): 25 | query = {"_id": userid} 26 | users = collection.find(query) 27 | return users[0]["reputation"] 28 | 29 | def getEmbed(Title, msg): 30 | embed = discord.Embed(title=Title, description=msg, color=discord.Color.dark_theme()) 31 | return embed 32 | 33 | def does_not_exist(userid, collection): 34 | check_query = { "_id": userid } 35 | return collection.count_documents(check_query) == 0 36 | 37 | 38 | class Mod(commands.Cog): 39 | def __init__(self, bot): 40 | self.bot = bot 41 | 42 | class count_num: 43 | def __init__(self, client): 44 | client.value = 0 45 | 46 | def __ge__(self, other: int): 47 | return client.value >= other 48 | 49 | def add(self, client): 50 | client.value += 1 51 | return client.value 52 | 53 | async def get_muted_role(self, guild): 54 | muted_role = discord.utils.get(guild.roles, name='Muted') 55 | if muted_role is None: 56 | muted_permissions = discord.Permissions() 57 | muted_permissions.send_messages = False 58 | muted_permissions.add_reactions = False 59 | muted_role = await guild.create_role( 60 | name='Muted', 61 | permissions=muted_permissions, 62 | color=discord.Color.dark_red() 63 | ) 64 | 65 | return muted_role 66 | 67 | async def log( 68 | self, 69 | ctx, 70 | desc, 71 | title='**Moderation**', 72 | color=0xff0000, 73 | **kwargs 74 | ): 75 | 76 | guild = ctx.guild 77 | log_embed = discord.Embed( 78 | title=title, 79 | description=desc, 80 | color=color 81 | ) 82 | for key, value in kwargs.items(): 83 | if key == 'fields': 84 | for field in value: 85 | if len(field) == 2: 86 | log_embed.add_field( 87 | name=field[0], 88 | value=field[1] 89 | ) 90 | else: 91 | log_embed.add_field( 92 | name=field[0], 93 | value=field[1], 94 | inline=field[2] 95 | ) 96 | if key == 'showauth': 97 | if value: 98 | author = ctx.author 99 | disp_name = author.display_name 100 | icon_url = author.avatar_url 101 | log_embed.set_author( 102 | name=disp_name, 103 | icon_url=icon_url 104 | ) 105 | log_embed.set_thumbnail( 106 | url=icon_url 107 | ) 108 | now = datetime.now() 109 | log_embed.timestamp = now 110 | log_channel = discord.utils.get(guild.text_channels, name="billy-logs") 111 | await log_channel.send(embed=log_embed) 112 | 113 | 114 | @commands.command(name='kick', aliases=['k']) 115 | @has_permissions(kick_members=True) 116 | async def kick(self, ctx, user: discord.Member, *_): 117 | '''Kick a user. 118 | Example Usage: kick [reason] // Kicks reason''' 119 | msg = ctx.message 120 | author = ctx.author 121 | try: 122 | reason = msg.content.split(None, 1)[1] 123 | found_reason = True 124 | except IndexError: 125 | found_reason = False 126 | if found_reason: 127 | await self.log( 128 | ctx, 129 | f'<@{author.id} kicked <@{user.id}>', 130 | fields=[ 131 | ('**Reason:**', reason) 132 | ] 133 | ) 134 | await user.kick(reason=reason) 135 | else: 136 | await self.log( 137 | ctx, 138 | f'<@{author.id}> kicked <@{user.id}>' 139 | ) 140 | await user.kick() 141 | print("Event. ", user, " kicked! by ", author) 142 | 143 | 144 | @commands.command(name='ban') 145 | @has_permissions(ban_members=True) 146 | async def ban(self, ctx, user: discord.Member, *argv): 147 | '''Ban a user. 148 | Example Usage: 149 | ban [reason]]// Bans from the guild for the reason [reason]''' 150 | fields = [] 151 | guild = ctx.guild 152 | argv = list(argv) 153 | 154 | author = ctx.author 155 | if len(argv) > 0: 156 | reason = ' '.join(argv) 157 | fields.append( 158 | ('**Reason:**', reason, True) 159 | ) 160 | 161 | await self.log( 162 | ctx, 163 | f'<@{author.id}> banned <@{user.id}>', 164 | fields=fields, 165 | showauth=True 166 | ) 167 | embed = discord.Embed( 168 | title='**Ban**', 169 | description=f'<@{user.id}> has been banned.', 170 | color=0xff0000 171 | ) 172 | await user.ban() 173 | await ctx.send(embed=embed) 174 | print("Event. ", user, " banned! by ", author) 175 | 176 | 177 | @commands.command(name='mute', aliases=['silence']) 178 | @has_permissions(kick_members=True) 179 | async def mute(self, ctx, user: discord.Member, time=None, *argv): 180 | '''Mute a user so that they cannot send messages anymore. 181 | Example Usage: 182 | mute [reason] // Mutes permanately for reason [reason]''' 183 | 184 | fields = [] 185 | guild = ctx.guild 186 | argv = list(argv) 187 | argv.insert(0, time) 188 | 189 | author = ctx.author 190 | if len(argv) > 0: 191 | reason = ' '.join(argv) 192 | fields.append( 193 | ('**Reason:**', reason, True) 194 | ) 195 | else: 196 | fields.append( 197 | ('**Reason:**', "for some reason", True) 198 | ) 199 | 200 | 201 | await self.log( 202 | ctx, 203 | f'<@{author.id}> muted <@{user.id}>', 204 | fields=fields, 205 | showauth=True 206 | ) 207 | muted_role = await self.get_muted_role(guild) 208 | await user.add_roles(muted_role) 209 | embed = discord.Embed( 210 | title='**Mute**', 211 | description=f'<@{user.id}> has been muted.', 212 | color=0xff0000 213 | ) 214 | await ctx.send(embed=embed) 215 | print("Event. ", user, " muted! by ", author, ' Reason: ', reason) 216 | 217 | 218 | @commands.command(name='unmute') 219 | @has_permissions(kick_members=True) 220 | async def unmute(self, ctx, user: discord.Member, *argv): 221 | '''Unmute a user. 222 | Example usage: 223 | unmute oops wrong person // Unbans for the reason oops wrong person.''' 224 | fields = [] 225 | guild = ctx.guild 226 | 227 | author = ctx.author 228 | try: 229 | reason = ' '.join(argv) 230 | fields.append( 231 | ('**Reason:**', reason, True) 232 | ) 233 | except IndexError: 234 | pass 235 | 236 | await self.log( 237 | ctx, 238 | f'<@{author.id}> unmuted <@{user.id}>', 239 | fields=fields, 240 | showauth=True 241 | ) 242 | muted_role = await self.get_muted_role(guild) 243 | await user.remove_roles(muted_role) 244 | print("Event. ", user, " unmuted! by ", author, ' Reason: ', reason) 245 | 246 | 247 | @commands.command(name='purge') 248 | @has_permissions(manage_messages=True) 249 | async def purge(self, ctx, ammount: int, user: discord.Member = None): 250 | ''' 251 | Bulk delete messages in a channel. 252 | Example Usage: 253 | purge 20 // Purges the last 20 messages in the channel 254 | purge 20 @baduser#1234 // Purge the last 20 messages by @baduser#1234 in the channel.''' 255 | channel = ctx.channel 256 | if ammount > 200: 257 | await ctx.send("You can't delete more than 200 messages at at time.") 258 | 259 | def check_user(message): 260 | return message.author == user 261 | 262 | msg = await ctx.send('Purging messages.') 263 | if user is not None: 264 | msg_number = self.bot.count_num() 265 | 266 | def msg_check(x): 267 | 268 | if msg_number >= ammount: 269 | return False 270 | if x.id != msg.id and x.author == user: 271 | msg_number.add() 272 | return True 273 | return False 274 | 275 | msgs = await channel.purge( 276 | limit=100, 277 | check=msg_check, 278 | bulk=True 279 | ) 280 | await self.log( 281 | ctx, 282 | f"{len(msgs)} of <@{user.id}>'s messages were " 283 | f"deleted by <@{ctx.author.id}>", 284 | '**Message Purge**', 285 | showauth=True 286 | ) 287 | print("Event. #Message Purge ", len(msgs), " of ", user.name,'s messages were deleted by ', ctx.author.name) 288 | # print(msg in msgs, len(msgs)) 289 | else: 290 | 291 | msgs = await channel.purge( 292 | limit=ammount + 2, 293 | check=lambda x: x.id != msg.id, 294 | bulk=True 295 | ) 296 | await self.log( 297 | ctx, 298 | f'{len(msgs)} messages were deleted by <@{ctx.author.id}>', 299 | '**Message Purge**', 300 | showauth=True 301 | ) 302 | print("Event. #Message Purge ", len(msgs), 'messages were deleted by ', ctx.author.name) 303 | # print(msg in msgs) 304 | 305 | await msg.edit(content='Deleted messages.') 306 | await asyncio.sleep(2) 307 | await msg.delete() 308 | 309 | @commands.command(name='slowmode', aliases=["slow"]) 310 | @has_permissions(manage_messages=True) 311 | async def slowmode(self, ctx, seconds: int): 312 | try: 313 | await ctx.channel.edit(slowmode_delay=seconds) 314 | embed = discord.Embed(title="Slowmode", description=f"Set the slowmode delay in this channel to {seconds} seconds!", color=discord.Color.blue()) 315 | except: 316 | embed = discord.Embed(title="Slowmode", description="Couldn't set slowmode!", color=discord.Color.red()) 317 | await ctx.send(embed=embed) 318 | 319 | @commands.command(name='activity', aliases=["presence", "changeactivity"]) 320 | @has_permissions(manage_messages=True) 321 | async def activity(self, ctx, *, _activity="beanson"): 322 | await self.bot.change_presence(activity=discord.Game(name=_activity)) 323 | await ctx.send(f"activity changed to {_activity}") 324 | 325 | @commands.command(name="rep", aliases=['reputation']) 326 | @has_permissions(manage_messages=True) 327 | async def rep(self, ctx, userr: discord.Member = None, score: int = None): 328 | """check/give reputation""" 329 | await ctx.trigger_typing() 330 | if not userr: 331 | userr = ctx.author 332 | 333 | collection = rsetup(ctx.guild.id) 334 | user = userr.id 335 | username = str(userr) 336 | score = score 337 | 338 | # data doesn't exist 339 | if (does_not_exist(userr.id, collection)): 340 | if not score: 341 | post = { 342 | '_id': user, 343 | 'name': username, 344 | 'reputation': 10 345 | } 346 | collection.insert_one(post) 347 | try: 348 | current_reputation = reputation(user, collection) 349 | except: 350 | return 351 | message = f"{userr.name} has {current_reputation} reputation in this server." 352 | embed = getEmbed("Reputation", message) 353 | await ctx.send(embed=embed) 354 | else: 355 | post = { 356 | '_id': user, 357 | 'name': username, 358 | 'reputation': score 359 | } 360 | collection.insert_one(post) 361 | 362 | try: 363 | current_reputation = reputation(user, collection) 364 | except: 365 | return 366 | message = f"{userr.name} has currently {current_reputation} reputation." 367 | embed = getEmbed("Reputation", message) 368 | await ctx.send(embed=embed) 369 | # data do exist 370 | else: 371 | if not score: 372 | try: 373 | current_reputation = reputation(user, collection) 374 | except: 375 | return 376 | message = f"{userr.name} has {current_reputation} reputation in this server." 377 | embed = getEmbed("Reputation", message) 378 | await ctx.send(embed=embed) 379 | else: 380 | try: 381 | current_reputation = reputation(user, collection) 382 | except: 383 | return 384 | current_reputation += score 385 | collection.update_one({"_id":user}, {"$set":{"name": username,"reputation": current_reputation}}) 386 | 387 | try: 388 | current_reputation = reputation(user, collection) 389 | except: 390 | return 391 | message = f"{userr.name} now has {current_reputation} reputation." 392 | embed = getEmbed("Reputation", message) 393 | await ctx.send(embed=embed) 394 | await self.log( 395 | ctx, 396 | f"{user.name}'s reputation data has been updated by {ctx.author.name}.", 397 | '**Reputation**', 398 | showauth=True 399 | ) 400 | 401 | @commands.command(name="reset", aliases=['r', 'Reset']) 402 | @has_permissions(manage_messages=True) 403 | async def reset(self, ctx, userr: discord.Member): 404 | user = userr.id 405 | collection = rsetup(ctx.guild.id) 406 | current_reputation = 10 407 | collection.update_one({"_id":user}, {"$set":{"reputation": current_reputation}}) 408 | message = f"{user.name}'s reputation data has been cleaned." 409 | embed = getEmbed("User Data Reset", message) 410 | await ctx.send(embed=embed) 411 | await ctx.message.add_reaction("✅") 412 | await self.log( 413 | ctx, 414 | f"{user.name}'s reputation data has been cleaned by {ctx.author.name}.", 415 | '**User Data Reset**', 416 | showauth=True 417 | ) 418 | 419 | @commands.command(name="thanks", aliases=['thx', 'thnx']) 420 | @commands.guild_only() 421 | @commands.cooldown(rate=1, per=600, type=BucketType.user) 422 | async def Thanks(self, ctx, user: discord.Member): 423 | if ctx.author.id == user.id: 424 | return 425 | collection = rsetup(ctx.guild.id) 426 | user = user.id 427 | username = str(user) 428 | check_query = { "_id": user } 429 | 430 | 431 | if (collection.count_documents(check_query) == 0): 432 | post = { 433 | '_id': user, 434 | 'name': username, 435 | 'reputation': 11 436 | } 437 | collection.insert_one(post) 438 | else: 439 | try: 440 | current_reputation = reputation(user, collection) 441 | except: 442 | return 443 | current_reputation += 1 444 | collection.update_one({"_id":user}, {"$set":{"name": username,"reputation": current_reputation}}) 445 | await ctx.message.add_reaction("✅") 446 | await self.log( 447 | ctx, 448 | f"{user.name}'s got thanked by {ctx.author.name}.", 449 | '**Thanks Reputation**', 450 | showauth=True 451 | ) 452 | 453 | @commands.command(name="myrep", aliases=['myreputation']) 454 | async def myrep(self, ctx, userr: discord.Member=None): 455 | """check reputation""" 456 | await ctx.trigger_typing() 457 | if not userr: 458 | userr = ctx.author 459 | 460 | collection = rsetup(ctx.guild.id) 461 | user = userr.id 462 | username = str(userr) 463 | 464 | current_reputation = 0 465 | 466 | # user's data doesn't exist in db 467 | if (does_not_exist(user, collection)): 468 | post = { 469 | '_id': user, 470 | 'name': username, 471 | 'reputation': 10 472 | } 473 | collection.insert_one(post) 474 | current_reputation = 10 475 | # user's data does exist in the db 476 | else: 477 | try: 478 | current_reputation = reputation(user, collection) 479 | collection.update_one({"_id":user}, {"$set":{"name": username}}) 480 | except: 481 | return 482 | message = f"{userr.name} has {current_reputation} reputation in this server." 483 | embed = discord.Embed(title="Reputation", description=message, color=discord.Color.dark_theme()) 484 | await ctx.send(embed=embed) 485 | 486 | @commands.command(name="leaderboard", aliases=['top', 'reptop']) 487 | async def leaderboard(self, ctx): 488 | collection = rsetup(ctx.guild.id) 489 | embed = discord.Embed(color=discord.Color.dark_theme()) 490 | holder = "" 491 | sorted_users = collection.find().sort("reputation", pymongo.DESCENDING) 492 | 493 | holder += f"🥇 **{sorted_users[0]['reputation']}** - {sorted_users[0]['name']}\n" 494 | holder += f"🥈 **{sorted_users[1]['reputation']}** - {sorted_users[1]['name']}\n" 495 | holder += f"🥉 **{sorted_users[2]['reputation']}** - {sorted_users[2]['name']}\n" 496 | holder += f"🏅 **{sorted_users[3]['reputation']}** - {sorted_users[3]['name']}\n" 497 | holder += f"🏅 **{sorted_users[4]['reputation']}** - {sorted_users[4]['name']}\n" 498 | 499 | embed.add_field(name="Reputation Leaderboard", value=holder) 500 | await ctx.send(embed=embed) 501 | 502 | 503 | def setup(bot): 504 | bot.add_cog(Mod(bot)) 505 | -------------------------------------------------------------------------------- /cogs/modmail.py: -------------------------------------------------------------------------------- 1 | """ 2 | ModMail module 3 | """ 4 | 5 | import discord 6 | import asyncio 7 | from discord.ext import commands 8 | from discord.ext.commands import has_permissions, MissingPermissions, BadArgument 9 | 10 | from libs import config 11 | 12 | 13 | class ModMail(commands.Cog): 14 | def __init__(self, bot): 15 | self.bot = bot 16 | 17 | @commands.command() 18 | @commands.guild_only() 19 | @has_permissions(administrator=True) 20 | async def setup(self, ctx): 21 | await ctx.trigger_typing() 22 | await asyncio.sleep(2) 23 | channel = discord.utils.get(ctx.guild.channels, name=config.mails_channel_name) 24 | if channel is None: 25 | guild = ctx.guild 26 | overwrites = { 27 | guild.default_role: discord.PermissionOverwrite(read_messages=False), 28 | guild.me: discord.PermissionOverwrite(read_messages=True) 29 | } 30 | 31 | mod_channel = await guild.create_text_channel(config.mails_channel_name, overwrites=overwrites) 32 | embed = discord.Embed( 33 | title='Setup completed', 34 | description=f"{mod_channel.name} is created.", 35 | color = discord.Color.green(), 36 | ) 37 | else: 38 | mod_channel = channel 39 | embed = discord.Embed( 40 | title='Setup completed', 41 | description=f"{mod_channel.name} exists", 42 | color = discord.Color.blue(), 43 | ) 44 | 45 | await ctx.send(embed=embed) 46 | 47 | overwrites2 = { 48 | guild.default_role: discord.PermissionOverwrite(read_messages=False), 49 | guild.me: discord.PermissionOverwrite(read_messages=True) 50 | } 51 | try: 52 | mod_logs = await guild.create_text_channel("mod-logs", overwrites=overwrites2) 53 | except: 54 | print("couldn't create a mod-logs channel, maybe it exists") 55 | 56 | @setup.error 57 | async def setup_error(self, ctx, error): 58 | if isinstance(error, MissingPermissions): 59 | embed = discord.Embed( 60 | title='Setup', 61 | description="You don't have permissions to manage mod mails", 62 | color = discord.Color.red(), 63 | ) 64 | await ctx.send(embed=embed) 65 | # else: 66 | # embed = discord.Embed( 67 | # title='Server Only Command', 68 | # description="You can't use this command here", 69 | # color = discord.Color.red(), 70 | # ) 71 | # await ctx.send(embed=embed) 72 | 73 | @commands.Cog.listener() 74 | async def on_message(self, message): 75 | #print(f"{message.author} sent : {message.content}") 76 | if not message.content.startswith('[]'): 77 | if isinstance(message.channel, discord.channel.DMChannel) and message.author != self.bot.user: 78 | try: 79 | # send to server 80 | embed_to = discord.Embed( 81 | title='Mod Mail Received', 82 | description=f"sent by: {message.author} \nmessage: {message.content} \nuser id: {message.author.id}", 83 | color = discord.Color.blue(), 84 | ) 85 | embed_to.set_footer(text="use reply ") 86 | await config.mails_channel.send(embed=embed_to) 87 | 88 | # report result to user 89 | embed_reply = discord.Embed( 90 | title='Mail sent', 91 | description=f"Your message has been sent to moderators", 92 | color = discord.Color.green(), 93 | ) 94 | await message.author.send(embed=embed_reply) 95 | except: 96 | # report result to user 97 | embed_reply = discord.Embed( 98 | title='Sorry 😔', 99 | description=f"I couldn't send your message to moderators", 100 | color = discord.Color.red(), 101 | ) 102 | await message.author.send(embed=embed_reply) 103 | 104 | @commands.command() 105 | @commands.guild_only() 106 | async def reply(self, ctx, id: int = 0, *, msg: str = "moderator is replying..."): 107 | await ctx.trigger_typing() 108 | message = msg 109 | user = self.bot.get_user(id) 110 | if user is not None: 111 | # EMBED report result to user 112 | embed_reply = discord.Embed( 113 | title='Reply from Moderator', 114 | # title=f'Replied by {ctx.author.name}', 115 | description=f"{message}", 116 | color = discord.Color.blue(), 117 | ) 118 | await user.send(embed=embed_reply) 119 | 120 | # EMBED show results to author 121 | embed_result= discord.Embed( 122 | title='Message sent succesfully', 123 | description=f"message sent to {user.name}", 124 | color = discord.Color.green(), 125 | ) 126 | await ctx.send(embed=embed_result) 127 | elif user is None: 128 | # EMBED show results to author 129 | embed_result = discord.Embed( 130 | title='Failed to send message', 131 | description=f"can't find user with the id {id}", 132 | color = discord.Color.red(), 133 | ) 134 | await ctx.send(embed=embed_result) 135 | 136 | @reply.error 137 | async def reply_error(self, ctx, error): 138 | if isinstance(error, BadArgument): 139 | embed = discord.Embed( 140 | title="That's not how you use it", 141 | description="the correct format is reply ", 142 | color = discord.Color.red(), 143 | ) 144 | await ctx.send(embed=embed) 145 | else: 146 | embed = discord.Embed( 147 | title='Syntax error', 148 | description="recheck your command.\nsee help module of the command for details", 149 | color = discord.Color.red(), 150 | ) 151 | await ctx.send(embed=embed) 152 | 153 | #===================================== ADD COG ======================================# 154 | 155 | def setup(bot): # a extension must have a setup function 156 | bot.add_cog(ModMail(bot)) -------------------------------------------------------------------------------- /cogs/money.py: -------------------------------------------------------------------------------- 1 | """ 2 | the main economy-management file. 3 | """ 4 | import discord 5 | from discord.ext import commands 6 | from discord.ext.commands import Bot, BucketType 7 | 8 | from .economy.data import sync_data 9 | from .economy.functions import * 10 | 11 | class Economy(commands.Cog): 12 | def __init__(self, bot): 13 | self.bot = bot 14 | sync_data() 15 | 16 | 17 | @commands.command(name="top", aliases=['leaderboard', 'rich']) 18 | async def leaderboard(self, ctx): 19 | """ 20 | shows the leaderboard based on amount of wallet money. 21 | """ 22 | await leaderboard(ctx=ctx) 23 | 24 | 25 | # noinspection SpellCheckingInspection 26 | @commands.command(name="work") 27 | @commands.cooldown(1, 3600, BucketType.user) 28 | async def work(self, ctx): 29 | """ 30 | The main work category 31 | """ 32 | await work(ctx=ctx) 33 | 34 | 35 | # noinspection SpellCheckingInspection 36 | @commands.command(name="worklist", aliases=["jobs", "work_list"]) 37 | async def work_list(self, ctx): 38 | """ 39 | shows the list of available jobs and their respected salary 40 | """ 41 | await work_list(ctx) 42 | 43 | 44 | @commands.command(name="apply", aliases=['workas', 'apply for', 'workapply', 'join', 'work_as', 'work_apply']) 45 | async def apply(self, ctx, *, job=None): 46 | """ 47 | apply for a job, which is in work list. 48 | :param ctx: 49 | :param job: 50 | """ 51 | await apply(ctx, job) 52 | 53 | 54 | @commands.command(name="beg", aliases=["Beg"]) 55 | async def beg(self, ctx): 56 | """ 57 | check for donations. 58 | """ 59 | await beg(ctx=ctx) 60 | 61 | 62 | @commands.command(name="balance", aliases=['bal', 'Balance']) 63 | async def balance(self, ctx, _member: discord.Member = None): 64 | """ 65 | check the balance of the specified user, or the context author. 66 | :param _member: 67 | """ 68 | await balance(ctx=ctx, _member=_member) 69 | 70 | 71 | @work.error 72 | async def work_error(self, ctx, error): 73 | if isinstance(error, commands.CommandOnCooldown): 74 | cool_down_message = "You need to wait **1 hour** until you can work again!" 75 | await ctx.send(cool_down_message) 76 | else: 77 | pass 78 | 79 | 80 | @commands.command(name="steal", aliases=["rob", "Rob", "Steal"]) 81 | async def steal(self, ctx, _member: discord.Member = None): 82 | """ 83 | steal from other users. 84 | :param _member: 85 | :param ctx: 86 | """ 87 | await steal(ctx, _member) 88 | 89 | 90 | # TODO: make deposit command 91 | # TODO: make withdraw 92 | @commands.command(name="deposit", aliases=["dep", "Dep", "Deposit"]) 93 | async def deposit(self, ctx, amount: int = None, part: str = None): 94 | """ 95 | deposit money to bank account. 96 | :param ctx: 97 | :param amount: 98 | :param part: 99 | """ 100 | await deposit(ctx=ctx) 101 | 102 | def setup(bot): 103 | bot.add_cog(Economy(bot)) 104 | 105 | -------------------------------------------------------------------------------- /cogs/news.py: -------------------------------------------------------------------------------- 1 | """ 2 | News Module 3 | """ 4 | 5 | import random 6 | import json 7 | 8 | import discord 9 | from discord.ext import commands, tasks 10 | 11 | from libs.httpsession import http_session 12 | from libs import config 13 | 14 | 15 | FAILED_ALERTS = [ 16 | "What the hell man, {0}", 17 | "Ayo {0}, what have you done idiot, news no workey!", 18 | "Sorry peeps, its because of that dumb {0}, no news today sadly.", 19 | "Everyone blame {0} for this 🏃🏻‍♂️", 20 | "Smhmhmhmh {0}, why news no workey ⁉", 21 | "You better fix news {0}, or imma come to yer house", 22 | "For god sake {0} will you ever fix news", 23 | "Yo {0}, looks like news not workin'", 24 | "Naw {0}, news is down", 25 | "Sorry everyone, no news today #blame{0}", 26 | "baka {0}, your news thing is not working again", 27 | "{0} can you please fix news.", 28 | "Looks like i need to visit {0} today, FIX NEWS YOU IDIOT!", 29 | "You better fix news {0}, or imma break yer cookie jar", 30 | ] 31 | 32 | # TODO: remove api key, add it as a secret 33 | NEWS_WORLD = f"https://api.nytimes.com/svc/topstories/v2/world.json?api-key={config.NYT_TOKEN}" 34 | 35 | def base_embed(): 36 | return discord.Embed( 37 | title=f"📰 Basement Daily", 38 | description="Hows it going everyone ☕ Here is your todays newspaper", 39 | color=discord.Color.dark_theme() 40 | ) 41 | 42 | color = False 43 | debug = False 44 | 45 | def rand(s, e, c): 46 | ns = [] 47 | while True: 48 | if len(ns) > c: 49 | return ns 50 | n = (random.randint(s, e)) 51 | if n not in ns: 52 | ns.append(n) 53 | 54 | def bullet(): 55 | global color 56 | color = not color 57 | if color: 58 | return '🔸' 59 | else: 60 | return '🔹' 61 | 62 | class News(commands.Cog): 63 | """ 64 | NYT News 65 | """ 66 | def __init__(self, bot): 67 | self.bot = bot 68 | 69 | self.news.start() 70 | 71 | @tasks.loop(hours=24) 72 | async def news(self): 73 | """ 74 | NYT News 75 | """ 76 | await self.send_news() 77 | 78 | @commands.command(name="news", aliases=["sn", "send_news", "snm"]) 79 | @commands.is_owner() 80 | async def send_news_manually(self, ctx): 81 | await self.send_news() 82 | 83 | async def send_news(self): 84 | # news channel not configured 85 | if config.news_channel is None: 86 | return 87 | 88 | # Fetch Data 89 | # ---- 90 | async with http_session.get(url=NEWS_WORLD) as response: 91 | if response.status == 200: 92 | data = await response.json() 93 | else: 94 | print(f'Status code is not 200, it is {response.status}') 95 | if debug: 96 | err = discord.Embed( 97 | title="ERROR", 98 | color=Color.dark_theme() 99 | ) 100 | await config.news_channel.send(embed=err) 101 | return 102 | 103 | # Data Extraction 104 | # ---- 105 | num_results = int(data['num_results']) 106 | results = data['results'] 107 | selected = rand(0, num_results - 1, 5) 108 | date = data['last_updated'][:10] 109 | 110 | if debug: 111 | print(f"Number of results: {num_results}\nSelected: {selected}") 112 | 113 | # Prepare Embed 114 | # ---- 115 | embed = base_embed() 116 | for selection in selected: 117 | result = results[selection] 118 | title = result['title'] 119 | des = result['abstract'] 120 | if debug: 121 | print(f"length: {len(des)}") 122 | embed.add_field(name=f"{bullet()} {title}", value=f" {des} " if len(des) < 200 else f" {des}... ", inline=False) 123 | 124 | embed.set_footer(text=data['copyright']) 125 | 126 | try: 127 | await config.news_channel.send(f"☕ __**{date}**__") 128 | await config.news_channel.send(embed=embed) 129 | except Exception as e: 130 | if debug: 131 | bad = discord.Embed( 132 | title="BAD", 133 | description=e, 134 | color=discord.Color.dark_theme() 135 | ) 136 | await config.news_channel.send(embed=bad) 137 | print(e) 138 | 139 | # embed = Embed( 140 | # title="News Failure", 141 | # description=f"```py\n{e}\n```", 142 | # color=discord.Color.dark_theme() 143 | # ) 144 | # await ctx.send(embed=embed) 145 | await config.news_channel.send(f"{random.choice(FAILED_ALERTS).format(config.owner.mention)}") 146 | 147 | def setup(bot): 148 | bot.add_cog(News(bot)) 149 | -------------------------------------------------------------------------------- /cogs/owner.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | from libs import httpsession 5 | 6 | class Owner(commands.Cog): 7 | def __init__(self, bot): 8 | self.bot = bot 9 | 10 | @commands.command(name="closehttp", aliases=["closesession"]) 11 | @commands.is_owner() 12 | async def close_http_session(self, ctx): 13 | await httpsession.close_session() 14 | await ctx.send("> Closed HTTP session.") 15 | 16 | def setup(bot): 17 | bot.add_cog(Owner(bot)) -------------------------------------------------------------------------------- /cogs/rules.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | from discord.ext.commands.cooldowns import BucketType 4 | 5 | 6 | rules = [ 7 | "Refrain from being rude to other members.", 8 | "Please avoid controversial topics!", 9 | "Use collaboration channel for recruiting teams.", 10 | "Keep it clean.", 11 | "Don't ask to ask, Just ask.", 12 | "Use the template for collaboration Posts.", 13 | "Follow the Discord Terms of Services!", 14 | "Advertise only in Promotion channel ", 15 | "Space out your Ads.", 16 | "Google/Bing before asking.", 17 | "English only.", 18 | "Follow Wheaton's law." 19 | ] 20 | 21 | ruleinfo = [ 22 | "They're people too! If you have an issue with someone, call for a staff member or continue talking with that person in DMs. Discriminatory jokes and language, hate speech (which calls out a group by their age, race, gender), etc. are strictly prohibited. Any kind of verbal abuse, insults, or threats towards others is strictly prohibited.", 23 | "Avoid controversial topics such as Religion, Politics, Suicide, etc. This is a programmers' server. There is a time and place for everything and this server ain't the place!", 24 | "If you want work done for you, you can find people to work with you in #collaboration channel.", 25 | "Displaying offensive, derogatory, or sexually explicit content is not allowed.", 26 | "Don't ask 'can someone help me', don't ping random users, don't ask for DMs. We are here to help! If you're asking in the Development & Help category, you can skip the needless introductions. We'd much rather you just ask your question outright.", 27 | "When posting in #collaboration channel, please try to follow the format provided.(check pinned messages).", 28 | "This includes no piracy links, although discussions are fine.", 29 | "Advertise gamedev-programming-related content in #promotion channel. Showcase your works in progress in #showcase. Any non-programmer-gamedev-related content will be deleted. (NOTE: Discord server links are not allowed, please reach out to the staff if you'd like to have partnerships).", 30 | "Space out your posts in #promotion and #showcase channels. Give other people a chance to be seen.", 31 | "Before asking for help, please google/bing your issue first, attempt to solve it yourself, and then ask. You learn more this way than being spoon-fed!", 32 | "We are an English community around English content with English speaking moderation team. Everyone here understands English, other languages not so much. You are only allowed to speak other languages in the spam/misc category.", 33 | "Do not be a idiot." 34 | ] 35 | 36 | 37 | class Rules(commands.Cog): 38 | """ 39 | This cog provides server rules related commands, such as showing nth rule, sending all rules, etc. 40 | """ 41 | def __init__(self, bot): 42 | self.bot = bot 43 | 44 | @commands.command(name="rule", aliases=["ruleno"]) 45 | @commands.guild_only() 46 | @commands.cooldown(rate=1, per=3, type=BucketType.default) 47 | async def _rule(self, ctx, n: int=None): 48 | """ 49 | Displays the nth rule, if exits 50 | """ 51 | 52 | await ctx.trigger_typing() 53 | 54 | embed = None 55 | 56 | if n is not None: 57 | try: 58 | embed = discord.Embed(title=rules[n - 1], description=ruleinfo[n - 1], color = discord.Color.dark_theme()) 59 | embed.set_footer(text=f'rule no. {n}') 60 | except: 61 | embed = discord.Embed(color = discord.Color.dark_theme()) 62 | embed.add_field(name="Rule Not Found", value=f"Rule with index {n} doesn't exist.") 63 | else: 64 | embed = discord.Embed(title='Rule N', color = discord.Color.dark_theme()) 65 | embed.add_field(name="Usage", value="Pass the index of the rule to be shown as an argument as follows...\n ```[]rule [number]```") 66 | 67 | await ctx.send(embed=embed) 68 | 69 | @commands.command(name="rules", aliases=["all_rules", "allrules"]) 70 | @commands.has_permissions(manage_messages=True) 71 | @commands.cooldown(rate=1, per=3, type=BucketType.default) 72 | async def _rules(self, ctx): 73 | """ 74 | Displays all rules. 75 | """ 76 | 77 | await ctx.trigger_typing() 78 | 79 | for i in range(len(rules)): 80 | embed = discord.Embed(title=rules[i], description=f"```{ruleinfo[i]}```", color = discord.Color.dark_theme()) 81 | embed.set_footer(text=f"rule no. {i + 1}/{len(rules)}.") 82 | 83 | await ctx.send(embed=embed) 84 | 85 | 86 | def setup(bot): 87 | bot.add_cog(Rules(bot)) 88 | -------------------------------------------------------------------------------- /cogs/stackoverflow.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from html import unescape 3 | from urllib.parse import quote_plus 4 | 5 | import discord 6 | from discord import Embed, HTTPException, Color 7 | from discord.ext import commands 8 | 9 | from libs.httpsession import http_session 10 | 11 | BASE_URL = "https://api.stackexchange.com/2.2/search/advanced" 12 | SO_PARAMS = { 13 | "order": "desc", 14 | "sort": "activity", 15 | "site": "stackoverflow" 16 | } 17 | SEARCH_URL = "https://stackoverflow.com/search?q={query}" 18 | ERR_EMBED = Embed( 19 | title="Error in fetching results from Stackoverflow", 20 | description=( 21 | "Sorry, there was en error while trying to fetch data from the Stackoverflow website. Please try again in some " 22 | "time. If this issue persists, please contact the staff or send a message in #dev-contrib." 23 | ), 24 | color=Color.dark_theme() 25 | ) 26 | 27 | 28 | class Stackoverflow(commands.Cog): 29 | """Contains command to interact with stackoverflow from discord.""" 30 | 31 | def __init__(self, bot): 32 | self.bot = bot 33 | 34 | @commands.command(aliases=["so"]) 35 | @commands.cooldown(1, 15, commands.cooldowns.BucketType.user) 36 | async def stackoverflow(self, ctx: commands.Context, *, search_query: str) -> None: 37 | """Sends the top 5 results of a search query from stackoverflow.""" 38 | params = SO_PARAMS | {"q": search_query} 39 | async with http_session.get(url=BASE_URL, params=params) as response: 40 | if response.status == 200: 41 | data = await response.json() 42 | else: 43 | logger.error(f'Status code is not 200, it is {response.status}') 44 | await ctx.send(embed=ERR_EMBED) 45 | return 46 | if not data['items']: 47 | no_search_result = Embed( 48 | title=f"No search results found for {search_query}", 49 | color=Color.dark_theme() 50 | ) 51 | await ctx.send(embed=no_search_result) 52 | return 53 | 54 | top5 = data["items"][:5] 55 | encoded_search_query = quote_plus(search_query) 56 | embed = Embed( 57 | title="Search results - Stackoverflow", 58 | url=SEARCH_URL.format(query=encoded_search_query), 59 | description=f"Here are the top {len(top5)} results:", 60 | color=Color.dark_theme() 61 | ) 62 | for item in top5: 63 | embed.add_field( 64 | name=unescape(item['title']), 65 | value=( 66 | f"[⬆ {item['score']} " 67 | f"👀 {item['view_count']} " 68 | f"💬 {item['answer_count']} " 69 | f"🏷 {', '.join(item['tags'][:3])}]" 70 | f"({item['link']})" 71 | ), 72 | inline=False) 73 | embed.set_footer(text="View the original link for more results.") 74 | 75 | try: 76 | await ctx.send(embed=embed) 77 | except HTTPException: 78 | search_query_too_long = Embed( 79 | title="Your search query is too long, please try shortening your search query", 80 | color=Color.dark_theme() 81 | ) 82 | await ctx.send(embed=search_query_too_long) 83 | 84 | 85 | def setup(bot) -> None: 86 | bot.add_cog(Stackoverflow(bot)) 87 | -------------------------------------------------------------------------------- /cogs/user.py: -------------------------------------------------------------------------------- 1 | """ 2 | User module 3 | """ 4 | 5 | import discord 6 | import random 7 | import asyncio 8 | from discord.ext import commands 9 | from discord.ext.commands import has_permissions, MissingPermissions, BadArgument 10 | 11 | import requests, json, pyfiglet 12 | from datetime import timedelta, datetime 13 | 14 | 15 | class User(commands.Cog): 16 | api_key = "bbde6a19c33fb4c3962e36b8187abbf8" 17 | base_url = "http://api.openweathermap.org/data/2.5/weather?" 18 | 19 | def __init__(self, bot): 20 | self.bot = bot 21 | 22 | def get_embed(self, _title, _description, icon): 23 | embed = discord.Embed(title=_title, description=_description, color= discord.Color.dark_theme()) 24 | embed.set_thumbnail(url=icon) 25 | return embed 26 | 27 | 28 | def get_weather(self, city_name): 29 | complete_url = self.base_url + "appid=" + self.api_key + "&q=" + city_name 30 | response = requests.get(complete_url) 31 | x = response.json() 32 | 33 | if x["cod"] != "404": 34 | # store the value of "main" 35 | # key in variable y 36 | y = x["main"] 37 | 38 | # store the value corresponding 39 | # to the "temp" key of y 40 | current_temperature = y["temp"] 41 | 42 | # store the value corresponding 43 | # to the "pressure" key of y 44 | current_pressure = y["pressure"] 45 | 46 | # store the value corresponding 47 | # to the "humidity" key of y 48 | current_humidiy = y["humidity"] 49 | 50 | # store the value of "weather" 51 | # key in variable z 52 | z = x["weather"] 53 | 54 | # store the value corresponding 55 | # to the "description" key at 56 | # the 0th index of z 57 | weather_description = z[0]["description"] 58 | 59 | # print following values 60 | result = ("Temperature (in kelvin unit) = " + str(current_temperature) + "\natmospheric pressure (in hPa unit) = " + str(current_pressure) + "\nhumidity (in percentage) = " + str(current_humidiy) + "\ndescription = " + str(weather_description)) 61 | return result 62 | else: 63 | print(" City Not Found : " + city_name) 64 | return "That city might be in moon" 65 | 66 | 67 | @commands.command() 68 | async def say(self, ctx, *, arg): 69 | async with ctx.channel.typing(): 70 | thing = arg 71 | await (ctx.channel).send(thing) 72 | print("Event: Repeated {ctx.author.name}: ", arg) 73 | 74 | 75 | @commands.command() 76 | async def hi(self, ctx): 77 | async with ctx.channel.typing(): 78 | thing = "hello human!" 79 | await (ctx.channel).send(thing) 80 | print("Event: I said Hi to ", ctx.author.name) 81 | 82 | 83 | @commands.command() 84 | async def info(self, ctx, *, member: discord.Member): 85 | async with ctx.channel.typing(): 86 | await asyncio.sleep(2) 87 | avatar = member.avatar_url 88 | fmt = 'Joined basement on {0.joined_at} \njoined Discord on {0.created_at} \nThis member has {1} roles.' 89 | msg = self.get_embed("Info of {0.display_name}".format(member), fmt.format(member, len(member.roles)), avatar) 90 | await ctx.send(embed=msg) 91 | print(ctx.author.name, " checked info of ", member.name) 92 | 93 | 94 | @info.error 95 | async def info_error(self, ctx, error): 96 | if isinstance(error, commands.BadArgument): 97 | await ctx.send('I could not find that member...') 98 | 99 | 100 | @commands.command(pass_context=True) 101 | async def weather(self, ctx, a: str): 102 | async with ctx.channel.typing(): 103 | msg = self.get_weather(a) 104 | await asyncio.sleep(2) 105 | await ctx.send(embed=discord.Embed(title=f"Weather status at {a}", description=msg, color=discord.Color.dark_theme())) 106 | print("Event. weather checked on user's command: ", ctx.author.name, ", location: ", a) 107 | 108 | 109 | @commands.command() 110 | async def bing(self, ctx): 111 | async with ctx.channel.typing(): 112 | thing = discord.Embed(title="Bong!", description="Sounds like something " + "https://www.bing.com/"+" would know!", color=discord.Color.dark_theme()) 113 | await (ctx.channel).send(embed=thing) 114 | print("Event. I binged, bong! : ", ctx.author.name) 115 | 116 | @commands.command() 117 | async def google(self, ctx): 118 | await ctx.send("It is quite important that you **google your problems before asking** someone. Most of your questions have already been answered at least once online because you are definitely not the only one with this particular question. Additionally, each programming language, API, or program should be well documented in its official documentation. \nRefer to this page: https://duck-dev.github.io/general/how-to-google/") 119 | print("Event. how to google! : ", ctx.author.name) 120 | 121 | 122 | @commands.command() 123 | async def dontasktoask(self, ctx): 124 | async with ctx.channel.typing(): 125 | thing = discord.Embed(title="Don't ask to ask, Just ask!", description="Ask your question, instead of asking to help \nhttps://dontasktoask.com/", color=discord.Color.dark_theme()) 126 | await (ctx.channel).send(embed = thing) 127 | print("Event. ", ctx.author.name, " did ask to ask!") 128 | 129 | @commands.command(name='goodnight', aliases=['night', 'gn']) 130 | async def goodnight(self, ctx, *, args = "nothing"): 131 | async with ctx.channel.typing(): 132 | thing = discord.Embed(title="Good Night", description="Sleep tight", color= discord.Color.dark_theme()) 133 | await (ctx.channel).send(embed=thing) 134 | print(f"Event. {ctx.author.name} said good night") 135 | 136 | @commands.command(name='goodmorning', aliases=['morning', 'gm']) 137 | async def goodmorning(self, ctx, *, args = "nothing"): 138 | async with ctx.channel.typing(): 139 | thing = discord.Embed(title="Good Morning", description="Wishing you a good day", color= discord.Color.dark_theme()) 140 | await (ctx.channel).send(embed=thing) 141 | print(f"Event. {ctx.author.name} said good morning") 142 | 143 | @commands.group() 144 | async def git(self, ctx): 145 | """ 146 | A set of funny ~~useful~~ git commands. 147 | """ 148 | if ctx.invoked_subcommand is None: 149 | await ctx.send('> See: `[]help git`') 150 | 151 | @git.command() 152 | async def push(self, ctx, remote: str, branch: str): 153 | await ctx.send('Pushing {} to {}'.format(remote, branch)) 154 | 155 | @git.command() 156 | async def blame(self, ctx, branch: str): 157 | await ctx.send('#blame{}'.format(branch)) 158 | 159 | @git.command() 160 | async def lick(self, ctx, user): 161 | if random.choice([True, False]): 162 | await ctx.send('*licks {}, Mmm tastes good*'.format(user)) 163 | else: 164 | await ctx.send('*licks {}, euh tastes kinda bad*'.format(user)) 165 | 166 | @git.command() 167 | async def commit(self, ctx, *, message: str): 168 | await ctx.send('Commiting {}'.format(message)) 169 | 170 | @git.command() 171 | async def pull(self, ctx, branch: str): 172 | await ctx.send('Pulling {}'.format(branch)) 173 | 174 | @git.command() 175 | async def status(self, ctx, user: discord.Member=None): 176 | if user: 177 | await ctx.send("On branch {0}\nYour branch is up to date with 'origin/main'. \nstatus: {1}".format(user.display_name, user.status)) 178 | else: 179 | await ctx.send("On branch main\nYour branch is up to date with 'origin/main'. \nstatus: {}".format(ctx.author.status)) 180 | 181 | @git.command() 182 | async def merge(self, ctx, thing, anotherthing): 183 | await ctx.send('Merging {0} to {1}'.format(thing, anotherthing)) 184 | 185 | @git.command() 186 | async def add(self, ctx, *, thing): 187 | msg = await ctx.send('Adding {0}...'.format(thing)) 188 | await asyncio.sleep(2) 189 | await msg.edit(content='Added {0} to changes.\n`{1} additions and {2} deletions.`'.format(thing, random.randint(10, 1000), random.randint(10, 1000))) 190 | 191 | @git.command() 192 | async def out(self, ctx, *, thing): 193 | await ctx.send('https://tenor.com/view/the-office-steve-carell-please-leave-get-out-move-gif-3579774') 194 | 195 | @commands.command(name='codeblocks', aliases=['codeblock', 'cb', 'myst']) 196 | async def codeblocks(self, ctx, *args): 197 | async with ctx.channel.typing(): 198 | thing = discord.Embed(title="Code Blocks", description="""**__Use codeblocks to send code in a message!__** 199 | 200 | To make a codeblock, surround your code with \`\`\` 201 | \`\`\`cs 202 | // your code here 203 | \`\`\` 204 | 205 | `In order use C# syntax highlighting add cs after the three back ticks` 206 | 207 | To send lengthy code, paste it into and send the link of the paste into chat.""", color=discord.Color.dark_theme()) 208 | await (ctx.channel).send(embed=thing) 209 | print(f"Event: {ctx.author.name} used codeblocks") 210 | 211 | @commands.command(name='example', aliases=['Example', 'eg', 'eg.']) 212 | async def example(self, ctx, *args): 213 | async with ctx.channel.typing(): 214 | thing = discord.Embed(title="Example", description="""**__How to create a Minimal, Reproducible Example__** 215 | 216 | When asking a question, people will be better able to provide help if you provide code that they can easily understand and use to reproduce the problem. This is referred to by community members as creating a minimal, reproducible example (**reprex**), a minimal, complete and verifiable example (**mcve**), or a minimal, workable example (**mwe**). Regardless of how it's communicated to you, it boils down to ensuring your code that reproduces the problem follows the following guidelines: 217 | 218 | **__Your code examples should be…__** 219 | 220 | » **Minimal** – Use as little code as possible that still produces the same problem 221 | » **Complete** – Provide all parts someone else needs to reproduce your problem in the question itself 222 | » **Reproducible** – Test the code you're about to provide to make sure it reproduces the problem 223 | """, color=discord.Color.dark_theme()) 224 | await (ctx.channel).send(embed=thing) 225 | print(f"Event: {ctx.author.name} used example") 226 | 227 | @commands.command(name='pastemyst', aliases=['pm', 'pastebin', 'PasteMyst', 'paste']) 228 | async def pastemyst(self, ctx, *, args = "nothing"): 229 | async with ctx.channel.typing(): 230 | thing = discord.Embed(title="How to use PasteMyst", description="> 1. paste your code in https://paste.myst.rs/\n> 2. copy the link of the website completely\n> 3. send the link into chat.", color=discord.Color.dark_theme()) 231 | await (ctx.channel).send(embed=thing) 232 | print(f"Event: {ctx.author.name} used how to use pastemyst") 233 | 234 | @commands.group(name="ascii") 235 | async def ascii(self, ctx): 236 | if ctx.invoked_subcommand is None: 237 | await ctx.trigger_typing() 238 | embed = discord.Embed(title="Ascii Modules", description="use []ascii ", color = discord.Color.dark_theme()) 239 | embed.add_field(name="Word", value="Shows ascii art of given text.", inline=False) 240 | embed.add_field(name="Fonts", value="See available Fonts.", inline=False) 241 | embed.set_footer(text="use []ascii ") 242 | await ctx.send(embed=embed) 243 | 244 | 245 | @ascii.command(name="word", aliases=["w", "Word", "W"]) 246 | async def word(self, ctx, word:str = "hey", font:str = "standard"): 247 | try: 248 | result = pyfiglet.figlet_format(word, font = font) 249 | except: 250 | result = f"There is no font called {font}." 251 | await ctx.send("```\n" + result + "\n```") 252 | 253 | @ascii.command(name="fonts", aliases=["font", "f"]) 254 | async def fonts(self, ctx, page:int=1): 255 | total_pages = 4 256 | with open('./cogs/fonts.json', 'r') as f: 257 | try: 258 | data = json.load(f) 259 | 260 | if page == 1: 261 | page_data = data['fonts1'] 262 | page_no = 1 263 | elif page == 2: 264 | page_data = data['fonts2'] 265 | page_no = 2 266 | elif page == 3: 267 | page_data = data['fonts3'] 268 | page_no = 3 269 | elif page == 4: 270 | page_data = data['fonts4'] 271 | page_no = 4 272 | elif page is None: 273 | page_data = data['fonts1'] 274 | page_no = 1 275 | else: 276 | page_data = "more fonts will be added in future" 277 | page_no = 0 278 | except: 279 | print("fonts.json loading error") 280 | 281 | if page_data is not None: 282 | Separator = "\n" 283 | fields = Separator.join(page_data) 284 | 285 | #embeding 286 | embed = discord.Embed(color = discord.Color.dark_theme()) 287 | embed.set_author(name='Ascii Art') 288 | embed.add_field(name='Fonts page', value=fields, inline=False) 289 | if page_no != 0: 290 | embed.set_footer(text=f"page: {page_no}/{total_pages}") 291 | else: 292 | embed.set_footer(text="use []ascii fonts ") 293 | await ctx.send(embed=embed) 294 | else: 295 | print("looks like there's a problem with page_data") 296 | 297 | 298 | #===================================== ADD COG ======================================# 299 | 300 | def setup(bot): 301 | bot.add_cog(User(bot)) 302 | -------------------------------------------------------------------------------- /data/beg_results.json: -------------------------------------------------------------------------------- 1 | { 2 | "results": [ 3 | "sorry", 4 | "stop begging", 5 | "go ask someone else", 6 | "I maxed my credit cards already", 7 | "Get a job ye hippy", 8 | "ew get away", 9 | "HAHAHAHA no", 10 | "I used all my money to fund treeteams", 11 | "sure take this non-existent doubloon", 12 | "No way, you'll just use it to buy orange juice", 13 | "I would not share with the likes of you", 14 | "ew no", 15 | "Back in my day we worked for a living", 16 | "there. is. no. coins. for. ye.", 17 | "lol you suck, you found nothing", 18 | "No I already gave money to the last beggar", 19 | "Sorry, I just don't have money to spare", 20 | "I'm too poor", 21 | "nah, would rather not feed your gambling addiction", 22 | "ur too stanky", 23 | "coin.exe has stopped working", 24 | "sure take this non-existent coin", 25 | "can you not", 26 | "bye bitch, no coins for you", 27 | "I only give money to milkers", 28 | "honestly stop asking me for coins" 29 | ] 30 | } -------------------------------------------------------------------------------- /data/money.json: -------------------------------------------------------------------------------- 1 | { 2 | "users": { 3 | "1": { 4 | "name": "example_user1", 5 | "wallet": 0 6 | }, 7 | "2": { 8 | "name": "example_user2", 9 | "wallet": 0 10 | }, 11 | "3": { 12 | "name": "example_user3", 13 | "wallet": 0 14 | }, 15 | "4": { 16 | "name": "example_user4", 17 | "wallet": 0 18 | }, 19 | "5": { 20 | "name": "example_user5", 21 | "wallet": 0 22 | }, 23 | "699589680408297553": { 24 | "name": "billyeatcookies#8444", 25 | "job": 1, 26 | "wallet": 3290, 27 | "bank": 0 28 | }, 29 | "460608954226049024": { 30 | "name": "PP#4017", 31 | "job": 1, 32 | "wallet": 688, 33 | "bank": 0 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /data/names.json: -------------------------------------------------------------------------------- 1 | { 2 | "names": [ 3 | "Donald Trump", 4 | "billie eyelash", 5 | "Keanu Reeves", 6 | "bulk bogan", 7 | "Captain Europa", 8 | "Stranger", 9 | "Joe Biden", 10 | "Thor", 11 | "Ant Man", 12 | "Hulk", 13 | "Beanos", 14 | "Spiderman", 15 | "Bat Man", 16 | "Superman", 17 | "Wonder Woman", 18 | "Cat woman", 19 | "Flash", 20 | "Kamala Harris", 21 | "Joe Bitten", 22 | "Wolverine", 23 | "Brackeys", 24 | "Dani", 25 | "Shawn Mendes", 26 | "Pew Die Pie", 27 | "Justin Bieber", 28 | "Selena Gomez", 29 | "Cardi B", 30 | "Alan Walker", 31 | "Felix Jaehn", 32 | "Ava Max", 33 | "GeorgeNotFound", 34 | "Dream", 35 | "Fat Dino", 36 | "Acegikmo", 37 | "Mario", 38 | "Luigi", 39 | "Yoshi", 40 | "Princess Peach", 41 | "Billy", 42 | "Wumpus", 43 | "Link", 44 | "Zelda", 45 | "[REDACTED]", 46 | "Samus Aran", 47 | "Christiano Ronaldo", 48 | "Lionel Messi", 49 | "August D", 50 | "RM", 51 | "BTS", 52 | "Google", 53 | "Microsoft", 54 | "MacroHard", 55 | "CallMeKevin", 56 | "Mr.Beast", 57 | "TubboIsLive", 58 | "Mr.Money", 59 | "BillyToday at 5:37 PM", 60 | "PieDiePew", 61 | "[Expunged]", 62 | "Shigero Miya-motor", 63 | "Sans", 64 | "Frisk", 65 | "Papyrus", 66 | "Kris", 67 | "WillNE", 68 | "George Memeulous", 69 | "Mark Zuckerberg", 70 | "Jeff Bezos", 71 | "Bill Gates", 72 | "Mukesh Ambani", 73 | "Elizabeth II", 74 | "Winston Churchill", 75 | "George I", 76 | "Hitler", 77 | "Mussolini", 78 | "Charles de Gaulle", 79 | "Louis XIV", 80 | "Loch Walesa", 81 | "Stalin", 82 | "Putin", 83 | "Lenin", 84 | "Andrew Garfield", 85 | "Marx", 86 | "Robert Downey Jr.", 87 | "Chris Evans", 88 | "J.K. Rowling", 89 | "Leonardo Da Vinci", 90 | "Alexander III of Macedon", 91 | "Arthur Conan Doyle", 92 | "Gaius Octavius", 93 | "James Hadley Chase", 94 | "Cristopher Columbus", 95 | "Piccolo", 96 | "Lorenzo de Medici", 97 | "Lional Messi", 98 | "Ataturk", 99 | "Genghis Khan", 100 | "Kublai Khan", 101 | "Christiano Ronaldo", 102 | "Julius Caesar", 103 | "Brennus", 104 | "Neymer Jr.", 105 | "Hannibal", 106 | "Elon Musk", 107 | "unknown", 108 | "Larry Ellison", 109 | "Larry Page", 110 | "Warren Buffet", 111 | "Harry Styles", 112 | "Sergey Brin", 113 | "Liam Payne", 114 | "Zayn Malik", 115 | "Emperor Hirohito", 116 | "Meiji", 117 | "Wooshi", 118 | "Ken Kutaragi", 119 | "Gucci Banana", 120 | "Kim Jong-un", 121 | "IP man", 122 | "Bradley Cooper", 123 | "Gucci OGucci", 124 | "Ford", 125 | "Lady Gaga", 126 | "Marshmello", 127 | "Ninja", 128 | "Melani Martinez", 129 | "Chilled Cow", 130 | "Lionel Martin", 131 | "Hans Zimmer", 132 | "Gru", 133 | "Mercedes Benz", 134 | "Dru", 135 | "Peter Parker", 136 | "Steve Rogers", 137 | "Harry Potter", 138 | "Tony Stark", 139 | "Peter Griffin", 140 | "Kyle Brofloski", 141 | "Jennifer Loran", 142 | "Stan Marsh", 143 | "Eric Cartman", 144 | "Kenny Mcormik", 145 | "Hermione Granger", 146 | "Emma watson", 147 | "Ron Weasely", 148 | "Daniel Radcliff", 149 | "Rupert Grint", 150 | "Tom Hanks", 151 | "Albus Dumbledore", 152 | "JoJo", 153 | "Goku", 154 | "Meliodas", 155 | "Son Goku", 156 | "Donnie Yen", 157 | "Bulma", 158 | "Lynn Hung", 159 | "Marilyn Monroe", 160 | "Abraham Lincoln", 161 | "Nelson Mandela", 162 | "Gowther", 163 | "Escanor", 164 | "Merlin", 165 | "John F Kennedy", 166 | "Ban", 167 | "Martin Luther King", 168 | "Zeldris", 169 | "George Washington", 170 | "Ben Gurion", 171 | "Mother Teresa", 172 | "Pope Francis", 173 | "Franklin D. Roosevelt", 174 | "George Orwell", 175 | "Neil Armstrong", 176 | "Walt Disney", 177 | "Pele", 178 | "Angelina Jolie", 179 | "George Bush Jr.", 180 | "Greta Thunberg", 181 | "Mikhail Gorbachev", 182 | "Malala Yousafzai", 183 | "Your drunk self", 184 | "billy's non-existent beard", 185 | "dis boi", 186 | "dat boi", 187 | "your step sis" 188 | ] 189 | } -------------------------------------------------------------------------------- /data/names.txt: -------------------------------------------------------------------------------- 1 | Donald Trump 2 | billie eyelash 3 | Keanu Reeves 4 | bulk bogan 5 | Captain Europa 6 | Stranger 7 | Joe Biden 8 | Thor 9 | Ant Man 10 | Hulk 11 | Beanos 12 | Spiderman 13 | Bat Man 14 | Superman 15 | Wonder Woman 16 | Cat woman 17 | Flash 18 | Kamala Harris 19 | Joe Bitten 20 | Wolverine 21 | Brackeys 22 | Dani 23 | Shawn Mendes 24 | Pew Die Pie 25 | Justin Bieber 26 | Selena Gomez 27 | Cardi B 28 | Alan Walker 29 | Felix Jaehn 30 | Ava Max 31 | GeorgeNotFound 32 | Dream 33 | Fat Dino 34 | Acegikmo 35 | Mario 36 | Luigi 37 | Yoshi 38 | Princess Peach 39 | Billy 40 | Wumpus 41 | Link 42 | Zelda 43 | [REDACTED] 44 | Samus Aran 45 | Christiano Ronaldo 46 | Lionel Messi 47 | August D 48 | RM 49 | BTS 50 | Google 51 | Microsoft 52 | MacroHard 53 | CallMeKevin 54 | Mr.Beast 55 | TubboIsLive 56 | Mr.Money 57 | BillyToday at 5:37 PM 58 | PieDiePew 59 | [Expunged] 60 | Shigero Miya-motor 61 | Sans 62 | Frisk 63 | Papyrus 64 | Kris 65 | WillNE 66 | George Memeulous 67 | Mark Zuckerberg 68 | Jeff Bezos 69 | Bill Gates 70 | Mukesh Ambani 71 | Elizabeth II 72 | Winston Churchill 73 | George I 74 | Hitler 75 | Mussolini 76 | Charles de Gaulle 77 | Louis XIV 78 | Loch Walesa 79 | Stalin 80 | Putin 81 | Lenin 82 | Andrew Garfield 83 | Marx 84 | Robert Downey Jr. 85 | Chris Evans 86 | J.K. Rowling 87 | Leonardo Da Vinci 88 | Alexander III of Macedon 89 | Arthur Conan Doyle 90 | Gaius Octavius 91 | James Hadley Chase 92 | Cristopher Columbus 93 | Piccolo 94 | Lorenzo de Medici 95 | Lional Messi 96 | Ataturk 97 | Genghis Khan 98 | Kublai Khan 99 | Christiano Ronaldo 100 | Julius Caesar 101 | Brennus 102 | Neymer Jr. 103 | Hannibal 104 | Elon Musk 105 | unknown 106 | Larry Ellison 107 | Larry Page 108 | Warren Buffet 109 | Harry Styles 110 | Sergey Brin 111 | Liam Payne 112 | Zayn Malik 113 | Emperor Hirohito 114 | Meiji 115 | Wooshi 116 | Ken Kutaragi 117 | Gucci Banana 118 | Kim Jong-un 119 | IP man 120 | Bradley Cooper 121 | Gucci OGucci 122 | Ford 123 | Lady Gaga 124 | Marshmello 125 | Ninja 126 | Melani Martinez 127 | Chilled Cow 128 | Lionel Martin 129 | Hans Zimmer 130 | Gru 131 | Mercedes Benz 132 | Dru 133 | Peter Parker 134 | Steve Rogers 135 | Harry Potter 136 | Tony Stark 137 | Peter Griffin 138 | Kyle Brofloski 139 | Jennifer Loran 140 | Stan Marsh 141 | Eric Cartman 142 | Kenny Mcormik 143 | Hermione Granger 144 | Emma watson 145 | Ron Weasely 146 | Daniel Radcliff 147 | Rupert Grint 148 | Tom Hanks 149 | Albus Dumbledore 150 | JoJo 151 | Goku 152 | Meliodas 153 | Son Goku 154 | Donnie Yen 155 | Bulma 156 | Lynn Hung 157 | Marilyn Monroe 158 | Abraham Lincoln 159 | Nelson Mandela 160 | Gowther 161 | Escanor 162 | Merlin 163 | John F Kennedy 164 | Ban 165 | Martin Luther King 166 | Zeldris 167 | George Washington 168 | Ben Gurion 169 | Mother Teresa 170 | Pope Francis 171 | Franklin D. Roosevelt 172 | George Orwell 173 | Neil Armstrong 174 | Walt Disney 175 | Pele 176 | Angelina Jolie 177 | George Bush Jr. 178 | Greta Thunberg 179 | Mikhail Gorbachev 180 | Malala Yousafzai 181 | -------------------------------------------------------------------------------- /docs/images/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomlin7/RoboBilly/6ef8b90746e3c9895e1d91a7819b0f172a719f79/docs/images/icon.png -------------------------------------------------------------------------------- /libs/config.py: -------------------------------------------------------------------------------- 1 | import discord, json, os 2 | 3 | prefix = '[]' 4 | 5 | owner = None 6 | guild = None 7 | news_channel = None 8 | mails_channel = None 9 | 10 | owner_id = 699589680408297553 11 | 12 | guild_id = 750945243305869343 13 | news_channel_name = '📰-basement-daily' 14 | mails_channel_name = 'mails' 15 | 16 | # environmental variables 17 | NYT_TOKEN = os.getenv("NYT_TOKEN") 18 | MONGO_URL = os.getenv("MONGO_URL") 19 | DISCORD_TOKEN = os.getenv("DISCORD_TOKEN") 20 | 21 | special_event = "Halloween" 22 | 23 | def load_config(client): 24 | global guild, news_channel, mails_channel, guild_id, news_channel_name, mails_channel_name, owner, owner_id 25 | 26 | if guild_id is not None: 27 | guild = client.get_guild(guild_id) 28 | if guild is not None: 29 | for channel in guild.channels: 30 | if channel.name == news_channel_name: 31 | news_channel = channel 32 | elif channel.name == mails_channel_name: 33 | mails_channel = channel 34 | 35 | owner = guild.get_member(owner_id) -------------------------------------------------------------------------------- /libs/data.py: -------------------------------------------------------------------------------- 1 | import discord 2 | 3 | def file(): 4 | return discord.File('output.png') -------------------------------------------------------------------------------- /libs/help.py: -------------------------------------------------------------------------------- 1 | import discord 2 | from discord.ext import commands 3 | 4 | class HelpCommand(commands.MinimalHelpCommand): 5 | async def send_pages(self): 6 | destination = self.get_destination() 7 | e = discord.Embed(color=discord.Color.dark_theme(), description='') 8 | for page in self.paginator.pages: 9 | e.description += page 10 | await destination.send(embed=e) -------------------------------------------------------------------------------- /libs/httpsession.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import asyncio 3 | 4 | from aiohttp import AsyncResolver, ClientSession, TCPConnector 5 | 6 | try: 7 | asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) 8 | except: 9 | pass 10 | 11 | http_session = ClientSession( 12 | connector=TCPConnector(resolver=AsyncResolver(), family=socket.AF_INET) 13 | ) 14 | 15 | async def close_session(): 16 | await http_session.close() 17 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import discord 3 | from discord.ext import commands 4 | 5 | from libs import config 6 | from libs import help 7 | from libs import httpsession 8 | 9 | client = commands.Bot(command_prefix=commands.when_mentioned_or(config.prefix), intents = discord.Intents.all()) 10 | 11 | # Load cogs 12 | for filename in os.listdir('./cogs'): 13 | if filename.endswith('.py'): 14 | client.load_extension(f'cogs.{filename[:-3]}') 15 | 16 | client.load_extension('jishaku') 17 | 18 | client.help_command = help.HelpCommand() 19 | client.run(config.DISCORD_TOKEN) 20 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | discord.py 2 | requests 3 | asyncio 4 | datetime 5 | sly 6 | pyfiglet 7 | mal-api==0.3.5 8 | jishaku 9 | pillow 10 | psutil 11 | mcstatus 12 | pymongo 13 | cairosvg 14 | chess 15 | matplotlib 16 | aiodns 17 | imgkit 18 | randomword -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | python main.py -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.9.13 2 | --------------------------------------------------------------------------------