示例#1
0
def bot_dice(channel_id, message):
    '''
    Bot rolls a dice (6 if no number of sides specified), returning a random side
    '''
    sides = 6
    # Not default
    try:
        if len(message) > 5:
            sides = int(message[6:])
        choice = 1 + random.choice(range(sides))
        bot_msg = f'Rolling a {sides}-sided dice.. and got {choice}'
        bot_send_message(channel_with_id(channel_id), bot_msg, temporary=False)
    except Exception:
        bot_msg = 'Please provide a valid number for /dice X, or just /dice for a six-sided dice!'
        bot_send_message(channel_with_id(channel_id), bot_msg, temporary=False)
示例#2
0
def message_prune(token, channel_id, num_messages):
    '''
    Prunes the last num_messages messages from a channel
    NOTE: this function cannot be placed in message.py
          due to circular imports
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)
    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel')
    elif auth_user not in channel.get_all_members():
        raise AccessError('Invalid permission')
    elif auth_user not in channel.get_owner_members(
    ) and auth_user.get_permission_id() != 1:
        raise AccessError('Invalid permission for pruning messages')
    total_messages = len(channel.get_messages())
    if num_messages > total_messages:
        raise InputError(
            f'Attempted to prune more messages than there are messages in the channel'
        )
    # Prune last num_messages messages
    del channel.get_messages()[-num_messages:]

    return {}
示例#3
0
def standup_start(token, channel_id, length):
    '''
    For a given channel, start the standup period whereby for the next "length" seconds
    if someone calls "standup_send" with a message, it is buffered in the standup queue
    then at the end of the standup period a message will be added to the message queue
    in the channel from the user who started the standup.
    Input: token (str), channel_id (int), length (int)
    Output: time_finish (UNIX timestamp int)
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel')
    elif auth_user not in channel.get_all_members():
        raise AccessError('User not member of channel')
    elif length <= 0:
        raise InputError('Invalid standup time')
    elif channel.get_standup_status()['is_active']:
        raise InputError('An active standup is currently running')

    end_time = channel.start_standup(initiator=auth_user, length=length)

    return {
        'time_finish': end_time,
    }
示例#4
0
def message_send(token, channel_id, message):
    '''
    Sends the message (str) by storing it in the channel
    with channel_id (int) and sender as user with token (str)
    Output: message_id (int) of message stored
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel')
    elif auth_user not in channel.get_all_members():
        raise AccessError('User not in channel')
    elif not message:
        raise InputError('Empty message not allowed')
    elif len(message) > 1000:
        raise InputError('Message should be 1000 characters or less')

    # Store message
    new_message = Message(auth_user, message, current_time())
    channel.get_messages().append(new_message)
    bot_message_parser(token, channel_id, message)

    return {
        'message_id': new_message.get_message_id(),
    }
示例#5
0
def channel_kick(token, channel_id, u_id):
    '''
    Remove user with user id u_id as a member of the channel
    Input: token (str), channel_id (int), u_id (int)
    Output: empty dict
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)
    old_user = user_with_id(u_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel_id')
    elif old_user is None:
        raise AccessError('Invalid u_id')
    elif auth_user not in channel.get_all_members():
        # Flockr owner may not be a channel member
        raise AccessError('Authorised user is not a member in the channel')
    elif auth_user not in channel.get_owner_members() and auth_user.get_permission_id() != 1:
        raise AccessError('Authorised user is not an owner of channel and not Flockr owner')
    elif old_user in channel.get_owner_members():
        # User cannot be an owner of the channel
        raise InputError('User to be kicked cannot be an owner in the channel')
    elif old_user not in channel.get_all_members():
        raise InputError('User to be kicked is not a member in the channel')

    # Remove owner
    channel.get_all_members().remove(old_user)

    return {
    }
示例#6
0
def channel_invite(token, channel_id, u_id):
    '''
    Invites a user (with user id u_id) to join a channel with ID channel_id.
    Once invited the user is added to the channel immediately
    Input: token (str), channel_id (int), u_id (int)
    Output: empty dict
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)
    invited_user = user_with_id(u_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel_id')
    elif invited_user is None:
        raise InputError('Invalid u_id')
    elif auth_user not in channel.get_all_members():
        raise AccessError('Authorised user not a member of channel')

    # Append invited user to all_members (if they're not already a member)
    if invited_user not in channel.get_all_members():
        channel.get_all_members().append(invited_user)

    return {
    }
示例#7
0
def standup_send(token, channel_id, message):
    '''
    Send a message to get buffered in the standup queue,
    assuming a standup is currently active
    Input: token (str), channel_id (int), message (str)
    Output: empty dict
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel')
    elif auth_user not in channel.get_all_members():
        raise AccessError('User not member of channel')
    elif not channel.get_standup_status()['is_active']:
        raise InputError('An active standup is not currently running')
    elif not message:
        raise InputError('Empty message not allowed')
    elif len(message) > 1000:
        raise InputError('Message should be 1000 characters or less')

    # Add message to queue
    msg = Message(auth_user, message, time_created=current_time())
    channel.get_standup_status()['queued_messages'].append(msg)

    return {}
示例#8
0
def bot_help(channel_id):
    ''' Displays help message '''
    bot_msg = '''
    Available commands:
    === General ===
    - /help
      displays this message
    - /time
      displays the current time
    - /standup X
      starts a standup for X seconds
    - /prune X
      removes the last X messages - requires admin permissions
    - /kick user_handle
      kicks a specified user from this channel - requires admin permissions
    === Hangman ===
    - /hangman start
      starts a hangman game
    - /guess X
      guess a character or word for an active hangman game
    === Fun Utilities ===
    - /choose A B C.
      bot randomly chooses from the space-separated arguments
    - /flip
      flips a coin - heads or tails?
    - /dice (X)
      rolls a X-sided dice, or a six-sided dice by default
    '''
    bot_send_message(channel_with_id(channel_id), bot_msg, temporary=False)
示例#9
0
def standup_active(token, channel_id):
    '''
    For a given channel, return whether a standup is active in it,
    and what time the standup finishes. If no standup is active,
    then time_finish returns None.
    Input: token (str), channel_id (int)
    Output: is_active (bool), time_finish (UNIX timestamp int)
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel')
    elif auth_user not in channel.get_all_members():
        raise AccessError('User not member of channel')

    standup_status = channel.get_standup_status()

    return {
        'is_active': standup_status['is_active'],
        'time_finish': standup_status['time_finish'],
    }
示例#10
0
def channel_messages(token, channel_id, start):
    '''
    Given a Channel with ID channel_id that the authorised user is part of,
    return up to 50 messages between index "start" and "start + 50".
    Message with index 0 is the most recent message in the channel.
    This function returns a new index "end" which is the value of "start + 50", or,
    if this function has returned the least recent messages in the channel,
    returns -1 in "end" to indicate there are no more messages to load after this return.
    Input: token (str), channel_id (int), start (int)
    Ouput: dict
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel_id')
    elif auth_user not in channel.get_all_members():
        raise AccessError('Authorised user not a member of channel')
    elif start < 0 or start > len(channel.get_messages()):
        raise InputError('Invalid start index')

    # Messages originally ordered chronologically -
    # reverse and retrieve a maximum of 50 most recent messages
    messages = list(reversed(channel.get_messages()))[start : start + 50]
    if len(messages) == 0:
        # The end is reached there are no messages
        end = -1
    else:
        # The end is also reached if the first message (id) is included in messages
        first_message_id = channel.get_messages()[0].get_message_id()
        first_message_reached = any(message.get_message_id() == first_message_id
                                    for message in messages)
        end = -1 if first_message_reached else start + 50

    return {
        'messages': [
            {
                'message_id': message.get_message_id(),
                'u_id': message.get_sender().get_u_id(),
                'time_created': message.get_time_created(),
                'message': message.get_message(),
                'reacts': [
                    {
                        'react_id': react.get_react_id(),
                        'u_ids': [reactor.get_u_id() for reactor in react.get_reactors()],
                        'is_this_user_reacted': auth_user in react.get_reactors(),
                    }
                    for react in message.get_reacts()
                ],
                'is_pinned': message.get_is_pinned(),
            }
            for message in messages
        ],
        'start': start,
        'end': end,
    }
示例#11
0
def message_sendlater(token, channel_id, message, time_sent):
    '''
    Send a message from authorised_user to the channel specified
    by channel_id automatically at a specified time in the future.
    Input: token (str), channel_id (int), message (str), time_sent (UNIX timestamp - float)
    Output: message_id (int) of message to be sent
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)
    time_diff = time_sent - current_time()

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel')
    elif auth_user not in channel.get_all_members():
        raise AccessError('User not in channel')
    elif not message:
        raise InputError('Empty message not allowed')
    elif len(message) > 1000:
        raise InputError('Message should be 1000 characters or less')
    elif time_diff < 0:
        raise InputError('Time is in the past')

    # Note that message will still be sent later even if the user
    # leaves channel or logs out before message is actually sent
    new_message = Message(auth_user, message, time_created=time_sent)
    t = Timer(time_diff, channel.get_messages().append, args=[new_message])
    t.start()

    return {
        'message_id': new_message.get_message_id(),
    }
示例#12
0
def bot_choose(channel_id, message):
    '''
    Bot randomly chooses one of the options listed in the /choose command
    '''
    options = message.split(' ')[1:]
    bot_msg = f'Hmm.. tough choice.. but I choose {random.choice(options)}'
    bot_send_message(channel_with_id(channel_id), bot_msg, temporary=False)
示例#13
0
def channel_addowner(token, channel_id, u_id):
    '''
    Make user with user id u_id an owner of this channel
    Input: token (str), channel_id (int), u_id (int)
    Output: empty dict
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)
    new_owner = user_with_id(u_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel_id')
    elif new_owner is None or new_owner not in channel.get_all_members():
        raise AccessError('Invalid u_id or user is not a member in the channel')
    elif auth_user not in channel.get_owner_members() and auth_user.get_permission_id() != 1:
        raise AccessError('Authorised user is not an owner of channel and not Flockr owner')
    elif auth_user not in channel.get_all_members():
        # Note that Flockr owner may not be a channel member
        raise AccessError('Authorised user is not a member in the channel')
    elif new_owner in channel.get_owner_members():
        raise InputError('User to be added as an owner is already an owner in the channel')

    # Add user as owner
    channel.get_owner_members().append(new_owner)

    return {
    }
示例#14
0
def channel_leave(token, channel_id):
    '''
    Given a channel ID, the user removed as a member of this channel
    Input: token (str), channel_id (int)
    Output: empty dict
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel_id')
    elif auth_user not in channel.get_all_members():
        raise AccessError('Authorised user not a member of channel')

    # Remove user from all_members
    channel.get_all_members().remove(auth_user)

    # Attempt to remove user from owner_members if they are an owner
    if auth_user in channel.get_owner_members():
        channel.get_owner_members().remove(auth_user)

    return {
    }
示例#15
0
def bot_time(channel_id):
    '''
    Displays the current time
    '''
    bot_init()
    channel = channel_with_id(channel_id)
    bot_msg = f'The current time is {datetime.now().strftime(r"%A %-d %B %Y, %-I:%M %p")}.'
    bot_send_message(channel, bot_msg, temporary=False)
示例#16
0
def bot_hangman_guess(token, channel_id, message):
    '''
    Registers a guess for an active hangman game
    '''
    channel = channel_with_id(channel_id)
    try:
        global hangman_status
        if not hangman_status['active']:
            raise InputError(
                'No active hangman games.. please type /hangman start to start one!'
            )
        # Extract character or word
        game_win = False
        if len(message) < 8:
            raise InputError(
                "Invalid guess format. Please ensure it's /guess C")
        elif len(message) == 8:
            # Character guessed
            character = message[7].upper()
            hangman_status['guessed_letters'].add(character)
            hangman_status['guesses_remaining'] -= 1
            # Win condition (all letters in word have been guessed, as a subset)
            if hangman_status['word_set'].issubset(
                    hangman_status['guessed_letters']):
                game_win = True
        else:
            # Word guessed
            hangman_status['guesses_remaining'] -= 1
            # Check win condition
            if hangman_status['word'] == message[7:].upper():
                game_win = True

        # Process end condition
        if game_win:
            # Win condition (word guessed)
            user = user_with_token(token)
            bot_msg = f"Congratulations {user.get_handle()} on guessing the word {hangman_status['word']}!"
            bot_send_message(channel, bot_msg, temporary=False)
            bot_hangman_reset()
        elif hangman_status['guesses_remaining'] == 0:
            # Loss condition
            bot_msg = f"Unlucky, the word was {hangman_status['word']}!"
            bot_send_message(channel, bot_msg, temporary=False)
            bot_hangman_reset()
        else:
            # Continue condition
            bot_hangman_word_display(channel)

    except Exception as e:
        bot_msg = f'Failed to register guess: {e}'
        bot_send_message(channel, bot_msg, temporary=False)
示例#17
0
def bot_message_prune(token, channel_id, message):
    '''
    Wrapper command for pruning messages
    '''
    bot_init()
    channel = channel_with_id(channel_id)
    try:
        auth_user = user_with_token(token)
        num_messages = int(message[6:])
        message_prune(token, channel_id, num_messages)
        bot_msg = f'{num_messages} messages have been successfully pruned by {auth_user.get_handle()}'
        bot_send_message(channel, bot_msg, temporary=True)
    except Exception as e:
        bot_msg = f'Failed to prune: {e}'
        bot_send_message(channel, bot_msg, temporary=False)
示例#18
0
def bot_kick(token, channel_id, message):
    '''
    Wrapper command for kicking a user from a channel
    '''
    user = user_with_token(token)
    channel = channel_with_id(channel_id)
    try:
        handle = message[6:]
        kick_user = user_with_handle(handle)
        if kick_user is None:
            raise InputError('Please provide a valid user handle!')
        channel_kick(token, channel_id, kick_user.get_u_id())
        bot_msg = f'⚽️ {kick_user.get_handle()} has been kicked by {user.get_handle()}!'
        bot_send_message(channel, bot_msg, temporary=False)
    except Exception as e:
        bot_msg = f'Failed to kick: {e}'
        bot_send_message(channel, bot_msg, temporary=False)
示例#19
0
def bot_hangman_start(channel_id):
    '''
    Starts a new hangman game
    '''
    channel = channel_with_id(channel_id)
    global hangman_status
    if hangman_status['active']:
        # Already active
        bot_msg = 'Hangman game already in progress!'
        bot_send_message(channel, bot_msg, temporary=False)
        bot_hangman_word_display(channel)
        return
    word = random.choice(list(english_words_set)).upper()
    hangman_status = {
        'active': True,
        'word': word,
        'word_set': set(word),
        'guessed_letters': set(),
        'guesses_remaining': TOTAL_HANGMAN_GUESSES,
    }
    bot_hangman_word_display(channel)
示例#20
0
def channel_details(token, channel_id):
    '''
    Given a Channel with ID channel_id that the authorised user is part of,
    provide basic details about the channel
    Input: token (str), channel_id (int)
    Output: dict
    '''
    # Retrieve data
    auth_user = user_with_token(token)
    channel = channel_with_id(channel_id)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel_id')
    elif auth_user not in channel.get_all_members():
        raise AccessError('Authorised user not a member of channel')

    return {
        'name': channel.get_name(),
        'owner_members': [
            {
                'u_id': owner.get_u_id(),
                'name_first': owner.get_name_first(),
                'name_last': owner.get_name_last(),
                'profile_img_url': owner.get_profile_img_url(),
            }
            for owner in channel.get_owner_members()
        ],
        'all_members': [
            {
                'u_id': member.get_u_id(),
                'name_first': member.get_name_first(),
                'name_last': member.get_name_last(),
                'profile_img_url': member.get_profile_img_url(),
            }
            for member in channel.get_all_members()
        ],
    }
示例#21
0
def channel_join(token, channel_id):
    '''
    Given a channel_id of a channel that the authorised user can join, adds them to that channel
    Input: token (str), channel_id (int)
    Output: empty dict
    '''
    # Retrieve data
    channel = channel_with_id(channel_id)
    auth_user = user_with_token(token)

    # Error check
    if auth_user is None:
        raise AccessError('Invalid token')
    elif channel is None:
        raise InputError('Invalid channel_id')
    elif not channel.get_is_public() and auth_user.get_permission_id() != 1:
        raise AccessError('Private channel and authorised user is not Flockr owner')

    # Adds user to channel if not already in channel (don't want to add duplicate users to list)
    if auth_user not in channel.get_all_members():
        channel.get_all_members().append(auth_user)

    return {
    }
示例#22
0
def bot_flip(channel_id):
    '''
    Bot flips a coin and returns heads or tails
    '''
    bot_msg = f"It appears to be {random.choice(['heads', 'tails'])}!"
    bot_send_message(channel_with_id(channel_id), bot_msg, temporary=False)