Passed
Push — main ( 98503b...6c3c91 )
by Bartosz
01:17
created

build.cogs.maincog.MainCog.exit_bot()   A

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 5
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 5
dl 5
loc 5
rs 10
c 0
b 0
f 0
cc 1
nop 2
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 discord
16
from discord_slash.utils.manage_commands import create_permission
17
from discord.ext import commands
18
from discord_slash import cog_ext, SlashContext
19
from discord_slash.model import SlashCommandPermissionType
20
import json
21
from cogs.cogbase import BaseCog
22
from modules.get_settings import get_settings
23
from modules.pull_config.pull_config import get_config
24
25
guild_ids = get_settings("guild")
26
27
MODERATION_IDS = get_settings("MOD_ROLES")
28
PERMISSIONS_MODS = {
29
    guild_ids[0]: [
30
        create_permission(MODERATION_IDS[0], SlashCommandPermissionType.ROLE, True),
31
        create_permission(MODERATION_IDS[1], SlashCommandPermissionType.ROLE, True)
32
    ]
33
}
34
35
36 View Code Duplication
class MainCog(BaseCog):
37
    def __init__(self, base):
38
        super().__init__(base)
39
40
    # GENERAL FUNCTIONS
41
    # Check latency
42
    @cog_ext.cog_slash(name="ping", guild_ids=guild_ids,
43
                       description="Test function for checking latency",
44
                       default_permission=False,
45
                       permissions=PERMISSIONS_MODS)
46
    async def _ping(self, ctx: SlashContext):
47
        await ctx.send(f"Pong! {round(self.bot.latency * 1000)}ms", delete_after=4.0)
48
49
    # Clear messages
50
    @cog_ext.cog_slash(name="clear", guild_ids=guild_ids,
51
                       description="Function for clearing messages on channel",
52
                       default_permission=False,
53
                       permissions=PERMISSIONS_MODS)
54
    async def _purge(self, ctx: SlashContext, number):
55
        num_messages = int(number)
56
        await ctx.channel.purge(limit=num_messages)
57
        await ctx.send(f"Cleared {num_messages} messages!", delete_after=4.0)
58
59
    # Disconnect Bot
60
    @cog_ext.cog_slash(name="exit", guild_ids=guild_ids,
61
                       description="Turn off the bot",
62
                       default_permission=False,
63
                       permissions=PERMISSIONS_MODS)
64
    async def _exit(self, ctx: SlashContext):
65
        await ctx.send(f"Closing Bot", delete_after=1.0)
66
        print("[INFO]: Exiting Bot")
67
        await asyncio.sleep(2)
68
        await self.bot.close()
69
70
    # WARN FUNCTIONS
71
    # Warn user
72
    @cog_ext.cog_slash(name="warn", guild_ids=guild_ids,
73
                       description="Function for warning users",
74
                       default_permission=False,
75
                       permissions=PERMISSIONS_MODS)
76
    async def _warn(self, ctx: SlashContext, user: discord.User, reason: str):
77
        with open('./json_files/warns.json', encoding='utf-8') as f:
78
            try:
79
                report = json.load(f)
80
            except ValueError:
81
                report = {'users': []}
82
83
        warned = False
84
        reason = ''.join(reason)
85
        for current_user in report['users']:
86
            if current_user['id'] == user.id:
87
                current_user['reasons'].append(reason)
88
                warned = True
89
                await ctx.send(f"{user.mention} was warned for:\n\"{reason}\"\n"
90
                               f"Number of warns: {len(current_user['reasons'])}")
91
                break
92
        if not warned:
93
            report['users'].append({
94
                'id': user.id,
95
                'name': user.display_name,
96
                'reasons': [reason, ]
97
            })
98
            # TODO: Improve 'reasons' format(or not?)
99
            await ctx.send(f"{user.mention} was warned for:\n\"{reason}\"\n")
100
101
        with open('./json_files/warns.json', 'w+') as f:
102
            json.dump(report, f, indent=4)
103
104
    # Get list of user's warns
105
    # Does not work if used too much
106
    @cog_ext.cog_slash(name="warns", guild_ids=guild_ids,
107
                       description="Function for warning users",
108
                       default_permission=False,
109
                       permissions=PERMISSIONS_MODS)
110
    async def _warns(self, ctx: SlashContext, user: discord.User):
111
        with open('./json_files/warns.json', encoding='utf-8') as f:
112
            try:
113
                report = json.load(f)
114
            except ValueError:
115
                report = {'users': []}
116
117
        for current_user in report['users']:
118
            if user.id == current_user['id']:
119
                message = f"{user.name} has been warned {len(current_user['reasons'])} times\nReasons:\n " \
120
                          f"{','.join(current_user['reasons'])}"
121
                # TODO: Improve 'reasons' message formatting
122
                await ctx.author.send(message)
123
                await ctx.send(f"{user.name} warns has been sent to DM", hidden=True)
124
                break
125
        else:
126
            await ctx.author.send(f"{user.name} has never been warned")
127
            await ctx.send(f"{user.name} warns has been sent to DM", hidden=True)
128
129
    @cog_ext.cog_slash(name="removeWarns", guild_ids=guild_ids,
130
                       description="Function for managing user's warns",
131
                       default_permission=False,
132
                       permissions=PERMISSIONS_MODS)
133
    async def remove_warns(self, ctx: SlashContext, user: discord.User, nr_to_delete: int):
134
        if nr_to_delete < 0:
135
            await ctx.send(f"Really? Negative nr?", hidden=True)
136
            return
137
138
        with open('./json_files/warns.json', encoding='utf-8') as f:
139
            try:
140
                report = json.load(f)
141
            except ValueError:
142
                report = {'users': []}
143
144
        warns_removed = False
145
        for current_user in report['users']:
146
            if current_user['id'] == user.id:
147
                current_user['reasons'] = current_user['reasons'][:-nr_to_delete or None]
148
                await ctx.send(f"{user.display_name}'s last {nr_to_delete} warns were deleted", delete_after=5.0)
149
                warns_removed = True
150
                break
151
        if not warns_removed:
152
            await ctx.send(f"{user.display_name} did not have any warns", delete_after=5.0)
153
154
        with open('./json_files/warns.json', 'w+') as f:
155
            json.dump(report, f, indent=4)
156
157
    @cog_ext.cog_slash(name="updateTotMem", guild_ids=guild_ids,
158
                       description="Update total number of members",
159
                       default_permission=False,
160
                       permissions=PERMISSIONS_MODS)
161
    async def update_member_count_command(self, ctx: SlashContext):
162
        await self.bot.update_member_count(ctx)
163
        await ctx.send(f"Total Members count updated", hidden=True)
164
165
    @cog_ext.cog_slash(name="updateCommons", guild_ids=guild_ids,
166
                       description="Update common channel name",
167
                       default_permission=False,
168
                       permissions=PERMISSIONS_MODS)
169
    async def update_commons_ch(self, ctx: SlashContext, common: str):
170
        new_name = f"common-{common}"
171
        channel = self.bot.get_channel(self.bot.CH_COMMON)
172
        await discord.TextChannel.edit(channel, name=new_name)
173
        await ctx.send(f"Common channel updated", hidden=True)
174
175
    # Pull config.json from Google Sheets
176
    @cog_ext.cog_slash(name="pullConfig", guild_ids=guild_ids,
177
                       description="Pull config from google sheets",
178
                       default_permission=False,
179
                       permissions={
180
                           guild_ids[0]: [
181
                               create_permission(get_settings("ADMIN"), SlashCommandPermissionType.USER, True)
182
                           ]
183
                       })
184
    async def pull_config(self, ctx: SlashContext):
185
        get_config()
186
        with open('json_files/config.json', 'r', encoding='utf-8-sig') as fp:
187
            self.bot.config = json.load(fp)
188
            self.bot.reload_extension("cogs.rolecog")
189
        await ctx.send(f"Config.json updated", hidden=True)
190
191
    # OTHER
192
193
    # Did BonJowi killed N-Word? (unstable)
194
    # Apparently you can not use this command more often than every x minutes
195
    @cog_ext.cog_slash(name="nword", guild_ids=guild_ids,
196
                       description="Change N-Word channel name",
197
                       permissions=PERMISSIONS_MODS)
198
    async def rename_nword_channel(self, ctx, status: str):
199
        new_status = status
200
        channel = self.bot.get_channel(self.bot.CH_NIGHTMARE_KILLED)
201
        if new_status in channel.name:
202
            await ctx.send(f"{channel.name} has been changed", hidden=True)
203
            return
204
        else:
205
            await discord.VoiceChannel.edit(channel, name=f"N-Word spotted: {new_status}")
206
            await ctx.send(f"{channel.name} channel name has been changed", hidden=True)
207
208
    # async def rename_nword_channel(self, ctx):
209
    #     channel = self.bot.get_channel(CH_NWORD_KILLED)
210
    #     if "YES" in channel.name:
211
    #         new_status = "NO"
212
    #     elif "NO" in channel.name:
213
    #         new_status = "YES"
214
    #     else:
215
    #         return
216
    #     # new_status = "YES" if "NO" in channel.name else "NO" if "YES" in channel.name else ""
217
    #     print(type(new_status))
218
    #     print(new_status)
219
    #     await discord.VoiceChannel.edit(channel, name=f"N-Word killed: {new_status}")
220
    #     await ctx.send(f"{channel.name} channel name has been changed", hidden=True)
221
222
    # Disconnect Bot using "!" prefix (For safety reasons in case Slash commands are not working
223
    @commands.command(name="ex", pass_context=True, aliases=["e", "exit"])
224
    async def exit_bot(self, ctx):
225
        print("[INFO]: Exiting Bot")
226
        await ctx.send(f"Closing Bot")
227
        await self.bot.close()
228
229
230
def setup(bot: commands.Bot):
231
    bot.add_cog(MainCog(bot))
232