-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdiscord.py
165 lines (129 loc) · 5.54 KB
/
discord.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
from __future__ import annotations
import asyncio
import re
import warnings
from typing import TYPE_CHECKING, AsyncIterable, Iterable, Union
import discord
from discord.ext import commands
from .tools import Paginator
async def get_role(
guild: discord.Guild,
name: str,
overwrite: discord.PermissionOverwrite = None,
permissions: discord.Permissions = None,
) -> discord.Role:
"""Returns a role with specific overwrites"""
role = discord.utils.find(lambda r: r.name.lower() == name.lower(), guild.roles)
if role is None:
role = await guild.create_role(name=name, permissions=permissions or discord.Permissions.none())
elif permissions is not None and role.permissions != permissions:
await role.edit(permissions=permissions)
if overwrite is None:
return role
for channel in guild.channels:
if channel.category and channel.permissions_synced:
channel = channel.category
if channel.overwrites_for(role) != overwrite:
await channel.set_permissions(role, overwrite=overwrite)
return role
async def get_muted_role(guild: discord.Guild) -> discord.Role:
"""Returns the muted role or creates one."""
overwrite = discord.PermissionOverwrite(send_messages=False, add_reactions=False)
return await get_role(guild, "muted", overwrite)
async def get_webhook(channel: discord.TextChannel) -> discord.Webhook:
"""Returns the general bot hook or creates one"""
webhook = discord.utils.find(
lambda w: w.name is not None and w.name.lower() == "culture hook", await channel.webhooks()
)
if webhook is None:
from bot import bot
webhook = await channel.create_webhook(
name="Culture Hook", avatar=await bot.user.display_avatar.read(), reason="For making better looking messages"
)
return webhook
def get_emoji(name: str, guild: discord.Guild = None) -> discord.Emoji:
"""Returns the emoji from the main server"""
if guild is None:
from bot import bot
guild = bot.get_guild(570841314200125460) # type: ignore
emoji = discord.utils.find(lambda e: e.name.lower() == name.lower(), guild.emojis)
if emoji is None:
warnings.warn(f"Couldn't find an emoji: {name}")
return discord.PartialEmoji(name=":grey_question:") # type: ignore
return emoji
async def _try_delete_reaction(message: discord.Message, payload: discord.RawReactionActionEvent) -> None:
try:
await message.remove_reaction(payload.emoji, discord.Object(id=payload.user_id))
except discord.Forbidden:
pass
page_left, page_right, remove = "◀", "▶", "❌"
async def send_pages(
ctx: commands.Context,
destination: Union[discord.abc.Messageable, discord.Message],
pages: Union[Iterable[discord.Embed], AsyncIterable[discord.Embed]],
asyncify: bool = False,
timeout: int = 60,
):
"""Send multiple embeds as pages, supports iterators
If asyncify is true the items will be gotten asynchronously even with sync iterables.
"""
paginator = await Paginator.create(pages)
if isinstance(destination, discord.Message):
message = destination
else:
message = await destination.send(embed=paginator.curr)
for reaction in (page_left, page_right, remove):
asyncio.create_task(message.add_reaction(reaction))
while True:
try:
payload = await ctx.bot.wait_for(
"raw_reaction_add",
check=lambda payload: payload.user_id != ctx.bot.user.id and message.id == payload.message_id,
timeout=timeout,
)
except asyncio.TimeoutError:
try:
await message.clear_reactions()
except discord.Forbidden:
pass
return
del_task = asyncio.create_task(_try_delete_reaction(message, payload))
if payload.user_id != ctx.author.id:
continue
r = str(payload.emoji)
if r == remove:
del_task.cancel()
await message.delete()
return
elif r == page_right:
embed = await paginator.next(asyncify=asyncify)
elif r == page_left:
try:
embed = paginator.prev()
except IndexError:
continue
else:
continue
await message.edit(embed=embed)
def bot_channel_only(regex: str = r"bot|spam", category: bool = True, dms: bool = True):
def predicate(ctx: commands.Context):
channel = ctx.channel
if not isinstance(channel, discord.TextChannel):
if dms:
return True
raise commands.CheckFailure("Dms are not counted as a bot channel.")
if re.search(regex, channel.name) or category and re.search(regex, str(channel.category)):
return True
raise commands.CheckFailure("This channel is not a bot channel.")
return commands.check(predicate)
def guild_check(guild: Union[int, discord.Guild]):
"""A check decorator for guilds"""
guild = guild.id if isinstance(guild, discord.Guild) else guild
def predicate(ctx: commands.Context):
if ctx.guild is None:
raise commands.NoPrivateMessage()
elif ctx.guild.id != guild:
raise commands.CheckFailure("This command cannot be used in this server")
else:
return True
return commands.check(predicate)