Passed
Branch BonHowi (5fc634)
by Bartosz
03:11 queued 26s
created

build.cogs.commandscog.CommandsCog.reload_cog()   A

Complexity

Conditions 3

Size

Total Lines 15
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 15
rs 9.7
c 0
b 0
f 0
cc 3
nop 3
1
"""
2
Cog with general commands available in the Bot.
3
4
Current commands:
5
/ping -     check Bot latency
6
/clear -    clear x messages on the channel
7
/exit | !exit -     end Bot's runtime and disconnect from the server
8
/warn -     warn @user with reason
9
/warns -    send @user warns to author's DM
10
/nword -    Changes N-Word killed channel name  -   UNSTABLE
11
/updatetotmem - Update #TotalMembers channel
12
/updatecommon - Update common spotting channel with new monster name
13
"""
14
import asyncio
15
import json
16
import discord
17
from discord.utils import get
18
import cogs.cogbase as cogbase
19
from discord.ext import commands
20
from discord_slash import cog_ext, SlashContext
21
from cogs.databasecog import DatabaseCog
22
from cogs.leaderboardcog import legend_multiplier
23
from modules.pull_config.pull_config import get_config
24
25
26
class CommandsCog(cogbase.BaseCog):
27
    def __init__(self, base):
28
        super().__init__(base)
29
30
    # GENERAL FUNCTIONS
31
    # Check latency
32
    @cog_ext.cog_slash(name="ping", guild_ids=cogbase.GUILD_IDS,
33
                       description="Test function for checking latency",
34
                       default_permission=False,
35
                       permissions=cogbase.PERMISSION_MODS)
36
    async def _ping(self, ctx: SlashContext):
37
        await ctx.send(f"Pong! {round(self.bot.latency * 1000)}ms", delete_after=4.0)
38
39
    # Clear messages
40
    @cog_ext.cog_slash(name="clear", guild_ids=cogbase.GUILD_IDS,
41
                       description="Function for clearing messages on channel",
42
                       default_permission=False,
43
                       permissions=cogbase.PERMISSION_MODS)
44
    async def _purge(self, ctx: SlashContext, number):
45
        num_messages = int(number)
46
        await ctx.channel.purge(limit=num_messages)
47
        await ctx.send(f"Cleared {num_messages} messages!", delete_after=4.0)
48
49
    # Disconnect Bot
50
    @cog_ext.cog_slash(name="exit", guild_ids=cogbase.GUILD_IDS,
51
                       description="Turn off the bot",
52
                       default_permission=False,
53
                       permissions=cogbase.PERMISSION_ADMINS)
54
    async def _exit(self, ctx: SlashContext):
55
        await ctx.send(f"Closing Bot", delete_after=1.0)
56
        dt_string = self.bot.get_current_time()
57
        print(f"({dt_string})\t[{self.__class__.__name__}]: Exiting Bot")
58
        await asyncio.sleep(3)
59
        await self.bot.close()
60
61
    # WARN FUNCTIONS
62
    # Warn user
63
    @cog_ext.cog_slash(name="warn", guild_ids=cogbase.GUILD_IDS,
64
                       description="Function for warning users",
65
                       default_permission=False,
66
                       permissions=cogbase.PERMISSION_MODS)
67
    async def _warn(self, ctx: SlashContext, user: discord.User, reason: str):
68
69
        await DatabaseCog.db_add_warn(user.id, reason)
70
        await ctx.send(
71
            f"{user.mention} was warned for:\n*\"{reason}\"*\n")  # f"Number of warns: {len(current_user['reasons'])}")
72
73
    # Get list of user's warns
74
    @cog_ext.cog_slash(name="warns", guild_ids=cogbase.GUILD_IDS,
75
                       description="Function for warning users",
76
                       default_permission=False,
77
                       permissions=cogbase.PERMISSION_MODS)
78
    async def _warns(self, ctx: SlashContext, user: discord.User):
79
        warns, nr_of_warns = await DatabaseCog.db_get_warns(user.id)
80
        nl = "\n"
81
        message = f"**{user.name}** has been warned **{nr_of_warns}** times\n\n_Reasons_:\n" \
82
                  f"{nl.join(warns)}\n"
83
        await ctx.author.send(message)
84
        await ctx.send(f"{user.name} warns has been sent to DM", hidden=True)
85
86
    # Remove all member's warns
87
    @cog_ext.cog_slash(name="removeWarns", guild_ids=cogbase.GUILD_IDS,
88
                       description="Function for removing user's all warns",
89
                       default_permission=False,
90
                       permissions=cogbase.PERMISSION_ADMINS)
91
    async def remove_warns(self, ctx: SlashContext, user: discord.User):
92
        await DatabaseCog.db_remove_warns(user.id)
93
        await ctx.send(f"{user.display_name}'s warns were deleted", hidden=True)
94
95
    # Mute member
96
    @cog_ext.cog_slash(name="mute", guild_ids=cogbase.GUILD_IDS,
97
                       description="Mute member for x minutes",
98
                       default_permission=False,
99
                       permissions=cogbase.PERMISSION_MODS)
100
    async def _mute(self, ctx: SlashContext, user: discord.User, time: int, reason: str):
101
        duration = time * 60
102
        guild = ctx.guild
103
        muted = discord.utils.get(guild.roles, name="Muted")
104
105
        if not muted:
106
            muted = await guild.create_role(name="Muted")
107
            for channel in guild.channels:
108
                await channel.set_permissions(muted, speak=False, send_messages=False, read_message_history=True,
109
                                              read_messages=False)
110
        await user.add_roles(muted, reason=reason)
111
        await ctx.send(f"{user.mention} Was muted by {ctx.author.name} for {time} min\n"
112
                       f"Reason: {reason}", delete_after=10)
113
        await asyncio.sleep(duration)
114
        await user.remove_roles(muted)
115
        await ctx.send(f"{user.mention}'s mute is over", delete_after=10)
116
117
    # CHANNEL NAMES UPDATES
118
    # Total member channel name
119
    @cog_ext.cog_slash(name="updateTotalMembers", guild_ids=cogbase.GUILD_IDS,
120
                       description="Update total number of members",
121
                       default_permission=False,
122
                       permissions=cogbase.PERMISSION_MODS)
123
    async def update_member_count_command(self, ctx: SlashContext):
124
        await self.bot.update_member_count(ctx)
125
        await ctx.send(f"Total Members count updated", hidden=True)
126
127
    # Commons channel name
128
    @cog_ext.cog_slash(name="updateCommons", guild_ids=cogbase.GUILD_IDS,
129
                       description="Update common channel name",
130
                       default_permission=False,
131
                       permissions=cogbase.PERMISSION_MODS)
132
    async def update_commons_ch_command(self, ctx: SlashContext):
133
        with open('./server_files/commons.txt') as f:
134
            try:
135
                commons = f.read().splitlines()
136
            except ValueError:
137
                print(ValueError)
138
139
        await self.update_commons_ch(ctx, commons)
140
141
        commons.append(commons.pop(commons.index(commons[0])))
142
        with open('./server_files/commons.txt', 'w') as f:
143
            for item in commons:
144
                f.write("%s\n" % item)
145
146
    async def update_commons_ch(self, ctx: SlashContext, commons):
147
        new_name = f"common {commons[0]}"
148
        common_ch = self.bot.get_channel(self.bot.ch_common)
149
        await discord.TextChannel.edit(common_ch, name=new_name)
150
        dt_string = self.bot.get_current_time()
151
        print(f"({dt_string})\t[{self.__class__.__name__}]: Common channel name updated: {commons[0]}")
152
153
        admin_posting = self.bot.get_channel(self.bot.ch_admin_posting)
154
        await admin_posting.send(f"Common changed: {commons[0]}")
155
        await ctx.send(f"Common changed: {commons[0]}", hidden=True)
156
157
    # N-Word spotted channel name
158
    # Doesn't work if used too many times in a short period of time
159
    @cog_ext.cog_slash(name="nword", guild_ids=cogbase.GUILD_IDS,
160
                       description="Change N-Word channel name",
161
                       permissions=cogbase.PERMISSION_ADMINS)
162
    async def rename_nword_channel(self, ctx, status: str):
163
        new_status = status
164
        channel = self.bot.get_channel(self.bot.ch_nightmare_killed)
165
        if new_status in channel.name:
166
            await ctx.send(f"{channel.name} has been changed", hidden=True)
167
        else:
168
            await discord.VoiceChannel.edit(channel, name=f"N-Word spotted: {new_status}")
169
            await ctx.send(f"{channel.name} channel name has been changed", hidden=True)
170
171
    # OTHER
172
173
    # Pull config.json from Google Sheets
174
    @cog_ext.cog_slash(name="pullConfig", guild_ids=cogbase.GUILD_IDS,
175
                       description="Pull config from google sheets",
176
                       default_permission=False,
177
                       permissions=cogbase.PERMISSION_ADMINS)
178
    async def pull_config(self, ctx: SlashContext):
179
        get_config()
180
        with open('server_files/config.json', 'r', encoding='utf-8-sig') as fp:
181
            self.bot.config = json.load(fp)
182
            await self.create_roles(ctx, True)
183
            await self.create_roles(ctx, False)
184
            dt_string = self.bot.get_current_time()
185
            print(f"({dt_string})\t[{self.__class__.__name__}]: Finished data pull")
186
        await ctx.send(f"Config.json updated", hidden=True)
187
188
    # Create roles if pull_config gets non existent roles
189
    async def create_roles(self, ctx: SlashContext, common: bool):
190
        milestones = "common_milestones" if common else "total_milestones"
191
        for mon_type in self.bot.config[milestones][0]:
192
            if get(ctx.guild.roles, name=mon_type):
193
                continue
194
            else:
195
                await ctx.guild.create_role(name=mon_type)
196
                dt_string = self.bot.get_current_time()
197
                print(f"({dt_string})\t[{self.__class__.__name__}]: {mon_type} role created")
198
199
    # Clear temp spots table in database
200
    @cog_ext.cog_slash(name="clearTempSpots", guild_ids=cogbase.GUILD_IDS,
201
                       description="Clear temp spots table in database",
202
                       permissions=cogbase.PERMISSION_ADMINS)
203
    async def clear_temp_spots_table(self, ctx):
204
        await DatabaseCog.db_clear_spots_temp_table()
205
        await ctx.send(f"Temp spots table was cleared", hidden=True)
206
        await self.reload_cog(ctx, "cogs.databasecog")
207
208
    # Reloads cog, very useful because there is no need to exit the bot after updating cog
209
    async def reload_cog(self, ctx: SlashContext, module: str):
210
        """Reloads a module."""
211
        dt_string = self.bot.get_current_time()
212
        try:
213
            self.bot.load_extension(f"{module}")
214
            await ctx.send(f'[{module}] loaded', hidden=True)
215
            print(f'({dt_string})\t[{self.__class__.__name__}]: {module} loaded')
216
        except commands.ExtensionAlreadyLoaded:
217
            self.bot.unload_extension(module)
218
            self.bot.load_extension(module)
219
            await ctx.send(f'[{module}] reloaded', hidden=True)
220
            print(f'({dt_string})\t[{self.__class__.__name__}]: {module} reloaded')
221
        except commands.ExtensionNotFound:
222
            await ctx.send(f'[{module}] not found', hidden=True)
223
            print(f'({dt_string})\t[{self.__class__.__name__}]: {module} not found')
224
225
    # Command for reloading specific cog
226
    @cog_ext.cog_slash(name="reloadCog", guild_ids=cogbase.GUILD_IDS,
227
                       description="Reload cog",
228
                       permissions=cogbase.PERMISSION_ADMINS)
229
    async def reload_cog_command(self, ctx: SlashContext, module: str):
230
        await self.reload_cog(ctx, module)
231
232
    # Command for reloading all cogs
233
    @cog_ext.cog_slash(name="reloadAllCogs", guild_ids=cogbase.GUILD_IDS,
234
                       description="Reload cog",
235
                       permissions=cogbase.PERMISSION_ADMINS)
236
    async def reload_all_cogs(self, ctx: SlashContext = None):
237
        for cog in list(self.bot.extensions.keys()):
238
            await self.reload_cog(ctx, cog)
239
        await ctx.send(f'All cogs reloaded', hidden=True)
240
241
    # Get own spotting stats
242
    @cog_ext.cog_slash(name="myStats", guild_ids=cogbase.GUILD_IDS,
243
                       description="Get your spot stats",
244
                       default_permission=True)
245
    async def get_stats(self, ctx):
246
        spot_roles = self.bot.config["total_milestones"][0]
247
        guild = self.bot.get_guild(self.bot.guild[0])
248
        spots_df = await DatabaseCog.db_get_member_stats(ctx.author.id)
249
        spots_df["total"] = spots_df["legendary"] * legend_multiplier + spots_df["rare"]
250
251
        role_new = ""
252
        spots_for_new = -1
253
        roles_list = [key for (key, value) in spot_roles.items() if spots_df.at[0, "total"] < value]
254
        values_list = [value for (key, value) in spot_roles.items() if spots_df.at[0, "total"] < value]
255
        if roles_list:
256
            role_new = get(guild.roles, name=roles_list[0])
257
            spots_for_new = values_list[0]
258
259
        message = f"**Legends**: {spots_df.at[0, 'legendary']}\n" \
260
                  f"**Rares**: {spots_df.at[0, 'rare']}\n" \
261
                  f"**Commons**: {spots_df.at[0, 'common']}\n\n" \
262
                  f"**Total points**: {spots_df.at[0, 'total']}\n" \
263
                  f"**Progress**: {spots_df.at[0, 'total']}/{spots_for_new}\n" \
264
                  f"**Next role**: _{role_new}_"
265
266
        await ctx.send(f"{ctx.author.mention} stats:\n{message}", hidden=True)
267
268
    @cog_ext.cog_slash(name="saveCoordinates", guild_ids=cogbase.GUILD_IDS,
269
                       description="Get your spot stats",
270
                       permissions=cogbase.PERMISSION_ADMINS)
271
    async def save_coordinates(self, ctx: SlashContext):
272
        coords_df = await DatabaseCog.db_get_coords()
273
        coords_df[['latitude', 'longitude']] = coords_df['coords'].str.split(',', expand=True)
274
        coords_df.to_excel(r'server_files/coords.xlsx', index=False)
275
        await ctx.send(f"Coords saved", hidden=True)
276
        dt_string = self.bot.get_current_time()
277
        print(f'({dt_string})\t[{self.__class__.__name__}]: Coords saved to server_files/coords.xlsx')
278
279
280
def setup(bot: commands.Bot):
281
    bot.add_cog(CommandsCog(bot))
282