-
Notifications
You must be signed in to change notification settings - Fork 0
/
meatmonsters.py
146 lines (113 loc) · 4.67 KB
/
meatmonsters.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import os
import glob
import sys
import re
import random
import json
import base64
import hashlib
from random import choice
from socketIO_client import SocketIO
class Monster(object):
"""
A Monster is a bot instance, created from a directory containing an attributes.json
file plus a collection of gifs and text files for each defined action.
"""
@staticmethod
def get_gif (filename):
"""get a gif from the filesystem and base64 encode it"""
with open (filename, "rb") as image_file:
data = base64.b64encode(image_file.read())
gif = "data:image/gif;base64," + data
return gif
@staticmethod
def get_txt (filename):
"""create a collection from a text file"""
with open (filename, "r") as text_file:
lines = [line.rstrip() for line in text_file.readlines()]
return lines
def __init__(self, files):
"""initialize a bot from a directory"""
with open (os.sep.join([files, "attributes.json"]), 'r') as conf:
self.config = json.load(conf)
self.name = self.config["name"]
self.actions = {}
self.triggers = {}
for action, triggers in self.config["actions"].items():
if action not in self.actions:
self.actions[action] = {"gifs":[], "txts":[]}
gif_blob = os.sep.join([files, action]) + "*.gif"
for gif_path in glob.glob(gif_blob):
self.actions[action]["gifs"].append(Monster.get_gif(gif_path))
txt_name = ".".join([action, "txt"])
txt_path = os.sep.join([files, txt_name])
self.actions[action]["txts"] = Monster.get_txt(txt_path)
for trigger in triggers:
compiled = re.compile(trigger, re.IGNORECASE)
self.triggers[compiled] = {"monster":self.name, "action":action}
def action(self, action):
"""return information for a called action"""
values = {}
values["message"] = choice(self.actions[action]["txts"])
values["picture"] = choice(self.actions[action]["gifs"])
return values
class MeatMonsters(object):
"""
MeatMonsters is a framework for loading a collection of Monsters,
connecting them to meatspace and dispatching commands to them
"""
def __init__(self):
"""initialize a MeatMonsters collection from a config file"""
with open ('meatmonsters.json', 'r') as conf:
self.config = json.load(conf)
self.api_key = self.config["key"]
self.address = self.config["address"]
self.monsters_dir = "./monsters/"
self.fingerprint = "thisisthemeatmonsterfingerprint"
self.debug = True
self.monsters = {}
self.triggers = {}
self.load_monsters()
def load_monsters(self):
"""load all monsters from monster subdirectory"""
for monster_subdir in os.walk(self.monsters_dir).next()[1]:
monster_path = os.sep.join([self.monsters_dir, monster_subdir])
monster = Monster(files=monster_path)
self.monsters[monster.name] = monster
for trigger, action in monster.triggers.items():
self.triggers[trigger] = action
def get_post (self, data):
"""extract wanted information from meatspace post"""
post = {}
post["key"] = data["chat"]["key"]
post["message"] = data["chat"]["value"]["message"]
return post
def get_message (self, reply, image):
"""given a reply string and an image, construct a response"""
message = {}
message ['apiKey'] = self.api_key
message ['message'] = reply
message ['fingerprint'] = self.fingerprint
message ['picture'] = image
return message
def send_message (self, reply, image):
"""send a message to meatspace"""
SocketIO(self.address).emit('message', self.get_message(reply, image))
def on_message(self, *args):
"""handles incoming messages from meatspace"""
post = self.get_post (args[0])
print post['message']
for trigger, action in self.triggers.items():
if trigger.search(post['message']):
values = self.monsters[action['monster']].action(action['action'])
self.send_message(values["message"], values["picture"])
def run (self):
"""start the monsters!"""
if self.debug:
print "Listening to %s" % self.address
with SocketIO(self.address) as socketIO_listen:
socketIO_listen.on('message', self.on_message)
socketIO_listen.wait()
if __name__ == '__main__':
game = MeatMonsters()
game.run()