def usaco_account(self, event, user, usaco_user, password): if password: self._redact(event, password) if event.public and password: event.addresponse(u"Giving your password in public is bad! Please tell me that again in a private message.") return if not event.account: event.addresponse(u'Sorry, you need to create an account with me first (type "usage accounts" to see how)') return admin = auth_responses(event, u'usacoadmin') if user.lower() == 'i': if password is None and not admin: event.addresponse(u'Sorry, I need your USACO password to verify your account') if password and not self._check_login(user, password): event.addresponse(u'Sorry, that account is invalid') return account = event.session.query(Account).get(event.account) else: if not admin: event.addresponse(event.complain) return account = event.session.query(Account).filter_by(username=user).first() if account is None: event.addresponse(u"I don't know who %s is", user) return try: monitor_url = self._get_monitor_url() except UsacoException, e: event.addresponse(e) return
def remove(self, event, user, source, username): if not username: account = event.session.query(Account).get(event.account) else: if not auth_responses(event, "accounts"): return account = event.session.query(Account).filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return identity = event.session.query(Identity).filter_by(account_id=account.id, identity=user, source=source).first() if not identity: event.addresponse(u"I don't know about that identity") else: identity.account_id = None event.session.add(identity) event.session.commit() identify_cache.clear() event.addresponse(True) log.info( u"Removed identity %s (%s on %s) from account %s (%s) by %s/%s (%s)", identity.id, identity.identity, identity.source, account.id, account.username, event.account, event.identity, event.sender["connection"], )
def attribute(self, event, username, name, value): if username.lower() == "my": if not event.account: event.addresponse(u"I don't know who you are") return account = event.session.query(Account).get(event.account) if not account: event.addresponse(u"%s doesn't exist. Please use 'add account' first", username) return else: if not auth_responses(event, "accounts"): return account = event.session.query(Account).filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return account.attributes.append(Attribute(name, value)) event.session.add(account) event.session.commit() event.addresponse(True) log.info( u"Added attribute '%s' = '%s' to account %s (%s) by %s/%s (%s)", name, value, account.id, account.username, event.account, event.identity, event.sender["connection"], )
def remove(self, event, user, source, username): if not username: account = event.session.query(Account).get(event.account) else: if not auth_responses(event, 'accounts'): return account = event.session.query(Account) \ .filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return identity = event.session.query(Identity) \ .filter_by(account_id=account.id, identity=user, source=source).first() if not identity: event.addresponse(u"I don't know about that identity") else: identity.account_id = None event.session.save_or_update(identity) event.session.commit() identify_cache.clear() event.addresponse(True) log.info( u"Removed identity %s (%s on %s) from account %s (%s) by %s/%s (%s)", identity.id, identity.identity, identity.source, account.id, account.username, event.account, event.identity, event.sender['connection'])
def attribute(self, event, username, name, value): if username.lower() == 'my': if not event.account: event.addresponse(u"I don't know who you are") return account = event.session.query(Account).get(event.account) if not account: event.addresponse( u"%s doesn't exist. Please use 'add account' first", username) return else: if not auth_responses(event, 'accounts'): return account = event.session.query(Account) \ .filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return account.attributes.append(Attribute(name, value)) event.session.save_or_update(account) event.session.commit() event.addresponse(True) log.info( u"Added attribute '%s' = '%s' to account %s (%s) by %s/%s (%s)", name, value, account.id, account.username, event.account, event.identity, event.sender['connection'])
def set_factoid(self, event, correction, name, addition1, verb1, verb2, addition2, value): verb = verb1 or verb2 addition = addition1 or addition2 name = strip_name(name) if name == u'': event.addresponse(u"Sorry, I'm not interested in empty factoids") return if name.lower() in self.interrogatives: event.addresponse( choice(( u"I'm afraid I have no idea", u"Not a clue, sorry", u"Erk, dunno", ))) return factoid = event.session.query(Factoid).join(Factoid.names)\ .filter(FactoidName.name==escape_name(name)).first() if factoid: if correction: identities = get_identities(event) if not auth_responses(event, u'factoidadmin') and len( filter(lambda x: x.identity_id not in identities, factoid.values)) > 0: return for fvalue in factoid.values: event.session.delete(fvalue) elif not addition: event.addresponse(u'I already know stuff about %s', name) return else: factoid = Factoid() fname = FactoidName(unicode(name), event.identity) factoid.names.append(fname) event.session.add(factoid) event.session.flush() log.info(u"Creating factoid %s with name '%s' by %s", factoid.id, fname.name, event.identity) if not reply_re.match(value) and not action_re.match(value): value = '%s %s' % (verb, value) fvalue = FactoidValue(unicode(value), event.identity) factoid.values.append(fvalue) event.session.add(factoid) event.session.commit() self.last_set_factoid = factoid.names[0].name log.info(u"Added value '%s' to factoid %s (%s) by %s/%s (%s)", fvalue.value, factoid.id, factoid.names[0].name, event.account, event.identity, event.sender['connection']) event.addresponse( choice(( u'If you say so', u'One learns a new thing every day', u"I'll remember that", u'Got it', )))
def get(self, event, key): if 'password' in key.lower() and not auth_responses(event, u'config'): return option = self.find_option(key) if isinstance(option, dict): config = option key = '' elif option is not None: config = option[0].__get__(option[1], type(option[1])) key = option[2] elif key == 'plugins': # Construct a dictionary since this isn't a list-valued option, # but a list of option keys. config = dict((plugin, None) for plugin in list_plugins()) key = '' elif key == 'sources': config = ibid.sources key = '' else: config = ibid.config if key: for part in key.split('.'): if not isinstance(config, dict) or part not in config: event.addresponse(u'No such option') return config = config[part] if isinstance(config, list): event.addresponse(u', '.join(config)) elif isinstance(config, dict): event.addresponse(u'Keys: ' + human_join(config.keys())) else: event.addresponse(unicode(config))
def set_factoid(self, event, correction, name, addition1, verb1, verb2, addition2, value): verb = verb1 or verb2 addition = addition1 or addition2 name = strip_name(name) if name == u'': event.addresponse(u"Sorry, I'm not interested in empty factoids") return if name.lower() in self.interrogatives: event.addresponse(choice(( u"I'm afraid I have no idea", u"Not a clue, sorry", u"Erk, dunno", ))) return factoid = event.session.query(Factoid).join(Factoid.names)\ .filter(FactoidName.name==escape_name(name)).first() if factoid: if correction: identities = get_identities(event) if not auth_responses(event, u'factoidadmin') and len(filter(lambda x: x.identity_id not in identities, factoid.values)) > 0: return for fvalue in factoid.values: event.session.delete(fvalue) elif not addition: event.addresponse(u'I already know stuff about %s', name) return else: factoid = Factoid() fname = FactoidName(unicode(name), event.identity) factoid.names.append(fname) event.session.save_or_update(factoid) event.session.flush() log.info(u"Creating factoid %s with name '%s' by %s", factoid.id, fname.name, event.identity) if not reply_re.match(value) and not action_re.match(value): value = '%s %s' % (verb, value) fvalue = FactoidValue(unicode(value), event.identity) factoid.values.append(fvalue) event.session.save_or_update(factoid) event.session.commit() self.last_set_factoid=factoid.names[0].name log.info(u"Added value '%s' to factoid %s (%s) by %s/%s (%s)", fvalue.value, factoid.id, factoid.names[0].name, event.account, event.identity, event.sender['connection']) event.addresponse(choice(( u'If you say so', u'One learns a new thing every day', u"I'll remember that", u'Got it', )))
def append(self, event, name, number, pattern, is_regex, suffix): name = strip_name(name) factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True, literal=True) if len(factoids) == 0: if pattern: event.addresponse( u"I don't know about any %(name)s matching %(pattern)s", { 'name': name, 'pattern': pattern, }) else: factoids = get_factoid(event.session, name, None, pattern, is_regex, all=True) if factoids: event.addresponse( u"I only know %(number)d things about %(name)s", { u'number': len(factoids), u'name': name, }) else: event.addresponse(u"I don't know about %s", name) elif len(factoids) > 1 and number is None: event.addresponse( u"Pattern matches multiple factoids, please be more specific") else: factoidadmin = auth_responses(event, u'factoidadmin') identities = get_identities(event) factoid = factoids[0] if factoid[2].identity_id not in identities and not factoidadmin: return oldvalue = factoid[2].value factoid[2].value += suffix event.session.add(factoid[2]) event.session.commit() log.info( u"Appended '%s' to value %s (%s) of factoid %s (%s) by %s/%s (%s)", suffix, factoid[2].id, oldvalue, factoid[0].id, factoid[0].names[0].name, event.account, event.identity, event.sender['connection']) event.addresponse(True)
def handler(self, event, user, source, method, credential): if user.lower() == "me": if not event.account: event.addresponse(u"I don't know who you are") return if not ibid.auth.authenticate(event): event.complain = "notauthed" return account = event.session.query(Account).get(event.account) else: if not auth_responses(event, "admin"): return account = event.session.query(Account).filter_by(username=user).first() if not account: event.addresponse(u"I don't know who %s is", user) return if source: if source not in ibid.sources: event.addresponse(u"I am not connected to %s", source) return source = ibid.sources[source].name if method.lower() == "password": password = hash(credential) event.message["clean"] = event.message["clean"][: -len(credential)] + password event.message["raw"] = ( event.message["raw"][: event.message["raw"].rfind(credential)] + password + event.message["raw"][event.message["raw"].rfind(credential) + len(credential) :] ) credential = password credential = Credential(method, credential, source, account.id) event.session.add(credential) event.session.commit() log.info( u"Added %s credential %s for account %s (%s) on %s by account %s", method, credential.credential, account.id, account.username, source, event.account, ) event.addresponse(True)
def get(self, event, key): if 'password' in key.lower() and not auth_responses(event, u'config'): return config = ibid.config for part in key.split('.'): if not isinstance(config, dict) or part not in config: event.addresponse(u'No such option') return config = config[part] if isinstance(config, list): event.addresponse(u', '.join(config)) elif isinstance(config, dict): event.addresponse(u'Keys: ' + human_join(config.keys())) else: event.addresponse(unicode(config))
def list(self, event, username): if not username: if not event.account: event.addresponse(u"I don't know who you are") return account = event.session.query(Account).get(event.account) else: if not auth_responses(event, u"accounts"): return account = event.session.query(Account).filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return permissions = sorted(u"%s%s" % (permission_values[perm.value], perm.name) for perm in account.permissions) event.addresponse(u"Permissions: %s", human_join(permissions) or u"none")
def list(self, event, username): if not username: if not event.account: event.addresponse(u"I don't know who you are") return account = event.session.query(Account).get(event.account) else: if not auth_responses(event, u'accounts'): return account = event.session.query(Account) \ .filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return permissions = sorted(u'%s%s' % (permission_values[perm.value], perm.name) for perm in account.permissions) event.addresponse(u'Permissions: %s', human_join(permissions) or u'none')
def handler(self, event, user, source, method, credential): if user.lower() == 'me': if not event.account: event.addresponse(u"I don't know who you are") return if not ibid.auth.authenticate(event): event.complain = 'notauthed' return account = event.session.query(Account).get(event.account) else: if not auth_responses(event, 'admin'): return account = event.session.query(Account).filter_by( username=user).first() if not account: event.addresponse(u"I don't know who %s is", user) return if source: if source not in ibid.sources: event.addresponse(u"I am not connected to %s", source) return source = ibid.sources[source].name if method.lower() == 'password': password = hash(credential) event.message[ 'clean'] = event.message['clean'][:-len(credential)] + password event.message['raw'] = event.message['raw'][:event.message['raw'].rfind(credential)] \ + password + event.message['raw'][event.message['raw'].rfind(credential)+len(credential):] credential = password credential = Credential(method, credential, source, account.id) event.session.save_or_update(credential) event.session.commit() log.info( u"Added %s credential %s for account %s (%s) on %s by account %s", method, credential.credential, account.id, account.username, source, event.account) event.addresponse(True)
def append(self, event, name, number, pattern, is_regex, suffix): name = strip_name(name) factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True, literal=True) if len(factoids) == 0: if pattern: event.addresponse(u"I don't know about any %(name)s matching %(pattern)s", { 'name': name, 'pattern': pattern, }) else: factoids = get_factoid(event.session, name, None, pattern, is_regex, all=True) if factoids: event.addresponse(u"I only know %(number)d things about %(name)s", { u'number': len(factoids), u'name': name, }) else: event.addresponse(u"I don't know about %s", name) elif len(factoids) > 1 and number is None: event.addresponse(u"Pattern matches multiple factoids, please be more specific") else: factoidadmin = auth_responses(event, u'factoidadmin') identities = get_identities(event) factoid = factoids[0] if factoid[2].identity_id not in identities and not factoidadmin: return oldvalue = factoid[2].value factoid[2].value += suffix event.session.add(factoid[2]) event.session.commit() log.info(u"Appended '%s' to value %s (%s) of factoid %s (%s) by %s/%s (%s)", suffix, factoid[2].id, oldvalue, factoid[0].id, factoid[0].names[0].name, event.account, event.identity, event.sender['connection']) event.addresponse(True)
def identity(self, event, username, identity, source): admin = False identity = identity.replace(' ', '') reverse_attach = False if username is None: if event.account: account = event.session.query(Account).get(event.account) else: account = event.session.query(Account) \ .join('identities') \ .filter(Identity.identity == identity) \ .filter(Identity.source == source).first() if account: reverse_attach = True else: username = event.sender['id'] account = event.session.query(Account) \ .filter_by(username=username).first() if account: event.addresponse(u'I tried to create the account %s for you, but it already exists. ' u"Please use 'create account <name>'", username) return account = Account(username) event.session.save_or_update(account) currentidentity = event.session.query(Identity) \ .get(event.identity) currentidentity.account_id = account.id event.session.save_or_update(currentidentity) identify_cache.clear() event.addresponse(u"I've created the account %s for you", username) event.session.commit() log.info(u"Created account %s (%s) by %s/%s (%s)", account.id, account.username, event.account, event.identity, event.sender['connection']) log.info(u"Attached identity %s (%s on %s) to account %s (%s)", currentidentity.id, currentidentity.identity, currentidentity.source, account.id, account.username) else: if not auth_responses(event, 'accounts'): return admin = True account = event.session.query(Account) \ .filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return if reverse_attach: ident = event.session.query(Identity).get(event.identity) else: ident = event.session.query(Identity) \ .filter_by(identity=identity, source=source).first() if ident and ident.account: event.addresponse(u'This identity is already attached to account %s', ident.account.username) return if source not in ibid.sources: event.addresponse(u'I am not connected to %s', source) return else: source = ibid.sources[source].name if not admin: token = ''.join([choice(chars) for i in xrange(16)]) if reverse_attach: self.tokens[token] = (account.id, ident.identity, ident.source) response = { 'reply': u'Please send me this message from %s on %s: %s' % (ident.identity, ident.source, token), 'target': identity, 'source': source, } event.addresponse(True) else: self.tokens[token] = (account.id, identity, source) response = {'reply': u'Please send me this message from %s on %s: %s' % (identity, source, token)} if event.public: response['target'] = event.sender['id'] event.addresponse(True) event.addresponse(response) log.info(u"Sent token %s to %s/%s (%s)", token, event.account, event.identity, event.sender['connection']) else: if not ident: ident = Identity(source, identity) ident.account_id = account.id event.session.save_or_update(ident) event.session.commit() identify_cache.clear() event.addresponse(True) log.info(u"Attached identity %s (%s on %s) to account %s (%s) by %s/%s (%s)", ident.id, ident.identity, ident.source, account.id, account.username, event.account, event.identity, event.sender['connection'])
def identity(self, event, username, identity, source): admin = False identity = identity.replace(" ", "") reverse_attach = False if username is None: if event.account: account = event.session.query(Account).get(event.account) else: account = ( event.session.query(Account) .join("identities") .filter(Identity.identity == identity) .filter(Identity.source == source) .first() ) if account: reverse_attach = True else: username = event.sender["id"] account = event.session.query(Account).filter_by(username=username).first() if account: event.addresponse( u"I tried to create the account %s for you, but it already exists. " u"Please use 'create account <name>'", username, ) return account = Account(username) event.session.add(account) currentidentity = event.session.query(Identity).get(event.identity) currentidentity.account_id = account.id event.session.add(currentidentity) identify_cache.clear() event.addresponse(u"I've created the account %s for you", username) event.session.commit() log.info( u"Created account %s (%s) by %s/%s (%s)", account.id, account.username, event.account, event.identity, event.sender["connection"], ) log.info( u"Attached identity %s (%s on %s) to account %s (%s)", currentidentity.id, currentidentity.identity, currentidentity.source, account.id, account.username, ) else: if not auth_responses(event, "accounts"): return admin = True account = event.session.query(Account).filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return if reverse_attach: ident = event.session.query(Identity).get(event.identity) else: ident = event.session.query(Identity).filter_by(identity=identity, source=source).first() if ident and ident.account: event.addresponse(u"This identity is already attached to account %s", ident.account.username) return if source not in ibid.sources: event.addresponse(u"I am not connected to %s", source) return else: source = ibid.sources[source].name if not admin: token = "".join([choice(chars) for i in xrange(16)]) if reverse_attach: self.tokens[token] = (account.id, ident.identity, ident.source) response = { "reply": u"Please send me this message from %s on %s: %s" % (ident.identity, ident.source, token), "target": identity, "source": source, } event.addresponse(True) else: self.tokens[token] = (account.id, identity, source) response = {"reply": u"Please send me this message from %s on %s: %s" % (identity, source, token)} if event.public: response["target"] = event.sender["id"] event.addresponse(True) event.addresponse(response) log.info(u"Sent token %s to %s/%s (%s)", token, event.account, event.identity, event.sender["connection"]) else: if not ident: ident = Identity(source, identity) ident.account_id = account.id event.session.add(ident) event.session.commit() identify_cache.clear() event.addresponse(True) log.info( u"Attached identity %s (%s on %s) to account %s (%s) by %s/%s (%s)", ident.id, ident.identity, ident.source, account.id, account.username, event.account, event.identity, event.sender["connection"], )
def identity(self, event, username, identity, source): admin = False identity = identity.replace(' ', '') reverse_attach = False if username is None: if event.account: account = event.session.query(Account).get(event.account) else: account = event.session.query(Account) \ .join('identities') \ .filter(Identity.identity == identity) \ .filter(Identity.source == source).first() if account: reverse_attach = True else: username = event.sender['id'] account = event.session.query(Account) \ .filter_by(username=username).first() if account: event.addresponse( u'I tried to create the account %s for you, but it already exists. ' u"Please use 'create account <name>'", username) return account = Account(username) event.session.save_or_update(account) currentidentity = event.session.query(Identity) \ .get(event.identity) currentidentity.account_id = account.id event.session.save_or_update(currentidentity) identify_cache.clear() event.addresponse(u"I've created the account %s for you", username) event.session.commit() log.info(u"Created account %s (%s) by %s/%s (%s)", account.id, account.username, event.account, event.identity, event.sender['connection']) log.info( u"Attached identity %s (%s on %s) to account %s (%s)", currentidentity.id, currentidentity.identity, currentidentity.source, account.id, account.username) else: if not auth_responses(event, 'accounts'): return admin = True account = event.session.query(Account) \ .filter_by(username=username).first() if not account: event.addresponse(u"I don't know who %s is", username) return if reverse_attach: ident = event.session.query(Identity).get(event.identity) else: ident = event.session.query(Identity) \ .filter_by(identity=identity, source=source).first() if ident and ident.account: event.addresponse( u'This identity is already attached to account %s', ident.account.username) return if source not in ibid.sources: event.addresponse(u'I am not connected to %s', source) return else: source = ibid.sources[source].name if not admin: token = ''.join([choice(chars) for i in xrange(16)]) if reverse_attach: self.tokens[token] = (account.id, ident.identity, ident.source) response = { 'reply': u'Please send me this message from %s on %s: %s' % (ident.identity, ident.source, token), 'target': identity, 'source': source, } event.addresponse(True) else: self.tokens[token] = (account.id, identity, source) response = { 'reply': u'Please send me this message from %s on %s: %s' % (identity, source, token) } if event.public: response['target'] = event.sender['id'] event.addresponse(True) event.addresponse(response) log.info(u"Sent token %s to %s/%s (%s)", token, event.account, event.identity, event.sender['connection']) else: if not ident: ident = Identity(source, identity) ident.account_id = account.id event.session.save_or_update(ident) event.session.commit() identify_cache.clear() event.addresponse(True) log.info( u"Attached identity %s (%s on %s) to account %s (%s) by %s/%s (%s)", ident.id, ident.identity, ident.source, account.id, account.username, event.account, event.identity, event.sender['connection'])
def modify(self, event, name, number, pattern, is_regex, operation, sep): factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True) if len(factoids) == 0: if pattern: event.addresponse(u"I don't know about any %(name)s matching %(pattern)s", { 'name': name, 'pattern': pattern, }) else: event.addresponse(u"I don't know about %s", name) elif len(factoids) > 1: event.addresponse(u"Pattern matches multiple factoids, please be more specific") else: factoidadmin = auth_responses(event, u'factoidadmin') identities = get_identities(event) factoid = factoids[0] if factoid[2].identity_id not in identities and not factoidadmin: return # Not very pythonistic, but escaping is a nightmare. separator = sep parts = [[]] pos = 0 while pos < len(operation): char = operation[pos] if char == separator: parts.append([]) elif char == u"\\": if pos < len(operation) - 1: if operation[pos+1] == u"\\": parts[-1].append(u"\\") pos += 1 elif operation[pos+1] == separator: parts[-1].append(separator) pos += 1 else: parts[-1].append(u"\\") else: parts[-1].append(u"\\") else: parts[-1].append(char) pos += 1 parts = [u"".join(x) for x in parts] if len(parts) != 4: event.addresponse(u"That operation makes no sense. Try something like s/foo/bar/") return oldvalue = factoid[2].value op, search, replace, flags = parts flags = flags.lower() if op == "s": if "r" not in flags: plain_search = search search = re.escape(search) replace = replace.replace('\\', '\\\\') if "i" in flags: search += "(?i)" try: if "r" not in flags and not re.search(search, oldvalue): event.addresponse(u"I couldn't find '%(terms)s' in " u"'%(oldvalue)s'. If that was a " u"proper regular expression, append " u"the 'r' flag", { 'terms': plain_search, 'oldvalue': oldvalue, }) return factoid[2].value = re.sub(search, replace, oldvalue, int("g" not in flags)) except: event.addresponse(u"That operation makes no sense. Try something like s/foo/bar/") return elif op == "y": if len(search) != len(replace): event.addresponse(u"That operation makes no sense. The source and destination must be the same length") return try: table = dict((ord(x), ord(y)) for x, y in zip(search, replace)) factoid[2].value = oldvalue.translate(table) except: event.addresponse(u"That operation makes no sense. Try something like y/abcdef/ABCDEF/") return event.session.save_or_update(factoid[2]) event.session.commit() log.info(u"Applying '%s' to value %s of factoid %s (%s) by %s/%s (%s)", operation, factoid[2].id, factoid[0].id, oldvalue, event.account, event.identity, event.sender['connection']) event.addresponse(True)
def forget(self, event, name, number, pattern, is_regex): factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True, literal=True) if factoids: factoidadmin = auth_responses(event, u'factoidadmin') identities = get_identities(event) factoid = event.session.query(Factoid).get(factoids[0][0].id) if len(factoids) > 1 and pattern is not None: event.addresponse(u'Pattern matches multiple factoids, please be more specific') return if number or pattern: if factoids[0][2].identity_id not in identities and not factoidadmin: return if event.session.query(FactoidValue).filter_by(factoid_id=factoid.id).count() == 1: if len(filter(lambda x: x.identity_id not in identities, factoid.names)) > 0 and not factoidadmin: return id = factoid.id event.session.delete(factoid) event.session.commit() log.info(u"Deleted factoid %s (%s) by %s/%s (%s)", id, name, event.account, event.identity, event.sender['connection']) else: id = factoids[0][2].id event.session.delete(factoids[0][2]) event.session.commit() log.info(u"Deleted value %s (%s) of factoid %s (%s) by %s/%s (%s)", id, factoids[0][2].value, factoid.id, name, event.account, event.identity, event.sender['connection']) else: if factoids[0][1].identity_id not in identities and not factoidadmin: return if event.session.query(FactoidName).filter_by(factoid_id=factoid.id).count() == 1: if len(filter(lambda x: x.identity_id not in identities, factoid.values)) > 0 and not factoidadmin: return id = factoid.id event.session.delete(factoid) event.session.commit() log.info(u"Deleted factoid %s (%s) by %s/%s (%s)", id, name, event.account, event.identity, event.sender['connection']) else: id = factoids[0][1].id event.session.delete(factoids[0][1]) event.session.commit() log.info(u"Deleted name %s (%s) of factoid %s (%s) by %s/%s (%s)", id, factoids[0][1].name, factoid.id, factoids[0][0].names[0].name, event.account, event.identity, event.sender['connection']) event.addresponse(True) else: factoids = get_factoid(event.session, name, None, pattern, is_regex, all=True, literal=True) if factoids: event.addresponse(u"I only know %(number)d things about %(name)s", { u'number': len(factoids), u'name': name, }) else: event.addresponse(u"I didn't know about %s anyway", name)
def modify(self, event, name, number, pattern, is_regex, operation, sep): factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True) if len(factoids) == 0: if pattern: event.addresponse( u"I don't know about any %(name)s matching %(pattern)s", { 'name': name, 'pattern': pattern, }) else: event.addresponse(u"I don't know about %s", name) elif len(factoids) > 1: event.addresponse( u"Pattern matches multiple factoids, please be more specific") else: factoidadmin = auth_responses(event, u'factoidadmin') identities = get_identities(event) factoid = factoids[0] if factoid[2].identity_id not in identities and not factoidadmin: return # Not very pythonistic, but escaping is a nightmare. separator = sep parts = [[]] pos = 0 while pos < len(operation): char = operation[pos] if char == separator: parts.append([]) elif char == u"\\": if pos < len(operation) - 1: if operation[pos + 1] == u"\\": parts[-1].append(u"\\") pos += 1 elif operation[pos + 1] == separator: parts[-1].append(separator) pos += 1 else: parts[-1].append(u"\\") else: parts[-1].append(u"\\") else: parts[-1].append(char) pos += 1 parts = [u"".join(x) for x in parts] if len(parts) != 4: event.addresponse( u"That operation makes no sense. Try something like s/foo/bar/" ) return oldvalue = factoid[2].value op, search, replace, flags = parts flags = flags.lower() if op == "s": if "r" not in flags: plain_search = search search = re.escape(search) replace = replace.replace('\\', '\\\\') if "i" in flags: search += "(?i)" try: if "r" not in flags and not re.search(search, oldvalue): event.addresponse( u"I couldn't find '%(terms)s' in " u"'%(oldvalue)s'. If that was a " u"proper regular expression, append " u"the 'r' flag", { 'terms': plain_search, 'oldvalue': oldvalue, }) return factoid[2].value = re.sub(search, replace, oldvalue, int("g" not in flags)) except: event.addresponse( u"That operation makes no sense. Try something like s/foo/bar/" ) return elif op == "y": if len(search) != len(replace): event.addresponse( u"That operation makes no sense. The source and destination must be the same length" ) return try: table = dict( (ord(x), ord(y)) for x, y in zip(search, replace)) factoid[2].value = oldvalue.translate(table) except: event.addresponse( u"That operation makes no sense. Try something like y/abcdef/ABCDEF/" ) return event.session.add(factoid[2]) event.session.commit() log.info( u"Applying '%s' to value %s (%s) of factoid %s (%s) by %s/%s (%s)", operation, factoid[2].id, oldvalue, factoid[0].id, factoid[0].names[0].name, event.account, event.identity, event.sender['connection']) event.addresponse(True)
def forget(self, event, name, number, pattern, is_regex): factoids = get_factoid(event.session, name, number, pattern, is_regex, all=True, literal=True) if factoids: factoidadmin = auth_responses(event, u'factoidadmin') identities = get_identities(event) factoid = event.session.query(Factoid).get(factoids[0][0].id) if len(factoids) > 1 and pattern is not None: event.addresponse( u'Pattern matches multiple factoids, please be more specific' ) return if number or pattern: if factoids[0][ 2].identity_id not in identities and not factoidadmin: return if event.session.query(FactoidValue).filter_by( factoid_id=factoid.id).count() == 1: if len( filter(lambda x: x.identity_id not in identities, factoid.names)) > 0 and not factoidadmin: return id = factoid.id event.session.delete(factoid) event.session.commit() log.info(u"Deleted factoid %s (%s) by %s/%s (%s)", id, name, event.account, event.identity, event.sender['connection']) else: id = factoids[0][2].id event.session.delete(factoids[0][2]) event.session.commit() log.info( u"Deleted value %s (%s) of factoid %s (%s) by %s/%s (%s)", id, factoids[0][2].value, factoid.id, name, event.account, event.identity, event.sender['connection']) else: if factoids[0][ 1].identity_id not in identities and not factoidadmin: return if event.session.query(FactoidName).filter_by( factoid_id=factoid.id).count() == 1: if len( filter(lambda x: x.identity_id not in identities, factoid.values)) > 0 and not factoidadmin: return id = factoid.id event.session.delete(factoid) event.session.commit() log.info(u"Deleted factoid %s (%s) by %s/%s (%s)", id, name, event.account, event.identity, event.sender['connection']) else: id = factoids[0][1].id event.session.delete(factoids[0][1]) event.session.commit() log.info( u"Deleted name %s (%s) of factoid %s (%s) by %s/%s (%s)", id, factoids[0][1].name, factoid.id, factoids[0][0].names[0].name, event.account, event.identity, event.sender['connection']) event.addresponse(True) else: factoids = get_factoid(event.session, name, None, pattern, is_regex, all=True, literal=True) if factoids: event.addresponse( u"I only know %(number)d things about %(name)s", { u'number': len(factoids), u'name': name, }) else: event.addresponse(u"I didn't know about %s anyway", name)