├── .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 |
7 | Discord Bot with amazing features! (scroll down) 8 |
9 | 10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
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 |
48 |
.*?)"
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 |
--------------------------------------------------------------------------------