diff --git a/.gitignore b/.gitignore index 96e8e14..a98492d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ images/** output/** src/index.json +src/database.json .DS_Store src/**.wav diff --git a/Makefile b/Makefile index 45054d4..fab6eed 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,6 @@ ifeq ($(OS),Darwin) @echo $(OS) endif - # POST-PROCESSING RECIPES ocr/output.txt: ## ocr with tesseract @@ -130,3 +129,6 @@ ttssr-human-only: ocr/output.txt ## Loop: text to speech-speech recognition. Dep chatbook: ocr/output.txt #chatbot based on the knowledge of the scans Dependencies: nltk_rake, irc, nltk python3 src/chatbook.py + +oulibot: ocr/output.txt #chatbot based on the knowledge of the scans Dependencies: nltk_rake, irc, nltk + python3 src/oulibot.py diff --git a/README b/README index f6b23a7..41ee0b6 100644 --- a/README +++ b/README @@ -110,3 +110,20 @@ To move on to the next line of text, press enter twice. To see your pattern, type 'pattern'. To save your pattern in a text file, type 'save'. To leave the program, type 'quit'. + +## oulibot: Alex +Description: Chatbot that will help you to write a poem based on the text you inserted by giving you constraints. + +run: make oulibot + + +Dependencies: +irc.bot: pip3 install irc_client +nltk: pip3 install nltk && python3 -m nltk.downloader +rake_nltk: pip3 install rake_nltk +nltk.tokenize +nltk.corpus +textblob: pip3 install textblob +PIL: pip3 install Pillow +numpy: pip3 install numpy +tweepy: pip3 install tweepy diff --git a/ocr/list.txt b/ocr/list.txt index c6c69f9..16c631e 100644 --- a/ocr/list.txt +++ b/ocr/list.txt @@ -1,3 +1,3 @@ -images/0012.tif +images/0029.jpg diff --git a/src/build_database.py b/src/build_database.py index 722f54c..69d71d8 100644 --- a/src/build_database.py +++ b/src/build_database.py @@ -2,16 +2,30 @@ import json import argparse import sys from nltk.tokenize import sent_tokenize, word_tokenize +from nltk.corpus import stopwords +import nltk +import numpy as np from rake_nltk import Rake - +from textblob import TextBlob +stop_words = set(stopwords.words('english')) r= Rake() ap = argparse.ArgumentParser("JSON Dumper") ap.add_argument("text", nargs="+", help="text sources") args=ap.parse_args() +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 + +#### INDEX (DEPR) -with open('src/index.json') as f: +with open('src/index.json', 'w') as f: try: index = json.load(f) except: @@ -36,3 +50,86 @@ for n in args.text: with open('src/index.json', 'w') as outfile: json.dump(index, outfile) + + + +######## DATABASE + +with open('src/database.json', 'w') as f: + try: + index = json.load(f) + except: + index={} + + +nouns = [] +verbs = [] +adverbs = [] +pronouns = ["I", "you", "we", "they"] +adjectives = [] +keywords = [] +keywordspersentence = {} +alltext = "" +allcharacters = [] + +for n in args.text: + text = open(n).read() + rawtext = text.replace("\n", " ") + #get pos + for letter in list(rawtext): + if letter not in allcharacters and not letter.isalpha(): + allcharacters.append(letter) + + alltext += rawtext + text = cleanedText(text) + thistext = TextBlob(text) + words = word_tokenize(text) + listWithPos = nltk.pos_tag(words) + print(thistext.tags) + for key, tag in thistext.tags: + if(tag == "VBP"): + verbs.append(key) + if(tag == "NN" or tag == "NNS"): + nouns.append(key) + if(tag == "RB"): + adverbs.append(key) + if(tag == "JJ"): + adjectives.append(key) + + print("Verbs: {}".format(verbs)) + print("Nouns: {}".format(nouns)) + print("Adverbs: {}".format(adverbs)) + print("Adjectives: {}".format(adjectives)) + #keywords + r.extract_keywords_from_text(rawtext) + phrases = r.get_ranked_phrases_with_scores() + for key, phrase in phrases: + if key > 2: + keywords.append(phrase) + + print("Keywords: {}".format(keywords)) + + # keywordsofsentences + sentences = sent_tokenize(text) + for sentence in sentences: + + r.extract_keywords_from_text(sentence) + keys = r.get_ranked_phrases() + for key in keys: + if key not in keywordspersentence: + keywordspersentence[key] = [] + keywordspersentence[key].append({'filename': n, 'sentence': sentence, 'key': key}) + +print(allcharacters) +index["nouns"]=nouns +index["verbs"]=verbs +index["pronouns"]=pronouns +index["adverbs"]=adverbs +index["adjectives"]=adjectives +index["keywords"]=keywords +index["keywordspersentence"]=keywordspersentence +index["rawtext"]=alltext +index["chars"] = allcharacters + +with open('src/database.json', 'w') as outfile: + json.dump(index, outfile) diff --git a/src/chatbook.py b/src/chatbook.py index 0c98dca..09b5d49 100644 --- a/src/chatbook.py +++ b/src/chatbook.py @@ -69,9 +69,10 @@ if __name__ == "__main__": try: index = json.load(f) except: - index={} + print("I can't work with no knowledge") + sys.exit() + - #print(index) myhost = os.uname()[1] diff --git a/src/oulibot.py b/src/oulibot.py new file mode 100644 index 0000000..9405815 --- /dev/null +++ b/src/oulibot.py @@ -0,0 +1,500 @@ +##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'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) + self.channel = channel + self.index = index + self.lastAnswer = "" + self.lastincoming_msg = ["common", "statement"] + 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): + 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) + 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) + c.privmsg(self.channel,"I'm your personal writing assistent, how can i help you?") + 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 "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: + 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]): + 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) + 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!"] + 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, "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) + + 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)) + c.privmsg(self.channel, "Nice one! Let's add another line:") + 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 = "Finished poem" + 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[1] + 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) + +# 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]): + 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?"] + msg = random.choice(answers) + c.privmsg(self.channel,msg) + level=-1 + else: + 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()