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
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
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)
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
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
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
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