ee04134a by Barry

Full database integration. No more json!

1 parent 6c38afa3
No preview for this file type
1 import json 1 import json
2 import sqlite3 2 import sqlite3
3 import datetime
3 4
4 conn = sqlite3.connect('db.sqlite3') 5 conn = sqlite3.connect('db.sqlite3')
5 6
...@@ -65,6 +66,152 @@ def import_messages(conn): ...@@ -65,6 +66,152 @@ def import_messages(conn):
65 pass 66 pass
66 conn.commit() 67 conn.commit()
67 68
68 import_jokes(conn)
69 import_fortunes(conn)
70 import_messages(conn)
...\ No newline at end of file ...\ No newline at end of file
69 def get_game_names(game_id_list):
70 games_file = 'games.json'
71 json_data=open(games_file).read()
72 data = json.loads(json_data)
73 result = []
74 for game_id in game_id_list:
75 if isinstance(game_id, str) and not game_id.isdigit():
76 result.append(game_id)
77 continue
78 name_set = False
79 for game in data:
80 if game['id'] == game_id:
81 result.append(game['name'])
82 name_set = True
83 return result
84
85 def dict_factory(cursor, row):
86 if row == None:
87 return None
88 d = {}
89 for idx, col in enumerate(cursor.description):
90 d[col[0]] = row[idx]
91 return d
92
93 def db_get_member(discord_id=None, username=None):
94 # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name
95 c = conn.cursor()
96 result = None
97 if discord_id:
98 result = c.execute("SELECT member_id, member_name, discord_id, discord_mention, is_afk, afk_at, status, prev_status, status_change_at, current_game FROM members WHERE discord_id = ?;", (discord_id,)).fetchone()
99 if username:
100 result = c.execute("SELECT member_id, member_name, discord_id, discord_mention, is_afk, afk_at, status, prev_status, status_change_at, current_game FROM members WHERE member_name = ?;", (username,)).fetchone()
101 return dict_factory(c, result)
102 def log(message):
103 print("{} - {}".format(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S'), message))
104
105 def db_add_game(member_id, game_name):
106 # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name
107 c = conn.cursor()
108 games = c.execute("SELECT game_id FROM games WHERE game_name = ?;", (game_name,)).fetchone()
109 db_game_id = 0
110 if not games:
111 log("Adding Game: {}".format(game_name,))
112 c.execute("INSERT INTO games(game_name) VALUES(?);", (game_name,))
113 conn.commit()
114 db_game_id = c.execute("select last_insert_rowid();").fetchone()[0]
115 else:
116 db_game_id = games[0]
117 #log("DB Game ID: {}".format(db_game_id,))
118 member_games = c.execute("SELECT launch_count FROM xmember_games WHERE game_id = ? AND member_id = ?;", (db_game_id, member_id)).fetchone()
119 if not member_games:
120 #log("Inserting Member Games: {}, {}".format(db_game_id, member_id))
121 c.execute("INSERT INTO xmember_games(game_id, member_id, launch_count) VALUES(?, ?, 1);", (db_game_id, member_id))
122 conn.commit()
123 else:
124 #log("Updating Member Games: {}, {}".format(db_game_id, member_id))
125 c.execute("UPDATE xmember_games SET launch_count = launch_count + 1 WHERE game_id = ? AND member_id = ?;", (db_game_id, member_id))
126 conn.commit()
127
128 def db_create_member(member):
129 # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name
130 c = conn.cursor()
131 c.execute("""INSERT INTO members (member_name, discord_id, discord_mention,
132 is_afk, afk_at, status, prev_status,
133 status_change_at, current_game)
134 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?);""", (member.name.lower(),
135 member.id, member.mention,
136 0, datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S'),
137 'online', 'offline',
138 datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S'),
139 member.game_id))
140 conn.commit()
141 if member.game_id != None:
142 db_add_game(db_get_member(member.id)['member_id'], member.game_id)
143 class Member:
144 pass
145 def import_games(conn):
146 games_file = 'games.json'
147 members_file = 'members.json'
148
149 json_data=open(members_file).read()
150 member_data = json.loads(json_data)
151
152 json_data=open(games_file).read()
153 game_data = json.loads(json_data)
154
155 c = conn.cursor()
156 user_games = {}
157 for username in member_data:
158 if 'games_played' in member_data[username]:
159 for game_id in member_data[username]['games_played']:
160 if (game_id != 'None' and game_id != 0):
161 if username not in user_games:
162 user_games[username] = []
163 if game_id:
164 if isinstance( game_id, int) or game_id.isdigit():
165 game_names = get_game_names([game_id])
166 #print(game_names)
167 if len(game_names) > 0:
168 user_games[username].append(game_names[0])
169 else:
170 user_games[username].append(game_id)
171 #print(user_games)
172 for username, game_list in user_games.iteritems():
173 member = db_get_member(username=username)
174 if member:
175 for game in game_list:
176 db_add_game(member['member_id'], game)
177 print("Added Game: {} - {}".format(member['member_id'], game))
178 else:
179 if 'id' not in member_data[username]:
180 continue
181 member_to_create = Member()
182 member_to_create.name = username
183 member_to_create.id = member_data[username]['id']
184 member_to_create.mention = member_data[username]['mention']
185 member_to_create.game_id = None
186 db_create_member(member_to_create)
187 print("missing {}".format(byteify(username)))
188 print(member_to_create)
189
190
191
192 # 'id': user_id,
193 # 'mention': mention,
194 # 'is_afk': is_afk,
195 # 'afk_at': afk_at,
196 # 'status': status,
197 # 'prev_status': prev_status,
198 # 'status_change_at': status_change_at,
199 # 'game_id': game_id,
200 # 'games_played': games_played,
201 # 'aliases': aliases
202
203
204 # for username in data:
205 # print("Username: %s" % username)
206 # for author in data[username]:
207 # try:
208 # c.execute("INSERT INTO messages (message, delivery_time, channel, message_from, message_to, user_id) VALUES (?, ?, ?, ?, ?, ?)", (data[username][author]['message'], data[username][author]['delivery_time'],data[username][author]['channel'], author, username, data[username][author]['user_id']))
209 # except Exception as e:
210 # print(e)
211 # pass
212 # conn.commit()
213
214 #import_jokes(conn)
215 #import_fortunes(conn)
216 #import_messages(conn)
217 #import_games(conn)
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -3,6 +3,7 @@ import discord ...@@ -3,6 +3,7 @@ import discord
3 import random 3 import random
4 import datetime 4 import datetime
5 import re 5 import re
6 import operator
6 7
7 import traceback 8 import traceback
8 import sys 9 import sys
...@@ -34,6 +35,14 @@ muted_until = datetime.datetime.now() ...@@ -34,6 +35,14 @@ muted_until = datetime.datetime.now()
34 client = discord.Client() 35 client = discord.Client()
35 wolf = {} 36 wolf = {}
36 37
38
39 #####################
40 ## Utility Functions
41 #####################
42
43 def log(message):
44 print("{} - {}".format(datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S'), message))
45
37 def format_exception(e): 46 def format_exception(e):
38 exception_list = traceback.format_stack() 47 exception_list = traceback.format_stack()
39 exception_list = exception_list[:-2] 48 exception_list = exception_list[:-2]
...@@ -89,76 +98,228 @@ def search_google_images(query, animated=False): ...@@ -89,76 +98,228 @@ def search_google_images(query, animated=False):
89 return search_result 98 return search_result
90 return "boo you fail.." 99 return "boo you fail.."
91 100
101 ##################
102 ## Database Calls
103 ##################
104
105 # Converts a row into a dictionary
106 def dict_factory(cursor, row):
107 if row == None:
108 return None
109 d = {}
110 for idx, col in enumerate(cursor.description):
111 d[col[0]] = row[idx]
112 return d
113
114 def db_add_message(message, delivery_time, channel, message_from, message_to, user_id):
115 c = conn.cursor()
116 c.execute("""INSERT INTO messages(message, delivery_time, channel, message_from, message_to, user_id)
117 VALUES(?, ?, ?, ?, ?, ?);""", (message, delivery_time, channel, message_from, message_to, user_id))
118 conn.commit()
119
120 def db_delete_sent_message(message_id):
121 c = conn.cursor()
122 c.execute("DELETE FROM messages WHERE message_id = ?;", (message_id,))
123 conn.commit()
124
125 def db_get_aliases(member_id):
126 c = conn.cursor()
127 aliases = c.execute("SELECT alias_name FROM aliases WHERE member_id = ?;", (member_id,)).fetchall()
128 if aliases:
129 alias_list = []
130 for alias in aliases:
131 alias_list.append(alias[0])
132 return alias_list
133 else:
134 return None
135
136 def db_add_aliases(member_id, alias_name):
137 c = conn.cursor()
138 c.execute("INSERT INTO aliases(alias_name, member_id) VALUES (?, ?);", (alias_name, member_id,))
139 conn.commit()
140
141 def db_get_messages():
142 msg_conn = sqlite3.connect('db.sqlite3')
143
144 c = msg_conn.cursor()
145 messages = c.execute("SELECT * FROM messages WHERE datetime('now') >= datetime( replace(delivery_time, '/', '-'));").fetchall()
146 if messages:
147 db_messages = []
148 for message in messages:
149 db_messages.append(dict_factory(c, message))
150 else:
151 db_messages = None
152 msg_conn.close()
153 return db_messages
154
155 def db_get_whoplayed(game_name):
156 c = conn.cursor()
157 members = c.execute("""SELECT m.member_name, xmg.launch_count
158 FROM members m
159 INNER JOIN xmember_games xmg ON
160 m.member_id = xmg.member_id
161 INNER JOIN games g ON
162 g.game_id = xmg.game_id
163 WHERE g.game_name COLLATE nocase = ?
164 Order By xmg.launch_count, m.member_name DESC;""", (game_name,)).fetchall()
165 member_list = {}
166 for member in members:
167 member_list[member[0]] = member[1]
168 #log(member_list)
169 return sorted(member_list.items(), reverse=True, key=operator.itemgetter(1))
170 #return sorted(member_list, reverse=True, key=lambda tup: tup[1])
171
172 def db_get_games(username):
173 c = conn.cursor()
174 games = c.execute("""SELECT g.game_name, xmg.launch_count FROM games g
175 INNER JOIN xmember_games xmg ON
176 g.game_id = xmg.game_id
177 INNER JOIN members m ON
178 m.member_id = xmg.member_id
179 WHERE m.member_name COLLATE nocase = ?;""", (username,)).fetchall()
180 games_list = {}
181 for game in games:
182 games_list[game[0]] = game[1]
183 return games_list
184
185 def db_get_games_list(limit):
186 c = conn.cursor()
187 games_list = c.execute("""SELECT g.game_name, count(DISTINCT xmg.member_id)
188 FROM games g
189 INNER JOIN xmember_games xmg ON
190 g.game_id = xmg.game_id
191 Group By xmg.game_id
192 Order By COUNT(DISTINCT xmg.member_id) DESC
193 LIMIT ?""", (limit,)).fetchall()
194 return games_list
195
196 def db_add_game(member_id, game_name):
197 # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name
198 c = conn.cursor()
199 games = c.execute("SELECT game_id FROM games WHERE game_name = ?;", (game_name,)).fetchone()
200 db_game_id = 0
201 if not games:
202 log("Adding Game: {}".format(game_name,))
203 c.execute("INSERT INTO games(game_name) VALUES(?);", (game_name,))
204 conn.commit()
205 db_game_id = c.execute("select last_insert_rowid();").fetchone()[0]
206 else:
207 db_game_id = games[0]
208 #log("DB Game ID: {}".format(db_game_id,))
209 member_games = c.execute("SELECT launch_count FROM xmember_games WHERE game_id = ? AND member_id = ?;", (db_game_id, member_id)).fetchone()
210 if not member_games:
211 #log("Inserting Member Games: {}, {}".format(db_game_id, member_id))
212 c.execute("INSERT INTO xmember_games(game_id, member_id, launch_count) VALUES(?, ?, 1);", (db_game_id, member_id))
213 conn.commit()
214 else:
215 #log("Updating Member Games: {}, {}".format(db_game_id, member_id))
216 c.execute("UPDATE xmember_games SET launch_count = launch_count + 1 WHERE game_id = ? AND member_id = ?;", (db_game_id, member_id))
217 conn.commit()
218
219 def db_get_member(discord_id=None, username=None):
220 # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name
221 member_conn = sqlite3.connect('db.sqlite3')
222
223 c = member_conn.cursor()
224 result = None
225 if discord_id:
226 result = c.execute("SELECT member_id, member_name, discord_id, discord_mention, is_afk, afk_at, status, prev_status, status_change_at, current_game FROM members WHERE discord_id = ?;", (discord_id,)).fetchone()
227 if username:
228 result = c.execute("SELECT member_id, member_name, discord_id, discord_mention, is_afk, afk_at, status, prev_status, status_change_at, current_game FROM members WHERE member_name = ?;", (username,)).fetchone()
229 member_conn.close()
230 return dict_factory(c, result)
231
232 def db_create_member(member):
233 # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name
234 c = conn.cursor()
235 c.execute("""INSERT INTO members (member_name, discord_id, discord_mention,
236 is_afk, afk_at, status, prev_status,
237 status_change_at, current_game)
238 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?);""", (member.name.lower(),
239 member.id, member.mention(),
240 0, datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S'),
241 'online', 'offline',
242 datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S'),
243 member.game_id))
244 conn.commit()
245 if member.game_id != None:
246 db_add_game(db_get_member(member.id)['member_id'], member.game_id)
247
248 def db_update_member(member, db_member):
249 # Do a lookup by ID, if it's found but the name doesn't match then add a row to aliases with the previous name and change the member name
250 db_member_id = db_member['member_id']
251 db_membername = db_member['member_name']
252 status = db_member['status']
253 prev_status = db_member['prev_status']
254
255 c = conn.cursor()
256 if member.name.lower() != db_membername:
257 log("Member Name changed! {} to {}".format(db_membername, member.name.lower()))
258 c.execute("UPDATE members SET member_name = ? WHERE discord_id = ?;", (member.name.lower(), member.id,))
259 conn.commit()
260
261 aliases = c.execute("SELECT * FROM aliases WHERE alias_name = ? AND member_id = ?;", (db_membername, db_member_id)).fetchone()
262 log("Alias list for user: {}".format(aliases))
263 if aliases == None:
264 log("creating new alias: {}, {}".format(db_membername, db_member_id))
265 c.execute("INSERT INTO aliases (alias_name, member_id) VALUES (?, ?);", (db_membername, db_member_id))
266 conn.commit()
267
268 if member.status == 'idle':
269 afk_at = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
270 is_afk = True
271 else:
272 is_afk = False
273 status_change_at = None
274 if status != member.status:
275 prev_status = status
276 status = member.status
277 status_change_at = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
278 if is_afk:
279 #log("is afk")
280 c.execute("""UPDATE members
281 SET is_afk = ?, afk_at = ?, status = ?,
282 prev_status = ?, status_change_at = ?
283 WHERE discord_id = ?;""", (1, afk_at, status, prev_status, status_change_at, member.id))
284 conn.commit()
285 else:
286 #log("is not afk")
287 c.execute("""UPDATE members
288 SET is_afk = ?, status = ?,
289 prev_status = ?, status_change_at = ?
290 WHERE discord_id = ?;""", (0, status, prev_status, status_change_at, member.id))
291 conn.commit()
292 c.execute("UPDATE members SET current_game = ? WHERE discord_id = ?;", (member.game_id, member.id))
293 conn.commit()
294
295 #log("Member: {} \nMember GameID: {} db Game id: {}".format(member, member.game_id, db_member['current_game']))
296 if member.game_id != None and member.game_id != db_member['current_game']:
297 db_add_game(db_member['member_id'], member.game_id)
298
299 #################
300 ## Client Events
301 #################
302
92 @client.event 303 @client.event
93 def on_socket_raw_send(payload, binary=False): 304 def on_socket_raw_send(payload, binary=False):
94 check_msg_queue() 305 check_msg_queue()
95 306
96 @client.event 307 @client.event
97 def on_status(member): 308 def on_status(member):
98 #print("Status Changed %s" % (member,))
99 try:
100 json_data=open(member_status).read()
101 data = json.loads(json_data)
102 print(json_data)
103 except ValueError:
104 data = {}
105 if not data:
106 data = {}
107 try: 309 try:
108 username = member.name.lower() 310 db_member = db_get_member(member.id)
109 user_id = member.id 311 #log(db_member)
110 mention = member.mention() 312 if not db_member:
111 if username in data: 313 log("Creating new member: {}".format(member) )
112 is_afk = data[username]['is_afk'] 314 db_create_member(member)
113 afk_at = data[username]['afk_at']
114 status = data[username]['status']
115 prev_status = data[username]['prev_status']
116 status_change_at = data[username]['status_change_at']
117 game_id = data[username]['game_id']
118 games_played = data[username]['games_played']
119 aliases = data[username]['aliases']
120 else:
121 is_afk = False
122 afk_at = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
123 status = 'online'
124 prev_status = 'offline'
125 status_change_at = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
126 game_id = None
127 games_played = []
128 aliases = []
129 if member.status == 'idle':
130 afk_at = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
131 is_afk = True
132 else: 315 else:
133 is_afk = False 316 #log("Updating member: {}".format(member) )
134 if status != member.status: 317 db_update_member(member, db_member)
135 prev_status = status
136 status = member.status
137 status_change_at = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S')
138 if game_id != member.game_id:
139 game_id = member.game_id
140 if game_id not in games_played:
141 games_played.append(game_id)
142 data[username] = {
143 'id': user_id,
144 'mention': mention,
145 'is_afk': is_afk,
146 'afk_at': afk_at,
147 'status': status,
148 'prev_status': prev_status,
149 'status_change_at': status_change_at,
150 'game_id': game_id,
151 'games_played': games_played,
152 'aliases': aliases
153 }
154 #print('Status Change: %s' % (data,))
155 jdata = json.dumps(data, ensure_ascii=False)
156 except Exception as e:
157 print('Error saving status change: %s' % (e),)
158 return
159 318
160 open(member_status, 'wb+').write(jdata.encode('utf8')) 319 check_msg_queue()
161 check_msg_queue() 320 except Exception as e:
321 log("Exception: {}".format(format_exception(e)))
322 pass
162 323
163 def get_game_names(game_id_list): 324 def get_game_names(game_id_list):
164 json_data=open(games_file).read() 325 json_data=open(games_file).read()
...@@ -190,46 +351,21 @@ def get_mention_status(mention): ...@@ -190,46 +351,21 @@ def get_mention_status(mention):
190 return None 351 return None
191 352
192 def check_msg_queue(): 353 def check_msg_queue():
193 print("checking messages") 354 #print("checking messages")
194 try: 355 messages = db_get_messages()
195 json_data=open(deliveries_file).read() 356 if messages:
196 data = json.loads(json_data) 357 for message in messages:
197 except ValueError: 358 try:
198 data = {} 359 member = db_get_member(filter(unicode.isalnum, message['message_to']))
199 if not data: 360 if member:
200 data = {} 361 if message['message_to'] == member['discord_mention']:
201 #print("Data: %s" % data) 362 print("Found Message: {} - {} - Status: {} Channel: {}".format(message['message_to'], member['discord_mention'], member['status'], message['channel']))
202 new_data = {} 363 if member['status'] == 'online':
203 for username in data: 364 client.send_message(Object(message['channel']), '{}, {} asked me to tell you "{}"'.format(message['message_to'], message['message_from'], message['message']))
204 for author in data[username]: 365 db_delete_sent_message(message['message_id'])
205 print("Message: %s" % data[username][author]) 366 except Exception as e:
206 delivery = datetime.datetime.strptime(data[username][author]['delivery_time'], '%Y/%m/%d %H:%M:%S') 367 log("{}\nFailed to send message: {}".format(format_exception(e), message['message_id'],))
207 if delivery <= datetime.datetime.now(): 368 return
208 offline = False
209 for member in client.get_all_members():
210 print('MEMBER MENTION: %s USERNAME: %s' % (member.mention(), username))
211
212 if username == member.mention():
213 if member.status != 'online':
214 print('OFFLINE USER, TRY AGAIN LATER')
215 offline = True
216 break
217 if offline:
218 new_data[username] = {}
219 new_data[username][author] = data[username][author]
220 break
221 channel = Object(data[username][author]['channel'])
222 message = data[username][author]['message']
223 client.send_message(channel, '{}, {} asked me to tell you "{}"'.format(username, author, message))
224 else:
225 new_data[username] = {}
226 new_data[username][author] = data[username][author]
227
228 jdata = json.dumps(new_data, ensure_ascii=False)
229 #print("New Data: %s" % new_data)
230 open(deliveries_file, 'wb+').write(jdata.encode('utf8'))
231 return
232
233 369
234 @client.event 370 @client.event
235 def on_message(message): 371 def on_message(message):
...@@ -282,32 +418,26 @@ Stuff: ...@@ -282,32 +418,26 @@ Stuff:
282 return 418 return
283 419
284 if message.content.startswith('!lastseen'): 420 if message.content.startswith('!lastseen'):
285 data = None 421 username = message.content[10:].replace('@', '').lower()
286 try: 422 member = db_get_member(username=username)
287 json_data=open(member_status).read() 423 log(member)
288 data = json.loads(json_data) 424 if member:
289 except ValueError: 425 out_string = ''
290 pass 426 if member['is_afk'] == 1:
291 if not data: 427 out_string = 'Went AFK at: {}\n'.format(member['afk_at'])
292 client.send_message(message.channel, 'I am a bit confused right now.. maybe I need more data. {}!'.format(message.author.mention())) 428 elif member['status'] == 'offline':
293 else: 429 out_string = 'Currently Offline\n'
294 username = message.content[10:].replace('@', '').lower()
295 if username in data:
296 out_string = ''
297 if data[username]['is_afk'] == True:
298 out_string = 'Went AFK at: {}\n'.format(data[username]['afk_at'])
299 elif data[username]['status'] == 'offline':
300 out_string = 'Currently Offline\n'
301 else:
302 out_string = 'Currently Online\n'
303 out_string += 'Last Status: {} at {} which was {}\nPrevious Status: {}\n'.format(data[username]['status'],
304 data[username]['status_change_at'],
305 human(datetime.datetime.strptime(data[username]['status_change_at'], '%Y/%m/%d %H:%M:%S')),
306 data[username]['prev_status'])
307
308 client.send_message(message.channel, 'Last Information on {}:\n{}'.format(username, out_string))
309 else: 430 else:
310 client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(username, message.author.mention())) 431 out_string = 'Currently Online\n'
432 out_string += 'Last Status: {} at {} which was {}\nPrevious Status: {}\n'.format(member['status'],
433 member['status_change_at'],
434 human(datetime.datetime.strptime(member['status_change_at'], '%Y/%m/%d %H:%M:%S')),
435 member['prev_status'])
436
437 client.send_message(message.channel, 'Last Information on {}:\n{}'.format(username, out_string))
438 else:
439 client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(username, message.author.mention()))
440 return
311 441
312 if message.content.startswith('!shutup'): 442 if message.content.startswith('!shutup'):
313 muted_until = datetime.datetime.now() + datetime.timedelta(minutes=5) 443 muted_until = datetime.datetime.now() + datetime.timedelta(minutes=5)
...@@ -360,136 +490,72 @@ Stuff: ...@@ -360,136 +490,72 @@ Stuff:
360 client.send_message(message.channel, out_string) 490 client.send_message(message.channel, out_string)
361 return 491 return
362 492
363 if message.content.startswith('!gameslist'): 493 if message.content.startswith('!gameslist') or message.content.startswith('!gamelist') :
364 data = None 494 parts = message.content.split(' ')
365 try: 495 limit = 20
366 json_data=open(member_status).read() 496 if len(parts) > 1 and parts[1].isdigit():
367 data = json.loads(json_data) 497 limit = int(parts[1])
368 except ValueError: 498 games_list = db_get_games_list(limit)
369 pass 499
370 if not data: 500 out_string = ''
371 client.send_message(message.channel, 'I am a bit confused right now.. maybe I need more data. {}!'.format(message.author.mention())) 501 for game in games_list:
372 else: 502 out_string += ' {} - {}\n'.format(game[1], byteify(game[0]))
373 parts = message.content.split(' ') 503 client.send_message(message.channel, 'The games I have seen people playing are: ')
374 limit = 20 504 while len(out_string) > 0:
375 if len(parts) > 1 and parts[1].isdigit(): 505 client.send_message(message.channel, out_string[:1900])
376 limit = int(parts[1]) 506 out_string = out_string[1900:]
377
378 game_list = []
379 for user in data:
380 if 'games_played' in data[user]:
381 #print('%s' % data[user]['games_played'])
382
383 game_list += data[user]['games_played']
384 print('%s' % game_list)
385 games_sorted = leaders(get_game_names(game_list), top=limit)
386 print('%s' % games_sorted)
387 out_string = ''
388 for game in games_sorted:
389 #print('%s' % game)
390 out_string += ' {} - {}\n'.format(game[1], game[0])
391
392 client.send_message(message.channel, 'The games I have seen people playing are: ')
393 while len(out_string) > 0:
394 client.send_message(message.channel, out_string[:1900])
395 out_string = out_string[1900:]
396 507
397 return 508 return
398 509
399 if message.content.startswith('!aliases'): 510 if message.content.startswith('!aliases'):
400 data = None 511 username = message.content[9:].replace('@', '').lower()
401 try: 512 member = db_get_member(username=username)
402 json_data=open(member_status).read() 513 if member:
403 data = json.loads(json_data) 514 aliases = db_get_aliases(member['member_id'])
404 except ValueError: 515 if aliases:
405 pass 516 client.send_message(message.channel, '{} has the following aliases: {}'.format(username, ', '.join(aliases)))
406 if not data:
407 client.send_message(message.channel, 'I am a bit confused right now.. maybe I need more data. {}!'.format(message.author.mention()))
408 else:
409 username = message.content[9:].replace('@', '').lower()
410 if username.strip() == '':
411 client.send_message(message.channel, '{} please provide a username. !aliases <username>'.format(message.author.mention()))
412 return
413 if username in data and 'aliases' in data[username]:
414 client.send_message(message.channel, '{} has the following aliases: {}'.format(username, ', '.join(data[username]['aliases'])))
415 else: 517 else:
416 client.send_message(message.channel, 'No known alises for {} yet {}'.format(username, message.author.mention())) 518 client.send_message(message.channel, 'No known alises for {} yet {}'.format(username, message.author.mention()))
519 else:
520 client.send_message(message.channel, 'I don\'t know who you are speaking of {}!'.format(message.author.mention()))
417 return 521 return
418 522
419 if message.content.startswith('!addalias'): 523 if message.content.startswith('!addalias'):
420 data = None 524 alias = message.content[10:]
421 try: 525 username = message.author.name.lower()
422 json_data=open(member_status).read() 526 member = db_get_member(username=username)
423 data = json.loads(json_data) 527 if member:
424 except ValueError: 528 db_add_aliases(member['member_id'], alias)
425 pass 529 client.send_message(message.channel, '{} has been added to your aliases'.format(alias))
426 if not data:
427 client.send_message(message.channel, 'I am a bit confused right now.. maybe I need more data. {}!'.format(message.author.mention()))
428 else: 530 else:
429 alias = message.content[10:] 531 client.send_message(message.channel, 'Something horrible happened and it is all your fault, try logging out / on again or play a game. (or fuck off i dunno i\'m just an error message. Who am I to tell you how to run your life...)')
430 username = message.author.name.lower()
431 if username in data:
432 if 'aliases' not in data[username]:
433 data[username]['aliases'] = []
434 data[username]['aliases'].append(alias)
435 jdata = json.dumps(data, ensure_ascii=False)
436
437 open(member_status, 'wb+').write(jdata.encode('utf8'))
438 client.send_message(message.channel, '{} has been added to your aliases'.format(alias))
439 else:
440 client.send_message(message.channel, 'Something horrible happened and it is all your fault.')
441 return 532 return
442 533
443 if message.content.startswith('!games'): 534 if message.content.startswith('!games'):
444 data = None 535 username = message.content[7:].replace('@', '').lower()
445 try: 536 games_list = db_get_games(username)
446 json_data=open(member_status).read() 537 if games_list:
447 data = json.loads(json_data) 538 games = ', '.join(games_list)
448 except ValueError: 539 client.send_message(message.channel, 'I have seen {} playing: {}'.format(username, games))
449 pass
450 if not data:
451 client.send_message(message.channel, 'I am a bit confused right now.. maybe I need more data. {}!'.format(message.author.mention()))
452 else: 540 else:
453 username = message.content[7:].replace('@', '').lower() 541 client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(username, message.author.mention()))
454 if username in data:
455 games = ', '.join(get_game_names(data[username]['games_played']))
456 client.send_message(message.channel, 'I have seen {} playing: {}'.format(username, games))
457 else:
458 client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(username, message.author.mention()))
459 return
460 542
461 if message.content.startswith('!whoplayed'): 543 if message.content.startswith('!whoplayed'):
462 member_data = None 544 game_name = message.content[11:]
463 try: 545 member_list = db_get_whoplayed(game_name)
464 json_data=open(member_status).read() 546 if not member_list:
465 member_data = json.loads(json_data) 547 client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(byteify(game_name), message.author.mention()))
466 except ValueError:
467 pass
468 if not member_data:
469 client.send_message(message.channel, 'I am a bit confused right now.. maybe I need more data. {}!'.format(message.author.mention()))
470 else: 548 else:
471 game_name = message.content[11:] 549 out_string = ''
472 json_data=open(games_file).read() 550 for member in member_list:
473 data = json.loads(json_data) 551 out_string += ' {} - {}\n'.format(byteify(member[1]), byteify(member[0]))
474 game_id = 0 552 client.send_message(message.channel, 'Below is a list of people who have played {} and the number of times they have launched the game:'.format(byteify(game_name),))
475 for game in data: 553 while len(out_string) > 0:
476 if game['name'].lower() == game_name.lower(): 554 client.send_message(message.channel, out_string[:1900])
477 game_id = game['id'] 555 out_string = out_string[1900:]
478 #if game_id == 0:
479 # #client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(game_name, message.author.mention()))
480 # #return
481 matched_usernames = []
482 for username in member_data:
483 if 'games_played' in member_data[username]:
484 for id in member_data[username]['games_played']:
485 if id == game_name or (id == game_id and game_id != 0):
486 matched_usernames.append(username)
487 if len(matched_usernames) == 0:
488 client.send_message(message.channel, 'I don\'t have any data on {} yet {}'.format(game_name, message.author.mention()))
489 else:
490 client.send_message(message.channel, 'I have seen {} playing: {}'.format(', '.join(matched_usernames), game_name))
491
492 return 556 return
557
558
493 # !msg joe in 5 minutes YOU ARE A DICK 559 # !msg joe in 5 minutes YOU ARE A DICK
494 if message.content.startswith('!msg'): 560 if message.content.startswith('!msg'):
495 try: 561 try:
...@@ -530,6 +596,7 @@ Stuff: ...@@ -530,6 +596,7 @@ Stuff:
530 596
531 username = message_bits[1] 597 username = message_bits[1]
532 user_mention = '' 598 user_mention = ''
599 # TODO: have it look in the database. Do this AFTER on startup we add all users.
533 for member in client.get_all_members(): 600 for member in client.get_all_members():
534 print("MEMBER: %s" % member) 601 print("MEMBER: %s" % member)
535 if username.lower() == member.name.lower(): 602 if username.lower() == member.name.lower():
...@@ -542,16 +609,17 @@ Stuff: ...@@ -542,16 +609,17 @@ Stuff:
542 msg_text = byteify(' '.join(message_bits[msg_idx:])) 609 msg_text = byteify(' '.join(message_bits[msg_idx:]))
543 message = {'user_id': user_id, 'channel': channel.id, 'delivery_time': msg_datetime.strftime('%Y/%m/%d %H:%M:%S'), 'message': msg_text} 610 message = {'user_id': user_id, 'channel': channel.id, 'delivery_time': msg_datetime.strftime('%Y/%m/%d %H:%M:%S'), 'message': msg_text}
544 print("Message: %s" % message) 611 print("Message: %s" % message)
545 data[user_mention] = {} 612 db_add_message(msg_text, msg_datetime.strftime('%Y-%m-%d %H:%M:%S'), channel.id, author.mention(), user_mention, user_id)
546 data[user_mention][author.mention()] = message 613 # data[user_mention] = {}
547 jdata = json.dumps(data, ensure_ascii=False) 614 # data[user_mention][author.mention()] = message
548 print("Data: %s" % data) 615 # jdata = json.dumps(data, ensure_ascii=False)
616 # print("Data: %s" % data)
549 #test_ch = Object(channel.id) 617 #test_ch = Object(channel.id)
550 #client.send_message(test_ch, 'Test Message {}.'.format(author)) 618 #client.send_message(test_ch, 'Test Message {}.'.format(author))
551 except Exception as e: 619 except Exception as e:
552 client.send_message(channel, 'Your shitty message has been rejected {}. {}'.format(author.name, e)) 620 client.send_message(channel, 'Your shitty message has been rejected {}. {}'.format(author.name, e))
553 return 621 return
554 open(deliveries_file, 'wb+').write(jdata.encode('utf8')) 622 # open(deliveries_file, 'wb+').write(jdata.encode('utf8'))
555 if msg_datetime < datetime.datetime.now(): 623 if msg_datetime < datetime.datetime.now():
556 client.send_message(channel, '{} your message will be delivered to {} as soon as they are available.'.format(author.name, user_mention)) 624 client.send_message(channel, '{} your message will be delivered to {} as soon as they are available.'.format(author.name, user_mention))
557 else: 625 else:
...@@ -675,6 +743,7 @@ def on_ready(): ...@@ -675,6 +743,7 @@ def on_ready():
675 print(client.user.name) 743 print(client.user.name)
676 print(client.user.id) 744 print(client.user.id)
677 print('------') 745 print('------')
746 check_msg_queue()
678 747
679 retries = 0 748 retries = 0
680 while retries < 1000: 749 while retries < 1000:
...@@ -683,7 +752,6 @@ while retries < 1000: ...@@ -683,7 +752,6 @@ while retries < 1000:
683 creds = json.loads(json_data) 752 creds = json.loads(json_data)
684 wolf = wolframalpha.Client(creds['wolframkey']) 753 wolf = wolframalpha.Client(creds['wolframkey'])
685 client.login(creds['username'], creds['password']) 754 client.login(creds['username'], creds['password'])
686
687 client.run() 755 client.run()
688 except KeyboardInterrupt: 756 except KeyboardInterrupt:
689 conn.close 757 conn.close
......
1 {"zan": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 09:25:10", "mention": "<@65178351664377856>", "prev_status": "online", "game_id": "Dragon's Dogma: Dark Arisen", "games_played": ["If My Heart Had Wings", "World of Warcraft", null, "XCOM: Enemy Unknown", "Go! Go! Nippon! ~My First Trip to Japan~", "Dragon's Dogma: Dark Arisen"], "afk_at": "2016/01/24 09:20:06", "id": "65178351664377856", "aliases": []}, "solidsteak": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 08:52:15", "mention": "<@62955839694053376>", "prev_status": "online", "game_id": "Rainbow Six Siege", "games_played": [248, null, 310, 533, 448, 715, 1, "Insurgency", "Rainbow Six Siege"], "afk_at": "2016/01/24 08:52:15", "id": "62955839694053376", "aliases": []}, "apple": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 09:34:37", "mention": "<@121822410096771072>", "prev_status": "idle", "games_played": [1, 6, null, "FINAL FANTASY XIV", "Borderlands 2"], "game_id": "FINAL FANTASY XIV", "afk_at": "2016/01/24 05:11:24", "id": "121822410096771072", "aliases": []}, "sheik": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/22 12:56:00", "mention": "<@48148712194576384>", "prev_status": "online", "game_id": "Guild Wars 2", "games_played": [283, null, 5, 11, 310, 249, 659, 308, 6, 260, 182, "Diablo 3", "Guild Wars 2", "Metal Gear Solid V: The Phantom Pain"], "afk_at": "2016/01/22 12:37:49", "id": "48148712194576384", "aliases": []}, "puncherboxer": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/04 04:11:44", "mention": "<@118544498996412416>", "prev_status": "online", "games_played": [], "game_id": null, "afk_at": "2015/12/04 03:48:11", "id": "118544498996412416"}, "rae": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 09:55:52", "mention": "<@48162082507456512>", "prev_status": "online", "game_id": "Dragon's Dogma: Dark Arisen", "games_played": [488, null, 141, "Dark Souls II", "Black Desert Online", "Dragon's Dogma: Dark Arisen"], "afk_at": "2016/01/24 09:55:52", "id": "48162082507456512", "aliases": []}, "marion": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/03 05:14:48", "prev_status": "online", "games_played": [1, null], "game_id": null, "afk_at": "2015/12/02 08:30:16"}, "shyrith": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/03 08:10:52", "prev_status": "online", "games_played": [1, 644, null], "game_id": null, "afk_at": "2015/12/02 21:54:35"}, "hiimapirate": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/12 05:08:57", "mention": "<@133758935009198080>", "prev_status": "online", "games_played": [], "game_id": null, "afk_at": "2015/12/20 11:34:43", "id": "133758935009198080", "aliases": []}, "az": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/23 06:17:41", "mention": "<@127330097949573121>", "prev_status": "online", "games_played": [], "game_id": null, "afk_at": "2015/12/19 06:10:40", "id": "127330097949573121", "aliases": []}, "yung_thirsty": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 08:36:17", "mention": "<@136368619423531008>", "prev_status": "online", "games_played": ["League of Legends", "Amnesia: The Dark Descent", "Clicker Heroes", "Crusader Kings II"], "game_id": "League of Legends", "afk_at": "2016/01/12 07:22:37", "id": "136368619423531008", "aliases": []}, "goshzilla": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 09:04:18", "mention": "<@47934670406422528>", "prev_status": "online", "games_played": [3, null, 6, 7, 777, "League of Legends", "Monster Hunter Online"], "game_id": "Monster Hunter Online", "afk_at": "2016/01/24 09:04:18", "id": "47934670406422528", "aliases": []}, "herbeh": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/11 10:46:35", "mention": "<@105392869782622208>", "prev_status": "online", "game_id": null, "games_played": [], "afk_at": "2016/01/11 08:46:57", "id": "105392869782622208", "aliases": []}, "eeri": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/15 06:31:49", "mention": "<@122023217371021313>", "prev_status": "online", "game_id": null, "games_played": [659, null], "afk_at": "2015/12/15 06:09:09", "id": "122023217371021313", "aliases": []}, "dick": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 10:00:54", "mention": "<@78767611436863488>", "prev_status": "online", "game_id": "Black Desert Online", "games_played": [372, null, 1, 488, "Dark Souls", "Metal Gear Solid V: The Phantom Pain", "Phantasy Star Online 2", "Black Desert Online"], "afk_at": "2016/01/24 10:00:54", "id": "78767611436863488", "aliases": []}, "arka": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 10:13:07", "mention": "<@121466618126532608>", "prev_status": "idle", "games_played": [1, null, 313, 488, "FINAL FANTASY XIV"], "game_id": "FINAL FANTASY XIV", "afk_at": "2016/01/24 09:57:47", "id": "121466618126532608", "aliases": []}, "wriggle": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/16 19:20:41", "mention": "<@80169354666192896>", "prev_status": "online", "games_played": [], "game_id": null, "afk_at": "2015/12/02 15:37:49", "id": "80169354666192896", "aliases": []}, "tim": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/04 10:25:19", "mention": "<@109145030354030592>", "prev_status": "online", "game_id": null, "games_played": [], "afk_at": "2015/12/04 07:08:23", "id": "109145030354030592"}, "charisma": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 07:23:41", "mention": "<@65187139276513280>", "prev_status": "online", "game_id": "Dragon's Dogma: Dark Arisen", "games_played": [313, null, 807, 471, 671, 728, 0, "Sony Playstation Emulator", "Black Desert Online", "Dragon's Dogma: Dark Arisen"], "afk_at": "2016/01/24 07:23:41", "id": "65187139276513280", "aliases": []}, "mate": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/04 09:11:30", "mention": "<@109145154044071936>", "prev_status": "online", "game_id": null, "games_played": [], "afk_at": "2015/12/04 05:06:58", "id": "109145154044071936"}, "sig": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/23 13:11:50", "mention": "<@104055037243707392>", "prev_status": "online", "games_played": [8, null, 7, 466, 588, 15, 6, 13, 165, 669, 101, "Diablo 3", "Tabletop Simulator", "DOTA 2", "Crusader Kings II"], "game_id": "DOTA 2", "afk_at": "2016/01/23 05:03:03", "id": "104055037243707392", "aliases": []}, "bunta": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 05:09:39", "mention": "<@122520378089275395>", "prev_status": "online", "game_id": null, "games_played": [488, null], "afk_at": "2016/01/24 05:09:39", "id": "122520378089275395", "aliases": []}, "mr. nelson": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/14 13:35:09", "mention": "<@103311664748707840>", "prev_status": "online", "game_id": null, "games_played": [], "afk_at": "2015/12/14 10:25:27", "id": "103311664748707840", "aliases": []}, "草 goshzilla": {"status": "online", "is_afk": false, "status_change_at": "2016/01/15 15:28:19", "mention": "<@47934670406422528>", "prev_status": "offline", "game_id": null, "games_played": [], "afk_at": "2016/01/15 08:23:14", "id": "47934670406422528", "aliases": []}, "skeletonhorn": {"status": "online", "is_afk": false, "status_change_at": "2015/12/03 00:36:39", "prev_status": "offline", "games_played": [], "game_id": null, "afk_at": "2015/12/03 00:36:39"}, "yoltan": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/08 23:38:09", "mention": "<@122369674808786948>", "prev_status": "online", "games_played": [238, null, 307], "game_id": null, "afk_at": "2015/12/04 16:14:00", "id": "122369674808786948", "aliases": []}, "rui": {"status": "online", "mention": "<@63649222993391616>", "is_afk": false, "games_played": [174, null, 660, 724, 488, 149, 780, 301, 438, 140, 680, "Grand Theft Auto V", "Dragon's Dogma: Dark Arisen"], "game_id": "Dragon's Dogma: Dark Arisen", "afk_at": "2016/01/24 09:55:44", "status_change_at": "2016/01/24 10:04:13", "id": "63649222993391616", "prev_status": "idle", "aliases": []}, "adol": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 04:45:52", "mention": "<@122079633796497409>", "prev_status": "online", "game_id": "Clicker Heroes", "games_played": [550, null, 1, "Black Desert Online", "Clicker Heroes"], "afk_at": "2016/01/24 03:10:24", "id": "122079633796497409", "aliases": []}, "xorfos": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 06:54:12", "mention": "<@121019458700443650>", "prev_status": "online", "game_id": "Cook, Serve, Delicious!", "games_played": [430, null, 550, 140, "Dwarf Fortress", "Tales of Zestiria", "Cook, Serve, Delicious!"], "afk_at": "2016/01/24 06:54:12", "id": "121019458700443650", "aliases": []}, "roris": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 08:10:56", "mention": "<@80876422352076800>", "prev_status": "online", "game_id": "Dragon's Dogma: Dark Arisen", "games_played": [1, null, 0, 658, 345, 724, 471, 269, 307, "Grandia 2", "Black Desert Online", "Dragon's Dogma: Dark Arisen"], "afk_at": "2016/01/24 00:50:04", "id": "80876422352076800", "aliases": []}, "projectaria": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 10:06:36", "mention": "<@48146724769763328>", "prev_status": "idle", "game_id": "Nintendo Emulator", "games_played": [1, null, "Nintendo Emulator"], "afk_at": "2016/01/24 09:13:15", "id": "48146724769763328", "aliases": []}, "moss": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 10:15:27", "mention": "<@48168872238387200>", "prev_status": "online", "games_played": [0, null, 1, 715, 127, 206, 440], "game_id": null, "afk_at": "2016/01/20 23:28:15", "id": "48168872238387200", "aliases": []}, "master of moisture": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/20 10:57:33", "mention": "<@112340697771765760>", "prev_status": "idle", "game_id": null, "games_played": [], "afk_at": "2015/12/20 10:52:58", "id": "112340697771765760", "aliases": []}, "hellsbreath:skull:": {"status": "online", "is_afk": false, "status_change_at": "2015/12/10 15:13:36", "mention": "<@78767557628133376>", "prev_status": "offline", "games_played": [], "game_id": null, "afk_at": "2015/12/10 15:13:36", "id": "78767557628133376", "aliases": []}, "hellsbreath :skull:": {"status": "online", "is_afk": false, "status_change_at": "2015/12/10 15:13:50", "mention": "<@78767557628133376>", "prev_status": "offline", "game_id": null, "games_played": [], "afk_at": "2015/12/10 15:13:50", "id": "78767557628133376", "aliases": []}, "yobi": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 10:14:51", "mention": "<@65180855919714304>", "prev_status": "online", "game_id": null, "games_played": [3, null, 680, 379, "Unity", "World of Warcraft"], "afk_at": "2016/01/24 10:14:51", "id": "65180855919714304", "aliases": []}, "salt": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 07:12:09", "mention": "<@48140539459010560>", "prev_status": "idle", "games_played": [466, 8, null, 680, 588, 15, 512, 260, "Hearthstone", "Tabletop Simulator", "Crusader Kings II"], "game_id": "Hearthstone", "afk_at": "2016/01/24 06:42:59", "id": "48140539459010560", "aliases": []}, "study": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 10:14:35", "mention": "<@121821978222002178>", "prev_status": "idle", "games_played": ["FINAL FANTASY XIV", "Rocket League", "Dragon's Dogma: Dark Arisen"], "game_id": "Dragon's Dogma: Dark Arisen", "afk_at": "2016/01/24 10:14:15", "id": "121821978222002178", "aliases": []}, "草 goshzilla 一角": {"status": "online", "is_afk": false, "status_change_at": "2016/01/17 18:31:46", "mention": "<@47934670406422528>", "prev_status": "idle", "game_id": "League of Legends", "games_played": ["League of Legends"], "afk_at": "2016/01/17 18:27:26", "id": "47934670406422528", "aliases": []}, "grey": {"status": "online", "is_afk": false, "status_change_at": "2016/01/23 03:54:03", "mention": "<@48120346410221568>", "prev_status": "offline", "games_played": [550, null, 1, 208, 283, 318, "Counter-Strike: Global Offensive", "FINAL FANTASY XIV", "Skyforge", "Dark Souls II", "Crypt of the NecroDancer", "", "Rocket League", "Dragon's Dogma: Dark Arisen"], "game_id": "Dark Souls II", "afk_at": "2016/01/20 10:14:28", "id": "48120346410221568", "aliases": []}, "hellsbreath": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 10:08:27", "mention": "<@78767557628133376>", "prev_status": "offline", "games_played": [326, null, 660, 680, 566, 441, 363, 488, 246, "The Last Remnant", "Phantasy Star Online 2", "FINAL FANTASY XI", "Rainbow Six Siege", "Tales of Zestiria", "SolForge"], "game_id": "SolForge", "afk_at": "2016/01/24 09:04:01", "id": "78767557628133376", "aliases": ["Barry", "Ben Killin", "Hellsbreath", "Barry", "Ben Killin"]}, "green": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 06:54:32", "mention": "<@63098846506397696>", "prev_status": "idle", "games_played": [4, null, 3, 11, "League of Legends"], "game_id": "League of Legends", "afk_at": "2016/01/24 06:50:07", "id": "63098846506397696", "aliases": []}, "azia": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 01:01:33", "mention": "<@121404665727418368>", "prev_status": "offline", "games_played": ["Dragon's Dogma: Dark Arisen"], "game_id": "Dragon's Dogma: Dark Arisen", "afk_at": "2016/01/23 06:32:51", "id": "121404665727418368", "aliases": []}, "scoops": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 01:44:34", "mention": "<@65211875771559936>", "prev_status": "online", "games_played": [347, null, 0, 644, 308, 15, 3, 306, 351, "Counter-Strike: Global Offensive", "Rocket League"], "game_id": null, "afk_at": "2016/01/23 19:28:16", "id": "65211875771559936", "aliases": []}, "richter": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 06:50:08", "mention": "<@49237234515181568>", "prev_status": "online", "games_played": [488, null, 183, 11], "game_id": null, "afk_at": "2016/01/24 05:30:10", "id": "49237234515181568", "aliases": []}, "cae": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 07:15:06", "mention": "<@65178683714830336>", "prev_status": "online", "game_id": null, "games_played": [335, null, 215, 112, 274, 443, "Undertale"], "afk_at": "2016/01/24 07:15:06", "id": "65178683714830336", "aliases": []}}
...\ No newline at end of file ...\ No newline at end of file
1 {"zan": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 23:39:00", "mention": "<@65178351664377856>", "prev_status": "idle", "games_played": ["If My Heart Had Wings", "World of Warcraft", null, "XCOM: Enemy Unknown", "Go! Go! Nippon! ~My First Trip to Japan~", "Dragon's Dogma: Dark Arisen"], "game_id": "Dragon's Dogma: Dark Arisen", "afk_at": "2016/01/24 23:38:52", "id": "65178351664377856", "aliases": []}, "solidsteak": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 23:56:33", "mention": "<@62955839694053376>", "prev_status": "idle", "games_played": [248, null, 310, 533, 448, 715, 1, "Insurgency", "Rainbow Six Siege"], "game_id": null, "afk_at": "2016/01/24 23:05:50", "id": "62955839694053376", "aliases": []}, "apple": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 22:57:47", "mention": "<@121822410096771072>", "prev_status": "online", "games_played": [1, 6, null, "FINAL FANTASY XIV", "Borderlands 2"], "game_id": "FINAL FANTASY XIV", "afk_at": "2016/01/24 22:57:47", "id": "121822410096771072", "aliases": []}, "sheik": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 23:09:43", "mention": "<@48148712194576384>", "prev_status": "online", "games_played": [283, null, 5, 11, 310, 249, 659, 308, 6, 260, 182, "Diablo 3", "Guild Wars 2", "Metal Gear Solid V: The Phantom Pain", "Dragon's Dogma: Dark Arisen"], "game_id": null, "afk_at": "2016/01/24 23:09:43", "id": "48148712194576384", "aliases": []}, "puncherboxer": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/04 04:11:44", "mention": "<@118544498996412416>", "prev_status": "online", "games_played": [], "game_id": null, "afk_at": "2015/12/04 03:48:11", "id": "118544498996412416"}, "rae": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 23:53:05", "mention": "<@48162082507456512>", "prev_status": "idle", "games_played": [488, null, 141, "Dark Souls II", "Black Desert Online", "Dragon's Dogma: Dark Arisen"], "game_id": "Dragon's Dogma: Dark Arisen", "afk_at": "2016/01/24 23:52:05", "id": "48162082507456512", "aliases": []}, "marion": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/03 05:14:48", "prev_status": "online", "games_played": [1, null], "game_id": null, "afk_at": "2015/12/02 08:30:16"}, "shyrith": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/03 08:10:52", "prev_status": "online", "games_played": [1, 644, null], "game_id": null, "afk_at": "2015/12/02 21:54:35"}, "hiimapirate": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/12 05:08:57", "mention": "<@133758935009198080>", "prev_status": "online", "games_played": [], "game_id": null, "afk_at": "2015/12/20 11:34:43", "id": "133758935009198080", "aliases": []}, "az": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/23 06:17:41", "mention": "<@127330097949573121>", "prev_status": "online", "games_played": [], "game_id": null, "afk_at": "2015/12/19 06:10:40", "id": "127330097949573121", "aliases": []}, "yung_thirsty": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 08:36:17", "mention": "<@136368619423531008>", "prev_status": "online", "games_played": ["League of Legends", "Amnesia: The Dark Descent", "Clicker Heroes", "Crusader Kings II"], "game_id": "League of Legends", "afk_at": "2016/01/12 07:22:37", "id": "136368619423531008", "aliases": []}, "goshzilla": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 22:31:01", "mention": "<@47934670406422528>", "prev_status": "idle", "game_id": "Monster Hunter Online", "games_played": [3, null, 6, 7, 777, "League of Legends", "Monster Hunter Online"], "afk_at": "2016/01/24 22:08:02", "id": "47934670406422528", "aliases": []}, "herbeh": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/11 10:46:35", "mention": "<@105392869782622208>", "prev_status": "online", "game_id": null, "games_played": [], "afk_at": "2016/01/11 08:46:57", "id": "105392869782622208", "aliases": []}, "eeri": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/15 06:31:49", "mention": "<@122023217371021313>", "prev_status": "online", "game_id": null, "games_played": [659, null], "afk_at": "2015/12/15 06:09:09", "id": "122023217371021313", "aliases": []}, "dick": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 22:39:52", "mention": "<@78767611436863488>", "prev_status": "online", "games_played": [372, null, 1, 488, "Dark Souls", "Metal Gear Solid V: The Phantom Pain", "Phantasy Star Online 2", "Black Desert Online"], "game_id": null, "afk_at": "2016/01/24 22:39:52", "id": "78767611436863488", "aliases": []}, "arka": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 23:44:00", "mention": "<@121466618126532608>", "prev_status": "offline", "games_played": [1, null, 313, 488, "FINAL FANTASY XIV"], "game_id": null, "afk_at": "2016/01/24 23:03:26", "id": "121466618126532608", "aliases": []}, "wriggle": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/16 19:20:41", "mention": "<@80169354666192896>", "prev_status": "online", "games_played": [], "game_id": null, "afk_at": "2015/12/02 15:37:49", "id": "80169354666192896", "aliases": []}, "tim": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/04 10:25:19", "mention": "<@109145030354030592>", "prev_status": "online", "game_id": null, "games_played": [], "afk_at": "2015/12/04 07:08:23", "id": "109145030354030592"}, "charisma": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 22:42:31", "mention": "<@65187139276513280>", "prev_status": "idle", "game_id": "Dragon's Dogma: Dark Arisen", "games_played": [313, null, 807, 471, 671, 728, 0, "Sony Playstation Emulator", "Black Desert Online", "Dragon's Dogma: Dark Arisen"], "afk_at": "2016/01/24 22:42:11", "id": "65187139276513280", "aliases": []}, "mate": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/04 09:11:30", "mention": "<@109145154044071936>", "prev_status": "online", "game_id": null, "games_played": [], "afk_at": "2015/12/04 05:06:58", "id": "109145154044071936"}, "sig": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/23 13:11:50", "mention": "<@104055037243707392>", "prev_status": "online", "games_played": [8, null, 7, 466, 588, 15, 6, 13, 165, 669, 101, "Diablo 3", "Tabletop Simulator", "DOTA 2", "Crusader Kings II"], "game_id": "DOTA 2", "afk_at": "2016/01/23 05:03:03", "id": "104055037243707392", "aliases": []}, "bunta": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 22:24:40", "mention": "<@122520378089275395>", "prev_status": "online", "game_id": null, "games_played": [488, null], "afk_at": "2016/01/24 22:24:40", "id": "122520378089275395", "aliases": []}, "mr. nelson": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/14 13:35:09", "mention": "<@103311664748707840>", "prev_status": "online", "game_id": null, "games_played": [], "afk_at": "2015/12/14 10:25:27", "id": "103311664748707840", "aliases": []}, "草 goshzilla": {"status": "online", "is_afk": false, "status_change_at": "2016/01/15 15:28:19", "mention": "<@47934670406422528>", "prev_status": "offline", "game_id": null, "games_played": [], "afk_at": "2016/01/15 08:23:14", "id": "47934670406422528", "aliases": []}, "skeletonhorn": {"status": "online", "is_afk": false, "status_change_at": "2015/12/03 00:36:39", "prev_status": "offline", "games_played": [], "game_id": null, "afk_at": "2015/12/03 00:36:39"}, "yoltan": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/08 23:38:09", "mention": "<@122369674808786948>", "prev_status": "online", "games_played": [238, null, 307], "game_id": null, "afk_at": "2015/12/04 16:14:00", "id": "122369674808786948", "aliases": []}, "rui": {"status": "offline", "is_afk": false, "status_change_at": "2016/01/24 23:35:21", "mention": "<@63649222993391616>", "prev_status": "online", "games_played": [174, null, 660, 724, 488, 149, 780, 301, 438, 140, 680, "Grand Theft Auto V", "Dragon's Dogma: Dark Arisen"], "game_id": "Grand Theft Auto V", "afk_at": "2016/01/24 23:17:25", "id": "63649222993391616", "aliases": []}, "adol": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 15:58:19", "mention": "<@122079633796497409>", "prev_status": "idle", "games_played": [550, null, 1, "Black Desert Online", "Clicker Heroes"], "game_id": "Clicker Heroes", "afk_at": "2016/01/24 15:57:49", "id": "122079633796497409", "aliases": []}, "xorfos": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 22:35:29", "mention": "<@121019458700443650>", "prev_status": "online", "game_id": null, "games_played": [430, null, 550, 140, "Dwarf Fortress", "Tales of Zestiria", "Cook, Serve, Delicious!"], "afk_at": "2016/01/24 22:35:29", "id": "121019458700443650", "aliases": []}, "roris": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 22:58:35", "mention": "<@80876422352076800>", "prev_status": "online", "game_id": "Dragon's Dogma: Dark Arisen", "games_played": [1, null, 0, 658, 345, 724, 471, 269, 307, "Grandia 2", "Black Desert Online", "Dragon's Dogma: Dark Arisen"], "afk_at": "2016/01/24 22:58:35", "id": "80876422352076800", "aliases": []}, "projectaria": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 20:40:15", "mention": "<@48146724769763328>", "prev_status": "online", "game_id": null, "games_played": [1, null, "Nintendo Emulator"], "afk_at": "2016/01/24 20:40:15", "id": "48146724769763328", "aliases": []}, "moss": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 22:43:58", "mention": "<@48168872238387200>", "prev_status": "idle", "games_played": [0, null, 1, 715, 127, 206, 440], "game_id": null, "afk_at": "2016/01/24 22:35:08", "id": "48168872238387200", "aliases": []}, "master of moisture": {"status": "offline", "is_afk": false, "status_change_at": "2015/12/20 10:57:33", "mention": "<@112340697771765760>", "prev_status": "idle", "game_id": null, "games_played": [], "afk_at": "2015/12/20 10:52:58", "id": "112340697771765760", "aliases": []}, "hellsbreath:skull:": {"status": "online", "is_afk": false, "status_change_at": "2015/12/10 15:13:36", "mention": "<@78767557628133376>", "prev_status": "offline", "games_played": [], "game_id": null, "afk_at": "2015/12/10 15:13:36", "id": "78767557628133376", "aliases": []}, "hellsbreath :skull:": {"status": "online", "is_afk": false, "status_change_at": "2015/12/10 15:13:50", "mention": "<@78767557628133376>", "prev_status": "offline", "game_id": null, "games_played": [], "afk_at": "2015/12/10 15:13:50", "id": "78767557628133376", "aliases": []}, "yobi": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 20:05:45", "mention": "<@65180855919714304>", "prev_status": "idle", "games_played": [3, null, 680, 379, "Unity", "World of Warcraft"], "game_id": null, "afk_at": "2016/01/24 19:55:05", "id": "65180855919714304", "aliases": []}, "salt": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 21:52:01", "mention": "<@48140539459010560>", "prev_status": "offline", "game_id": null, "games_played": [466, 8, null, 680, 588, 15, 512, 260, "Hearthstone", "Tabletop Simulator", "Crusader Kings II"], "afk_at": "2016/01/24 11:15:21", "id": "48140539459010560", "aliases": []}, "study": {"status": "online", "mention": "<@121821978222002178>", "is_afk": false, "games_played": ["FINAL FANTASY XIV", "Rocket League", "Dragon's Dogma: Dark Arisen", null], "game_id": "Dragon's Dogma: Dark Arisen", "afk_at": "2016/01/24 10:24:35", "status_change_at": "2016/01/24 23:41:56", "id": "121821978222002178", "prev_status": "offline", "aliases": []}, "草 goshzilla 一角": {"status": "online", "is_afk": false, "status_change_at": "2016/01/17 18:31:46", "mention": "<@47934670406422528>", "prev_status": "idle", "game_id": "League of Legends", "games_played": ["League of Legends"], "afk_at": "2016/01/17 18:27:26", "id": "47934670406422528", "aliases": []}, "grey": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 19:25:55", "mention": "<@48120346410221568>", "prev_status": "offline", "games_played": [550, null, 1, 208, 283, 318, "Counter-Strike: Global Offensive", "FINAL FANTASY XIV", "Skyforge", "Dark Souls II", "Crypt of the NecroDancer", "", "Rocket League", "Dragon's Dogma: Dark Arisen"], "game_id": "Dragon's Dogma: Dark Arisen", "afk_at": "2016/01/24 15:28:16", "id": "48120346410221568", "aliases": []}, "hellsbreath": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 23:32:44", "mention": "<@78767557628133376>", "prev_status": "offline", "games_played": [326, null, 660, 680, 566, 441, 363, 488, 246, "The Last Remnant", "Phantasy Star Online 2", "FINAL FANTASY XI", "Rainbow Six Siege", "Tales of Zestiria", "SolForge", "Fallout 4", "Wolfenstein.The.New.Order", "King's Quest"], "game_id": null, "afk_at": "2016/01/24 19:58:40", "id": "78767557628133376", "aliases": ["Barry", "Ben Killin", "Hellsbreath", "Barry", "Ben Killin"]}, "green": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 23:04:39", "mention": "<@63098846506397696>", "prev_status": "offline", "game_id": null, "games_played": [4, null, 3, 11, "League of Legends"], "afk_at": "2016/01/24 06:50:07", "id": "63098846506397696", "aliases": []}, "azia": {"status": "idle", "is_afk": true, "status_change_at": "2016/01/24 18:56:35", "mention": "<@121404665727418368>", "prev_status": "online", "games_played": ["Dragon's Dogma: Dark Arisen", null], "game_id": null, "afk_at": "2016/01/24 18:56:35", "id": "121404665727418368", "aliases": []}, "scoops": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 18:58:15", "mention": "<@65211875771559936>", "prev_status": "offline", "games_played": [347, null, 0, 644, 308, 15, 3, 306, 351, "Counter-Strike: Global Offensive", "Rocket League"], "game_id": null, "afk_at": "2016/01/23 19:28:16", "id": "65211875771559936", "aliases": []}, "richter": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 22:41:52", "mention": "<@49237234515181568>", "prev_status": "idle", "game_id": null, "games_played": [488, null, 183, 11], "afk_at": "2016/01/24 22:36:41", "id": "49237234515181568", "aliases": []}, "cae": {"status": "online", "is_afk": false, "status_change_at": "2016/01/24 21:27:13", "mention": "<@65178683714830336>", "prev_status": "idle", "games_played": [335, null, 215, 112, 274, 443, "Undertale"], "game_id": null, "afk_at": "2016/01/24 21:13:13", "id": "65178683714830336", "aliases": []}}
...\ No newline at end of file ...\ No newline at end of file
......