def markov(server, text, event): """ <user channel> - Generate sentence using a markov chain for a user using data from the given channel. If no user is specified, a sentence will be generated using all user messages. """ # Parse input text = text.split(" ") chan_id = "" user = "" if len(text) == 2: user = str_to_id(text[0]).strip() chan_id = str_to_id(text[1]).strip() elif len(text) == 1: chan_id = str_to_id(text[0]).strip() else: return "Needs at least a channel (e.g. `.markov #chan`) or a user and a channel (e.g. `.markov @user #channel`)" chan = get_channel_by_id(server, chan_id) if not chan: return "Given parameter is not a channel. Help:\n%s" % markov.__doc__ author_has_access = False for user_acc in chan.members_accessing_chan(): if event.author.id == user_acc.id: author_has_access = True break if not author_has_access: return "Invalid channel." # Get data msg_list = [] if user == "": msg_list = get_msgs_in_chan(chan.id, MSG_LIMIT) else: msg_list = get_msgs_for_user_in_chan(user, chan.id, MSG_LIMIT) msg_list = list(set(msg_list)) if len(msg_list) == 0: return "Could get data" print("Got %d messages" % len(msg_list)) # Remove short messages for idx, msg in enumerate(msg_list): msg_split = set(msg.split()) if len(msg_split) < 6: msg_list.pop(idx) print("Inputting %d messages" % len(msg_list)) text_model = markovify.NewlineText("\n".join(msg_list), retain_original=False) return "```%s```" % text_model.make_short_sentence( min_chars=50, max_chars=300, tries=10000, DEFAULT_MAX_OVERLAP_RATIO=0.4)
async def make_chan_private(text, server, reply): """ <channel> - make a channel private """ text = text.split(" ") if len(text) != 1: reply("Please input a valid channel name") return chdata = dutils.str_to_id(text[0]) for chan in server.get_chans_in_cat(PUB_CAT): if chan.name == chdata or chan.id == chdata: await chan.move_to_category(PRV_CAT) await sort_chans(server, PRV_CAT) # Create the op role await server.create_role("%s-op" % chan.name, mentionable=True) # Create the member role await server.create_role("%s-member" % chan.name, mentionable=True) await resync_roles(server) reply("Done!") return reply("No public channel named %s" % chdata)
def bday_add(text): user = server.get_user(dutils.str_to_id(text[0])) if not user: reply("Invalid user.") return try: date = parse_day(text[1]) except Exception as e: reply(str(e)) return if find_user(user.id, storage): reply("User already has a birthday set, remove him first!") return if date[1] not in storage["birthdays"]: storage["birthdays"][date[1]] = {} if date[0] not in storage["birthdays"][date[1]]: storage["birthdays"][date[1]][date[0]] = [] storage["birthdays"][date[1]][date[0]].append(user.id) storage.sync() reply("Added birthday.")
def give_toggled_role(text, server, command_name, storage, event): try: text = " ".join(text.split()).split() if len(text) < 1: return 'Needs a user (e.g. .{CMD} @cnc - to toggle @cnc the {CMD} role OR .{CMD} @cnc bad boy - to toggle @cnc the {CMD} role and save the reason "bad boy"'.format( CMD=command_name) user = dutils.get_user_by_id(server, dutils.str_to_id(text[0])) if not user: return "No such user" reason = "Not given" if len(text) >= 2: reason = " ".join(text[1:]) # Get the role main_role = dutils.get_role_by_id( server, storage["cmds"][command_name]["role_id"]) if main_role is None: return "Could not find given role" # Check if user is already in toggled role present = False for role in user.roles: if role == main_role: present = True break if not present: user.add_role(main_role) storage.sync() user.send_pm( "You have been given the `%s` role.\nReason: %s\nAuthor: %s" % ( storage["cmds"][command_name]["role_name"], reason, event.author.name, )) return "Given role" else: user.remove_role(main_role) user.send_pm( "You have been removed the `%s` role.\nReason: %s\nAuthor: %s" % ( storage["cmds"][command_name]["role_name"], reason, event.author.name, )) return "Removed the role" return "Nothing happened" except Exception as e: return "Couldn't give role: %s" % repr(e)
def bday_set_role(text): id = dutils.str_to_id(text[0]) role = server.get_role(id) if not role: reply("Invalid role.") return storage["role"] = id storage.sync() reply("Set role.")
def bday_set_channel(text): id = dutils.str_to_id(text[0]) channel = server.get_chan(id) if not channel: reply("Invalid channel.") return storage["chan"] = id storage.sync() reply("Set channel.")
async def grab(text, channel, storage, reply, event): """<user> - grab user's last message""" to_grab = None # Check if we're grabbing a user user_id = dutils.str_to_id(text) if event.author.id == user_id: reply("Didn't your mom teach you not to grab yourself in public?") return messages = await channel.async_get_latest_messages(100) to_grab = None for msg in messages: if msg.author.id == user_id: to_grab = msg break # Or we may be grabbing a message link or ID if not to_grab: _, _, msg_id = dutils.parse_message_link(text) if not msg_id: msg_id = text try: to_grab = await channel.async_get_message(msg_id) except: import traceback traceback.print_exc() if not to_grab: reply("Couldn't find anything.") if not storage["grabs"]: storage["grabs"] = [] for elem in storage["grabs"]: if elem["id"] == to_grab.id: reply("Message already grabbed") return grab_data = {} grab_data["text"] = to_grab.clean_content grab_data["id"] = to_grab.id grab_data["author_id"] = to_grab.author.id grab_data["author_name"] = to_grab.author.name storage["grabs"].append(grab_data) storage.sync() reply("Done.")
async def say(text, server, async_send_message): """ <channel message> - Send a message to a channel """ data = text.split(" ", maxsplit=1) channel = dutils.get_channel_by_id(server, dutils.str_to_id(data[0])) if not channel: return "Invalid channel" await async_send_message(text=data[1], target=channel.id, allowed_mentions=AllowedMentions.all())
def set_mod_log_chan(server, storage, text): """ <channel> - Set channel for moderator actions. When a moderator action will be done through the bot, details about the action will be logged to this channel. """ channel = dutils.get_channel_by_id(server, dutils.str_to_id(text)) if not channel: return "No such channel" else: storage["modlog_chan"] = channel.id storage.sync() return "Done."
async def timeout(text, server, storage, event, send_embed): """ Timeout an user: timeout @plp 1m - timeouts plp for one minute timeout @plp - displays timeout for plp If the user is timeouted, the timeout can be modified by issuing the timeout command again. """ text = text.split(" ") if len(text) == 0: return "Please specify a parameter:\n" + timeout.__doc__ user = dutils.get_user_by_id(server, dutils.str_to_id(text[0])) if not user: return "Could not find user" crt_timeout = user.timeout # User info needed if len(text) == 1: if crt_timeout == None: return "User does not have a timeout set." else: return f"Timeout will expire in: {time_utils.sec_to_human(crt_timeout.timestamp() - time_utils.tnow())}" # Set a timeout elif len(text) >= 2: tosec = time_utils.timeout_to_sec(text[1]) texp = time_utils.tnow() + tosec reason = "Not given" if len(text) >= 3: reason = " ".join(text[2:]) await user.set_timeout(time_utils.time_to_date(texp)) if crt_timeout != None: return f"Adjusted timeout to {time_utils.sec_to_human(tosec)}" else: # Create reason reason = add_reason(storage, event, user, reason, server, texp, "timeout") # Log the action log_action( storage, reason, send_embed, "User given timeout", ) return f"Set timeout to {time_utils.sec_to_human(tosec)}"
async def del_chan_category(server, text, reply, storage): """ <category name or ID> - Delete an existing channel category """ name_or_id = dutils.str_to_id(text).lower() # Check for duplicates for cat in get_bot_categs(storage, server): if cat["name"].lower() == name_or_id or cat["id"] == name_or_id: storage["bot_cats"].remove(cat) storage.sync() reply("Done.") return reply("Category not found")
async def userhistory(text, storage, async_send_message, server): """<user> - List confinement reasons for user""" def get_reasons(text, storage, user_id): if "reasons" not in storage: return ["No reasons set"] if user_id not in storage["reasons"]: return ["No history for given user"] rlist = [] for reason in storage["reasons"][user_id]: rtype = "No type given" # Skip closed cases if "Closed" in reason and reason["Closed"]: continue # Type may be missing if "Type" in reason: rtype = reason["Type"] rtext = "Case: %s | Type: %s | Date: %s | Author: %s" % ( reason["Case ID"], rtype, reason["Date"], reason["Author"].split("/")[0], ) rlist.append(rtext) return rlist try: # Get the user user_id = dutils.str_to_id(text) # Get reasons usr_hist = get_reasons(text, storage, user_id) # Print as pages paged_content = paged.element(usr_hist, async_send_message, "User history:", no_timeout=True) await paged_content.get_crt_page() except: import traceback traceback.print_exc()
async def add_chan_category(server, text, reply, storage): """ <category name or ID, type (managed, unmanaged)> - Add an existing channel category to the bot A 'managed' category will have the permissions managed automatically by inheriting them from the parent category. An 'unmanaged' category will NOT have the permissions managed automatically. Instead, there will still be channel OPs. """ text = text.split(" ") if len(text) != 2: reply("Please specify name/ID manager/unmanaged") return if text[1] not in CAT_TYPES: reply("Please specify a category: %s" % ", ".join(CAT_TYPES)) return name_or_id = dutils.str_to_id(text[0]).lower() cat_type = text[1] # Check for duplicates for cat in get_bot_categs(storage, server): if cat["name"] == name_or_id or cat["id"] == name_or_id: if cat["type"] != cat_type: cat["type"] = cat_type storage.sync() reply("Category updated to %s" % cat_type) return reply("Checking if %s exists" % name_or_id) for cat in server.get_categories(): if cat.name == name_or_id or cat.id == name_or_id: if "bot_cats" not in storage: storage["bot_cats"] = [] storage["bot_cats"].append({ "name": cat.name, "id": cat.id, "type": text[1] }) storage.sync() reply("Found! Done!") return reply("Category not found")
async def create_channel(text, server, reply): """ <name type founder> - create a channel by specifying a 'name', type (either 'public' or 'private') and who is the channel founder """ # Check input text = text.split(" ") if len(text) != 3: return create_channel.__doc__ # Parse data chname = text[0].lower() chtype = text[1].lower() user = dutils.get_user_by_id(server, dutils.str_to_id(text[2])) if not user: reply("Could not find given user") return if chtype not in CHTYPES: reply("Channel type must be one of: %s" % str(CHTYPES)) return # Check dupes for chan in chain(server.get_chans_in_cat(PUB_CAT), server.get_chans_in_cat(PRV_CAT)): if chan.name == chname: reply("A channel by that name already exists") return await server.create_role("%s-op" % chname, mentionable=True) if chtype == PUB_CAT: await server.create_text_channel(chname, PUB_CAT) elif chtype == PRV_CAT: await server.create_text_channel(chname, PRV_CAT) await server.create_role("%s-member" % chname, mentionable=True) print("Created roles") await sort_roles(server) await sort_chans(server, PUB_CAT) await sort_chans(server, PRV_CAT) await resync_roles(server) # Add the OP user.add_role(dutils.get_role_by_name(server, "%s-op" % chname)) print("Should be done!")
def say_pm(text, bot): """ <user message> - Send a message to an user. """ data = text.split(" ", maxsplit=1) user_id = dutils.str_to_id(data[0]) user = None for server in bot.backend.get_servers(): user = dutils.get_user_by_id(server, user_id) if user: break if not user: return "Invalid user" user.send_pm(data[1]) return "Done"
def bday_remove(text): user = server.get_user(dutils.str_to_id(text[0])) if not user: reply("Invalid user.") return date = find_user(user.id, storage) if not date: reply("User does not have a birthday set.") return storage["birthdays"][date[1]][date[0]].remove(user.id) if len(storage["birthdays"][date[1]][date[0]]) == 0: del storage["birthdays"][date[1]][date[0]] if len(storage["birthdays"][date[1]]) == 0: del storage["birthdays"][date[1]] storage.sync() reply("Removed birthday.")
def bday_setDate(text): user = server.get_user(dutils.str_to_id(text[0])) if not user: reply("Invalid user.") return date = find_user(user.id, storage) if not date: reply("User does not have a birthday set.") return try: new_date = parse_day(text[1]) except Exception as e: reply(str(e)) return if date == new_date: reply("User already has this birthday set!") return storage["birthdays"][date[1]][date[0]].remove(user.id) if len(storage["birthdays"][date[1]][date[0]]) == 0: del storage["birthdays"][date[1]][date[0]] if len(storage["birthdays"][date[1]]) == 0: del storage["birthdays"][date[1]] if new_date[1] not in storage["birthdays"]: storage["birthdays"][new_date[1]] = {} if new_date[0] not in storage["birthdays"][new_date[1]]: storage["birthdays"][new_date[1]][new_date[0]] = [] storage["birthdays"][new_date[1]][new_date[0]].append(user.id) storage.sync() reply("Updated birthday date.")
async def make_chan_public(text, server, reply): """ <channel> - make a channel public """ text = text.split(" ") if len(text) != 1: reply("Please input a valid channel name") return chdata = dutils.str_to_id(text[0]) for chan in server.get_chans_in_cat(PRV_CAT): if chan.name == chdata or chan.id == chdata: await chan.move_to_category(PUB_CAT) await sort_chans(server, PUB_CAT) # Delete role await server.delete_role_by_name("%s-member" % chan.name) await resync_roles(server) reply("Done!") return reply("No private channel named %s" % chdata)
async def grab(text, channel, storage, reply, event): """<user> - grab user's last message. If <user> is empty, it will try to grab the message you're replying to""" to_grab = None if text != "": # Check if we're grabbing a user user_id = dutils.str_to_id(text) if event.author.id == user_id: reply("Didn't your mom teach you not to grab yourself in public?") return messages = await channel.async_get_latest_messages(100) to_grab = None for msg in messages: if msg.author.id == user_id: to_grab = msg break # Or we may be grabbing a message link or ID if not to_grab: _, _, msg_id = dutils.parse_message_link(text) if not msg_id: msg_id = text try: to_grab = await channel.async_get_message(msg_id) except nextcord.errors.NotFound: pass except: import traceback traceback.print_exc() # Or we're grabbing a message we are replying to if not to_grab: ref = await event.msg.reference() if ref: if ref.author.id == event.author.id: reply("Don't try to grab yourself 😉") return to_grab = ref if not to_grab: reply("Couldn't find anything.") return if not storage["grabs"]: storage["grabs"] = [] for elem in storage["grabs"]: if elem["id"] == to_grab.id: reply("Message already grabbed") return grab_data = {} grab_data["text"] = to_grab.clean_content grab_data["id"] = to_grab.id grab_data["author_id"] = to_grab.author.id grab_data["author_name"] = to_grab.author.name storage["grabs"].append(grab_data) storage.sync() reply("Done.")
def give_temp_role(text, server, command_name, storage, event): # Remove extra whitespace and split text = " ".join(text.split()).split() if len(text) < 2: return "Needs at least user and time (e.g. .{CMD} @plp, 5m - to give @plp {CMD} for 5 minutes OR .{CMD} @plp 5m bad user - to give @plp {CMD} for 5m and save the reason \"bad user\")".format(CMD=command_name) + \ "The abbrebiations are: s - seconds, m - minutes, h - hours, d - days." # Get user user = dutils.get_user_by_id(server, dutils.str_to_id(text[0])) if not user: return "No such user" # Get reason reason = "Not given" if len(text) >= 3: reason = " ".join(text[2:]) # Get timeout timeout_sec = time_utils.timeout_to_sec(text[1]) # If timeout is 0, double check the input if timeout_sec == 0 and text[1] != "0s": return "There may have been a problem parsing `%s`. Please check it and run the command again." % text[ 1] # When the timeout will expire texp = datetime.datetime.now().timestamp() + timeout_sec # Get the role role = dutils.get_role_by_id(server, storage["cmds"][command_name]["role_id"]) if role is None: return "Could not find given role" if "temp_roles" not in storage: storage["temp_roles"] = {} if command_name not in storage["temp_roles"]: storage["temp_roles"][command_name] = [] # Check if user is already in temp role extra = False for entry in storage["temp_roles"][command_name]: if entry["user_id"] == user.id: extra = True break crt_roles = [] # Get current roles for urole in user.roles: # If the role has already been given, assume that it will be timed from now if urole.id == role.id: continue crt_roles.append(urole.id) # Check if it's extra time if not extra: # Create a new user entry reason_entry = create_user_reason( storage, user, event.author, reason, "https://discordapp.com/channels/%s/%s/%s" % (server.id, event.channel.id, event.msg.id), texp, command_name) # Create command entry new_entry = {} new_entry["user_id"] = str(user.id) new_entry["user_name"] = user.name new_entry["expire"] = texp new_entry["crt_roles"] = crt_roles new_entry["reason_id"] = reason_entry["Case ID"] storage["temp_roles"][command_name].append(new_entry) # Replace user roles user.replace_roles([role]) storage.sync() user.send_pm( "You have been given the `%s` role. It will last for %s.\nReason: %s\nAuthor: %s" % (storage["cmds"][command_name]["role_name"], text[1], reason, event.author.name)) return reason_entry else: adjust_user_reason( storage, event.author, user.id, command_name, texp, "https://discordapp.com/channels/%s/%s/%s" % (server.id, event.channel.id, event.msg.id)) return "Adjusted time for user to %d" % timeout_sec return "Nothing happened"