コード例 #1
0
ファイル: strife.py プロジェクト: node-/strife
def main():
    b = Brain("brains/bible.brain")
    #with open("learning/bible.txt", "r") as bibleFile:
    #    bible = bibleFile.readlines()

    #for line in bible:
    #    b.learn(line)

    print b.reply("Hello cobe")
コード例 #2
0
def main():
    b = Brain("brains/bible.brain")
    #with open("learning/bible.txt", "r") as bibleFile:
    #    bible = bibleFile.readlines()

    #for line in bible:
    #    b.learn(line)

    print b.reply("Hello cobe")
コード例 #3
0
ファイル: bot.py プロジェクト: mpedrero/demibot
def handle(msg):
    content_type, chat_type, chat_id = telepot.glance(msg)
    if content_type == 'text':
        brain = Brain(config.get('Brain', 'path') + str(chat_id) + ".brain")
        brain.learn(msg['text'])
        if 'reply_to_message' in msg and msg['reply_to_message']['from']['username'] == "Braulio_bot":
            bot.sendMessage(chat_id,brain.reply(msg['text']),reply_to_message_id=msg['message_id'])
        elif 'braulio' in msg['text'].lower():
            bot.sendMessage(chat_id,brain.reply(msg['text']).replace("Braulio",msg['from']['first_name']))
コード例 #4
0
ファイル: mBot.py プロジェクト: treisska/MarkovBot
def fun(message):
    print message.text
    brain = Brain("/db/" + str(message.chat.id)[1:] + ".br")
    # Telegram understands UTF-8, so encode text for unicode compatibility
    brain.learn(message.text)
    if "tagueul" in message.text.lower() or "tg" in message.text.lower() or "ta gueule" in message.text.lower():
        bot.reply_to(message, "Non, toi ta gueule.")
    elif (randint(1, 100) < percent):
        if violence : 
          bot.reply_to(message, brain.reply(message.text.upper(), 3000))
        else :
          bot.reply_to(message, brain.reply(message.text, 3000))
    return 'ok'
コード例 #5
0
def handle(msg):
    content_type, chat_type, chat_id = telepot.glance(msg)
    if content_type == 'text':
        brain = Brain(config.get('Brain', 'path') + str(chat_id) + ".brain")
        brain.learn(msg['text'])
        if 'reply_to_message' in msg and msg['reply_to_message']['from'][
                'username'] == "Braulio_bot":
            bot.sendMessage(chat_id,
                            brain.reply(msg['text']),
                            reply_to_message_id=msg['message_id'])
        elif 'braulio' in msg['text'].lower():
            bot.sendMessage(
                chat_id,
                brain.reply(msg['text']).replace("Braulio",
                                                 msg['from']['first_name']))
コード例 #6
0
ファイル: markov.py プロジェクト: sim1/slack-markov
class Markov:
    def __init__(self, brain_id):
        self.brain_id = brain_id
        brain_path = f'data/cobe/{brain_id}'
        os.makedirs('data/cobe/', exist_ok=True)

        self.brain = Brain(brain_path)

    def filter(self, message):
        message = re.sub('\<@[A-Z0-9a-z]{9}\>', '', message)  # remove mentions
        message = re.sub('\s{2,}', ' ', message)  #remove double spaces
        message = re.sub('\<[^\<]+\>', '', message)  #remove shit like links
        message = message.strip()  # remove unneeded spaces
        valid = False
        if len(message) > 5:
            valid = True
        return [valid, message]

    def learn(self, message):
        valid, message = self.filter(message)
        if not valid:
            return
        self.brain.learn(message)

    def speak(self, message):
        response = self.brain.reply(message)
        valid, response = self.filter(response)
        if not valid:
            return None
        return response
コード例 #7
0
ファイル: twert_helper.py プロジェクト: Floppy/twitter_ebooks
def create_tweet(catalyst=''):
	b = Brain(os.path.join(os.path.dirname(__file__), 'cobe.brain'))

	# get a reply from brain, encode as UTF-8
	i = 0

	while True:
		tweet = b.reply(catalyst).encode('utf-8', 'replace')
		if(config.filter_url):
			tweet = remove_url(tweet)
		if(config.filter_hashtag):
			tweet = remove_hashtag(tweet)
		if(config.filter_handle):
			tweet = remove_handle(tweet)
		tweet = smart_truncate(tweet)
		#make sure we're not tweeting something close to something else in the txt files
		#or we can just give up after 100 tries
		if check_tweet(tweet) or i >= 100:
			break
		i += 1
		
	#put the tweet in the db
	db_manager.insert_tweet(tweet)

	return tweet
コード例 #8
0
    def _reply(self, irc, msg, channel, text):
        """Send a response to text"""

        cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
        response = cobeBrain.reply(text).encode('utf-8')
        response = self._strip_nick(irc, msg, response)

        for i in range(response.lower().count(self.magicnick.lower())):
            # If first word is nick, switch with the callers nick.
            if self.magicnick in response:
                response = response.replace(
                    self.magicnick,
                    random.choice(list(irc.state.channels[msg.args[0]].users)))
            if self.magicnick.lower() in response:
                response = response.replace(
                    self.magicnick.lower(),
                    random.choice(list(irc.state.channels[msg.args[0]].users)))

        cobeBrain.learn(
            response)  # Let's have the bot learn the wacky things it says

        self.log.info("Attempting to respond in {0} with message: {1}".format(
            channel, response))

        # delay the response here so we look real?
        if self.registryValue('responseDelay', channel):
            self.log.info("Delayed the response in %s." % channel)
            delayseconds = time.time() + random.randint(2, 5)
            schedule.addEvent(irc.queueMsg(ircmsgs.privmsg(channel, response)),
                              delayseconds)
        else:
            irc.queueMsg(ircmsgs.privmsg(channel, response))
コード例 #9
0
ファイル: plugin.py プロジェクト: waratte/supybot
    def _reply(self, irc, msg, channel, text):
        """Send a response to text"""
        
        cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
        response = cobeBrain.reply(text).encode('utf-8')
        response = self._strip_nick(irc, msg, response)
        
        for i in range(response.lower().count(self.magicnick.lower())):
            # If first word is nick, switch with the callers nick.
            if self.magicnick in response:
                response = response.replace(self.magicnick, random.choice(list(irc.state.channels[msg.args[0]].users)))
            if self.magicnick.lower() in response:
                response = response.replace(self.magicnick.lower(), random.choice(list(irc.state.channels[msg.args[0]].users)))

        
        cobeBrain.learn(response) # Let's have the bot learn the wacky things it says
        
        self.log.info("Attempting to respond in {0} with message: {1}".format(channel, response))
        
        # delay the response here so we look real?
        if self.registryValue('responseDelay', channel):
            self.log.info("Delayed the response in %s." % channel)
            delayseconds = time.time() + random.randint(2, 5)
            schedule.addEvent(irc.queueMsg(ircmsgs.privmsg(channel, response)), delayseconds)
        else:
            irc.queueMsg(ircmsgs.privmsg(channel, response))
コード例 #10
0
def create_tweet(catalyst='', save_to_history=True):
	b = Brain(os.path.join(os.path.dirname(__file__), 'cobe.brain'))

	# get a reply from brain, encode as UTF-8
	i = 0

	while True:
		tweet = b.reply(catalyst).replace("&gt;", ">").replace("&lt;", "<").replace("&amp;", "&").replace("\"", "").replace("“", "").replace("”", "")
		if config.filter_url:
			tweet = remove_url(tweet)
		if config.filter_hashtag:
			tweet = remove_hashtag(tweet)
		if(config.filter_handle):
			tweet = remove_handle(tweet)
		tweet = smart_truncate(tweet)
		#make sure we're not tweeting something close to something else in the txt files
		#or we can just give up after 300 tries
		if check_tweet(tweet):
			# tweet matches criteria
			if save_to_history==True:
				db_manager.insert_tweet(tweet)
				print "[debug] Saved tweet to twert history database"
			return tweet
		elif i >= 300:
			print "[debug] Failure to create unique tweet. >300 tries"
			return unicode('')

		i += 1
コード例 #11
0
ファイル: test_brain.py プロジェクト: wodim/cobe
class BrainTest(unittest.TestCase):
    def setUp(self):
        self.brain = Brain(":memory:")

    def test_train(self):
        # It's hard to test training from here; make sure the model
        # gets expected probabilities.
        model = self.brain.model

        self.brain.train(u"this is a test")
        self.assertAlmostEqual(1.0, model.prob(u"a", u"this is".split()))

        self.brain.train(u"this is another test")
        self.assertAlmostEqual(0.5, model.prob(u"a", u"this is".split()))

    def test_train_many(self):
        self.brain.train_many([u"this is a test"])

        model = self.brain.model
        self.assertAlmostEqual(1.0, model.prob(u"a", u"this is".split()))

    def test_reply(self):
        training = [u"this is a test", u"this is another test"]

        for train in training:
            self.brain.train(train)

        self.assert_(self.brain.reply(u"testing") in set(training))
コード例 #12
0
ファイル: bot.py プロジェクト: miachm/demibot
def handle(msg):
    print msg
    content_type, chat_type, chat_id = telepot.glance(msg)
    if content_type == 'text':
        brain = Brain(config.get('Brain', 'path') + str(chat_id) + ".brain")
        brain.learn(msg['text'])
        if 'braulio' in msg['text'].lower():
            bot.sendMessage(chat_id,brain.reply(msg['text']))
コード例 #13
0
def handle(msg):
    print msg
    content_type, chat_type, chat_id = telepot.glance(msg)
    if content_type == 'text':
        brain = Brain(config.get('Brain', 'path') + str(chat_id) + ".brain")
        brain.learn(msg['text'])
        if 'braulio' in msg['text'].lower():
            bot.sendMessage(chat_id, brain.reply(msg['text']))
コード例 #14
0
ファイル: plugin.py プロジェクト: carriercomm/MegaHAL
    def corpusreply(self, irc, msg, args, text):
        """<text>

        Manually have the brain reply to <text>
        """
        
        b = Brain(self._brainfile)
        response = b.reply(text).encode('utf-8')
        irc.reply(response)
コード例 #15
0
ファイル: plugin.py プロジェクト: clukawski/nish
 def invalidCommand(self, irc, msg, tokens):
     channel = msg.args[0]
     text = msg.args[1]
     text = self._cleanText(text)
     #cobeBrain = Brain(self.brainDirectories[channel])
     cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
     response = cobeBrain.reply(text).encode('utf-8')
     response = self._strip_nick(irc, msg, response)
     irc.reply(response, prefixNick=False)
コード例 #16
0
def create_tweet(catalyst=''):
    b = Brain(os.path.join(os.path.dirname(__file__), 'cobe.brain'))

    # get a reply from brain, encode as UTF-8
    i = 0

    while True:
        tweet = b.reply(catalyst).encode('utf-8', 'replace')
        if(config['filter_urls']):
            tweet = remove_url(tweet)
        tweet = smart_truncate(tweet)


        # check if last words of tweet are less than 4 and remove them
        last_words_twert = tweet.split(' ')
        while len(last_words_twert[-1]) < 4:
            print "[debug] Removing last word:"+last_words_twert[-1]
            del(last_words_twert[-1])
        tweet = ' '.join(last_words_twert)



        #make sure we're not tweeting something close to something else in the txt files
        #or we can just give up after 100 tries
        if check_tweet(tweet) or i >= 100:
            break
        i += 1
    
    tweet = HTMLParser().unescape(tweet)
    tweet = tweet.upper()
    # clean up miscellaneous characters INCLUDING NUMBERS?
    for ch in ['(',')','1','2','3','4','5','6','7','8','9','0','.',', ,','-,','-;','-.',',,',' ;' ]:
        if ch in tweet:
            tweet=tweet.replace(ch,"")
        if ' TH ' in tweet:
            tweet = tweet.replace(' TH ',' ')
        if ' ND ' in tweet:
            tweet = tweet.replace(' ND ',' ')
        if ' RD ' in tweet:
            tweet = tweet.replace(' RD ',' ')
        if 'THE OF' in tweet:
            tweet = tweet.replace('THE OF ',' ')
        if "  " in tweet:
            tweet = tweet.replace("  "," ")
        if " - " in tweet:
            tweet = tweet.replace(" - "," ")
        if " , " in tweet:
            tweet = tweet.replace(" , ",", ")
    tweet = tweet.rstrip(" ,;=-")
    tweet = tweet.lstrip(" ,;=-?{}[]/_=+")

        
    #put the tweet in the db
    db_manager.insert_tweet(tweet)

    return tweet
コード例 #17
0
ファイル: plugin.py プロジェクト: carriercomm/MegaHAL
 def _reply(self, irc, channel, text):
     self.log.info("Trying to respond in %s" % channel)
     b = Brain(self._brainfile)
     response = b.reply(text).encode('utf-8')
     # delay the response here so we look real?
     if self.registryValue('responseDelay', channel):
         self.log.info("Delayed response in %s" % channel)
         delayseconds = time.time() + random.randint(2, 5)
         schedule.addEvent((irc.queueMsg(ircmsgs.privmsg(channel, response))), delayseconds)
     else:
         irc.queueMsg(ircmsgs.privmsg(channel, response))
コード例 #18
0
ファイル: Markov.py プロジェクト: Heufneutje/Hubbot_Twisted
class Markov(ModuleInterface):
    help = "Markov - Yeah I'm sentient, what of it?"

    def onEnable(self):
        self.brain = Brain(os.path.join("hubbot", "data", "{}.brain".format(self.bot.server)))

    def addToBrain(self, msg):
        if "://" not in msg and len(msg) > 1:
            self.brain.learn(msg)

    def shouldTrigger(self, message):
        """
        @type message: hubbot.message.IRCMessage
        """
        if message.Type in self.acceptedTypes:
            return True
        return False

    def onTrigger(self, message):
        """
        @type message: hubbot.message.IRCMessage
        """
        if message.User.Name == self.bot.nickname:
            return
        elif message.TargetType is TargetTypes.USER and not message.MessageString.startswith(self.bot.commandChar):
            reply = self.brain.reply(message.MessageString, max_len=100)
            return IRCResponse(ResponseType.Say, reply.capitalize(), message.ReplyTo)
        elif self.bot.nickname.lower() in message.MessageString.lower() and len(message.MessageList) > 1:
            messageList = [item.lower() for item in message.MessageList if item.lower() != self.bot.nickname.lower()]
            reply = self.brain.reply(" ".join(messageList), max_len=100)

            nickList = [nick.lower() for nick in self.bot.channels[message.ReplyTo].Users.keys()]
            for word in reply.split():
                if word.lower() in nickList:
                    reply.replace(word, message.User.Name)
            return IRCResponse(ResponseType.Say, reply.capitalize(), message.ReplyTo)
        else:
            messageList = [item.lower() for item in message.MessageList if item.lower() != self.bot.nickname.lower()]
            self.addToBrain(" ".join(messageList))
コード例 #19
0
ファイル: server.py プロジェクト: happz/viki
class Chatter(object):
  def __init__(self):
    self.brain = Brain('cobe.brain')

    with open('seed.txt', 'r') as f:
      text = [l.strip() for l in f.read().replace('\n', ' ').replace('.', '\n').replace('?', '\n').replace('\xa0', ' - ').split('\n') if l.strip()]

      for line in text:
        self.brain.learn(line)

  def reply(self, message):
    return self.brain.reply(message)

  def learn(self, line):
    self.brain.learn(line)
コード例 #20
0
ファイル: plugin.py プロジェクト: Latinx/supybot
 def _reply(self, irc, channel, text):
     """Send a response to text"""
     
     cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
     response = cobeBrain.reply(text).encode('utf-8')
     
     cobeBrain.learn(response) # Let's have the bot learn the wacky things it says
     
     self.log.info("Attempting to respond in {0} with message: {1}".format(channel, response))
     
     # delay the response here so we look real?
     if self.registryValue('responseDelay', channel):
         self.log.info("Delayed the response in %s." % channel)
         delayseconds = time.time() + random.randint(2, 5)
         schedule.addEvent(irc.queueMsg(ircmsgs.privmsg(channel, response)), delayseconds)
     else:
         irc.queueMsg(ircmsgs.privmsg(channel, response))
コード例 #21
0
ファイル: run.py プロジェクト: loadletter/cobe-cleverbot
def chatbot(botname, remotebot, out=sys.stdout):
	mem = Brain(botname + ".brain")
	mem.learn("This is the only thing I know!")

	msg = "Hello!"
	out.write("BEGIN LOG: %s\n" % time.ctime())
	try:
		while True:
			out.write("Local: %s\n" % msg)
			msg = remotebot.think(msg)
			out.write("Remote: %s\n" % msg)
			if LEARN == True:
				mem.learn(msg)
			msg = mem.reply(msg)
			out.flush()

	except (KeyboardInterrupt, SystemExit, EOFError):
		print "Saving..."
		out.write("END LOG: %s\n" % time.ctime())
		out.close()
コード例 #22
0
def create_tweet(catalyst=''):
    b = Brain(os.path.join(os.path.dirname(__file__), 'cobe.brain'))

    # get a reply from brain, encode as UTF-8
    i = 0

    while True:
        tweet = b.reply(catalyst).encode('utf-8', 'replace')
        if (config.filter_url):
            tweet = remove_url(tweet)
        tweet = smart_truncate(tweet)
        #make sure we're not tweeting something close to something else in the txt files
        #or we can just give up after 100 tries
        if check_tweet(tweet) or i >= 100:
            break
        i += 1

    #put the tweet in the db
    db_manager.insert_tweet(tweet)

    return tweet
コード例 #23
0
    def _reply(self, irc, msg, channel, text):
        """Send a response to text"""

        cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
        response = cobeBrain.reply(text).encode('utf-8')
        response = self._strip_nick(irc, msg, response)

        cobeBrain.learn(
            response)  # Let's have the bot learn the wacky things it says

        self.log.info("Attempting to respond in {0} with message: {1}".format(
            channel, response))

        # delay the response here so we look real?
        if self.registryValue('responseDelay', channel):
            self.log.info("Delayed the response in %s." % channel)
            delayseconds = time.time() + random.randint(2, 5)
            schedule.addEvent(irc.queueMsg(ircmsgs.privmsg(channel, response)),
                              delayseconds)
        else:
            irc.queueMsg(ircmsgs.privmsg(channel, response))
コード例 #24
0
def create_tweet(catalyst=""):
    b = Brain(os.path.join(os.path.dirname(__file__), "cobe.brain"))

    # get a reply from brain, encode as UTF-8
    i = 0

    while True:
        tweet = b.reply(catalyst).encode("utf-8", "replace")
        if config["filter_urls"]:
            tweet = remove_url(tweet)
        tweet = smart_truncate(tweet)
        tweet = quote_fixer(tweet)
        # make sure we're not tweeting something close to something else in the txt files
        # or we can just give up after 100 tries
        if check_tweet(tweet) or i >= 2000:
            break
        i += 1

    tweet = HTMLParser().unescape(tweet)

    # put the tweet in the db
    db_manager.insert_tweet(tweet)

    return tweet
コード例 #25
0
ファイル: skynet.py プロジェクト: skittie/snippets
class Bot(irc.IRCClient):
    '''	def _get_nickname(self):
		return self.factory.nick
	nickname = property(_get_nickname)
	'''
    def __init__(self, *args, **kwargs):
        self._namescallback = {}

    def got_names(self, nicklist):
        self.ircnames = nicklist
        #print nicklist
        self.ircnames = [s.replace('@', '') for s in nicklist]
        self.ircnames = [s.strip('+') for s in nicklist]
        print self.ircnames

    def names(self, channel):
        channel = channel.lower()
        d = defer.Deferred()
        if channel not in self._namescallback:
            self._namescallback[channel] = ([], [])

        self._namescallback[channel][0].append(d)
        self.sendLine("NAMES %s" % channel)
        return d

    def irc_RPL_NAMREPLY(self, prefix, params):
        channel = params[2].lower()
        nicklist = params[3].split(' ')

        if channel not in self._namescallback:
            return

        n = self._namescallback[channel][1]
        n += nicklist

    def irc_RPL_ENDOFNAMES(self, prefix, params):
        channel = params[1].lower()
        if channel not in self._namescallback:
            return

        callbacks, namelist = self._namescallback[channel]

        for cb in callbacks:
            cb.callback(namelist)

        del self._namescallback[channel]

# START

    def connectionMade(self):
        self.nickname = self.factory.nick
        self.password = self.factory.password
        self.replyrate = self.factory.replyrate
        self.ignored = self.factory.ignored
        self.trusted = self.factory.trusted
        self.talking = self.factory.talking

        irc.IRCClient.connectionMade(self)
        print("Connected")

        print("Using brain %s" % self.factory.brain)
        self.brain = Brain(self.factory.brain)

    def connectionLost(self, reason):
        print("Disconnected: %s" % reason)
        irc.IRCClient.connectionLost(self, reason)

    def signedOn(self):
        print("Signed on as %s" % self.nickname)
        for channel in self.factory.channels:
            self.join(channel)

    def userJoined(self, user, channel):
        #print("userjoined "+user+" "+channel)
        nick = user.split('!')[0]
        reply = self.brain.reply("")
        time.sleep(1)
        self.ircnames.append(nick)
        self.msg(channel, nick + ": " + reply)
        print(">>> [%s] %s" % (channel, reply))

    def joined(self, channel):
        print("Joined %s" % channel)
        self.names(channel).addCallback(self.got_names)
        print self.names(channel)

    def msg(self, user, message, length=None):
        if type(message) is unicode:
            message = message.encode('utf-8')
        irc.IRCClient.msg(self, user, message, length)

    def privmsg(self, user, channel, msg):
        msg = msg.decode('utf-8')
        who = user if channel == self.nickname else channel
        nick = user.split('!')[0]
        #		print(user)
        print("<<< [%s] <%s> %s" % (who, nick, msg))

        if nick == self.nickname:
            return

        replyrate = self.replyrate
        if self.nickname in msg:
            msg.replace(self.nickname + ":", "")
            replyrate = 100

#		msg.replace(self.nickname, "#nick")

#		escaped_users = map(re.escape, self.ircnames)
#		p = re.compile(r'\b(' + ('|'.join(escaped_users)) + r')\b')
#		msg = p.sub('skynet', msg)

# Commands

        if msg.startswith('!!') and user in self.trusted:
            command = msg.lstrip('!').split(' ')
            print(str(command) + " from " + user)
            try:
                if command[0] == 'replyrate':
                    if len(command) > 1:
                        self.replyrate = int(command[1])
                        self.msg(
                            who, "Now replying to " + str(self.replyrate) +
                            "% of messages")
                    else:
                        self.msg(
                            who, "Replying to " + str(self.replyrate) +
                            "% of messages")

                elif command[0] == 'ignore':
                    if len(command) > 1:
                        self.ignored + command[1]
                    self.msg(who, str(self.ignored))

                elif command[0] == 'unignore':
                    if len(command) > 1:
                        self.ignored.remove(command[1])
                    self.msg(who, str(self.ignored))

                elif command[0] == 'reload':
                    self.brain = Brain(self.factory.brain)
                    self.msg(who, "done")

                elif command[0] == 'shutup' or command[0] == 'turpakiinni':
                    self.talking = False
                    self.msg(who, "okay.jpg")

                elif command[0] == 'wakeup':
                    self.talking = True
                    self.msg(who, "oho")

                elif command[0] == 'brain':
                    self.brain = Brain(command[1])
                    self.msg(who, "done")

                elif command[0] == 'stemmer':
                    try:
                        brain.set_stemmer(command[1])
                        self.msg(who, "Stemmer set to " + command[1])
                    except Exception, e:
                        brain.set_stemmer("finnish")
                        self.msg(who, "Stemmer set to finnish")
                        self.msg(e)

                elif command[0] == 'quit':
                    self.quit("mo :D")
                    sys.exit()

                elif command[0] == 'join':
                    self.join(command[1])

                elif command[0] == 'leave' or command[0] == 'part':
                    self.leave(command[1])

                elif command[0] == 'stats':
                    if command[1] == 'stems':
                        c = self.brain.graph.cursor()
                        count = c.execute(
                            "SELECT count(*) FROM token_stems").fetchone()
                        self.msg(who, str(count[0]))

                    if command[1] == 'tokens':
                        c = self.brain.graph.cursor()
                        count = c.execute(
                            "SELECT count(*) FROM tokens").fetchone()
                        self.msg(who, str(count[0]))

                    if command[1] == 'nodes':
                        c = self.brain.graph.cursor()
                        count = c.execute(
                            "SELECT count(*) FROM nodes").fetchone()
                        self.msg(who, str(count[0]))

                    if command[1] == 'edges':
                        c = self.brain.graph.cursor()
                        count = c.execute(
                            "SELECT count(*) FROM edges").fetchone()
                        self.msg(who, str(count[0]))

            except Exception, e:
                self.msg(who, str(e))
コード例 #26
0
ファイル: test_brain.py プロジェクト: Gustavo6046/cobe
    def testEmptyReply(self):
        Brain.init(TEST_BRAIN_FILE)

        brain = Brain(TEST_BRAIN_FILE)
        self.assertTrue(brain.reply("") != "")
コード例 #27
0
ファイル: Cobe.py プロジェクト: alyptik/dotfiles
    def respond(self, irc, msg, args, channel, text):
        """[<channel>] <text>

        Replies to <text>. If the channel is not given, the current channel is used.
        """
        if not channel:  # Did the user enter in a channel? If not, set the current channel
            channel = msg.args[0]

        if not irc.isChannel(msg.args[0]) and irc.isChannel(channel):
            # Are we in a channel and is the channel supplied a channel?

            if os.path.exists(self._getBrainDirectoryForChannel(channel)):
                # Does this channel have a brain file?

                text = self._cleanText(text)
                if text and len(text) > 1 and not text.isspace():

                    cobeBrain = Brain(self.brainDirectories[channel])
                    response = cobeBrain.reply(text).encode('utf-8')
                    response = self._strip_nick(irc, msg, response)
                    for i in range(response.lower().count(
                            self.magicnick.lower())):
                        # If first word is nick, switch with the callers nick.
                        if self.magicnick in response:
                            response = response.replace(
                                self.magicnick,
                                re.sub(
                                    r'[Kk]', r'κ',
                                    re.sub(r'^(.)',
                                           r'\1​',
                                           random.choice(
                                               list(irc.state.channels[
                                                   msg.args[0]].users)),
                                           count=1)))
                        if self.magicnick.lower() in response:
                            response = response.replace(
                                self.magicnick,
                                re.sub(
                                    r'[Kk]', r'κ',
                                    re.sub(r'^(.)',
                                           r'\1​',
                                           random.choice(
                                               list(irc.state.channels[
                                                   msg.args[0]].users)),
                                           count=1)))
                        if self.magicnick in response:
                            response = response.replace(
                                self.magicnick,
                                re.sub(
                                    r'[Ee]', r'ε',
                                    re.sub(r'^(.)',
                                           r'\1​',
                                           random.choice(
                                               list(irc.state.channels[
                                                   msg.args[0]].users)),
                                           count=1)))
                        if self.magicnick.lower() in response:
                            response = response.replace(
                                self.magicnick.lower(),
                                re.sub(
                                    r'[Ee]', r'ε',
                                    re.sub(r'^(.)',
                                           r'\1​',
                                           random.choice(
                                               list(irc.state.channels[
                                                   msg.args[0]].users)),
                                           count=1)))

                else:

                    irc.error(_("No text to reply to!"), Raise=True)

            else:
                # Nope, create one!

                self.log.info("Non-existent brainfile in {0}!".format(channel))
                self.log.info("Creating a brainfile now in {0}".format(
                    self._getBrainDirectoryForChannel(channel)))

                commands.getoutput('{0} {1}'.format(self._doCommand(channel),
                                                    'init'))

                text = self._cleanText(text)
                if text and len(text) > 1 and not text.isspace():

                    cobeBrain = Brain(
                        self._getBrainDirectoryForChannel(channel))
                    response = cobeBrain.reply(text).encode('utf-8')
                    response = self._strip_nick(irc, msg, response)
                    for i in range(response.lower().count(
                            self.magicnick.lower())):
                        # If first word is nick, switch with the callers nick.
                        if self.magicnick in response:
                            response = response.replace(
                                self.magicnick,
                                re.sub(
                                    r'[Kk]', r'κ',
                                    re.sub(r'^(.)',
                                           r'\1​',
                                           random.choice(
                                               list(irc.state.channels[
                                                   msg.args[0]].users)),
                                           count=1)))
                        if self.magicnick.lower() in response:
                            response = response.replace(
                                self.magicnick,
                                re.sub(
                                    r'[Kk]', r'κ',
                                    re.sub(r'^(.)',
                                           r'\1​',
                                           random.choice(
                                               list(irc.state.channels[
                                                   msg.args[0]].users)),
                                           count=1)))
                        if self.magicnick in response:
                            response = response.replace(
                                self.magicnick,
                                re.sub(
                                    r'[Ee]', r'ε',
                                    re.sub(r'^(.)',
                                           r'\1​',
                                           random.choice(
                                               list(irc.state.channels[
                                                   msg.args[0]].users)),
                                           count=1)))
                        if self.magicnick.lower() in response:
                            response = response.replace(
                                self.magicnick.lower(),
                                re.sub(
                                    r'[Ee]', r'ε',
                                    re.sub(r'^(.)',
                                           r'\1​',
                                           random.choice(
                                               list(irc.state.channels[
                                                   msg.args[0]].users)),
                                           count=1)))

                    # lowercase first letter of the string.
                    response = response[0].lower() + response[1:]

                    irc.reply(response)

                else:
                    irc.error(_("No text to reply to!"), Raise=True)

        elif os.path.exists(self._getBrainDirectoryForChannel(
                channel)) and irc.isChannel(channel):
            # We are in a channel! Does the brain file exist and is this a channel?

            text = self._cleanText(text)
            if text and len(text) > 1 and not text.isspace():

                cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
                response = cobeBrain.reply(text).encode('utf-8')
                response = self._strip_nick(irc, msg, response)
                # If first word is nick, switch with the callers nick.
                if self.magicnick in response:
                    response = response.replace(
                        self.magicnick,
                        re.sub(
                            r'[Kk]', r'κ',
                            re.sub(r'^(.)',
                                   r'\1​',
                                   random.choice(
                                       list(irc.state.channels[
                                           msg.args[0]].users)),
                                   count=1)))
                if self.magicnick.lower() in response:
                    response = response.replace(
                        self.magicnick,
                        re.sub(
                            r'[Kk]', r'κ',
                            re.sub(r'^(.)',
                                   r'\1​',
                                   random.choice(
                                       list(irc.state.channels[
                                           msg.args[0]].users)),
                                   count=1)))
                if self.magicnick in response:
                    response = response.replace(
                        self.magicnick,
                        re.sub(
                            r'[Ee]', r'ε',
                            re.sub(r'^(.)',
                                   r'\1​',
                                   random.choice(
                                       list(irc.state.channels[
                                           msg.args[0]].users)),
                                   count=1)))
                if self.magicnick.lower() in response:
                    response = response.replace(
                        self.magicnick.lower(),
                        re.sub(
                            r'[Ee]', r'ε',
                            re.sub(r'^(.)',
                                   r'\1​',
                                   random.choice(
                                       list(irc.state.channels[
                                           msg.args[0]].users)),
                                   count=1)))

                # lowercase first letter of the string.
                response = response[0].lower() + response[1:]

                irc.reply(response)

            else:
                irc.error(_("No text to reply to!"), Raise=True)

        elif not os.path.exists(self._getBrainDirectoryForChannel(
                channel)) and irc.isChannel(channel):
            # Nope, create one!

            self.log.info("Non-existent brainfile in {0}!".format(channel))
            self.log.info("Creating a brainfile now in {0}".format(
                self._getBrainDirectoryForChannel(channel)))

            commands.getoutput('{0} {1}'.format(self._doCommand(channel),
                                                'init'))

            text = self._cleanText(text)
            if text and len(text) > 1 and not text.isspace():

                irc.reply("Learning text: {0}".format(text))
                cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
                response = self._strip_nick(irc, msg, response)
                # If first word is nick, switch with the callers nick.
                if self.magicnick in response:
                    response = response.replace(
                        self.magicnick,
                        re.sub(
                            r'[Kk]', r'κ',
                            re.sub(r'^(.)',
                                   r'\1​',
                                   random.choice(
                                       list(irc.state.channels[
                                           msg.args[0]].users)),
                                   count=1)))

                if self.magicnick.lower() in response:
                    response = response.replace(
                        self.magicnick,
                        re.sub(
                            r'[Kk]', r'κ',
                            re.sub(r'^(.)',
                                   r'\1​',
                                   random.choice(
                                       list(irc.state.channels[
                                           msg.args[0]].users)),
                                   count=1)))
                if self.magicnick in response:
                    response = response.replace(
                        self.magicnick,
                        re.sub(
                            r'[Ee]', r'ε',
                            re.sub(r'^(.)',
                                   r'\1​',
                                   random.choice(
                                       list(irc.state.channels[
                                           msg.args[0]].users)),
                                   count=1)))
                if self.magicnick.lower() in response:
                    response = response.replace(
                        self.magicnick.lower(),
                        re.sub(
                            r'[Ee]', r'ε',
                            re.sub(r'^(.)',
                                   r'\1​',
                                   random.choice(
                                       list(irc.state.channels[
                                           msg.args[0]].users)),
                                   count=1)))

                cobeBrain.learn(text)

            else:
                irc.error(_("No text to reply to!"), Raise=True)

        else:
            irc.error(_("Improper channel given!"), Raise=True)
コード例 #28
0
ファイル: botserver.py プロジェクト: Srol/teenbot
def responderText(textQuery):
	b = Brain("cobe.brain")
	return b.reply(textQuery)
コード例 #29
0
class Cobe():
  def __init__(self, config=CONFIG):
    self.ready = False
    self.psapi = pushshift_api
    self.rapi = reddit_api
    self.config = CONFIG
    self.brain = Brain(self.config.get("cobe_main_db"))
    self.size = 0

  def get_reply(self, replyto: str=''):
    if self.ready:
      return self.brain.reply(replyto)
    else:
      log.info(f"cobe not initialized, run init")

  def init(self):
    log.info("using cobe to generate comments")
    main_db = self.config.get("cobe_main_db")
    
    # make sure db was initialized correctly
    if os.path.isfile(main_db):
      # set the initial size
      self.size = os.path.getsize(main_db)
    else:
      log.info(f"cobe db failed to initialize. exiting")
      sys.exit()

    log.debug('filling cobe database for commenting')
    # loop through learning comments until we reach the min db size
    while self.size <= tobytes(self.config.get("cobe_min_db_size")):

      log.info(f"cobe db size is: {str(bytesto(self.size, 'm'))}mb, need {self.config.get('cobe_min_db_size')} - learning...")
      
      # just learn from random subreddits for now
      subreddit = get_subreddit(getsubclass=True)
      
      log.info(f"learning from /r/{subreddit}")
      
      # get the comment generator function from pushshift
      comments = self.psapi.get_comments(subreddit)

      # go through 500 comments per subreddit
      for x in range(500):
        # get the comment from the generator function
        try:
          comment = next(comments)
        except StopIteration as e:
          log.info(f"end of comments")
        
        # bot responses are better when it learns from short comments
        if len(comment.body) < 240:
          log.debug(f"learning comment: {comment.body.encode('utf8')}")
          
          # only learn comments that don't contain an avoid word
          if not any(word in comment.body for word in AVOID_WORDS):
            self.brain.learn(comment.body.encode("utf8")) 

      # update the class size variable so the while loop
      # knows when to break
      self.size = os.path.getsize(main_db)

    log.info(f"database min size ({self.config.get('cobe_min_db_size')}) reached")
    self.ready = True
コード例 #30
0
#!/usr/bin/env python
import sys
from cobe.brain import Brain

if len(sys.argv) != 2:
    print "Usage: %s <brain>" % sys.argv[0]
    sys.exit(1)

brain = Brain(sys.argv[1])

while True:
    data = sys.stdin.readline().decode('utf-8')
    if len(data) == 0:
        break
    cmd, line = data.split(' ', 1)
    if cmd == 'learn':
        brain.learn(line)
    elif cmd == 'reply':
        reply = brain.reply(line)
        sys.stdout.write((reply + "\n").encode('utf-8'))
        sys.stdout.flush()
コード例 #31
0
    def testEmptyReply(self):
        Brain.init(TEST_BRAIN_FILE)

        brain = Brain(TEST_BRAIN_FILE)
        self.assert_(brain.reply("") is not "")
コード例 #32
0
ファイル: reply.py プロジェクト: postcasio/twitter_ebooks
	state = loads(open(os.path.join(os.path.dirname(__file__), '.state'), 'r').read())
except:
	state = {}

if 'last_reply' not in state:
	state['last_reply'] = 0

api = twitter.Api(**config.api)

if config.replies:
	print "Performing replies"
	
	last_tweet = long(state['last_reply'])

	replies = api.GetReplies(since_id=last_tweet)

	for reply in replies:
		if reply.user.screen_name.lower() == config.screen_name.lower():
			continue
		try:
			api.PostUpdate(smart_truncate('@%s %s' % (reply.user.screen_name, b.reply(reply.text).encode('utf-8', 'replace'))), in_reply_to_status_id=reply.id)
		except:
			print 'Error posting reply.'
		last_tweet = max(reply.id, last_tweet)

	state['last_reply'] = str(last_tweet)

print "Saving state"

open(os.path.join(os.path.dirname(__file__), '.state'), 'w').write(dumps(state))
コード例 #33
0
ファイル: plugin.py プロジェクト: Latinx/supybot
    def respond(self, irc, msg, args, channel, text):
        """[<channel>] <text>

        Replies to <text>. If the channel is not given, the current channel is used.
        """
        if not channel: # Did the user enter in a channel? If not, set the current channel
            channel = msg.args[0]

        if not irc.isChannel(msg.args[0]) and irc.isChannel(channel): 
            # Are we in a channel and is the channel supplied a channel?
            
            if os.path.exists(self._getBrainDirectoryForChannel(channel)):
                # Does this channel have a brain file?
                
                    text = self._cleanText(text)
                    if text and len(text) > 1 and not text.isspace():
                
                        cobeBrain = Brain(self.brainDirectories[channel])
                        response = cobeBrain.reply(text).encode('utf-8')
                        irc.reply(response)

                    else:
            
                        irc.error(_("No text to reply to!"), Raise=True)
                    
            else: 
                # Nope, create one!
            
                self.log.info("Non-existent brainfile in {0}!".format(channel))
                self.log.info("Creating a brainfile now in {0}".format(self._getBrainDirectoryForChannel(channel)))
                
                commands.getoutput('{0} {1}'.format(self._doCommand(channel), 'init'))
                
                text = self._cleanText(text)
                if text and len(text) > 1 and not text.isspace():
            
                    cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
                    response = cobeBrain.reply(text).encode('utf-8')
                    irc.reply(response)
                    
                else:
                    irc.error(_("No text to reply to!"), Raise=True)
                
        elif os.path.exists(self._getBrainDirectoryForChannel(channel)) and irc.isChannel(channel): 
            # We are in a channel! Does the brain file exist and is this a channel?
    
            text = self._cleanText(text)
            if text and len(text) > 1 and not text.isspace():

                cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
                response = cobeBrain.reply(text).encode('utf-8')
                irc.reply(response)

            else:
                irc.error(_("No text to reply to!"), Raise=True)

        elif not os.path.exists(self._getBrainDirectoryForChannel(channel)) and irc.isChannel(channel):
            # Nope, create one!
        
            self.log.info("Non-existent brainfile in {0}!".format(channel))
            self.log.info("Creating a brainfile now in {0}".format(self._getBrainDirectoryForChannel(channel)))
            
            commands.getoutput('{0} {1}'.format(self._doCommand(channel), 'init'))
            
            text = self._cleanText(text)
            if text and len(text) > 1 and not text.isspace():
        
                irc.reply("Learning text: {0}".format(text))
                cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
                cobeBrain.learn(text)
                
            else:
                irc.error(_("No text to reply to!"), Raise=True)
                
        else:
            irc.error(_("Improper channel given!"), Raise=True)
コード例 #34
0
ファイル: plugin.py プロジェクト: avinson/supybot-plugins
class Cobe(callbacks.Plugin):
    """This plugins provides a Cobe integration for Supybot.
    Cobe must be installed ('apt-get install brain' on Debian)"""
    callAfter = ['MoobotFactoids', 'Factoids', 'Infobot']
    callBefore = ['Dunno']

    def __init__(self, irc):
        # Call Supybot's scripts
        self.__parent = super(Cobe, self)
        self.__parent.__init__(irc)
        
        # Save state
        saved = (sys.stdout, os.getcwd())
        
        # Create proxy for Cobe
        os.chdir(conf.supybot.directories.data())
        sys.stdout = StringIO()
        
        # Initialize Cobe
        self.brain = Brain("cobe.store")
        
        # Restore state
        sys.stdout, cwd = saved
        os.chdir(cwd)
        
        random.seed()
    
    _dontKnow = [
                 'I don\'t know enough to answer you yet!',
                 'I am utterly speechless!',
                 'I forgot what I was going to say!'
                ]
    _translations = {
                     'I don\'t know enough to answer you yet!':
                         _('I don\'t know enough to answer you yet!'),
                     'I am utterly speechless!':
                         _('I am utterly speechless!'),
                     'I forgot what I was going to say!':
                         _('I forgot what I was going to say!'),
                    }

    def _response(self, msg, prb, reply):
        if random.randint(0, 100) < prb:
            response = self.brain.reply(unicode(msg))
            if self._translations.has_key(response):
                response = self._translations[response]
            reply(response, prefixNick=False)
        else:
            match = re.search(r'^\w+:|\+\+$|http:|https:', msg)
            if not match:
              self.brain.train(unicode(msg))

    def doPrivmsg(self, irc, msg):
        if not msg.args[0].startswith('#'): # It is a private message
            return
        message = msg.args[1]
        
        if message.startswith(irc.nick) or re.match('\W.*', message):
            # Managed by invalidCommand
            return
        
        probability = self.registryValue('answer.probability', msg.args[0])
        self._response(message, probability, irc.reply)

    def invalidCommand(self, irc, msg, tokens):
        if not msg.args[0].startswith('#'): # It is a private message
            # Actually, we would like to answer, but :
            # 1) It may be a mistyped identify command (or whatever)
            # 2) Cobe can't reply without learning
            return
        message = msg.args[1]
        usedToStartWithNick = False
        if message.startswith(message):
            parsed = re.match('(.+ |\W)?(?P<message>\w.*)', message)
            message = parsed.group('message')
            usedToStartWithNick = True
        if self.registryValue('answer.commands') or usedToStartWithNick:
            print msg.args[0]
            self._response(message,
                        self.registryValue('answer.probabilityWhenAddressed',
                                           msg.args[0]),
                        irc.reply)
        elif self.registryValue('learn.commands'):
            self.brain.train(unicode(message))
    
    @internationalizeDocstring
    def cleanup(self, irc, msg, args):
        """takes no argument
        
        Saves Cobe brain to disk."""
    #    brain.cleanup()
        irc.replySuccess()
コード例 #35
0
ファイル: twert.py プロジェクト: CelestialBeard/thom_ebooks
import twitter
#get keys/secrets from dev.twitter.com signed in as the bot account
api = twitter.Api(consumer_key='', consumer_secret='', access_token_key='', access_token_secret='')

from cobe.brain import Brain

b = Brain("cobe.brain")

#truncate to 140 characters, do not cut off words
def smart_truncate(content, length=140):
    if len(content) <= length:
        return content
    else:
        return content[:length].rsplit(' ', 1)[0]

#feed cobe an empty reply so it babbles
status = api.PostUpdate((smart_truncate(b.reply(""))))
コード例 #36
0
ファイル: cobe.py プロジェクト: pteichman/kibot-modules
class cobe(kibot.BaseModule.BaseModule):
    """intelligence"""

    _nolearn_uperm = UserPerm("nolearn")

    def __init__(self, bot):
        self._brain_file = os.path.join(bot.op.files.data_dir, "cobe.brain")
        self._trace_file = os.path.join(bot.op.files.data_dir, "cobe.trace")

        # rotate logs
        if os.path.exists(self._trace_file):
            now = datetime.datetime.now()
            stamp = now.strftime("%Y-%m-%d.%H%M%S")
            os.rename(self._trace_file, "%s.%s" % (self._trace_file, stamp))

        self._brain = Brain(self._brain_file, instatrace=self._trace_file)

        kibot.BaseModule.BaseModule.__init__(self, bot)

    def _on_pubmsg(self, conn, event):
        import string, re

        message = event.args[0]
        message = re.sub("<\S+>", "", message)

        match = re.match('"(.*)" --\S+, \d+-\S+\d+.', message)
        if match:
            message = match.group(1)

        match = re.match("\s*(\S+)\s*[,:]\s*(.*?)\s*$", message)

        if match:
            to = match.group(1)
            text = match.group(2)
        else:
            to = None
            text = message

        speaker = nm_to_n(event.source)

        # drop any extra whitespace in the string
        text = string.join(string.split(text), " ")

        user = self.bot.ircdb.get_user(nickmask=event.source)
        if user is not None:
            uperms = list(user.get_perms())
        else:
            uperms = list(self.bot.permdb.get_unknown_perms())
            uperms.append(self._nolearn_uperm)

        if "ignore" in uperms:
            return "NO MORE"

        # convert text to Unicode
        text = text.decode("utf-8")

        # if spoken to directly, generate a reply
        if str(to).lower() == self.bot.nick.lower():
            self._brain.learn(text)
            reply = self._brain.reply(text)

            # convert to utf-8 for output
            reply = reply.encode("utf-8")

            conn.privmsg(event.target, "%s: %s" % (speaker, reply))
        else:
            self._brain.learn(text)

        return "NO MORE"
コード例 #37
0
ファイル: twert.py プロジェクト: postcasio/twitter_ebooks
from cobe.brain import Brain

parser = argparse.ArgumentParser(description="Post ebooks tweets to twitter.")
parser.add_argument('-o', '--stdout', action='store_true', help="Output to stdout instead of posting to twitter.")
parser.add_argument('-t', '--tweet', help="Tweet arbitrary text instead of using the brain.")

args = parser.parse_args()

api = twitter.Api(**config.api)

if args.tweet:
	api.PostUpdate(args.tweet)
else:

	b = Brain(os.path.join(os.path.dirname(__file__), 'cobe.brain'))

	#truncate to 140 characters, do not cut off words
	def smart_truncate(content, length=140):
	    if len(content) <= length:
	        return content
	    else:
	        return content[:length].rsplit(' ', 1)[0]

	# get a reply from brain, encode as UTF-8
	tweet = smart_truncate(b.reply("").encode('utf-8', 'replace'))

	if args.stdout:
		print tweet
	else:
		status = api.PostUpdate(tweet)
コード例 #38
0
ファイル: cobe_pipe.py プロジェクト: Bediko/happyman
#!/usr/bin/env python
import sys
from cobe.brain import Brain

if len(sys.argv) != 2:
	print "Usage: %s <brain>" % sys.argv[0]
	sys.exit(1)

brain = Brain(sys.argv[1])

while True:
	data = sys.stdin.readline().decode('utf-8')
	if len(data) == 0:
		break
	cmd, line = data.split(' ', 1)
	if cmd == 'learn':
		brain.learn(line)
	elif cmd == 'reply':
		reply = brain.reply(line)
		sys.stdout.write((reply + "\n").encode('utf-8'))
		sys.stdout.flush()
コード例 #39
0
    def respond(self, irc, msg, args, channel, text):
        """[<channel>] <text>

        Replies to <text>. If the channel is not given, the current channel is used.
        """
        if not channel:  # Did the user enter in a channel? If not, set the current channel
            channel = msg.args[0]

        if not irc.isChannel(msg.args[0]) and irc.isChannel(channel):
            # Are we in a channel and is the channel supplied a channel?

            if os.path.exists(self._getBrainDirectoryForChannel(channel)):
                # Does this channel have a brain file?

                text = self._cleanText(text)
                if text and len(text) > 1 and not text.isspace():

                    cobeBrain = Brain(self.brainDirectories[channel])
                    response = cobeBrain.reply(text).encode('utf-8')
                    irc.reply(response)

                else:

                    irc.error(_("No text to reply to!"), Raise=True)

            else:
                # Nope, create one!

                self.log.info("Non-existent brainfile in {0}!".format(channel))
                self.log.info("Creating a brainfile now in {0}".format(
                    self._getBrainDirectoryForChannel(channel)))

                commands.getoutput('{0} {1}'.format(self._doCommand(channel),
                                                    'init'))

                text = self._cleanText(text)
                if text and len(text) > 1 and not text.isspace():

                    cobeBrain = Brain(
                        self._getBrainDirectoryForChannel(channel))
                    response = cobeBrain.reply(text).encode('utf-8')
                    irc.reply(response)

                else:
                    irc.error(_("No text to reply to!"), Raise=True)

        elif os.path.exists(self._getBrainDirectoryForChannel(
                channel)) and irc.isChannel(channel):
            # We are in a channel! Does the brain file exist and is this a channel?

            text = self._cleanText(text)
            if text and len(text) > 1 and not text.isspace():

                cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
                response = cobeBrain.reply(text).encode('utf-8')
                irc.reply(response)

            else:
                irc.error(_("No text to reply to!"), Raise=True)

        elif not os.path.exists(self._getBrainDirectoryForChannel(
                channel)) and irc.isChannel(channel):
            # Nope, create one!

            self.log.info("Non-existent brainfile in {0}!".format(channel))
            self.log.info("Creating a brainfile now in {0}".format(
                self._getBrainDirectoryForChannel(channel)))

            commands.getoutput('{0} {1}'.format(self._doCommand(channel),
                                                'init'))

            text = self._cleanText(text)
            if text and len(text) > 1 and not text.isspace():

                irc.reply("Learning text: {0}".format(text))
                cobeBrain = Brain(self._getBrainDirectoryForChannel(channel))
                cobeBrain.learn(text)

            else:
                irc.error(_("No text to reply to!"), Raise=True)

        else:
            irc.error(_("Improper channel given!"), Raise=True)
コード例 #40
0
ファイル: wormgas.py プロジェクト: RodrigoTjader/wormgas
class wormgas(SingleServerIRCBot):

    channel_ids = {
        u'rw': 1,
        u'game': 1,
        u'oc': 2,
        u'ocr': 2,
        u'vw': 3,
        u'mw': 3,
        u'cover': 3,
        u'covers': 3,
        u'bw': 4,
        u'chip': 4,
        u'ch': 4,
        u'ow': 5,
        u'omni': 5,
        u'all': 5
    }

    def __init__(self):
        self.path, self.file = os.path.split(_abspath)
        self.brain = Brain(u'{}/brain.sqlite'.format(self.path))

        config_json = u'{}/config.json'.format(self.path)
        rps_json = u'{}/rps.json'.format(self.path)
        keys_json = u'{}/keys.json'.format(self.path)
        self.config = dbaccess.Config(config_json, rps_json, keys_json)

        # Load plugins
        for plug_name in self.config.get(u'plugins', list())[:]:
            public, private = self.handle_load([u'!load', plug_name])
            for m in private:
                log.info(m)

        self.mb = util.CollectionOfNamedLists(u'{}/mb.json'.format(self.path))
        self.tf = util.TitleFetcher()

        args = sys.argv[1:]
        for arg in args:
            if arg.startswith(u'--set-'):
                key, value = arg[6:].split(u'=', 1)
                print u'Setting \'{}\' to \'{}\'.'.format(key, value)
                self.config.set(key, value)

        # Set up ignore if the ignore list is non-empty.
        ignore = self.config.get(u'msg:ignore', u'')
        self.reignore = None
        if ignore:
            self.reignore = re.compile(ignore, re.IGNORECASE)

        server = self.config.get(u'irc:server')
        nick = self.config.get(u'irc:nick')
        name = self.config.get(u'irc:name')
        SingleServerIRCBot.__init__(self, [(server, 6667)], nick, name)
        self.connection.buffer_class.errors = u'replace'

    def stop(self):
        '''Save all data and shut down the bot.'''
        del self.config
        del self.brain

    def _dispatcher(self, c, e):
        et = e.type
        if et not in self._events_not_logged():
            s = e.source
            t = e.target
            log.debug(u'{}, {}, {} -- {}'.format(et, s, t, e.arguments))
        SingleServerIRCBot._dispatcher(self, c, e)

    def _aux_wa(self, query):
        '''Auxilliary function that does the Wolfram API magic.'''

        apikey = self.config.get(u'wa:apikey', None)
        if apikey is None:
            return [u'Wolfram Alpha API key not configured, cannot use !wa.']
        try:
            url = u'http://api.wolframalpha.com/v2/query'
            payload = {
                u'appid': apikey,
                u'input': query,
                u'format': u'plaintext'
            }
            r = requests.get(url, timeout=10, params=payload)
            root = xml.etree.ElementTree.fromstring(r.text.encode(u'utf-8'))
            if root.get(u'success') != u'true':
                return [u'Wolfram Alpha found no answer.']
            plaintext = root.find(u'./pod[@primary="true"]/subpod/plaintext')
            if plaintext is None:
                for pod in root.findall(u'./pod'):
                    if pod.get(u'title') != u'Input interpretation':
                        plaintext = pod.find(u'./subpod/plaintext')
                        if plaintext is not None:
                            break
            if plaintext is None:
                return [u'Error: could not find response.']
            if plaintext.text is None:
                return [u'Error: empty response.']
            return plaintext.text.splitlines()
        except requests.exceptions.Timeout:
            return [u'Error: Wolfram Alpha timed out.']
        except xml.etree.ElementTree.ParseError:
            return [u'Error: could not parse response.']
        except Exception as e:
            log.exception(e)
            return [u'Error: An unknown error occurred.']

    @command_handler(u'!wa (?P<query>.+)')
    def handle_wa(self, nick, channel, query=None):
        '''Ask something of the Wolfram Alpha API.'''

        log.info(u'{} used !wa'.format(nick))
        self.mb.clear(nick)
        result = self._aux_wa(query)

        # Private messages always get the full result
        if channel == PRIVMSG:
            self.mb.set(nick, result)
            return

        # Otherwise, check for the cooldown and respond accordingly.
        ltw = int(self.config.get(u'lasttime:wa', 0))
        ww = int(self.config.get(u'wait:wa', 0))
        if ltw < time.time() - ww:
            # If sending to the channel, send at most 5 lines.
            self.mb.set(channel, result[:5])
            self.config.set(u'lasttime:wa', time.time())
        else:
            self.mb.set(nick, result)
            wait = ltw + ww - int(time.time())
            r = u'I am cooling down. You cannot use !wa in '
            r += u'{} for another {} seconds.'.format(channel, wait)
            self.mb.add(nick, r)

    @command_handler(u'!8ball')
    def handle_8ball(self, nick, channel):
        '''Ask a question of the magic 8ball.'''

        log.info(u'{} used !8ball'.format(nick))
        self.mb.clear(nick)

        result = random.choice(self._answers_8ball())
        # Private messages always get the result.
        if channel == PRIVMSG:
            self.mb.add(nick, result)
            return

        # Otherwise, check for the cooldown and respond accordingly.
        ltb = int(self.config.get(u'lasttime:8ball', 0))
        wb = int(self.config.get(u'wait:8ball', 0))
        if ltb < time.time() - wb:
            self.mb.add(channel, result)
            if u'again' not in result:
                self.config.set(u'lasttime:8ball', time.time())
        else:
            self.mb.add(nick, result)
            wait = ltb + wb - int(time.time())
            r = u'I am cooling down. You cannot use !8ball in '
            r += u'{} for another {} seconds.'.format(channel, wait)
            self.mb.add(nick, r)

    @command_handler(r'^!$')
    def handle_bang(self, nick, channel):
        '''Get messages from the message buffer.'''

        log.info(u'{} used !'.format(nick))
        pass

    @command_handler(u'^!help(\s(?P<topic>\w+))?')
    def handle_help(self, nick, channel, topic=None):
        '''Look up help about a topic'''

        log.info(u'{} used !help'.format(nick))

        self.mb.clear(nick)
        self._help(nick, topic)

    def _help(self, nick, topic):
        is_admin = self._is_admin(nick)
        rs = list()

        chan_code_ls = u'\x02, \x02'.join(self.channel_ids.keys())
        channelcodes = (u'Channel codes are \x02{}\x02.'.format(chan_code_ls))
        notpermitted = u'You are not permitted to use this command.'
        wiki = (u'More help is available at '
                u'https://github.com/williamjacksn/wormgas/wiki')

        if topic in [u'all', None]:
            rs.append(u'Use \x02!help [<topic>]\x02 with one of these topics: '
                      u'8ball, flip, id, key, nowplaying, prevplayed, roll, '
                      u'rps, rq, wa.')
            if is_admin:
                rs.append(u'Administration topics: restart, set, stop, unset.')
            rs.append(wiki)
        elif topic == u'8ball':
            rs.append(u'Use \x02!8ball\x02 to ask a question of the magic '
                      u'8ball.')
        elif topic == u'wa':
            rs.append(u'Use \x02!wa <query>\x02 to query Wolfram Alpha.')
        elif topic == u'flip':
            rs.append(u'Use \x02!flip\x02 to flip a coin.')
        elif topic == u'id':
            rs.append(u'Look up your Rainwave user id at '
                      u'http://rainwave.cc/auth/ and use \x02!id add <id>\x02 '
                      u'to tell me about it.')
            rs.append(u'Use \x02!id drop\x02 to delete your user id and '
                      u'\x02!id show\x02 to see it.')
        elif topic == u'key':
            rs.append(u'Get an API key from http://rainwave.cc/auth/ and use '
                      u'\x02!key add <key>\x02 to tell me about it.')
            rs.append(u'Use \x02!key drop\x02 to delete your key and \x02!key '
                      u'show\x02 to see it.')
        elif topic in [u'nowplaying', u'np']:
            rs.append(u'Use \x02!nowplaying <channel>\x02 to show what is now '
                      u'playing on the radio.')
            rs.append(u'Short version is \x02!np<channel>\x02.')
            rs.append(channelcodes)
        elif topic in [u'prevplayed', u'pp']:
            rs.append(u'Use \x02!prevplayed <channel> [<index>]\x02 to show '
                      u'what was previously playing on the radio.')
            rs.append(u'Short version is \x02!pp<channel> [<index>]\x02.')
            rs.append(u'Index should be one of (0, 1, 2), 0 is default, '
                      u'higher numbers are further in the past.')
            rs.append(channelcodes)
        elif topic == u'restart':
            if is_admin:
                rs.append(u'Use \x02!restart\x02 to restart the bot.')
            else:
                rs.append(notpermitted)
        elif topic == u'roll':
            rs.append(u'Use \x02!roll [#d^]\x02 to roll a ^-sided die # '
                      u'times.')
        elif topic == u'rps':
            rs.append(u'Use \x02!rock\x02, \x02!paper\x02, or '
                      u'\x02!scissors\x02 to play a game.')
            rs.append(u'Use \x02!rps record [<nick>]\x02 to see the record '
                      u'for <nick>, leave off <nick> to see your own record, '
                      u'use nick \'!global\' to see the global record.')
            rs.append(u'Use \x02!rps stats [<nick>]\x02 to see some '
                      u'statistics for <nick>, leave off <nick> to see your '
                      u'own statistics.')
            rs.append(u'Use \x02!rps reset\x02 to reset your record and '
                      u'delete your game history, there is no confirmation '
                      u'and this cannot be undone.')
            rs.append(u'Use \x02!rps who\x02 to see a list of known players')
            if is_admin:
                rs.append(u'Administrators can use \x02!rps rename <oldnick> '
                          u'<newnick>\x02 to reassign stats and game history '
                          u'from one nick to another.')
        elif topic == u'rq':
            rs.append(u'Use \x02!rq <song_id>\x02 to add a song to your '
                      u'request queue, find the <song_id> using '
                      u'\x02!lookup\x02 or \x02!unrated\x02.')
            rs.append(u'Use \x02!rq unrated\x02 to fill your request queue '
                      u'with unrated songs.')
            rs.append(u'Use \x02!rq fav\x02 to add favourite songs to your '
                      u'request queue.')
            rs.append(u'Use \x02!rq pause\x02 to pause your request queue).')
            rs.append(u'Use \x02!rq resume\x02 to resume your request queue).')
            rs.append(u'Use \x02!rq clear\x02 to remove all songs from your '
                      u'request queue.')
        elif topic == u'set':
            if is_admin:
                rs.append(u'Use \x02!set [<id>] [<value>]\x02 to display or '
                          u'change configuration settings.')
                rs.append(u'Leave off <value> to see the current setting.')
                rs.append(u'Leave off <id> and <value> to see a list of all '
                          u'available config ids.')
            else:
                rs.append(notpermitted)
        elif topic == u'stop':
            if is_admin:
                rs.append(u'Use \x02!stop\x02 to shut down the bot.')
            else:
                rs.append(notpermitted)
        elif topic == u'unset':
            if is_admin:
                rs.append(u'Use \x02!unset <id>\x02 to remove a configuration '
                          u'setting.')
            else:
                rs.append(notpermitted)
        else:
            rs.append(u'I cannot help you with \'{}\''.format(topic))
            rs.append(wiki)

        for r in rs:
            self.mb.add(nick, r)

    @command_handler(u'^!id(\s(?P<mode>\w+))?(\s(?P<id>\d+))?')
    def handle_id(self, nick, channel, mode=None, uid=None):
        '''Manage correlation between an IRC nick and Rainwave User ID

        Arguments:
            mode: string, one of 'add', 'drop', 'show'
            uid: numeric, the person's Rainwave User ID'''

        log.info(u'{} used !id'.format(nick))

        self.mb.clear(nick)

        if mode == u'add' and user_id:
            self.config.add_id_to_nick(uid, nick)
            r = u'I assigned the user id {} to nick \'{}\'.'.format(uid, nick)
            self.mb.add(nick, r)
        elif mode == u'drop':
            self.config.drop_id_for_nick(nick)
            r = u'I dropped the user id for nick \'{}\'.'.format(nick)
            self.mb.add(nick, r)
        elif mode == u'show':
            stored_id = self.config.get_id_for_nick(nick)
            if stored_id:
                r = u'The user id for \'{}\' is {}.'.format(nick, stored_id)
                self.mb.add(nick, r)
            else:
                r = u'I do not have a user id for nick \'{}\'.'.format(nick)
                self.mb.add(nick, r)
        else:
            self._help(nick, topic=u'id')

    @command_handler(u'^!key(\s(?P<mode>\w+))?(\s(?P<key>\w{10}))?')
    def handle_key(self, nick, channel, mode=None, key=None):
        '''Manage API keys

        Arguments:
            mode: string, one of 'add', 'drop', 'show'
            key: string, the API key to add'''

        log.info(u'{} used !key'.format(nick))

        self.mb.clear(nick)

        if mode == u'add' and key:
            self.config.add_key_to_nick(key, nick)
            r = u'I assigned the API key \'{}\' to \'{}\'.'.format(key, nick)
            self.mb.add(nick, r)
        elif mode == u'drop':
            self.config.drop_key_for_nick(nick)
            r = u'I dropped the API key for \'{}\'.'.format(nick)
            self.mb.add(nick, r)
        elif mode == u'show':
            stored_id = self.config.get_key_for_nick(nick)
            if stored_id:
                r = u'The API key for \'{}\' is'.format(nick)
                r = u'{} \'{}\'.'.format(r, stored_id)
                self.mb.add(nick, r)
            else:
                r = u'I do not have an API key for nick \'{}\'.'.format(nick)
                self.mb.add(nick, r)
        else:
            self._help(nick, topic=u'key')

    def handle_load(self, tokens):
        public = list()
        private = list()

        if len(tokens) < 2:
            private.append(u'Please specify a plugin to load.')
            return public, private

        plug_name = tokens[1]
        module_name = u'plugins.{}'.format(plug_name)
        if module_name in sys.modules:
            module = reload(sys.modules[module_name])
        else:
            try:
                module = importlib.import_module(module_name)
            except ImportError:
                err = u'Error while loading plugin: {}.'.format(plug_name)
                log.exception(err)
                private.append(err)
                return public, private

        plugins = set(self.config.get(u'plugins', list()))
        plugins.add(plug_name)
        self.config.set(u'plugins', list(plugins))
        for plug_handler in inspect.getmembers(module, inspect.isclass):
            cls = plug_handler[1]
            cmd_dict = _plug_commands
            if cls.admin:
                cmd_dict = _plug_commands_admin
            for cmd in cls.cmds:
                cmd_dict[cmd] = cls.handle
                private.append(u'Loaded a command: {}.'.format(cmd))

        return public, private

    def handle_unload(self, tokens):
        public = list()
        private = list()

        if len(tokens) < 2:
            private.append(u'Please specify a plugin to load.')
            return public, private

        plug_name = tokens[1]
        module_name = u'plugins.{}'.format(plug_name)

        plugins = set(self.config.get(u'plugins', list()))
        if plug_name in plugins:
            plugins.remove(plug_name)
            self.config.set(u'plugins', list(plugins))

        if module_name in sys.modules:
            module = sys.modules.get(module_name)
            for plug_handler in inspect.getmembers(module, inspect.isclass):
                cls = plug_handler[1]
                cmd_dict = _plug_commands
                if cls.admin:
                    cmd_dict = _plug_commands_admin
                for cmd in cls.cmds:
                    if cmd in cmd_dict:
                        del cmd_dict[cmd]
                        private.append(u'Unloaded a command: {}'.format(cmd))
                    else:
                        private.append(u'Command not found: {}'.format(cmd))
        else:
            private.append(u'Plugin not loaded: {}'.format(plug_name))

        return public, private

    @command_handler(u'!restart')
    def handle_restart(self, nick, channel):
        '''Restart the bot'''

        log.info(u'{} used !restart'.format(nick))

        if self._is_admin(nick):
            self.config.set(u'restart_on_stop', 1)
            self.handle_stop(nick, channel)
        else:
            log.warning(u'{} does not have privs to use !restart'.format(nick))

    @command_handler(u'!roll(\s(?P<dice>\d+)(d(?P<sides>\d+))?)?')
    def handle_roll(self, nick, channel, dice=None, sides=None):
        '''Roll some dice'''

        log.info(u'{} used !roll'.format(nick))

        self.mb.clear(nick)

        try:
            dice = min(int(dice), 100)
        except TypeError:
            dice = 1

        try:
            sides = max(min(int(sides), 100), 1)
        except TypeError:
            sides = 20

        rolls = []
        for i in range(dice):
            rolls.append(random.randint(1, sides))

        r = u'{}d{}: '.format(dice, sides)
        if dice > 1 and dice < 11:
            r += u'[' + u', '.join(map(str, rolls)) + u'] = '
        r += u'{}'.format(sum(rolls))

        if channel == PRIVMSG:
            self.mb.add(nick, r)
            return

        ltr = int(self.config.get(u'lasttime:roll', 0))
        wr = int(self.config.get(u'wait:roll', 0))
        if ltr < time.time() - wr:
            self.mb.add(channel, r)
            self.config.set(u'lasttime:roll', time.time())
        else:
            self.mb.add(nick, r)
            wait = ltr + wr - int(time.time())
            r = u'I am cooling down. You cannot use !roll in '
            r += u'{} for another {} seconds.'.format(channel, wait)
            self.mb.add(nick, r)

    @command_handler(u'!(?P<mode>rock|paper|scissors)')
    def handle_rps(self, nick, channel, mode=None):
        '''Rock, paper, scissors'''

        if mode is None:
            return
        else:
            mode = mode.lower()

        log.info(u'{} used !{}'.format(nick, mode))

        self.mb.clear(nick)

        rps = [u'rock', u'paper', u'scissors']
        challenge = rps.index(mode)
        response = random.randint(0, 2)

        self.config.log_rps(nick, challenge, response)

        r = u'You challenge with {}. I counter with'.format(mode)
        r = u'{} {}. '.format(r, rps[response])

        if challenge == (response + 1) % 3:
            r += u'You win!'
        elif challenge == response:
            r += u'We draw!'
        elif challenge == (response + 2) % 3:
            r += u'You lose!'

        w, d, l = self.config.get_rps_record(nick)
        pw = int(float(w) / float(w + d + l) * 100)
        pd = int(float(d) / float(w + d + l) * 100)
        pl = int(float(l) / float(w + d + l) * 100)
        r += u' Your current record is '
        r += u'{}-{}-{} or {}%-{}%-{}% (w-d-l).'.format(w, d, l, pw, pd, pl)

        if channel == PRIVMSG:
            self.mb.add(nick, r)
            return

        ltr = int(self.config.get(u'lasttime:rps', 0))
        wr = int(self.config.get(u'wait:rps', 0))
        if ltr < time.time() - wr:
            self.mb.add(channel, r)
            self.config.set(u'lasttime:rps', time.time())
        else:
            self.mb.add(nick, r)
            wait = ltr + wr - int(time.time())
            r = u'I am cooling down. You cannot use !{}'.format(mode)
            r = u'{} in {} for another {} seconds.'.format(r, channel, wait)
            self.mb.add(nick, r)

    @command_handler(u'^!rps record(\s(?P<target>\S+))?')
    def handle_rps_record(self, nick, channel, target=None):
        '''Report RPS record for a nick'''

        log.info(u'{} used !rps record'.format(nick))

        self.mb.clear(nick)

        if target is None:
            target = nick

        w, d, l = self.config.get_rps_record(target)
        total = sum((w, d, l))
        r = u'RPS record for {} ({} game'.format(target, total)
        if total != 1:
            r += u's'
        r += u') is {}-{}-{} (w-d-l).'.format(w, d, l)

        if channel == PRIVMSG:
            self.mb.add(nick, r)
            return

        ltr = int(self.config.get(u'lasttime:rps', 0))
        wr = int(self.config.get(u'wait:rps', 0))
        if ltr < time.time() - wr:
            self.mb.add(channel, r)
            self.config.set(u'lasttime:rps', time.time())
        else:
            self.mb.add(nick, r)
            wait = ltr + wr - int(time.time())
            m = u'I am cooling down. You cannot use !rps in '
            m += u'{} for another {} seconds.'.format(channel, wait)
            self.mb.add(nick, m)

    @command_handler(u'!rps rename(\s(?P<old>\S+))?(\s(?P<new>\S+))?')
    def handle_rps_rename(self, nick, channel, old=None, new=None):
        '''Rename an RPS nick, useful for merging game histories'''

        log.info(u'{} used !rps rename'.format(nick))

        if self._is_admin(nick) and old and new:
            self.mb.clear(nick)
            self.config.rename_rps_player(old, new)
            r = u'I assigned RPS game history for {} to {}.'.format(old, new)
            self.mb.add(nick, r)

    @command_handler(u'^!rps reset')
    def handle_rps_reset(self, nick, channel):
        '''Reset RPS stats and delete game history for a nick'''

        log.info(u'{} used !rps reset'.format(nick))

        self.mb.clear(nick)

        self.config.reset_rps_record(nick)
        r = u'I reset your RPS record and deleted your game history.'
        self.mb.add(nick, r)

    @command_handler(u'!rps stats(\s(?P<target>\S+))?')
    def handle_rps_stats(self, nick, channel, target=None):
        '''Get some RPS statistics for a player'''

        log.info(u'{} used !rps stats'.format(nick))

        self.mb.clear(nick)

        if target is None:
            target = nick

        totals = self.config.get_rps_challenge_totals(target)
        games = sum(totals)
        if games > 0:
            r_rate = totals[0] / float(games) * 100
            p_rate = totals[1] / float(games) * 100
            s_rate = totals[2] / float(games) * 100

            r = target
            r += u' challenges with rock/paper/scissors at these rates: '
            r += u'{:3.1f}/{:3.1f}/{:3.1f}%.'.format(r_rate, p_rate, s_rate)
        else:
            r = u'{} does not play. :('.format(target)

        if channel == PRIVMSG:
            self.mb.add(nick, r)
            return

        ltr = int(self.config.get(u'lasttime:rps', 0))
        wr = int(self.config.get(u'wait:rps', 0))
        if ltr < time.time() - wr:
            self.mb.add(channel, r)
            self.config.set(u'lasttime:rps', time.time())
        else:
            self.mb.add(nick, r)
            wait = ltr + wr - int(time.time())
            r = u'I am cooling down. You cannot use !rps in {}'.format(channel)
            r = u'{} for another {} seconds.'.format(r, wait)
            self.mb.add(nick, r)

    @command_handler(u'^!rps who')
    def handle_rps_who(self, nick, channel):
        '''List all players in the RPS game history'''

        log.info(u'{} used !rps who'.format(nick))

        self.mb.clear(nick)

        players = self.config.get_rps_players()

        mlnl = int(self.config.get(u'maxlength:nicklist', 10))
        while len(players) > mlnl:
            plist = players[:mlnl]
            players[:mlnl] = []
            r = u'RPS players: ' + u', '.join(plist)
            self.mb.add(nick, r)
        r = u'RPS players: ' + u', '.join(players)
        self.mb.add(nick, r)

    @command_handler(u'^!set(\s(?P<id>\S+))?(\s(?P<value>.+))?')
    def handle_set(self, nick, channel, id=None, value=None):
        '''View and set bot configuration'''

        log.info(u'{} used !set'.format(nick))

        self.mb.clear(nick)

        if self._is_admin(nick):
            self.mb.set(nick, self.config.handle(id, value))
        else:
            log.warning(u'{} does not have privs to use !set'.format(nick))

    @command_handler(u'!stop')
    def handle_stop(self, nick, channel):
        '''Shut down the bot'''

        log.info(u'{} used !stop'.format(nick))

        if self._is_admin(nick):
            if self.config.get(u'restart_on_stop'):
                self.config.unset(u'restart_on_stop')
                pid = subprocess.Popen(
                    [_abspath],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    stdin=subprocess.PIPE)
            self.die(u'I was stopped by {}'.format(nick))
        else:
            log.warning(u'{} does not have privs to use !stop'.format(nick))

    @command_handler(u'^!unset(\s(?P<id>\S+))?')
    def handle_unset(self, nick, channel, id=None):
        '''Unset a configuration item'''

        log.info(u'{} used !unset'.format(nick))

        if self._is_admin(nick):
            if id:
                self.config.unset(id)
                self.mb.clear(nick)
                self.mb.add(nick, u'{} has been unset.'.format(id))
                return
        else:
            log.warning(u'{} does not have privs to use !unset'.format(nick))

    def on_join(self, c, e):
        '''This method is called when an IRC join event happens

        Arguments:
            c: the Connection object asociated with this event
            e: the Event object'''

        nick = e.source.nick
        irc_chan = e.target

        # Check for a join response
        jr = self.config.get(u'joinresponse:{}'.format(nick))
        if jr:
            self._to_irc(c, u'privmsg', irc_chan, jr)

        ja = self.config.get(u'joinaction:{}'.format(nick))
        if ja:
            self._to_irc(c, u'action', irc_chan, ja)

    def on_ping(self, c, e):
        '''This method is called when an IRC ping event happens'''

        # Start the periodic tasks.
        self._periodic(c)

    def on_privmsg(self, c, e):
        '''This method is called when a message is sent directly to the bot

        Arguments:
            c: the Connection object associated with this event
            e: the Event object'''

        nick = e.source.nick
        me = e.target
        msg = e.arguments[0].strip()
        chan = self.config.get(u'irc:channel')

        command_handled = False

        # Core commands
        tokens = msg.split()
        if len(tokens) == 0:
            return
        cmd = tokens[0].lower()
        if cmd == u'!load':
            command_handled = True
            if self._is_admin(nick):
                public, private = self.handle_load(tokens)
                self.mb.set(chan, public)
                self.mb.set(nick, private)
            else:
                self.mb.add(nick, u'You are not an admin.')

        if cmd == u'!unload':
            command_handled = True
            if self._is_admin(nick):
                public, private = self.handle_unload(tokens)
                self.mb.set(chan, public)
                self.mb.set(nick, private)
            else:
                self.mb.add(nick, u'You are not an admin.')

        # Try admin commands from plugins
        if not command_handled:
            if self._is_admin(nick) and cmd in _plug_commands_admin:
                command_handled = True
                handler = _plug_commands_admin.get(cmd)
                try:
                    public, private = handler(nick, me, tokens, self.config)
                    self.mb.set(chan, public)
                    self.mb.set(nick, private)
                except:
                    log.exception(u'Exception in {}'.format(cmd))
                    m = (u'I experienced a problem and recorded some '
                         u'exception information in the log.')
                    self.mb.set(nick, [m])

        # Try normal commands from plugins
        if not command_handled:
            if cmd in _plug_commands:
                command_handled = True
                handler = _plug_commands.get(cmd)
                try:
                    public, private = handler(nick, me, tokens, self.config)
                    self.mb.set(chan, public)
                    self.mb.set(nick, private)
                except:
                    log.exception(u'Exception in {}'.format(cmd))
                    m = (u'I experienced a problem and recorded some '
                         u'exception information in the log.')
                    self.mb.set(nick, [m])

        # Try all the decorated command handlers
        for command in _commands:
            if command(self, nick, msg, PRIVMSG):
                command_handled = True
                break

        if not command_handled:
            # No responses from the commands, punt to the brain
            self.mb.clear(nick)
            self.mb.add(nick, self._talk(msg))

        # Send responses
        while self.mb.items(chan):
            self._to_irc(c, u'privmsg', chan, self.mb.pop(chan, 0))

        rs = list()
        while len(rs) < 7 and self.mb.items(nick):
            rs.append(self.mb.pop(nick, 0))

        if len(self.mb.items(nick)) == 1:
            rs.append(self.mb.pop(nick, 0))

        if len(self.mb.items(nick)) > 1:
            num = len(self.mb.items(nick))
            r = u'Use \x02!\x02 to see more messages ({} left).'.format(num)
            rs.append(r)

        for r in rs:
            self._to_irc(c, u'privmsg', nick, r)

    def on_pubmsg(self, c, e):
        '''This method is called when a message is sent to the channel the bot
        is on

        Arguments:
            c: the Connection object associated with this event
            e: the Event object'''

        nick = e.source.nick
        msg = e.arguments[0].strip()
        chan = e.target

        command_handled = False

        # Core commands
        tokens = msg.split()
        if len(tokens) == 0:
            return
        cmd = tokens[0].lower()
        if cmd == u'!load':
            command_handled = True
            if self._is_admin(nick):
                public, private = self.handle_load(tokens)
                self.mb.set(chan, public)
                self.mb.set(nick, private)
            else:
                self.mb.add(nick, u'You are not an admin.')

        if cmd == u'!unload':
            command_handled = True
            if self._is_admin(nick):
                public, private = self.handle_unload(tokens)
                self.mb.set(chan, public)
                self.mb.set(nick, private)
            else:
                self.mb.add(nick, u'You are not an admin.')

        # Try admin commands from plugins
        if not command_handled:
            if self._is_admin(nick) and cmd in _plug_commands_admin:
                command_handled = True
                handler = _plug_commands_admin.get(cmd)
                try:
                    public, private = handler(nick, chan, tokens, self.config)
                    self.mb.set(chan, public)
                    self.mb.set(nick, private)
                except:
                    log.exception(u'Exception in {}'.format(cmd))
                    m = (u'I experienced a problem and recorded some '
                         u'exception information in the log.')
                    self.mb.set(nick, [m])

        # Try normal commands from plugins
        if not command_handled:
            if cmd in _plug_commands:
                command_handled = True
                handler = _plug_commands.get(cmd)
                try:
                    public, private = handler(nick, chan, tokens, self.config)
                    self.mb.set(chan, public)
                    self.mb.set(nick, private)
                except:
                    log.exception(u'Exception in {}'.format(cmd))
                    m = (u'I experienced a problem and recorded some '
                         u'exception information in the log.')
                    self.mb.set(nick, [m])

        # Try all the decorated command handlers
        if not command_handled:
            for command in _commands:
                if command(self, nick, msg, chan):
                    command_handled = True
                    break

        # If there are no responses from the commands, look for URLs
        title_found = False
        if not command_handled:
            urls = self._find_urls(msg)
            for url in urls:
                title = None
                try:
                    title = self.tf.get_title(url)
                except util.TitleFetcherError as err:
                    log.exception(err)
                if title:
                    log.info(u'Found a title: {}'.format(title))
                    title_found = True
                    self.mb.add(chan, u'[ {} ]'.format(title))

        # If there are no URLs, punt to the brain
        if not (command_handled or title_found):
            talkr = self._talk(msg)
            if talkr:
                self.config.set(u'msg:last', msg)
                self.config.set(u'lasttime:msg', time.time())
                ltr = int(self.config.get(u'lasttime:respond', 0))
                wr = int(self.config.get(u'wait:respond', 0))

                if self.config.get(u'irc:nick') in msg:
                    if time.time() > ltr + wr:
                        self.mb.add(chan, talkr)
                        self.config.set(u'msg:last', talkr)
                        self.config.set(u'lasttime:respond', time.time())
                    else:
                        self._to_irc(c, u'privmsg', nick, talkr)
                        wait = ltr + wr - int(time.time())
                        r = u'I am cooling down. I cannot respond in '
                        r += u'{} for another {} seconds.'.format(chan, wait)
                        self._to_irc(c, u'privmsg', nick, r)

        # Send responses
        while self.mb.items(chan):
            r = u'{}: {}'.format(nick, self.mb.pop(chan, 0))
            self._to_irc(c, u'privmsg', chan, r)

        if command_handled:
            rs = list()
            while len(rs) < 7 and self.mb.items(nick):
                rs.append(self.mb.pop(nick, 0))

            if len(self.mb.items(nick)) == 1:
                rs.append(self.mb.pop(nick, 0))

            if len(self.mb.items(nick)) > 1:
                n = len(self.mb.items(nick))
                r = u'Use \x02!\x02 to see more messages ({} left).'.format(n)
                rs.append(r)

            for r in rs:
                self._to_irc(c, u'privmsg', nick, r)

    def on_welcome(self, c, e):
        '''This method is called when the bot first connects to the server

        Arguments:
            c: the Connection object associated with this event
            e: the Event object'''

        passwd = self.config.get(u'irc:nickservpass')
        if passwd is not None:
            m = u'identify {}'.format(passwd)
            self._to_irc(c, u'privmsg', u'nickserv', m)
        c.join(self.config.get(u'irc:channel'))

    def _answers_8ball(self):
        return [
            u'As I see it, yes.',
            u'Ask again later.',
            u'Better not tell you now.',
            u'Cannot predict now.',
            u'Concentrate and ask again.',
            u'Don\'t count on it.',
            u'It is certain.',
            u'It is decidedly so.',
            u'Most likely.',
            u'My reply is no.',
            u'My sources say no.',
            u'Outlook good.',
            u'Outlook not so good.',
            u'Reply hazy, try again.',
            u'Signs point to yes.',
            u'Very doubtful.',
            u'Without a doubt.',
            u'Yes.',
            u'Yes - definitely.',
            u'You may rely on it.'
        ]

    def _events_not_logged(self):
        return [
            u'all_raw_messages',
            u'created',
            u'endofmotd',
            u'featurelist',
            u'luserchannels',
            u'luserclient',
            u'luserme',
            u'luserop',
            u'luserunknown',
            u'motd',
            u'motdstart',
            u'myinfo',
            u'n_global',
            u'n_local'
        ]

    def _find_urls(self, text):
        '''Look for URLs in arbitrary text. Return a list of the URLs found.'''

        log.info(u'Looking for URLs in: {}'.format(text))

        urls = []
        for token in text.split():
            try:
                o = urlparse(token)
            except ValueError:
                log.exception(u'Trouble looking for URLs.')
                return urls
            if u'http' in o.scheme and o.netloc:
                url = o.geturl()
                log.info(u'Found a URL: {}'.format(url))
                urls.append(url)
        return urls

    def _is_admin(self, nick):
        '''Check whether a nick has privileges to use admin commands'''

        channel = self.config.get(u'irc:channel').encode(u'ascii')
        if channel in self.channels:
            chan = self.channels[channel]
            if nick in chan.owners():
                return True
            elif nick in chan.opers():
                return True
            elif nick in chan.halfops():
                return True

        return False

    def _periodic(self, c):
        # If I have not checked for forum activity for 'timeout:forumcheck'
        # seconds, check now

        log.info(u'Performing periodic tasks')

        chan = self.config.get(u'irc:channel')

        ltm = int(self.config.get(u'lasttime:msg', 0))
        toc = int(self.config.get(u'timeout:chat', 3600))
        if int(time.time()) > ltm + toc:
            log.info(u'Chat timeout exceeded, keep the conversation moving')
            talkr = self._talk()
            if talkr:
                self.config.set(u'msg:last', talkr)
                self.config.set(u'lasttime:msg', time.time())
                self.config.set(u'lasttime:respond', time.time())
                self.mb.add(chan, talkr)

        while self.mb.items(chan):
            self._to_irc(c, u'privmsg', chan, self.mb.pop(chan, 0))

    quotes = [
        (u'Attack the evil that is within yourself, rather than attacking the '
         u'evil that is in others.'),
        u'Before you embark on a journey of revenge, dig two graves.',
        u'Better a diamond with a flaw than a pebble without.',
        u'Everything has beauty, but not everyone sees it.',
        u'He who knows all the answers has not been asked all the questions.',
        (u'He who learns but does not think, is lost! He who thinks but does '
         u'not learn is in great danger.'),
        u'I hear and I forget. I see and I remember. I do and I understand.',
        (u'If what one has to say is not better than silence, then one should '
         u'keep silent.'),
        (u'If you make a mistake and do not correct it, this is called a '
         u'mistake.'),
        (u'Ignorance is the night of the mind but a night without moon and '
         u'star.'),
        (u'Music produces a kind of pleasure which human nature cannot do '
         u'without.'),
        u'Only the wisest and stupidest of men never change.',
        (u'Our greatest glory is not in never falling, but in rising every '
         u'time we fall.'),
        u'Respect yourself and others will respect you.',
        u'Silence is a true friend who never betrays.',
        (u'The hardest thing of all is to find a black cat in a dark room, '
         u'especially if there is no cat.'),
        (u'The man who asks a question is a fool for a minute, the man who '
         u'does not ask is a fool for life.'),
        (u'The superior man is modest in his speech, but exceeds in his '
         u'actions.'),
        u'To be wronged is nothing, unless you continue to remember it.',
        (u'To see what is right and not to do it, is want of courage or of '
         u'principle.'),
        (u'What you know, you know, what you don\'t know, you don\'t know. '
         u'This is true wisdom.')
    ]

    def _talk(self, msg=None):
        '''Engage the brain, respond when appropriate

        Arguments:
            msg: the message to learn and possible reply to

        Returns: a string'''

        # If I am not replying to anything in particular, use the last message
        if msg is None:
            msg = self.config.get(u'msg:last')
        if msg is None:
            return random.choice(self.quotes)

        # Ignore messages with certain words
        if self.reignore:
            result = self.reignore.search(msg)
            if result is not None:
                return random.choice(self.quotes)

        # Clean up the message before sending to the brain
        tobrain = msg
        tobrain = tobrain.replace(self.config.get(u'irc:nick'), u'')
        tobrain = tobrain.replace(u':', u'')

        self.brain.learn(tobrain)

        return self.brain.reply(tobrain)

    def _to_irc(self, c, msgtype, target, msg):
        '''Send an IRC message'''

        log.debug(u'Sending {} to {} -- {}'.format(msgtype, target, msg))

        if hasattr(c, msgtype):
            f = getattr(c, msgtype)
            if type(msg) is not unicode:
                msg = unicode(msg, u'utf-8')
            try:
                f(target, msg)
            except:
                log.exception(u'Problem sending to IRC')
        else:
            log.error(u'Invalid message type \'{}\''.format(msgtype))
コード例 #41
0
ファイル: test_brain.py プロジェクト: CrazyPython/cobe
    def testEmptyReply(self):
        Brain.init(TEST_BRAIN_FILE)

        brain = Brain(TEST_BRAIN_FILE)
        self.assertTrue(brain.reply("") is not "")