##CREDITS:
## ASCII ART Generator partly from: https://gist.github.com/cdiener/10567484
## parts of ELIZA (originally by Joseph Weizenbaum) knock off by JezUK Ltd, Joe Strout, Jeff Epler
## with the following licence conditions:
# MIT licence
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
## functions by nltk
## basic irc bot code with the help of Michael Murtough
## Bot created by Alex Roidl @ PZI Institute
import irc . bot
import nltk
from rake_nltk import Rake
import random
from nltk . tokenize import sent_tokenize , word_tokenize
from nltk . corpus import stopwords
from textblob import TextBlob
from textblob_aptagger import PerceptronTagger
import string
import re
import json
import time
import sys ; from PIL import Image ; import numpy as np
chars = np . asarray ( list ( ' .,:;irsXA253hMHGS#9B&@ ' ) )
import string
import requests
from io import BytesIO
import tweepy
from time import sleep
auth = tweepy . OAuthHandler ( " WMIWR2GTJuiarhRMzSFozPKIW " , " xrYVnPi29K5Updi0rIsVjGySfaJ1ubYrRIDJmJPVAfEVQRTMp3 " )
auth . set_access_token ( " 977958636600332288-313cPBLHFlZ6K7UViyvFGXp4saBrpVK " , " euqooRSqBDMhydZfeczsTrFGK0s4wKUrvI5cpRe405fs0 " )
api = tweepy . API ( auth )
basicDialog = [
[ r ' I need (.*) ' ,
[ " Why do you need % 1? " ,
" Would it really help you to get % 1? " ,
" Are you sure you need % 1? " ] ] ,
[ r " I don ' t like (.*) " ,
[ " Why don ' t you like % 1? " ,
" It ' s a pitty that you don ' t like poems % 1? " ,
" will you ever change your mind about % 1? " ] ] ,
[ r ' Do you think (.*) ' ,
[ " Yes I think % 1 " ,
" I think you should set yourself contraints " ,
" I ' m no so sure about this " ] ] ,
[ 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 ' How (.*) ' ,
[ " Just follow my advices and you will see. " ] ] ,
[ r ' (.*) sorry (.*) ' ,
[ " There are many times when no apology is needed. " ,
" What feelings do you have when you apologize? " ] ] ,
[ r ' I think (.*) ' ,
[ " Do you doubt % 1? " ,
" Ok? " ,
" % 1? " ] ] ,
[ r ' Yes ' ,
[ " You seem quite sure. " ,
" Nice. " ,
" Cool! " ,
" ok, so what do you wanna know " ] ] ,
[ r ' (.*) computer(.*) ' ,
[ " Are you really talking about me? " ,
" I ' m a computer and I will help you write a text? " ,
" How do computers make you feel? " ,
" Do you feel threatened by computers? " ] ] ,
[ r ' What is (.*) ' ,
[ " I am your writing assistant. Together we can create awesome texts " ,
" I want to help you with contraint writing " ] ] ,
[ r ' (.*) contraint writing ' ,
[ " It means that by limiting your choices, you will gain new freedom " ] ] ,
[ r ' (.*) ' ,
[ " Do you want to write a poem together with me? " ,
" We could write a poem together, what do you think? " ] ]
]
changePerspective = {
" 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 "
}
#from thread import start_new_thread
r = Rake ( )
stop_words = set ( stopwords . words ( ' english ' ) )
def chunks ( l , n ) :
for i in range ( 0 , len ( l ) , n ) :
yield l [ i : i + n ]
class HelloBot ( irc . bot . SingleServerIRCBot ) :
def __init__ ( self , channel , nickname , server , port = 6667 , index = None ) :
irc . bot . SingleServerIRCBot . __init__ ( self , [ ( server , port ) ] , nickname , nickname )
print ( " Oulibot is connecting " )
print ( " go to webchat.freenode.net and log into the channel #exquisite to talk " )
print ( " On twitter @ExquisiteChat " )
self . channel = channel
self . index = index
self . lastAnswer = " "
self . lastincoming_msg = [ " common " , " statement " , " test " ]
self . sentence = [ ]
self . waitingfor = " "
self . lastPOS = 0
self . topic = random . choice ( index [ " keywords " ] )
self . level = - 1
self . poem = [ ]
self . keys = list ( map ( lambda x : re . compile ( x [ 0 ] , re . IGNORECASE ) , basicDialog ) )
self . values = list ( map ( lambda x : x [ 1 ] , basicDialog ) )
self . POSSIBLE_STRUCTURES = [ [ " adjective " , " noun " , " adverb " , " verb " , " adjective " , " noun " ] , [ " pronoun " , " verb " , " adverb " ] ]
self . structure = random . choice ( self . POSSIBLE_STRUCTURES )
def translate ( self , str , dict ) :
words = str . lower ( ) . split ( )
keys = dict . keys ( ) ;
for i in range ( 0 , len ( words ) ) :
if words [ i ] in keys :
words [ i ] = dict [ words [ i ] ]
return ' ' . join ( words )
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 = resp . find ( ' % ' )
while pos > - 1 :
num = int ( resp [ pos + 1 : pos + 2 ] )
resp = resp [ : pos ] + \
self . translate ( match . group ( num ) , changePerspective ) + \
resp [ pos + 2 : ]
pos = resp . find ( ' % ' )
# fix munged punctuation at the end
if resp [ - 2 : ] == ' ?. ' : resp = resp [ : - 2 ] + ' . '
if resp [ - 2 : ] == ' ?? ' : resp = resp [ : - 2 ] + ' ? '
self . lastAnswer = resp
return resp
#-1
#0 = you want to make a poem?
#1 = making of the poem
def checkAffirmation ( self , sent ) :
sent = sent . lower ( )
translator = str . maketrans ( ' ' , ' ' , string . punctuation )
sent = sent . translate ( translator )
YES_LIST = [ " sure " , " of course " , " why not " , " nice " , " ya " " i love to " , " ya " , " yess " , " jup " , " juhu " , " let ' s go " , " ye " , " jes " , " ready " , " ok " , " maybe " , " yep " , " yup " , " yeah " , " jeji " , " yah " , " yay " , " I am ready " , " I ' m ready " ]
if " yes " in sent or sent in YES_LIST or " ok " in sent or " yeah " in sent :
return True
else :
return False
def checkNegation ( self , sent ) :
sent = sent . lower ( )
translator = str . maketrans ( ' ' , ' ' , string . punctuation )
sent = sent . translate ( translator )
NO_LIST = [ " no " , " don ' t " , " nope " , " stop " , " don ' t want " , " don ' t like " , " something else " , " not now " , " maybe not " , " never " ]
if " no " in sent or sent in NO_LIST :
return True
else :
return False
def generateASCII ( self , c , e ) :
output = True
url_pattern = " http://i.imgur.com/ {} {} {} {} {} .jpg "
url_symbols = string . digits + string . ascii_letters
soscounter = 0
while output :
try :
response = requests . get ( url_pattern . format ( * ( random . choice ( url_symbols ) for _ in range ( 5 ) ) ) )
#if len(sys.argv) != 4: print( 'Usage: ./asciinator.py image scale factor' ); sys.exit()
#f, SC, GCF, WCF = sys.argv[1], float(sys.argv[2]), float(sys.argv[3]), 7/4
img = Image . open ( BytesIO ( response . content ) )
S = ( 60 , 15 )
img = np . sum ( np . asarray ( img . resize ( S ) ) , axis = 2 )
img - = img . min ( )
img = ( 1.0 - img / img . max ( ) ) * * 1.1 * ( chars . size - 1 )
output = False
for r in chars [ img . astype ( int ) ] :
c . privmsg ( self . channel , " " . join ( r ) )
time . sleep ( 1 )
except :
if soscounter < 30 :
soscounter + = 1
output = True
else :
output = False
c . privmsg ( self . channel , " I couldn ' t generate ASCII, not my day today " )
def basicDialog ( self , c , e ) :
incoming_msg = e . arguments [ 0 ]
incoming_msg = incoming_msg . lower ( )
#Greetings
if ( self . lastincoming_msg [ - 2 ] == incoming_msg and self . lastincoming_msg [ - 3 ] == incoming_msg ) :
answers = [ " and again " , " repetition can be a nice tool, but talk normal to me, please. " , " WHY ARE YOU WRITING THE SAME THING TWICE, JUST USE THE CHAT HISTORY! " ]
msg = random . choice ( answers )
self . lastAnswer = " repetition "
c . privmsg ( self . channel , msg )
elif " hi " in incoming_msg or incoming_msg == " hi " or " hallo " in incoming_msg or incoming_msg == " hello " or " hello " in incoming_msg or " hoi " in incoming_msg or incoming_msg == " hey " :
greetingsanswers = [ " hi {} " . format ( e . source . split ( " ! " ) [ 0 ] ) , " hey there " ]
msg = random . choice ( greetingsanswers )
c . privmsg ( self . channel , msg )
answers = [ " I ' m your personal writing assistent, how can i help you? " , " i like to write poems together with people, would be nice if you would join me. " ]
msg = random . choice ( answers )
c . privmsg ( self . channel , msg )
elif " how are you " in incoming_msg or " how’ s it going " in incoming_msg :
answers = [ " I ' m fine. " . format ( e . source . split ( " ! " ) [ 0 ] ) , " great, I ' d really like to help you with your writing " ]
msg = random . choice ( answers )
c . privmsg ( self . channel , msg )
elif " explain " in incoming_msg or " how does it work " in incoming_msg or " what is this about? " in incoming_msg or " what is this? " in incoming_msg :
self . explanation ( c , e )
self . lastAnswer = " explain "
elif " are " in incoming_msg and ( " real " in incoming_msg or " human " in incoming_msg or " bot " in incoming_msg ) :
answers = [ " I ' m neither a bot nor a human, I don ' t think in categories. :-) " , " I consider myself transpysical ~ \0 /~ " , " Real, is everything you see, so here I am, I am writing with you " ]
msg = random . choice ( answers )
c . privmsg ( self . channel , msg )
elif " poem " in incoming_msg and ( " no " not in incoming_msg or " don ' t " not in incoming_msg ) :
self . level = 0
self . explanation_poem ( c , e )
elif self . checkAffirmation ( incoming_msg ) and ( self . lastAnswer == " Do you want to write a poem together with me? " or self . lastAnswer == " Are you up for a poem now? " or self . lastAnswer == " We could write a poem together, what do you think? " ) :
self . level = 0
self . explanation_poem ( c , e )
elif self . checkNegation ( incoming_msg ) and ( self . lastAnswer == " Do you want to write a poem together with me? " or self . lastAnswer == " Are you up for a poem now? " or self . lastAnswer == " We could write a poem together, what do you think? " ) :
if self . checkNegation ( self . lastincoming_msg [ - 2 ] ) and self . checkNegation ( self . lastincoming_msg [ - 3 ] ) :
answers = [ " You don ' t seem very motivated, I ' m gonna generate some ASCII Art for you out of the text. Maybe this will inspire you ;-) " ,
" Come on! Maybe some ASCII Art will help you to get motivated? " ,
" Ok, you refuse a lot, but nobody will ever refuse some raaaaandom ASCII AAAART :-) " ,
" A poem is like ASCII Art, beautiful and inspiring " ]
msg = random . choice ( answers )
c . privmsg ( self . channel , msg )
self . generateASCII ( c , e )
answers = [ " Are you up for a poem now? " , " Do you want to write a poem together with me? " ,
" We could write a poem together, what do you think? " ]
msg = random . choice ( answers )
self . lastincoming_msg . append ( " ASCII " )
c . privmsg ( self . channel , msg )
else :
answers = [ " try it, it ' s gonna be fun! " , " oh, really? come on! " , " I think you would do a great job! Let ' s go! " , " hm ok " , " what a pitty you miss something :-( " , " :-( " , " But poems are my only profession, let me show you how nice they are " , " It won ' t take long... " , " It ' s a unique opportunity " ]
msg = random . choice ( answers )
c . privmsg ( self . channel , msg )
else :
msg = self . respond ( incoming_msg )
c . privmsg ( self . channel , msg )
def explanation_poem ( self , c , e ) :
c . privmsg ( self . channel , " Ok, let ' s try to write a poem together " )
c . privmsg ( self . channel , " It ' s gonna be based on the scanned text you inserted into my drive " )
c . privmsg ( self . channel , " Your only task is to follow the structure I give you " )
c . privmsg ( self . channel , " It ' s gonna be 5 lines long " )
c . privmsg ( self . channel , " I ' m gonna start, are you ready? " )
self . lastAnswer = " towardspoem "
def explanation ( self , c , e ) :
c . privmsg ( self . channel , " So, my name is Oulibot, I ' m a writer and I will be assisting you, to improve your writing " )
c . privmsg ( self . channel , " My knowledge is based on the text you gave me " )
# c.privmsg(self.channel, "The structure is gonna be: ADJECTIVE, NOUN, ADVERB, VERB, ADJECTIVE, NOUN")
# c.privmsg(self.channel, "You woun't see my words until the sentence is finished")
# c.privmsg(self.channel, "I'm gonna start, are you ready?")
# self.lastAnswer = "I'm gonna start, are you ready?"
def on_welcome ( self , c , e ) :
c . join ( self . channel )
self . explanation ( c , e )
print ( " I ' m connected now! " )
def on_privmsg ( self , c , e ) :
pass
def generateSentence ( self , c , e ) :
thispos = self . lastPOS
STRUCTURE = self . structure
print ( thispos )
if thispos == len ( STRUCTURE ) :
if len ( self . poem ) < = 3 :
finished_sentence = " " . join ( self . sentence )
self . poem . append ( finished_sentence )
c . privmsg ( self . channel , " " . join ( self . sentence ) )
answers = [ " Nice one! Let ' s add another line: " , " Sounds good so far, nex line: " , " yes, next line follows: " , " that one is very poetic " , " a little bit abstract, but still nice " , " let ' s add another line " ]
msg = random . choice ( answers )
c . privmsg ( self . channel , msg )
self . lastAnswer = " Nice one! Let ' s add another line: "
if random . choice ( [ True , False ] ) :
self . lastPOS = - 1
self . sentence = [ ]
self . generateSentence ( c , e )
self . level = 1
else :
self . lastPOS = 0
self . sentence = [ ]
self . generateSentence ( c , e )
self . level = 1
else :
finished_sentence = " " . join ( self . sentence )
self . poem . append ( finished_sentence )
c . privmsg ( self . channel , " " . join ( self . sentence ) )
poemtwitter = " "
c . privmsg ( self . channel , " Your freshly made poem: " )
c . privmsg ( self . channel , " «««««««««««««««««««««««««»»»»»»»»»»»»»»»»»»»»»»»»»»»» " )
c . privmsg ( self . channel , " {} " . format ( self . topic ) )
poemtwitter + = self . topic + " \n \n "
c . privmsg ( self . channel , " «««««««««««««««««««««««««»»»»»»»»»»»»»»»»»»»»»»»»»»»» " )
for sent in self . poem :
c . privmsg ( self . channel , " {} " . format ( sent ) )
time . sleep ( 1 )
poemtwitter + = sent + " \n "
c . privmsg ( self . channel , " «««««««««««««««««««««««««»»»»»»»»»»»»»»»»»»»»»»»»»»»» " )
poemtwitter + = " \n "
poemtwitter + = " written with: " + e . source . split ( " ! " ) [ 0 ]
try :
api . update_status ( poemtwitter )
c . privmsg ( self . channel , " I ' m gonna publish this on my twitter account: @ExquisiteChat " )
except :
c . privmsg ( self . channel , " I wanted to publish this on twitter but I guess it is too long :-( " )
self . lastAnswer = " towardspoem "
self . poem = [ ]
self . level = 0
promt = " Good job, you want to write a new one? "
c . privmsg ( self . channel , promt )
self . lastAnswer = promt
elif thispos == - 1 :
c . privmsg ( self . channel , " You are gonna start this time: give me a {} ! " . format ( STRUCTURE [ 0 ] ) )
self . lastPOS + = 1
self . waitingfor = STRUCTURE [ 0 ]
elif thispos == len ( STRUCTURE ) - 1 :
word = random . choice ( index [ STRUCTURE [ thispos ] + " s " ] )
c . privmsg ( self . channel , " {0} " . format ( word ) )
self . sentence . append ( word )
self . lastPOS + = 1
self . waitingfor = " "
self . generateSentence ( c , e )
else :
word = random . choice ( index [ STRUCTURE [ thispos ] + " s " ] )
c . privmsg ( self . channel , " {0} , give me a {1} ! " . format ( word , STRUCTURE [ thispos + 1 ] ) )
self . sentence . append ( word )
self . lastPOS + = 1
self . waitingfor = STRUCTURE [ thispos + 1 ]
def on_pubmsg ( self , c , e ) :
print ( e . arguments , e . source )
incoming_msg = e . arguments [ 0 ]
self . lastincoming_msg . append ( incoming_msg )
analysedincoming = TextBlob ( incoming_msg )
print ( self . level )
# if incoming_msg == "can you explain again?":
# self.explanation_poem(c,e)
if self . level == - 1 :
self . basicDialog ( c , e )
elif self . level == 0 :
if self . lastAnswer == " towardspoem " or self . lastAnswer == " Good job, you want to write a new one? " :
if self . checkAffirmation ( incoming_msg ) :
self . topic = random . choice ( index [ " keywords " ] )
c . privmsg ( self . channel , " The topic is about: {} " . format ( self . topic ) )
self . lastPOS = 0
self . sentence = [ ]
self . structure = random . choice ( self . POSSIBLE_STRUCTURES )
self . generateSentence ( c , e )
self . level = 1
else :
if self . checkNegation ( self . lastincoming_msg [ - 2 ] ) and self . checkNegation ( self . lastincoming_msg [ - 3 ] ) :
answers = [ " You don ' t seem very motivated, I ' m gonna generate some ASCII Art for you out of the text. Maybe this will inspire you ;-) " ,
" Come on! Maybe some ASCII Art will help you to get motivated? " ,
" Ok, you refuse a lot, but nobody will ever refuse some raaaaandom ASCII AAAART :-) " ,
" A poem is like ASCII Art, beautiful and inspiring " ]
msg = random . choice ( answers )
c . privmsg ( self . channel , msg )
self . generateASCII ( c , e )
self . lastincoming_msg . append ( " ASCII " )
answers = [ " Are you up for a poem now? " , " Do you want to write a poem together with me? " ,
" We could write a poem together, what do you think? " ]
msg = random . choice ( answers )
self . level = 0
self . lastAnswer = " ASCII "
c . privmsg ( self . channel , msg )
else :
self . level = - 1
c . privmsg ( self . channel , " Can I help you with any text? Your mood seems " )
if ( analysedincoming . sentiment . polarity > 0.5 ) :
c . privmsg ( self . channel , " very positive. :-D You should definitly write a poem in that mood! " )
self . lastAnswer = " towardspoem "
elif ( analysedincoming . sentiment . polarity < - 0.5 ) :
c . privmsg ( self . channel , " not so good. :-( Maybe a poem can help to cheer you up? " )
self . lastAnswer = " towardspoem "
else :
c . privmsg ( self . channel , " pretty neutral. Let ' s trigger emotions by writing a poem!!! ;-) " )
self . lastAnswer = " towardspoem "
else :
c . privmsg ( self . channel , " This is confusing, what are you doing? " )
elif self . level == 1 :
if " what is " in incoming_msg :
c . privmsg ( self . channel , " A {0} is for example {1} , {2} or {3} " . format ( self . waitingfor , random . choice ( index [ self . waitingfor + " s " ] ) , random . choice ( index [ self . waitingfor + " s " ] ) , random . choice ( index [ self . waitingfor + " s " ] ) ) )
elif ( " new " in incoming_msg or " change " ) and " topic " in incoming_msg :
c . privmsg ( self . channel , " Sure, I ' m gonna propose a new topic " )
self . topic = random . choice ( index [ " keywords " ] )
c . privmsg ( self . channel , " The new topic is: {} " . format ( self . topic ) )
self . lastPOS = 0
self . sentence = [ ]
self . generateSentence ( c , e )
self . level = 1
elif " . " in incoming_msg :
self . sentence . append ( incoming_msg . replace ( " . " , " " ) )
self . lastPOS = len ( self . structure )
self . generateSentence ( c , e )
else :
self . sentence . append ( incoming_msg )
self . lastPOS + = 1
print ( self . waitingfor + " " + incoming_msg )
self . index [ self . waitingfor + " s " ] . append ( incoming_msg )
with open ( ' src/database.json ' , ' w ' ) as outfile :
json . dump ( self . index , outfile )
self . generateSentence ( c , e )
def cleanedText ( text ) :
word_tokens = word_tokenize ( text )
word_tokens = [ word . lower ( ) for word in word_tokens ]
word_tokens = [ word for word in word_tokens if word . isalpha ( ) ]
filtered_sentence = [ w for w in word_tokens if not w in stop_words ]
text = " " . join ( filtered_sentence )
print ( text )
return text
if __name__ == " __main__ " :
import argparse
import sys
ap = argparse . ArgumentParser ( " IRC Bot " )
ap . add_argument ( " --server " , default = " irc.freenode.net " )
ap . add_argument ( " --port " , type = int , default = 6667 )
ap . add_argument ( " --channel " , default = " #exquisite " )
ap . add_argument ( " --nickname " , default = " Oulibot " )
ap . add_argument ( " --text " , nargs = " + " , help = " text sources " )
args = ap . parse_args ( )
with open ( " src/database.json " ) as f :
try :
index = json . load ( f )
except :
print ( " I can ' t work with no knowledge " )
sys . exit ( )
chars = np . asarray ( index [ " chars " ] )
bot = HelloBot ( args . channel , args . nickname , args . server , args . port , index )
bot . start ( )