From 615d9389e77819403794b30348d1a373f11b2232 Mon Sep 17 00:00:00 2001 From: Jesse Morgan Date: Mon, 23 May 2011 20:26:41 +0000 Subject: Started to organize a bit. Added eliza. --- JKTwitterBot/src/eliza.py | 311 +++++++++++++++++++++++++++++++++++++++++++++ JKTwitterBot/src/thebot.py | 203 ++++++++++++++++++----------- 2 files changed, 438 insertions(+), 76 deletions(-) create mode 100644 JKTwitterBot/src/eliza.py (limited to 'JKTwitterBot/src') diff --git a/JKTwitterBot/src/eliza.py b/JKTwitterBot/src/eliza.py new file mode 100644 index 0000000..fd394d9 --- /dev/null +++ b/JKTwitterBot/src/eliza.py @@ -0,0 +1,311 @@ +#---------------------------------------------------------------------- +# 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 +#---------------------------------------------------------------------- + +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?"]], + + [r'I think (.*)', + [ "Do you doubt %1?", + "Do you really think so?", + "But you're not sure %1?"]], + + [r'(.*) friend (.*)', + [ "Tell me more about your friends.", + "When you think of a friend, what comes to mind?", + "Why don't you tell me about a childhood friend?"]], + + [r'Yes', + [ "You seem quite sure.", + "OK, but can you elaborate a bit?"]], + + [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'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'(.*)', + [ "Please tell me more.", + "Let's change focus a bit... Tell me about your family.", + "Can you elaborate on that?", + "Why do you say that %1?", + "I see.", + "Very interesting.", + "%1.", + "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() diff --git a/JKTwitterBot/src/thebot.py b/JKTwitterBot/src/thebot.py index 30d3866..0a01ec0 100644 --- a/JKTwitterBot/src/thebot.py +++ b/JKTwitterBot/src/thebot.py @@ -15,9 +15,15 @@ import os import time import json import urllib2 +import eliza + CONSUMER_KEY='uS6hO2sV6tDKIOeVjhnFnQ' CONSUMER_SECRET='MEYTOS97VvlHX7K1rwHPEqVpTSqZ71HtvoK4sVuYk' +# Setting this to true causes tweets to be printed to the screen +# instead of tweeted. +TEST_MODE = True + DEFAULT_USERNAME = 'ziggster00' # "this will need to be changed" DEFAULT_AUTH_FILENAME = '.twitter_oauth' DEFAULT_LASTID_FILENAME = '.twitter_lastid' @@ -27,6 +33,106 @@ questions_status_update_File = 'question_status.txt' make_Friends_File = 'friends.txt' count = 0 response_count = 0 + +def status_update(outgoing_text): + if not TEST_MODE: + print '====> Resp =', outgoing_text + try: + poster.statuses.update(status=outgoing_text) + except TwitterError as e: + print '*** Twitter returned an error:\n***%s' % e + + else: + print '====> (TEST MODE) Resp =', outgoing_text + +def follow_user(user): + try: + poster.friendships.create(id=user) + except TwitterError as e: + print e + poster.friendships.destroy(id=user) + poster.friendships.create(id=user) + + +def reply_to_tweets(): + results = reader.search(q=username, since_id=lastid)['results'] + for result in reversed(results): + asker = result['from_user'] + msgid = str(result['id']) + incoming_text = result['text'] + + print " <<< " + asker + ": " + incoming_text + + if incoming_text.lower().find(username) != 0: + print '====> No response (not directed to %s)' % (username,) + elif (lastid != '') and (long(msgid) <= long(lastid)): + print '====> No response (%s < %s)' % (msgid, lastid) + else: + # Found a tweet directed to us. + usedoctor = True + + if usedoctor: + doctor_response = doctor.respond(incoming_text.strip()) + outgoing_text = "@%s %s" % (str(asker), doctor_response) + + else: + outgoing_text = '@%s %s' % (str(asker), str(response[response_count])) + response_count = (response_count + 1) % len(response); + + print '====> Resp = %s' % outgoing_text + try: + status_update(outgoing_text) + + except TwitterError as e: + print '*** Twitter returned an error:\n***%s' % e + + else: + lastid = msgid + print 'Last id replied = ', lastid + with open(lastid_filename, 'w') as f: + f.write(lastid) + + # Sleep for a second + time.sleep(1) + + +def ask_questions(): + # may want to add ask questions to friends too + # Ask questions specific to followers + connection = urllib2.urlopen('http://api.twitter.com/1/statuses/followers.json?screen_name=' + username) + friendship = urllib2.urlopen('http://api.twitter.com/1/statuses/friends.json?screen_name=' + username) + following_str = connection.read() + following_obj = json.loads(following_str) + friend_str = friendship.read() + friend_obj = json.loads(friend_str) + following_list = [] + friend_list = [] + for i in range(len(following_obj)): + followers = following_obj[i] + following_list.append(followers[u'screen_name']) + for x in range(len(friend_obj)): + supfriend = friend_obj[x] + friend_list.append(supfriend[u'screen_name']) + if count == len(question): + postnumber = 0 + else: postnumber = count + + for follow_me in friend_list: + if not (follow_me in following_list): + post = follow_me + ' ' + question[postnumber] + #status_update(post) #May want to ask everyone questions regardless of friendship + time.sleep(1) + postnumber = postnumber + 1 + if (follow_me in following_list):#Left open if we want to make specific questions to friends + print follow_me + if postnumber == len(question): + postnumber = 0 + + + +######################### +# Execution starts here # +######################### if __name__ == '__main__': parser = OptionParser() @@ -81,89 +187,34 @@ if __name__ == '__main__': with open(make_Friends_File, 'r') as f: friends = pickle.load(f) - def status_update(outgoing_text): - print '====> Resp =', outgoing_text - try: - poster.statuses.update(status=outgoing_text) - except TwitterError as e: - print '*** Twitter returned an error:\n***%s' % e - def follow_user(user): - try: - poster.friendships.create(id=user) - except TwitterError as e: - print e - poster.friendships.destroy(id=user) - poster.friendships.create(id=user) + # Prepare Eliza (code from the_shrink.py) + doctor = eliza.eliza() + # commented out so all friends are not added #for friend in friends: # adds all friends from friends.txt # follow_user(friend) while True: - results = reader.search(q=username, since_id=lastid)['results'] - for result in reversed(results): - if (response_count == len(response)-1): - response_count = 0 - asker = result['from_user'] - msgid = str(result['id']) - incoming_text = result['text'] - print " <<< " + asker + ": " + incoming_text - if incoming_text.lower().find(username) != 0: - print '====> No response (not directed to %s)' % (username,) - elif (lastid != '') and (long(msgid) <= long(lastid)): - print '====> No response (%s < %s)' % (msgid, lastid) - else: - outgoing_text = 'RT @' + str(asker)+' '+ str(response[response_count]) - response_count = response_count+1 - print '====> Resp = %s' % outgoing_text - try: - print outgoing_text - #status_update(outgoing_text) - except TwitterError as e: - print '*** Twitter returned an error:\n***%s' % e - else: - lastid = msgid - print 'Last id replied = ', lastid - with open(lastid_filename, 'w') as f: - f.write(lastid) - time.sleep(1) - if (count == len(tweet)-1): - count = 0 + # Reply to tweets directed to us + reply_to_tweets() + + # Send out a generic tweet print count - print tweet[count] - #status_update(tweet[count]) # post a status update + status_update(tweet[count]) # post a status update + count = (count + 1) % len(tweet); + + # Sleep for a bit to add some realism. print 'Now sleeping... \n' time.sleep(1) # set at 5min but is at 2min - print question[count] - #status_update(question[count]) + + # Pose a question + status_update(question[count]) + + # Sleep for a bit to add some realism. print 'Now sleeping... \n' time.sleep(1) # set for 2min. - # may want to add ask questions to friends too - # Ask questions specific to followers - connection = urllib2.urlopen('http://api.twitter.com/1/statuses/followers.json?screen_name=' + username) - friendship = urllib2.urlopen('http://api.twitter.com/1/statuses/friends.json?screen_name=' + username) - following_str = connection.read() - following_obj = json.loads(following_str) - friend_str = friendship.read() - friend_obj = json.loads(friend_str) - following_list = [] - friend_list = [] - for i in range(len(following_obj)): - followers = following_obj[i] - following_list.append(followers[u'screen_name']) - for x in range(len(friend_obj)): - supfriend = friend_obj[x] - friend_list.append(supfriend[u'screen_name']) - if count == len(question): - postnumber = 0 - else: postnumber = count - for follow_me in friend_list: - if not (follow_me in following_list): - post = follow_me + ' ' + question[postnumber] - #status_update(post) #May want to ask everyone questions regardless of friendship - time.sleep(1) - postnumber = postnumber + 1 - if (follow_me in following_list):#Left open if we want to make specific questions to friends - print follow_me - if postnumber == len(question): - postnumber = 0 - count = count + 1 \ No newline at end of file + + ask_questions() + + + \ No newline at end of file -- cgit v1.2.3