-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmanager.py
259 lines (217 loc) · 9.08 KB
/
manager.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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#!/usr/bin/python
import datetime
import time
from voglogger import logger
from authorized import whoIs
import pymongo
# establish connection to mongodb server
try:
connection = pymongo.MongoClient('monty', 27017)
logger.info('Successfully connected to MongoDB daemon')
except pymongo.errors.ConnectionFailure as e:
logger.error('Failed to connect to MongoDB: %s' % e)
logger.error('VOGLBot exiting!')
sys.exit(1)
db = connection['voglbot']
students = db['students']
### helper functions ###
def houseIsValid(house):
houses = {
'green': True,
'black': True,
'purple': True,
'blue': True,
'red': True,
'orange': True,
'all': True,
}
return houses.get(house, False)
def statusIsValid(status):
statuses = {
'present': True,
'absent': True,
'total': True,
}
return statuses.get(status, False)
def fieldIsValid(field):
fields = {
'name': True,
'type': True,
'color': True,
'house': True,
'status': True,
'statuslog': True,
'diet': True,
'medical': True,
'addedby': True,
}
return fields.get(field, False)
def enumerator(cursor, fields):
reply = ''
# catch size 0 cursor
if cursor.count() == 0:
return 'No records found.'
i = 1
for person in cursor:
reply += str(i) + '.\n'
for field in fields:
if field == 'house':
reply += '%s: %s\n' % (field.title(), person[field][0].title())
elif field == 'diet' or field == 'medical':
reply += '%s: %s\n' % (field.title(), person[field])
else:
reply += '%s: %s\n' % (field.title(), person[field].title())
i += 1
reply += '\n'
return reply
def makeTimestamp():
return datetime.datetime.fromtimestamp(time.time()).strftime('%I:%M%p, %d %B')
### executive functions ###
def add(house, name, requester):
if houseIsValid(house):
# check for duplicate name
if students.find( {'name': name, 'house': house }).count() != 0:
logger.warn('%s: /add failed due to duplicate entry' % (whoIs(requester)))
return 'There is already someone with that name and house in the database. /add failed.'
timestamp = str(datetime.datetime.now())
logger.info('%s: Adding \'%s\' from \'%s\'' % (whoIs(requester), name, house))
student = {
'name': name,
'type': 'freshman',
'color': house,
'house': [house, 'all'],
'status': 'present',
'statuslog': ['Initial Registration @ ' + makeTimestamp()],
'diet': 'NIL',
'medical': 'NIL',
'addedby': whoIs(requester)
}
students.insert_one(student)
logger.info('%s: Added \'%s\' to \'%s\' house' % (whoIs(requester), name, house))
return 'Successfully added \'%s\' of \'%s\' house into database.' % (name, house)
logger.info('%s: /add query failed (invalid parameters)' % whoIs(requester))
return 'Invalid house name. See \'/help add\''
def remove(house, name, requester):
reply = 'Removed \'%s\' of \'%s\' house from database.' % (name, house)
# perform remove
if students.find( {'name': name, 'house': house }).count() == 0:
return 'No such record found.'
elif students.find( {'name': name, 'house': house }).count() == 1:
students.remove( {'name': name, 'house': house}, 1 )
logger.info(whoIs(requester) + ': ' + reply)
return reply
return 'Multiple records with the same name and house found. Contact Darren for removal.'
def getStrength(house, status, requester):
reply = ''
if houseIsValid(house) and statusIsValid(status):
# get total house strength (status-independent)
house_strength = students.count( {'house': house} )
# get modal house strength (status-dependent) and build reply
if status in ['present', 'absent']:
status_strength = students.count( {'house': house, 'status': status} )
reply += 'Strength for \'%s\' in \'%s\': %d/%d' % (status, house, status_strength, house_strength)
else:
reply += 'Total strength for \'%s\' house is %d' % (house, house_strength)
else:
# catch shitty parameters
logger.info('%s: /strength query failed (invalid parameters)' % whoIs(requester))
return 'Invalid house or status. See \'/help strength\''
logger.info('%s: Returning strength for \'%s\' house' % (whoIs(requester), house))
return reply
def getEnumerate(house, requester):
if houseIsValid(house):
# cover the all case and single house case
if house == 'all':
houses = ['black', 'blue', 'green', 'orange', 'purple', 'red']
else:
houses = [house]
reply = ''
for target_house in houses:
reply += '=====================\n'
reply += target_house.upper() + '\n\n'
for status in ['present','absent']:
# query for database cursor
results = students.find( {'house': target_house, 'status': status} )
# sort results
results.sort( [ ('color', 1), ('name', 1) ] )
reply += status.title() + '\n'
# catch empty house/mode query
if results.count() == 0:
reply += 'No records found.\n'
else:
# build the reply message
i = 1
for person in results:
reply += '%d. %-15s' % (i, person['name'].title())
i += 1
if (i+1)%2 == 0:
reply += '\n'
reply += '\n'
else:
# catch invalid parameters
logger.info('%s: /enum query failed (invalid parameters)' % whoIs(requester))
return 'Invalid house or status. See \'/help enumerate\''
logger.info('%s: Returning enumeration for \'%s\' in \'%s\'' % (whoIs(requester), status, house))
return reply
def find(house, pattern, verbose, requester):
reply = ''
if houseIsValid(house):
# query for database cursor
results = students.find( {'name': { '$regex': '.*' + pattern + '.*'}, 'house': house } )
# sort results
results.sort( [ ('color', -1), ('name', 1) ] )
# what info to send back (determined by verbose flag)
if verbose is True:
details = ['name', 'house', 'status', 'diet', 'medical', 'addedby']
else:
details = ['name', 'house', 'status']
# build the reply
reply += 'Finding any names containing \'%s\' for \'%s\'\n\n' % (pattern, house)
reply += enumerator(results, details)
else:
# catch shitty parameters
logger.info('%s: /find query failed (invalid parameters)' % whoIs(requester))
return 'Invalid house. See \'/help find\''
logger.info('%s: Returning find query for pattern \'%s\' for \'%s\'' % (whoIs(requester), pattern, house))
return reply
def updater(house, name, field, content, requester):
reply = 'Updating \'%s\' for \'%s\' in \'%s\' house.\n\n' % (field, name, house)
if houseIsValid(house):
# check if result was found
if students.find_one( {'name': name, 'house':house} ) == None:
# no results
reply += 'Could not find \'%s\' from \'%s\' house.' % (name, house)
else:
# got results
if fieldIsValid(field) and field != 'house':
logger.info('%s: Updating \'%s\' for \'%s\' in \'%s\' with: \'%s\'' % (whoIs(requester), field, name, house, content))
students.update_one( {'name': name, 'house': house}, { '$set': { field: content } } ) # perform update
reply += 'Successfully updated \'%s\' field for \'%s\' in \'%s\' with: \'%s\'' % (field, name, house, content)
else:
reply += 'Invalid field.'
return reply
def updateAttendanceLog(house, name, isIn, requester):
if houseIsValid(house):
if isIn == True:
entry = 'In @ %s' % makeTimestamp()
else:
entry = 'Out @ %s' % makeTimestamp()
students.update_one( {'name': name, 'house': house}, { '$push': {'statuslog': entry} } )
logger.info('%s: Appended status log entry to \'%s\' from \'%s\'' % (whoIs(requester), name.title(), house.title()))
def getAttendanceLog(house, name, requester):
reply = ''
if houseIsValid(house):
if students.find_one( {'name': name, 'house': house} ) == None:
# no results
reply += 'Could not find \'%s\' from \'%s\' house.' % (name, house)
else:
# got results
result = students.find_one( {'name': name, 'house': house} )
reply += 'Attendance for: %s (%s)\n\n' % (name, house)
i = 1
for entry in result['statuslog']:
reply += '%d. %s\n' % (i, entry)
i += 1
else:
reply += 'House not valid.'
return reply