Passed
Push — main ( 530a31...c507f0 )
by Bartosz
02:42 queued 01:19
created

build.cogs.utilscog.UtilsCog.system_status()   A

Complexity

Conditions 1

Size

Total Lines 33
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 28
dl 0
loc 33
rs 9.208
c 0
b 0
f 0
cc 1
nop 2
1
import json
2
import math
3
import os
4
import re
5
from datetime import datetime
6
import time
7
import discord
8
import psutil
9
from discord.utils import get
10
from numpyencoder import NumpyEncoder
11
12
from modules.get_settings import get_settings
13
import cogs.cogbase as cogbase
14
from discord.ext import commands
15
from discord_slash import cog_ext, SlashContext
16
from cogs.databasecog import DatabaseCog
17
from modules.pull_config.pull_config import get_config
18
19
20
class UtilsCog(cogbase.BaseCog):
21
    def __init__(self, base):
22
        super().__init__(base)
23
24
    # OTHER
25
    # Pull config.json from Google Sheets
26
    @cog_ext.cog_slash(name="pullConfig", guild_ids=cogbase.GUILD_IDS,
27
                       description="Pull config from google sheets",
28
                       default_permission=False,
29
                       permissions=cogbase.PERMISSION_ADMINS)
30
    async def pull_config_command(self, ctx: SlashContext):
31
        get_config()
32
        with open('server_files/config.json', 'r', encoding='utf-8-sig') as fp:
33
            self.bot.config = json.load(fp)
34
            await self.create_roles(ctx, True)
35
            await self.create_roles(ctx, False)
36
            self.create_log_msg(f"Finished data pull")
37
        await ctx.send(f"Config.json updated", hidden=True)
38
39
    # Create roles if pull_config gets non existent roles
40
    async def create_roles(self, ctx: SlashContext, common: bool):
41
        milestones = "common_milestones" if common else "total_milestones"
42
        for mon_type in self.bot.config[milestones][0]:
43
            if get(ctx.guild.roles, name=mon_type):
44
                continue
45
            else:
46
                await ctx.guild.create_role(name=mon_type)
47
                self.create_log_msg(f"{mon_type} role created")
48
49
    # Clear temp spots table in database
50
    @cog_ext.cog_slash(name="clearTempSpots", guild_ids=cogbase.GUILD_IDS,
51
                       description="Clear temp spots table in database",
52
                       default_permission=False,
53
                       permissions=cogbase.PERMISSION_ADMINS)
54
    async def clear_temp_spots_table(self, ctx):
55
        await DatabaseCog.db_clear_spots_temp_table()
56
        await ctx.send(f"Temp spots table was cleared", hidden=True)
57
        await self.reload_cog(ctx, "databasecog")
58
59
    # Reloads cog, very useful because there is no need to exit the bot after updating cog
60
    async def reload_cog(self, ctx: SlashContext, module: str):
61
        """Reloads a module."""
62
        module = f"cogs.{module}"
63
        try:
64
            self.bot.load_extension(f"{module}")
65
            await ctx.send(f'[{module}] loaded', delete_after=4.0)
66
            self.create_log_msg(f"{module} loaded")
67
        except commands.ExtensionAlreadyLoaded:
68
            self.bot.unload_extension(module)
69
            self.bot.load_extension(module)
70
            await ctx.send(f'[{module}] reloaded', delete_after=4.0)
71
            self.create_log_msg(f"{module} reloaded")
72
        except commands.ExtensionNotFound:
73
            await ctx.send(f'[{module}] not found', delete_after=2.0)
74
            self.create_log_msg(f"{module} not found")
75
76
    # Command for reloading specific cog
77
    @cog_ext.cog_slash(name="reloadCog", guild_ids=cogbase.GUILD_IDS,
78
                       description="Reload cog",
79
                       default_permission=False,
80
                       permissions=cogbase.PERMISSION_ADMINS)
81
    async def reload_cog_command(self, ctx: SlashContext, module: str):
82
        await self.reload_cog(ctx, module)
83
84
    # Command for reloading all cogs
85
    @cog_ext.cog_slash(name="reloadAllCogs", guild_ids=cogbase.GUILD_IDS,
86
                       description="Reload all bot cogs",
87
                       default_permission=False,
88
                       permissions=cogbase.PERMISSION_ADMINS)
89
    async def reload_all_cogs(self, ctx: SlashContext = None):
90
        for cog in list(self.bot.extensions.keys()):
91
            cog = cog.replace('cogs.', '')
92
            await self.reload_cog(ctx, cog)
93
        await ctx.send(f'All cogs reloaded', delete_after=2.0)
94
95
    @cog_ext.cog_slash(name="saveDatabaseCoordinates", guild_ids=cogbase.GUILD_IDS,
96
                       description="Save coordinates from database to a file",
97
                       default_permission=False,
98
                       permissions=cogbase.PERMISSION_ADMINS)
99
    async def save_coordinates(self, ctx: SlashContext):
100
        coords_df = await DatabaseCog.db_get_coords()
101
        coords_df = coords_df[coords_df.coords.str.contains(",")]
102
        print(coords_df)
103
        coords_df[['latitude', 'longitude']] = coords_df['coords'].str.split(',', 1, expand=True)
104
        path_coords = r"server_files/coords.xlsx"
105
        coords_df.to_excel(path_coords, index=False)
106
        await ctx.send(f"Coords saved", hidden=True)
107
        self.create_log_msg(f"Coords saved to {path_coords}")
108
109
    # Get member info
110
    @cog_ext.cog_slash(name="memberinfo", guild_ids=cogbase.GUILD_IDS,
111
                       description="Get member discord info",
112
                       default_permission=False,
113
                       permissions=cogbase.PERMISSION_ADMINS)
114
    async def member_info(self, ctx: SlashContext, *, user: discord.Member = None):
115
        if user is None:
116
            user = ctx.author
117
        date_format = "%a, %d %b %Y %I:%M %p"
118
        embed = discord.Embed(color=0xFF0000, description=user.mention)
119
        embed.set_author(name=str(user), icon_url=user.avatar_url)
120
        embed.set_thumbnail(url=user.avatar_url)
121
        embed.add_field(name="Joined Server", value=user.joined_at.strftime(date_format), inline=False)
122
        members = sorted(ctx.guild.members, key=lambda m: m.joined_at)
123
        embed.add_field(name="Join Position", value=str(members.index(user) + 1), inline=False)
124
        embed.add_field(name="Joined Discord", value=user.created_at.strftime(date_format), inline=False)
125
        if len(user.roles) > 1:
126
            role_string = ' '.join([r.mention for r in user.roles][1:])
127
            embed.add_field(name="Roles [{}]".format(len(user.roles) - 1), value=role_string, inline=False)
128
        embed.set_footer(text='ID: ' + str(user.id))
129
        return await ctx.send(embed=embed)
130
131
    # Backup database to a file
132
    @cog_ext.cog_slash(name="backupDatabase", guild_ids=cogbase.GUILD_IDS,
133
                       description="Backup database to a file",
134
                       default_permission=False,
135
                       permissions=cogbase.PERMISSION_MODS)
136
    async def backup_database(self, ctx: SlashContext):
137
        now = datetime.now()
138
        cmd = f"mysqldump -u {get_settings('DB_U')} " \
139
              f"--result-file=database_backup/backup-{now.strftime('%m-%d-%Y')}.sql " \
140
              f"-p{get_settings('DB_P')} server_database"
141
        os.system(cmd)
142
        await ctx.send(f"Database backed up", hidden=True)
143
144
    # System stats
145
    @cog_ext.cog_slash(name="systemStatus", guild_ids=cogbase.GUILD_IDS,
146
                       description="Get status of the system",
147
                       default_permission=False,
148
                       permissions=cogbase.PERMISSION_MODS)
149
    async def system_status(self, ctx):
150
        """Get status of the system."""
151
        process_uptime = time.time() - self.bot.start_time
152
        process_uptime = time.strftime("%ed %Hh %Mm %Ss", time.gmtime(process_uptime))
153
        process_uptime = process_uptime.replace(re.search(r'\d+', process_uptime).group(),
154
                                                str(int(re.search(r'\d+', process_uptime).group()) - 1), 1)
155
        system_uptime = time.time() - psutil.boot_time()
156
        system_uptime = time.strftime("%ed %Hh %Mm %Ss", time.gmtime(system_uptime))
157
        system_uptime = system_uptime.replace(re.search(r'\d+', system_uptime).group(),
158
                                              str(int(re.search(r'\d+', system_uptime).group()) - 1), 1)
159
        mem = psutil.virtual_memory()
160
        pid = os.getpid()
161
        memory_use = psutil.Process(pid).memory_info()[0]
162
163
        data = [
164
            ("Version", self.bot.version),
165
            ("Process uptime", process_uptime),
166
            ("Process memory", f"{memory_use / math.pow(1024, 2):.2f}MB"),
167
            ("System uptime", system_uptime),
168
            ("CPU Usage", f"{psutil.cpu_percent()}%"),
169
            ("RAM Usage", f"{mem.percent}%"),
170
        ]
171
172
        content = discord.Embed(
173
            title=":computer: System status",
174
            colour=int("5dadec", 16),
175
            description="\n".join(f"**{x[0]}** {x[1]}" for x in data),
176
        )
177
        await ctx.send(embed=content)
178
179
    # Change monster type(for events)
180
    @cog_ext.cog_slash(name="changeMonsterType", guild_ids=cogbase.GUILD_IDS,
181
                       description="Change type of a monster",
182
                       default_permission=False,
183
                       permissions=cogbase.PERMISSION_ADMINS)
184
    async def change_monster_type(self, ctx, monster: str, new_type: int):
185
        config = self.bot.config
186
        for mon in config["commands"]:
187
            if mon["name"] == monster:
188
                mon["type"] = new_type
189
                self.create_log_msg(f"Changed type for {monster}")
190
                await ctx.send(f"{monster}'s type changed", hidden=True)
191
                break
192
193
        self.bot.config = config
194
        with open('server_files/config.json', 'w', encoding='utf8') as f:
195
            json.dump(config, f, indent=4, ensure_ascii=False, sort_keys=False, cls=NumpyEncoder)
196
197
    # Update guides channel
198
    @cog_ext.cog_slash(name="updateGuides", guild_ids=cogbase.GUILD_IDS,
199
                       description="Update #guides channel",
200
                       default_permission=False,
201
                       permissions=cogbase.PERMISSION_MODS)
202
    async def update_guides(self, ctx: SlashContext):
203
        await ctx.channel.purge(limit=10)
204
205
        embed = discord.Embed(title="SPOOFING GUIDES", color=0x878a00)
206
        embed.add_field(name="Recommended Fake GPS App for Android users",
207
                        value="https://play.google.com/store/apps/details?id=com.theappninjas.fakegpsjoystick",
208
                        inline=True)
209
        embed.add_field(name="Recommended Fake GPS App for iOS users",
210
                        value="https://www.thinkskysoft.com/itools", inline=False)
211
        embed.add_field(name="Recommended android emulator for Windows and Mac",
212
                        value="https://www.bignox.com", inline=False)
213
        embed.add_field(name="YT Guide for Fake GPS Location recommended app (by @ChampattioNonNightMareMare)",
214
                        value="https://www.youtube.com/watch?v=wU7qOLEm7qQ", inline=False)
215
        embed.add_field(name="YT Guide for GPS spoofing with iTools (by @Loonasek)",
216
                        value="https://www.youtube.com/watch?v=1M8jq3JNAMM", inline=False)
217
        embed.add_field(
218
            name="Nox guide for creating macro and keyboard mapping; "
219
                 "it can help in automatically making potion, fight, blocks signs etc.",
220
            value="https://support.bignox.com/en/keyboard/macro1", inline=False)
221
        await ctx.send(embed=embed)
222
223
        embed = discord.Embed(title="GAME GUIDES", color=0x8a3c00)
224
        embed.add_field(name="Advanced Combat guide", value="https://www.youtube.com/watch?v=-D0wIzwxp0Y",
225
                        inline=False)
226
        embed.add_field(name="Guide to the game quests",
227
                        value="https://docs.google.com/document/d/"
228
                              "1vK1HfJlglTluNdypzH3XbQDi0vgJ0SNi2lUHbk3lqcE/edit",
229
                        inline=False)
230
        embed.add_field(name="Recommended Skill Tree (by @Sagar)",
231
                        value="https://pasteboard.co/LYjVo2u1aIDt.jpg%", inline=False)
232
        await ctx.send(embed=embed)
233
234
        embed = discord.Embed(title="USEFUL TOOLS", color=0x019827)
235
        embed.add_field(name="Great sheet for checking monster spawn conditions(credit to @TaraxGoat))",
236
                        value="https://docs.google.com/spreadsheets/d/"
237
                              "148qPGW9oYOaYAzpk_a06u2FBnw9rZzAmBZ6AxWFrryI/edit#gid=2093943306",
238
                        inline=False)
239
        embed.add_field(name="Website for checking timezones/current time",
240
                        value="https://www.timeanddate.com/worldclock/?sort=2", inline=False)
241
        await ctx.send(embed=embed)
242
243
        with open('./server_files/bot_guide.txt') as f:
244
            try:
245
                bot_guide = f.read()
246
            except ValueError:
247
                print(ValueError)
248
        await ctx.send(bot_guide)
249
250
251
def setup(bot: commands.Bot):
252
    bot.add_cog(UtilsCog(bot))
253