def handle(self, *args, **options): self._commit = options['commit'] self._courses = {} self._session = SessionManagement() self._recorder = RemoteRecorderManagement() if options['stdin']: for line in sys.stdin: self._process_course(line.rstrip('\n')) else: for session in args: self._process_course(session)
class SessionRecordingTime(RESTDispatch): def __init__(self): self._recorder_api = RemoteRecorderManagement() self._audit_log = logging.getLogger('audit') def GET(self, request, **kwargs): session_id = kwargs.get('session_id') if session_id: raw_session = self._session_api.getSessionsById([session_id])[0][0] start_utc = raw_session.StartTime.astimezone(pytz.utc) end_utc = start_utc + datetime.timedelta( seconds=int(raw_session.Duration)) recording_time = { 'start': start_utc.isoformat(), 'end': end_utc.isoformat() } else: recording_time = {} return self.json_response(recording_time) def PUT(self, request, **kwargs): try: session_id = kwargs.get('session_id') data = json.loads(request.body) start_time = self._valid_time(data.get("start", "").strip()) end_time = self._valid_time(data.get("end", "").strip()) self._recorder_api.updateRecordingTime( session_id, start_time, end_time) self._audit_log.info('%s set %s start/stop to %s and %s' % ( request.user, session_id, start_time, end_time)) return self.json_response({ 'recording_id': session_id }) except InvalidParamException as ex: return self.error_response(400, "%s" % ex) except Exception as ex: return self.error_response(500, "Unable to save session: %s" % ex) def _valid_time(self, time): if time and len(time): return time raise InvalidParamException('bad time value')
def handle(self, *args, **options): self._commit = options['commit'] self._courses = {} self._session = SessionManagement() self._recorder = RemoteRecorderManagement() if options['stdin']: for line in sys.stdin: self._process_course(line.rstrip('\n')) else: for session in args: self._process_course(session)
class Command(BaseCommand): help = "Matchrecording session dates to SWS meeting times" option_list = BaseCommand.option_list + ( make_option('--commit', dest='commit', action="store_true", default=False, help='Update Panopto recording with SWS meeting time'), make_option('--stdin', dest='stdin', action="store_true", default=False, help='get Panopto session external ids on standard input'), ) def handle(self, *args, **options): self._commit = options['commit'] self._courses = {} self._session = SessionManagement() self._recorder = RemoteRecorderManagement() if options['stdin']: for line in sys.stdin: self._process_course(line.rstrip('\n')) else: for session in args: self._process_course(session) def _process_course(self, session_id): # 2015-spring-PSYCH-202-A-2015-06-04 course = re.match( r'^(20[0-9]{2})-(winter|spring|summer|autumn)' r'-([A-Z ]+)-([0-9]{3})-([A-Z][A-Z0-9]*)-2*', session_id) if course: label = "%s,%s,%s,%s/%s" % (course.group(1), course.group(2), course.group(3), course.group(4), course.group(5)) if label not in self._courses: now = datetime.datetime.now(tz.tzlocal()).replace( second=0, microsecond=0) section = get_section_by_label( label, include_instructor_not_on_time_schedule=False) (start, end) = self._lecture_times(section) self._courses[label] = { 'start': start.split(':'), 'end': end.split(':') } offered = self._courses[label] else: print >> sys.stderr, "unrecognized session id: %s" % session_id return pan_session = self._session.getSessionsByExternalId([session_id]) if 'Session' in pan_session and len(pan_session.Session) == 1: # broken-ass suds. fsuds = re.match(r'.*\<a\:StartTime\>([^<]+)\<\/a\:StartTime\>.*', self._session._api.last_received().plain()) if not fsuds: Exception('Untrustable time') pan_start = parser.parse(fsuds.group(1)) pan_start_local = pan_start.astimezone(tz.tzlocal()) sws_start_local = pan_start_local.replace( hour=int(offered['start'][0]), minute=int(offered['start'][1])) sws_end_local = pan_start_local.replace( hour=int(offered['end'][0]), minute=int(offered['end'][1])) schedule_delta = sws_start_local - pan_start_local duration_delta = (sws_end_local - sws_start_local).seconds - int( pan_session.Session[0].Duration) if schedule_delta or duration_delta: pan_start = (pan_start_local + schedule_delta).astimezone( tz.tzutc()) duration = pan_session.Session[0].Duration if duration_delta: duration += duration_delta pan_end = pan_start + datetime.timedelta(0, duration) adjustment = [ session_id, '(%s)' % pan_session.Session[0].Id, '' if self._commit else 'WOULD', 'RESCHEDULE', fsuds.group(1), 'TO', pan_start.isoformat(), ':' ] if schedule_delta.days < 0: adjustment.append("(-%s shift)" % (datetime.timedelta() - schedule_delta)) else: adjustment.append("(%s shift)" % schedule_delta) if duration_delta: adjustment.append('AND DURATION') adjustment.append("%s" % duration_delta) adjustment.append('seconds') print >> sys.stderr, ' '.join(adjustment) if self._commit: result = self._recorder.updateRecordingTime( pan_session.Session[0].Id, pan_start.isoformat(), pan_end.isoformat()) if not result: print >> sys.stderr, "FAIL: null return value" elif result.ConflictsExist: print >> sys.stderr, "CONFLICT: %s" % ( result.ConflictingSessions[0][0].SessionName) else: print >> sys.stderr, "UPDATED %s" % ( result.SessionIDs[0][0]) else: print >> sys.stderr, "%s: UNCHANGED" % (session_id) else: print >> sys.stderr, "unrecognized session id: %s" % session_id def _lecture_times(self, section): for meeting in section.meetings: if (meeting.meeting_type in ['lecture', 'quiz', 'seminar'] and meeting.start_time and meeting.end_time): return meeting.start_time, meeting.end_time Exception("no lecture times set")
def __init__(self): self._recorder_api = RemoteRecorderManagement() self._audit_log = logging.getLogger('audit')
def __init__(self): self._session_api = SessionManagement() self._recorder_api = RemoteRecorderManagement() self._access_api = AccessManagement() self._user_api = UserManagement() self._audit_log = logging.getLogger('audit')
class Session(RESTDispatch): def __init__(self): self._session_api = SessionManagement() self._recorder_api = RemoteRecorderManagement() self._access_api = AccessManagement() self._user_api = UserManagement() self._audit_log = logging.getLogger('audit') def GET(self, request, **kwargs): session_id = kwargs.get('session_id') if session_id: raw_session = self._session_api.getSessionsById( [session_id])[0][0] raw_access = self._access_api.getSessionAccessDetails( session_id) start_utc = pytz.utc.localize( raw_session['StartTime']).astimezone(tz.tzutc()) session = { 'creator_id': raw_session['CreatorId'], 'description': raw_session['Description'], 'duration': raw_session['Duration'], 'external_id': raw_session['ExternalId'], 'folder_id': raw_session['FolderId'], 'folder_name': raw_session['FolderName'], 'folder_creators': [], 'id': raw_session['Id'], 'is_video_url': raw_session['IosVideoUrl'], 'is_broadcast': raw_session['IsBroadcast'], 'is_public': raw_access['IsPublic'], 'is_downloadable': raw_session['IsDownloadable'], 'name': raw_session['Name'], 'remote_recorder_ids': raw_session['RemoteRecorderIds'].get( 'guid', None), 'share_page_url': raw_session['SharePageUrl'], 'start_time': start_utc.isoformat(), 'state': raw_session['State'], 'status_message': raw_session['StatusMessage'], 'thumb_url': raw_session['ThumbUrl'], 'viewer_url': raw_session['ViewerUrl'], } else: session = {} return self.json_response(session) def POST(self, request, **kwargs): try: new_session = self._validate_session(request.body) session = self._recorder_api.scheduleRecording(new_session.get('name'), new_session.get('folder_id'), new_session.get('is_broadcast'), new_session.get('start_time'), new_session.get('end_time'), new_session.get('recorder_id')) if session.ConflictsExist: conflict = session.ConflictingSessions[0][0] start_time = conflict.StartTime end_time = conflict.EndTime content = { 'conflict_name': conflict.SessionName, 'conflict_start': start_time.isoformat(), 'conflict_end': end_time.isoformat() } return self.error_response(409, "Schedule Conflict Exists", content=content) session_id = session.SessionIDs[0][0] self._session_api.updateSessionExternalId( session_id, new_session.get('external_id')) if new_session.get('is_public'): self._access_api.updateSessionIsPublic(session_id, True) messages = [] creators = new_session.get('folder_creators') if creators and type(creators) is list: messages = self._sync_creators( new_session.get('folder_id'), creators) self._audit_log.info('%s scheduled %s for %s from %s to %s' % ( request.user, new_session.get('external_id'), new_session.get('uwnetid'), new_session.get('start_time'), new_session.get('end_time'))) return self.json_response({ 'recording_id': session_id, 'messages': messages }) except InvalidParamException as ex: return self.error_response(400, "%s" % ex) except Exception as ex: return self.error_response(500, "Unable to save session: %s" % ex) def PUT(self, request, **kwargs): try: session_update = self._validate_session(request.body) session = self._session_api.getSessionsById( session_update.get('recording_id'))[0][0] start_utc = session.StartTime.astimezone(pytz.utc) end_utc = start_utc + datetime.timedelta( seconds=int(session.Duration)) session_update_start = self._valid_time(session_update.get('start_time')) session_update_end = self._valid_time(session_update.get('end_time')) if not (start_utc.isoformat() == session_update_start and end_utc.isoformat() == session_update_end): self._recorder_api.updateRecordingTime( session.Id, session_update_start, session_update_end) access = self._access_api.getSessionAccessDetails(session.Id) if access.IsPublic != session_update.get('is_public'): self._access_api.updateSessionIsPublic( session.Id, session_update.get('is_public')) if session.IsBroadcast != session_update.get('is_broadcast'): self._session_api.updateSessionIsBroadcast( session.Id, session_update.get('is_broadcast')) folder_name = session_update.get('folder_name') if session.FolderName != folder_name: self._session_api.moveSessions( [session.Id], session_update.get('folder_id')) messages = [] creators = session_update.get('folder_creators') if creators and type(creators) is list: messages = self._sync_creators( session_update.get('folder_id'), creators) self._audit_log.info('%s modified %s for %s from %s to %s in %s' % ( request.user, session_update.get('external_id'), session_update.get('uwnetid'), session_update.get('start_time'), session_update.get('end_time'), session_update.get('folder_name'))) return self.json_response({ 'recording_id': session.Id, 'messages': messages }) except InvalidParamException as ex: return self.error_response(400, "%s" % ex) except Exception as ex: return self.error_response(500, "Unable to save session: %s" % ex) def DELETE(self, request, **kwargs): try: session_id = self._valid_recorder_id(kwargs.get('session_id')) # do not permit param tampering key = course_event_key(request.GET.get('uwnetid', ''), request.GET.get('name', ''), request.GET.get('eid', ''), request.GET.get('rid', '')) if key != request.GET.get("key", None): raise InvalidParamException('Invalid Client Key') self._session_api.deleteSessions([session_id]) self._audit_log.info('%s deleted session %s' % (request.user, session_id)) return self.json_response({ 'deleted_recording_id': session_id }) except InvalidParamException as err: return self.error_response(400, "Invalid Parameter: %s" % err) def _valid_folder(self, name, external_id): try: folder_id = Validation().panopto_id(external_id) return folder_id except InvalidParamException: pass try: if external_id and len(external_id): folders = self._session_api.getAllFoldersByExternalId( [external_id]) if folders and len(folders) == 1 and len(folders[0]): return folders[0][0].Id folders = self._session_api.getFoldersList(search_query=name) if folders and len(folders): for folder in folders: if folder.Name == name: folder_id = folder.Id if external_id and len(external_id): self._session_api.updateFolderExternalId( folder_id, external_id) return folder_id new_folder = self._session_api.addFolder(name) if not new_folder: raise InvalidParamException('Cannot add folder: %s' % name) new_folder_id = new_folder.Id if external_id and len(external_id): self._session_api.updateFolderExternalId( new_folder_id, external_id) return new_folder_id except Exception as ex: raise InvalidParamException('Cannot add folder: %s' % ex) def _validate_session(self, request_body): session = {} data = json.loads(request_body) session['recording_id'] = data.get("recording_id", "") session['uwnetid'] = data.get("uwnetid", "") session['name'] = self._valid_recording_name(data.get("name", "").strip()) session['external_id'] = self._valid_external_id( data.get("external_id", "").strip()) session['recorder_id'] = self._valid_recorder_id( data.get("recorder_id", "").strip()) session['folder_external_id'] = data.get( "folder_external_id", "").strip() session['session_id'] = data.get("session_id", "").strip() if len(session['session_id']): self._valid_external_id(session['session_id']) # do not permit param tamperings key = course_event_key(session['uwnetid'], session['name'], session['external_id'], session['recorder_id']) if key != data.get("key", ''): raise InvalidParamException('Invalid Client Key') session['is_broadcast'] = self._valid_boolean(data.get("is_broadcast", False)) session['is_public'] = self._valid_boolean(data.get("is_public", False)) session['start_time'] = self._valid_time(data.get("start_time", "").strip()) session['end_time'] = self._valid_time(data.get("end_time", "").strip()) session['folder_name'] = data.get("folder_name", "").strip() session['folder_id'] = self._valid_folder(session['folder_name'], session['folder_external_id']) session['folder_creators'] = data.get("creators", None) return session def _valid_external_id(self, external_id): if external_id and len(external_id): return external_id raise InvalidParamException('bad external_id') def _valid_recorder_id(self, recorder_id): if (recorder_id): return Validation().panopto_id(recorder_id) raise InvalidParamException('missing recorder id') def _valid_recording_name(self, name): if name and len(name): return name raise InvalidParamException('bad recording name') def _valid_boolean(self, is_broadcast): if not (is_broadcast is None or type(is_broadcast) == bool): raise InvalidParamException('bad broadcast flag') return is_broadcast def _valid_time(self, time): if time and len(time): return time raise InvalidParamException('bad time value') def _sync_creators(self, folder_id, folder_creators): messages = [] new_creator_ids = [] deleted_creator_ids = [] current_creators = get_panopto_folder_creators(folder_id) for creator in folder_creators: if creator not in current_creators: try: new_creator_ids.append(self._get_panopto_user_id(creator)) except PanoptoUserException as ex: messages.append('Invalid UWNetId %s' % creator) for creator in current_creators: if creator not in folder_creators: try: deleted_creator_ids.append(self._get_panopto_user_id(creator)) except PanoptoUserException as ex: messages.append('Invalid UWNetId %s' % creator) if len(new_creator_ids): try: self._access_api.grantUsersAccessToFolder( folder_id, new_creator_ids, 'Creator') except PanoptoAPIException as ex: match = re.match(r'.*Server raised fault: \'(.+)\'$', str(ex)) messages.append('%s: %s' % (creator, match.group(1) if match else str(ex))) if len(deleted_creator_ids): try: self._access_api.revokeUsersAccessFromFolder( folder_id, deleted_creator_ids, 'Creator') except PanoptoAPIException as ex: match = re.match(r'.*Server raised fault: \'(.+)\'$', str(ex)) messages.append('%s: %s' % (creator, match.group(1) if match else str(ex))) return messages def _get_panopto_user_id(self, netid): key = "%s\%s" % (settings.PANOPTO_API_APP_ID, netid) user = self._user_api.getUserByKey(key) if not user or user['UserId'] == '00000000-0000-0000-0000-000000000000': raise PanoptoUserException('Unprovisioned UWNetId: %s' % (netid)) return user['UserId']
def __init__(self): self._api = RemoteRecorderManagement() # timeout in hours self._space_list_cache_timeout = 1
class Recorder(RESTDispatch): def __init__(self): self._api = RemoteRecorderManagement() # timeout in hours self._space_list_cache_timeout = 1 def GET(self, request, **kwargs): recorder_id = kwargs.get('recorder_id') if request.GET.get('timeout'): self._space_list_cache_timeout = float(request.GET.get('timeout')) if (recorder_id): return self._get_recorder_details(recorder_id) else: return self._list_recorders() def PUT(self, request, **kwargs): recorder_id = kwargs.get('recorder_id') try: Validation().panopto_id(recorder_id) data = json.loads(request.body) external_id = data.get('external_id', None) if external_id is not None: rv = self._api.updateRemoteRecorderExternalId( recorder_id, external_id) try: cache_entry = RecorderCacheEntry.objects.get( recorder_id=recorder_id) cache_entry.recorder_external_id = external_id cache_entry.save() except RecorderCacheEntry.DoesNotExist: pass return self._get_recorder_details(recorder_id) except (MissingParamException, InvalidParamException, PanoptoAPIException) as err: return self.error_response(400, message="%s" % err) def _get_recorder_details(self, recorder_id): try: recorders = get_api_recorder_details(self._api, recorder_id) except (RecorderException, PanoptoAPIException, MissingParamException, InvalidParamException) as err: return self.error_response(400, message="%s" % err) if recorders is None: return self.error_response(404, message="No Recorder Found") return self._recorder_rep(recorders) def _recorder_rep(self, recorders): reps = [] for recorder in recorders: rep = { 'id': recorder.Id, 'external_id': recorder.ExternalId, 'name': recorder.Name, 'settings_url': recorder.SettingsUrl, 'state': recorder.State, 'space': None, 'scheduled_recordings': [] } if recorder.ScheduledRecordings and hasattr( recorder.ScheduledRecordings, 'guid'): for recording in recorder.ScheduledRecordings.guid: rep['scheduled_recordings'].append(recording) if recorder.ExternalId: try: space = get_space_by_id(recorders[0].ExternalId) rep['space'] = { 'space_id': space.space_id, 'name': space.name, 'formal_name': space.formal_name } except DataFailureException as err: logger.error('Cannot get space for id: %s: %s' % (recorders[0].ExternalId, err)) reps.append(rep) return self.json_response(reps) def _list_recorders(self): try: rec_cache = RecorderCache.objects.all()[0] now = pytz.UTC.localize(datetime.datetime.now()) timeout = datetime.timedelta(hours=self._space_list_cache_timeout) if (now - timeout) > rec_cache.created_date: self._scrub_recorder_cache(rec_cache) except (IndexError, RecorderCache.DoesNotExist): try: recorders = self._api.listRecorders() rec_cache = self._cache_recorders(recorders) except PanoptoAPIException as err: return self.error_response(400, message="%s" % err) rep = [] for recorder in RecorderCacheEntry.objects.filter(cache=rec_cache): rep.append({ 'id': recorder.recorder_id, 'external_id': recorder.recorder_external_id, 'name': recorder.name, 'scheduled_recordings': [] }) return self.json_response(rep) def _cache_recorders(self, recorders): rec_cache = RecorderCache() rec_cache.save() for recorder in recorders: RecorderCacheEntry.objects.create( cache=rec_cache, recorder_id=recorder.Id, recorder_external_id=recorder.ExternalId or '', name=recorder.Name) return rec_cache def _scrub_recorder_cache(self, rec_cache): RecorderCacheEntry.objects.filter(cache=rec_cache).delete() rec_cache.delete() raise RecorderCache.DoesNotExist()
def __init__(self): self._api = RemoteRecorderManagement() # timeout in hours self._space_list_cache_timeout = 1
class Recorder(RESTDispatch): def __init__(self): self._api = RemoteRecorderManagement() # timeout in hours self._space_list_cache_timeout = 1 def GET(self, request, **kwargs): recorder_id = kwargs.get('recorder_id') if request.GET.get('timeout'): self._space_list_cache_timeout = float(request.GET.get('timeout')) if (recorder_id): return self._get_recorder_details(recorder_id) else: return self._list_recorders() def PUT(self, request, **kwargs): recorder_id = kwargs.get('recorder_id') try: Validation().panopto_id(recorder_id) data = json.loads(request.body) external_id = data.get('external_id', None) if external_id is not None: rv = self._api.updateRemoteRecorderExternalId(recorder_id, external_id) try: cache_entry = RecorderCacheEntry.objects.get( recorder_id=recorder_id) cache_entry.recorder_external_id = external_id cache_entry.save() except RecorderCacheEntry.DoesNotExist: pass return self._get_recorder_details(recorder_id) except (MissingParamException, InvalidParamException, PanoptoAPIException) as err: return self.error_response(400, message="%s" % err) def _get_recorder_details(self, recorder_id): try: recorders = get_api_recorder_details(self._api, recorder_id) except (RecorderException, PanoptoAPIException, MissingParamException, InvalidParamException) as err: return self.error_response(400, message="%s" % err) if recorders is None: return self.error_response(404, message="No Recorder Found") return self._recorder_rep(recorders) def _recorder_rep(self, recorders): reps = [] for recorder in recorders: rep = { 'id': recorder.Id, 'external_id': recorder.ExternalId, 'name': recorder.Name, 'settings_url': recorder.SettingsUrl, 'state': recorder.State, 'space': None, 'scheduled_recordings': [] } if recorder.ScheduledRecordings and hasattr( recorder.ScheduledRecordings, 'guid'): for recording in recorder.ScheduledRecordings.guid: rep['scheduled_recordings'].append(recording) if recorder.ExternalId: try: space = get_space_by_id(recorders[0].ExternalId) rep['space'] = { 'space_id': space.space_id, 'name': space.name, 'formal_name': space.formal_name } except DataFailureException as err: logger.error('Cannot get space for id: %s: %s' % (recorders[0].ExternalId, err)) reps.append(rep) return self.json_response(reps) def _list_recorders(self): try: rec_cache = RecorderCache.objects.all()[0] now = pytz.UTC.localize(datetime.datetime.now()) timeout = datetime.timedelta(hours=self._space_list_cache_timeout) if (now - timeout) > rec_cache.created_date: self._scrub_recorder_cache(rec_cache) except (IndexError, RecorderCache.DoesNotExist): try: recorders = self._api.listRecorders() rec_cache = self._cache_recorders(recorders) except PanoptoAPIException as err: return self.error_response(400, message="%s" % err) rep = [] for recorder in RecorderCacheEntry.objects.filter(cache=rec_cache): rep.append({ 'id': recorder.recorder_id, 'external_id': recorder.recorder_external_id, 'name': recorder.name, 'scheduled_recordings': [] }) return self.json_response(rep) def _cache_recorders(self, recorders): rec_cache = RecorderCache() rec_cache.save() for recorder in recorders: RecorderCacheEntry.objects.create( cache=rec_cache, recorder_id=recorder.Id, recorder_external_id=recorder.ExternalId or '', name=recorder.Name) return rec_cache def _scrub_recorder_cache(self, rec_cache): RecorderCacheEntry.objects.filter(cache=rec_cache).delete() rec_cache.delete() raise RecorderCache.DoesNotExist()
class Command(BaseCommand): help = "Matchrecording session dates to SWS meeting times" option_list = BaseCommand.option_list + ( make_option('--commit', dest='commit', action="store_true", default=False, help='Update Panopto recording with SWS meeting time'), make_option('--stdin', dest='stdin', action="store_true", default=False, help='get Panopto session external ids on standard input'), ) def handle(self, *args, **options): self._commit = options['commit'] self._courses = {} self._session = SessionManagement() self._recorder = RemoteRecorderManagement() if options['stdin']: for line in sys.stdin: self._process_course(line.rstrip('\n')) else: for session in args: self._process_course(session) def _process_course(self, session_id): # 2015-spring-PSYCH-202-A-2015-06-04 course = re.match(r'^(20[0-9]{2})-(winter|spring|summer|autumn)' r'-([A-Z ]+)-([0-9]{3})-([A-Z][A-Z0-9]*)-2*', session_id) if course: label = "%s,%s,%s,%s/%s" % ( course.group(1), course.group(2), course.group(3), course.group(4), course.group(5)) if label not in self._courses: now = datetime.datetime.now( tz.tzlocal()).replace(second=0, microsecond=0) section = get_section_by_label( label, include_instructor_not_on_time_schedule=False) (start, end) = self._lecture_times(section) self._courses[label] = { 'start': start.split(':'), 'end': end.split(':') } offered = self._courses[label] else: print >> sys.stderr, "unrecognized session id: %s" % session_id return pan_session = self._session.getSessionsByExternalId([session_id]) if 'Session' in pan_session and len(pan_session.Session) == 1: # broken-ass suds. fsuds = re.match(r'.*\<a\:StartTime\>([^<]+)\<\/a\:StartTime\>.*', self._session._api.last_received().plain()) if not fsuds: Exception('Untrustable time') pan_start = parser.parse(fsuds.group(1)) pan_start_local = pan_start.astimezone(tz.tzlocal()) sws_start_local = pan_start_local.replace( hour=int(offered['start'][0]), minute=int(offered['start'][1])) sws_end_local = pan_start_local.replace( hour=int(offered['end'][0]), minute=int(offered['end'][1])) schedule_delta = sws_start_local - pan_start_local duration_delta = (sws_end_local - sws_start_local).seconds - int( pan_session.Session[0].Duration) if schedule_delta or duration_delta: pan_start = (pan_start_local + schedule_delta).astimezone(tz.tzutc()) duration = pan_session.Session[0].Duration if duration_delta: duration += duration_delta pan_end = pan_start + datetime.timedelta(0, duration) adjustment = [session_id, '(%s)' % pan_session.Session[0].Id, '' if self._commit else 'WOULD', 'RESCHEDULE', fsuds.group(1), 'TO', pan_start.isoformat(), ':'] if schedule_delta.days < 0: adjustment.append("(-%s shift)" % (datetime.timedelta() - schedule_delta)) else: adjustment.append("(%s shift)" % schedule_delta) if duration_delta: adjustment.append('AND DURATION') adjustment.append("%s" % duration_delta) adjustment.append('seconds') print >> sys.stderr, ' '.join(adjustment) if self._commit: result = self._recorder.updateRecordingTime( pan_session.Session[0].Id, pan_start.isoformat(), pan_end.isoformat()) if not result: print >> sys.stderr, "FAIL: null return value" elif result.ConflictsExist: print >> sys.stderr, "CONFLICT: %s" % ( result.ConflictingSessions[0][0].SessionName) else: print >> sys.stderr, "UPDATED %s" % ( result.SessionIDs[0][0]) else: print >> sys.stderr, "%s: UNCHANGED" % (session_id) else: print >> sys.stderr, "unrecognized session id: %s" % session_id def _lecture_times(self, section): for meeting in section.meetings: if (meeting.meeting_type in ['lecture', 'quiz', 'seminar'] and meeting.start_time and meeting.end_time): return meeting.start_time, meeting.end_time Exception("no lecture times set")
def get_recorder_details(recorder_id): return get_api_recorder_details(RemoteRecorderManagement(), recorder_id)