├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── README.md
└── Sx4
├── cogs
├── animals.py
├── antiad.py
├── antilink.py
├── autorole.py
├── economy.py
├── fun.py
├── general.py
├── giveaway.py
├── help.py
├── image.py
├── logs.py
├── mod.py
├── music.py
├── owner.py
├── page.py
├── selfroles.py
├── serverlog.py
├── serverpost.py
├── status.py
└── welcomer.py
├── main.py
└── utils
├── PagedResult.py
├── arg.py
├── arghelp.py
├── checks.py
├── ctime.py
├── data.py
├── database.py
├── dateify.py
└── paged.py
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Device**:
27 | The device you were using at the time of the bug
28 |
29 | **Additional context**
30 | Add any other context about the problem here.
31 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # __Sx4__
2 |
3 | Sx4 is a mutlipurpose bot, this means it can be used for many different purposes making it easier for you to focus your whole server around a few bots. It also has over 210 commands (Over 500 including sub commands) for many different purposes
4 |
5 | __Moderation__
6 |
7 | Sx4 includes a variety of different moderation commands so you can organize your server to the best ability, it has things such as antilink, antiinvite, selfroles, autorole, a warning system, basic mod commands (mute, kick, ban etc) and so much more! All these things can also be logged in an optional mod-log to keep track of who's been muted, kicked, banned etc. You can also add reasons after the action has happened to make sure they are valid actions!
8 |
9 | __Economy__
10 |
11 | Sx4 is mainly based around it's economy system with many ways you can make money, you can get daily money where you can build up
12 | streaks as long as you come back everyday to collect your daily money, the higher streak the more chance you have of being
13 | rewarded a crate the higher the streak the higher chance of a better crate and a better reward. You can buy different pickaxes
14 | which can give you a variety of materials at a max of 1 per material as well as some money, pickaxes have durability and always
15 | guarentee profit with the added benefit of materials so the better the pickaxe the better the rewards, another way you can make
16 | money easily is, fishing, by default you can fish and it will give you a random amount between $2 to $15 every 5 minutes as long as
17 | you revisit the command every 5 minutes but you can buy rods with durability which give extra profit per fish so that you can make
18 | extra money at the cost of the rod price.
19 | A really effective way of collecting materials is miners you can buy them using the currency and they
20 | give you a variety of materials but it's not limited to 1 material you can have multiple of the same (miners are stackable) and
21 | then you can also gain materials through using your pickaxe and opening crates. With these materials you can purchase factories
22 | these factories yield you money depending on how hard it is obtaining the factory (factories are also stackable), or you can even
23 | sell your stuff on an online auction house built into the bot where you can also buy items off other users who also use the bot.
24 | You can also get some bonus money by simply voting for the bot to rocket your start in the economy, make sure to vote every 12
25 | hours as it's very profitable in the long run (If you give your referral links to friends you get bonus money just for referring them) and it doubles on weekends due to votes counting as 2 so double the reward!
26 |
27 | __Utility__
28 |
29 | Sx4 has many utility commands such as commands like serverinfo, userinfo, channelinfo and roleinfo which gives detailed info on the desired user/role/server/channel. There are also commands such as invites which displays how many invites a user has for the current server, their placement for amount of invites and the percent of the server they have invited. This and so much more!
30 |
31 | __Logging__
32 |
33 | Sx4 can log your server to make sure your server stays safe, it has a very detailed logging system where it logs:
34 | • Deleted messages
35 | • Edited messages
36 | • When a user gets banned
37 | • When a user gets unbanned
38 | • When a user joins/changes/leaves a voice channel
39 | • When a user joins the server
40 | • When a user leaves the server
41 | • When a user gets a role
42 | • When a user is removed from a role
43 | • When a user has a nickname change
44 | • When a user is server muted/deafened in a voice channel
45 | • Permissions updates on a role, shows what perms have been removed/added
46 |
47 | __Welcomer__
48 |
49 | Sx4 has a welcomer which is highly customizable, you can edit the message it welcomes the user with and even the leave message, or you can just choose for it to be sent to the user's dms which automatically disables the leave message. You also have the option for your message to be displayed in an embed and a image welcomer options with a customizable banner.
50 |
51 | __Music__
52 |
53 | Sx4 has 18 music commands and is really simple to use all you do is play a song or playlist and as long as you're in a voice channel it'll stream smooth music to your ears for you to enjoy, with commands such as play, search, playlist, seek, rewind, movesong and more you will not be left with little choice.
54 |
55 | __Fun__
56 |
57 | There are many fun commands on Sx4 to keep you entertained, there are commands such as rock paper scissors which you can play against the bot (the bot logs how many you've won/lost in stats) you can also marry/divorce other users which can be displayed on your very own customizable profile, as well as use google, steam, urbandictionary, steamsearch so you can search for games easily, a randomly generated minesweeper with the new addition of spoilers, google translate and much more!
58 |
--------------------------------------------------------------------------------
/Sx4/cogs/animals.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | from utils import checks
4 | from urllib.request import Request, urlopen
5 | import json
6 | import urllib
7 | import requests
8 |
9 | class animals:
10 | def __init__(self, bot, connection):
11 | self.bot = bot
12 | self.db = connection
13 |
14 | @commands.command()
15 | async def catfact(self, ctx):
16 | """Learn cat stuff"""
17 | url = "https://catfact.ninja/fact"
18 | request = Request(url)
19 | data = json.loads(urlopen(request).read().decode())
20 | s=discord.Embed(description=data["fact"], colour=ctx.message.author.colour)
21 | s.set_author(name="Did you know?")
22 | s.set_thumbnail(url="https://emojipedia-us.s3.amazonaws.com/thumbs/120/twitter/134/cat-face_1f431.png")
23 | await ctx.send(embed=s)
24 |
25 | @commands.command()
26 | async def dog(self, ctx):
27 | """Shows a random dog"""
28 | url = "https://dog.ceo/api/breeds/image/random"
29 | request = Request(url)
30 | request.add_header('User-Agent', 'Mozilla/5.0')
31 | data = json.loads(urlopen(request).read().decode())
32 | s=discord.Embed(description=":dog:", colour=ctx.message.author.colour)
33 | s.set_image(url=data["message"])
34 | try:
35 | await ctx.send(embed=s)
36 | except:
37 | await ctx.send("The dog didn't make it, sorry :no_entry:")
38 |
39 | @commands.command()
40 | async def birb(self, ctx):
41 | url = "https://api.alexflipnote.xyz/birb"
42 | try:
43 | response = requests.get(url, timeout=2).json()
44 | except:
45 | return await ctx.send("Request timed out :no_entry:")
46 | s=discord.Embed(description=":bird:", colour=ctx.author.colour)
47 | s.set_image(url=response["file"])
48 | s.set_footer(text="api.alexflipnote.xyz")
49 | await ctx.send(embed=s)
50 |
51 | @commands.command()
52 | async def cat(self, ctx):
53 | """Shows a random cat"""
54 | try:
55 | response = requests.get("http://aws.random.cat/meow", timeout=2).json()
56 | except:
57 | return await ctx.send("Request timed out :no_entry:")
58 | image = response["file"]
59 | s=discord.Embed(description=":cat:", colour=ctx.message.author.colour)
60 | s.set_image(url=image)
61 | try:
62 | await ctx.send(embed=s)
63 | except:
64 | await ctx.send("The cat didn't make it, sorry :no_entry:")
65 |
66 | @commands.command()
67 | async def duck(self, ctx):
68 | "Shows a random duck"
69 | url = "https://random-d.uk/api/v1/random"
70 | request = Request(url)
71 | request.add_header('User-Agent', 'Mozilla/5.0')
72 | data = json.loads(urlopen(request).read().decode())
73 | s=discord.Embed(description=":duck:", colour=ctx.message.author.colour)
74 | s.set_image(url=data["url"])
75 | s.set_footer(text="Powered by random-d.uk")
76 | try:
77 | await ctx.send(embed=s)
78 | except:
79 | await ctx.send("The duck didn't make it, sorry :no_entry:")
80 |
81 | @commands.command()
82 | async def fox(self, ctx):
83 | "Shows a random fox"
84 | url = "https://randomfox.ca/floof/"
85 | request = Request(url)
86 | request.add_header('User-Agent', 'Mozilla/5.0')
87 | data = json.loads(urlopen(request).read().decode())
88 | s=discord.Embed(description=":fox:", colour=ctx.message.author.colour)
89 | s.set_image(url=data["image"])
90 | try:
91 | await ctx.send(embed=s)
92 | except:
93 | await ctx.send("The Fox didn't make it, sorry :no_entry:")
94 |
95 | def setup(bot, connection):
96 | bot.add_cog(animals(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/antiad.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | import rethinkdb as r
4 | from utils import checks
5 | from datetime import datetime
6 | from collections import deque, defaultdict
7 | import os
8 | import re
9 | import logging
10 | from cogs import mod
11 | import asyncio
12 | import random
13 | from utils import arghelp, arg
14 | import time
15 |
16 | reinvite = re.compile("(?:[\s \S]|)*(?:https?://)?(?:www.)?(?:discord.gg|(?:canary.)?discordapp.com/invite)/((?:[a-zA-Z0-9]){2,32})(?:[\s \S]|)*", re.IGNORECASE)
17 |
18 |
19 | class antiad:
20 |
21 | def __init__(self, bot, connection):
22 | self.bot = bot
23 | self.db = connection
24 |
25 | @commands.group(usage="")
26 | async def antiinvite(self, ctx):
27 | """Block out those discord invite advertisers"""
28 | server = ctx.guild
29 | if ctx.invoked_subcommand is None:
30 | await arghelp.send(self.bot, ctx)
31 | else:
32 | r.table("antiad").insert({"id": str(server.id), "toggle": False, "modtoggle": True, "admintoggle": False, "bottoggle": True, "baninvites": False, "channels": [], "action": None, "attempts": 3, "users": []}).run(self.db, durability="soft")
33 |
34 | @antiinvite.command()
35 | @checks.has_permissions("manage_guild")
36 | async def toggle(self, ctx):
37 | """Toggle antiinvite on or off"""
38 | server = ctx.guild
39 | data = r.table("antiad").get(str(server.id))
40 | if data["toggle"].run(self.db, durability="soft") == True:
41 | data.update({"toggle": False}).run(self.db, durability="soft")
42 | await ctx.send("Anti-invite has been **Disabled**")
43 | return
44 | if data["toggle"].run(self.db, durability="soft") == False:
45 | data.update({"toggle": True}).run(self.db, durability="soft")
46 | await ctx.send("Anti-invite has been **Enabled**")
47 | return
48 |
49 | @antiinvite.command()
50 | @checks.has_permissions("manage_guild")
51 | async def banusernames(self, ctx):
52 | """Ban users if they join with an advertising discord link username"""
53 | server = ctx.guild
54 | data = r.table("antiad").get(str(server.id))
55 | if data["baninvites"].run(self.db, durability="soft") == True:
56 | data.update({"baninvites": False}).run(self.db, durability="soft")
57 | await ctx.send("I will no longer ban users with a discord link as their name.")
58 | return
59 | if data["baninvites"].run(self.db, durability="soft") == False:
60 | data.update({"baninvites": True}).run(self.db, durability="soft")
61 | await ctx.send("I will now ban users with a discord link as their name.")
62 | return
63 |
64 | @antiinvite.command()
65 | @checks.has_permissions("manage_guild")
66 | async def action(self, ctx, action: str):
67 | """Set an action (mute, kick, ban, none) to happen when a user reaches a certain amount of posted invites (defaults at 3 but can be changed using `s?antiinvite attempts `)"""
68 | data = r.table("antiad").get(str(ctx.guild.id))
69 | if action.lower() in ["none", "off"]:
70 | await ctx.send("Auto mod for antiinvite is now disabled.")
71 | data.update({"action": None}).run(self.db, durability="soft")
72 | elif action.lower() in ["mute", "kick", "ban"]:
73 | await ctx.send("Users who post **{}** {} will now receive a **{}**".format(data["attempts"].run(self.db, durability="soft"), "invite" if data["attempts"].run(self.db, durability="soft") == 1 else "invites", action.lower()))
74 | data.update({"action": action.lower()}).run(self.db, durability="soft")
75 | else:
76 | await ctx.send("That is not a valid action :no_entry:")
77 |
78 | @antiinvite.command()
79 | @checks.has_permissions("manage_guild")
80 | async def attempts(self, ctx, attempts: int):
81 | """Sets the amount of invites which can be sent by a user before an action happens"""
82 | data = r.table("antiad").get(str(ctx.guild.id))
83 | if attempts < 1:
84 | return await ctx.send("The amount of sent invites needs to be 1 or above :no_entry:")
85 | if attempts > 500:
86 | return await ctx.send("The max amount of attempts is 500 :no_entry:")
87 | if data["action"].run(self.db, durability="soft"):
88 | await ctx.send("Users who post **{}** {} will now receive a **{}**".format(attempts, "invite" if attempts == 1 else "invites", data["action"].run(self.db, durability="soft")))
89 | else:
90 | await ctx.send("Attempts set to **{}** to make the bot do an action after **{}** {}, use `{}antiinvite action `".format(attempts, attempts, "attempt" if attempts == 1 else "attempts", ctx.prefix))
91 | data.update({"attempts": attempts}).run(self.db, durability="soft")
92 |
93 | @antiinvite.command(aliases=["reset"])
94 | async def resetattempts(self, ctx, user: str=None):
95 | """Resets the attempts of a user"""
96 | if not user:
97 | user = ctx.author
98 | else:
99 | user = arg.get_server_member(ctx, user)
100 | if not user:
101 | return await ctx.send("I could not find that user :no_entry:")
102 | data = r.table("antiad").get(str(ctx.guild.id))
103 | if str(user.id) not in data["users"].map(lambda x: x["id"]).run(self.db, durability="soft"):
104 | return await ctx.send("This user doesn't have any attempts :no_entry:")
105 | else:
106 | if data["users"].filter(lambda x: x["id"] == str(user.id))[0]["attempts"].run(self.db, durability="soft") == 0:
107 | return await ctx.send("This user doesn't have any attempts :no_entry:")
108 | else:
109 | await ctx.send("**{}** attempts have been reset.".format(user))
110 | data.update({"users": r.row["users"].map(lambda x: r.branch(x["id"] == str(user.id), x.merge({"attempts": 0}), x))}).run(self.db, durability="soft")
111 |
112 | @antiinvite.command()
113 | @checks.has_permissions("manage_guild")
114 | async def modtoggle(self, ctx):
115 | """Choose whether you want your mods to be able to send invites or not (manage_message and above are classed as mods)"""
116 | server = ctx.guild
117 | data = r.table("antiad").get(str(server.id))
118 | if data["modtoggle"].run(self.db, durability="soft") == True:
119 | data.update({"modtoggle": False}).run(self.db, durability="soft")
120 | await ctx.send("Mods will now not be affected by anti-invite.")
121 | return
122 | if data["modtoggle"].run(self.db, durability="soft") == False:
123 | data.update({"modtoggle": True}).run(self.db, durability="soft")
124 | await ctx.send("Mods will now be affected by anti-invite.")
125 | return
126 |
127 | @antiinvite.command()
128 | @checks.has_permissions("manage_guild")
129 | async def admintoggle(self, ctx):
130 | """Choose whether you want your admins to be able to send invites or not (administrator perms are classed as admins)"""
131 | server = ctx.guild
132 | data = r.table("antiad").get(str(server.id))
133 | if data["admintoggle"].run(self.db, durability="soft") == True:
134 | data.update({"admintoggle": False}).run(self.db, durability="soft")
135 | await ctx.send("Admins will now not be affected by anti-invite.")
136 | return
137 | if data["admintoggle"].run(self.db, durability="soft") == False:
138 | data.update({"admintoggle": True}).run(self.db, durability="soft")
139 | await ctx.send("Admins will now be affected by anti-invite.")
140 | return
141 |
142 | @antiinvite.command()
143 | @checks.has_permissions("manage_guild")
144 | async def togglebot(self, ctx):
145 | """Choose whether bots can send invites or not"""
146 | server = ctx.guild
147 | data = r.table("antiad").get(str(server.id))
148 | if data["bottoggle"].run(self.db, durability="soft") == True:
149 | data.update({"bottoggle": False}).run(self.db, durability="soft")
150 | await ctx.send("Bots will now not be affected by anti-invite.")
151 | return
152 | if data["bottoggle"].run(self.db, durability="soft") == False:
153 | data.update({"bottoggle": True}).run(self.db, durability="soft")
154 | await ctx.send("Bots will now be affected by anti-invite.")
155 | return
156 |
157 | @antiinvite.command()
158 | @checks.has_permissions("manage_guild")
159 | async def togglechannel(self, ctx, channel: discord.TextChannel=None):
160 | """Choose what channels you want to count towards antiinvite"""
161 | server = ctx.guild
162 | data = r.table("antiad").get(str(server.id))
163 | if not channel:
164 | channel = ctx.channel
165 | if str(channel.id) in data["channels"].run(self.db, durability="soft"):
166 | data.update({"channels": r.row["channels"].difference([str(channel.id)])}).run(self.db, durability="soft")
167 | await ctx.send("Anti-invite is now enabled in <#{}>".format(str(channel.id)))
168 | else:
169 | data.update({"channels": r.row["channels"].append(str(channel.id))}).run(self.db, durability="soft")
170 | await ctx.send("Anti-invite is now disabled in <#{}>".format(str(channel.id)))
171 |
172 | @antiinvite.command()
173 | async def stats(self, ctx):
174 | """View the settings of the antiinvite in your server"""
175 | serverid=ctx.guild.id
176 | server=ctx.guild
177 | s=discord.Embed(colour=0xfff90d)
178 | s.set_author(name="Anti-invite Settings", icon_url=self.bot.user.avatar_url)
179 | data = r.table("antiad").get(str(server.id))
180 | msg = ""
181 | if data["toggle"].run(self.db, durability="soft") == True:
182 | toggle = "Enabled"
183 | else:
184 | toggle = "Disabled"
185 | if data["modtoggle"].run(self.db, durability="soft") == False:
186 | mod = "Mods **Can** send links"
187 | else:
188 | mod = "Mods **Can't** send links"
189 | if data["bottoggle"].run(self.db, durability="soft") == False:
190 | bottoggle = "Bots **Can** send links"
191 | else:
192 | bottoggle = "Bots **Can't** send links"
193 | if data["admintoggle"].run(self.db, durability="soft") == False:
194 | admin = "Admins **Can** send links"
195 | else:
196 | admin = "Admins **Can't** send links"
197 | if data["action"].run(self.db, durability="soft"):
198 | action = "Sending {} {} will result in a {}".format(data["attempts"].run(self.db, durability="soft"), "invite" if data["attempts"].run(self.db, durability="soft") == 1 else "invites", data["action"].run(self.db, durability="soft"))
199 | else:
200 | action = "Disabled"
201 | s.add_field(name="Status", value=toggle)
202 | s.add_field(name="Mod Perms", value=mod)
203 | s.add_field(name="Admin Perms", value=admin)
204 | s.add_field(name="Bots", value=bottoggle)
205 | s.add_field(name="Auto Mod", value=action)
206 | s.add_field(name="Ban Users with Invites in their names", value="Yes" if data["baninvites"].run(self.db) else "No")
207 | for channelid in data["channels"].run(self.db, durability="soft"):
208 | channel = discord.utils.get(server.channels, id=int(channelid))
209 | msg += channel.mention + "\n"
210 | s.add_field(name="Disabled Channels", value=msg if msg != "" else "None")
211 | await ctx.send(embed=s)
212 |
213 | async def on_member_join(self, member):
214 | server = member.guild
215 | if r.table("antiad").get(str(server.id))["baninvites"].run(self.db) == True:
216 | if reinvite.match(member.name):
217 | try:
218 | invite = await self.bot.get_invite(reinvite.match(member.name).group(1))
219 | if invite.guild == server:
220 | return
221 | else:
222 | reason = "Invite in username"
223 | action = "Ban (Automatic)"
224 | author = member
225 | await server.ban(member, reason=reason)
226 | await mod._log(self.bot, self.bot.user, server, action, reason, author, self.db)
227 | except:
228 | return
229 |
230 | async def on_message(self, message):
231 | serverid = message.guild.id
232 | server = message.guild
233 | author = message.author
234 | channel = message.channel
235 | data = r.table("antiad").get(str(serverid))
236 | if not data.run(self.db):
237 | return
238 | if author == self.bot.user:
239 | return
240 | if data["modtoggle"].run(self.db, durability="soft") == False:
241 | if channel.permissions_for(author).manage_messages:
242 | return
243 | if data["admintoggle"].run(self.db, durability="soft") == False:
244 | if channel.permissions_for(author).administrator:
245 | return
246 | if data["bottoggle"].run(self.db, durability="soft") == False:
247 | if author.bot:
248 | return
249 | if str(channel.id) in data["channels"].run(self.db, durability="soft"):
250 | return
251 | if data["toggle"].run(self.db, durability="soft") == True:
252 | if reinvite.match(message.content):
253 | try:
254 | invite = await self.get_invite(reinvite.match(message.content).group(1))
255 | if "guild" in invite:
256 | if invite["guild"]["id"] == str(server.id):
257 | return
258 | elif "channel" in invite:
259 | pass
260 | else:
261 | return
262 | await message.delete()
263 | msg = "{}, You are not allowed to send invite links here :no_entry:".format(author.mention)
264 | if data["action"].run(self.db, durability="soft"):
265 | if str(author.id) not in data["users"].map(lambda x: x["id"]).run(self.db, durability="soft"):
266 | amount = 1
267 | userdata = {}
268 | userdata["attempts"] = amount
269 | userdata["id"] = str(author.id)
270 | data.update({"users": r.row["users"].append(userdata)}).run(self.db, durability="soft", noreply=True)
271 | else:
272 | amount = data["users"].filter(lambda x: x["id"] == str(author.id))[0]["attempts"].run(self.db, durability="soft") + 1
273 | msg = "{}, You are not allowed to send invite links here, If you continue you will receive a {}. **({}/{})** :no_entry:".format(author.mention, data["action"].run(self.db, durability="soft"), amount, data["attempts"].run(self.db, durability="soft"))
274 | if amount >= data["attempts"].run(self.db, durability="soft"):
275 | if data["action"].run(self.db, durability="soft") == "ban":
276 | try:
277 | reason = "Auto ban (Sent {} invite link(s))".format(data["attempts"].run(self.db, durability="soft"))
278 | await server.ban(author, reason=reason)
279 | msg = "**{}** was banned for sending a total of **{}** {}".format(author, data["attempts"].run(self.db, durability="soft"), "invite" if data["attempts"].run(self.db, durability="soft") == 1 else "invites")
280 | amount = 0
281 | action = "Ban (Automatic)"
282 | except:
283 | msg = "I attempted to ban **{}** for posting too many invite links but it failed, check my role is above the users top role and i have sufficient permissions :no_entry:".format(author)
284 | if data["action"].run(self.db, durability="soft") == "kick":
285 | try:
286 | reason = "Auto kick (Sent {} invite link(s))".format(data["attempts"].run(self.db, durability="soft"))
287 | await server.kick(author, reason=reason)
288 | msg = "**{}** was kicked for sending a total of **{}** {}".format(author, data["attempts"].run(self.db, durability="soft"), "invite" if data["attempts"].run(self.db, durability="soft") == 1 else "invites")
289 | amount = 0
290 | action = "Kick (Automatic)"
291 | except:
292 | msg = "I attempted to kick **{}** for posting too many invite links but it failed, check my role is above the users top role and i have sufficient permissions :no_entry: {}".format(author)
293 | if data["action"].run(self.db, durability="soft") == "mute":
294 | if str(server.id) not in r.table("mute").map(lambda x: x["id"]).run(self.db, durability="soft"):
295 | r.table("mute").insert({"id": str(server.id), "users": []}).run(self.db, durability="soft", noreply=True)
296 | mutedata = r.table("mute").get(str(serverid))
297 | role = discord.utils.get(server.roles, name="Muted - Sx4")
298 | if not role:
299 | try:
300 | role = await server.create_role(name="Muted - Sx4")
301 | except:
302 | msg = "I was unable to make the mute role therefore i was not able to mute {}, check if i have the manage_roles permission :no_entry:".format(author)
303 | if role:
304 | try:
305 | await author.add_roles(role)
306 | msg = "**{}** was muted for 60 minutes for sending a total of **{}** {}".format(author, data["attempts"].run(self.db, durability="soft"), "invite" if data["attempts"].run(self.db, durability="soft") == 1 else "invites")
307 | action = "Mute (Automatic)"
308 | reason = "Auto mute (Sent {} invite link(s))".format(data["attempts"].run(self.db, durability="soft"))
309 | amount = 0
310 | if str(author.id) not in mutedata["users"].map(lambda x: x["id"]).run(self.db, durability="soft"):
311 | userobj = {}
312 | userobj["id"] = str(author.id)
313 | userobj["toggle"] = True
314 | userobj["amount"] = 3600
315 | userobj["time"] = message.created_at.timestamp()
316 | mutedata.update({"users": r.row["users"].append(userobj)}).run(self.db, durability="soft", noreply=True)
317 | else:
318 | mutedata.update({"users": r.row["users"].map(lambda x: r.branch(x["id"] == str(author.id), x.merge({"time": message.created_at.timestamp(), "amount": 3600, "toggle": True}), x))}).run(self.db, durability="soft", noreply=True)
319 | except:
320 | msg = "I attempted to mute **{}** for posting too many invite links but it failed, check that i have the manage_roles permission and that my role is above the mute role :no_entry:".format(author)
321 | data.update({"users": r.row["users"].map(lambda x: r.branch(x["id"] == str(author.id), x.merge({"attempts": amount}), x))}).run(self.db, durability="soft", noreply=True)
322 | await channel.send(msg)
323 | await mod._log(self.bot, self.bot.user, server, action, reason, author, self.db)
324 | except:
325 | return
326 |
327 | async def on_message_edit(self, before, after):
328 | serverid = before.guild.id
329 | server = before.guild
330 | author = before.author
331 | channel = before.channel
332 | data = r.table("antiad").get(str(serverid))
333 | if not data.run(self.db):
334 | return
335 | if author == self.bot.user:
336 | return
337 | if data["modtoggle"].run(self.db, durability="soft") == False:
338 | if channel.permissions_for(author).manage_messages:
339 | return
340 | if data["admintoggle"].run(self.db, durability="soft") == False:
341 | if channel.permissions_for(author).administrator:
342 | return
343 | if data["bottoggle"].run(self.db, durability="soft") == False:
344 | if author.bot:
345 | return
346 | if str(channel.id) in data["channels"].run(self.db, durability="soft"):
347 | return
348 | if data["toggle"].run(self.db, durability="soft") == True:
349 | if reinvite.match(after.content):
350 | try:
351 | invite = await self.get_invite(reinvite.match(after.content).group(1))
352 | if "guild" in invite:
353 | if invite["guild"]["id"] == str(server.id):
354 | return
355 | elif "channel" in invite:
356 | pass
357 | else:
358 | return
359 | await after.delete()
360 | msg = "{}, You are not allowed to send invite links here :no_entry:".format(author.mention)
361 | if data["action"].run(self.db, durability="soft"):
362 | if str(author.id) not in data["users"].map(lambda x: x["id"]).run(self.db, durability="soft"):
363 | amount = 1
364 | userdata = {}
365 | userdata["attempts"] = amount
366 | userdata["id"] = str(author.id)
367 | data.update({"users": r.row["users"].append(userdata)}).run(self.db, durability="soft", noreply=True)
368 | else:
369 | amount = data["users"].filter(lambda x: x["id"] == str(author.id))[0]["attempts"].run(self.db, durability="soft", noreply=True) + 1
370 | msg = "{}, You are not allowed to send invite links here, If you continue you will receive a {}. **({}/{})** :no_entry:".format(author.mention, data["action"].run(self.db, durability="soft"), amount, data["attempts"].run(self.db, durability="soft"))
371 | if amount >= data["attempts"].run(self.db, durability="soft"):
372 | if data["action"].run(self.db, durability="soft") == "ban":
373 | try:
374 | reason = "Auto ban (Sent {} invite link(s))".format(data["attempts"].run(self.db, durability="soft"))
375 | await server.ban(author, reason=reason)
376 | msg = "**{}** was banned for sending a total of **{}** {}".format(author, data["attempts"].run(self.db, durability="soft"), "invite" if data["attempts"].run(self.db, durability="soft") == 1 else "invites")
377 | amount = 0
378 | action = "Ban (Automatic)"
379 | except:
380 | msg = "I attempted to ban **{}** for posting too many invite links but it failed, check my role is above the users top role and i have sufficient permissions :no_entry:".format(author)
381 | if data["action"].run(self.db, durability="soft") == "kick":
382 | try:
383 | reason = "Auto kick (Sent {} invite link(s))".format(data["attempts"].run(self.db, durability="soft"))
384 | await server.kick(author, reason=reason)
385 | msg = "**{}** was kicked for sending a total of **{}** {}".format(author, data["attempts"].run(self.db, durability="soft"), "invite" if data["attempts"].run(self.db, durability="soft") == 1 else "invites")
386 | amount = 0
387 | action = "Kick (Automatic)"
388 | except:
389 | msg = "I attempted to kick **{}** for posting too many invite links but it failed, check my role is above the users top role and i have sufficient permissions :no_entry:".format(author)
390 | if data["action"].run(self.db, durability="soft") == "mute":
391 | if str(server.id) not in r.table("mute").map(lambda x: x["id"]).run(self.db, durability="soft"):
392 | r.table("mute").insert({"id": str(server.id), "users": []}).run(self.db, durability="soft", noreply=True)
393 | mutedata = r.table("mute").get(str(serverid))
394 | role = discord.utils.get(server.roles, name="Muted - Sx4")
395 | if not role:
396 | try:
397 | role = await server.create_role(name="Muted - Sx4")
398 | except:
399 | msg = "I was unable to make the mute role therefore i was not able to mute {}, check if i have the manage_roles permission :no_entry:".format(author)
400 | if role:
401 | try:
402 | await author.add_roles(role)
403 | msg = "**{}** was muted for 60 minutes for sending a total of **{}** {}".format(author, data["attempts"].run(self.db, durability="soft"), "invite" if data["attempts"].run(self.db, durability="soft") == 1 else "invites")
404 | amount = 0
405 | action = "Mute (Automatic)"
406 | reason = "Auto mute (Sent {} invite link(s))".format(data["attempts"].run(self.db, durability="soft"))
407 | if str(author.id) not in mutedata["users"].map(lambda x: x["id"]).run(self.db, durability="soft"):
408 | userobj = {}
409 | userobj["id"] = str(author.id)
410 | userobj["toggle"] = True
411 | userobj["amount"] = 3600
412 | userobj["time"] = after.edited_at.timestamp()
413 | mutedata.update({"users": r.row["users"].append(userobj)}).run(self.db, durability="soft", noreply=True)
414 | else:
415 | mutedata.update({"users": r.row["users"].map(lambda x: r.branch(x["id"] == str(author.id), x.merge({"time": after.edited_at.timestamp(), "amount": 3600, "toggle": True}), x))}).run(self.db, durability="soft", noreply=True)
416 | except:
417 | msg = "I attempted to mute **{}** for posting too many invite links but it failed, check that i have the manage_roles permission and that my role is above the mute role :no_entry:".format(author)
418 | data.update({"users": r.row["users"].map(lambda x: r.branch(x["id"] == str(author.id), x.merge({"attempts": amount}), x))}).run(self.db, durability="soft", noreply=True)
419 | await channel.send(msg)
420 | mod._log(self.bot, self.bot.user, server, action, reason, author, self.db)
421 | except:
422 | return
423 |
424 | async def get_invite(self, invite):
425 | client = self.bot.http
426 | r = discord.http.Route('GET', '/invite/{invite}?with_counts=true', invite=invite)
427 | return await client.request(r)
428 |
429 | def setup(bot, connection):
430 | bot.add_cog(antiad(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/antilink.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | import rethinkdb as r
4 | from utils import checks
5 | from datetime import datetime
6 | from collections import deque, defaultdict
7 | import os
8 | from utils import arghelp
9 | import re
10 | import logging
11 | import asyncio
12 | import random
13 | import time
14 |
15 |
16 | class antilink:
17 |
18 | def __init__(self, bot, connection):
19 | self.bot = bot
20 | self.db = connection
21 |
22 | @commands.group(usage="")
23 | async def antilink(self, ctx):
24 | """Block out those advertisers"""
25 | server = ctx.guild
26 | if ctx.invoked_subcommand is None:
27 | await arghelp.send(self.bot, ctx)
28 | else:
29 | r.table("antilink").insert({"id": str(server.id), "toggle": False, "modtoggle": True, "admintoggle": False, "bottoggle": True, "channels": []}).run(self.db, durability="soft")
30 |
31 | @antilink.command()
32 | @checks.has_permissions("manage_messages")
33 | async def toggle(self, ctx):
34 | """Toggle antilink on or off"""
35 | server = ctx.guild
36 | data = r.table("antilink").get(str(server.id))
37 | if data["toggle"].run(self.db, durability="soft") == True:
38 | data.update({"toggle": False}).run(self.db, durability="soft")
39 | await ctx.send("Anti-link has been **Disabled**")
40 | return
41 | if data["toggle"].run(self.db, durability="soft") == False:
42 | data.update({"toggle": True}).run(self.db, durability="soft")
43 | await ctx.send("Anti-link has been **Enabled**")
44 | return
45 |
46 | @antilink.command()
47 | @checks.has_permissions("manage_guild")
48 | async def modtoggle(self, ctx):
49 | """Choose whether you want your mods to be able to send links or not (manage_message and above are classed as mods)"""
50 | server = ctx.guild
51 | data = r.table("antilink").get(str(server.id))
52 | if data["modtoggle"].run(self.db, durability="soft") == True:
53 | data.update({"modtoggle": False}).run(self.db, durability="soft")
54 | await ctx.send("Mods will now not be affected by anti-link.")
55 | return
56 | if data["modtoggle"].run(self.db, durability="soft") == False:
57 | data.update({"modtoggle": True}).run(self.db, durability="soft")
58 | await ctx.send("Mods will now be affected by anti-link.")
59 | return
60 |
61 | @antilink.command()
62 | @checks.has_permissions("manage_guild")
63 | async def admintoggle(self, ctx):
64 | """Choose whether you want your admins to be able to send links or not (administrator perms are classed as admins)"""
65 | server = ctx.guild
66 | data = r.table("antilink").get(str(server.id))
67 | if data["admintoggle"].run(self.db, durability="soft") == True:
68 | data.update({"admintoggle": False}).run(self.db, durability="soft")
69 | await ctx.send("Admins will now not be affected by anti-link.")
70 | return
71 | if data["admintoggle"].run(self.db, durability="soft") == False:
72 | data.update({"admintoggle": True}).run(self.db, durability="soft")
73 | await ctx.send("Admins will now be affected by anti-link.")
74 | return
75 |
76 | @antilink.command()
77 | @checks.has_permissions("manage_guild")
78 | async def togglebot(self, ctx):
79 | """Choose whether bots can send links or not"""
80 | server = ctx.guild
81 | data = r.table("antilink").get(str(server.id))
82 | if data["bottoggle"].run(self.db, durability="soft") == True:
83 | data.update({"bottoggle": False}).run(self.db, durability="soft")
84 | await ctx.send("Bots will now not be affected by anti-link.")
85 | return
86 | if data["bottoggle"].run(self.db, durability="soft") == False:
87 | data.update({"bottoggle": True}).run(self.db, durability="soft")
88 | await ctx.send("Bots will now be affected by anti-link.")
89 | return
90 |
91 | @antilink.command()
92 | @checks.has_permissions("manage_guild")
93 | async def togglechannel(self, ctx, channel: discord.TextChannel=None):
94 | """Choose what channels you want to count towards antilink"""
95 | server = ctx.guild
96 | data = r.table("antilink").get(str(server.id))
97 | if not channel:
98 | channel = ctx.channel
99 | if str(channel.id) in data["channels"].run(self.db, durability="soft"):
100 | data.update({"channels": r.row["channels"].difference([str(channel.id)])}).run(self.db, durability="soft")
101 | await ctx.send("Anti-link is now enabled in <#{}>".format(str(channel.id)))
102 | return
103 | else:
104 | data.update({"channels": r.row["channels"].append(str(channel.id))}).run(self.db, durability="soft")
105 | await ctx.send("Anti-link is now disabled in <#{}>".format(str(channel.id)))
106 | return
107 |
108 | @antilink.command()
109 | async def stats(self, ctx):
110 | """View the settings of the antilink in your server"""
111 | serverid=ctx.guild.id
112 | server=ctx.guild
113 | data = r.table("antilink").get(str(server.id))
114 | s=discord.Embed(colour=0xfff90d)
115 | s.set_author(name="Anti-link Settings", icon_url=self.bot.user.avatar_url)
116 | msg = ""
117 | if data["toggle"].run(self.db, durability="soft") == True:
118 | toggle = "Enabled"
119 | else:
120 | toggle = "Disabled"
121 | if data["modtoggle"].run(self.db, durability="soft") == False:
122 | mod = "Mods **Can** send links"
123 | else:
124 | mod = "Mods **Can't** send links"
125 | if data["bottoggle"].run(self.db, durability="soft") == False:
126 | bottoggle = "Bots **Can** send links"
127 | else:
128 | bottoggle = "Bots **Can't** send links"
129 | if data["admintoggle"].run(self.db, durability="soft") == False:
130 | admin = "Admins **Can** send links"
131 | else:
132 | admin = "Admins **Can't** send links"
133 | s.add_field(name="Status", value=toggle)
134 | s.add_field(name="Mod Perms", value=mod)
135 | s.add_field(name="Admin Perms", value=admin)
136 | s.add_field(name="Bots", value=bottoggle)
137 | for channelid in data["channels"].run(self.db, durability="soft"):
138 | channel = discord.utils.get(server.channels, id=int(channelid))
139 | if channel:
140 | msg += channel.mention + "\n"
141 | s.add_field(name="Disabled Channels", value=msg if msg != "" else "None")
142 | await ctx.send(embed=s)
143 |
144 |
145 | async def on_message(self, message):
146 | serverid = message.guild.id
147 | author = message.author
148 | channel = message.channel
149 | data = r.table("antilink").get(str(serverid))
150 | if data["modtoggle"].run(self.db, durability="soft") == False:
151 | if channel.permissions_for(author).manage_messages:
152 | return
153 | if data["admintoggle"].run(self.db, durability="soft") == False:
154 | if channel.permissions_for(author).administrator:
155 | return
156 | if data["bottoggle"].run(self.db, durability="soft") == False:
157 | if author.bot:
158 | return
159 | if str(channel.id) in data["channels"].run(self.db, durability="soft"):
160 | return
161 | if data["toggle"].run(self.db, durability="soft") == True:
162 | if ("http://" in message.content.lower()) or ("https://" in message.content.lower()):
163 | await message.delete()
164 | await channel.send("{}, You are not allowed to send links here :no_entry:".format(author.mention))
165 |
166 | async def on_message_edit(self, before, after):
167 | serverid = before.guild.id
168 | author = before.author
169 | channel = before.channel
170 | data = r.table("antilink").get(str(serverid))
171 | if data["modtoggle"].run(self.db, durability="soft") == False:
172 | if channel.permissions_for(author).manage_messages:
173 | return
174 | if data["admintoggle"].run(self.db, durability="soft") == False:
175 | if channel.permissions_for(author).administrator:
176 | return
177 | if data["bottoggle"].run(self.db, durability="soft") == False:
178 | if author.bot:
179 | return
180 | if str(channel.id) in data["channels"].run(self.db, durability="soft"):
181 | return
182 | if data["toggle"].run(self.db, durability="soft") == True:
183 | if ("http://" in after.content.lower()) or ("https://" in after.content.lower()):
184 | await after.delete()
185 | await channel.send("{}, You are not allowed to send links here :no_entry:".format(author.mention))
186 |
187 | def setup(bot, connection):
188 | bot.add_cog(antilink(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/autorole.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | from utils import checks
4 | import datetime
5 | from collections import deque, defaultdict
6 | import os
7 | import re
8 | import logging
9 | import rethinkdb as r
10 | import asyncio
11 | import random
12 | import time
13 | from utils import arghelp, arg
14 | import discord
15 | from discord.ext import commands
16 | from random import randint
17 | from random import choice as randchoice
18 | from discord.ext.commands import CommandNotFound
19 |
20 |
21 | class autorole:
22 | def __init__(self, bot, connection):
23 | self.bot = bot
24 | self.db = connection
25 |
26 | @commands.group(usage="")
27 | async def autorole(self, ctx):
28 | """Allows a role to be added to a user when they join the server"""
29 | server = ctx.guild
30 | if ctx.invoked_subcommand is None:
31 | await arghelp.send(self.bot, ctx)
32 | else:
33 | r.table("autorole").insert({"id": str(server.id), "role": None, "toggle": False, "botrole": None}).run(self.db, durability="soft")
34 |
35 | @autorole.command()
36 | @checks.has_permissions("manage_roles")
37 | async def role(self, ctx, *, role: str):
38 | """Set the role to be added to a user when they join"""
39 | server = ctx.guild
40 | role = arg.get_role(ctx, role)
41 | if not role:
42 | return await ctx.send("I could not find that role :no_entry:")
43 | r.table("autorole").get(str(server.id)).update({"role": str(role.id)}).run(self.db, durability="soft")
44 | await ctx.send("The autorole role is now **{}** <:done:403285928233402378>".format(role.name))
45 |
46 | @autorole.command()
47 | @checks.has_permissions("manage_roles")
48 | async def botrole(self, ctx, *, role: str):
49 | """Set the role to be added to a bot when it joins"""
50 | server = ctx.guild
51 | role = arg.get_role(ctx, role)
52 | if not role:
53 | return await ctx.send("I could not find that role :no_entry:")
54 | r.table("autorole").get(str(server.id)).update({"botrole": str(role.id)}).run(self.db, durability="soft")
55 | await ctx.send("The autorole bot role is now **{}** <:done:403285928233402378>".format(role.name))
56 |
57 | @autorole.command()
58 | @commands.cooldown(1, 360, commands.BucketType.guild)
59 | @checks.has_permissions("manage_roles")
60 | async def fix(self, ctx):
61 | """Has the bot been offline and missed a few users? Use this to add the role to everyone who doesn't have it"""
62 | server = ctx.guild
63 | data = r.table("autorole").get(str(server.id)).run(self.db)
64 | if not data:
65 | return await ctx.send("You need to set the autorole before you can use this :no_entry:")
66 | if not data["role"]:
67 | return await ctx.send("You need to set the autorole before you can use this :no_entry:")
68 | role = ctx.guild.get_role(int(data["role"]))
69 | if not role:
70 | return await ctx.send("The auto role which is set was deleted or no longer exists :no_entry:")
71 | if data["botrole"]:
72 | botrole = ctx.guild.get_role(int(data["botrole"]))
73 | else:
74 | botrole = data["botrole"]
75 | members = [x for x in ctx.guild.members if not x.bot and role not in x.roles] if botrole else [x for x in ctx.guild.members if role not in x.roles]
76 | bots = [x for x in ctx.guild.members if x.bot and botrole not in x.roles]
77 | added_users, added_bots = 0, 0
78 | if botrole:
79 | for bot in bots:
80 | try:
81 | await bot.add_roles(botrole, reason="Autorole fix")
82 | added_bots += 1
83 | except:
84 | pass
85 | for user in members:
86 | try:
87 | await user.add_roles(role, reason="Autorole fix")
88 | added_users += 1
89 | except:
90 | pass
91 | user_msg = ", I was unable to add the role to **{}** users".format(len(members) - added_users)
92 | bot_msg = ", I was unable to add the role to **{}** bots".format(len(bots) - added_bots)
93 | await ctx.send("Added **{}** to **{}** users{}\n{}".format(role.name, added_users, user_msg if len(members) != added_users else "", "Added **{}** to **{}** bots{}".format(botrole.name, added_bots, bot_msg if len(bots) != added_bots else "") if botrole else ""))
94 |
95 | @autorole.command()
96 | @checks.has_permissions("manage_roles")
97 | async def toggle(self, ctx):
98 | """Toggle autorole on or off"""
99 | server = ctx.guild
100 | data = r.table("autorole").get(str(server.id))
101 | if data["toggle"].run(self.db, durability="soft") == True:
102 | data.update({"toggle": False}).run(self.db, durability="soft")
103 | await ctx.send("Auto-role has been **Disabled**")
104 | return
105 | if data["toggle"].run(self.db, durability="soft") == False:
106 | data.update({"toggle": True}).run(self.db, durability="soft")
107 | await ctx.send("Auto-role has been **Enabled**")
108 | return
109 |
110 | @autorole.command()
111 | async def stats(self, ctx):
112 | """View the settings of autorole on your server"""
113 | server = ctx.guild
114 | data = r.table("autorole").get(str(server.id)).run(self.db)
115 | s=discord.Embed(colour=0xfff90d)
116 | s.set_author(name="Auto-role Settings", icon_url=self.bot.user.avatar_url)
117 | if data["toggle"] == True:
118 | toggle = "Enabled"
119 | else:
120 | toggle = "Disabled"
121 | s.add_field(name="Status", value=toggle)
122 | if not data["role"]:
123 | s.add_field(name="Auto-role role", value="Not set")
124 | else:
125 | s.add_field(name="Auto-role role", value=ctx.guild.get_role(int(data["role"])).mention if ctx.guild.get_role(int(data["role"])) else "Not set")
126 | if data["botrole"]:
127 | s.add_field(name="Auto-role bot role", value=ctx.guild.get_role(int(data["botrole"])).mention if ctx.guild.get_role(int(data["botrole"])) else "Not set")
128 | else:
129 | s.add_field(name="Auto-role bot role", value="Not set")
130 | await ctx.send(embed=s)
131 |
132 | async def on_member_join(self, member):
133 | server = member.guild
134 | data = r.table("autorole").get(str(server.id)).run(self.db)
135 | role = server.get_role(int(data["role"]))
136 | if data["toggle"] == True:
137 | if member.bot:
138 | if data["botrole"]:
139 | botrole = server.get_role(int(data["botrole"]))
140 | if botrole:
141 | await member.add_roles(botrole, reason="Autorole")
142 | else:
143 | await member.add_roles(role, reason="Autorole")
144 | else:
145 | await member.add_roles(role, reason="Autorole")
146 | else:
147 | await member.add_roles(role, reason="Autorole")
148 |
149 | def setup(bot, connection):
150 | bot.add_cog(autorole(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/giveaway.py:
--------------------------------------------------------------------------------
1 | import discord
2 | import asyncio
3 | from discord.ext import commands
4 | from random import choice as randchoice
5 | import time
6 | import datetime
7 | import html
8 | import random
9 | import math
10 | from utils import arghelp
11 | from PIL import Image, ImageFilter, ImageEnhance
12 | import psutil
13 | from datetime import datetime, timedelta
14 | from utils import checks
15 | import psutil
16 | from urllib.request import Request, urlopen
17 | import json
18 | import urllib
19 | import re
20 | import traceback
21 | from utils import ctime, arg
22 | import os
23 | from random import choice
24 | from threading import Timer
25 | import requests
26 | import rethinkdb as r
27 | from random import randint
28 | from copy import deepcopy
29 | from collections import namedtuple, defaultdict, deque
30 | from copy import deepcopy
31 | from enum import Enum
32 | import asyncio
33 | from difflib import get_close_matches
34 |
35 | class giveaway:
36 | def __init__(self, bot, connection):
37 | self.bot = bot
38 | self.db = connection
39 | self._giveaway_task = bot.loop.create_task(self.check_giveaway())
40 |
41 | def __unload(self):
42 | self._giveaway_task.cancel()
43 |
44 | @commands.group(usage="")
45 | async def giveaway(self, ctx):
46 | server = ctx.guild
47 | if ctx.invoked_subcommand is None:
48 | await arghelp.send(self.bot, ctx)
49 | else:
50 | r.table("giveaway").insert({"id": str(server.id), "giveaway#": 0, "giveaways": []}).run(self.db, durability="soft")
51 |
52 | @giveaway.command()
53 | async def end(self, ctx, giveaway_id: int):
54 | serverdata = r.table("giveaway").get(str(ctx.guild.id))
55 | try:
56 | await self.determine_giveaway(serverdata, giveaway_id)
57 | except Exception as e:
58 | await ctx.send(e.args[0])
59 |
60 | @giveaway.command()
61 | async def reroll(self, ctx, message_id: int, winners: int=None):
62 | users = []
63 | if not winners:
64 | winners = 1
65 | try:
66 | message = await ctx.channel.get_message(message_id)
67 | except:
68 | return await ctx.send("Make sure you are re-rolling in the same channel as the giveaway message and that the ID is correct :no_entry:")
69 | if message.author != self.bot.user:
70 | return await ctx.send("Make sure the message id is a giveaway message :no_entry:")
71 | try:
72 | if message.embeds[0].footer.text == "Giveaway Ended":
73 | try:
74 | regex = re.match("\*\*(.*)\*\* has won \*\*(.*)\*\*", message.embeds[0].description).group(1)
75 | if regex:
76 | for x in regex.split(", "):
77 | user = discord.utils.get(ctx.guild.members, name=x.split("#")[0], discriminator=x.split("#")[1])
78 | if user:
79 | users.append(user)
80 | else:
81 | return await ctx.send("That's not a giveaway message :no_entry:")
82 | except:
83 | return await ctx.send("That's not a giveaway message :no_entry:")
84 | else:
85 | return await ctx.send("The giveaway has not finished yet :no_entry:")
86 | except:
87 | return await ctx.send("That's not a giveaway message :no_entry:")
88 | try:
89 | reaction = list(filter(lambda x: x.emoji == "🎉", message.reactions))[0]
90 | except:
91 | return await ctx.send("This message has no :tada: reactions :no_entry:")
92 | try:
93 | winner = random.sample([x for x in await reaction.users().flatten() if x != self.bot.user and x not in users], k=winners)
94 | except:
95 | try:
96 | winner = random.sample([x for x in await reaction.users().flatten() if x != self.bot.user and x not in users], k=len([x for x in await reaction.users().flatten() if x != self.bot.user]))
97 | except:
98 | return await ctx.send("Not enough people reacted on the message to get a new winner :no_entry:")
99 | await ctx.send("The new {} {}, Congratulations :tada:".format("winner is" if len(winner) == 1 else "winners are", ", ".join([x.mention for x in winner])))
100 |
101 | @giveaway.command()
102 | @checks.has_permissions("manage_roles")
103 | async def delete(self, ctx, giveaway_id: int):
104 | """delete a giveaway"""
105 | server = ctx.guild
106 | serverdata = r.table("giveaway").get(str(server.id))
107 | giveaway = serverdata["giveaways"].filter(lambda x: x["id"] == giveaway_id).run(self.db)
108 | if not giveaway:
109 | return await ctx.send("That giveaway ID does not exist :no_entry:")
110 | else:
111 | giveaway = giveaway[0]
112 | channel = ctx.guild.get_channel(int(giveaway["channel"]))
113 | if channel:
114 | try:
115 | message = await channel.get_message(int(giveaway["message"]))
116 | try:
117 | await message.delete()
118 | except:
119 | pass
120 | except discord.errors.NotFound:
121 | pass
122 | serverdata.update({"giveaways": r.row["giveaways"].filter(lambda x: x["id"] != giveaway_id)}).run(self.db, durability="soft")
123 | await ctx.send("That giveaway has been cancelled and deleted.")
124 |
125 | @giveaway.command()
126 | @checks.has_permissions("manage_roles")
127 | async def setup(self, ctx, channel: str=None, winners: int=None, duration: str=None, *, giveaway_item: str=None):
128 | """Setup a giveaway, minimum time 120 seconds"""
129 | giveaway = {}
130 | server = ctx.guild
131 | serverdata = r.table("giveaway").get(str(server.id))
132 | if channel and duration and giveaway_item and winners:
133 | title = "Giveaway"
134 | else:
135 | def checkchar(m):
136 | return m.channel == ctx.channel and m.author == ctx.author and len(m.content) <= 256
137 | def check(m):
138 | return m.channel == ctx.channel and m.author == ctx.author and len(m.content) <= 2000
139 | def check_winner(m):
140 | return m.channel == ctx.channel and m.author == ctx.author and m.content.isdigit()
141 | def check_time(m):
142 | if m.channel == ctx.channel and m.author == ctx.author:
143 | if m.content.lower() == "cancel":
144 | return True
145 | else:
146 | try:
147 | seconds = ctime.convert(m.content.lower())
148 | except ValueError:
149 | return False
150 | if seconds >= 120 and seconds <= 31556926:
151 | return True
152 | def check_channel(m):
153 | if m.channel == ctx.channel and m.author == ctx.author:
154 | if m.content.lower() == "cancel":
155 | return True
156 | channel = arg.get_text_channel(ctx, m.content)
157 | if channel:
158 | return True
159 | if not channel:
160 | await ctx.send("What channel would you like me to start this giveaway? Type \"cancel\" at anytime to cancel the creation (Respond below)")
161 | try:
162 | channel = await self.bot.wait_for("message", check=check_channel, timeout=300)
163 | if channel.content.lower() == "cancel":
164 | await ctx.send("Cancelled")
165 | return
166 | channel = channel.content
167 | except asyncio.TimeoutError:
168 | await ctx.send("Timed out :stopwatch:")
169 | return
170 | except asyncio.TimeoutError:
171 | await ctx.send("Timed out :stopwatch:")
172 | return
173 | await ctx.send("What do you want to name your giveaway? (Respond below)")
174 | try:
175 | title = await self.bot.wait_for("message", check=checkchar, timeout=300)
176 | if title.content.lower() == "cancel":
177 | await ctx.send("Cancelled")
178 | return
179 | title = title.content
180 | except asyncio.TimeoutError:
181 | await ctx.send("Timed out :stopwatch:")
182 | return
183 | if not winners:
184 | await ctx.send("How many winners would you like? (Respond below)")
185 | try:
186 | winners = await self.bot.wait_for("message", check=check_winner, timeout=300)
187 | if winners.content.lower() == "cancel":
188 | await ctx.send("Cancelled")
189 | return
190 | winners = int(winners.content)
191 | except asyncio.TimeoutError:
192 | await ctx.send("Timed out :stopwatch:")
193 | return
194 | if not duration:
195 | await ctx.send("How long do you want your giveaway to last? (After the numerical value add 'd' for days, 'h' for hours, 'm' for minutes, 's' for seconds) Minimum time: 2 minutes. (Respond below)")
196 | try:
197 | time2 = await self.bot.wait_for("message", check=check_time, timeout=300)
198 | if time2.content.lower() == "cancel":
199 | await ctx.send("Cancelled")
200 | return
201 | duration = time2.content
202 | except asyncio.TimeoutError:
203 | await ctx.send("Timed out :stopwatch:")
204 | return
205 | if not giveaway_item:
206 | await ctx.send("What are you giving away? (Respond below)")
207 | try:
208 | item = await self.bot.wait_for("message", check=check, timeout=300)
209 | if item.content.lower() == "cancel":
210 | await ctx.send("Cancelled")
211 | return
212 | giveaway_item = item.content
213 | except asyncio.TimeoutError:
214 | await ctx.send("Timed out :stopwatch:")
215 | return
216 |
217 | serverdata.update({"giveaway#": r.row["giveaway#"] + 1}).run(self.db, durability="soft")
218 | id = serverdata["giveaway#"].run(self.db, durability="soft")
219 | channel = arg.get_text_channel(ctx, channel)
220 | if not channel:
221 | return await ctx.send("I could not find that channel :no_entry:")
222 | try:
223 | giveaway_seconds = ctime.convert(duration)
224 | except ValueError:
225 | return await ctx.send("Invalid duration format :no_entry:")
226 | if giveaway_seconds < 120:
227 | return await ctx.send("Giveaways have to be at least 2 minutes long :no_entry:")
228 | starttime = datetime.utcnow().timestamp()
229 | endtime = datetime.utcnow().timestamp() + giveaway_seconds
230 | s=discord.Embed(title=title, description="Enter by reacting with :tada:\n\nThis giveaway is for **{}**\nDuration: **{}**\nWinners: **{}**".format(giveaway_item, self.giveaway_time(starttime, endtime), winners), timestamp=datetime.fromtimestamp(datetime.utcnow().timestamp() + giveaway_seconds))
231 | s.set_footer(text="Ends")
232 | message = await channel.send(embed=s)
233 | await message.add_reaction("🎉")
234 | giveaway["title"] = title
235 | giveaway["endtime"] = datetime.utcnow().timestamp() + giveaway_seconds
236 | giveaway["length"] = giveaway_seconds
237 | giveaway["item"] = giveaway_item
238 | giveaway["channel"] = str(channel.id)
239 | giveaway["message"] = str(message.id)
240 | giveaway["winners"] = winners
241 | giveaway["id"] = id
242 | serverdata.update({"giveaways": r.row["giveaways"].append(giveaway)}).run(self.db, durability="soft")
243 | await ctx.send("Your giveaway has been created :tada:\nGiveaway ID: `{}` (This can be used to delete and end giveaways)".format(id))
244 |
245 | async def check_giveaway(self):
246 | while not self.bot.is_closed():
247 | try:
248 | data = r.table("giveaway")
249 | for sdata in data.run(self.db, durability="soft"):
250 | serverdata = data.get(sdata["id"])
251 | for x in sdata["giveaways"]:
252 | if x["endtime"] <= datetime.utcnow().timestamp():
253 | try:
254 | await self.determine_giveaway(serverdata, x["id"])
255 | except:
256 | serverdata.update({"giveaways": r.row["giveaways"].filter(lambda y: y["id"] != x["id"])}).run(self.db, durability="soft", noreply=True)
257 | except Exception as e:
258 | await self.bot.get_channel(344091594972069888).send(e)
259 | await asyncio.sleep(60)
260 |
261 | async def determine_giveaway(self, guild_data, giveaway_id):
262 | guild = self.bot.get_guild(int(guild_data["id"].run(self.db)))
263 | message_data = guild_data["giveaways"].filter(lambda x: x["id"] == giveaway_id).run(self.db)
264 | if not message_data:
265 | raise ValueError("Invalid giveaway ID :no_entry:")
266 | message_data = message_data[0]
267 | channel = guild.get_channel(int(message_data["channel"]))
268 | if channel is None:
269 | raise ValueError("The channel in which that giveaway was hosted has been deleted :no_entry:")
270 | try:
271 | message = await channel.get_message(int(message_data["message"]))
272 | except discord.errors.NotFound as e:
273 | raise discord.errors.NotFound(e.response, "The message in the giveaway no longer exists :no_entry:")
274 | try:
275 | reaction = [x for x in message.reactions if x.emoji == "🎉"][0]
276 | except IndexError:
277 | raise IndexError("There are not any :tada: reactions on that message :no_entry:")
278 | winner = random.sample([x for x in await reaction.users().flatten() if x != self.bot.user], k=min(len([x for x in await reaction.users().flatten() if x != self.bot.user]), message_data["winners"]))
279 | if winner == []:
280 | await channel.send("No one entered the giveaway :no_entry:")
281 | await message.delete()
282 | guild_data.update({"giveaways": r.row["giveaways"].filter(lambda y: y["id"] != message_data["id"])}).run(self.db, durability="soft", noreply=True)
283 | return
284 | s=discord.Embed(title=message_data["title"], description="**{}** has won **{}**".format(", ".join([str(x) for x in winner]), message_data["item"]))
285 | s.set_footer(text="Giveaway Ended")
286 | await message.edit(embed=s)
287 | await channel.send("{}, Congratulations you won the giveaway for **{}**".format(", ".join([x.mention for x in winner]), message_data["item"]))
288 | guild_data.update({"giveaways": r.row["giveaways"].filter(lambda y: y["id"] != message_data["id"])}).run(self.db, durability="soft", noreply=True)
289 |
290 |
291 | def giveaway_time(self, starttime, endtime):
292 | m, s = divmod(endtime - starttime, 60)
293 | h, m = divmod(m, 60)
294 | d, h = divmod(h, 24)
295 | if d == 1:
296 | days = "day"
297 | else:
298 | days = "days"
299 | if h == 1:
300 | hours = "hour"
301 | else:
302 | hours = "hours"
303 | if m == 1:
304 | minutes = "minute"
305 | else:
306 | minutes = "minutes"
307 | if s == 1:
308 | seconds = "seconds"
309 | else:
310 | seconds = "seconds"
311 | duration = ("%d %s " % (d, days) if d != 0 else "") + ("%d %s " % (h, hours) if h != 0 else "") + ("%d %s " % (m, minutes) if m != 0 else "") + ("%d %s " % (s, seconds) if s >= 1 else "")
312 | return duration
313 |
314 | def setup(bot, connection):
315 | bot.add_cog(giveaway(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/help.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | import os
4 | from copy import deepcopy
5 | from collections import namedtuple, defaultdict, deque
6 | from datetime import datetime
7 | from random import randint
8 | from copy import deepcopy
9 | import inspect
10 | from utils import checks
11 | from enum import Enum
12 | import time
13 | import logging
14 | import datetime
15 | import math
16 | from urllib.request import Request, urlopen
17 | import json
18 | from utils.PagedResult import PagedResult
19 | from utils.PagedResult import PagedResultData
20 | import random
21 | from random import choice
22 | import asyncio
23 | from difflib import get_close_matches
24 |
25 | class help:
26 | """help command"""
27 |
28 | def __init__(self, bot, connection):
29 | self.bot = bot
30 | self.db = connection
31 |
32 | @commands.command()
33 | async def help(self, ctx, commandname=None, *, subcommand=None):
34 | if not commandname and not subcommand:
35 | cogs = list(self.bot.cogs)
36 | economy = cogs.index("economy")
37 | cogs[0], cogs[economy] = cogs[economy], cogs[0]
38 | s=discord.Embed(colour=0xffff00)
39 | s.set_footer(text="s?help for more info", icon_url=ctx.message.author.avatar_url)
40 | for cog in cogs:
41 | commands = ", ".join(sorted(["`" + command + "`" for command in self.bot.cogs[cog].bot.all_commands if self.bot.all_commands[command].module[5:].lower() == cog.lower() and self.bot.all_commands[command].hidden == False and command not in self.bot.all_commands[command].aliases], key=lambda x: x.lower()))
42 | commandsnum = len([x for x in self.bot.all_commands if self.bot.all_commands[x].hidden == False and x not in self.bot.all_commands[x].aliases])
43 | cogsnum = len([x for x in self.bot.all_commands if self.bot.all_commands[x].module[5:].lower() == cog.lower() and self.bot.all_commands[x].hidden == False and x not in self.bot.all_commands[x].aliases])
44 | s.set_author(name="Help ({} Commands)".format(commandsnum), icon_url=self.bot.user.avatar_url)
45 | if commands != "" and cog != "help":
46 | s.add_field(name=cog.title() + " [{}]".format(cogsnum), value=commands, inline=False)
47 | await ctx.send(embed=s)
48 | elif not subcommand and commandname:
49 | msg = ""
50 | try:
51 | self.bot.all_commands[commandname.lower()]
52 | try:
53 | perms = self.bot.all_commands[commandname.lower()].checks[0]
54 | except:
55 | perms = None
56 | except:
57 | try:
58 | cogcommandsnum = len("\n".join(["`{}` - {}".format(x, self.bot.cogs[commandname.lower()].bot.all_commands[x].help) for x in self.bot.cogs[commandname.lower()].bot.all_commands if self.bot.all_commands[x].module[5:].lower() == commandname.lower() and self.bot.all_commands[x].hidden == False and x not in self.bot.all_commands[x].aliases]))
59 | pages = math.ceil(cogcommandsnum / 2000)
60 | commandnumber = len([x for x in self.bot.cogs[commandname.lower()].bot.all_commands if self.bot.all_commands[x].module[5:].lower() == commandname.lower() and self.bot.all_commands[x].hidden == False and x not in self.bot.all_commands[x].aliases])
61 | cogcommands = "\n".join(sorted(["`{}` - {}".format(x, self.bot.cogs[commandname.lower()].bot.all_commands[x].help) for x in self.bot.cogs[commandname.lower()].bot.all_commands if self.bot.all_commands[x].module[5:].lower() == commandname.lower() and self.bot.all_commands[x].hidden == False and x not in self.bot.all_commands[x].aliases], key=lambda x: x))
62 | n = 0
63 | m = 2000
64 | for x in range(pages):
65 | if n != 0:
66 | while cogcommands[n-1:n] != "\n":
67 | n -= 1
68 | while cogcommands[m-1:m] != "\n":
69 | m -= 1
70 | s=discord.Embed(colour=0xffff00, description=cogcommands[n:m])
71 | if n == 0:
72 | s.set_author(name=commandname.title() + " ({} Commands)".format(commandnumber), icon_url=self.bot.user.avatar_url)
73 | s.set_footer(text="s?help for more info", icon_url=ctx.message.author.avatar_url)
74 | n += 2000
75 | m += 2000
76 | await ctx.send(embed=s)
77 | return
78 | except:
79 | await ctx.send("That is not a valid command or module :no_entry:")
80 | return
81 | if not self.bot.all_commands[commandname.lower()].usage:
82 | for x in self.bot.all_commands[commandname.lower()].params:
83 | if x != "ctx":
84 | if x != "self":
85 | if "=" in str(self.bot.all_commands[commandname.lower()].params[x]):
86 | msg += "[{}] ".format(x)
87 | else:
88 | msg += "<{}> ".format(x)
89 | else:
90 | msg += self.bot.all_commands[commandname.lower()].usage
91 | if not self.bot.all_commands[commandname.lower()].aliases:
92 | aliases = "None"
93 | else:
94 | aliases = ", ".join([x for x in self.bot.all_commands[commandname.lower()].aliases])
95 | if not perms:
96 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: None\nCommand description: {}".format(ctx.prefix, self.bot.all_commands[commandname.lower()], msg, aliases, self.bot.all_commands[commandname.lower()].help)
97 | else:
98 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: {}\nCommand description: {}".format(ctx.prefix, self.bot.all_commands[commandname.lower()], msg, aliases,
99 | ", ".join(inspect.getclosurevars(perms).nonlocals["perms"]) if perms.__name__ != "is_owner_check" and str(perms).split(" ")[1].split(".")[0] != "is_main_owner" else "Bot Owner", self.bot.all_commands[commandname.lower()].help)
100 | try:
101 | msg += "\n\nSub commands: {}".format(", ".join([x for x in self.bot.all_commands[commandname.lower()].all_commands if x not in self.bot.all_commands[commandname.lower()].all_commands[x].aliases]))
102 | except:
103 | pass
104 | s=discord.Embed(description=msg)
105 | s.set_author(name=self.bot.all_commands[commandname.lower()].name, icon_url=self.bot.user.avatar_url)
106 | await ctx.send(embed=s)
107 | else:
108 | msg = ""
109 | try:
110 | self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()]
111 | try:
112 | perms = self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].checks[0]
113 | except:
114 | perms = None
115 | except:
116 | await ctx.send("That is not a command :no_entry:")
117 | return
118 | if not self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].usage:
119 | for x in self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].params:
120 | if x != "ctx":
121 | if x != "self":
122 | if "=" in str(self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].params[x]):
123 | msg += "[{}] ".format(x)
124 | else:
125 | msg += "<{}> ".format(x)
126 | else:
127 | msg += self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].usage
128 | if not self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].aliases:
129 | aliases = "None"
130 | else:
131 | aliases = ", ".join([x for x in self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].aliases])
132 | if not perms:
133 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: None\nCommand description: {}".format(ctx.prefix, self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()], msg, aliases, self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].help)
134 | else:
135 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: {}\nCommand description: {}".format(ctx.prefix, self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()], msg, aliases,
136 | ", ".join(inspect.getclosurevars(perms).nonlocals["perms"]) if perms.__name__ != "is_owner_check" and str(perms).split(" ")[1].split(".")[0] != "is_main_owner" else "Bot Owner", self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].help)
137 | s=discord.Embed(description=msg)
138 | s.set_author(name=self.bot.all_commands[commandname.lower()].name + " " + self.bot.all_commands[commandname.lower()].all_commands[subcommand.lower()].name, icon_url=self.bot.user.avatar_url)
139 | await ctx.send(embed=s)
140 |
141 | def setup(bot, connection):
142 | n = help(bot, connection)
143 | bot.remove_command('help')
144 | bot.add_cog(n)
145 |
--------------------------------------------------------------------------------
/Sx4/cogs/image.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | import os
4 | from copy import deepcopy
5 | from collections import namedtuple, defaultdict, deque
6 | from datetime import datetime
7 | from random import randint
8 | from copy import deepcopy
9 | from io import BytesIO, StringIO
10 | from utils import checks
11 | from enum import Enum
12 | import time
13 | import logging
14 | import datetime
15 | import math
16 | from utils import arg
17 | from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageEnhance, ImageSequence
18 | from urllib.request import Request, urlopen
19 | import re
20 | import json
21 | import aiohttp
22 | import urllib.request
23 | from utils import data
24 | import requests
25 | import random
26 | from random import choice
27 | import asyncio
28 | from difflib import get_close_matches
29 |
30 | colours = data.read_json("data/colours/colournames.json")
31 |
32 | class image:
33 | """Fun image commands"""
34 |
35 | def __init__(self, bot, connection):
36 | self.bot = bot
37 | self.db = connection
38 |
39 | @commands.command(aliases=["htg"])
40 | @commands.cooldown(1, 5, commands.BucketType.user)
41 | async def howtogoogle(self, ctx, *, text):
42 | """Shows someone how to use google"""
43 | if len(text) > 50:
44 | return await ctx.send("You can only use **50** characters :no_entry:")
45 | async with ctx.channel.typing():
46 | async with aiohttp.ClientSession() as session:
47 | async with session.get("http://localhost:8443/api/google?{}".format(urllib.parse.urlencode({"q": text}))) as f:
48 | if f.status == 200:
49 | await ctx.send(file=discord.File(f.content, "google.{}".format(f.headers["Content-Type"].split("/")[1])))
50 | elif f.status == 400:
51 | await ctx.send(await f.text())
52 | else:
53 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
54 |
55 | @commands.command(usage="[user | image]")
56 | @commands.cooldown(1, 5, commands.BucketType.user)
57 | async def hot(self, ctx, user_or_image: str=None):
58 | """The specified user/image will be called hot by will smith"""
59 | if ctx.message.attachments and not user_or_image:
60 | url = ctx.message.attachments[0].url
61 | elif not ctx.message.attachments and not user_or_image:
62 | url = get_avatar_url(ctx.author)
63 | else:
64 | user = arg.get_server_member(ctx, user_or_image)
65 | if not user:
66 | url = user_or_image
67 | else:
68 | url = get_avatar_url(user)
69 | async with aiohttp.ClientSession() as session:
70 | async with session.get("http://localhost:8443/api/hot?image={}".format(url)) as f:
71 | if f.status == 200:
72 | await ctx.send(file=discord.File(f.content, "hot.{}".format(f.headers["Content-Type"].split("/")[1])))
73 | elif f.status == 400:
74 | await ctx.send(await f.text())
75 | else:
76 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
77 |
78 | @commands.command(name="discord", usage=" ")
79 | @commands.cooldown(1, 5, commands.BucketType.user)
80 | async def _discord(self, ctx, user: str, *, discord_text: str):
81 | """Recreate a message from discord using this command"""
82 | user = arg.get_server_member(ctx, user)
83 | if not user:
84 | return await ctx.send("Invalid user :no_entry:")
85 | if discord_text.lower().endswith(" --white"):
86 | white = True
87 | discord_text = discord_text[:-8]
88 | else:
89 | white = False
90 | url = "http://localhost:8443/api/discord?image={}&theme={}&{}&colour={}&{}&bot={}".format(get_avatar_url(user), "dark" if not white else "white", urllib.parse.urlencode({"text": discord_text}),
91 | str(user.colour)[1:], urllib.parse.urlencode({"name": user.display_name}), user.bot)
92 | async with aiohttp.ClientSession() as session:
93 | async with session.get(url) as f:
94 | if f.status == 200:
95 | await ctx.send(file=discord.File(f.content, "discord.{}".format(f.headers["Content-Type"].split("/")[1])))
96 | elif f.status == 400:
97 | await ctx.send(await f.text())
98 | else:
99 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
100 |
101 | @commands.command()
102 | @commands.cooldown(1, 5, commands.BucketType.user)
103 | async def flag(self, ctx, flag_initial: str, *, user: discord.Member=None):
104 | """Put a flag on top of your profile picture"""
105 | if not user:
106 | user = ctx.author
107 | async with aiohttp.ClientSession() as session:
108 | async with session.get("http://localhost:8443/api/flag?image={}&flag={}".format(get_avatar_url(user), flag_initial.lower())) as f:
109 | if f.status == 200:
110 | await ctx.send(file=discord.File(f.content, "flag.{}".format(f.headers["Content-Type"].split("/")[1])))
111 | elif f.status == 400:
112 | await ctx.send(await f.text())
113 | else:
114 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
115 |
116 | @commands.command(usage="[user | image]")
117 | @commands.cooldown(1, 5, commands.BucketType.user)
118 | async def christmas(self, ctx, *, user_or_image: str=None):
119 | """Turn an image into a christmas themed one"""
120 | if not user_or_image:
121 | if ctx.message.attachments:
122 | url = ctx.message.attachments[0].url
123 | else:
124 | url = get_avatar_url(ctx.author)
125 | else:
126 | user = arg.get_server_member(ctx, user_or_image)
127 | if not user:
128 | url = user_or_image
129 | else:
130 | url = get_avatar_url(user)
131 | async with aiohttp.ClientSession() as session:
132 | async with session.get("http://localhost:8443/api/christmas?image={}".format(url)) as f:
133 | if f.status == 200:
134 | await ctx.send(file=discord.File(f.content, "christmas.{}".format(f.headers["Content-Type"].split("/")[1])))
135 | elif f.status == 400:
136 | await ctx.send(await f.text())
137 | else:
138 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
139 |
140 | @commands.command(usage="[user | image]")
141 | @commands.cooldown(1, 5, commands.BucketType.user)
142 | async def halloween(self, ctx, *, user_or_image: str=None):
143 | """Turn an image into a halloween themed one"""
144 | if not user_or_image:
145 | if ctx.message.attachments:
146 | url = ctx.message.attachments[0].url
147 | else:
148 | url = get_avatar_url(ctx.author)
149 | else:
150 | user = arg.get_server_member(ctx, user_or_image)
151 | if not user:
152 | url = user_or_image
153 | else:
154 | url = get_avatar_url(user)
155 | async with aiohttp.ClientSession() as session:
156 | async with session.get("http://localhost:8443/api/halloween?image={}".format(url)) as f:
157 | if f.status == 200:
158 | await ctx.send(file=discord.File(f.content, "halloween.{}".format(f.headers["Content-Type"].split("/")[1])))
159 | elif f.status == 400:
160 | await ctx.send(await f.text())
161 | else:
162 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
163 |
164 | @commands.command(usage="[user | image]")
165 | @commands.cooldown(1, 5, commands.BucketType.user)
166 | async def trash(self, ctx, user_or_imagelink: str=None):
167 | """Make someone look like trash"""
168 | channel = ctx.message.channel
169 | author = ctx.message.author
170 | if not user_or_imagelink:
171 | if ctx.message.attachments:
172 | url = ctx.message.attachments[0].url
173 | else:
174 | url = ctx.author.avatar_url_as(format="png")
175 | else:
176 | user = arg.get_server_member(ctx, user_or_imagelink)
177 | if not user:
178 | url = user_or_imagelink
179 | else:
180 | url = user.avatar_url_as(format="png")
181 | async with aiohttp.ClientSession() as session:
182 | async with session.get("http://localhost:8443/api/trash?image={}".format(url)) as f:
183 | if f.status == 200:
184 | await ctx.send(file=discord.File(f.content, "trash.png"))
185 | elif f.status == 400:
186 | await ctx.send(await f.text())
187 | else:
188 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
189 |
190 | @commands.command(aliases=["www"], usage="[user | image] [user | image]")
191 | @commands.cooldown(1, 5, commands.BucketType.user)
192 | async def whowouldwin(self, ctx, user_or_imagelink: str, user_or_imagelink2: str=None):
193 | """Who would win out of 2 images"""
194 | channel = ctx.channel
195 | author = ctx.author
196 | user = arg.get_server_member(ctx, user_or_imagelink)
197 | if not user:
198 | url1 = user_or_imagelink
199 | else:
200 | url1 = user.avatar_url_as(format="png")
201 | if not user_or_imagelink2:
202 | url2 = author.avatar_url_as(format="png")
203 | else:
204 | user = arg.get_server_member(ctx, user_or_imagelink2)
205 | if not user:
206 | url2 = user_or_imagelink2
207 | else:
208 | url2 = user.avatar_url_as(format="png")
209 | async with aiohttp.ClientSession() as session:
210 | async with session.get("http://localhost:8443/api/www?firstImage={}&secondImage={}".format(url1, url2)) as f:
211 | if f.status == 200:
212 | await ctx.send(file=discord.File(f.content, "www.png"))
213 | elif f.status == 400:
214 | await ctx.send(await f.text())
215 | else:
216 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
217 |
218 | @commands.command(usage="[user | image]")
219 | @commands.cooldown(1, 5, commands.BucketType.user)
220 | async def fear(self, ctx, user_or_imagelink: str=None):
221 | """Make someone look feared of"""
222 | channel = ctx.channel
223 | author = ctx.author
224 | if not user_or_imagelink:
225 | if ctx.message.attachments:
226 | url = ctx.message.attachments[0].url
227 | else:
228 | url = get_avatar_url(author)
229 | else:
230 | user = arg.get_server_member(ctx, user_or_imagelink)
231 | if not user:
232 | url = user_or_imagelink
233 | else:
234 | url = get_avatar_url(user)
235 | async with aiohttp.ClientSession() as session:
236 | async with session.get("http://localhost:8443/api/fear?image={}".format(url)) as f:
237 | if f.status == 200:
238 | await ctx.send(file=discord.File(f.content, "fear.{}".format(f.headers["Content-Type"].split("/")[1])))
239 | elif f.status == 400:
240 | await ctx.send(await f.text())
241 | else:
242 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
243 |
244 | @commands.command(usage="[user | image]")
245 | @commands.cooldown(1, 5, commands.BucketType.user)
246 | async def emboss(self, ctx, user_or_image: str=None):
247 | """Make a profile picture emboss"""
248 | channel = ctx.channel
249 | author = ctx.author
250 | if not user_or_image:
251 | if ctx.message.attachments:
252 | url = ctx.message.attachments[0].url
253 | else:
254 | url = get_avatar_url(author)
255 | else:
256 | user = arg.get_server_member(ctx, user_or_image)
257 | if not user:
258 | url = user_or_image
259 | else:
260 | url = get_avatar_url(user)
261 | async with aiohttp.ClientSession() as session:
262 | async with session.get("http://localhost:8443/api/emboss?image={}".format(url)) as f:
263 | if f.status == 200:
264 | await ctx.send(file=discord.File(f.content, "emboss.{}".format(f.headers["Content-Type"].split("/")[1])))
265 | elif f.status == 400:
266 | await ctx.send(await f.text())
267 | else:
268 | await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
269 |
270 | @commands.command(usage=" [user]")
271 | @commands.cooldown(1, 5, commands.BucketType.user)
272 | async def ship(self, ctx, user1: str, *, user2: str=None):
273 | """Ship 2 users"""
274 | if not user2:
275 | user2 = arg.get_server_member(ctx, user1)
276 | user1 = ctx.author
277 | else:
278 | user1 = arg.get_server_member(ctx, user1)
279 | user2 = arg.get_server_member(ctx, user2)
280 | if not user1 or not user2:
281 | return await ctx.send("Invalid user :no_entry:")
282 | shipname = str(user1.name[:math.ceil(len(user1.name)/2)]) + str(user2.name[math.ceil(len(user2.name)/2):])
283 | state = random.getstate()
284 | random.seed(user2.id + user1.id)
285 | number = randint(0, 100)
286 | random.setstate(state)
287 | u1avatar = user1.avatar_url_as(format="png")
288 | u2avatar = user2.avatar_url_as(format="png")
289 | async with aiohttp.ClientSession() as session:
290 | async with session.get("http://localhost:8443/api/ship?firstImage={}&secondImage={}".format(u1avatar, u2avatar)) as f:
291 | if f.status == 200:
292 | await ctx.send(content="Ship Name: **{}**\nLove Percentage: **{}%**".format(shipname, number), file=discord.File(f.content, "ship.png"))
293 | elif f.status == 400:
294 | return await ctx.send(await f.text())
295 | else:
296 | return await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
297 |
298 | @commands.command(usage="[user | image]")
299 | @commands.cooldown(1, 5, commands.BucketType.user)
300 | async def vr(self, ctx, user_or_image: str=None):
301 | """Make someone feel emotional in vr"""
302 | channel = ctx.channel
303 | author = ctx.author
304 | if not user_or_image:
305 | if ctx.message.attachments:
306 | url = ctx.message.attachments[0].url
307 | else:
308 | url = get_avatar_url(author)
309 | else:
310 | user = arg.get_server_member(ctx, user_or_image)
311 | if not user:
312 | url = user_or_image
313 | else:
314 | url = get_avatar_url(user)
315 | async with aiohttp.ClientSession() as session:
316 | async with session.get("http://localhost:8443/api/vr?image={}".format(url)) as f:
317 | if f.status == 200:
318 | await ctx.send(file=discord.File(f.content, "vr.{}".format(f.headers["Content-Type"].split("/")[1])))
319 | elif f.status == 400:
320 | return await ctx.send(await f.text())
321 | else:
322 | return await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
323 |
324 |
325 | @commands.command(usage="[user | image]")
326 | @commands.cooldown(1, 5, commands.BucketType.user)
327 | async def shit(self, ctx, user_or_image: str=None):
328 | """Choose who you want to be shit"""
329 | channel = ctx.channel
330 | author = ctx.author
331 | if not user_or_image:
332 | if ctx.message.attachments:
333 | url = ctx.message.attachments[0].url
334 | else:
335 | url = get_avatar_url(author)
336 | else:
337 | user = arg.get_server_member(ctx, user_or_image)
338 | if not user:
339 | url = user_or_image
340 | else:
341 | url = get_avatar_url(user)
342 | async with aiohttp.ClientSession() as session:
343 | async with session.get("http://localhost:8443/api/shit?image={}".format(url)) as f:
344 | if f.status == 200:
345 | await ctx.send(file=discord.File(f.content, "shit.{}".format(f.headers["Content-Type"].split("/")[1])))
346 | elif f.status == 400:
347 | return await ctx.send(await f.text())
348 | else:
349 | return await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
350 |
351 | @commands.command(usage="[user | image]")
352 | @commands.cooldown(1, 5, commands.BucketType.user)
353 | async def beautiful(self, ctx, user_or_image: str=None):
354 | """Turn something to a masterpiece"""
355 | channel = ctx.channel
356 | author = ctx.author
357 | if not user_or_image:
358 | if ctx.message.attachments:
359 | url = ctx.message.attachments[0].url
360 | else:
361 | url = get_avatar_url(author)
362 | else:
363 | user = arg.get_server_member(ctx, user_or_image)
364 | if not user:
365 | url = user_or_image
366 | else:
367 | url = get_avatar_url(user)
368 | async with aiohttp.ClientSession() as session:
369 | async with session.get("http://localhost:8443/api/beautiful?image={}".format(url)) as f:
370 | if f.status == 200:
371 | await ctx.send(file=discord.File(f.content, "beautiful.{}".format(f.headers["Content-Type"].split("/")[1])))
372 | elif f.status == 400:
373 | return await ctx.send(await f.text())
374 | else:
375 | return await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
376 |
377 | @commands.command(usage="[user | image]")
378 | async def gay(self, ctx, user_or_imagelink: str=None):
379 | """Turn someone or yourself gay"""
380 | channel = ctx.message.channel
381 | author = ctx.message.author
382 | if not user_or_imagelink:
383 | if ctx.message.attachments:
384 | url = ctx.message.attachments[0].url
385 | else:
386 | url = get_avatar_url(author)
387 | else:
388 | user = arg.get_server_member(ctx, user_or_imagelink)
389 | if not user:
390 | url = user_or_imagelink
391 | else:
392 | url = get_avatar_url(user)
393 | async with aiohttp.ClientSession() as session:
394 | async with session.get("http://localhost:8443/api/gay?image={}".format(url)) as f:
395 | if f.status == 200:
396 | await ctx.send(file=discord.File(f.content, "gay.{}".format(f.headers["Content-Type"].split("/")[1])))
397 | elif f.status == 400:
398 | return await ctx.send(await f.text())
399 | else:
400 | return await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
401 |
402 | @commands.command()
403 | @commands.cooldown(1, 5, commands.BucketType.user)
404 | async def trumptweet(self, ctx, *, text: str):
405 | """Make trump say something on twitter"""
406 | channel = ctx.channel
407 | author = ctx.author
408 | if len(text) > 250:
409 | await ctx.send("No more than 250 characters :no_entry:")
410 | return
411 | async with aiohttp.ClientSession() as session:
412 | async with session.get("http://localhost:8443/api/trump?text={}".format(text)) as f:
413 | if f.status == 200:
414 | await ctx.send(file=discord.File(f.content, "trump.png"))
415 | elif f.status == 400:
416 | return await ctx.send(await f.text())
417 | else:
418 | return await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
419 |
420 | @commands.command()
421 | @commands.cooldown(1, 5, commands.BucketType.user)
422 | async def tweet(self, ctx, user: str, *, text: commands.clean_content(fix_channel_mentions=True)):
423 | """Tweet from your or another users account"""
424 | await ctx.channel.trigger_typing()
425 | user = arg.get_server_member(ctx, user)
426 | if not user:
427 | return await ctx.send("I could not find that user :no_entry:")
428 | if len(text) > 250:
429 | await ctx.send("No more than 250 characters :no_entry:")
430 | return
431 | retweets = randint(1, ctx.guild.member_count)
432 | likes = randint(1, ctx.guild.member_count)
433 | urls = list(map(lambda x: x.avatar_url_as(format="png", size=64), random.sample(ctx.guild.members, min(ctx.guild.member_count, 10, likes))))
434 | data = {"displayName": user.display_name, "name": user.name, "avatarUrl": user.avatar_url_as(format="png", size=128), "urls": urls, "likes": likes, "retweets": retweets, "text": text}
435 | async with aiohttp.ClientSession() as session:
436 | async with session.post("http://localhost:8443/api/tweet", json=data, headers={"Content-Type": "application/json"}) as f:
437 | if f.status == 200:
438 | await ctx.send(file=discord.File(f.content, "tweet.png"))
439 | elif f.status == 400:
440 | return await ctx.send(await f.text())
441 | else:
442 | return await ctx.send("Oops something went wrong! Status code: {}".format(f.status))
443 |
444 | @commands.command()
445 | @commands.cooldown(1, 5, commands.BucketType.user)
446 | async def scroll(self, ctx, *, text: str):
447 | """The terrible truth"""
448 | channel = ctx.message.channel
449 | author = ctx.message.author
450 | if len(text) > 80:
451 | await ctx.send("No more than 80 characters :no_entry:")
452 | return
453 | img = Image.open("scroll-meme.png")
454 | draw = ImageDraw.Draw(img)
455 | n = 0
456 | m = 12
457 | char = 12
458 | times = 0
459 | size = 20
460 | description = ""
461 | if (math.ceil(len(str(text))/char)+1) >=6:
462 | for x in range((math.ceil(len(str(text))/char)+1) - 6):
463 | size -= 3
464 | char += 1
465 | for x in range(math.ceil(len(str(text))/char)+1):
466 | if [x for x in text if " " in x]:
467 | for x in range(len([x for x in text if " " in x])+1):
468 | while text[m-1:m] != " " and m != 0 and m != len(str(text)):
469 | m -= 1
470 | times += char
471 | if m == 0:
472 | n = times - char
473 | m = times
474 | description += text[n:m] + "\n"
475 | n = m
476 | m += char
477 | font = ImageFont.truetype("arial.ttf", size)
478 | draw.text((95, 285), description, (0, 0, 0), font=font)
479 | await send_file(ctx, img)
480 |
481 | @commands.command(aliases=["color", "hex"])
482 | @commands.cooldown(1, 5, commands.BucketType.user)
483 | async def colour(self, ctx, *, colour: str=None):
484 | """View a colours hex code and RGB and a image with the colour, if a colour is not specified it will get a random one"""
485 | if not colour:
486 | colour = ''.join([random.choice('0123456789ABCDEF') for x in range(6)])
487 | colour = discord.Colour(int(colour, 16))
488 | colourname = str(colour)
489 | for x in colours:
490 | if str(colour).lower() == colours[x].lower():
491 | if not re.match("(?:[a-f A-F]|[0-9]){6}" if "#" not in colour else "#(?:[a-f A-F]|[0-9]){6}", colour):
492 | return await ctx.send("Invalid hex :no_entry:")
493 | colourname = x.title()
494 | image = Image.new('RGBA', (100, 100), (colour.r, colour.g, colour.b))
495 | image.save("result.png")
496 | s=discord.Embed(colour=colour, description="Hex: {}\nRGB: ({}, {}, {})".format(str(colour), colour.r, colour.g, colour.b))
497 | s.set_image(url="attachment://result.png")
498 | s.set_author(name=colourname, icon_url="attachment://result.png")
499 | await ctx.send(file=discord.File("result.png", "result.png"), embed=s)
500 | try:
501 | os.remove("result.png")
502 | except:
503 | pass
504 | return
505 | colourname = colour
506 | for x in colours:
507 | if x.title() == colour.title():
508 | colourname = colours[x].lower()
509 | colour = colours[x].lower()
510 | elif "#" + str(colour).replace("#", "").lower() == colours[x].lower():
511 | if not re.match("(?:[a-f A-F]|[0-9]){6}" if "#" not in colour else "#(?:[a-f A-F]|[0-9]){6}", colour):
512 | return await ctx.send("Invalid hex :no_entry:")
513 | colourname = x.title()
514 | if not re.match("(?:[a-f A-F]|[0-9]){6}" if "#" not in colour else "#(?:[a-f A-F]|[0-9]){6}", colour):
515 | return await ctx.send("Invalid hex :no_entry:")
516 | image = Image.new('RGBA', (100, 100), (discord.Colour(int(colour.replace("#", ""), 16)).r, discord.Colour(int(colour.replace("#", ""), 16)).g, discord.Colour(int(colour.replace("#", ""), 16)).b))
517 | image.save("result.png")
518 | s=discord.Embed(colour=discord.Colour(int(colour.replace("#", ""), 16)), description="Hex: {}\nRGB: ({}, {}, {})".format("#" + str(colour).replace("#", ""), discord.Colour(int(colour.replace("#", ""), 16)).r, discord.Colour(int(colour.replace("#", ""), 16)).g, discord.Colour(int(colour.replace("#", ""), 16)).b))
519 | s.set_image(url="attachment://result.png")
520 | s.set_author(name=colourname, icon_url="attachment://result.png")
521 | await ctx.send(file=discord.File("result.png", "result.png"), embed=s)
522 | try:
523 | os.remove("result.png")
524 | except:
525 | pass
526 |
527 | @commands.command()
528 | @commands.cooldown(1, 5, commands.BucketType.user)
529 | async def drift(self, ctx, user: discord.Member, textleft: str, textright: str=None):
530 | """Drift away from something, any words over 10 characters will be ignored"""
531 | channel = ctx.message.channel
532 | author = ctx.message.author
533 | try:
534 | if len(textright) > 50:
535 | await ctx.send("No more than 50 characters on the right sign :no_entry:")
536 | return
537 | except:
538 | pass
539 | if len(textleft) > 50:
540 | await ctx.send("No more than 50 characters on the left sign :no_entry:")
541 | return
542 | img = Image.open("drift-meme.png")
543 | draw = ImageDraw.Draw(img)
544 | n = 0
545 | m = 10
546 | number = 0
547 | times = 0
548 | size = 20
549 | description = ""
550 | for x in range(math.ceil(len(str(textleft))/10)+1):
551 | number += 1
552 | if [x for x in textleft if " " in x]:
553 | for x in range(len([x for x in textleft if " " in x])+1):
554 | while textleft[m-1:m] != " " and m != 0 and m != len(str(textleft)):
555 | m -= 1
556 | times += 10
557 | if m == 0:
558 | n = times - 10
559 | m = times
560 | if number > 4:
561 | size -= 3
562 | description += textleft[n:m] + "\n"
563 | n = m
564 | m += 10
565 | a = 0
566 | b = 13
567 | number2 = 0
568 | times2 = 0
569 | size2 = 20
570 | description2 = ""
571 | if textright:
572 | for x in range(math.ceil(len(str(textright))/13)+1):
573 | number2 += 1
574 | if [x for x in textright if " " in x]:
575 | for x in range(len([x for x in textright if " " in x])+1):
576 | while textright[b-1:b] != " " and b != 0 and b != len(str(textright)):
577 | b -= 1
578 | times += 13
579 | if b == 0:
580 | a = times - 13
581 | b = times
582 | if number2 > 5:
583 | size2 -= 3
584 | description2 += textright[a:b] + "\n"
585 | a = b
586 | b += 13
587 | font = ImageFont.truetype("arial.ttf", size)
588 | font2 = ImageFont.truetype("arial.ttf", size2)
589 | draw.text((125, 60), description, (255, 255, 255), font=font)
590 | if description2 != "":
591 | draw.text((265, 60), description2, (255, 255, 255), font=font2)
592 | img2 = getImage(user.avatar_url.replace("gif", "png").replace("webp", "png"))
593 | img2 = img2.resize((23, 23))
594 | img.paste(img2, (270, 335))
595 | await send_file(ctx, img)
596 |
597 | @commands.command(usage="[user | image]")
598 | async def commoncolour(self, ctx, user_or_imagelink: str=None):
599 | """Returns the most common colour from an image"""
600 | if not user_or_imagelink:
601 | if ctx.message.attachments:
602 | url = ctx.message.attachments[0].url
603 | else:
604 | url = ctx.author.avatar_url
605 | else:
606 | user = await arg.get_member(ctx, user_or_imagelink)
607 | if not user:
608 | url = user_or_imagelink
609 | else:
610 | url = user.avatar_url
611 | try:
612 | image = getImage(url).convert("RGB")
613 | except:
614 | return await ctx.send("Invalid Image/User :no_entry:")
615 | pixdata = image.load()
616 | entries = {}
617 | for y in range(image.size[1]):
618 | for x in range(image.size[0]):
619 | if pixdata[x, y] not in entries:
620 | entries[pixdata[x, y]] = 1
621 | else:
622 | entries[pixdata[x, y]] += 1
623 | image = Image.new("RGBA", (300, 50), sorted(entries.items(), key=lambda x: x[1], reverse=True)[0][0])
624 | hex = '%02x%02x%02x' % sorted(entries.items(), key=lambda x: x[1], reverse=True)[0][0]
625 | await ctx.send(file=get_file(image), embed=discord.Embed(title="Most Common Colour: #{}".format(hex.upper()), description="RGB: {}".format(sorted(entries.items(), key=lambda x: x[1], reverse=True)[0][0]), colour=discord.Colour(int(hex, 16))).set_image(url="attachment://result.png").set_thumbnail(url=url))
626 | del entries
627 |
628 |
629 | def get_avatar_url(user):
630 | if ".gif" in user.avatar_url:
631 | return user.avatar_url
632 | else:
633 | return user.avatar_url_as(format="png")
634 |
635 |
636 | async def send_file(ctx, img):
637 | temp = BytesIO()
638 | img.save(temp, "png")
639 | temp.seek(0)
640 | await ctx.send(file=discord.File(temp, "result.png"))
641 |
642 | def get_file(img):
643 | temp = BytesIO()
644 | img.save(temp, "png")
645 | temp.seek(0)
646 | return discord.File(temp, "result.png")
647 |
648 | def get_file_gif(img, frames):
649 | temp = BytesIO()
650 | img.save(temp, "gif", save_all=True, append_images=frames)
651 | temp.seek(0)
652 | return discord.File(temp, "result.gif")
653 |
654 | def getImage(url):
655 | r = requests.get(url, stream=True, timeout=3)
656 | img = Image.open(r.raw).convert('RGBA')
657 | return img
658 |
659 | def setup(bot, connection):
660 | bot.add_cog(image(bot, connection))
661 |
--------------------------------------------------------------------------------
/Sx4/cogs/logs.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | from utils import checks
4 | from datetime import datetime
5 | from collections import deque, defaultdict
6 | import os
7 | import re
8 | from . import owner as dev
9 | import logging
10 | import asyncio
11 | import rethinkdb as r
12 | import random
13 | from utils import arghelp
14 | import time
15 | import discord
16 | from discord.ext import commands
17 | from random import randint
18 | from random import choice as randchoice
19 | from discord.ext.commands import CommandNotFound
20 |
21 | class logs:
22 | def __init__(self, bot, connection):
23 | self.bot = bot
24 | self.db = connection
25 |
26 | @commands.group(usage="")
27 | async def logs(self, ctx):
28 | """Log actions in your server"""
29 | server = ctx.guild
30 | if ctx.invoked_subcommand is None:
31 | await arghelp.send(self.bot, ctx)
32 | else:
33 | r.table("logs").insert({"id": str(server.id), "channel": None, "toggle": False}).run(self.db, durability="soft")
34 |
35 | @logs.command()
36 | @checks.has_permissions("manage_guild")
37 | async def channel(self, ctx, channel: discord.TextChannel=None):
38 | """Set the channel where you want stuff to be logged"""
39 | server = ctx.guild
40 | serverdata = r.table("logs").get(str(server.id))
41 | if not channel:
42 | channel = ctx.message.channel
43 | serverdata.update({"channel": str(channel.id)}).run(self.db, durability="soft")
44 | await ctx.send("Logs will be recorded in <#{}> if toggled on <:done:403285928233402378>".format(channel.id))
45 |
46 | @logs.command()
47 | @checks.has_permissions("manage_guild")
48 | async def toggle(self, ctx):
49 | """Toggle logs on or off"""
50 | server = ctx.guild
51 | serverdata = r.table("logs").get(str(server.id))
52 | if serverdata["toggle"].run(self.db, durability="soft") == False:
53 | serverdata.update({"toggle": True}).run(self.db, durability="soft")
54 | await ctx.send("Logs have been toggled **on** <:done:403285928233402378>")
55 | return
56 | if serverdata["toggle"].run(self.db, durability="soft") == True:
57 | serverdata.update({"toggle": False}).run(self.db, durability="soft")
58 | await ctx.send("Logs have been toggled **off** <:done:403285928233402378>")
59 | return
60 |
61 | @logs.command()
62 | async def stats(self, ctx):
63 | server = ctx.guild
64 | serverdata = r.table("logs").get(str(server.id)).run(self.db, durability="soft")
65 | s=discord.Embed(colour=0xffff00)
66 | s.set_author(name="Logs Settings", icon_url=self.bot.user.avatar_url)
67 | s.add_field(name="Status", value="Enabled" if serverdata["toggle"] else "Disabled")
68 | s.add_field(name="Channel", value=server.get_channel(int(serverdata["channel"])).mention if serverdata["channel"] and server.get_channel(int(serverdata["channel"])) else "Not set")
69 | await ctx.send(embed=s)
70 |
71 | def setup(bot, connection):
72 | bot.add_cog(logs(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/owner.py:
--------------------------------------------------------------------------------
1 | import discord
2 | import asyncio
3 | from discord.ext import commands
4 | from random import choice as randchoice
5 | import time
6 | import requests
7 | import datetime
8 | import rethinkdb as r
9 | from discord.ext.commands.view import StringView
10 | import json
11 | import inspect
12 | from utils import arg
13 | import math
14 | import functools
15 | import psutil
16 | from PIL import Image, ImageDraw, ImageFont, ImageOps
17 | from utils import checks
18 | import os
19 |
20 | execution_times = {}
21 |
22 | def log(method):
23 | @functools.wraps(method)
24 | async def timed(*args, **kw):
25 | memory_start = psutil.Process(os.getpid()).memory_info().rss/1000000
26 | start_time = time.time()
27 | result = await method(*args, **kw)
28 | execution_time = int((time.time() - start_time) * 1000)
29 | memory_gained = (psutil.Process(os.getpid()).memory_info().rss/1000000) - memory_start
30 |
31 | method_name = method.__module__ + "." + method.__name__
32 | if method_name not in execution_times:
33 | execution_times[method_name] = {"average": 0, "data_points": 0, "memory_average": 0}
34 |
35 | entry = execution_times[method_name]
36 |
37 | new_average = ((entry["average"] * entry["data_points"]) + execution_time)/(entry["data_points"] + 1)
38 | new_average_memory = ((entry["memory_average"] * entry["data_points"]) + memory_gained)/(entry["data_points"] + 1)
39 |
40 | entry["average_memory"] = new_average_memory
41 | entry["average"] = new_average
42 | entry["data_points"] += 1
43 |
44 | if "min_execution_time" not in entry:
45 | entry["min_execution_time"] = execution_time
46 |
47 | entry["min_execution_time"] = min(entry["min_execution_time"], execution_time)
48 |
49 | if "max_execution_time" not in entry:
50 | entry["max_execution_time"] = execution_time
51 |
52 | entry["max_execution_time"] = max(entry["max_execution_time"], execution_time)
53 |
54 | if "min_memory_gained" not in entry:
55 | entry["min_memory_gained"] = memory_gained
56 |
57 | entry["min_memory_gained"] = min(entry["min_memory_gained"], memory_gained)
58 |
59 | if "max_memory_gained" not in entry:
60 | entry["max_memory_gained"] = memory_gained
61 |
62 | entry["max_memory_gained"] = max(entry["max_memory_gained"], memory_gained)
63 | print(entry)
64 | return result
65 | return timed
66 |
67 | class owner:
68 | def __init__(self, bot, connection):
69 | self.bot = bot
70 | self.db = connection
71 |
72 | @commands.command(hidden=True)
73 | @checks.is_owner()
74 | async def code(self, ctx, *, command: str=None):
75 | if not command:
76 | command = ctx.command
77 | else:
78 | command = self.bot.get_command(command)
79 | if not command:
80 | return await ctx.send("Invalid command :no_entry:")
81 | wrap = "```py\n{}```"
82 | code = inspect.getsource(command.callback)
83 | code = code.replace("```", "\```")
84 | if len(code) > 1990:
85 | pages = math.ceil(len(code)/1990)
86 | n = 0
87 | m = 1990
88 | for x in range(pages):
89 | if n != 0:
90 | while code[n-1:n] != "\n":
91 | n -= 1
92 | while code[m-1:m] != "\n":
93 | m -= 1
94 | await ctx.send(wrap.format(code[n:m]))
95 | n += 1990
96 | m += 1990
97 | else:
98 | await ctx.send(wrap.format(code))
99 |
100 | @commands.command(hidden=True)
101 | @checks.is_owner()
102 | async def collage(self, ctx):
103 | pixels = 64
104 | width = math.ceil(math.sqrt(ctx.guild.member_count)*pixels)
105 | height = math.ceil(math.sqrt(ctx.guild.member_count)*pixels)
106 | background = Image.new("RGBA", (width+pixels, height+pixels), (0, 0, 0, 0))
107 | x, y, i = 0, 0, 0
108 | await ctx.send("Creating collage...")
109 | t1 = time.perf_counter()
110 | for member in ctx.guild.members:
111 | i += 1
112 | print(str(member) + " ({}/{})".format(i, ctx.guild.member_count))
113 | try:
114 | with open("avatar.png", "wb") as f:
115 | f.write(requests.get(member.avatar_url).content)
116 | image = Image.open("avatar.png").convert("RGBA")
117 | image = image.resize((pixels, pixels))
118 | background.paste(image, (x, y))
119 | x += pixels
120 | if x >= width:
121 | y += pixels
122 | x = 0
123 | print("Successful")
124 | except Exception as e:
125 | print(e)
126 | background.save("collage.png")
127 | t2 = time.perf_counter()
128 | try:
129 | await ctx.send(content="Executed in **{}ms**".format(round((t2-t1)*1000)), file=discord.File("collage.png", "collage.png"))
130 | except:
131 | await ctx.send("Executed in **{}ms**\n\nImage saved in hosters files".format(round((t2-t1)*1000)))
132 | return os.remove("avatar.png")
133 | try:
134 | os.remove("collage.png")
135 | os.remove("avatar.png")
136 | except:
137 | pass
138 |
139 | @commands.command(hidden=True, name="as")
140 | @checks.is_main_owner()
141 | async def _as(self, ctx, user: str, command_name: str, *, args: str=""):
142 | user = await arg.get_member(ctx, user)
143 | if not user:
144 | return await ctx.send("You're retarded that's not a user :no_entry:")
145 | else:
146 | ctx.author = user
147 | ctx.message.author = user
148 | if " " in command_name:
149 | command = command_name.split(" ", 1)
150 | try:
151 | command = self.bot.all_commands[command[0]].all_commands[command[1]]
152 | except KeyError:
153 | return await ctx.send("Invalid command :no_entry:")
154 | else:
155 | try:
156 | command = self.bot.all_commands[command_name]
157 | except KeyError:
158 | return await ctx.send("Invalid command :no_entry:")
159 | ctx.message.content = ctx.prefix + command_name + " " + args
160 | ctx.view = StringView(args)
161 | await command.invoke(ctx)
162 |
163 | @commands.command(hidden=True)
164 | @checks.is_owner()
165 | async def commandlog(self, ctx, *, code: str=None):
166 | if not code:
167 | with open("commandlog.json", "wb") as f:
168 | f.write(json.dumps(r.table("botstats").get("stats")["commandlog"].run(self.db, durability="soft")).encode())
169 | else:
170 | with open("commandlog.json", "wb") as f:
171 | f.write(json.dumps(list(eval(code.replace("data", 'r.table("botstats").get("stats")["commandlog"].run(self.db, durability="soft")')))).encode())
172 | await ctx.send(file=discord.File("commandlog.json"))
173 | os.remove("commandlog.json")
174 |
175 | @commands.command(hidden=True)
176 | @checks.is_owner()
177 | async def blacklistuser(self, ctx, user: str):
178 | user = await arg.get_member(ctx, user)
179 | r.table("blacklist").insert({"id": "owner", "users": []}).run(self.db, durability="soft")
180 | data = r.table("blacklist").get("owner")
181 | if str(user.id) not in data["users"].run(self.db, durability="soft"):
182 | data.update({"users": r.row["users"].append(str(user.id))}).run(self.db, durability="soft")
183 | await ctx.send("{} has been blacklisted.".format(user))
184 | elif str(user.id) in data["users"].run(self.db, durability="soft"):
185 | data.update({"users": r.row["users"].difference([str(user.id)])}).run(self.db, durability="soft")
186 | await ctx.send("{} is no longer blacklisted".format(user))
187 |
188 | @commands.command(hidden=True)
189 | @checks.is_owner()
190 | async def disable(self, ctx, *, command: str):
191 | command = self.bot.get_command(command)
192 | if not command:
193 | return await ctx.send("Invalid command :no_entry:")
194 | command.enabled = not command.enabled
195 | if command.enabled == False:
196 | await ctx.send("`{}` has been disabled.".format(command))
197 | else:
198 | await ctx.send("`{}` has been enabled.".format(command))
199 |
200 | @commands.command(hidden=True)
201 | async def modules(self, ctx):
202 | unloaded, loaded = [], []
203 | list = [x.replace(".py", "") for x in os.listdir("cogs") if ".py" in x]
204 | for x in list:
205 | if not self.bot.get_cog(x):
206 | unloaded.append(x)
207 | else:
208 | loaded.append(x)
209 | s=discord.Embed(title="Modules ({})".format(len(list)))
210 | s.add_field(name="Loaded ({})".format(len(loaded)), value=", ".join(loaded) if loaded != [] else "None", inline=False)
211 | s.add_field(name="Unloaded ({})".format(len(unloaded)), value=", ".join(unloaded) if unloaded != [] else "None", inline=False)
212 | await ctx.send(embed=s)
213 |
214 | @commands.command(hidden=True)
215 | @checks.is_owner()
216 | async def updateavatar(self, ctx, *, url=None):
217 | if not url:
218 | if ctx.message.attachments:
219 | url = ctx.message.attachments[0].url
220 | else:
221 | await ctx.send("Provide a valid image :no_entry:")
222 | return
223 | avatar = requests.get(url).content
224 | try:
225 | await self.bot.user.edit(password=None, avatar=avatar)
226 | except:
227 | return await ctx.send("Clap you've changed my profile picture too many times")
228 | await ctx.send("I have changed my profile picture")
229 |
230 | @commands.command(hidden=True)
231 | @checks.is_owner()
232 | async def httpunban(self, ctx, server_id: str, user_id: str):
233 | user = await self.bot.get_user_info(user_id)
234 | server = self.bot.get_guild(server_id)
235 | await self.bot.http.unban(user_id, server_id)
236 | await ctx.send("I have unbanned **{}** from **{}**".format(user, server))
237 |
238 | @commands.command(hidden=True)
239 | @checks.is_owner()
240 | async def msg(self, ctx, channel_id, *, text):
241 | await ctx.message.delete()
242 | await self.bot.http.send_message(channel_id, text)
243 |
244 | @commands.command(hidden=True)
245 | @checks.is_owner()
246 | async def shutdown(self, ctx):
247 | await ctx.send("Shutting down...")
248 | await self.bot.logout()
249 |
250 | async def on_guild_join(self, guild):
251 | channel = self.bot.get_channel(493439822682259497)
252 | if channel:
253 | guilds = len(self.bot.guilds)
254 | if guilds % 100 == 0:
255 | await channel.send("{:,} servers :tada:".format(guilds))
256 |
257 | async def on_guild_remove(self, guild):
258 | channel = self.bot.get_channel(493439822682259497)
259 | if channel:
260 | guilds = len(self.bot.guilds)
261 | if guilds % 100 != 0:
262 | for x in await channel.history(limit=1).flatten():
263 | if int(x.content.split(" ")[0].replace(",", "")) > guilds:
264 | await x.delete()
265 |
266 | async def on_command(self, ctx, *args, **kwargs):
267 | guild = self.bot.get_guild(330399610273136641)
268 | channel = guild.get_channel(507684635673886742)
269 | webhook = discord.utils.get(await channel.webhooks(), id=507684441020170251)
270 | if checks.is_owner_c(ctx.author):
271 | ctx.command.reset_cooldown(ctx)
272 | try:
273 | s=discord.Embed(colour=0xffff00, timestamp=ctx.message.edited_at if ctx.message.edited_at else ctx.message.created_at)
274 | s.add_field(name="Message", value="Content: {}\nID: {}".format(ctx.message.content, ctx.message.id), inline=False)
275 | s.add_field(name="Channel", value="Name: {}\nID: {}".format(ctx.channel.name, ctx.channel.id), inline=False)
276 | s.add_field(name="Guild", value="Name: {}\nID: {}\nShard: {}\nMember Count: {:,}".format(ctx.guild.name, ctx.guild.id, ctx.guild.shard_id + 1, ctx.guild.member_count), inline=False)
277 | s.add_field(name="Author", value="User: {}\nID: {}".format(ctx.author, ctx.author.id), inline=False)
278 | s.add_field(name="Command", value="Prefix: {}\nCommand: {}\nArguments: {}".format(ctx.prefix, ctx.command, kwargs), inline=False)
279 | s.add_field(name="Attachments", value="\n".join(map(lambda x: x.url, ctx.message.attachments)) if ctx.message.attachments else "None", inline=False)
280 | await webhook.send(embed=s)
281 | except Exception as e:
282 | await webhook.send(e)
283 |
284 | def setup(bot, connection):
285 | bot.add_cog(owner(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/page.py:
--------------------------------------------------------------------------------
1 | import discord
2 | import asyncio
3 | from discord.ext import commands
4 | from utils.PagedResult import PagedResult
5 | from utils.PagedResult import PagedResultData
6 | from random import choice as randchoice
7 | import time
8 | import datetime
9 | import random
10 | from utils import checks
11 | import numbers
12 | import os
13 | from random import choice
14 | from random import randint
15 | from copy import deepcopy
16 | from collections import namedtuple, defaultdict, deque
17 | from copy import deepcopy
18 | from enum import Enum
19 | import asyncio
20 | from difflib import get_close_matches
21 |
22 | class page:
23 | def __init__(self, bot, connection):
24 | self.bot = bot
25 | self.db = connection
26 |
27 | @commands.command(no_pm=True, aliases=["sroles", "roles"])
28 | async def serverroles(self, ctx):
29 | server = ctx.message.guild
30 | channel = ctx.message.channel
31 | author = ctx.message.author
32 |
33 | if server.id not in PagedResultData.paged_results:
34 | PagedResultData.paged_results[server.id] = dict()
35 |
36 | if channel.id not in PagedResultData.paged_results[server.id]:
37 | PagedResultData.paged_results[server.id][channel.id] = dict()
38 |
39 | paged_result = PagedResult(ctx.guild.roles[::-1], lambda role: role.mention)
40 | paged_result.list_indexes = True
41 | paged_result.selectable = False
42 |
43 | message = await channel.send(embed=paged_result.get_current_page_embed())
44 |
45 | paged_result.message_id = message.id
46 |
47 | PagedResultData.paged_results[server.id][channel.id][author.id] = paged_result
48 |
49 | @commands.command()
50 | async def members(self, ctx):
51 | server = ctx.message.guild
52 | channel = ctx.message.channel
53 | author = ctx.message.author
54 |
55 | if server.id not in PagedResultData.paged_results:
56 | PagedResultData.paged_results[server.id] = dict()
57 |
58 | if channel.id not in PagedResultData.paged_results[server.id]:
59 | PagedResultData.paged_results[server.id][channel.id] = dict()
60 |
61 | paged_result = PagedResult(list(server.members), lambda member: member.mention)
62 | paged_result.list_indexes = True
63 | paged_result.selectable = True
64 |
65 | async def selected(event):
66 | joined_server = event.entry.joined_at.strftime("%d %b %Y %H:%M")
67 | joined_discord = event.entry.created_at.strftime("%d %b %Y %H:%M")
68 | if event.entry.status == discord.Status.online:
69 | status="Online<:online:361440486998671381>"
70 | if event.entry.status == discord.Status.idle:
71 | status="Idle<:idle:361440487233814528>"
72 | if event.entry.status == discord.Status.do_not_disturb:
73 | status="DND<:dnd:361440487179157505>"
74 | if event.entry.status == discord.Status.offline:
75 | status="Offline<:offline:361445086275567626>"
76 | description=""
77 | if not event.entry.activity:
78 | pass
79 | elif event.entry.activity:
80 | description="{} {}".format(event.entry.activity.type.name.title(), event.entry.activity.name)
81 | elif event.entry.activity.url:
82 | description="Streaming [{}]({})".format(event.entry.activity.name, event.entry.activity.url)
83 | s=discord.Embed(description=description, colour=event.entry.colour, timestamp=__import__('datetime').datetime.utcnow())
84 | s.set_author(name=event.entry.name, icon_url=event.entry.avatar_url)
85 | s.set_thumbnail(url=event.entry.avatar_url)
86 | s.add_field(name="Joined Discord", value=joined_discord)
87 | s.add_field(name="Joined {}".format(server .name), value=joined_server)
88 | s.add_field(name="Name", value="{}".format(event.entry.name))
89 | s.add_field(name="Nickname", value="{}".format(event.entry.nick))
90 | s.add_field(name="Discriminator", value="#{}".format(event.entry.discriminator))
91 | s.add_field(name="Status", value="{}".format(status))
92 | s.add_field(name="User's Colour", value="{}".format(event.entry.colour))
93 | s.add_field(name="User's ID", value="{}".format(event.entry.id))
94 | s.set_footer(text="Requested by {}".format(author))
95 | s.add_field(name="Highest Role", value=event.entry.top_role)
96 | s.add_field(name="Roles", value=len(event.entry.roles))
97 | await channel.send(embed=s)
98 |
99 | paged_result.on_select = selected
100 |
101 | message = await channel.send(embed=paged_result.get_current_page_embed())
102 |
103 | paged_result.message_id = message.id
104 |
105 | PagedResultData.paged_results[server.id][channel.id][author.id] = paged_result
106 |
107 | async def on_message(self, message):
108 | # Not sure how you store the other stuff but I suppose you do something like this
109 | server = message.guild
110 | channel = message.channel
111 | author = message.author
112 |
113 | paged_results = PagedResultData.paged_results
114 |
115 | paged_result = None
116 | if server.id in paged_results:
117 | if channel.id in paged_results[server.id]:
118 | if author.id in paged_results[server.id][channel.id]:
119 | paged_result = paged_results[server.id][channel.id][author.id]
120 |
121 | if paged_result is None:
122 | return
123 |
124 | page_message = None
125 |
126 | try:
127 | # Get message from paged_result.message_id and set message to it
128 | page_message = await channel.get_message(paged_result.message_id)
129 | except TypeError:
130 | pass
131 |
132 | if message.content == "next page":
133 | if paged_result.next_page():
134 | await message.delete()
135 | if page_message == None:
136 | # Send paged_result.get_current_page_embed() and set paged_result.message_id to its id
137 | temp_message = await channel.send(embed=paged_result.get_current_page_embed())
138 | paged_result.message_id = temp_message.id
139 | else:
140 | # Edit the message by paged_result.message_id to paged_result.get_current_page_embed()
141 | await page_message.edit(embed=paged_result.get_current_page_embed())
142 | elif message.content == "previous page":
143 | if paged_result.previous_page():
144 | await message.delete()
145 | if page_message == None:
146 | # Send paged_result.get_current_page_embed() and set paged_result.message_id to its id
147 | temp_message = await channel.send(embed=paged_result.get_current_page_embed())
148 | paged_result.message_id = temp_message.id
149 | else:
150 | # Edit the message by paged_result.message_id to paged_result.get_current_page_embed()
151 | await page_message.edit(embed=paged_result.get_current_page_embed())
152 | elif message.content.startswith("go to page "):
153 | number = None
154 | try:
155 | number = int(message.content[len("go to page "):])
156 | except ValueError:
157 | await channel.send("Invalid page number")
158 |
159 | return
160 |
161 | if paged_result.set_page(number):
162 | await message.delete()
163 | if page_message == None:
164 | # Send paged_result.get_current_page_embed() and set paged_result.message_id to its id
165 | temp_message = await channel.send(embed=paged_result.get_current_page_embed())
166 | paged_result.message_id = temp_message.id
167 | else:
168 | # Edit the message by paged_result.message_id to paged_result.get_current_page_embed()
169 | await page_message.edit(embed=paged_result.get_current_page_embed())
170 | else:
171 | await channel.send("Invalid page number")
172 | return
173 | elif message.content == "cancel":
174 | if page_message != None:
175 | # Delete message by paged_result.message_id
176 | await message.delete()
177 | await page_message.delete()
178 |
179 | del paged_results[server.id][channel.id][author.id]
180 |
181 | if paged_result.selectable:
182 | number = None
183 | try:
184 | number = int(message.content)
185 | except ValueError:
186 | return
187 |
188 | if number > 0 and number <= paged_result.entries_per_page:
189 | del paged_results[server.id][channel.id][author.id]
190 |
191 | await message.delete()
192 | await page_message.delete()
193 |
194 | await paged_result.select(number)
195 |
196 | def setup(bot, connection):
197 | bot.add_cog(page(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/serverlog.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | from datetime import datetime
4 | import os
5 | import re
6 | import logging
7 | import asyncio
8 | import random
9 | import time
10 | from utils import dateify
11 |
12 |
13 | class serverlog:
14 | """Shows when the bot joins and leaves a server"""
15 |
16 | def __init__(self, bot, connection):
17 | self.bot = bot
18 | self.db = connection
19 |
20 | async def on_guild_join(self, guild):
21 | try:
22 | server = guild
23 | s=discord.Embed(description="I am now in {:,} servers and connected to {:,} users".format(len(self.bot.guilds), len(self.bot.users)), colour=0x5fe468, timestamp=datetime.utcnow())
24 | s.set_author(name="Joined Server!", icon_url=self.bot.user.avatar_url)
25 | s.add_field(name="Server Name", value=server.name)
26 | s.add_field(name="Server ID", value=server.id)
27 | s.add_field(name="Server Owner", value="{}\n{}".format(server.owner, server.owner.id))
28 | s.add_field(name="Total members", value="{} members".format(len(server.members)))
29 | channels = server.text_channels
30 | try:
31 | if len(await server.invites()) > 0:
32 | for x in await server.invites():
33 | if x.max_age == 0:
34 | invite = x.url
35 | break
36 | else:
37 | invite = None
38 | except:
39 | invite = None
40 | try:
41 | if invite:
42 | s.add_field(name="Server Invite", value=invite)
43 | except:
44 | pass
45 | mutual = list(map(lambda x: x.name, sorted([x for x in self.bot.guilds if server.owner in x.members and x != server], key=lambda x: x.member_count, reverse=True)))
46 | if len(mutual) > 15:
47 | s.add_field(name="Mutual Servers (Owner)", value="\n".join(mutual[:15]) + "\n and {} more...".format(len(mutual)-15))
48 | else:
49 | s.add_field(name="Mutual Servers (Owner)", value="\n".join(mutual) if len(mutual) != 0 else "None")
50 | if server.icon_url:
51 | s.set_thumbnail(url=server.icon_url)
52 | else:
53 | s.set_thumbnail(url="https://cdn.discordapp.com/attachments/344091594972069888/396285725605363712/no_server_icon.png")
54 | await self.bot.get_channel(396013262514421761).send(embed=s)
55 | if server.system_channel:
56 | try:
57 | await server.system_channel.send("Thanks for adding me (I'm now in {:,} servers, Thank you for contributing)!\nMy prefix is `s?`\nAll my info and commands can be found in `s?help`\nIf you need any help feel free to join the support server: https://discord.gg/PqJNcfB".format(len(self.bot.guilds)))
58 | return
59 | except:
60 | pass
61 | for channel in channels:
62 | try:
63 | await channel.send("Thanks for adding me (I'm now in {:,} servers, Thank you for contributing)!\nMy prefix is `s?`\nAll my info and commands can be found in `s?help`\nIf you need any help feel free to join the support server: https://discord.gg/PqJNcfB".format(len(self.bot.guilds)))
64 | break
65 | except:
66 | pass
67 | except Exception as e:
68 | await self.bot.get_channel(396013262514421761).send(e)
69 |
70 | async def on_guild_remove(self, guild):
71 | try:
72 | server = guild
73 | s=discord.Embed(description="I am now in {:,} servers and connected to {:,} users".format(len(self.bot.guilds), len(self.bot.users)), colour=0xf84b50, timestamp=datetime.utcnow())
74 | s.set_author(name="Left Server!", icon_url=self.bot.user.avatar_url)
75 | s.add_field(name="Server Name", value=server.name)
76 | s.add_field(name="Server ID", value=server.id)
77 | s.add_field(name="Server Owner", value="{}\n{}".format(server.owner, server.owner.id))
78 | s.add_field(name="Total members", value="{} members".format(len(server.members)))
79 | try:
80 | s.add_field(name="Stayed For", value=dateify.get((datetime.utcnow() - server.me.joined_at).total_seconds()), inline=False)
81 | except Exception as e:
82 | pass
83 | if server.icon_url:
84 | s.set_thumbnail(url=server.icon_url)
85 | else:
86 | s.set_thumbnail(url="https://cdn.discordapp.com/attachments/344091594972069888/396285725605363712/no_server_icon.png")
87 | await self.bot.get_channel(396013262514421761).send(embed=s)
88 | except Exception as e:
89 | await self.bot.get_channel(396013262514421761).send(e)
90 |
91 |
92 | def setup(bot, connection):
93 | bot.add_cog(serverlog(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/serverpost.py:
--------------------------------------------------------------------------------
1 | import discord
2 | import asyncio
3 | from discord.ext import commands
4 | from random import choice as randchoice
5 | import time
6 | import datetime
7 | from utils import checks
8 | from urllib.parse import urlencode
9 | from urllib.request import Request, urlopen
10 | import requests
11 | from cogs import mod
12 | from utils import Token
13 | import aiohttp
14 | import json
15 | import traceback
16 | import sys
17 | import os
18 | import subprocess
19 |
20 | dbltoken = Token.dbl()
21 | dbotspwtoken = Token.dbpw()
22 | botspacetoken = Token.botlistspace()
23 | dbpwurl = "https://discord.bots.gg/api/v1/bots/440996323156819968/stats"
24 | url = "https://discordbots.org/api/bots/440996323156819968/stats"
25 | botspaceurl = "https://api.botlist.space/v1/bots/440996323156819968/"
26 | headers = {"Authorization" : dbltoken}
27 | headersdb = {"Authorization" : dbotspwtoken, "Content-Type" : "application/json"}
28 | headersbs = {"Authorization" : botspacetoken, "Content-Type" : "application/json"}
29 |
30 | class serverpost:
31 | def __init__(self, bot, connection):
32 | self.bot = bot
33 | self.db = connection
34 | self.task = bot.loop.create_task(self.server_post())
35 |
36 | def __unload(self):
37 | self.task.cancel()
38 |
39 | @commands.command(hidden=True)
40 | @checks.is_owner()
41 | async def post(self, ctx):
42 | dblpayloadservers = {"server_count": len(self.bot.guilds), "shard_count": self.bot.shard_count}
43 | payloadservers = {"server_count": len(self.bot.guilds), "shards": self.bot.shard_count}
44 | dbpwpayload = {"guildCount": len(self.bot.guilds), "shardCount": self.bot.shard_count}
45 | s=discord.Embed()
46 | s.set_author(name="Server Count Posting", icon_url=self.bot.user.avatar_url)
47 | try:
48 | requests.post(url, data=dblpayloadservers, headers=headers)
49 | s.add_field(name="Discord Bot List", value="Posted")
50 | except Exception as e:
51 | s.add_field(name="Discord Bot List", value=e)
52 | try:
53 | requests.post(dbpwurl, data=dbpwpayload, headers=headersdb)
54 | s.add_field(name="Discord Bots.pw", value="Posted")
55 | except Exception as e:
56 | s.add_field(name="Discord Bots.pw", value=e)
57 | try:
58 | requests.post(botspaceurl, data=json.dumps(payloadservers), headers=headersbs)
59 | s.add_field(name="BotList.Space", value="Posted")
60 | except Exception as e:
61 | s.add_field(name="BotList.Space", value=e)
62 | await ctx.send(embed=s)
63 |
64 |
65 | async def server_post(self):
66 | while not self.bot.is_closed():
67 | dblpayloadservers = {"server_count": len(self.bot.guilds), "shard_count": self.bot.shard_count}
68 | payloadservers = {"server_count": len(self.bot.guilds), "shards": self.bot.shard_count}
69 | dbpwpayload = {"guildCount": len(self.bot.guilds), "shardCount": self.bot.shard_count}
70 | try:
71 | requests.post(url, data=dblpayloadservers, headers=headers)
72 | except:
73 | pass
74 | try:
75 | requests.post(dbpwurl, data=json.dumps(dbpwpayload), headers=headersdb)
76 | except:
77 | pass
78 | try:
79 | requests.post(botspaceurl, data=json.dumps(payloadservers), headers=headersbs)
80 | except:
81 | pass
82 | await asyncio.sleep(3600)
83 |
84 | def setup(bot, connection):
85 | bot.add_cog(serverpost(bot, connection))
--------------------------------------------------------------------------------
/Sx4/cogs/status.py:
--------------------------------------------------------------------------------
1 | import os
2 | import discord
3 | from discord.ext import commands
4 | from discord.utils import find
5 | from random import randint
6 | import asyncio
7 |
8 | class status:
9 | """Bot Status"""
10 |
11 | def __init__(self, bot, connection):
12 | self.bot = bot
13 | self.db = connection
14 | self._task = bot.loop.create_task(self.display_status())
15 |
16 | def __unload(self):
17 | self._task.cancel()
18 |
19 | async def display_status(self):
20 | i = 0
21 | while not self.bot.is_closed():
22 | try:
23 | statuses = [
24 | "{:,} servers".format(len(self.bot.guilds)),
25 | "{:,} users".format(len(self.bot.users))
26 | ]
27 | new_status = statuses[i]
28 | await self.bot.change_presence(activity=discord.Activity(name=new_status, type=discord.ActivityType.watching))
29 | except Exception as e:
30 | await self.bot.get_channel(439745234285625355).send(e)
31 | if i == len(statuses) - 1:
32 | i = 0
33 | else:
34 | i += 1
35 | await asyncio.sleep(300)
36 |
37 | def setup(bot, connection):
38 | n = status(bot, connection)
39 | bot.add_cog(n)
--------------------------------------------------------------------------------
/Sx4/cogs/welcomer.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from discord.ext import commands
3 | from utils import checks
4 | from datetime import datetime
5 | from collections import deque, defaultdict
6 | import os
7 | import re
8 | from utils import arghelp, dateify
9 | from . import owner as dev
10 | import math
11 | from io import BytesIO
12 | from urllib.request import Request, urlopen
13 | import logging
14 | import rethinkdb as r
15 | import aiohttp
16 | import urllib
17 | import requests
18 | import cogs.image as img
19 | from PIL import Image, ImageDraw, ImageFont, ImageOps
20 | import asyncio
21 | import random
22 | import time
23 |
24 | class welcomer:
25 | """Shows when a user joins and leaves a server"""
26 |
27 | def __init__(self, bot, connection):
28 | self.bot = bot
29 | self.db = connection
30 | self.avatar = None
31 |
32 | @commands.group(usage="")
33 | @checks.has_permissions("manage_messages")
34 | async def imgwelcomer(self, ctx):
35 | """Make the bot welcome people for you with an image"""
36 | if ctx.invoked_subcommand is None:
37 | await arghelp.send(self.bot, ctx)
38 | else:
39 | r.table("welcomer").insert({"id": str(ctx.guild.id), "toggle": False, "channel": None,
40 | "message": "{user.mention}, Welcome to **{server}**. Enjoy your time here! The server now has {server.members} members.",
41 | "message-leave": "**{user.name}** has just left **{server}**. Bye **{user.name}**!", "dm": False, "imgwelcomertog": False,
42 | "banner": None, "leavetoggle": True, "embed": False, "embedcolour": None}).run(self.db, durability="soft")
43 |
44 | @imgwelcomer.command(name="toggle")
45 | @checks.has_permissions("manage_messages")
46 | async def _toggle(self, ctx):
47 | "toggle image welcomer on or off"
48 | server = ctx.guild
49 | data = r.table("welcomer").get(str(server.id))
50 | if data["imgwelcomertog"].run(self.db, durability="soft") == True:
51 | data.update({"imgwelcomertog": False}).run(self.db, durability="soft")
52 | await ctx.send("Image Welcomer has been **Disabled**")
53 | return
54 | if data["imgwelcomertog"].run(self.db, durability="soft") == False:
55 | data.update({"imgwelcomertog": True}).run(self.db, durability="soft")
56 | await ctx.send("Image Welcomer has been **Enabled**")
57 | return
58 |
59 | @imgwelcomer.command()
60 | @checks.has_permissions("manage_messages")
61 | async def banner(self, ctx, banner: str=None):
62 | """Adds a banner to the image welcomer, when added the image welcomer changes resolution to 2560 x 1440 so a banner that size would be ideal"""
63 | author = ctx.author
64 | server = ctx.guild
65 | data = r.table("welcomer").get(str(server.id))
66 | if not banner:
67 | if ctx.message.attachments:
68 | try:
69 | banner = ctx.message.attachments[0].url
70 | data.update({"banner": banner}).run(self.db, durability="soft")
71 | return await ctx.send("Your banner for image welcomer has been set.")
72 | except:
73 | pass
74 | data.update({"banner": None}).run(self.db, durability="soft")
75 | await ctx.send("Your banner for image welcomer has been reset.")
76 | return
77 | if ".webp" in banner:
78 | return await ctx.send("WEBP files are not supported :no_entry:")
79 | try:
80 | img.getImage(banner)
81 | except:
82 | return await ctx.send("Invalid image url :no_entry:")
83 | data.update({"banner": banner}).run(self.db, durability="soft")
84 | await ctx.send("Your banner for image welcomer has been set.")
85 |
86 |
87 | @commands.group(usage="")
88 | async def welcomer(self, ctx):
89 | """Make the bot welcome people for you"""
90 | if ctx.invoked_subcommand is None:
91 | await arghelp.send(self.bot, ctx)
92 | else:
93 | r.table("welcomer").insert({"id": str(ctx.guild.id), "toggle": False, "channel": None,
94 | "message": "{user.mention}, Welcome to **{server}**. Enjoy your time here! The server now has {server.members} members.",
95 | "message-leave": "**{user.name}** has just left **{server}**. Bye **{user.name}**!", "dm": False, "imgwelcomertog": False,
96 | "banner": None, "leavetoggle": True, "embed": False, "embedcolour": None}).run(self.db, durability="soft")
97 |
98 | @welcomer.command()
99 | @checks.has_permissions("manage_messages")
100 | async def toggle(self, ctx):
101 | """Toggle welcomer on or off"""
102 | server = ctx.guild
103 | data = r.table("welcomer").get(str(server.id))
104 | if data["toggle"].run(self.db, durability="soft") == True:
105 | data.update({"toggle": False}).run(self.db, durability="soft")
106 | await ctx.send("Welcomer has been **Disabled**")
107 | return
108 | if data["toggle"].run(self.db, durability="soft") == False:
109 | data.update({"toggle": True}).run(self.db, durability="soft")
110 | await ctx.send("Welcomer has been **Enabled**")
111 | return
112 |
113 | @welcomer.command()
114 | @checks.has_permissions("manage_messages")
115 | async def embed(self, ctx):
116 | server = ctx.guild
117 | data = r.table("welcomer").get(str(server.id))
118 | if data["embed"].run(self.db, durability="soft") == True:
119 | data.update({"embed": False}).run(self.db, durability="soft")
120 | await ctx.send("Welcome messages will no longer be embedded.")
121 | return
122 | if data["embed"].run(self.db, durability="soft") == False:
123 | data.update({"embed": True}).run(self.db, durability="soft")
124 | await ctx.send("Welcome messages will now be embedded.")
125 | return
126 |
127 | @welcomer.command()
128 | @checks.has_permissions("manage_messages")
129 | async def embedcolour(self, ctx, colour: str):
130 | server = ctx.guild
131 | data = r.table("welcomer").get(str(server.id))
132 | if colour.lower() in ["none", "off"]:
133 | await ctx.send("Your embed colour has been reset.")
134 | return data.update({"embedcolour": None}).run(self.db, durability="soft")
135 | if colour.startswith("#"):
136 | colour = colour[1:]
137 | try:
138 | discord.Colour(int(colour, 16))
139 | except:
140 | return await ctx.send("Invalid hex :no_entry:")
141 | await ctx.send("Updated your embed colour to **{}**".format(str(colour)))
142 | data.update({"embedcolour": int(colour, 16)}).run(self.db, durability="soft")
143 |
144 | @welcomer.command()
145 | @checks.has_permissions("manage_messages")
146 | async def dmtoggle(self, ctx):
147 | """Toggle whether you want the bot to dm the user or not"""
148 | server = ctx.guild
149 | data = r.table("welcomer").get(str(server.id))
150 | if data["dm"].run(self.db, durability="soft") == True:
151 | data.update({"dm": False}).run(self.db, durability="soft")
152 | await ctx.send("Welcome messages will now be sent in the welcomer channel.")
153 | return
154 | if data["dm"].run(self.db, durability="soft") == False:
155 | data.update({"dm": True}).run(self.db, durability="soft")
156 | await ctx.send("Welcome messages will now be sent in dms.")
157 | return
158 |
159 | @welcomer.command()
160 | @checks.has_permissions("manage_messages")
161 | async def leavetoggle(self, ctx):
162 | """Toggle if you want the leave message or not"""
163 | server = ctx.guild
164 | data = r.table("welcomer").get(str(server.id))
165 | if data["leavetoggle"].run(self.db, durability="soft") == True:
166 | data.update({"leavetoggle": False}).run(self.db, durability="soft")
167 | await ctx.send("Leave messages are now disabled.")
168 | return
169 | if data["leavetoggle"].run(self.db, durability="soft") == False:
170 | data.update({"leavetoggle": True}).run(self.db, durability="soft")
171 | await ctx.send("Leave messages are now enabled.")
172 | return
173 |
174 | @welcomer.command()
175 | @checks.has_permissions("manage_messages")
176 | async def joinmessage(self, ctx, *, message: str=None):
177 | """Set the joining message"""
178 | server = ctx.guild
179 | data = r.table("welcomer").get(str(server.id))
180 | if not message:
181 | desc = """{server} = Your server name
182 | {user.mention} = Mentions the user who joins
183 | {user.name} = The username of the person who joined
184 | {user} = The username + discriminator
185 | {server.members} = The amount of members in your server
186 | {server.members.prefix} = The amount of members plus a prefix ex 232nd
187 | {user.created.length} = How long the users account has been created for ex 1 year 2 months 3 days
188 | **Make sure you keep the {} brackets in the message**
189 |
190 | Example: `s?welcomer joinmessage {user.mention}, Welcome to **{server}**. We now have **{server.members}** members :tada:`"""
191 | s=discord.Embed(description=desc, colour=ctx.message.author.colour)
192 | s.set_author(name="Examples on setting your message", icon_url=self.bot.user.avatar_url)
193 | await ctx.send(embed=s)
194 | return
195 | data.update({"message": message}).run(self.db, durability="soft")
196 | await ctx.send("Your message has been set <:done:403285928233402378>")
197 |
198 | @welcomer.command()
199 | @checks.has_permissions("manage_messages")
200 | async def leavemessage(self, ctx, *, message: str=None):
201 | """Set the leaving message"""
202 | server = ctx.guild
203 | data = r.table("welcomer").get(str(server.id))
204 | if not message:
205 | desc = """{server} = Your server name
206 | {user.mention} = Mentions the user who joins
207 | {user.name} = The username of the person who joined
208 | {user} = The username + discriminator
209 | {server.members} = The amount of members in your server
210 | {server.members.prefix} = The amount of members plus a prefix ex 232nd
211 | {user.created.length} = How long the users account has been created for ex 1 year 2 months 3 days
212 | **Make sure you keep the {} brackets in the message**
213 |
214 | Example: `s?welcomer leavemessage {user.mention}, Goodbye!`"""
215 | s=discord.Embed(description=desc, colour=ctx.message.author.colour)
216 | s.set_author(name="Examples on setting your message", icon_url=self.bot.user.avatar_url)
217 | await ctx.send(embed=s)
218 | return
219 | data.update({"message-leave": message}).run(self.db, durability="soft")
220 | await ctx.send("Your message has been set <:done:403285928233402378>")
221 |
222 | @welcomer.command()
223 | async def preview(self, ctx):
224 | """Look at the preview of your welcomer"""
225 | server = ctx.guild
226 | author = ctx.author
227 | data = r.table("welcomer").get(str(server.id)).run(self.db, durability="soft")
228 | message = data["message"]
229 | message = self.get_welcomer_message(server, author, message)
230 | message2 = data["message-leave"]
231 | message2 = self.get_welcomer_message(server, author, message2)
232 | s=discord.Embed(description=message, timestamp=datetime.utcnow(), colour=discord.Colour(data["embedcolour"]) if data["embedcolour"] else discord.Embed.Empty)
233 | s.set_author(name=str(author), icon_url=author.avatar_url)
234 | if data["imgwelcomertog"] and data["toggle"]:
235 | if data["embed"]:
236 | image = await self.image_welcomer(author, server)
237 | s.set_image(url="attachment://welcomer." + image.filename.split(".")[1])
238 | try:
239 | await ctx.send(embed=s, file=image)
240 | except discord.errors.HTTPException:
241 | await ctx.send("The welcomer banner you have sent makes the file size more than 8mb therefore I'm unable to send it :no_entry:")
242 | else:
243 | image = await self.image_welcomer(author, server)
244 | await ctx.send(content=message, file=image)
245 | elif data["imgwelcomertog"] and not data["toggle"]:
246 | image = await self.image_welcomer(author, server)
247 | try:
248 | await ctx.send(file=image)
249 | except discord.errors.HTTPException:
250 | await ctx.send("The welcomer banner you have sent makes the file size more than 8mb therefore I'm unable to send it :no_entry:")
251 | elif not data["imgwelcomertog"] and data["toggle"]:
252 | if data["embed"]:
253 | await ctx.send(embed=s)
254 | else:
255 | await ctx.send(message)
256 | else:
257 | return await ctx.send("You have neither image welcomer or welcomer enabled :no_entry:")
258 | if data["leavetoggle"]:
259 | if data["embed"]:
260 | s=discord.Embed(description=message2, timestamp=datetime.utcnow(), colour=discord.Colour(data["embedcolour"]) if data["embedcolour"] else discord.Embed.Empty)
261 | s.set_author(name=str(author), icon_url=author.avatar_url)
262 | await ctx.send(embed=s)
263 | else:
264 | await ctx.send(message2)
265 |
266 | @welcomer.command()
267 | @checks.has_permissions("manage_messages")
268 | async def channel(self, ctx, channel: discord.TextChannel):
269 | """Set the channel of where you want the bot to welcome people"""
270 | server = ctx.guild
271 | data = r.table("welcomer").get(str(server.id))
272 | data.update({"channel": str(channel.id)}).run(self.db, durability="soft")
273 | await ctx.send("<#{}> has been set as the join-leave channel".format(channel.id))
274 |
275 | @welcomer.command()
276 | async def stats(self, ctx):
277 | """Look at the settings of your welcomer"""
278 | server = ctx.guild
279 | data = r.table("welcomer").get(str(server.id)).run(self.db, durability="soft")
280 | message = "`" + data["message"] + "`"
281 | message2 = "`" + data["message-leave"] + "`"
282 | s=discord.Embed(colour=0xfff90d)
283 | s.set_author(name="Welcomer Settings", icon_url=self.bot.user.avatar_url)
284 | if data["toggle"] == True:
285 | msg = "Enabled"
286 | if data["toggle"] == False:
287 | msg = "Disabled"
288 | if data["dm"] == True:
289 | msg2 = "Enabled"
290 | if data["dm"] == False:
291 | msg2 = "Disabled"
292 | if data["imgwelcomertog"] == True:
293 | img = "Enabled"
294 | else:
295 | img = "Disabled"
296 | if data["leavetoggle"] == False:
297 | message2 = "Disabled"
298 | s.add_field(name="Welcomer status", value=msg)
299 | if not data["channel"]:
300 | channel = "Not set"
301 | else:
302 | channel = "<#{}>".format(data["channel"])
303 | s.add_field(name="Welcomer channel", value=channel)
304 | s.add_field(name="DM Welcomer", value=msg2)
305 | s.add_field(name="Image Welcomer", value=img)
306 | s.add_field(name="Embed", value="Message: {}\nColour: {}".format("Yes" if data["embed"] else "No", discord.Colour(data["embedcolour"]) if data["embedcolour"] else "Default"))
307 | s.add_field(name="Join message", value=message, inline=False)
308 | s.add_field(name="Leave message", value=message2, inline=False)
309 | await ctx.send(embed=s)
310 |
311 | def prefixfy(self, server):
312 | number = str(len(server.members))
313 | num = len(number) - 2
314 | num2 = len(number) - 1
315 | if int(number[num:]) < 11 or int(number[num:]) > 13:
316 | if int(number[num2:]) == 1:
317 | prefix = "st"
318 | elif int(number[num2:]) == 2:
319 | prefix = "nd"
320 | elif int(number[num2:]) == 3:
321 | prefix = "rd"
322 | else:
323 | prefix = "th"
324 | else:
325 | prefix = "th"
326 | return "{:,}".format(int(number)) + prefix
327 |
328 |
329 | async def on_member_join(self, member):
330 | server = member.guild
331 | data = r.table("welcomer").get(str(server.id)).run(self.db, durability="soft")
332 | message = data["message"]
333 | channel = data["channel"]
334 | channel = server.get_channel(int(channel))
335 | if not channel:
336 | if server.system_channel:
337 | channel = server.system_channel
338 | message = self.get_welcomer_message(server, member, message)
339 | s=discord.Embed(description=message, timestamp=datetime.utcnow(), colour=discord.Colour(data["embedcolour"]) if data["embedcolour"] else discord.Embed.Empty)
340 | s.set_author(name=str(member), icon_url=member.avatar_url)
341 | s.set_image(url="attachment://welcomer.png")
342 | if data["toggle"] == True and data["imgwelcomertog"] == True:
343 | if data["dm"] == True:
344 | if data["embed"]:
345 | image = await self.image_welcomer(member, server)
346 | if image:
347 | s.set_image(url="attachment://welcomer.{}".format(image.filename.split(".")[1]))
348 | await member.send(embed=s, file=image)
349 | else:
350 | await member.send(content=message, file=await self.image_welcomer(member, server))
351 | elif data["dm"] == False:
352 | if data["embed"]:
353 | image = await self.image_welcomer(member, server)
354 | if image:
355 | s.set_image(url="attachment://welcomer.{}".format(image.filename.split(".")[1]))
356 | await self.webhook_send(channel=channel, embed=s, file=image)
357 | else:
358 | await self.webhook_send(channel=channel, content=message, file=await self.image_welcomer(member, server))
359 | elif data["toggle"] == True and data["imgwelcomertog"] == False:
360 | if data["dm"] == True:
361 | if data["embed"]:
362 | await member.send(embed=s)
363 | else:
364 | await member.send(content=message)
365 | elif data["dm"] == False:
366 | if data["embed"]:
367 | await self.webhook_send(channel=channel, embed=s)
368 | else:
369 | await self.webhook_send(channel=channel, content=message)
370 | elif data["toggle"] == False and data["imgwelcomertog"] == True:
371 | if data["dm"] == True:
372 | await member.send(file=await self.image_welcomer(member, server))
373 | elif data["dm"] == False:
374 | await self.webhook_send(channel=channel, file=await self.image_welcomer(member, server))
375 |
376 | async def on_member_remove(self, member):
377 | server = member.guild
378 | data = r.table("welcomer").get(str(server.id)).run(self.db, durability="soft")
379 | if data["dm"] == True:
380 | return
381 | if data["leavetoggle"] == False:
382 | return
383 | channel = data["channel"]
384 | channel = server.get_channel(int(channel))
385 | if not channel:
386 | if server.system_channel:
387 | channel = server.system_channel
388 | message = data["message-leave"]
389 | if data["toggle"] == True:
390 | message = self.get_welcomer_message(server, member, message)
391 | if data["embed"]:
392 | s=discord.Embed(description=message, timestamp=datetime.utcnow(), colour=discord.Colour(data["embedcolour"]) if data["embedcolour"] else discord.Embed.Empty)
393 | s.set_author(name=str(member), icon_url=member.avatar_url)
394 | await self.webhook_send(channel=channel, embed=s)
395 | else:
396 | await self.webhook_send(channel=channel, content=message)
397 |
398 | def get_welcomer_message(self, guild, member, message: str):
399 | message = message.replace("{server}", guild.name)
400 | message = message.replace("{user.mention}", member.mention)
401 | message = message.replace("{user.name}", member.name)
402 | message = message.replace("{user}", str(member))
403 | message = message.replace("{server.members}", "{:,}".format(len(guild.members)))
404 | message = message.replace("{server.members.prefix}", self.prefixfy(guild))
405 | message = message.replace("{user.created.length}", dateify.get((datetime.utcnow() - member.created_at).total_seconds()))
406 | return message
407 |
408 | async def image_welcomer(self, author, server):
409 | data = r.table("welcomer").get(str(server.id)).run(self.db, durability="soft")
410 | banner = "" if not data["banner"] else "&background={}".format(data["banner"])
411 | async with aiohttp.ClientSession() as session:
412 | async with session.get("http://localhost:8443/api/welcomer?userAvatar={}&{}{}".format(author.avatar_url_as(format="png"), urllib.parse.urlencode({"userName": str(author)}), banner)) as f:
413 | return discord.File(await f.read(), "welcomer.{}".format(f.headers["Content-Type"].split("/")[1]))
414 |
415 | async def webhook_send(self, channel, content=None, file=None, embed=None):
416 | if self.avatar is None:
417 | try:
418 | with open("sx4-byellow.png", "rb") as f:
419 | self.avatar = f.read()
420 | except:
421 | pass
422 | webhook = discord.utils.get(await channel.guild.webhooks(), name="Sx4 - Welcomer")
423 | if not webhook:
424 | webhook = await channel.create_webhook(name="Sx4 - Welcomer", avatar=self.avatar)
425 | elif webhook and channel != webhook.channel:
426 | await webhook.delete()
427 | webhook = await channel.create_webhook(name="Sx4 - Welcomer", avatar=self.avatar)
428 | await webhook.send(content=content, file=file, embed=embed)
429 |
430 | def setup(bot, connection):
431 | bot.add_cog(welcomer(bot, connection))
432 |
--------------------------------------------------------------------------------
/Sx4/main.py:
--------------------------------------------------------------------------------
1 | import discord
2 | import asyncio
3 | from discord.ext import commands
4 | from random import choice as randchoice
5 | import time
6 | import datetime
7 | from utils import checks
8 | from urllib.parse import urlencode
9 | from urllib.request import Request, urlopen
10 | import requests
11 | from utils import Token
12 | import inspect
13 | import importlib
14 | import logging
15 | import aiohttp
16 | import json
17 | import rethinkdb as r
18 | from utils.database import Database
19 | import traceback
20 | import sys
21 | import os
22 | import subprocess
23 |
24 | async def prefix_function(bot, message):
25 | user = r.table("prefix").get(str(message.author.id)).run(connection)
26 | server = r.table("prefix").get(str(message.guild.id)).run(connection)
27 | if user and user["prefixes"] != []:
28 | return [x.encode().decode() for x in user["prefixes"]] + ['<@440996323156819968> ', '<@!440996323156819968> ']
29 | elif server and server["prefixes"] != []:
30 | return [x.encode().decode() for x in server["prefixes"]] + ['<@440996323156819968> ', '<@!440996323156819968> ']
31 | else:
32 | return ['s?', 'S?', 'sx4 ', '<@440996323156819968> ', '<@!440996323156819968> ']
33 |
34 | bot = commands.AutoShardedBot(command_prefix=prefix_function, case_insensitive=False)
35 | logging.basicConfig(level=logging.INFO)
36 | wrap = "```py\n{}\n```"
37 | modules = ["cogs." + x.replace(".py", "") for x in os.listdir("cogs") if ".py" in x]
38 |
39 | connection = Database.get_connection()
40 |
41 | def load_extension(self, name):
42 | if name in self.extensions:
43 | return
44 |
45 | lib = importlib.import_module(name)
46 | if not hasattr(lib, 'setup'):
47 | del lib
48 | del sys.modules[name]
49 | raise discord.ClientException('extension does not have a setup function')
50 |
51 | lib.setup(self, connection)
52 | self.extensions[name] = lib
53 |
54 | commands.AutoShardedBot.load_extension = load_extension
55 |
56 | @bot.event
57 | async def on_ready():
58 | print('Logged in as')
59 | print(bot.user.name + '#' + str(bot.user.discriminator) + ' (' + str(bot.user.id) + ')')
60 | print('Connected to {} servers and {} users | {} shards'.format(len(bot.guilds), len(set(bot.get_all_members())), bot.shard_count))
61 | print('------')
62 | for extension in modules:
63 | try:
64 | bot.load_extension(extension)
65 | except Exception as e:
66 | print(e)
67 | r.table("blacklist").insert({"id": "owner", "users": []}).run(connection)
68 |
69 | @bot.event
70 | async def on_shard_ready(shard_id):
71 | guild = bot.get_guild(330399610273136641)
72 | webhook = discord.utils.get(await guild.webhooks(), id=527878836055179275)
73 | s=discord.Embed(colour=0x5fe468, timestamp=datetime.datetime.utcnow())
74 | s.set_author(name=str(bot.user), icon_url=bot.user.avatar_url)
75 | s.add_field(name="Shard", value=shard_id)
76 | s.set_footer(text="Connected")
77 | await webhook.send(embed=s)
78 |
79 | @bot.event
80 | async def on_message(message):
81 | ctx = await bot.get_context(message)
82 | serverdata = r.table("blacklist").get(str(message.guild.id)).run(connection)
83 | if not ctx.command:
84 | return
85 | elif checks.is_owner_check(ctx):
86 | return await bot.process_commands(message)
87 | elif isinstance(message.channel, discord.abc.PrivateChannel):
88 | return await message.channel.send("You can't use commands in private messages :no_entry:")
89 | elif message.author.bot:
90 | return
91 | elif str(message.author.id) in r.table("blacklist").get("owner")["users"].run(connection):
92 | return await ctx.send("You are blacklisted from using the bot, to appeal make sure to join the bots support server which can be found in `{}support`".format(ctx.prefix))
93 | elif serverdata:
94 | if not checks.has_permissions("administrator").__closure__[0].cell_contents(ctx):
95 | commands = list(map(lambda x: x["id"], serverdata["commands"]))
96 | if ctx.command.module[5:] in commands:
97 | whitelisted = list(filter(lambda x: x["id"] == ctx.command.module[5:], serverdata["commands"]))[0]["whitelisted"]
98 | if whitelisted != []:
99 | if str(message.channel.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "channel", whitelisted)):
100 | return await bot.process_commands(message)
101 | if str(message.author.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "user", whitelisted)):
102 | return await bot.process_commands(message)
103 | for x in message.author.roles:
104 | if str(x.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "role", whitelisted)):
105 | return await bot.process_commands(message)
106 | if str(ctx.command) in commands:
107 | whitelisted = list(filter(lambda x: x["id"] == str(ctx.command), serverdata["commands"]))[0]["whitelisted"]
108 | if whitelisted != []:
109 | if str(message.channel.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "channel", whitelisted)):
110 | return await bot.process_commands(message)
111 | if str(message.author.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "user", whitelisted)):
112 | return await bot.process_commands(message)
113 | for x in message.author.roles:
114 | if str(x.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "role", whitelisted)):
115 | return await bot.process_commands(message)
116 | if ctx.command.module[5:] in commands:
117 | blacklisted = list(filter(lambda x: x["id"] == ctx.command.module[5:], serverdata["commands"]))[0]["blacklisted"]
118 | if blacklisted != []:
119 | if str(message.channel.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "channel", blacklisted)):
120 | return await ctx.send("You cannot use any commands in the module {} in this channel :no_entry:".format(ctx.command.module[5:]))
121 | if str(message.author.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "user", blacklisted)):
122 | return await ctx.send("You are blacklisted from using any commands in the module {} in this server :no_entry:".format(ctx.command.module[5:]))
123 | for x in message.author.roles:
124 | if str(x.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "role", blacklisted)):
125 | return await ctx.send("You are in the role `{}` which means you are blacklisted from using any commands in the module {} in this server :no_entry:".format(x.name, ctx.command.module[5:]))
126 | if str(ctx.command) in commands:
127 | blacklisted = list(filter(lambda x: x["id"] == str(ctx.command), serverdata["commands"]))[0]["blacklisted"]
128 | if blacklisted != []:
129 | if str(message.channel.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "channel", blacklisted)):
130 | return await ctx.send("You cannot use that command in this channel :no_entry:")
131 | if str(message.author.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "user", blacklisted)):
132 | return await ctx.send("You are blacklisted from using that command in this server :no_entry:")
133 | for x in message.author.roles:
134 | if str(x.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "role", blacklisted)):
135 | return await ctx.send("You are in the role `{}` which means you are blacklisted from using that command in this server :no_entry:".format(x.name))
136 | if str(ctx.command) in serverdata["disabled"]:
137 | return await ctx.send("That command is disabled across the server :no_entry:")
138 | await bot.process_commands(message)
139 |
140 | @bot.event
141 | async def on_message_edit(before, after):
142 | if before.content == after.content:
143 | return
144 | ctx = await bot.get_context(after)
145 | serverdata = r.table("blacklist").get(str(after.guild.id)).run(connection)
146 | if not ctx.command:
147 | return
148 | elif checks.is_owner_check(ctx):
149 | return await bot.process_commands(after)
150 | elif isinstance(after.channel, discord.abc.PrivateChannel):
151 | return await after.channel.send("You can't use commands in private messages :no_entry:")
152 | elif after.author.bot:
153 | return
154 | elif str(after.author.id) in r.table("blacklist").get("owner")["users"].run(connection):
155 | return await ctx.send("You are blacklisted from using the bot, to appeal make sure to join the bots support server which can be found in `{}support`".format(ctx.prefix))
156 | elif serverdata:
157 | if not checks.has_permissions("administrator").__closure__[0].cell_contents(ctx):
158 | commands = list(map(lambda x: x["id"], serverdata["commands"]))
159 | if ctx.command.module[5:] in commands:
160 | whitelisted = list(filter(lambda x: x["id"] == ctx.command.module[5:], serverdata["commands"]))[0]["whitelisted"]
161 | if whitelisted != []:
162 | if str(after.channel.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "channel", whitelisted)):
163 | return await bot.process_commands(after)
164 | if str(after.author.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "user", whitelisted)):
165 | return await bot.process_commands(after)
166 | for x in after.author.roles:
167 | if str(x.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "role", whitelisted)):
168 | return await bot.process_commands(after)
169 | if str(ctx.command) in commands:
170 | whitelisted = list(filter(lambda x: x["id"] == str(ctx.command), serverdata["commands"]))[0]["whitelisted"]
171 | if whitelisted != []:
172 | if str(after.channel.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "channel", whitelisted)):
173 | return await bot.process_commands(after)
174 | if str(after.author.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "user", whitelisted)):
175 | return await bot.process_commands(after)
176 | for x in after.author.roles:
177 | if str(x.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "role", whitelisted)):
178 | return await bot.process_commands(after)
179 | if ctx.command.module[5:] in commands:
180 | blacklisted = list(filter(lambda x: x["id"] == ctx.command.module[5:], serverdata["commands"]))[0]["blacklisted"]
181 | if blacklisted != []:
182 | if str(after.channel.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "channel", blacklisted)):
183 | return await ctx.send("You cannot use any commands in the module {} in this channel :no_entry:".format(ctx.command.module[5:]))
184 | if str(after.author.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "user", blacklisted)):
185 | return await ctx.send("You are blacklisted from using any commands in the module {} in this server :no_entry:".format(ctx.command.module[5:]))
186 | for x in after.author.roles:
187 | if str(x.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "role", blacklisted)):
188 | return await ctx.send("You are in the role `{}` which means you are blacklisted from using any commands in the module {} in this server :no_entry:".format(x.name, ctx.command.module[5:]))
189 | if str(ctx.command) in commands:
190 | blacklisted = list(filter(lambda x: x["id"] == str(ctx.command), serverdata["commands"]))[0]["blacklisted"]
191 | if blacklisted != []:
192 | if str(after.channel.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "channel", blacklisted)):
193 | return await ctx.send("You cannot use that command in this channel :no_entry:")
194 | if str(after.author.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "user", blacklisted)):
195 | return await ctx.send("You are blacklisted from using that command in this server :no_entry:")
196 | for x in after.author.roles:
197 | if str(x.id) in map(lambda x: x["id"], filter(lambda x: x["type"] == "role", blacklisted)):
198 | return await ctx.send("You are in the role `{}` which means you are blacklisted from using that command in this server :no_entry:".format(x.name))
199 | if str(ctx.command) in serverdata["disabled"]:
200 | return await ctx.send("That command is disabled across the server :no_entry:")
201 | await bot.process_commands(after)
202 |
203 | @bot.event
204 | async def on_command_error(ctx, error, *args, **kwargs):
205 | channel = ctx.channel
206 | author = ctx.author
207 | if isinstance(error, commands.CheckFailure):
208 | perms = ctx.command.checks[0]
209 | if ctx.command.checks[0].__name__ == "is_owner_check":
210 | try:
211 | ctx.command.reset_cooldown(ctx)
212 | except:
213 | pass
214 | return await channel.send("You do not have permission to use this command, Required permissions: Bot Owner :no_entry:")
215 | elif str(perms).split(" ")[1].split(".")[0] == "is_main_owner":
216 | try:
217 | ctx.command.reset_cooldown(ctx)
218 | except:
219 | pass
220 | return await channel.send("You do not have permission to use this command, Required permissions: Bot Owner :no_entry:")
221 | else:
222 | try:
223 | ctx.command.reset_cooldown(ctx)
224 | except:
225 | pass
226 | return await channel.send("You do not have permission to use this command, Required permissions: {} :no_entry:".format(", ".join(inspect.getclosurevars(ctx.command.checks[0]).nonlocals["perms"])))
227 | elif isinstance(error, commands.NoPrivateMessage):
228 | try:
229 | ctx.command.reset_cooldown(ctx)
230 | except:
231 | pass
232 | return await channel.send("This command cannot be used in DMs!")
233 | elif isinstance(error, commands.DisabledCommand):
234 | try:
235 | ctx.command.reset_cooldown(ctx)
236 | except:
237 | pass
238 | if not checks.is_owner_check(ctx):
239 | return await channel.send("The command `{}` has been disabled :no_entry:".format(ctx.command))
240 | elif isinstance(error, commands.CommandOnCooldown):
241 | m, s = divmod(error.retry_after, 60)
242 | h, m = divmod(m, 60)
243 | if h == 0:
244 | time = "%d minutes %d seconds" % (m, s)
245 | elif h == 0 and m == 0:
246 | time = "%d seconds" % (s)
247 | else:
248 | time = "%d hours %d minutes %d seconds" % (h, m, s)
249 | return await channel.send("This command is on cooldown! Try again in {}".format(time))
250 | elif isinstance(error, commands.MissingRequiredArgument):
251 | try:
252 | perms = ctx.command.checks[0]
253 | except:
254 | perms = None
255 | msg = ""
256 | if not ctx.command.usage:
257 | for x in ctx.command.params:
258 | if x != "ctx":
259 | if x != "self":
260 | if "=" in str(ctx.command.params[x]):
261 | msg += "[{}] ".format(x)
262 | else:
263 | msg += "<{}> ".format(x)
264 | else:
265 | msg += ctx.command.usage
266 | if not ctx.command.aliases:
267 | aliases = "None"
268 | else:
269 | aliases = ", ".join([x for x in ctx.command.aliases])
270 | if not perms:
271 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: None\nCommand description: {}".format(ctx.prefix, ctx.command, msg, aliases, ctx.command.help)
272 | else:
273 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: {}\nCommand description: {}".format(ctx.prefix, ctx.command, msg, aliases,
274 | ", ".join(inspect.getclosurevars(perms).nonlocals["perms"]) if perms.__name__ != "is_owner_check" and str(perms).split(" ")[1].split(".")[0] != "is_main_owner" else "Bot Owner", ctx.command.help)
275 | try:
276 | msg += "\n\nSub commands: {}".format(", ".join([x for x in ctx.command.all_commands if x not in ctx.command.all_commands[x].aliases]))
277 | except:
278 | pass
279 | s=discord.Embed(description=msg)
280 | s.set_author(name=ctx.command, icon_url=bot.user.avatar_url)
281 | await channel.send(embed=s)
282 | try:
283 | ctx.command.reset_cooldown(ctx)
284 | except:
285 | pass
286 | return
287 | elif isinstance(error, commands.CommandNotFound):
288 | pass
289 | elif isinstance(error, commands.BadArgument):
290 | try:
291 | perms = ctx.command.checks[0]
292 | except:
293 | perms = None
294 | msg = ""
295 | for x in ctx.command.params:
296 | if x != "ctx":
297 | if x != "self":
298 | if "=" in str(ctx.command.params[x]):
299 | msg += "[{}] ".format(x)
300 | else:
301 | msg += "<{}> ".format(x)
302 | if not ctx.command.aliases:
303 | aliases = "None"
304 | else:
305 | aliases = ", ".join([x for x in ctx.command.aliases])
306 | if not perms:
307 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: None\nCommand description: {}".format(ctx.prefix, ctx.command, msg, aliases, ctx.command.help)
308 | else:
309 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: {}\nCommand description: {}".format(ctx.prefix, ctx.command, msg, aliases,
310 | ", ".join(inspect.getclosurevars(perms).nonlocals["perms"]) if perms.__name__ != "is_owner_check" and str(perms).split(" ")[1].split(".")[0] != "is_main_owner" else "Bot Owner", ctx.command.help)
311 | try:
312 | msg += "\n\nSub commands: {}".format(", ".join([x for x in ctx.command.all_commands if x not in ctx.command.all_commands[x].aliases]))
313 | except:
314 | pass
315 | s=discord.Embed(description=msg)
316 | s.set_author(name=ctx.command, icon_url=bot.user.avatar_url)
317 | await channel.send(embed=s)
318 | try:
319 | ctx.command.reset_cooldown(ctx)
320 | except:
321 | pass
322 | return
323 | else:
324 | s=discord.Embed(title="Error", description="You have came across an error! [Support Server](https://discord.gg/PqJNcfB)\n{}".format(str(error)).replace("Command raised an exception: ", ""))
325 | await channel.send(embed=s)
326 | print("".join(traceback.format_exception(type(error), error, error.__traceback__)))
327 | await bot.get_channel(439745234285625355).send("```py\nServer: {}\nTime: {}\nCommand: {}\nAuthor: {}\n\n{}```".format(ctx.message.guild, datetime.datetime.utcnow().strftime("%d/%m/%Y %H:%M:%S"), ctx.command, ctx.message.author, "".join(traceback.format_exception(type(error), error, error.__traceback__, 1000))))
328 |
329 |
330 | class Main:
331 | def __init__(self, bot):
332 | self.bot = bot
333 |
334 | @bot.command(hidden=True)
335 | @checks.is_owner()
336 | async def load(ctx, *, module: str):
337 | """loads a part of the bot."""
338 | m = "cogs." + module
339 | try:
340 | if m in modules:
341 | bot.load_extension(m)
342 | await ctx.send("The module `{}` has been loaded <:done:403285928233402378>".format(module))
343 | else:
344 | await ctx.send("I cannot find the module you want me to load <:crossmark:410105895528300554>")
345 | except Exception as e:
346 | e=discord.Embed(description="Error:" + wrap.format(type(e).name + ': ' + str(e)), colour=discord.Colour.red())
347 | await ctx.send(embed=e)
348 |
349 | @bot.command(hidden=True)
350 | @checks.is_owner()
351 | async def unload(ctx, *, module: str):
352 | """unloads a part of the bot."""
353 | m = "cogs." + module
354 | try:
355 | if m in modules:
356 | bot.unload_extension(m)
357 | await ctx.send("The module `{}` has been unloaded <:done:403285928233402378>".format(module))
358 | else:
359 | await ctx.send("I cannot find the module you want me to unload <:crossmark:410105895528300554>")
360 | except Exception as e:
361 | e=discord.Embed(description="Error:" + wrap.format(type(e).name + ': ' + str(e)), colour=discord.Colour.red())
362 | await ctx.send(embed=e)
363 |
364 | @bot.command(hidden=True)
365 | @checks.is_owner()
366 | async def reload(ctx, *, module: str):
367 | """Reloads a part of the bot."""
368 | if module.lower() == "all":
369 | i = 0
370 | for m in modules:
371 | try:
372 | bot.unload_extension(m)
373 | bot.load_extension(m)
374 | except:
375 | i += 1
376 | await ctx.send("I was not able to load the module `{}` <:crossmark:410105895528300554>".format(str(m)[4:]))
377 | if i == 0:
378 | await ctx.send("All modules have been reloaded <:done:403285928233402378>")
379 | else:
380 | await ctx.send("{} modules have been reloaded <:done:403285928233402378>".format(len(modules)-i))
381 | return
382 | m = "cogs." + module
383 | try:
384 | if m in modules:
385 | bot.unload_extension(m)
386 | bot.load_extension(m)
387 | await ctx.send("The module `{}` has been reloaded <:done:403285928233402378>".format(module))
388 | else:
389 | await ctx.send("I cannot find the module you want me to reload <:crossmark:410105895528300554>")
390 | except Exception as e:
391 | e=discord.Embed(description="Error:" + wrap.format(type(e).name + ': ' + str(e)), colour=discord.Colour.red())
392 | await ctx.send(embed=e)
393 |
394 | async def on_error(self, event_method, *args, **kwargs):
395 | pass
396 |
397 | bot.on_error = on_error
398 |
399 | setattr(bot, "uptime", datetime.datetime.utcnow().timestamp())
400 |
401 | bot.add_cog(Main(bot))
402 |
403 | bot.run(Token.bot(), reconnect=True)
404 |
405 |
--------------------------------------------------------------------------------
/Sx4/utils/PagedResult.py:
--------------------------------------------------------------------------------
1 | import collections
2 | import discord
3 | import math
4 | from discord.ext import commands
5 | import discord.utils
6 |
7 | class PagedResultData:
8 | paged_results = dict()
9 |
10 | class SelectedEvent:
11 | pass
12 |
13 | class PagedResult:
14 | __page = 1
15 | entries_per_page = 10
16 |
17 | list_indexes = True
18 | selectable = True
19 | cancelable = True
20 |
21 | on_select = lambda s: s
22 |
23 | message_id = None
24 |
25 | def __init__(self, entries, display_function):
26 | if not isinstance(entries, collections.Iterable):
27 | raise ValueError("Incorrect type, entries is not an instance of list")
28 |
29 | if len(entries) <= 0:
30 | raise ValueError("List has no entries")
31 |
32 | self.entries = entries
33 |
34 | self.display_function = display_function
35 |
36 | self.__max_pages = self.determine_max_pages()
37 |
38 | self.embed = discord.Embed(colour=0xfff90d)
39 |
40 | def get_current_page(self):
41 | return self.__page
42 |
43 | def get_max_pages(self):
44 | return self.__max_pages
45 |
46 | def get_current_page_entries(self):
47 | start = (self.__page - 1) * self.entries_per_page
48 |
49 | if self.__page == self.__max_pages:
50 | end = len(self.entries) - start
51 | else:
52 | end = self.entries_per_page
53 |
54 | return self.entries[start:(start + end)]
55 |
56 | def get_current_page_embed(self):
57 | entries = self.get_current_page_entries()
58 | description = "Page **" + str(self.__page) + "**/**" + str(self.__max_pages) + "**\n"
59 |
60 | i = 1
61 | for e in entries:
62 | description = description + "\n" + (str(i) + " - " if self.list_indexes else "") + str(self.display_function(e))
63 |
64 | i = i + 1
65 |
66 | footer = ""
67 | if self.__page + 1 <= self.__max_pages:
68 | footer = footer + "next page | "
69 |
70 | if self.__page - 1 > 0:
71 | footer = footer + "previous page | "
72 |
73 | if self.__max_pages > 2:
74 | footer = footer + "go to page | "
75 |
76 | if self.cancelable:
77 | footer = footer + "cancel"
78 | else:
79 | footer = footer[:-3]
80 |
81 | self.embed.description = description
82 | self.embed.set_footer(text=footer)
83 |
84 | return self.embed
85 |
86 | def determine_max_pages(self):
87 | return math.ceil(len(self.entries)/self.entries_per_page)
88 |
89 | async def select(self, index):
90 | event = SelectedEvent()
91 | event.page = self.__page
92 | event.index = index
93 | event.actual_index = (self.__page - 1) * self.entries_per_page + (index - 1)
94 | event.entry = self.entries[event.actual_index]
95 |
96 | await self.on_select(event)
97 |
98 |
99 | def set_page(self, page):
100 | if page > self.__max_pages:
101 | return False
102 |
103 | if page < 1:
104 | return False
105 |
106 | self.__page = page
107 |
108 | return True
109 |
110 | def next_page(self):
111 | if self.__page + 1 > self.__max_pages:
112 | return False
113 |
114 | self.__page = self.__page + 1
115 |
116 | return True
117 |
118 | def previous_page(self):
119 | if self.__page - 1 < 1:
120 | return False
121 |
122 | self.__page = self.__page - 1
123 |
124 | return True
--------------------------------------------------------------------------------
/Sx4/utils/arg.py:
--------------------------------------------------------------------------------
1 | import discord
2 | import re
3 |
4 | regex_mention = re.compile("<@(?:!|)(\d+)>")
5 | regex_namediscrim = re.compile("(.{2,32})#(\d{4})")
6 | regex_id = re.compile("(^\d+$)")
7 | regex_name = re.compile("(.{2,32})")
8 | role_mention = re.compile("<@&(\d+)>")
9 | channel_mention = re.compile("<#(\d+)>")
10 |
11 | async def get_member_info(ctx, user_arg):
12 | bot = ctx.bot
13 | match_mention = regex_mention.match(user_arg)
14 | match_namediscrim = regex_namediscrim.match(user_arg)
15 | match_id = regex_id.match(user_arg)
16 | match_name = regex_name.match(user_arg)
17 | if match_mention:
18 | id = int(match_mention.group(1))
19 | user = ctx.guild.get_member(id)
20 | if not user:
21 | try:
22 | user = {x.id: x for x in bot.get_all_members()}[id]
23 | except KeyError:
24 | try:
25 | user = await bot.get_user_info(id)
26 | except:
27 | return None
28 | elif match_namediscrim:
29 | name = match_namediscrim.group(1)
30 | discrim = match_namediscrim.group(2)
31 | try:
32 | user = [x for x in ctx.guild.members if x.name.lower() == name.lower() and x.discriminator == discrim][0]
33 | except IndexError:
34 | try:
35 | user = [x for x in bot.get_all_members() if x.name.lower() == name.lower() and x.discriminator == discrim][0]
36 | except IndexError:
37 | return None
38 | elif match_id:
39 | id = int(match_id.group(1))
40 | user = ctx.guild.get_member(id)
41 | if not user:
42 | try:
43 | user = {x.id: x for x in bot.get_all_members()}[id]
44 | except KeyError:
45 | try:
46 | user = await bot.get_user_info(id)
47 | except:
48 | return None
49 | elif match_name:
50 | name2 = match_name.group(1)
51 | try:
52 | user = [x for x in ctx.guild.members if x.display_name.lower() == name2.lower()][0]
53 | except IndexError:
54 | try:
55 | user = [x for x in ctx.guild.members if x.name.lower() == name2.lower()][0]
56 | except IndexError:
57 | try:
58 | user = [x for x in bot.get_all_members() if x.name.lower() == name2.lower()][0]
59 | except IndexError:
60 | return None
61 | else:
62 | return None
63 | return user
64 |
65 | async def get_member(ctx, user_arg):
66 | bot = ctx.bot
67 | match_mention = regex_mention.match(user_arg)
68 | match_namediscrim = regex_namediscrim.match(user_arg)
69 | match_id = regex_id.match(user_arg)
70 | match_name = regex_name.match(user_arg)
71 | if match_mention:
72 | id = int(match_mention.group(1))
73 | user = ctx.guild.get_member(id)
74 | if not user:
75 | user = bot.get_user(id)
76 | if not user:
77 | try:
78 | user = await bot.get_user_info(id)
79 | except:
80 | return None
81 | elif match_namediscrim:
82 | name = match_namediscrim.group(1)
83 | discrim = match_namediscrim.group(2)
84 | try:
85 | user = [x for x in ctx.guild.members if x.name.lower() == name.lower() and x.discriminator == discrim][0]
86 | except IndexError:
87 | try:
88 | user = [x for x in bot.users if x.name.lower() == name.lower() and x.discriminator == discrim][0]
89 | except IndexError:
90 | return None
91 | elif match_id:
92 | id = int(match_id.group(1))
93 | user = ctx.guild.get_member(id)
94 | if not user:
95 | user = bot.get_user(id)
96 | if not user:
97 | try:
98 | user = await bot.get_user_info(id)
99 | except:
100 | return None
101 | elif match_name:
102 | name2 = match_name.group(1)
103 | try:
104 | user = [x for x in ctx.guild.members if x.display_name.lower() == name2.lower()][0]
105 | except IndexError:
106 | try:
107 | user = [x for x in ctx.guild.members if x.name.lower() == name2.lower()][0]
108 | except IndexError:
109 | try:
110 | user = [x for x in bot.users if x.name.lower() == name2.lower()][0]
111 | except IndexError:
112 | return None
113 | else:
114 | return None
115 | return user
116 |
117 | def get_role(ctx, role):
118 | if role_mention.match(role):
119 | role = ctx.guild.get_role(int(role_mention.match(role).group(1)))
120 | elif regex_id.match(role):
121 | role = ctx.guild.get_role(int(regex_id.match(role).group(1)))
122 | else:
123 | try:
124 | role = list(filter(lambda x: x.name.lower() == role.lower(), ctx.guild.roles))[0]
125 | except IndexError:
126 | try:
127 | role = list(filter(lambda x: x.name.lower().startswith(role.lower()), ctx.guild.roles))[0]
128 | except IndexError:
129 | try:
130 | role = list(filter(lambda x: role.lower() in x.name.lower(), ctx.guild.roles))[0]
131 | except IndexError:
132 | return None
133 | return role
134 |
135 | def get_server_member(ctx, user):
136 | match_mention = regex_mention.match(user)
137 | match_namediscrim = regex_namediscrim.match(user)
138 | match_id = regex_id.match(user)
139 | match_name = regex_name.match(user)
140 | if match_mention:
141 | id = int(match_mention.group(1))
142 | user = ctx.guild.get_member(id)
143 | if not user:
144 | return None
145 | elif match_namediscrim:
146 | name = match_namediscrim.group(1)
147 | discrim = match_namediscrim.group(2)
148 | try:
149 | user = [x for x in ctx.guild.members if x.name.lower() == name.lower() and x.discriminator == discrim][0]
150 | except IndexError:
151 | return None
152 | elif match_id:
153 | id = int(match_id.group(1))
154 | user = ctx.guild.get_member(id)
155 | if not user:
156 | return None
157 | elif match_name:
158 | name2 = match_name.group(1)
159 | try:
160 | user = [x for x in ctx.guild.members if x.display_name.lower() == name2.lower()][0]
161 | except IndexError:
162 | try:
163 | user = [x for x in ctx.guild.members if x.name.lower() == name2.lower()][0]
164 | except IndexError:
165 | try:
166 | user = [x for x in ctx.guild.members if name2.lower() in x.display_name.lower()][0]
167 | except IndexError:
168 | try:
169 | user = [x for x in ctx.guild.members if name2.lower() in x.name.lower()][0]
170 | except IndexError:
171 | return None
172 | else:
173 | return None
174 | return user
175 |
176 | def get_text_channel(ctx, channel):
177 | if channel_mention.match(channel):
178 | channel = discord.utils.get(ctx.guild.text_channels, id=int(channel_mention.match(channel).group(1)))
179 | elif regex_id.match(channel):
180 | channel = discord.utils.get(ctx.guild.text_channels, id=int(regex_id.match(channel).group(1)))
181 | else:
182 | try:
183 | channel = list(filter(lambda x: x.name.lower() == channel.lower(), ctx.guild.text_channels))[0]
184 | except IndexError:
185 | try:
186 | channel = list(filter(lambda x: x.name.lower().startswith(channel.lower()), ctx.guild.text_channels))[0]
187 | except IndexError:
188 | try:
189 | channel = list(filter(lambda x: channel.lower() in x.name.lower(), ctx.guild.text_channels))[0]
190 | except IndexError:
191 | return None
192 | return channel
193 |
194 | def get_voice_channel(ctx, channel):
195 | if regex_id.match(channel):
196 | channel = discord.utils.get(ctx.guild.voice_channels, id=int(regex_id.match(channel).group(1)))
197 | else:
198 | try:
199 | channel = list(filter(lambda x: x.name.lower() == channel.lower(), ctx.guild.voice_channels))[0]
200 | except IndexError:
201 | try:
202 | channel = list(filter(lambda x: x.name.lower().startswith(channel.lower()), ctx.guild.voice_channels))[0]
203 | except IndexError:
204 | try:
205 | channel = list(filter(lambda x: channel.lower() in x.name.lower(), ctx.guild.voice_channels))[0]
206 | except IndexError:
207 | return None
208 | return channel
209 |
210 | def get_category(ctx, category):
211 | if regex_id.match(category):
212 | channel = discord.utils.get(ctx.guild.categories, id=int(regex_id.match(category).group(1)))
213 | else:
214 | try:
215 | channel = list(filter(lambda x: x.name.lower() == category.lower(), ctx.guild.categories))[0]
216 | except IndexError:
217 | try:
218 | channel = list(filter(lambda x: x.name.lower().startswith(category.lower()), ctx.guild.categories))[0]
219 | except IndexError:
220 | try:
221 | channel = list(filter(lambda x: category.lower() in x.name.lower(), ctx.guild.categories))[0]
222 | except IndexError:
223 | return None
224 | return channel
--------------------------------------------------------------------------------
/Sx4/utils/arghelp.py:
--------------------------------------------------------------------------------
1 | from discord.ext import commands
2 | import discord
3 | import discord.utils
4 | import json
5 | import inspect
6 |
7 | async def send(bot, ctx):
8 | msg = ""
9 | try:
10 | perms = ctx.command.checks[0]
11 | except:
12 | perms = None
13 | if not ctx.command.usage:
14 | for x in ctx.command.params:
15 | if x != "ctx":
16 | if x != "self":
17 | if "=" in str(ctx.command.params[x]):
18 | msg += "[{}] ".format(x)
19 | else:
20 | msg += "<{}> ".format(x)
21 | else:
22 | msg += ctx.command.usage
23 | if not ctx.command.aliases:
24 | aliases = "None"
25 | else:
26 | aliases = ", ".join([x for x in ctx.command.aliases])
27 | if not perms:
28 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: None\nCommand description: {}".format(ctx.prefix, ctx.command, msg, aliases, ctx.command.help)
29 | else:
30 | msg = "Usage: {}{} {}\nCommand aliases: {}\nRequired permissions: {}\nCommand description: {}".format(ctx.prefix, ctx.command, msg, aliases,
31 | ", ".join(inspect.getclosurevars(perms).nonlocals["perms"]) if perms.__name__ != "is_owner_check" and str(perms).split(" ")[1].split(".")[0] != "is_main_owner" else "Bot Owner", ctx.command.help)
32 | try:
33 | msg += "\n\nSub commands: {}".format(", ".join([x for x in ctx.command.all_commands if x not in ctx.command.all_commands[x].aliases]))
34 | except:
35 | pass
36 | s=discord.Embed(description=msg)
37 | s.set_author(name=ctx.command, icon_url=bot.user.avatar_url)
38 | return await ctx.channel.send(embed=s)
39 |
--------------------------------------------------------------------------------
/Sx4/utils/checks.py:
--------------------------------------------------------------------------------
1 | from discord.ext import commands
2 | import discord
3 | import discord.utils
4 | import json
5 | import rethinkdb as r
6 | from utils.database import Database
7 |
8 | connection = Database.get_connection()
9 |
10 | def is_owner_check(ctx):
11 | if ctx.author.id in [153286414212005888, 51766611097944064, 402557516728369153, 190551803669118976, 388424304678666240]:
12 | return True
13 | else:
14 | return False
15 |
16 | def is_main_owner():
17 | def predicate(ctx):
18 | if ctx.author.id in [402557516728369153, 190551803669118976]:
19 | return True
20 | return commands.check(predicate)
21 |
22 | def is_owner():
23 | return commands.check(is_owner_check)
24 |
25 | def is_owner_c(author):
26 | if author.id in [153286414212005888, 51766611097944064, 402557516728369153, 190551803669118976, 388424304678666240]:
27 | return True
28 |
29 | def has_permissions(*perms):
30 | def predicate(ctx):
31 | serverdata = r.table("fakeperms").get(str(ctx.guild.id))
32 | role_perms = 0
33 | user_perms = 0
34 | if is_owner_check(ctx):
35 | return True
36 | elif ctx.author == ctx.guild.owner:
37 | return True
38 | elif serverdata.run(connection):
39 | user = serverdata["users"].filter(lambda x: x["id"] == str(ctx.author.id))
40 | roles = serverdata["roles"]
41 | if user.run(connection):
42 | user_perms = user[0]["perms"].run(connection)
43 | for x in ctx.author.roles:
44 | if str(x.id) in roles.map(lambda x: x["id"]).run(connection):
45 | role_perms |= roles.filter(lambda y: y["id"] == str(x.id))[0]["perms"].run(connection)
46 | perm_total = ctx.author.guild_permissions.value | user_perms | role_perms
47 | if discord.Permissions(perm_total).administrator:
48 | return True
49 | else:
50 | return all(getattr(discord.Permissions(perm_total), perm, None) for perm in perms)
51 | else:
52 | if ctx.author.guild_permissions.administrator:
53 | return True
54 | else:
55 | return all(getattr(ctx.author.guild_permissions, perm, None) for perm in perms)
56 | return commands.check(predicate)
57 |
--------------------------------------------------------------------------------
/Sx4/utils/ctime.py:
--------------------------------------------------------------------------------
1 | import discord
2 |
3 | def convert(time: str):
4 | times = time.split(" ")
5 | seconds = 0
6 | for x in times:
7 | if x.lower().endswith("s"):
8 | seconds += int(x[:-1])
9 | elif x.lower().endswith("m"):
10 | seconds += int(x[:-1]) * 60
11 | elif x.lower().endswith("h"):
12 | seconds += int(x[:-1]) * 3600
13 | elif x.lower().endswith("d"):
14 | seconds += int(x[:-1]) * 86400
15 | elif x.isdigit():
16 | seconds += int(x)
17 | else:
18 | pass
19 | return seconds
20 |
--------------------------------------------------------------------------------
/Sx4/utils/data.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | class FileAlreadyExists(Exception):
5 | pass
6 |
7 | def read_json(file):
8 | with open(file, "r") as f:
9 | return json.loads(f.read())
10 |
11 | def write_json(file, data: dict):
12 | with open(file, "w") as f:
13 | f.write(json.dumps(data))
14 |
15 | def file_exists(file):
16 | return os.path.isfile(file)
17 |
18 | def create_file(file, data: dict={}):
19 | if file_exists(file):
20 | raise FileAlreadyExists("That file already exists, use write_json to update the file")
21 | else:
22 | with open(file, "w") as f:
23 | f.write(json.dumps(data))
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/Sx4/utils/database.py:
--------------------------------------------------------------------------------
1 | import rethinkdb as r
2 |
3 | connection = r.connect(db="sx4")
4 |
5 | class Database:
6 | def get_connection():
7 | return connection
--------------------------------------------------------------------------------
/Sx4/utils/dateify.py:
--------------------------------------------------------------------------------
1 | import discord
2 | from datetime import datetime, timedelta
3 |
4 | def get(timestamp):
5 | m, s = divmod(timestamp, 60)
6 | h, m = divmod(m, 60)
7 | d, h = divmod(h, 24)
8 | w, d = divmod(d, 7)
9 | M, w = divmod(w, 4.345238095238096)
10 | y, M = divmod(M, 12)
11 | time_str = ""
12 | if y:
13 | time_str += "%d year%s " % (y, "" if y == 1 else "s")
14 | if M:
15 | time_str += "%d month%s " % (M, "" if M == 1 else "s")
16 | if w >= 1:
17 | time_str += "%d week%s " % (w, "" if w == 1 else "s")
18 | if d:
19 | time_str += "%d day%s " % (d, "" if d == 1 else "s")
20 | if h:
21 | time_str += "%d hour%s " % (h, "" if h == 1 else "s")
22 | if m:
23 | time_str += "%d minute%s " % (m, "" if m == 1 else "s")
24 | if s:
25 | time_str += "%d second%s " % (s, "" if s >= 1 and s < 2 else "s")
26 | return time_str[:-1]
27 |
--------------------------------------------------------------------------------
/Sx4/utils/paged.py:
--------------------------------------------------------------------------------
1 | import re
2 | import asyncio
3 | import math
4 | import discord
5 |
6 | previous_aliases = ["previous", "p", "previous page"]
7 | next_aliases = ["next", "n", "next page"]
8 | cancel_aliases = ["stop", "cancel", "c"]
9 | page_locations = ["title", "footer"]
10 | all_aliases = previous_aliases + next_aliases + cancel_aliases
11 | confirmed = ["y", "yes", "accept"]
12 |
13 | async def page(ctx, array: list, selectable: bool=False, per_page: int=10, function: callable=None, timeout: int=60, auto_select: bool=False, indexed: bool=True, page_location: str="title", title: str="", colour: int=None, author: dict={"name": "", "icon_url": discord.Embed.Empty, "url": ""}):
14 | bot = ctx.bot
15 | page_location = page_location.lower()
16 | current_page = 1
17 | max_page = math.ceil(len(array)/per_page)
18 | last_page_entries = len(array) % per_page if len(array) % per_page != 0 else per_page
19 | if selectable and len(array) == 1 and auto_select:
20 | page = current_page
21 | index = 0
22 | index_on_page = 1
23 | object = array[index]
24 | return {"object": object, "user_index": index_on_page, "index": index, "page": page}
25 | re_page = re.compile("go to ([0-9]+)")
26 | s=discord.Embed(title="Page {}/{}".format(current_page, max_page) + (" | " + title if title else "") if page_location == "title" else title,
27 | description="\n".join([("{}. ".format(i) if indexed else "") + "{}".format(function(x) if function else x) for i, x in enumerate(array[per_page*current_page-per_page:current_page*per_page], start=1)]),
28 | colour=discord.Colour(colour) if colour else discord.Embed.Empty)
29 | s.set_author(name=author["name"] if "name" in author else "", icon_url=author["icon_url"] if "icon_url" in author else discord.Embed.Empty, url=author["url"] if "url" in author else "")
30 | s.set_footer(text="next | previous | go to | cancel{}".format(" | Page {}/{}".format(current_page, max_page) if page_location == "footer" else ""))
31 | message = await ctx.send(embed=s)
32 | def check(m):
33 | regex = re_page.match(m.content.lower())
34 | if ctx.channel == m.channel and ctx.author == m.author:
35 | if regex:
36 | return int(regex.group(1)) <= max_page and int(regex.group(1)) > 0
37 | if not selectable:
38 | return m.content.lower() in all_aliases
39 | else:
40 | if m.content.lower() in all_aliases:
41 | return True
42 | elif m.content.isdigit():
43 | return int(m.content) > 0 and int(m.content) <= (per_page if current_page != max_page else last_page_entries)
44 | else:
45 | return False
46 | def update_page(current_page: int):
47 | embed = message.embeds[0]
48 | embed.description = "\n".join([("{}. ".format(i) if indexed else "") + "{}".format(function(x) if function else x) for i, x in enumerate(array[per_page*current_page-per_page:current_page*per_page], start=1)])
49 | embed.title = "Page {}/{}".format(current_page, max_page) + (" | " + title if title else "") if page_location == "title" else title
50 | if page_location == "footer":
51 | embed.set_footer(text="next | previous | go to | cancel | Page {}/{}".format(current_page, max_page))
52 | return embed
53 | while True:
54 | try:
55 | response = await bot.wait_for("message", check=check, timeout=timeout)
56 | regex_page = re_page.match(response.content.lower())
57 | if response.content.lower() in cancel_aliases:
58 | try:
59 | await message.delete()
60 | except:
61 | pass
62 | try:
63 | await response.delete()
64 | except:
65 | pass
66 | return None
67 | elif response.content.lower() in next_aliases:
68 | if current_page == max_page:
69 | current_page = 1
70 | else:
71 | current_page += 1
72 | try:
73 | await response.delete()
74 | except:
75 | pass
76 | await message.edit(embed=update_page(current_page))
77 | elif response.content.lower() in previous_aliases:
78 | if current_page == 1:
79 | current_page = max_page
80 | else:
81 | current_page -= 1
82 | try:
83 | await response.delete()
84 | except:
85 | pass
86 | await message.edit(embed=update_page(current_page))
87 | elif regex_page:
88 | current_page = int(regex_page.group(1))
89 | try:
90 | await response.delete()
91 | except:
92 | pass
93 | await message.edit(embed=update_page(current_page))
94 | elif response.content.isdigit():
95 | try:
96 | await message.delete()
97 | except:
98 | pass
99 | try:
100 | await response.delete()
101 | except:
102 | pass
103 | page = current_page
104 | index = ((current_page * per_page) - per_page) + (int(response.content) - 1)
105 | index_on_page = int(response.content)
106 | object = array[index]
107 | return {"object": object, "user_index": index_on_page, "index": index, "page": page}
108 | except asyncio.TimeoutError:
109 | try:
110 | await message.delete()
111 | except:
112 | pass
113 | try:
114 | await response.delete()
115 | except:
116 | pass
117 | return None
118 |
119 | async def confirm(ctx, timeout: int=60, message: discord.Message=None):
120 | bot = ctx.bot
121 | try:
122 | response = await bot.wait_for("message", check=lambda m: ctx.author == m.author and ctx.channel == m.channel, timeout=timeout)
123 | if response.content.lower() in confirmed:
124 | return True
125 | else:
126 | try:
127 | if message:
128 | await message.delete()
129 | except:
130 | pass
131 | try:
132 | await response.delete()
133 | except:
134 | pass
135 | return False
136 | except asyncio.TimeoutError:
137 | try:
138 | if message:
139 | await message.delete()
140 | except:
141 | pass
142 | try:
143 | await response.delete()
144 | except:
145 | pass
146 |
--------------------------------------------------------------------------------