New command [!chat]

Now it's possible to chat with the cleverbot
This commit is contained in:
Markus 2016-01-16 18:09:36 +01:00
parent f4fd244554
commit c1d73c3038
2 changed files with 195 additions and 0 deletions

176
cleverbot3.py Normal file
View File

@ -0,0 +1,176 @@
"""Python library allowing interaction with the Cleverbot API."""
import http.cookiejar
import hashlib
import urllib.request, urllib.parse, urllib.error
import urllib.request, urllib.error, urllib.parse
from urllib.parse import unquote
import html
class Cleverbot:
"""
Wrapper over the Cleverbot API.
"""
HOST = "www.cleverbot.com"
PROTOCOL = "http://"
RESOURCE = "/webservicemin"
API_URL = PROTOCOL + HOST + RESOURCE
headers = {
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)',
'Accept': 'text/html,application/xhtml+xml,'
'application/xml;q=0.9,*/*;q=0.8',
'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Accept-Language': 'en-us,en;q=0.8,en-us;q=0.5,en;q=0.3',
'Cache-Control': 'no-cache',
'Host': HOST,
'Referer': PROTOCOL + HOST + '/',
'Pragma': 'no-cache'
}
def __init__(self):
""" The data that will get passed to Cleverbot's web API """
self.data = {
'stimulus': '',
'start': 'y', # Never modified
'sessionid': '',
'vText8': '',
'vText7': '',
'vText6': '',
'vText5': '',
'vText4': '',
'vText3': '',
'vText2': '',
'icognoid': 'wsf', # Never modified
'icognocheck': '',
'fno': 0, # Never modified
'prevref': '',
'emotionaloutput': '', # Never modified
'emotionalhistory': '', # Never modified
'asbotname': '', # Never modified
'ttsvoice': '', # Never modified
'typing': '', # Never modified
'lineref': '',
'sub': 'Say', # Never modified
'islearning': 1, # Never modified
'cleanslate': False, # Never modified
}
# the log of our conversation with Cleverbot
self.conversation = []
self.resp = str()
# install an opener with support for cookies
cookies = http.cookiejar.LWPCookieJar()
handlers = [
urllib.request.HTTPHandler(),
urllib.request.HTTPSHandler(),
urllib.request.HTTPCookieProcessor(cookies)
]
opener = urllib.request.build_opener(*handlers)
urllib.request.install_opener(opener)
# get the main page to get a cookie (see bug #13)
try:
urllib.request.urlopen(Cleverbot.PROTOCOL + Cleverbot.HOST)
except urllib.error.HTTPError:
# TODO errors shouldn't pass unnoticed,
# here and in other places as well
return str()
def ask(self, question):
"""Asks Cleverbot a question.
Maintains message history.
Args:
q (str): The question to ask
Returns:
Cleverbot's answer
"""
# Set the current question
self.data['stimulus'] = question
# Connect to Cleverbot's API and remember the response
try:
self.resp = self._send()
except urllib.error.HTTPError:
# request failed. returning empty string
return str()
# Add the current question to the conversation log
self.conversation.append(question)
parsed = self._parse()
# Set data as appropriate
if self.data['sessionid'] != '':
self.data['sessionid'] = parsed['conversation_id']
# Add Cleverbot's reply to the conversation log
self.conversation.append(parsed['answer'])
return html.unescape(parsed['answer'])
def _send(self):
"""POST the user's question and all required information to the
Cleverbot API
Cleverbot tries to prevent unauthorized access to its API by
obfuscating how it generates the 'icognocheck' token, so we have
to URLencode the data twice: once to generate the token, and
twice to add the token to the data we're sending to Cleverbot.
"""
# Set data as appropriate
if self.conversation:
linecount = 1
for line in reversed(self.conversation):
linecount += 1
self.data['vText' + str(linecount)] = line
if linecount == 8:
break
# Generate the token
enc_data = urllib.parse.urlencode(self.data)
digest_txt = enc_data[9:35]
digest_txt = bytearray(digest_txt, 'utf-8')
token = hashlib.md5(digest_txt).hexdigest()
self.data['icognocheck'] = token
# Add the token to the data
enc_data = urllib.parse.urlencode(self.data)
enc_data = bytearray(enc_data, 'utf-8')
req = urllib.request.Request(self.API_URL, enc_data, self.headers)
# POST the data to Cleverbot's API
conn = urllib.request.urlopen(req)
resp = conn.read()
# Return Cleverbot's response
return resp
def _parse(self):
"""Parses Cleverbot's response"""
resp = self.resp.decode('utf-8')
parsed = [
item.split('\r') for item in resp.split('\r\r\r\r\r\r')[:-1]
]
try:
parsed_dict = {
'answer': parsed[0][0],
'conversation_id': parsed[0][1],
'conversation_log_id': parsed[0][2],
}
except:
parsed_dict = {
'answer': parsed[0][0],
'conversation_id': parsed[0][1],
'conversation_log_id': 'not found',
}
try:
parsed_dict['unknown'] = parsed[1][-1]
except IndexError:
parsed_dict['unknown'] = None
return parsed_dict

19
red.py
View File

@ -16,6 +16,7 @@ import aiohttp
import traceback
import re
import youtube_dl
import cleverbot3
import os
import asyncio
import glob
@ -44,6 +45,7 @@ help = """**Commands list:**
!roll [number] - Random number between 0 and [number]
!gif [text] - GIF search
!urban [text] - Search definitions in the urban dictionary
!chat [text] - Chat with the Cleverbot
!customcommands - Custom commands' list
!addcom [command] [text] - Add a custom command
!editcom [command] [text] - Edit a custom command
@ -202,6 +204,8 @@ async def on_message(message):
await gif(message)
elif message.content.startswith('!urban'):
await urban(message)
elif message.content.startswith('!chat'):
await chat(message)
elif message.content.startswith('!uptime'):
await uptime(message)
elif message.content.startswith('!avatar'):
@ -844,6 +848,21 @@ async def urban(message):
else:
await client.send_message(message.channel, "!urban [text]")
async def chat(message):
msg = message.content.split()
if len(msg) > 1:
try:
msg.remove(msg[0])
msg = "+".join(msg)
question = msg
answer = cleverbot_client.ask(question)
if msg != "":
await client.send_message(message.channel, "{}: ".format(message.author.mention) + answer)
except:
await client.send_message(message.channel, "Error.")
else:
await client.send_message(message.channel, "!chat [text]")
async def gif(message):
msg = message.content.split()
if len(msg) > 1: