22
22
"""
23
23
from __future__ import annotations
24
24
25
+ from typing import TypeVar
26
+
25
27
import discord
26
28
from discord .ext import commands
27
29
28
30
import core
31
+ from constants import GUILD_ID
29
32
30
33
31
- class InformationEmbed (discord .Embed ):
32
- """A subclass of discord.Embed.
34
+ EntityT = TypeVar ("EntityT" , discord .Member , discord .User , discord .Role , discord .abc .GuildChannel , discord .Guild )
33
35
34
- This class allows to automatically get information within the class instead of recreating the embed each time
35
36
36
- :param author: The embed author. Expects discord.Member or discord.User
37
- :param entity: The Member, User, Role, TextChannel, or Guild to get information about.
38
- """
37
+ class NoPermissions (commands .CommandError ):
38
+ pass
39
39
40
- def __init__ (
41
- self ,
42
- * ,
43
- author : discord .Member | discord .User ,
44
- entity : discord .Member | discord .User | discord .Role | discord .TextChannel | discord .Guild ,
45
- ) -> None :
46
- super ().__init__ ()
47
- created_at : str = f"{ discord .utils .format_dt (entity .created_at )} ({ discord .utils .format_dt (entity .created_at , 'R' )} )"
48
- if isinstance (entity , discord .Member ) and entity .joined_at :
49
- joined_at = f"\n \n Joined At: { discord .utils .format_dt (entity .joined_at )} ({ discord .utils .format_dt (entity .joined_at , 'R' )} )"
50
- else :
51
- joined_at = ""
52
40
53
- description = f"Name: { entity .name } \n \n ID: { entity .id } \n \n Created At: { created_at } { joined_at } "
54
- if isinstance (entity , discord .Member ):
55
- self .set_thumbnail (url = entity .guild_avatar or entity .display_avatar or None )
56
- elif isinstance (entity , discord .User ):
57
- self .set_thumbnail (url = entity .display_avatar or None )
41
+ class Information (core .Cog ):
42
+ """Information commands which allows you to get information about users, the guild, roles, and channels."""
43
+
44
+ def __init__ (self , bot : core .Bot ) -> None :
45
+ self .bot : core .Bot = bot
46
+
47
+ async def cog_command_error (self , ctx : core .Context , error : commands .CommandError ) -> None : # type: ignore # bad lib types.
48
+ error = getattr (error , "original" , error )
49
+
50
+ if isinstance (error , NoPermissions ):
51
+ await ctx .send ("Sorry, you don't have permissions to view details on this object." )
52
+ return
53
+
54
+ def _embed_factory (self , entity : EntityT ) -> discord .Embed :
55
+ embed = discord .Embed (title = f"Info on { entity .name } !" , colour = discord .Colour .random ())
56
+ embed .add_field (name = "ID:" , value = entity .id )
57
+ embed .timestamp = discord .utils .utcnow ()
58
+
59
+ if isinstance (entity , discord .User ):
60
+ return self ._user_info (entity , embed = embed )
61
+ elif isinstance (entity , discord .Member ):
62
+ embed = self ._user_info (entity , embed = embed ) # type: ignore # superclass
63
+ return self ._member_info (entity , embed = embed )
58
64
elif isinstance (entity , discord .Role ):
59
- description += f"\n \n Hoisted: { entity .hoist } \n \n Mentionable: { entity .mentionable } \n \n "
60
- elif isinstance (entity , discord .TextChannel ):
61
- description += f"\n \n Category: { entity .category } \n \n NSFW: { entity .nsfw } "
62
- else : # Change to elif when other types are added
63
- description += f"\n \n Owner: { entity .owner } "
64
- self .set_thumbnail (url = entity .icon or None )
65
+ return self ._role_info (entity , embed = embed )
66
+ elif isinstance (entity , discord .abc .GuildChannel ):
67
+ return self ._channel_info (entity , embed = embed )
68
+ else :
69
+ return self ._guild_info (entity , embed = embed )
65
70
66
- self .description = description
67
- self .set_author (name = author .name , icon_url = author .display_avatar )
68
- self .color = 0x7289DA
71
+ def _member_info (self , member : discord .Member , / , * , embed : discord .Embed ) -> discord .Embed :
72
+ if member .joined_at :
73
+ joined_at_fmt = (
74
+ discord .utils .format_dt (member .joined_at , "F" ) + "\n " f"({ discord .utils .format_dt (member .joined_at , 'R' )} )"
75
+ )
76
+ embed .add_field (name = "Member joined the guild on:" , value = joined_at_fmt )
69
77
78
+ roles = [role .mention for role in member .roles [1 :]]
79
+ roles .reverse ()
80
+ embed .add_field (name = "Member's top 5 roles:-" , value = "\n " .join (roles [:5 ]), inline = False )
81
+ embed .colour = member .colour or embed .colour
70
82
71
- class Information (core .Cog ):
72
- """Information commands which allows you to get information about users, the guild, roles, and channels."""
83
+ return embed
73
84
74
- def __init__ (self , bot : core .Bot ) -> None :
75
- self .bot = bot
85
+ def _user_info (self , user : discord .User , / , * , embed : discord .Embed ) -> discord .Embed :
86
+ embed = discord .Embed (title = f"Info on { user .display_name } !" , colour = discord .Colour .random ())
87
+ embed .set_author (name = user .name )
88
+ embed .set_image (url = user .display_avatar .url )
89
+ created_at_fmt = (
90
+ discord .utils .format_dt (user .created_at , "F" ) + "\n " f"({ discord .utils .format_dt (user .created_at , 'R' )} )"
91
+ )
92
+ embed .add_field (name = "Account was created on:" , value = created_at_fmt )
93
+
94
+ embed .timestamp = discord .utils .utcnow ()
95
+
96
+ return embed
97
+
98
+ def _role_info (self , role : discord .Role , / , * , embed : discord .Embed ) -> discord .Embed :
99
+ embed .colour = role .colour or embed .colour
100
+ embed .add_field (name = "Mentionable?" , value = role .mentionable )
101
+ embed .add_field (name = "Hoisted?" , value = role .hoist )
102
+ embed .add_field (name = "Member count:" , value = len (role .members ))
103
+ embed .add_field (name = "Created on:" , value = discord .utils .format_dt (role .created_at , "F" ))
104
+
105
+ return embed
106
+
107
+ def _channel_info (self , channel : discord .abc .GuildChannel , / , * , embed : discord .Embed ) -> discord .Embed :
108
+ sneaky_role = channel .guild .default_role
109
+ permissions = channel .permissions_for (sneaky_role )
110
+
111
+ allowed_to_read = discord .Permissions (read_messages = True , view_channel = True )
112
+
113
+ if not permissions .is_strict_superset (allowed_to_read ):
114
+ # They cannot read this channel
115
+ raise NoPermissions ("Cannot read this channel." )
116
+
117
+ embed .url = channel .jump_url
118
+
119
+ embed .add_field (name = "Channel type:" , value = channel .type .name , inline = False )
120
+
121
+ embed .add_field (name = "Created on:" , value = discord .utils .format_dt (channel .created_at , "F" ), inline = False )
122
+
123
+ is_private = not (permissions .view_channel or permissions .read_messages )
124
+ embed .add_field (name = "Private Channel?" , value = is_private )
125
+
126
+ return embed
127
+
128
+ def _guild_info (self , guild : discord .Guild , / , * , embed : discord .Embed ) -> discord .Embed :
129
+ if guild .id != GUILD_ID :
130
+ raise NoPermissions ("Unreachable but better safe than sorry." )
131
+
132
+ embed .add_field (name = "Created on:" , value = discord .utils .format_dt (guild .created_at , "F" ))
133
+ embed .set_thumbnail (url = (guild .icon and guild .icon .url ))
134
+
135
+ return embed
76
136
77
137
@commands .group (
78
138
name = "information" ,
@@ -81,18 +141,21 @@ def __init__(self, bot: core.Bot) -> None:
81
141
invoke_without_command = True ,
82
142
)
83
143
async def info (
84
- self , ctx : core .Context , entity : discord .Member | discord .User | discord .Role | discord .TextChannel = commands .Author
144
+ self ,
145
+ ctx : core .Context ,
146
+ * ,
147
+ entity : discord .Member
148
+ | discord .User
149
+ | discord .Role
150
+ | discord .abc .GuildChannel
151
+ | discord .Guild = commands .CurrentGuild ,
85
152
) -> None :
86
- """Get information about a object
87
- Args:
88
- entity: The user, role, or TextChannel to get information about"""
89
- embed = InformationEmbed (author = ctx .author , entity = entity )
90
- await ctx .send (embed = embed )
91
-
92
- @info .command (name = "guild" , brief = "Get the current guild's information." )
93
- async def guild_info (self , ctx : core .GuildContext ):
94
- embed = InformationEmbed (author = ctx .author , entity = ctx .guild )
95
- await ctx .reply (embed = embed )
153
+ """Get information about a specific Pythonista related object.
154
+
155
+ entity: Accepts a Person's ID, a Role ID or a Channel ID. Defaults to showing info on the Guild.
156
+ """
157
+ embed = self ._embed_factory (entity ) # type: ignore # we ignore because converter sadness
158
+ await ctx .reply (embed = embed , mention_author = False )
96
159
97
160
98
161
async def setup (bot : core .Bot ) -> None :
0 commit comments