Exemple #1
0
 def cmd_fact_edit(bot, trigger):
     if not option:
         bot.reply("Missing fact.")
         return NOLIMIT
     if '-' not in option:
         bot.reply(
             "Fact must include a language specifier.  (Perhaps you meant '{name}-{lang}'?)"
             .format(name=option, lang=bot.memory['ratfacts']['lang'][0]))
         return NOLIMIT
     name, lang = option.rsplit('-', 1)
     if command in ('add', 'set'):
         message = extra.strip() if extra else None
         if not message:
             bot.reply("Can't add a blank fact.")
             return NOLIMIT
         fact = db.merge(
             Fact(name=name,
                  lang=lang,
                  message=extra,
                  author=str(trigger.nick)))
         is_new = not inspect(fact).persistent
         db.commit()
         bot.reply(("Added " if is_new else "Updated ") + format_fact(fact))
         return NOLIMIT
     fact = Fact.find(db, name=name, lang=lang)
     if fact:
         db.delete(fact)
         db.commit()
         bot.reply("Deleted " + format_fact(fact))
     else:
         bot.reply("No such fact.")
     return NOLIMIT
Exemple #2
0
def find_fact(bot, text, exact=False, db=None):
    lang_search = bot.memory['ratfacts']['lang']

    fact = Fact.find(db, name=text, lang=lang_search[0] if exact else lang_search)
    if fact:
        return fact
    if '-' in text:
        name, lang = text.rsplit('-', 1)
        if not exact:
            lang = [lang] + lang_search
        return Fact.find(db, name=name, lang=lang)
    return None
Exemple #3
0
def find_fact(bot, text, exact=False, db=None):
    lang_search = bot.memory['ratfacts']['lang']

    fact = Fact.find(db,
                     name=text,
                     lang=lang_search[0] if exact else lang_search)
    if fact:
        return fact
    if '-' in text:
        name, lang = text.rsplit('-', 1)
        if not exact:
            lang = [lang] + lang_search
        return Fact.find(db, name=name, lang=lang)
    return None
Exemple #4
0
 def _gen(json):
     for k, v in json.items():
         if isinstance(v, dict):
             for name, message in v.items():
                 if isinstance(
                         message,
                         dict):  # New-style facts.json with attribution
                     yield Fact(name=name,
                                lang=k,
                                message=message['fact'],
                                author=message.get('author'))
                 else:  # Newer-style facts.json with language but not attribution -- or explicit deletion of fact.
                     yield Fact(name=name, lang=k, message=message)
         else:  # Old-style facts.json, single language
             yield Fact(name=k, lang=lang, message=v)
Exemple #5
0
 def cmd_fact_edit(bot, trigger):
     if not option:
         bot.reply("Missing fact.")
         return NOLIMIT
     if '-' not in option:
         bot.reply(
             "Fact must include a language specifier.  (Perhaps you meant '{name}-{lang}'?)"
                 .format(name=option, lang=bot.memory['ratfacts']['lang'][0])
         )
         return NOLIMIT
     name, lang = option.rsplit('-', 1)
     if command in ('add', 'set'):
         message = extra.strip() if extra else None
         if not message:
             bot.reply("Can't add a blank fact.")
             return NOLIMIT
         fact = db.merge(Fact(name=name, lang=lang, message=extra, author=str(trigger.nick)))
         is_new = not inspect(fact).persistent
         db.commit()
         bot.reply(("Added " if is_new else "Updated ") + format_fact(fact))
         return NOLIMIT
     fact = Fact.find(db, name=name, lang=lang)
     if fact:
         db.delete(fact)
         db.commit()
         bot.reply("Deleted " + format_fact(fact))
     else:
         bot.reply("No such fact.")
     return NOLIMIT
Exemple #6
0
 def cmd_fact_full(bot, trigger):
     if not trigger.is_privmsg:
         bot.reply("Messaging you the complete fact database.")
     pm("Language search order is {}".format(", ".join(bot.memory['ratfacts']['lang'])))
     for fact in Fact.findall(db):
         pm(format_fact(fact))
     pm("-- End of list --")
     return NOLIMIT
Exemple #7
0
def cmd_fact(bot, trigger, db=None):
    """
    Lists known facts, list details on a fact, or rescans the fact database.

    !fact - Lists all known facts
    !fact FACT [full] - Shows detailed stats on the specified fact.  'full' dumps all translations to a PM.
    !fact LANGUAGE [full] - Shows detailed stats on the specified language.  'full' dumps all facts to a PM.

    The following commands require privileges:
    !fact import [-f] - Reimports JSON data.  -f overwrites existing rows.
    !fact add <id> <text> - Creates a new fact or updates an existing one.  <id> must be of the format <factname>-<lang>
        Aliases: set
    !fact del <id> <text> - Deletes a fact.  <id> must be of the format <factname>-<lang>
        Aliases: delete remove
    """
    pm = functools.partial(bot.say, destination=trigger.nick)
    parts = re.split(r'\s+', trigger.group(2),
                     maxsplit=2) if trigger.group(2) else None
    command = parts.pop(0).lower() if parts else None
    option = parts.pop(0).lower() if parts else None
    extra = parts[0] if parts else None

    if not command:
        # List known facts.
        unique_facts = list(Fact.unique_names(db))
        if not unique_facts:
            return bot.reply(
                "Like Jon Snow, I know nothing.  (Or there's a problem with the fact database.)"
            )
        line = "{} known fact(s): {}".format(len(unique_facts),
                                             ", ".join(unique_facts))
        if len(line) > 400:
            lines = textwrap.wrap(line, 400, break_long_words=False)
            for l in lines:
                bot.say(l)
            return
        return bot.say(line)

    @require_overseer(
        'Sorry, but you need to be an overseer or higher to execute this command.'
    )
    def cmd_fact_import(bot, trigger):
        import_facts(bot, merge=(option == '-f'))
        return bot.say("Facts imported.")

    if command == 'import':
        return cmd_fact_import(bot, trigger)

    @require_overseer(
        'Sorry, but you need to be an overseer or higher to execute this command.'
    )
    def cmd_fact_edit(bot, trigger):
        if not option:
            bot.reply("Missing fact.")
            return NOLIMIT
        if '-' not in option:
            bot.reply(
                "Fact must include a language specifier.  (Perhaps you meant '{name}-{lang}'?)"
                .format(name=option, lang=bot.memory['ratfacts']['lang'][0]))
            return NOLIMIT
        name, lang = option.rsplit('-', 1)
        if command in ('add', 'set'):
            message = extra.strip() if extra else None
            if not message:
                bot.reply("Can't add a blank fact.")
                return NOLIMIT
            fact = db.merge(
                Fact(name=name,
                     lang=lang,
                     message=extra,
                     author=str(trigger.nick)))
            is_new = not inspect(fact).persistent
            db.commit()
            bot.reply(("Added " if is_new else "Updated ") + format_fact(fact))
            return NOLIMIT
        fact = Fact.find(db, name=name, lang=lang)
        if fact:
            db.delete(fact)
            db.commit()
            bot.reply("Deleted " + format_fact(fact))
        else:
            bot.reply("No such fact.")
        return NOLIMIT

    if command in ('add', 'set', 'del', 'delete', 'remove'):
        return cmd_fact_edit(bot, trigger)

    def _translation_stats(exists, missing, s='translation', p='translations'):
        if exists:
            exists = "{count} {word} ({names})".format(
                count=len(exists),
                word=s if len(exists) == 1 else p,
                names=", ".join(sorted(exists)))
        else:
            exists = "no " + p
        if missing:
            missing = "missing {count} ({names})".format(count=len(missing),
                                                         names=", ".join(
                                                             sorted(missing)))
        else:
            missing = "none missing"
        return exists + ", " + missing

    # See if it's the name of a fact or a lang
    full = option == 'full'
    for attr, opposite, name, opposite_name_s, opposite_name_p in [
        ('name', 'lang', 'fact', 'translation', 'translations'),
        ('lang', 'name', 'language', 'fact', 'facts')
    ]:
        if not db.query(
                Fact.query(db, order_by=False, **{
                    attr: command
                }).exists()).scalar():
            continue
        sq = Fact.unique_query(db,
                               field=getattr(Fact, opposite),
                               order_by=False).subquery()
        sq_opp = getattr(sq.c, opposite)
        fact_opp = getattr(Fact, opposite)
        fact_col = getattr(Fact, attr)

        query = (db.query(Fact, sq_opp).select_from(
            sq.outerjoin(Fact, (sq_opp == fact_opp) &
                         (fact_col == command))).order_by(
                             Fact.message.is_(None), sq_opp))
        exists = set()
        missing = set()
        if full:
            if not trigger.is_privmsg:
                bot.reply("Messaging you what I know about {} '{}'".format(
                    name, command))
            pm("Fact search for {} '{}'".format(name, command))

        for fact, key in query:
            if fact and full:
                pm(format_fact(fact))
            (exists if fact else missing).add(key)

        summary = ("{} '{}': ".format(name.title(), command) +
                   _translation_stats(
                       exists, missing, s=opposite_name_s, p=opposite_name_p))
        if full:
            lines = textwrap.wrap(summary, 400, break_long_words=False)
            for l in lines:
                pm(l)
            return NOLIMIT
        else:
            lines = textwrap.wrap(summary, 400, break_long_words=False)
            for l in lines:
                bot.say(l)
            return NOLIMIT

    bot.reply(
        "'{}' is not a known fact, language, or subcommand".format(command))
    return NOLIMIT
Exemple #8
0
def cmd_fact(bot, trigger, db=None):
    """
    Lists known facts, list details on a fact, or rescans the fact database.

    !fact - Lists all known facts
    !fact FACT [full] - Shows detailed stats on the specified fact.  'full' dumps all translations to a PM.
    !fact LANGUAGE [full] - Shows detailed stats on the specified language.  'full' dumps all facts to a PM.

    The following commands require privileges:
    !fact import [-f] - Reimports JSON data.  -f overwrites existing rows.
    !fact full - Dumps all facts, all languages to a PM.
    !fact add <id> <text> - Creates a new fact or updates an existing one.  <id> must be of the format <factname>-<lang>
        Aliases: set
    !fact del <id> <text> - Deletes a fact.  <id> must be of the format <factname>-<lang>
        Aliases: delete remove
    """
    pm = functools.partial(bot.say, destination=trigger.nick)
    parts = re.split(r'\s+', trigger.group(2), maxsplit=2) if trigger.group(2) else None
    command = parts.pop(0).lower() if parts else None
    option = parts.pop(0).lower() if parts else None
    extra = parts[0] if parts else None

    if not command:
        # List known facts.
        unique_facts = list(Fact.unique_names(db))
        if not unique_facts:
            return bot.reply("Like Jon Snow, I know nothing.  (Or there's a problem with the fact database.)")
        return bot.say("{} known fact(s): {}".format(len(unique_facts), ", ".join(unique_facts)))

    @require_overseer('Sorry, but you need to be an overseer or higher to execute this command.')
    def cmd_fact_import(bot, trigger):
        import_facts(bot, merge=(option == '-f'))
        return bot.say("Facts imported.")

    if command == 'import':
        return cmd_fact_import(bot, trigger)

    @require_overseer('Sorry, but you need to be an overseer or higher to execute this command.')
    def cmd_fact_full(bot, trigger):
        if not trigger.is_privmsg:
            bot.reply("Messaging you the complete fact database.")
        pm("Language search order is {}".format(", ".join(bot.memory['ratfacts']['lang'])))
        for fact in Fact.findall(db):
            pm(format_fact(fact))
        pm("-- End of list --")
        return NOLIMIT

    if command == 'full':
        return cmd_fact_full(bot, trigger)

    @require_overseer('Sorry, but you need to be an overseer or higher to execute this command.')
    def cmd_fact_edit(bot, trigger):
        if not option:
            bot.reply("Missing fact.")
            return NOLIMIT
        if '-' not in option:
            bot.reply(
                "Fact must include a language specifier.  (Perhaps you meant '{name}-{lang}'?)"
                    .format(name=option, lang=bot.memory['ratfacts']['lang'][0])
            )
            return NOLIMIT
        name, lang = option.rsplit('-', 1)
        if command in ('add', 'set'):
            message = extra.strip() if extra else None
            if not message:
                bot.reply("Can't add a blank fact.")
                return NOLIMIT
            fact = db.merge(Fact(name=name, lang=lang, message=extra, author=str(trigger.nick)))
            is_new = not inspect(fact).persistent
            db.commit()
            bot.reply(("Added " if is_new else "Updated ") + format_fact(fact))
            return NOLIMIT
        fact = Fact.find(db, name=name, lang=lang)
        if fact:
            db.delete(fact)
            db.commit()
            bot.reply("Deleted " + format_fact(fact))
        else:
            bot.reply("No such fact.")
        return NOLIMIT

    if command in ('add', 'set', 'del', 'delete', 'remove'):
        return cmd_fact_edit(bot, trigger)

    def _translation_stats(exists, missing, s='translation', p='translations'):
        if exists:
            exists = "{count} {word} ({names})".format(
                count=len(exists), word=s if len(exists) == 1 else p, names=", ".join(sorted(exists))
            )
        else:
            exists = "no " + p
        if missing:
            missing = "missing {count} ({names})".format(count=len(missing), names=", ".join(sorted(missing)))
        else:
            missing = "none missing"
        return exists + ", " + missing

    # See if it's the name of a fact or a lang
    full = option == 'full'
    for attr, opposite, name, opposite_name_s, opposite_name_p in [
        ('name', 'lang', 'fact', 'translation', 'translations'),
        ('lang', 'name', 'language', 'fact', 'facts')
    ]:
        if not db.query(Fact.query(db, order_by=False, **{attr: command}).exists()).scalar():
            continue
        sq = Fact.unique_query(db, field=getattr(Fact, opposite), order_by=False).subquery()
        sq_opp = getattr(sq.c, opposite)
        fact_opp = getattr(Fact, opposite)
        fact_col = getattr(Fact, attr)

        query = (
            db.query(Fact, sq_opp)
                .select_from(sq.outerjoin(Fact, (sq_opp == fact_opp) & (fact_col == command)))
                .order_by(Fact.message.is_(None), sq_opp)
        )
        exists = set()
        missing = set()
        if full:
            if not trigger.is_privmsg:
                bot.reply("Messaging you what I know about {} '{}'".format(name, command))
            pm("Fact search for {} '{}'".format(name, command))

        for fact, key in query:
            if fact and full:
                pm(format_fact(fact))
            (exists if fact else missing).add(key)

        summary = (
            "{} '{}': ".format(name.title(), command) +
            _translation_stats(exists, missing, s=opposite_name_s, p=opposite_name_p)
        )
        if full:
            pm(summary)
            return NOLIMIT
        else:
            bot.say(summary)
            return NOLIMIT

    bot.reply("'{}' is not a known fact, language, or subcommand".format(command))
    return NOLIMIT