def kh_putenv(self, arg0, tokens, ref): ''' process an instance of putenv :param tokens: token list :param ref: instance of :class:`FileRef` :raise UnhandledTokenPattern: unhandled token pattern ''' argument_list = [] for tkn in tokens[1:]: if tkn['tokName'] == 'STRING': argument_list.append( tkn['tokStr'] ) if len(argument_list) == 1: var, arg = utils.strip_quotes( argument_list[0].strip() ).split('=') arg = utils.strip_quotes(arg.strip()) self.env.set(var, arg, self, ref) elif len(argument_list) == 2: var, arg = argument_list arg = utils.strip_quotes(arg.strip()) self.env.set(var, arg) else: msg = str(ref) + reconstruct_line(tokens).strip() raise UnhandledTokenPattern, msg self.kh_shell_command(arg0, tokens, ref)
def tokens_to_list(self): ''' parse an enclosed list of tokens into a list Assume ``token_pointer`` is pointing at start terminator examples:: (DESC, "motor $(P)$(M)") --> ['DESC', 'motor $(P)$(M)'] {P, S, BL, T1, T2, A} --> ['P', 'S', 'BL', 'T1', 'T2', 'A'] {12ida1: A "##ID" 1 2 1} --> ['12ida1:', 'A', '##ID', '1', '2', '1'] TODO: alias($(IOC):IOC_CPU_LOAD,"$(IOC):load") ''' # first, decide the list terminators tok = self.getCurrentToken() t_start = token_key(tok) if t_start not in ('OP (', 'OP {'): msg = 'incorrect token type' raise ValueError, msg t_end = {'OP (': 'OP )', 'OP {': 'OP }'}[t_start] #content_names = ('NAME', 'NUMBER', 'OP', 'STRING', 'ERRORTOKEN') skip_list = ('COMMENT', 'NEWLINE', 'ENDMARKER', #'ERRORTOKEN', 'INDENT', 'DEDENT') v = '' end = tok['start'][1] items = [] depth = 1 while depth>0 or token_key(tok) not in ('', t_end): tok = self.nextActionable(skip_list) key = token_key(tok) if key == t_start: depth += 1 elif key == t_end: depth -= 1 if depth == 0: break if tok['start'][1] == end and key != 'OP ,': v += tok['tokStr'] end = tok['end'][1] else: if len(v) > 0: v = utils.strip_quotes(v) if len(v) == 0: v = '""' items.append(v) if key not in (t_end, 'OP ,'): v = tok['tokStr'] else: v='' end = tok['end'][1] if len(v) > 0: # last chance v = utils.strip_quotes(v) if len(v) == 0: v = '""' items.append(v) return items
def action_form(parser, token): arguments = token.split_contents() if len(arguments) > 4: raise template.TemplateSyntaxError, "%(tag_name)s tag takes 3 arguments at most {%% %(tag_name)s \ [complete_title] [commit_title] [undo_title] %%}" % {"tag_name": token.contents.split()[0]} params = [] if len(arguments) > 1: params.append(strip_quotes(arguments[1])) if len(arguments) > 2: params.append(strip_quotes(arguments[2])) if len(arguments) > 3: params.append(strip_quotes(arguments[3])) return ActionFormNode(*params)
def kh_epicsEnvSet(self, arg0, tokens, ref): '''symbol assignment''' if len(tokens) == 7: var = tokens[2]['tokStr'] value = tokens[4]['tokStr'] else: text = utils.strip_parentheses(reconstruct_line(tokens).strip()) parts = text.split(',') if len(parts) == 1: parts = text.split(' ') if len(parts) != 2: raise UnhandledTokenPattern('epicsEnvSet'+text) var, value = parts self.env.set(utils.strip_quotes( var ), utils.strip_quotes( value ), self, ref) self.kh_shell_command(arg0, tokens, ref)
def action_form(parser, token): arguments = token.split_contents() if len(arguments) > 4: raise template.TemplateSyntaxError, "%(tag_name)s tag takes 3 arguments at most {%% %(tag_name)s \ [complete_title] [commit_title] [undo_title] %%}" % { "tag_name": token.contents.split()[0] } params = [] if len(arguments) > 1: params.append(strip_quotes(arguments[1])) if len(arguments) > 2: params.append(strip_quotes(arguments[2])) if len(arguments) > 3: params.append(strip_quotes(arguments[3])) return ActionFormNode(*params)
def kh_dbLoadRecords(self, arg0, tokens, ref): local_macros = macros.Macros(**self.env.db) full_line = reconstruct_line(tokens).strip() tokenLog = TokenLog() tokenLog.tokenList = tokens tokenLog.token_pointer = 1 args = parse_bracketed_macro_definitions(tokenLog) nargs = len(args) if nargs not in (1, 2, 3,): msg = str(ref) + full_line raise UnhandledTokenPattern, msg utils.logMessage(arg0 + full_line, utils.LOGGING_DETAIL__NOISY) dbFileName = local_macros.replace(utils.strip_quotes(args[0])) if nargs in (2, 3,): # accumulate additional macro definitions local_macros = self.parse_macro_args(args[1], ref, tokens, local_macros) if nargs in (3,): path = args[2] # msg = str(ref) + full_line if self.symbols.exists(path): # substitute from symbol table path = self.symbols.get(path).value if os.path.exists(path): dbFileName = os.path.join(path, dbFileName) try: obj = database.Database(self, dbFileName, ref, **local_macros.db) self.database_list.append(obj) self.kh_shell_command(arg0, tokens, ref) except text_file.FileNotFound, _exc: msg = 'Could not find database file: ' + dbFileName utils.detailedExceptionLog(msg) return
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] settings = ctx['settings'] author = ctx['message'].author new_prefix = utils.strip_quotes(params_str) if not new_prefix: return False, ("You need to define a new prefix, e.g. `{}prefix avc-` to make " "`avc-` the new prefix.".format(ctx['print_prefix'])) disallowed_characters = ['\n', '\t', '`'] for c in disallowed_characters: if c in new_prefix: return False, "Your prefix can't contain **new lines**, **tab characters**, or **\`**." response = ("Done! My prefix in your server is now `{0}`. Try running `{0}ping` to test it out.\n" "Remember, you can always mention me instead of using my prefix (e.g: **{1} ping**)" ".".format(new_prefix, ctx['message'].guild.me.mention)) if len(new_prefix) == 1: response += ("\n\n:information_source: Note: If you use the **same prefix as another bot**, " "you should also run `{}dcnf` to prevent error messages when using that bot's commands." "".format(new_prefix)) cfg.PREFIXES[guild.id] = new_prefix settings['prefix'] = new_prefix utils.set_serv_settings(guild, settings) await func.server_log( guild, "💬 {} (`{}`) set the server's prefix to `{}`".format( func.user_hash(author), author.id, new_prefix ), 1, settings) return True, response
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] settings = ctx['settings'] author = ctx['message'].author new_word = params_str.replace('\n', ' ') # Can't have newlines in channel name. new_word = utils.strip_quotes(new_word) previous_word = ("text" if 'text_channel_name' not in settings else func.esc_md(settings['text_channel_name'])) if not new_word: return False, ( "You need to define a new name, e.g. `{}textchannelname links` to make " "**links** shown instead of **{}**.".format( ctx['print_prefix'], previous_word)) settings['text_channel_name'] = new_word utils.set_serv_settings(guild, settings) e_new_word = func.esc_md(new_word) await func.server_log( guild, "💬 {} (`{}`) définissez le nom \"text\" du serveur sur **{}**". format(func.user_hash(author), author.id, e_new_word), 2, settings) for p, pv in settings['auto_channels'].items(): for s, sv in pv['secondaries'].items(): if 'tc' in sv: tc = guild.get_channel(sv['tc']) try: await tc.edit(name=utils.nice_cname(new_word)) except discord.errors.Forbidden: pass return True, ( "Done! From now on I'll use **{}** instead of **{}**.".format( e_new_word, previous_word))
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] settings = ctx['settings'] author = ctx['message'].author nick = utils.strip_quotes(params_str) if nick.lower() == 'reset': try: del settings['custom_nicks'][str(author.id)] utils.set_serv_settings(guild, settings) except KeyError: return False, "You haven't set a custom nickname." return True, "Your custom nickname has been removed." if 'custom_nicks' not in settings: settings['custom_nicks'] = {} settings['custom_nicks'][str(author.id)] = nick utils.set_serv_settings(guild, settings) await func.server_log( guild, "🙋 {} (`{}`) set their custom nick to {}".format( func.user_hash(author), author.id, nick), 2, settings) return True, ( "Done! Channels that show the creator's name will now call you **{}** instead of **{}**." .format(nick, author.display_name))
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] settings = ctx['settings'] limit = utils.strip_quotes(params_str) author = ctx['message'].author vc = ctx['voice_channel'] if limit: try: limit = abs(int(limit)) except ValueError: return False, "`{}` is not a number.".format(limit) else: limit = len(vc.members) if limit > 99: return False, "The user limit cannot be higher than 99." await vc.edit(user_limit=limit) if limit != 0: log_msg = "👪 {} (`{}`) set the user limit of \"**{}**\" (`{}`) to {}".format( func.user_hash(author), author.id, func.esc_md(vc.name), vc.id, limit) else: log_msg = "👨👩👧👦 {} (`{}`) removed the user limit of \"**{}**\" (`{}`)".format( func.user_hash(author), author.id, func.esc_md(vc.name), vc.id) await func.server_log(guild, log_msg, 2, settings) return True, None
def dated_static(parser, token): bits = token.contents.split() if len(bits) <> 2: raise template.TemplateSyntaxError( "Wrong number of arguments passed. All we need is the path") return DatedStaticNode(strip_quotes(bits[1]))
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] username = utils.strip_quotes(params_str) if username: # Show roles of particular user if param is provided found_user = False for m in guild.members: if m.name == username or m.mention == username: roles = m.roles found_user = True break if not found_user: return False, "There is no user named \"{}\"".format(username) else: # If no param is provided, show all roles in server roles = guild.roles l = ["```{:^16}".format("ID") + " Creation Date Name```"] roles = sorted(roles, key=lambda x: x.created_at) for r in roles: if r.name != "@everyone": l.append("`{0}` `{1}` {2}".format( str(r.id), r.created_at.strftime("%Y/%m/%d"), r.name)) for c in utils.chunks(l, 10): await echo('\n'.join(c), ctx['channel'], ctx['message'].author) return True, "NO RESPONSE"
def kh_symbol(self, arg0, tokens, ref): '''symbol assignment''' # TODO: handle this: sym=func(key,value) # iocSubString=asdCreateSubstitutionString("IOC",iocprefix) arg = utils.strip_quotes( tokens[2]['tokStr'] ) self.symbols.set(arg0, arg, self, ref) self.kh_shell_command(arg0, tokens, ref)
def parse_prod(query): """ Returns a list of commprods if any are found in the query, otherise returns None. Run query through strip_old() before passing in. """ btb_regex = '((^)|(\s))((a btb)|(abtb)|(btb))' comm_regex = '(comm)(()|( )|(\.)|(\. )|( \.)|(\,)|(\, )|( \,))' prod_regex = '((prod)|(prodd))((\s)|(\.\s)|(\.\.\s))' commprod_regex = """((%(comm)s%(prod)s)|(%(comm)s\s%(prod)s))""" % { 'comm': comm_regex, 'prod': prod_regex, } regex = '%(btb)s(?P<comm_prod>.+?)%(commprod)s+' % { 'btb': btb_regex, 'commprod': commprod_regex, } pattern = re.compile(regex, re.I | re.DOTALL) if pattern.search(query): prods = [] for m in pattern.finditer(query): m = utils.strip_quotes(m.group('comm_prod')) prods.append(m) return prods return None
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] settings = ctx['settings'] author = ctx['message'].author new_word = params_str.replace('\n', ' ') # Can't have newlines in channel name. new_word = utils.strip_quotes(new_word) previous_word = "General" if 'general' not in settings else func.esc_md( settings['general']) if not new_word: return False, ( "You need to define a new word, e.g. `{}general Lounge` to make " "**Lounge** shown instead of **{}**.".format( ctx['print_prefix'], previous_word)) settings['general'] = new_word utils.set_serv_settings(guild, settings) e_new_word = func.esc_md(new_word) await func.server_log( guild, "🎮 {} (`{}`) set the server's \"General\" word to **{}**".format( func.user_hash(author), author.id, e_new_word), 2, settings) return True, ( "Done! From now on I'll use **{}** instead of **{}**.".format( e_new_word, previous_word))
def signal_received_email(sender, sma, app_id, html, text, from_field, **kwargs): from utils import reply_to_thread, strip_quotes # circular dependency fix logger.debug("Sendgrid signal receive: %s, %s, %s, %s, %s, %s"%(sender, sma, app_id, html, text, from_field) ) if app_id == sendgrid_settings.THREADED_MESSAGES_ID: body ='' if text: body = text if not body: body = strip_tags(html) if body: strip_quotes(body) thread = sma.content_object reply_to_thread(thread, sma.user, body)
def invoke(self, message, warnings): payload = message.get_payload() if isinstance(payload, basestring): if message.get('Content-Disposition', 'inline') == 'inline' and message.get_content_maintype() == 'text': message.set_payload(strip_quotes(payload)) else: for _message in payload: self.invoke(_message, warnings) return message
def signal_received_email(sender, sma, app_id, html, text, from_field, **kwargs): from utils import reply_to_thread, strip_quotes # circular dependency fix logger.debug("Sendgrid signal receive: %s, %s, %s, %s, %s, %s" % (sender, sma, app_id, html, text, from_field)) if app_id == sendgrid_settings.THREADED_MESSAGES_ID: body = '' if text: body = text if not body: body = strip_tags(html) if body: strip_quotes(body) thread = sma.content_object reply_to_thread(thread, sma.user, body)
def invoke(self, message, warnings): payload = message.get_payload() if isinstance(payload, basestring): if message.get( 'Content-Disposition', 'inline' ) == 'inline' and message.get_content_maintype() == 'text': message.set_payload(strip_quotes(payload)) else: for _message in payload: self.invoke(_message, warnings) return message
def kh_cd(self, arg0, tokens, ref): path = reconstruct_line(tokens).strip() path = utils.strip_quotes(path) # strip double-quotes if self.symbols.exists(path): # symbol substitution path = self.symbols.get(path).value path = self.env.replace(path) # macro substitution if len(path) == 0: path = self.startup_directory if len(path) > 0 and os.path.exists(path): if os.path.abspath(path) != os.getcwd(): # only cd if it is really different os.chdir(path) self.kh_shell_command(arg0, tokens, ref) utils.logMessage(arg0 + ' ' + path, utils.LOGGING_DETAIL__MEDIUM)
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] settings = ctx['settings'] gsplit = params_str.split('>>') if len(gsplit) != 2 or not gsplit[0] or not gsplit[-1]: return False, ( "Incorrect syntax for alias command. Should be: `{}alias [Actual game name] >> " "[New name]` (without square brackets).".format( ctx['print_prefix'])) else: gname = utils.strip_quotes(gsplit[0]) aname = utils.strip_quotes(gsplit[1]) if gname in settings['aliases']: oaname = settings['aliases'][gname] response = "'{}' already has an alias ('{}'), it will be replaced with '{}'.".format( gname, oaname, aname) else: response = "'{}' will now be shown as '{}'.".format(gname, aname) settings['aliases'][gname] = aname utils.set_serv_settings(guild, settings) return True, response
def kh_dbLoadTemplate(self, arg0, tokens, ref): # TODO: Can one template call another? local_macros = macros.Macros(**self.env.db) args = utils.strip_parentheses(reconstruct_line(tokens).strip()).split(',') if len(args) in (1, 2): tfile = os.path.join(os.getcwd(), utils.strip_quotes(args[0])) if len(args) == 2: # such as in 8idi: dbLoadTemplate("aiRegister.substitutions", top) # This is an ERROR. The IOC should be corrected. '''from the EPICS documentation regarding dbLoadTemplate(): dbLoadTemplate(char *subfile, char *substitutions) This IOC command reads a template substitutions file which provides instructions for loading database instance files and gives values for the $(xxx) macros they may contain. This command performs those substitutions while loading the database instances requested. The subfile parameter gives the name of the template substitution file to be used. The optional substitutions parameter may contain additional global macro values, which can be overridden by values given within the substitution file. ''' path = self.symbols.get(utils.strip_quotes(args[1]).strip(), None) if isinstance(path, macros.KVpair): alternative = os.path.join(path.value, tfile) if os.path.exists(alternative): tfile = alternative else: msg = 'problem parsing: ' + arg0 + reconstruct_line(tokens).strip() utils.logMessage(msg, utils.LOGGING_DETAIL__IMPORTANT) obj = template.Template(tfile, ref, **local_macros.db) self.template_list.append(obj) self.database_list += obj.database_list self.kh_shell_command(arg0, tokens, ref) for k, v in obj.getPVs(): self.pv_dict[k] = v
def parse_macro_args(self, arg, ref, tokens, parent_macros): local_macros = macros.Macros(**parent_macros.db) for definition in utils.strip_quotes(arg).split(','): if definition.find('=') < 0: # if self.symbols.get(definition, None) # such as: iocSubString=asdCreateSubstitutionString("IOC",iocprefix) msg = str(ref) + reconstruct_line(tokens).strip() utils.logMessage(msg, utils.LOGGING_DETAIL__IMPORTANT) #raise UnhandledTokenPattern, msg else: k, v = [_.strip() for _ in definition.split('=')] # expand macros now to avoid possible infinite loop while replacing # example: PORT=IP_$(PORT) v = local_macros.replace(v) local_macros.set(k, v, self, ref) return local_macros
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] settings = ctx['settings'] author = ctx['message'].author bitrate = utils.strip_quotes(params_str) v = author.voice in_vc = v is not None and v.channel.id in func.get_secondaries( guild, settings) if bitrate.lower() == 'reset': try: del settings['custom_bitrates'][str(author.id)] utils.set_serv_settings(guild, settings) except KeyError: return False, "You haven't set a custom bitrate." if in_vc: await func.update_bitrate(v.channel, settings, reset=True) return True, "Your custom bitrate has been reset, the channel default will be used for you from now on." try: bitrate = float(bitrate) except ValueError: return False, "`{}` is not a number.".format(bitrate) if bitrate < 8: return False, "The bitrate must be higher than 8." if bitrate * 1000 > guild.bitrate_limit: return False, "{} is higher than the maximum bitrate in this server ({}).".format( bitrate, guild.bitrate_limit / 1000) if 'custom_bitrates' not in settings: settings['custom_bitrates'] = {} settings['custom_bitrates'][str(author.id)] = bitrate utils.set_serv_settings(guild, settings) if in_vc: await func.update_bitrate(v.channel, settings) await func.server_log( guild, "🎚 {} (`{}`) set their custom bitrate to {}kbps".format( func.user_hash(author), author.id, bitrate), 2, settings) return True, ( "Done! From now on, channels you join will have their bitrate set to {}kbps.\n" "If multiple users in the channel have set custom bitrates, the average will be used.\n\n" "Use `{}channelinfo` to check the current bitrate of your channel.". format(bitrate, ctx['print_prefix']))
def test_strip_quotes(self): body = """nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan 2011/10/28 Nyan Cat <*****@*****.**>: > hey guys > sarete il 31 dicembre con Pascal a Firenze? > lo spero tanto, nel caso ditemi qualcosa... > >>> > >> >""" body_stripped = """nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan nyan """ self.assertEquals(body_stripped.strip(), strip_quotes(body).strip())
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] settings = ctx['settings'] param = utils.strip_quotes(params_str) if param.lower() == 'none': try: del settings['stct'] utils.set_serv_settings(guild, settings) return ( True, "From now on, new text channels will only be visible to the channel's occupants. " "Existing channels will not be affected.") except KeyError: return False, "Text channels are already invisible to everyone but the channel's occupants." role = None try: param = int(param) role = guild.get_role(param) except ValueError: if param == "@everyone": role = guild.default_role else: for r in guild.roles: if r.mention == param: role = r break if role is None: return False, "I can't find that role. You need to specify either the role ID, or `@mention` it." settings['stct'] = role.id utils.set_serv_settings(guild, settings) return ( True, "From now on, new text channels can be seen by users with the \"{}\" role. " "Existing channels will not be affected.".format( discord.utils.escape_mentions(role.name)))
async def execute(ctx, params): params_str = ' '.join(params) guild = ctx['guild'] limit = utils.strip_quotes(params_str) try: limit = int(limit) except ValueError: if limit: return False, "`{}` is not a number.".format(limit) else: return False, ("You need to specify a number to set the limit to. " "E.g. '{}defaultlimit 4'".format( ctx['print_prefix'])) await func.set_default_limit(guild, ctx['voice_channel'], limit) if int(limit) != 0: return True, ( "Done! From now on, voice channels like the one you're in now will be limited to " "{0} users. You can reset this by running `{1}defaultlimit 0`.\n" "If you want to set the limit of *only* your channel, " "use `{1}limit` instead.".format(limit, ctx['print_prefix'])) else: return True, ( "Done! From now on, voice channels like the one you're in now will have no user limit." )
async def admin_command(cmd, ctx): client = ctx['client'] message = ctx['message'] channel = message.channel params = ctx['params'] params_str = ctx['params_str'] guilds = ctx['guilds'] LAST_COMMIT = ctx['LAST_COMMIT'] if cmd == 'log': logfile = "log{}.txt".format("" if cfg.SAPPHIRE_ID is None else cfg.SAPPHIRE_ID) if not os.path.exists(logfile): await channel.send("No log file") return with open(logfile, 'r', encoding="utf8") as f: data = f.read() data = data[-10000:] # Drop everything but the last 10k characters to make string ops quicker data = data.replace(' Creating channel for ', ' ✅') data = data.replace(' Deleting ', ' ❌') data = data.replace(' Renaming ⌛ to ', ' ⏩ ') data = data.replace(' Renaming ', ' 🔄') data = data.replace(' to ', ' ⏩ ') data = data.replace(' CMD Y: ', ' C✔ ') data = data.replace(' CMD F: ', ' C✖ ') data = data.replace(" creating channels too quickly", " creating channels too quickly❗❗") data = data.replace(" where I don't have permissions", " where I don't have permissions❗❗") data = data.replace("Traceback (most recent", "❗❗Traceback (most recent") data = data.replace("discord.errors.", "❗❗discord.errors.") data = data.replace("Remembering channel ", "❗❗Remembering ") data = data.replace("New tickrate is ", "🕐") data = data.replace(", seed interval is ", " 🕐") data = data.replace(' ', ' ') # Reduce indent to save character space today = datetime.now(pytz.timezone(cfg.CONFIG['log_timezone'])).strftime("%Y-%m-%d") data = data.replace(today, 'T') character_limit = 2000 - 17 # 17 for length of ```autohotkey\n at start and ``` at end. data = data[character_limit * -1:] data = data.split('\n', 1)[1] lines = data.split('\n') for i, l in enumerate(lines): # Fake colon (U+02D0) to prevent highlighting the line if " ⏩" in l: lines[i] = l.replace(':', 'ː') elif l.startswith('T '): if '[' in l: s = l.split('[', 1) lines[i] = s[0] + '[' + s[1].replace(':', 'ː') data = '\n'.join(lines) data = '```autohotkey\n' + data data = data + '```' await channel.send(data) if cmd == 'stats': r = await channel.send(". . .") t1 = message.created_at t2 = r.created_at response_time = (t2 - t1).total_seconds() num_users = 0 for g in guilds: num_users += len([m for m in g.members if not m.bot]) lines_of_code = 0 for f in os.listdir(cfg.SCRIPT_DIR): if f.lower().endswith('.py'): lines_of_code += utils.count_lines(os.path.join(cfg.SCRIPT_DIR, f)) elif f == "commands": for sf in os.listdir(os.path.join(cfg.SCRIPT_DIR, f)): if sf.lower().endswith('.py'): lines_of_code += utils.count_lines(os.path.join(cfg.SCRIPT_DIR, f, sf)) cpu = psutil.cpu_percent() mem = psutil.virtual_memory() disk = psutil.disk_usage('/') await r.edit(content=( "Servers: **{tot_servs}** (A:{active_servs} S:{shards}) \t " "Users: **{users}** \t Channels: **{channels}** \n" "Response time: **{rt}** \t Tick rate: **{tr}** \t Tick time: **{tt}** | **{gtt}**\n" "CPU: **{cpu}%** \t MEM: **{memg} ({memp}%)** \t DISK: **{diskg} ({diskp}%)**\n" "**Last commit:** {commit}\n" "**Lines of code:** {lines}\n" "**Timings:** \n{timings}".format( tot_servs=len(guilds), active_servs=utils.num_active_guilds(guilds), shards=utils.num_shards(guilds), users=num_users, channels=utils.num_active_channels(guilds), rt="{0:.2f}s".format(response_time), tr="{0:.1f}s".format(cfg.TICK_RATE), tt="{0:.2f}s".format(cfg.TICK_TIME), gtt="{0:.2f}s".format(cfg.G_TICK_TIME), cpu=cpu, memg="{0:.1f}GB".format(mem.used / 1024 / 1024 / 1024), memp=round(mem.percent), diskg="{0:.1f}GB".format(disk.used / 1024 / 1024 / 1024), diskp=round(disk.percent), commit=LAST_COMMIT, lines=lines_of_code, timings=utils.format_timings() ) )) if cmd == 'ping': r = await channel.send(". . .") t1 = message.created_at t2 = r.created_at response_time = (t2 - t1).total_seconds() e = '🔴🔴🔴' if response_time > 5 else ('🟠🟠' if response_time > 1 else '🟢') await r.edit(content="**{0} {1:.1f}s**".format(e, response_time)) if cmd == 'top': top_guilds = [] for g in guilds: s = func.get_secondaries(g) top_guilds.append({"name": g.name, "size": len([m for m in g.members if not m.bot]), "num": len(s) if s is not None else 0}) top_guilds = sorted(top_guilds, key=lambda x: x['num'], reverse=True)[:10] r = "**Top Guilds:**" for g in top_guilds: r += "\n`{}` {}: \t**{}**".format( g['size'], func.esc_md(g['name']), g['num'] ) r += "\n\n**{}**".format(utils.num_active_channels(guilds)) await channel.send(r) if cmd == 'patrons': if patreon_info is None: await channel.send(content='❌') return patrons = patreon_info.fetch_patrons(force_update=True) if not patrons: await channel.send(content='❌') return fields = {} auths = patreon_info.update_patron_servers(patrons) for p, pv in patrons.items(): pu = client.get_user(p) if pu is not None: pn = pu.name else: pn = "Unknown" gn = "" if str(p) in auths: for s in auths[str(p)]['servers']: gn += "`{}` ".format(s) if 'extra_gold' in auths[str(p)]: for s in auths[str(p)]['extra_gold']: gn += "+g`{}` ".format(s) fields["`{}` **{}** {}".format(p, pn, cfg.TIER_ICONS[pv])] = gn try: for field_chunk in utils.dict_chunks(fields, 25): e = discord.Embed(color=discord.Color.from_rgb(205, 220, 57)) e.title = "{} Patrons".format(len(field_chunk)) for f, fv in field_chunk.items(): fv = fv if fv else "None" e.add_field(name=f, value=fv) await channel.send(embed=e) except: await channel.send(traceback.format_exc()) await func.react(message, '❌') if cmd == 'sapphiredebug': if cfg.SAPPHIRE_ID is None: await channel.send(content='❌ Not a sapphire') return if patreon_info is None: await channel.send(content='❌ No patreon_info') return auths = utils.read_json(os.path.join(cfg.SCRIPT_DIR, "patron_auths.json")) initiator_id = cfg.CONFIG["sapphires"][str(cfg.SAPPHIRE_ID)]['initiator'] msg = ("Sapphire ID: {}\n" "User: `{}`\n" "Actual guilds: {}\n" "Config guilds: {}\n" "Authenticated guilds: {}\n" "get_guilds: {}".format( cfg.SAPPHIRE_ID, initiator_id, ", ".join(['`' + str(g.id) + '`' for g in client.guilds]), ", ".join(['`' + str(g) + '`' for g in cfg.CONFIG["sapphires"][str(cfg.SAPPHIRE_ID)]['servers']]), ", ".join(['`' + str(g) + '`' for g in auths[str(initiator_id)]['servers']]), ", ".join(['`' + str(g.id) + '`' for g in func.get_guilds(client)])) ) await channel.send(msg) if cmd == 'status': g = utils.strip_quotes(params_str) if not g: await func.react(message, '❌') return try: await client.change_presence( activity=discord.Activity(name=g, type=discord.ActivityType.watching) ) await func.react(message, '✅') except: await channel.send(traceback.format_exc()) await func.react(message, '❌') if cmd == 'settings': gid = utils.strip_quotes(params_str) try: int(gid) except ValueError: for x in guilds: if x.name == gid: gid = str(x.id) break fname = gid + '.json' fp = os.path.join(cfg.SCRIPT_DIR, "guilds", fname) if os.path.exists(fp): gid = int(gid) g = client.get_guild(gid) head = "**{}** `{}`{}".format(g.name, gid, ("✅" if g in func.get_guilds(client) else "❌")) head += "💎" if func.is_sapphire(gid) else ("💳" if func.is_gold(gid) else "") s = head s += "\n```json\n" with open(fp, 'r') as f: file_content = f.read() s += file_content s += '```' try: await channel.send(s) except discord.errors.HTTPException: # Usually because message is over character limit haste_url = await utils.hastebin(file_content) await channel.send("{}\n{}".format(head, haste_url)) else: await func.react(message, '❌') if cmd == 'refetch': gid = utils.strip_quotes(params_str) try: gid = int(gid) except ValueError: await func.react(message, '❌') return g = client.get_guild(gid) if g is None: await func.react(message, '❓') return utils.get_serv_settings(g, force_refetch=True) await func.react(message, '✅') return if cmd == 'disable': try: g = client.get_guild(int(utils.strip_quotes(params_str))) settings = utils.get_serv_settings(g) settings['enabled'] = False utils.set_serv_settings(g, settings) log("Force Disabling", g) await func.react(message, '✅') except: await channel.send(traceback.format_exc()) await func.react(message, '❌') if cmd == 'enable': try: g = client.get_guild(int(utils.strip_quotes(params_str))) settings = utils.get_serv_settings(g) settings['enabled'] = True utils.set_serv_settings(g, settings) log("Force Enabling", g) await func.react(message, '✅') except: await channel.send(traceback.format_exc()) await func.react(message, '❌') if cmd == 'info': cid = utils.strip_quotes(params_str) try: c = client.get_channel(int(cid)) members = [m.display_name + " \t {}".format(utils.debug_unicode(m.display_name)) for m in c.members] games = [] for m in c.members: if m.activity: games.append(m.activity.name + " \t {}".format(utils.debug_unicode(m.activity.name))) s = "**__Server:__** {} `{}`\n**__Name:__** {}\n{}\n\n".format( c.guild.name, c.guild.id, c.name, utils.debug_unicode(c.name) ) if c.id in cfg.ATTEMPTED_CHANNEL_NAMES: s += "**__Attempted Name:__** {}\n{}\n\n".format( cfg.ATTEMPTED_CHANNEL_NAMES[c.id], utils.debug_unicode(cfg.ATTEMPTED_CHANNEL_NAMES[c.id]) ) s += "**__{} Members:__**\n".format(len(members)) s += '\n'.join(members) s += '\n\n**__{} Games:__**\n'.format(len(games)) s += '\n'.join(games) s = s.replace('\n\n\n', '\n\n') await channel.send(s) except: await channel.send(traceback.format_exc()) await func.react(message, '❌') if cmd == 'whois': uid = utils.strip_quotes(params_str) try: u = client.get_user(int(uid)) in_guilds = {} for g in client.guilds: if u in g.members: m = g.get_member(int(uid)) in_guilds[g.id] = { "guild_name": func.esc_md(g.name), "guild_size": g.member_count, "patron": "💎" if func.is_sapphire(g) else ("💳" if func.is_gold(g) else ""), "user_name": func.esc_md(m.display_name), "role": m.top_role.name, } if in_guilds: s = "**{}**".format(func.user_hash(u)) s += " \t :b: :regional_indicator_o: :regional_indicator_t:" if u.bot else "" can_dm = True try: await u.create_dm() can_dm = client.user.permissions_in(u.dm_channel).send_messages except discord.errors.Forbidden: can_dm = False s += " \t Can DM: {}".format('✅' if can_dm else '❌') for gid, g in in_guilds.items(): s += "\n{}`{}` **{}** (`{}`) \t {} ({})".format( g['patron'], gid, g['guild_name'], g['guild_size'], g['user_name'], g['role'] ) await echo(s, channel) else: await channel.send("¯\\_(ツ)_/¯") except: await channel.send(traceback.format_exc()) await func.react(message, '❌') if cmd == 'votekicks': try: readable = {} for k, kv in cfg.VOTEKICKS.items(): readable[k] = { "initiator": kv['initiator'].display_name, "participants": [m.display_name for m in kv['participants']], "required_votes": kv['required_votes'], "offender": kv['offender'].display_name, "reason": kv['reason'], "in_favor": [m.display_name for m in kv['in_favor']], "voice_channel": kv['voice_channel'].id, "message": kv['message'].id, "end_time": datetime.fromtimestamp(kv['end_time']).strftime("%Y-%m-%d %H:%M") } s = "```json\n" + json.dumps(readable, indent=1, sort_keys=True) + "```" print(s) try: await channel.send(s) except discord.errors.HTTPException: # Usually because message is over character limit haste_url = await utils.hastebin(s) await channel.send(haste_url) except: await channel.send(traceback.format_exc()) await func.react(message, '❌') if cmd == 'exit': attempts = 0 while attempts < 100: attempts += 1 if not cfg.WRITES_IN_PROGRESS: print("Exiting!") await client.close() sys.exit() break else: print("Failed to close", cfg.WRITES_IN_PROGRESS) await func.react(message, '❌') if cmd == 'loop': mode = params[0] loop_name = params[1] try: loop = ctx['loops'][loop_name] modes = { # Dict of possible loop functions/attrs as [fn, arg] 'current_loop': [loop.current_loop, None], 'next_iteration': [loop.next_iteration, None], 'next_run': [loop.next_iteration, None], # Alias 'start': [loop.start, client], 'stop': [loop.stop, None], 'cancel': [loop.cancel, None], 'restart': [loop.restart, client], 'is_being_cancelled': [loop.is_being_cancelled, None], 'last_run': [loop.last_run, None], } if mode not in modes: await func.react(message, '❓') return fn, arg = modes[mode] if callable(fn): if arg is None: r = fn() else: r = fn(arg) else: r = fn if r is not None: if isinstance(r, date): r = r.astimezone(pytz.timezone(cfg.CONFIG['log_timezone'])) await channel.send(r.strftime("%Y-%m-%d %H:%M:%S")) else: await channel.send(str(r)) await func.react(message, '✅') except: await channel.send(traceback.format_exc()) await channel.send("Loops: \n{}".format('\n'.join(ctx['loops'].keys()))) await func.react(message, '❌') if cmd == 'rename': try: cid = utils.strip_quotes(params[0]) c = client.get_channel(int(cid)) new_name = ' '.join(params[1:]) if not new_name: new_name = "⌛" await c.edit(name=new_name) except: await channel.send(traceback.format_exc()) await func.react(message, '❌') else: await func.react(message, '✅') log("{0} Force Renaming to {1}".format(cid[-4:], new_name), c.guild) if cmd == 'forget': try: cid = int(utils.strip_quotes(params[0])) c = client.get_channel(cid) settings = utils.get_serv_settings(c.guild) for p, pv in settings['auto_channels'].items(): tmp = settings['auto_channels'][p]['secondaries'].copy() for s, sv in pv['secondaries'].items(): if s == cid: del settings['auto_channels'][p]['secondaries'][s] break utils.set_serv_settings(c.guild, settings) except: await channel.send(traceback.format_exc()) await func.react(message, '❌') else: await func.react(message, '✅') if cmd == 'delete': try: cid = int(utils.strip_quotes(params[0])) c = client.get_channel(cid) await c.delete() except: await channel.send(traceback.format_exc()) await func.react(message, '❌') else: await func.react(message, '✅') if cmd == 'whisper': params_str = utils.strip_quotes(params_str) if '\n' not in params_str: await func.react(message, '❌') return uid, msg = params_str.split('\n', 1) try: u = await client.fetch_user(uid) except discord.errors.NotFound: await func.react(message, '❌') return if u.dm_channel is None: await u.create_dm() try: await u.dm_channel.send(msg) except: await channel.send(traceback.format_exc()) await func.react(message, '❌') else: await func.react(message, '✅') if cmd == 'cleanprimaries': try: n_primaries = 0 n_real_primaries = 0 for g in client.guilds: settings = utils.get_serv_settings(g) tmp = {} n_primaries += len(settings['auto_channels']) for p, pv in settings['auto_channels'].items(): c = g.get_channel(p) if c: tmp[p] = pv n_real_primaries += len(tmp) if len(settings['auto_channels']) != len(tmp): settings['auto_channels'] = tmp utils.set_serv_settings(g, settings) await channel.send("Cleaned {} of {} primaries".format(n_real_primaries, n_primaries)) except: await channel.send(traceback.format_exc()) await func.react(message, '❌') if cmd == 'leaveinactive': params_str = utils.strip_quotes(params_str) try: total_guilds = 0 inactive_guilds = 0 cfg.CONFIG['leave_inactive'] = [] for g in client.guilds: total_guilds += 1 if g and (not utils.guild_is_active(g) or g not in guilds): cfg.CONFIG['leave_inactive'].append(g.id) inactive_guilds += 1 if params_str == "go": try: await g.leave() except discord.errors.NotFound: pass if params_str == "go": await channel.send("Left {} of {} guilds.".format(inactive_guilds, total_guilds)) else: await channel.send("Will leave {} of {} guilds. " "Rerun command with 'go' at end to actually leave them.".format( inactive_guilds, total_guilds)) cfg.CONFIG['leave_inactive'] = [] except: await channel.send(traceback.format_exc()) await func.react(message, '❌')
def dated_static(parser, token): bits = token.contents.split() if len(bits) <> 2: raise template.TemplateSyntaxError("Wrong number of arguments passed. All we need is the path") return DatedStaticNode(strip_quotes(bits[1]))
async def on_message(message): if not client.is_ready(): return if message.author.bot: # Don't respond to self or bots return guilds = func.get_guilds(client) admin = ADMIN admin_channels = [] if admin is not None: admin_channels = [admin.dm_channel] if 'admin_channel' in cfg.CONFIG: admin_channels.append(ADMIN_CHANNEL) if message.channel in admin_channels: split = message.content.split(' ') cmd = split[0].split('\n')[0].lower() params_str = message.content[len(cmd):].strip() params = params_str.split(' ') if cmd == 'stop': m = utils.strip_quotes(params_str) success = await reload_modules(m) await func.react(message, '⌛' if success else '❌') await asyncio.sleep(3) await func.react(message, '🌑' if success else '❌') await asyncio.sleep(1) await func.react(message, '🌓' if success else '❌') await asyncio.sleep(1) await func.react(message, '🌔' if success else '❌') await asyncio.sleep(1) await func.react(message, '✅' if success else '❌') await message.channel.send("restarting..") await client.logout() else: ctx = { 'client': client, 'admin': admin, 'message': message, 'params': params, 'params_str': params_str, 'guilds': guilds, 'LAST_COMMIT': LAST_COMMIT, } await admin_commands.admin_command(cmd, ctx) return if not message.guild: # DM if 'help' in message.content and len( message.content) <= len("@Auto Voice Channels help"): await message.channel.send( "Sorry I don't respond to commands in DMs, " "you need to type the commands in a channel in your server.\n" "If you've tried that already, then make sure I have the right permissions " "to see and reply to your commands in that channel.") else: await admin_channels[-1].send( embed=discord.Embed(title="DM from **{}** [`{}`]:".format( message.author.name, message.author.id), description=message.content)) return if message.guild not in guilds: return prefix_m = message.guild.me.mention prefix_mx = "<@!" + prefix_m[2:] if message.guild.id in cfg.PREFIXES: prefix_p = cfg.PREFIXES[message.guild.id] else: prefix_p = 'vc/' prefix = None if message.content.startswith(prefix_m): prefix = prefix_m print_prefix = "@{} ".format(message.guild.me.display_name) elif message.content.startswith(prefix_mx): prefix = prefix_mx print_prefix = "@{} ".format(message.guild.me.display_name) elif message.content.lower().startswith(prefix_p.lower()): prefix = prefix_p print_prefix = prefix_p # Commands if prefix: msg = message.content[len(prefix):].strip() # Remove prefix split = msg.split(' ') cmd = split[0].lower() params = split[1:] params_str = ' '.join(params) clean_paramstr = ' '.join( message.clean_content[len(prefix):].strip().split(' ')[1:]) guild = message.guild channel = message.channel settings = utils.get_serv_settings(guild) if channel.id not in func.get_voice_context_channel_ids( guild, settings): settings['last_channel'] = channel.id utils.set_serv_settings(guild, settings) ctx = { 'client': client, 'guild': guild, 'prefix': prefix, 'print_prefix': print_prefix, 'prefix_p': prefix_p, 'command': cmd, 'gold': func.is_gold(guild), 'sapphire': func.is_sapphire(guild), 'settings': settings, 'message': message, 'channel': channel, 'clean_paramstr': clean_paramstr, } # Restricted commands perms = message.author.permissions_in(channel) perms_required = [ perms.manage_channels, perms.manage_roles, ] ctx['admin'] = all(perms_required) success, response = await commands.run(cmd, ctx, params) if success or response != "NO RESPONSE": log("CMD {}: {}".format("Y" if success else "F", msg), guild) if success: if response: if response != "NO RESPONSE": await echo(response, channel, message.author) else: await func.react(message, '✅') else: if response != "NO RESPONSE": await func.react(message, '❌') if response: await echo(response, channel, message.author)
async def on_message(message): if not client.is_ready(): return if message.author.bot: # Don't respond to self or bots return guilds = func.get_guilds(client) admin = ADMIN admin_channels = [] if admin is not None: admin_channels = [admin.dm_channel] if 'admin_channel' in cfg.CONFIG and ADMIN_CHANNEL is not None: admin_channels.append(ADMIN_CHANNEL) if message.channel in admin_channels: split = message.content.split(' ') cmd = split[0].split('\n')[0].lower() params_str = message.content[len(cmd):].strip() params = params_str.split(' ') if cmd == 'reload': m = utils.strip_quotes(params_str) success = await reload_modules(m) await func.react(message, '✅' if success else '❌') else: ctx = { 'client': client, 'admin': admin, 'message': message, 'params': params, 'params_str': params_str, 'guilds': guilds, 'LAST_COMMIT': LAST_COMMIT, } await admin_commands.admin_command(cmd, ctx) return if not message.guild: # DM if 'help' in message.content and len( message.content) <= len("@Auto Voice Channels help"): await message.channel.send( "Sorry I don't respond to commands in DMs, " "you need to type the commands in a channel in your server.\n" "If you've tried that already, then make sure I have the right permissions " "to see and reply to your commands in that channel.") elif message.content.lower().startswith("power-overwhelming"): channel = message.channel params_str = message.content[len("power-overwhelming"):].strip() if not params_str: await channel.send( "You need to specify a guild ID. " "Try typing `who am I` to get a list of guilds we're both in" ) return auth_guilds = params_str.replace(' ', '\n').split('\n') for auth_guild in auth_guilds: try: g = client.get_guild(int(auth_guild)) if g is None: await channel.send( "`{}` is not a guild I know about, " "maybe you need to invite me there first?".format( auth_guild)) return except ValueError: await channel.send( "`{}` is not a valid guild ID, try typing " "`who am I` to get a list of guilds we're both in.". format(auth_guild)) return except Exception as e: error_text = "Auth Error `{}`\nUser `{}`\nCMD `{}`".format( type(e).__name__, message.author.id, message.content) await func.admin_log(error_text, ctx['client']) log(error_text) error_text = traceback.format_exc() await func.admin_log(error_text, ctx['client']) log(error_text) return False, ( "A `{}` error occured :(\n" "An admin has been notified and will be in touch.\n" "In the meantime, try asking for help in the support server: " "https://discord.gg/qhMrz6u".format(type(e).__name__)) ctx = { 'message': message, 'channel': channel, 'client': client, } auth_guilds = [int(g) for g in auth_guilds] success, response = await func.power_overwhelming(ctx, auth_guilds) if success or response != "NO RESPONSE": log("DM CMD {}: {}".format("Y" if success else "F", message.content)) if success: if response: if response != "NO RESPONSE": await echo(response, channel, message.author) else: await func.react(message, '✅') else: if response != "NO RESPONSE": await func.react(message, '❌') if response: await echo(response, channel, message.author) elif message.content.lower() in ["who am i", "who am i?"]: in_guilds = [] for g in client.guilds: if message.author in g.members: in_guilds.append("`{}` **{}**".format(g.id, g.name)) if in_guilds: await message.channel.send( "We're both in the following guilds:\n{}".format( '\n'.join(in_guilds))) else: await message.channel.send( "I'm not in any of the same guilds as you.") else: await admin_channels[-1].send( embed=discord.Embed(title="DM from **{}** [`{}`]:".format( message.author.name, message.author.id), description=message.content)) return if message.guild not in guilds: return prefix_m = message.guild.me.mention prefix_mx = "<@!" + prefix_m[2:] if message.guild.id in cfg.PREFIXES: prefix_p = cfg.PREFIXES[message.guild.id] else: prefix_p = 'vc/' prefix = None if message.content.startswith(prefix_m): prefix = prefix_m print_prefix = "@{} ".format(message.guild.me.display_name) elif message.content.startswith(prefix_mx): prefix = prefix_mx print_prefix = "@{} ".format(message.guild.me.display_name) elif message.content.lower().startswith(prefix_p.lower()): prefix = prefix_p print_prefix = prefix_p # Commands if prefix: msg = message.content[len(prefix):].strip() # Remove prefix split = msg.split(' ') cmd = split[0].lower() params = split[1:] params_str = ' '.join(params) clean_paramstr = ' '.join( message.clean_content[len(prefix):].strip().split(' ')[1:]) guild = message.guild channel = message.channel settings = utils.get_serv_settings(guild) if channel.id not in func.get_voice_context_channel_ids( guild, settings): settings['last_channel'] = channel.id utils.set_serv_settings(guild, settings) ctx = { 'client': client, 'guild': guild, 'prefix': prefix, 'print_prefix': print_prefix, 'prefix_p': prefix_p, 'command': cmd, 'gold': func.is_gold(guild), 'sapphire': func.is_sapphire(guild), 'settings': settings, 'message': message, 'channel': channel, 'clean_paramstr': clean_paramstr, } # Restricted commands perms = message.author.permissions_in(channel) perms_required = [ perms.manage_channels, perms.manage_roles, ] ctx['admin'] = all(perms_required) success, response = await commands.run(cmd, ctx, params) if success or response != "NO RESPONSE": log("CMD {}: {}".format("Y" if success else "F", msg), guild) if success: if response: if response != "NO RESPONSE": await echo(response, channel, message.author) else: await func.react(message, '✅') else: if response != "NO RESPONSE": await func.react(message, '❌') if response: await echo(response, channel, message.author)