Supybot-plugins/Cleverbot/plugin.py

155 lines
5.5 KiB
Python

# CleverBot Supybot Plugin v1.0
# (C) Copyright 2012 Albert H. (alberthrocks)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import supybot.utils as utils
from supybot.commands import *
import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
import re, random, time, sys
if sys.version_info[0] >= 3:
from html.entities import name2codepoint
else:
from htmlentitydefs import name2codepoint
from . import cleverbot
class Cleverbot(callbacks.Plugin):
"""This plugin replies using the Cleverbot API upon intercepting an invalid command."""
threaded = True
callAfter = ['MoobotFactoids','Factoids','Infobot']
def __init__(self,irc):
self.__parent = super(Cleverbot,self)
self.__parent.__init__(irc)
self.nicks = {}
self.hashes = {}
self.sessions = {}
@staticmethod
def decode_htmlentities(s):
def substitute_entity(match):
ent = match.group(3)
if match.group(1) == "#": # number, decimal or hexadecimal
return unichr(int(ent)) if match.group(2) == '' else unichr(int('0x'+ent,16))
else: # name
cp = name2codepoint.get(ent)
return unichr(cp) if cp else match.group()
return re.compile(r'&(#?)(x?)(\w+);').subn(substitute_entity,s)[0]
@staticmethod
def _randHash():
return '%016x'%random.getrandbits(64)
@classmethod
def _post(cls,bot,hash,line,sess):
m = sess.Ask(line)
if m:
return m
return None
@classmethod
def _identify(cls,bot,hash,name):
return cleverbot.Session()
def getHash(self,nick):
nick = nick.lower()
if nick not in self.nicks:
self.nicks[nick] = self._randHash()
return self.nicks[nick]
def getResponse(self,irc,msg,line):
hash = self.getHash(msg.nick)
args = (self.registryValue('bot'),hash)
if hash not in self.hashes or time.time()-self.hashes[hash] > 300:
sess = self._identify(*(args+(msg.nick,)))
self.sessions[hash] = sess
else:
sess = self.sessions[hash]
self.hashes[hash] = time.time()
line = re.compile(r'\b'+re.escape(irc.nick)+r'\b',re.I).sub('you',re.compile(r'^'+re.escape(irc.nick)+r'\S',re.I).sub('',line))
reply = self._post(*(args+(line,sess,)))
if reply is None:
return None
name = self.registryValue('name')
return reply
def invalidCommand(self,irc,msg,tokens):
try:
self.log.debug('Channel is: "+str(irc.isChannel(msg.args[0]))')
self.log.debug("Message is: "+str(msg.args))
except:
self.log.error("message not retrievable.")
if irc.isChannel(msg.args[0]) and self.registryValue('react',msg.args[0]):
channel = msg.args[0]
self.log.debug("Fetching response...")
reply = self.getResponse(irc,msg,ircutils.stripFormatting(msg.args[1]).strip())
self.log.debug("Got response!")
if reply is not None:
self.log.debug("Reply is: "+str(reply))
if self.registryValue('enable', channel):
irc.reply(reply)
else:
irc.reply("My AI is down, sorry! :( I couldn't process what you said... blame it on a brain fart. :P")
elif (msg.args[0] == irc.nick) and self.registryValue('reactprivate',msg.args[0]):
err = ""
self.log.debug("Fetching response...")
reply = self.getResponse(irc,msg,ircutils.stripFormatting(msg.args[1]).strip())
self.log.debug("Got response!")
if reply is not None:
self.log.debug("Reply is: "+str(reply))
if self.registryValue('enable', channel):
irc.reply(reply)
else:
irc.reply("My AI is down, sorry! :( I couldn't process what you said... blame it on a brain fart. :P", err, None, True, None, None)
def Cleverbot(self,irc,msg,args,line):
"""<line>
Fetches response from Cleverbot
"""
reply = self.getResponse(irc,msg,line)
if reply is not None:
irc.reply('Cleverbot: %s'%reply)
else:
irc.reply('There was no response.')
Cleverbot = wrap(Cleverbot,['text'])
def doNick(self,irc,msg):
try:
del self.nicks[msg.nick.lower()]
except KeyError:
pass
self.nicks[msg.args[0].lower()] = self._randHash()
self._identify(self.registryValue('bot'),self.getHash(msg.args[0].lower()),msg.args[0])
# def doKick(self,irc,msg):
# del self.nicks[msg.args[1]]
# def doPart(self,irc,msg):
# del self.nicks[msg.nick.lower()]
def doQuit(self,irc,msg):
try:
del self.nicks[msg.nick.lower()]
except KeyError:
pass
Class = Cleverbot
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79: