2022-03-24 13:14:24 +01:00

92 lines
3.7 KiB
Python

import logging
import requests
from collections import namedtuple
from datetime import datetime, timedelta
class DaisyHandler:
def __init__(self, config):
self.auth = (config['daisy']['user'],
config['daisy']['password'])
self.headers = {'Accept': 'application/json'}
self.url = config['daisy']['url'].rstrip('/')
self.logger = logging.getLogger('play-daemon')
def _get(self, path, params={}):
r = requests.get(f'{self.url}{path}',
params,
headers=self.headers,
auth=self.auth)
r.raise_for_status()
return r.json()
def get_booking(self, start_time, end_time, room):
fmt = '%Y-%m-%d'
start_day = start_time.strftime(fmt)
end_day = (end_time + timedelta(days=1)).strftime(fmt)
params = {'start': start_day,
'end': end_day,
'room': room}
bookings = self._get('/schedule', params=params)
# Resolve all the numeric IDs in a booking:
for booking in bookings:
courses = []
for course in booking['courseSegmentInstances']:
courses.append(self.get_course(course['id']))
booking['courseSegmentInstances'] = sorted(courses)
teachers = []
for teacher in booking['teachers']:
teachers.append(self.get_person(teacher['id']))
booking['teachers'] = sorted(teachers)
if booking['bookedBy']:
booking['bookedBy'] = self.get_person(booking['bookedBy'])
def booking_sort(booking):
if booking['courseSegmentInstances']:
return booking['courseSegmentInstances'][0]
return ''
Fit = namedtuple('Fit', ['booking', 'overlap'])
best = Fit(None, timedelta())
self.logger.debug('Matching bookings for room %s at %s - %s',
room, start_time, end_time)
for booking in sorted(bookings, key=booking_sort):
b_start = datetime.fromtimestamp(int(booking['start'] / 1000))
b_end = datetime.fromtimestamp(int(booking['end'] / 1000))
self.logger.debug('Booking %s for course %s: %s - %s',
booking['id'], booking['courseSegmentInstances'],
b_start, b_end)
range_start = max(start_time, b_start)
range_end = min(end_time, b_end)
overlap = range_end - range_start
self.logger.debug('Time ranges overlap by %s', overlap)
self.logger.debug('Previous best overlap: %s', best.overlap)
if overlap > best.overlap:
self.logger.debug('Saving %s as current best fit',
booking['id'])
best = Fit(booking, overlap)
self.logger.debug('Best booking fit was %s for course %s, overlap %s',
best.booking['id'],
best.booking['courseSegmentInstances'],
best.overlap)
return best.booking
def get_person(self, person_id):
usernames = [name['username']
for name in self._get(f'/person/{person_id}/usernames')
if name['realm'] == 'SU.SE']
if len(usernames) != 1:
raise Exception(f'More than one SU.SE username: {usernames}')
return usernames[0]
def get_course(self, course_id):
course = self._get(f'/courseSegment/{course_id}')
return course['designation']
def get_room_name(self, room_id):
location = self._get(f'/location/{room_id}')
return location['designation']