Beispiel #1
0
def delete(bot, msg):
    """Delete a macro."""

    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        c.execute('DELETE FROM macros WHERE slug = %s', (slug, ))
        msg.respond('macro `{}` has been deleted.'.format(slug))
Beispiel #2
0
def addme(bot, msg):
    """Add yourself to a notification group as a member."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        group = get_group(c, slug)
        if group is None:
            msg.respond('No such notification group.')
            return

        # If you're already a _direct_ owner or member of this group, do nothing.
        if group['owners'] and msg.nick in group['owners'].split(' '):
            msg.respond(f'You\'re already an owner of {slug}!')
            return

        members = []
        if group['members']:
            members = group['members'].split(' ')

        if msg.nick in members:
            msg.respond(f'You\'re already a member of {slug}!')
            return

        members.append(msg.nick)

        c.execute(
            'UPDATE notify SET members = %s WHERE slug = %s',
            (' '.join(members), slug),
        )
        msg.respond(f'Added you to {slug}, as a member.')
Beispiel #3
0
def rand(bot, msg):
    """Show a random quote, optionally filtered by a search term."""
    if msg.match.groups():
        arg = msg.match.group(1).split()
    else:
        arg = []
    with db.cursor(password=bot.mysql_password) as c:
        c.execute(
            'SELECT * FROM quotes WHERE is_deleted = 0 ' +
            ' '.join(
                'AND quote LIKE %s COLLATE utf8mb4_unicode_ci'
                for _ in arg
            ) +
            ' ORDER BY RAND() LIMIT 1',
            tuple(
                f'%{a}%'
                for a in arg
            ),
        )
        quote = c.fetchone()

    if quote is not None:
        _print_quote(msg.respond, quote)
    else:
        msg.respond('There are... no quotes?')
Beispiel #4
0
def add(bot, msg):
    """Add a new quote."""
    with db.cursor(password=bot.mysql_password) as c:
        c.execute('INSERT INTO quotes (quote) VALUES (%s)',
                  (msg.match.group(1), ))

    msg.respond('Your quote was added as #{}'.format(c.lastrowid))
Beispiel #5
0
def add(bot, msg):
    """Add a new macro."""

    slug = msg.match.group(1)
    link = msg.match.group(2)

    if slug in KEYWORDS:
        msg.respond(f'`{slug}` is a reserved keyword.')
        return

    if len(slug) > 50 or len(link) > 100:
        msg.respond('macro slugs must be <= 50 and links <= 100 characters')
        return

    if len(link) > 80:
        msg.respond('please try to keep macro links below 80 characters')

    with db.cursor(password=bot.mysql_password) as c:

        c.execute('SELECT * FROM macros WHERE slug = %s', (slug, ))
        result = c.fetchone()
        if result is not None:
            msg.respond(
                'macro `{}` already exists as {}'.format(
                    result['slug'],
                    result['link'],
                ), )
        else:
            c.execute(
                'INSERT INTO macros (slug, link) VALUES (%s, %s)',
                (slug, link),
            )
            msg.respond(f'macro added as `{slug}`')
Beispiel #6
0
def removeme(bot, msg):
    """Remove yourself from a notification group."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        group = get_group(c, slug)
        if group is None:
            msg.respond('No such notification group.')
            return

        # If you're already a _direct_ owner or member of this group, do nothing.
        if group['owners'] and msg.nick in group['owners'].split(' '):
            msg.respond(
                f'You\'re an owner of {slug}. ' +
                'If you\'re sure you want to remove yourself, please use !notify remove.',
            )
            return

        if group['members'] is None:
            msg.respond(f'You\'re not a member of {slug}!')
            return

        members = group['members'].split(' ')
        if msg.nick not in members:
            msg.respond(f'You\'re not a member of {slug}!')
            return

        members = [m for m in members if m != msg.nick]

        c.execute(
            'UPDATE notify SET members = %s WHERE slug = %s',
            (' '.join(members), slug),
        )
        msg.respond(f'Removed you to from the member list for {slug}.')
Beispiel #7
0
def build_model(db_passwd, model_weights=[1, 1, 1]):
    """Rebuild the markov model using quotes, inspire, and rants databases as seeds."""
    with db.cursor(password=db_passwd) as c:
        # Fetch quote data
        c.execute('SELECT quote FROM quotes WHERE is_deleted = 0')
        quotes = c.fetchall()

        # Fetch inspire data
        c.execute('SELECT text FROM inspire')
        inspirations = c.fetchall()

        # Fetch iconic FOSS rants
        c.execute('SELECT text FROM markov_rants')
        rants = c.fetchall()

    # Normalize the quote data... Get rid of IRC junk
    clean_quotes = [normalize_quote(d['quote']) for d in quotes]

    # Normalize the inspire data... Just lightly prune authors
    clean_inspirations = [
        normalize_inspiration(d['text']) for d in inspirations
    ]

    # Normalize the rant data... just remove ending punctuation
    clean_rants = [normalize_rant(d['text']) for d in rants]

    # Create the three models, and combine them.
    # More heavily weight our quotes and rants
    rants_model = markovify.NewlineText('\n'.join(clean_rants))
    quotes_model = markovify.NewlineText('\n'.join(clean_quotes))
    inspire_model = markovify.NewlineText('\n'.join(clean_inspirations))
    return markovify.combine([quotes_model, rants_model, inspire_model],
                             model_weights)
Beispiel #8
0
def notify(bot, msg):
    """Notify all targets (owners and members) in the tagged notificaton group."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        targets = get_all_targets(c, slug)
        if targets is not None:
            targets_str = ' '.join(targets)
            msg.respond(f'{slug}: {targets_str}', ping=False)
Beispiel #9
0
def join_channel(bot, channel):
    if IRC_CHANNELS_JOIN_MYSQL:
        with db.cursor(password=bot.mysql_password) as c:
            c.execute(
                'INSERT IGNORE INTO channels (channel) VALUES (%s)',
                (channel,),
            )
    bot.connection.join(channel)
Beispiel #10
0
def register(bot):
    bot.listen(r'^join (#[a-zA-Z0-9\-_#]+)$', join, require_mention=True)
    bot.listen(r'^leave$', leave, require_mention=True)

    if IRC_CHANNELS_JOIN_MYSQL:
        with db.cursor(password=bot.mysql_password) as c:
            c.execute('SELECT channel FROM channels')
            bot.extra_channels |= {row['channel'] for row in c}
Beispiel #11
0
def list(bot):
    """List all macros for macros help page."""

    with db.cursor(password=bot.mysql_password) as c:
        c.execute('SELECT slug, link FROM macros ORDER BY slug')

    for entry in c.fetchall():
        yield entry['slug'], entry['link']
Beispiel #12
0
def leave(bot, msg):
    """Leave the current channel."""
    if msg.channel in IRC_CHANNELS_OPER | IRC_CHANNELS_ANNOUNCE:
        msg.respond("can't leave {}!".format(msg.channel))
    else:
        with db.cursor(password=bot.mysql_password) as c:
            c.execute('DELETE FROM channels WHERE channel = %s',
                      (msg.channel, ))
        bot.connection.part(msg.channel)
Beispiel #13
0
def know_that(bot, msg):
    """Create or update a definition."""
    thing, what_it_is = msg.match.groups()
    with db.cursor(password=bot.mysql_password) as c:
        c.execute(
            'REPLACE INTO what_is (thing, what_it_is) VALUES (%s, %s)',
            (thing, what_it_is),
        )
    msg.respond('okay, {} is {}'.format(thing, what_it_is), ping=False)
Beispiel #14
0
def replace(bot, msg):
    """Replace the target of a macro slug."""

    slug = msg.match.group(1)
    new_link = msg.match.group(2)

    with db.cursor(password=bot.mysql_password) as c:
        c.execute(
            'UPDATE macros SET link = %s WHERE slug = %s',
            (new_link, slug),
        )
        msg.respond(f'macro `{slug}` updated')
Beispiel #15
0
def delete(bot, msg):
    """Delete a quote."""
    arg = msg.match.group(1)
    try:
        quote_id = int(arg)
    except ValueError:
        msg.respond('Not a valid ID: {}'.format(arg))
    else:
        with db.cursor(password=bot.mysql_password) as c:
            c.execute('UPDATE quotes SET is_deleted = 1 WHERE id = %s',
                      (quote_id, ))
        msg.respond('Quote #{} has been deleted.'.format(quote_id))
Beispiel #16
0
def create(bot, msg):
    """Create a new notification group."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        existing = get_group(c, slug)
        if existing is not None:
            msg.respond(f'{slug} already exists.')
            return

        c.execute(
            'INSERT INTO notify (slug, owners) VALUES (%s, %s)',
            (slug, msg.nick),
        )
        msg.respond(f'Empty group "{slug}" added. You are the only owner.')
Beispiel #17
0
def show(bot, msg):
    """Show owners and members of the notification group."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        group = get_group(c, slug)
        if group is None:
            msg.respond(f'{slug} not found.')
            return
        for attr in ('owners', 'members'):
            if group[attr] is None:
                msg.respond(f'{slug} has no {attr}', ping=False)
            else:
                targets = expand_list(c, group[attr])
                msg.respond(f'{slug} {attr}: {targets}', ping=False)
Beispiel #18
0
def inspire(bot, msg):
    """Print a quote, optionally filtering."""
    term = msg.match.group(1) or ''
    with db.cursor(password=bot.mysql_password) as c:
        c.execute(
            'SELECT text FROM `inspire` ' +
            'WHERE LOWER(text) LIKE LOWER(%s) ' + 'ORDER BY RAND() LIMIT 1',
            '%{}%'.format(term),
        )

        quote = c.fetchone()

        msg.respond(quote['text'] if quote else
                    "Nothing inspirational matching '{}' found.".format(term))
Beispiel #19
0
def showdumb(bot, msg):
    """Show the notification group, but don't expand subgroups."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        group = get_group(c, slug)
        if group is None:
            msg.respond(f'{slug} not found.')
            return
        for attr in ('owners', 'members'):
            if group[attr] is None:
                msg.respond(f'{slug} has no {attr}', ping=False)
            else:
                targets = [deping(target) for target in group[attr].split(' ')]
                joined_targets = ' '.join(targets)
                msg.respond(f'{slug} {attr}: {joined_targets}', ping=False)
Beispiel #20
0
def rename(bot, msg):
    """Rename a macro."""

    old_slug = msg.match.group(1)
    new_slug = msg.match.group(2)

    if new_slug in KEYWORDS:
        msg.respond(f'`{new_slug}` is a reserved keyword.')
        return

    with db.cursor(password=bot.mysql_password) as c:
        c.execute(
            'UPDATE macros SET slug = %s WHERE slug = %s',
            (new_slug, old_slug),
        )
        msg.respond(f'macro `{old_slug}` has been renamed to `{new_slug}`')
Beispiel #21
0
def show(bot, msg):
    """Return a macro by slug."""
    slug = msg.match.group(1)

    # special case these so show doesn't trigger on add/delete
    # while still letting the trigger appear anywhere in the msg
    if slug in ('add', 'delete'):
        return

    with db.cursor(password=bot.mysql_password) as c:
        c.execute('SELECT link FROM macros WHERE slug = %s', (slug, ))
        macro = c.fetchone()
        if macro is not None:
            msg.respond(macro['link'], ping=False)
        else:
            msg.respond('macro `{}` does not exist.'.format(slug))
Beispiel #22
0
def addmembers(bot, msg):
    """Add member(s) to a notification group."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        group = get_group(c, slug)
        if group is None:
            msg.respond('No such notification group.')
            return

        if not msg.is_oper and not is_owner(c, msg.respond, group, msg.nick):
            msg.respond(f'You can\'t add to {slug}, since you\'re neither an oper, nor an owner of the group.')
            return

        members = []
        if group['members'] is not None:
            members = group['members'].split(' ')
        owners = []
        if group['owners'] is not None:
            owners = group['owners'].split(' ')

        present = []
        added = []
        for nick in filter(lambda s: s != '', msg.match.group(2).split(' ')):
            if nick in members or nick in owners:
                present.append(nick)
            else:
                members.append(nick)
                added.append(nick)

        if len(present) > 0:
            present_str = ', '.join(present)
            was_plural = 'were' if len(present) > 1 else 'was'
            msg.respond(f'{present_str} {was_plural} already in {slug}.')

        if len(added) == 0:
            return

        c.execute(
            'UPDATE notify SET members = %s WHERE slug = %s',
            (' '.join(members), slug),
        )

        added_str = ', '.join(added)
        if len(added) > 1:
            msg.respond(f'{added_str} were added to {slug} as members.')
        else:
            msg.respond(f'{added_str} was added to {slug} as a member.')
Beispiel #23
0
def delete(bot, msg):
    """Delete a notifcation group."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        group = get_group(c, slug)
        if group is None:
            msg.respond('No such notification group.')
            return

        if not msg.is_oper and not is_owner(c, msg.respond, group, msg.nick):
            msg.respond(f'You can\'t delete {slug}, since you\'re neither an oper, nor an owner of the group.')
            return

        c.execute(
            'DELETE FROM notify WHERE slug = %s',
            (slug,),
        )
        msg.respond(f'{slug} has been deleted.')
Beispiel #24
0
def what_is(bot, msg):
    """Print out the current definition."""
    what_who, thing = msg.match.groups()

    # Special case: "who is in the lab" should be ignored
    if thing.startswith('in the lab'):
        return

    with db.cursor(password=bot.mysql_password) as c:
        c.execute(
            'SELECT * FROM what_is WHERE thing = %s',
            (thing,),
        )
        definition = c.fetchone()

    if definition is not None:
        msg.respond('{} is {}'.format(thing, definition['what_it_is']), ping=False)
    else:
        msg.respond('idk {} {} is'.format(what_who, thing), ping=False)
Beispiel #25
0
def clear(bot, msg):
    """Reset a notification group, clearing all members."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        group = get_group(c, slug)
        if group is None:
            msg.respond('No such notification group.')
            return

        if not msg.is_oper and not is_owner(c, msg.respond, group, msg.nick):
            msg.respond(f'You can\'t clear {slug}, since you\'re neither an oper, nor an owner of the group.')
            return

        c.execute(
            'UPDATE notify SET owners = %s, members = NULL WHERE slug = %s',
            (msg.nick, slug),
        )

        msg.respond(f'{slug} has been cleared. You are now the only owner, and there are no members.')
Beispiel #26
0
def show(bot, msg):
    """Show quote(s) by ID."""
    arg = msg.match.group(1).split()
    quote_ids = []

    for a in arg:
        try:
            quote_ids.append(int(a.lstrip('#')))
        except ValueError:
            msg.respond('Not a valid ID: {}'.format(a))
            break
    else:
        with db.cursor(password=bot.mysql_password) as c:
            for quote_id in quote_ids:
                c.execute(
                    'SELECT * FROM quotes WHERE id = %s and is_deleted = 0',
                    (quote_id, ))
                quote = c.fetchone()
                if quote is not None:
                    _print_quote(msg.respond, quote)
                else:
                    msg.respond('Quote #{} does not exist.'.format(quote_id))
Beispiel #27
0
def list_groups(bot, msg):
    """List all notification groups."""
    with db.cursor(password=bot.mysql_password) as c:
        c.execute('SELECT slug FROM notify')
        slugs = sorted([group['slug'] for group in c.fetchall()])
        msg.respond(' '.join(slugs))
Beispiel #28
0
def remove(bot, msg):
    """Remove targets from a notification group, for both owners and members."""
    slug = msg.match.group(1)
    with db.cursor(password=bot.mysql_password) as c:
        group = get_group(c, slug)
        if group is None:
            msg.respond('No such notification group.')
            return

        if not msg.is_oper and not is_owner(c, msg.respond, group, msg.nick):
            msg.respond(f'You can\'t remove from {slug}, since you\'re neither an oper, nor an owner of the group.')
            return

        members = group['members'] and group['members'].split(' ')
        owners = group['owners'] and group['owners'].split(' ')

        missing = []
        former_members = []
        former_owners = []
        for nick in filter(lambda s: s != '', msg.match.group(2).split(' ')):
            if members and nick in members:
                members.remove(nick)
                former_members.append(nick)
            elif owners and nick in owners:
                owners.remove(nick)
                former_owners.append(nick)
            else:
                missing.append(nick)

        if len(missing) > 0:
            missing_str = ', '.join(missing)
            was_plural = 'were' if len(missing) > 1 else 'was'
            msg.respond(f'{missing_str} {was_plural} not in {slug}.')

        if len(former_owners) == 0 and len(former_members) == 0:
            return

        sql_owners = owners
        if owners is not None:
            sql_owners = ' '.join(owners)
        sql_members = members
        if members is not None:
            sql_members = ' '.join(members)

        c.execute(
            'UPDATE notify SET owners = %s, members = %s WHERE slug = %s',
            (sql_owners, sql_members, slug),
        )

        if len(former_owners) > 0:
            owners_str = ', '.join(former_owners)
            if len(former_owners) > 1:
                msg.respond(f'{owners_str} were removed as owners of {slug}.')
            else:
                msg.respond(f'{owners_str} was removed as an owner of {slug}.')

        if len(former_members) > 0:
            members_str = ', '.join(former_members)
            if len(former_members) > 1:
                msg.respond(f'{members_str} were removed as members of {slug}.')
            else:
                msg.respond(f'{members_str} was removed as a member of {slug}.')