-
Notifications
You must be signed in to change notification settings - Fork 0
/
__init__.py
206 lines (175 loc) · 8.13 KB
/
__init__.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
import asyncio
import contextlib
import io
import time
from discord import app_commands
from discord.ext import commands
import breadcord
from breadcord.module import ModuleCog
from .helpers import *
class Thermometer(ModuleCog, WhoisHelper):
def __init__(self, module_id: str):
super().__init__(module_id)
super(WhoisHelper, self).__init__()
self.cog_load_time: datetime = datetime.now()
self.ctx_menu = app_commands.ContextMenu(
name="Who got mentioned",
callback=self.role_mention_members_ctx_menu,
)
self.bot.tree.add_command(self.ctx_menu)
async def cog_load(self) -> None:
await self.open_session()
async def cog_unload(self) -> None:
await self.close_session()
@commands.hybrid_command(description="Returns how long the bot has been running.")
async def uptime(self, ctx: commands.Context) -> None:
# This is technically wrong, as it's the cog uptime, not necessarily the bot uptime, but eh
uptime = datetime.now() - self.cog_load_time
started_timestamp = round(time.mktime(self.cog_load_time.timetuple()))
await ctx.reply(
f"Bot has been online for {readable_timedelta(uptime)}, last started <t:{started_timestamp}>"
)
@commands.hybrid_command(aliases=["pfp"], description="Gets a user's profile picture.")
async def avatar(
self,
ctx: commands.Context,
user: discord.User | None = None,
global_avatar: bool = False,
) -> None:
user = user or ctx.author
await ctx.reply(
embed=discord.Embed(
title=f"{user}'s avatar",
colour=user.colour,
).set_image(
url=enhance_asset_image(user.avatar if global_avatar else user.display_avatar).url,
)
)
@commands.hybrid_command(description="Gets info about a user.")
async def whois(self, ctx: commands.Context, user: discord.User | None = None) -> None:
user: discord.User = await self.bot.fetch_user(user.id) if user else ctx.author
user_info = await self.get_user_info(user)
embeds = []
async def fetch_avatar() -> discord.File | None:
with contextlib.suppress(discord.NotFound):
return discord.File(
fp=io.BytesIO(await enhance_asset_image(user.avatar).read()),
filename="avatar.gif" if user.avatar.is_animated() else "avatar.png",
)
async def fetch_banner() -> discord.File | None:
if user.banner is None:
return None
with contextlib.suppress(discord.NotFound):
return discord.File(
fp=io.BytesIO(await enhance_asset_image(user.banner).read()),
filename="banner.gif" if user.banner.is_animated() else "banner.png",
)
if user in ctx.guild.members:
user: discord.Member = ctx.guild.get_member(user.id)
user_info |= await self.get_member_info(user)
embeds.extend(await self.get_member_activity_embeds(user))
avatar_task = asyncio.create_task(fetch_avatar())
banner_task = asyncio.create_task(fetch_banner())
done, pending = await asyncio.wait(
[avatar_task, banner_task],
return_when=asyncio.ALL_COMPLETED,
timeout=1,
)
embeds.insert(0, build_info_embed(
user_info,
title="User info",
colour=user.colour,
thumbnail=enhance_asset_image(user.avatar).url,
image=enhance_asset_image(user.banner).url if user.banner else None,
))
avatar_file, banner_file = None, None
if avatar_task in done:
avatar_file = avatar_task.result()
if avatar_file:
embeds[0].set_thumbnail(url=f"attachment://{avatar_file.filename}")
if banner_task in done:
banner_file = banner_task.result()
if banner_file:
embeds[0].set_image(url=f"attachment://{banner_file.filename}")
response = await ctx.reply(
embeds=embeds,
files=tuple(filter(bool, (avatar_file, banner_file))),
)
if pending:
if avatar_task in pending:
avatar_file = await avatar_task
if avatar_file:
embeds[0].set_thumbnail(url=f"attachment://{avatar_file.filename}")
if banner_task in pending:
banner_file = await banner_task
if banner_file:
embeds[0].set_image(url=f"attachment://{banner_file.filename}")
if not (avatar_file or banner_file):
return
if isinstance(avatar_file, discord.File):
avatar_file.fp.seek(0)
if isinstance(banner_file, discord.File):
banner_file.fp.seek(0)
await response.edit(
embeds=embeds,
attachments=tuple(filter(bool, (avatar_file, banner_file))),
)
@commands.hybrid_group(name="guild", description="Various guild related info")
async def guild_info_group(self, ctx: commands.Context) -> None:
# This function is executed when "guild" is run as a message command, it will never run from a slash command.
await self.guild_info(ctx)
@guild_info_group.command(name="channels", description="Get the guilds channels.")
async def guild_channels(self, ctx: commands.Context) -> None:
channels = [
channel.mention
for channel in ctx.guild.channels
if not isinstance(channel, discord.CategoryChannel)
]
await ctx.reply(embed=discord.Embed(
title="Guild channels",
description=f"**Channel count:** {len(channels)}\n\n" + "\n".join(channels)
))
@guild_info_group.command(name="emojis", description="Get the guilds emojis.")
async def guild_emojis(self, ctx: commands.Context) -> None:
emojis = ctx.guild.emojis
await ctx.reply(embed=discord.Embed(
title="Guild emojis",
description=f"**Emoji count:** {len(emojis)}\n\n" + "".join(map(str, emojis))
))
@guild_info_group.command(name="members", description="Get the guilds members.")
async def guild_members(self, ctx: commands.Context) -> None:
members = sorted(ctx.guild.members, key=lambda x: x.name)
await ctx.reply(embed=discord.Embed(
title="Guild members",
description=f"**Member count:** {len(members)}\n\n" + ", ".join([member.mention for member in members]),
))
@guild_info_group.command(name="info", description="Gets general info about the guild.")
async def guild_info(self, ctx: commands.Context) -> None:
await ctx.reply(embed=build_info_embed(
await GuildInfoHelper.get_guild_info(ctx.guild),
title="Guild info",
thumbnail=enhance_asset_image(ctx.guild.icon).url if ctx.guild.icon else None,
image=enhance_asset_image(ctx.guild.banner).url if ctx.guild.banner else None,
inline_fields=False,
))
async def role_mention_members_ctx_menu(self, interaction: discord.Interaction, message: discord.Message) -> None:
if not message.role_mentions:
await interaction.response.send_message("No role mentions found.", ephemeral=True)
return
embeds_to_be_sent = [
discord.Embed(
title=f'Members with the role "{role.name}" ' + ("(top 25)" if len(role.members) > 25 else ""),
description=", ".join([member.mention for member in role.members[:25]]),
colour=role.colour,
)
for role in message.role_mentions
if role.members
][:10]
await interaction.response.send_message(
f"Only showing 10 of the {len(message.role_mentions)} role mentions."
if len(message.role_mentions) > 10 else "",
embeds=embeds_to_be_sent,
ephemeral=True,
)
async def setup(bot: breadcord.Bot, module: breadcord.module.Module) -> None:
await bot.add_cog(Thermometer(module.id))