Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
    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.")
Exemplo n.º 4
0
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)
Exemplo n.º 5
0
    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.")
Exemplo n.º 6
0
    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.")
Exemplo n.º 7
0
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.")
Exemplo n.º 8
0
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())
Exemplo n.º 9
0
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."
Exemplo n.º 10
0
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)}"
Exemplo n.º 11
0
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")
Exemplo n.º 12
0
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()
Exemplo n.º 13
0
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")
Exemplo n.º 14
0
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!")
Exemplo n.º 15
0
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"
Exemplo n.º 16
0
    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.")
Exemplo n.º 17
0
    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.")
Exemplo n.º 18
0
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)
Exemplo n.º 19
0
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.")
Exemplo n.º 20
0
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"