newest
[scrappy.git] / modules / markov / markov.py
blob7091646f09c0d2064336525ee53f2056d69d8b56
1 #markov module for scrappy
3 #the inspiration for this code comes from
4 #"The Practice of Programming", so some of the variable
5 #names and such will be similar.
7 import random
8 import pickle
9 import re
10 import threading
13 #EXPERIMENTAL
14 last = ""
15 import twitter
17 api = None
18 twitteruser = 'scrappybot'
19 twitterpass = 'mark0vb0t'
21 nickmatch = None
22 statetab = {}
23 lock = None
24 w1 = w2 = "\n"
27 def init(scrap):
28 global nickmatch
29 global lock
30 global api
32 lock = threading.Lock()
34 scrap.register_event("markov", "msg", markov_learn)
35 scrap.register_event("markov", "msg", markov_talk)
36 scrap.register_event("markov", "msg", markov_load)
37 scrap.register_event("markov", "msg", markov_dump)
38 scrap.register_event("markov", "msg", markov_stats)
39 scrap.register_event("markov", "msg", tweet)
41 nickmatch = re.compile(scrap.nickname)
43 random.seed()
45 api = twitter.Api(username=twitteruser, password=twitterpass)
47 def markov_stats(c,list,bot):
48 global statetab
50 cmd = list[4].split(" ")[0]
52 if cmd == "markov_stats":
53 c.privmsg(list[5], "words: %d" % len(statetab[("\n","\n")]))
54 c.privmsg(list[5], "chains: %d" % len(statetab.items()))
56 #loads in a previously pickled saved state
57 def markov_load(c,list,bot):
58 global statetab
59 global lock
61 cmd = list[4].split(" ")[0]
63 if cmd == "mkload":
64 fp = list[4].split(" ")[1]
66 try:
67 lock.acquire()
68 pkfile = open(fp,"r")
69 statetab = pickle.load(pkfile)
70 lock.release()
71 except IOError:
72 print "Could not load db: Doesn't exist\n"
75 #pickles out the state to a file
76 def markov_dump(c,list,bot):
77 global statetab
78 global lock
80 lock.acquire()
82 cmd = list[4].split(" ")[0]
84 if cmd == "mkdump":
85 fp = list[4].split(" ")[1]
87 pkfile = open(fp,"w+")
89 pickle.dump(statetab,pkfile)
91 lock.release()
93 def markov_learn(c,list,bot):
94 """ Should not be called directly """
95 global lock
97 cmd = list[4].split(" ")[0]
98 if cmd == "talk" or cmd == "markov_stats" or cmd == "mkload" or cmd == "mkdump":
99 return
100 lock.acquire()
102 words = [x.lower().strip() for x in list[4].split(" ") if not x.isspace()]
104 global statetab
105 global w1
106 global w2
108 w1 = w2 = "\n"
110 #go through every word and put them in a hash table.
111 #EX the sentence "Mary had a little lamb"
112 #first iteration, w1 and w2 are both empty.
113 #statetab[w1][w2] doesn't exist, so make it and set
114 #statetab[""][""] to Mary.
116 #Then, set w1 to w2 and w2 to i, so the chain moves forward.
117 for i in words:
118 statetab.setdefault((w1,w2),[]).append(i)
119 w1,w2 = w2, i
121 statetab.setdefault((w1,w2),[]).append("\n")
123 if nickmatch.search(list[4]) and bot.autorep == 1 and random.randint(0,10) == 0:
124 tmp = emit_chain(random.choice(list[4].split(" ")))
126 if len(tmp) <= 2:
127 return
129 c.privmsg(list[5], "%s: %s" % (list[0],tmp))
130 return
132 #randomly reply
133 if random.randint(0,15) == 0 and bot.talk == 1:
134 c.privmsg(list[5], "%s" % (emit_chain(random.choice(list[4].split(" ")))))
136 lock.release()
138 def emit_chain(key):
139 global statetab
140 global w1
141 global w2
143 i = 0
145 w1 = w2 = "\n"
147 newword = ""
149 #make the first word the key if its not a space
150 # if(key != " "):
151 # retval = key + " "
152 # else:
153 retval = ""
155 if key != " ":
156 w2 = key
158 while 1:
159 try:
160 newword = random.choice(statetab[(w1,w2)]).strip()
161 except KeyError:
162 return retval
164 retval = retval + newword + " "
165 w1,w2 = w2,newword
167 i = i + 1
169 #max of rand words if we don't hit a space or other error
170 if i >= random.randint(5,50):
171 return retval
173 return retval
175 def markov_talk(c,list,bot):
176 """ Makes the markov chain talk to you """
177 global last
179 cmd = list[4].split(" ")[0]
181 try:
182 key = list[4].split(" ")[1].lower()
183 except IndexError:
184 key = " "
186 if list[3] and cmd == "talk":
187 tmp = emit_chain(key);
188 if len(tmp) <= 2:
189 return
190 last = tmp
191 c.privmsg(list[5],"%s %s" % (key, tmp))
195 def tweet(c, args, bot):
196 cmd = args[4].split(" ")[0]
198 if cmd == "tweet":
199 api.PostUpdate(last)
200 c.privmsg(args[5], "Updated Twitter with message: %s" % last)