diff --git a/clever.py b/clever.py new file mode 100644 index 0000000..aaaf3a7 --- /dev/null +++ b/clever.py @@ -0,0 +1,120 @@ +# -*- coding: utf-8 -*- +from twython import Twython + +import os +import time +import sys +import time +import cleverbottwo +import eliza +import datetime +from random import choice, randint +from creds import * +#import any other natual processing libs + + +"""Serialize function. Writes the last_reply_id to the file ~/.twitter_last_reply""" +def cleanup(last_id): + try: + filename = os.environ.get("HOME",'')+os.sep+'.twitter_last_reply' + f = file(filename, 'w') + f.write(last_id) + f.close() + except IOError: + print "[!] ERROR could not open", filename + + +#These are the keys from the twitter tools for python library. +CONSUMER_KEY = 'uS6hO2sV6tDKIOeVjhnFnQ' +CONSUMER_SECRET = 'MEYTOS97VvlHX7K1rwHPEqVpTSqZ71HtvoK4sVuYk' + +# input your bot handle +handle = "@silshack" + +clock = datetime.datetime.now() + +doctor = eliza.eliza() + +doctorisms = [" Mmkay?", " Hmmm?", " :/", " :)", " I mean...."] + +statuses = [u' (╯°□°)╯︵ ┻━┻)', + u'I drifted off there for a bit....Ƹ̵̡Ӝ̵̨̄Ʒ', + u'¯\_(ツ)_/¯ wah wahh', + u'Time for a fish: .·´¯`·.´¯`·.¸¸.·´¯`·.¸><(((º>', + u'I wish I owned a little cabin somewhere. __̴ı̴̴̡̡̡ ̡͌l̡̡̡ ̡͌l̡*̡̡ ̴̡ı̴̴̡ ̡̡͡|̲̲̲͡͡͡ ̲▫̲͡ ̲̲̲͡͡π̲̲͡͡ ̲̲͡▫̲̲͡͡ ̲|̡̡̡ ̡ ̴̡ı̴̡̡ ̡͌l̡̡̡̡.___', + u'HANDS OFF MY SERVERS ̿\̵͇̿̿\з=(◕_◕)=ε/̵͇̿̿/', + u'ˁ˚ᴥ˚ˀ That is all.', + u'()==[:::::::::::::>', + u'▇ ▅ █ ▅ ▇ ▂ ▃ ▁ ▁ ▅ ▃ ▅ ▅ ▄ ▅ ▇'] + + +if __name__ == "__main__": + + #anyone talking to us? + last_id_replied = '' + speaker_id = '' + message_id = '' + + #we serialize into a file in ~/.twitter_last_reply. check if this file is present and read value. + last_file = os.environ.get("HOME",'')+os.sep+'.twitter_last_reply' + if os.path.exists(last_file): + try: + id_file=file(last_file , 'r') + id = id_file.readline() + last_id_replied = id.strip() + print "[+] Read last_reply_id", last_id_replied + except IOError: + print"[!] Could not read ", last_file + else: print"[!] Didn't find ~/.twitter_last_reply file.. starting fresh prince" + + #twitter client to post. Posting requires oAuth schutff + twitter = Twython(APP_KEY, APP_SECRET, FINAL_OAUTH_TOKEN, FINAL_OAUTH_TOKEN_SECRET) + + #our cleverbot instance + cbot=cleverbottwo.Session() + #main loop. Just keep searching anyone talking to us + while True: + try: + mentions = twitter.search(q=handle, since_id=last_id_replied)['statuses'] + if not mentions: + print "No one talking to us now...", time.ctime() + for mention in mentions[:3]: + #cut our handle out + message = mention['text'].replace(handle , '') + message_id = mention['id'] + speaker = mention['user']['screen_name'] + + speaker_id = str(mention['user']['id']) + print "[+] Something named "+speaker+" is saying "+message + + # If it's not the bot speaking: + if speaker != handle[1:]: + # follow the user + twitter.create_friendship(screen_name = speaker, follow = "true") + #clever_response = cbot.Ask(message) + clever_response = doctor.respond(message.strip()) + reply = '@%s %s' % (speaker, clever_response + choice(doctorisms)) + print "[+] Replying " , reply + twitter.update_status(status=reply, in_reply_to_status_id = message_id) + #update last_id_replied + last_id_replied=str(int(message_id) + 1) + cleanup(last_id_replied) + + print "Last message_id was ", message_id + print "[Zzz] Slumber...\n" + time.sleep(10) + hour = clock.hour + if randint(1, 10000) < 416: + if hour > 10 and time.hour < 24: + zzz = "z" * randint(1,10) + "." * randint(1,25) + twitter.update_status(status==zzz) + stat = choice(statuses) + print "Soooo bored. Saying something random now:" + print stat + twitter.update_status(status=stat) + + except KeyboardInterrupt: + print"[!] Cleaning up. Last speaker_id was ", speaker_id, ". Last message_id was ", message_id + cleanup(last_id_replied) + sys.exit() + diff --git a/cleverbot.py b/cleverbot.py new file mode 100644 index 0000000..1b8f894 --- /dev/null +++ b/cleverbot.py @@ -0,0 +1,167 @@ +""" +Extracted source from https://pypi.python.org/pypi/cleverbot/0.1.1 +""" + +from hashlib import md5 +import pprint +import urllib, urllib2 + +class Cleverbot: + + HOST = "www.cleverbot.com" + PROTOCOL = "http://" + RESOURCE = "/webservicemin" + API_URL = PROTOCOL + HOST + RESOURCE + + DEBUG = False + + 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, debug=False): + self.DEBUG = debug + self.__debug("Initializing new session") + + """ 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=[] + + def ask(self,q): + """Asks Cleverbot a question. + + Maintains message history. + + Args: + q (str): The question to ask + Returns: + Cleverbot's answer + """ + self.__debug("Asking a question", q) + + # Set the current question + self.data['stimulus'] = q + + # Connect to Cleverbot's API and remember the response + resp = self._send() + + # TODO ensure Cleverbot received the question properly + + # Add the current question to the conversation log + self.conversation.append(q) + + #parsed = self._parse(resp) + + # 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 parsed['answer'] + return resp + + + 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. + """ + self.__debug("Sending data") + + # 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.urlencode(self.data) + digest_txt = enc_data[9:29] + token = md5(digest_txt).hexdigest() + self.data['icognocheck'] = token + + # Add the token to the data + enc_data = urllib.urlencode(self.data) + req = urllib2.Request(self.API_URL, enc_data, self.headers) + + # POST the data to Cleverbot's API + conn = urllib2.urlopen(req) + resp = conn.read() + + # Return Cleverbot's response + return resp + + def _parse(self, text): + """Parses Cleverbot's response""" + + self.__debug("Parsing response") + + parsed = map(lambda e: e.split('\r'), text.split('\r\r\r\r\r\r')[:-1]) + + return \ + { 'answer' : parsed[0][0] + , 'conversation_id' : parsed[0][1] + , 'conversation_log_id' : parsed[0][2] + , 'unknown': parsed[1][-1] + } + + def __debug(self, *args): + """Print stuff to stdin if DEBUG is true""" + + if self.DEBUG: + print args + +if __name__ == "__main__": + cb1 = Cleverbot() + cb2 = Cleverbot() + + resp1 = cb1.ask("Hello.") + print "Bob:", "Hello" + + while True: + print "Alice:", resp1 + resp2 = cb2.ask(resp1) + print "Bob:", resp2 + resp1 = cb1.ask(resp2) diff --git a/cleverbottwo.py b/cleverbottwo.py new file mode 100644 index 0000000..3ec7489 --- /dev/null +++ b/cleverbottwo.py @@ -0,0 +1,116 @@ +#!/usr/bin/python +""" +I, Ward Lanssens, did not create this code. It is just here to have an easy way to access it. + +This library lets you open chat session with cleverbot (www.cleverbot.com) + +Example of how to use the bindings: + +>>> import cleverbot +>>> cb=cleverbot.Session() +>>> print cb.Ask("Hello there") +'Hello.' + +""" + +import urllib2 +import hashlib +import re + +class ServerFullError(Exception): + pass + +ReplyFlagsRE = re.compile('', re.IGNORECASE | re.MULTILINE) + +class Session(object): + keylist=['stimulus','start','sessionid','vText8','vText7','vText6','vText5','vText4','vText3','vText2','icognoid','icognocheck','prevref','emotionaloutput','emotionalhistory','asbotname','ttsvoice','typing','lineref','fno','sub','islearning','cleanslate'] + headers={} + headers['User-Agent']='Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0' + headers['Accept']='text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' + headers['Accept-Language']='en-us;q=0.8,en;q=0.5' + headers['X-Moz']='prefetch' + headers['Accept-Charset']='ISO-8859-1,utf-8;q=0.7,*;q=0.7' + headers['Referer']='http://www.cleverbot.com' + headers['Cache-Control']='no-cache, no-cache' + headers['Pragma']='no-cache' + + def __init__(self): + self.arglist=['','y','','','','','','','','','wsf','','','','','','','','','0','Say','1','false'] + self.MsgList=[] + + def Send(self): + data=encode(self.keylist,self.arglist) + digest_txt=data[9:29] + hash=hashlib.md5(digest_txt).hexdigest() + self.arglist[self.keylist.index('icognocheck')]=hash + data=encode(self.keylist,self.arglist) + req=urllib2.Request("http://www.cleverbot.com/webservicemin",data,self.headers) + f=urllib2.urlopen(req) + reply=f.read() + return reply + + def Ask(self,q): + self.arglist[self.keylist.index('stimulus')]=q + if self.MsgList: self.arglist[self.keylist.index('lineref')]='!0'+str(len(self.MsgList)/2) + asw=self.Send() + self.MsgList.append(q) + answer = parseAnswers(asw) + for k,v in answer.iteritems(): + try: + self.arglist[self.keylist.index(k)] = v + except ValueError: + pass + self.arglist[self.keylist.index('emotionaloutput')]='' + text = answer['ttsText'] + self.MsgList.append(text) + return text + +def parseAnswers(text): + d = {} + keys = ["text", "sessionid", "logurl", "vText8", "vText7", "vText6", "vText5", "vText4", "vText3", + "vText2", "prevref", "foo", "emotionalhistory", "ttsLocMP3", "ttsLocTXT", + "ttsLocTXT3", "ttsText", "lineRef", "lineURL", "linePOST", "lineChoices", + "lineChoicesAbbrev", "typingData", "divert"] + values = text.split("\r") + i = 0 + for key in keys: + d[key] = values[i] + i += 1 + return d + +def encode(keylist,arglist): + text='' + for i in range(len(keylist)): + k=keylist[i]; v=quote(arglist[i]) + text+='&'+k+'='+v + text=text[1:] + return text + +always_safe = ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789' '_.-') +def quote(s, safe = '/'): #quote('abc def') -> 'abc%20def' + safe += always_safe + safe_map = {} + for i in range(256): + c = chr(i) + safe_map[c] = (c in safe) and c or ('%%%02X' % i) + res = map(safe_map.__getitem__, s) + return ''.join(res) + + +def main(): + import sys + cb = Session() + + q = '' + while q != 'bye': + try: + q = raw_input("> ") + except KeyboardInterrupt: + print + sys.exit() + print cb.Ask(q) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/eliza.py b/eliza.py new file mode 100755 index 0000000..eca1958 --- /dev/null +++ b/eliza.py @@ -0,0 +1,338 @@ +#---------------------------------------------------------------------- +# eliza.py +# +# a cheezy little Eliza knock-off by Joe Strout +# with some updates by Jeff Epler +# hacked into a module and updated by Jez Higgins +# last revised: 28 February 2005 +# Updated by Elliott Hauser March 26th 2014 +#---------------------------------------------------------------------- + +import string +import re +import random + +class eliza: + def __init__(self): + self.keys = map(lambda x:re.compile(x[0], re.IGNORECASE),gPats) + self.values = map(lambda x:x[1],gPats) + + #---------------------------------------------------------------------- + # translate: take a string, replace any words found in dict.keys() + # with the corresponding dict.values() + #---------------------------------------------------------------------- + def translate(self,str,dict): + words = string.split(string.lower(str)) + keys = dict.keys(); + for i in range(0,len(words)): + if words[i] in keys: + words[i] = dict[words[i]] + return string.join(words) + + #---------------------------------------------------------------------- + # respond: take a string, a set of regexps, and a corresponding + # set of response lists; find a match, and return a randomly + # chosen response from the corresponding list. + #---------------------------------------------------------------------- + def respond(self,str): + # find a match among keys + for i in range(0,len(self.keys)): + match = self.keys[i].match(str) + if match: + # found a match ... stuff with corresponding value + # chosen randomly from among the available options + resp = random.choice(self.values[i]) + # we've got a response... stuff in reflected text where indicated + pos = string.find(resp,'%') + while pos > -1: + num = string.atoi(resp[pos+1:pos+2]) + resp = resp[:pos] + \ + self.translate(match.group(num),gReflections) + \ + resp[pos+2:] + pos = string.find(resp,'%') + # fix munged punctuation at the end + if resp[-2:] == '?.': resp = resp[:-2] + '.' + if resp[-2:] == '??': resp = resp[:-2] + '?' + return resp + +#---------------------------------------------------------------------- +# gReflections, a translation table used to convert things you say +# into things the computer says back, e.g. "I am" --> "you are" +#---------------------------------------------------------------------- +gReflections = { + "am" : "are", + "was" : "were", + "i" : "you", + "i'd" : "you would", + "i've" : "you have", + "i'll" : "you will", + "my" : "your", + "are" : "am", + "you've": "I have", + "you'll": "I will", + "your" : "my", + "yours" : "mine", + "you" : "me", + "me" : "you" +} + +#---------------------------------------------------------------------- +# gPats, the main response table. Each element of the list is a +# two-element list; the first is a regexp, and the second is a +# list of possible responses, with group-macros labelled as +# %1, %2, etc. +#---------------------------------------------------------------------- +gPats = [ + [r'I need (.*)', + [ "Why do you need %1?", + "Would it really help you to get %1?", + "Are you sure you need %1?"]], + + [r'Why don\'?t you ([^\?]*)\??', + [ "Do you really think I don't %1?", + "Perhaps eventually I will %1.", + "Do you really want me to %1?"]], + + [r'Why can\'?t I ([^\?]*)\??', + [ "Do you think you should be able to %1?", + "If you could %1, what would you do?", + "I don't know -- why can't you %1?", + "Have you really tried?"]], + + [r'I can\'?t (.*)', + [ "How do you know you can't %1?", + "Perhaps you could %1 if you tried.", + "What would it take for you to %1?"]], + + [r'I am (.*)', + [ "Did you come to me because you are %1?", + "How long have you been %1?", + "How do you feel about being %1?"]], + + [r'I\'?m (.*)', + [ "How does being %1 make you feel?", + "Do you enjoy being %1?", + "Why do you tell me you're %1?", + "Why do you think you're %1?"]], + + [r'Are you ([^\?]*)\??', + [ "Why does it matter whether I am %1?", + "Would you prefer it if I were not %1?", + "Perhaps you believe I am %1.", + "I may be %1 -- what do you think?"]], + + [r'What (.*)', + [ "Why do you ask?", + "How would an answer to that help you?", + "What do you think?"]], + + [r'How (.*)', + [ "How do you suppose?", + "Perhaps you can answer your own question.", + "What is it you're really asking?"]], + + [r'Because (.*)', + [ "Is that the real reason?", + "What other reasons come to mind?", + "Does that reason apply to anything else?", + "If %1, what else must be true?"]], + + [r'(.*) sorry (.*)', + [ "There are many times when no apology is needed.", + "What feelings do you have when you apologize?"]], + + [r'Hello(.*)', + [ "Hello... I'm glad you could drop by today.", + "Hi there... how are you today?", + "Hello, how are you feeling today?", + "What's on your mind?", + "Hello. What are you thinking about?", + "Hello. Why did you decide to tweet at me?"]], + + [r'Hi(.*)', + [ "Hello... I'm glad you could drop by today.", + "Hi there... how are you today?", + "Hello, how are you feeling today?", + "What's on your mind?", + "Hello. What are you thinking about?", + "Hello. Why did you decide to tweet at me?"]], + + [r'I think (.*)', + [ "Do you have any doubts about %1?", + "Why do you think that?", + "But you're not sure %1?"]], + + [r'(.*) friend (.*)', + [ "Tell me more about your friends.", + "When you think of a friend, what comes to mind?", + "When's the last time you made a good friend?", + "Why don't you tell me about a childhood friend?"]], + + [r'Yes', + [ "You seem quite sure.", + "OK, but can you elaborate a bit?", + "Does it make you feel more in control when you're decisive?"]], + + [r'(.*) computer(.*)', + [ "Are you really talking about me?", + "Does it seem strange to talk to a computer?", + "How do computers make you feel?", + "Do you feel threatened by computers?"]], + + [r'(.*) internet(.*)', + [ "Do you get enough sleep?", + "Does it seem strange to not know who you're talking to?", + "Does teh technology you use make you feel lonely?", + "Do you feel threatened by connections with people?"]], + + [r'Is it (.*)', + [ "Do you think it is %1?", + "Perhaps it's %1 -- what do you think?", + "If it were %1, what would you do?", + "It could well be that %1."]], + + [r'It is (.*)', + [ "You seem very certain.", + "If I told you that it probably isn't %1, what would you feel?"]], + + [r'Can you ([^\?]*)\??', + [ "What makes you think I can't %1?", + "If I could %1, then what?", + "Why do you ask if I can %1?"]], + + [r'Can I ([^\?]*)\??', + [ "Perhaps you don't want to %1.", + "Do you want to be able to %1?", + "If you could %1, would you?"]], + + [r'You are (.*)', + [ "Why do you think I am %1?", + "Does it please you to think that I'm %1?", + "Perhaps you would like me to be %1.", + "Perhaps you're really talking about yourself?"]], + + [r'You\'?re (.*)', + [ "Why do you say I am %1?", + "Why do you think I am %1?", + "Are we talking about you, or me?"]], + + [r'I don\'?t (.*)', + [ "Don't you really %1?", + "Why don't you %1?", + "Do you want to %1?"]], + + [r'I feel (.*)', + [ "Good, tell me more about these feelings.", + "Do you often feel %1?", + "When do you usually feel %1?", + "When you feel %1, what do you do?"]], + + [r'I have (.*)', + [ "Why do you tell me that you've %1?", + "Have you really %1?", + "Now that you have %1, what will you do next?"]], + + [r'I would (.*)', + [ "Could you explain why you would %1?", + "Why would you %1?", + "Who else knows that you would %1?"]], + + [r'Is there (.*)', + [ "Do you think there is %1?", + "It's likely that there is %1.", + "Would you like there to be %1?"]], + + [r'My (.*)', + [ "I see, your %1.", + "Why do you say that your %1?", + "When your %1, how do you feel?"]], + + [r'You (.*)', + [ "We should be discussing you, not me.", + "Why do you say that about me?", + "Why do you care whether I %1?"]], + + [r'Why (.*)', + [ "Why don't you tell me the reason why %1?", + "Why do you think %1?" ]], + + [r'I want (.*)', + [ "What would it mean to you if you got %1?", + "Why do you want %1?", + "What would you do if you got %1?", + "If you got %1, then what would you do?"]], + + [r'(.*) mother(.*)', + [ "Tell me more about your mother.", + "What was your relationship with your mother like?", + "How do you feel about your mother?", + "How does this relate to your feelings today?", + "Good family relations are important."]], + + [r'(.*) father(.*)', + [ "Tell me more about your father.", + "How did your father make you feel?", + "How do you feel about your father?", + "Does your relationship with your father relate to your feelings today?", + "Do you have trouble showing affection with your family?"]], + + [r'(.*) child(.*)', + [ "Did you have close friends as a child?", + "What is your favorite childhood memory?", + "Do you remember any dreams or nightmares from childhood?", + "Did the other children sometimes tease you?", + "How do you think your childhood experiences relate to your feelings today?"]], + + [r'(.*)\?', + [ "Why do you ask that?", + "Please consider whether you can answer your own question.", + "Perhaps the answer lies within yourself?", + "Why don't you tell me?"]], + + [r'quit', + [ "Thank you for talking with me.", + "Good-bye.", + "Thank you, that will be $150. Have a good day!"]], + + [r'stop', + [ "Thank you for talking with me.", + "Good-bye.", + "Thank you, that will be $150. Have a good day!"]], + + [r'(.*)', + [ "Please tell me more.", + "Let's change focus a bit... Tell me about your family.", + "Can you elaborate on that?", + "Why do you say '%1'?", + "I see. I think", + "I see. Do you think I understand?", + "Very interesting.", + "Do you understand what that really means?", + "'%1.' Really?", + "I see. And what does that tell you?", + "How does that make you feel?", + "How do you feel when you say that?"]] + ] + +#---------------------------------------------------------------------- +# command_interface +#---------------------------------------------------------------------- +def command_interface(): + print "Therapist\n---------" + print "Talk to the program by typing in plain English, using normal upper-" + print 'and lower-case letters and punctuation. Enter "quit" when done.' + print '='*72 + print "Hello. How are you feeling today?" + s = "" + therapist = eliza(); + while s != "quit": + try: s = raw_input(">") + except EOFError: + s = "quit" + print s + while s[-1] in "!.": s = s[:-1] + print therapist.respond(s) + + +if __name__ == "__main__": + command_interface()