Passed
Pull Request — stable (#69)
by Sydney
49s
created

botutils.command_getprefix()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
#    Copyright 2017 Starbot Discord Project
2
# 
3
#    Licensed under the Apache License, Version 2.0 (the "License");
4
#    you may not use this file except in compliance with the License.
5
#    You may obtain a copy of the License at
6
# 
7
#        http://www.apache.org/licenses/LICENSE-2.0
8
# 
9
#    Unless required by applicable law or agreed to in writing, software
10
#    distributed under the License is distributed on an "AS IS" BASIS,
11
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
#    See the License for the specific language governing permissions and
13
#    limitations under the License.
14
15
import math
16
import os
17
import platform
18
import sys
19
import time
20
21
import discord
22
import psutil
23
import pyspeedtest
24
25
from api import settings, logging, command, message, plugin, git
26
from api.bot import Bot
27
from libs import progressBar, readableTime, displayname
28
29
def commands_detect_dups():
30
    duplicates = []
31
    commands_list = []
32
    for plugin_in in Bot.plugins:
33
        for command_in in plugin_in.commands:
34
            commands_list.append(command_in.name)
35
36
    for command_in in commands_list:
37
        commandOccurances = 0
38
        for command2 in commands_list:
39
            if command_in == command2:
40
                commandOccurances += 1
41
        if commandOccurances > 1:
42
            duplicates.append(command_in)
43
44
    return list(set(duplicates))
45
46
def convert_size(size_bytes: int) -> str:
47
    if size_bytes == 0:
48
        return '0B'
49
    size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
50
    i = int(math.floor(math.log(size_bytes, 1024)))
51
    p = math.pow(1024, i)
52
    s = round(size_bytes/p, 2)
53
    return '%s %s' % (s, size_name[i])
54
55
def onInit(plugin_in: plugin.Plugin):
56
    plugins_command    = command.Command(plugin_in, 'plugins',    command_plugins,    shortdesc='Print a list of plugins',                devcommand=True)
57
    commands_command   = command.Command(plugin_in, 'commands',   command_commands,   shortdesc='Print a list of commands',               devcommand=True)
58
    help_command       = command.Command(plugin_in, 'help',       command_commands,   shortdesc='Print a list of commands')
59
    info_command       = command.Command(plugin_in, 'info',       command_info,       shortdesc='Print some basic bot info')
60
    plugintree_command = command.Command(plugin_in, 'plugintree', command_plugintree, shortdesc='Print a tree of plugins and commands',   devcommand=True)
61
    uptime_command     = command.Command(plugin_in, 'uptime',     command_uptime,     shortdesc='Print the bot\'s uptime',                devcommand=True)
62
    hostinfo_command   = command.Command(plugin_in, 'hostinfo',   command_hostinfo,   shortdesc='Prints information about the bots home', devcommand=True)
63
    cpuinfo_command    = command.Command(plugin_in, 'cpuinfo',    command_cpuinfo,    shortdesc='Prints info about the system CPUs',      devcommand=True)
64
    setprefix_command  = command.Command(plugin_in, 'setprefix',  command_setprefix,  shortdesc='Set the server prefix',                  devcommand=True)
65
    getprefix_command  = command.Command(plugin_in, 'getprefix',  command_getprefix,  shortdesc='Get the server prefix',                  devcommand=True)
66
    speedtest_command  = command.Command(plugin_in, 'speedtest',  command_speedtest,  shortdesc='Run a speedtest',                        devcommand=True)
67
    addowner_command   = command.Command(plugin_in, 'addowner',   command_addowner,   shortdesc='Add a bot owner',                        devcommand=True)
68
    owners_command     = command.Command(plugin_in, 'owners',     command_owners,     shortdesc='Print the bot owners',                   devcommand=True)
69
    return plugin.Plugin(plugin_in, 'botutils', [plugins_command, commands_command, help_command, info_command, plugintree_command, uptime_command,
70
                                                 hostinfo_command, cpuinfo_command, setprefix_command, getprefix_command, speedtest_command, addowner_command,
71
                                                 owners_command])
72
73
async def command_plugins(message_in: message.Message):
74
    plugin_list = []
75
    for plugin_in in Bot.plugins:
76
        plugin_list.append(plugin_in.name)
77
    return message.Message(body='```{}```'.format(', '.join(plugin_list)))
78
79
async def command_commands(message_in: message.Message):
80
    cmd_names = []
81
    cmd_descs = []
82
    for botcommand in Bot.commands:
83
        if botcommand.devcommand != True:
84
            cmd_names.append(botcommand.name)
85
            cmd_descs.append(botcommand.shortdesc)
86
    cmd_list = []
87
    pad_len = len(max(cmd_names, key=len))
88
    for index, value in enumerate(cmd_names):
89
        cmd_list.append('{} - {}'.format(cmd_names[index].ljust(pad_len), cmd_descs[index]))
90
    return message.Message(body='```{}```'.format('\n'.join(cmd_list)))
91
92
async def command_info(message_in: message.Message):
93
    sha = git.git_commit()
94
    track = git.git_branch()
95
    remote = git.get_remote()
96
    if track == 'master':
97
        embed = discord.Embed(color=discord.Color.red())
98
    elif track == 'unstable':
99
        embed = discord.Embed(color=discord.Color.gold())
100
    elif track == 'stable':
101
        embed = discord.Embed(color=discord.Color.green())
102
    else:
103
        embed = discord.Embed(color=discord.Color.light_grey())
104
    embed.set_author(name='Project StarBot v0.2.0-{} on track {}'.format(sha[:7], track))
105
    embed.set_footer(text="Pulled from {}".format(remote))
106
    return message.Message(embed=embed)
107
108
async def command_plugintree(message_in: message.Message):
109
    dups = commands_detect_dups()
110
    plugin_string = '```\n'
111
    for plugin_in in Bot.plugins:
112
        plugin_string += '{}\n'.format(plugin_in.name)
113
        plugin_commands = len(plugin_in.commands)
114
        index = 0
115
        for command_in in plugin_in.commands:
116
            index += 1
117
            if plugin_commands != index:
118
                if command_in.name in dups:
119
                    plugin_string += '├ {} <-- duplicate\n'.format(command_in.name)
120
                else:
121
                    plugin_string += '├ {}\n'.format(command_in.name)
122
            else:
123
                if command_in.name in dups:
124
                    plugin_string += '└ {} <-- duplicate\n'.format(command_in.name)
125
                else:
126
                    plugin_string += '└ {}\n'.format(command_in.name)
127
    plugin_string += '```'
128
    return message.Message(body=plugin_string)
129
130
async def command_uptime(message_in: message.Message):
131
    time_current = int(time.time())
132
    time_str = readableTime.getReadableTimeBetween(Bot.startTime, time_current)
133
    return message.Message(body='I\'ve been up for *{}*.'.format(time_str))
134
135
async def command_hostinfo(message_in: message.Message):
136
    # Get information about host environment.
137
    time_current = int(time.time())
138
139
    # CPU stats.
140
    cpu_threads = os.cpu_count()
141
    cpu_usage = psutil.cpu_percent(interval=1)
142
143
    # Memory stats.
144
    mem_stats = psutil.virtual_memory()
145
    mem_percent = mem_stats.percent
146
    mem_used = convert_size(mem_stats.used)
147
    mem_total = convert_size(mem_stats.total)
148
149
    # Platform info.
150
    platform_current = platform.platform()
151
152
    # Python version info.
153
    pyver_major = sys.version_info.major
154
    pyver_minor = sys.version_info.minor
155
    pyver_micro = sys.version_info.micro
156
    pyver_release = sys.version_info.releaselevel
157
158
    # Storage info.
159
    stor = psutil.disk_usage('/')
160
    stor_used = convert_size(stor.used)
161
    stor_total = convert_size(stor.total)
162
    stor_free = convert_size(stor.total - stor.used)
163
164
    # Format hostinfo with OS, CPU, RAM, storage, and other bot info.
165
    msg = '***{}\'s*** **Home:**\n'.format(displayname.name(message_in.guild.me))
166
    msg += '```Host OS       : {}\n'.format(platform_current)
167
    msg += 'Host Python   : {}.{}.{} {}\n'.format(pyver_major, pyver_minor, pyver_micro, pyver_release)
168
    if not isinstance(cpu_threads, int):
169
        msg += 'Host CPU usage: {}% of {}\n'.format(cpu_usage, platform.machine())
170
    elif cpu_threads > 1:
171
        msg += 'Host CPU usage: {}% of {} ({} threads)\n'.format(cpu_usage, platform.machine(), cpu_threads)
172
    else:
173
        msg += 'Host CPU usage: {}% of {} ({} thread)\n'.format(cpu_usage, platform.machine(), cpu_threads)
174
    msg += 'Host RAM      : {} ({}%) of {}\n'.format(mem_used, mem_percent, mem_total)
175
    msg += 'Host storage  : {} ({}%) of {} - {} free\n'.format(stor_used, stor.percent, stor_total, stor_free)
176
    msg += 'Hostname      : {}\n'.format(platform.node())
177
    msg += 'Host uptime   : {}```'.format(readableTime.getReadableTimeBetween(psutil.boot_time(), time.time()))
178
179
    # Return completed message.
180
    return message.Message(body=msg)
181
182
async def command_cpuinfo(message_in: message.Message):
183
    # Get CPU usage and create string for message.
184
    cpu_pcts = psutil.cpu_percent(interval=0.1, percpu=True)
185
    cpu_pct_str = '{}\n'.format(platform.processor())
186
    cpu_threads = psutil.cpu_count()
187
    cpu_cores = psutil.cpu_count(logical=False)
188
    cpu_arch = platform.machine()
189
    # First, check to see if we can accurately determine the number of physical cores. If not, omit the core count.
190
    if not cpu_cores:
191
        if cpu_threads > 1:
192
            cpu_pct_str += '{} threads of {}'.format(cpu_threads, cpu_arch)
193
        else:
194
            cpu_pct_str += '{} thread of {}'.format(cpu_threads, cpu_arch)
195
    elif cpu_cores > 1: # Multiple cores.
196
        cpu_pct_str += '{} threads - {} cores of {}'.format(cpu_threads, cpu_cores, cpu_arch)
197
    else:
198
        if psutil.cpu_count() > 1: # Multiple threads, single core.
199
            cpu_pct_str += '{} threads - {} core of {}'.format(cpu_threads, cpu_cores, cpu_arch)
200
        else: # Single thread, single core.
201
            cpu_pct_str += '{} thread - {} core of {}'.format(cpu_threads, cpu_cores, cpu_arch)
202
203
    # Build CPU usage graph.
204
    cpu_pct_str += '\n\n'
205
    for index, value in enumerate(cpu_pcts):
206
        cpu_pct_str += 'CPU {}: {}\n'.format(str(index), progressBar.makeBar(cpu_pcts[index]))
207
208
    # Return completed message.
209
    return message.Message(body='```{}```'.format(cpu_pct_str))
210
211
async def command_setprefix(message_in: message.Message):
212
    if settings.owners_check(message_in.author.id):
213
        prefix = message_in.body.split(' ', 1)[-1]
214
        settings.prefix_set(message_in.guild.id, prefix)
215
        return message.Message(body='Prefix set to {}'.format(prefix))
216
    else:
217
        return message.Message(body='Only my owner can set the prefix!')
218
219
async def command_getprefix(message_in: message.Message):
220
    return message.Message(body='Prefix is {}'.format(settings.prefix_get(message_in.guild.id)))
221
222
async def command_speedtest(message_in: message.Message):
223
    if settings.owners_check(message_in.author.id):
224
        speed = pyspeedtest.SpeedTest()
225
        msg = '**Speed Test Results:**\n'
226
        msg += '```\n'
227
        msg += '    Ping: {}\n'.format(round(speed.ping(), 2))
228
        msg += 'Download: {}MB/s\n'.format(round(speed.download()/1024/1024, 2))
229
        msg += '  Upload: {}MB/s```'.format(round(speed.upload()/1024/1024, 2))
230
        return message.Message(body=msg)
231
    else:
232
        return message.Message(body='You do not have permisison to run a speedtest.')
233
234
async def command_addowner(message_in: message.Message):
235
    if settings.owners_get():
236
        try:
237
            if settings.owners_check(message_in.author.id):
238
                member = message_in.body.strip()
239
                new_member = displayname.memberForName(member, message_in.guild.members, message_in.guild.me)
240
241
                if settings.owners_check(new_member.id):
242
                    return message.Message(body="User is already an owner.")
243
                elif new_member.bot:
244
                    return message.Message(body="Bots cannot be owners.")
245
                else:
246
                    settings.owners_add(new_member.id)
247
                    return message.Message(body="Added owner successfully.")
248
            else:
249
                return message.Message(body="You aren't an owner of the bot.")
250
        except AttributeError:
251
            return message.Message(body="Invalid user.")
252
    else:
253
        settings.owners_add(message_in.author.id)
254
        return message.Message(body="You have successfully claimed yourself as the first owner!")
255
256
async def command_owners(message_in: message.Message):
257
    owners = []
258
    if not settings.owners_get():
259
        return message.Message(body='I have no owners')
260
    for owner in settings.owners_get():
261
        user = displayname.memberForID(owner, message_in.guild.members, message_in.guild.me)
262
        if user:
263
            owners.append(str(user.name))
264
        else:
265
            owners.append(str(owner))
266
    owner_list = ', '.join(owners)
267
    return message.Message(body=owner_list)