public static void Parse(CsvReader csvReader, IRemoteRecorderManagement rrMgr, Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, ISessionManagement sessionMgr, Utilities.SessionManagement46.AuthenticationInfo sessionAuth, int lineNumber, List <ScheduleRecording> schedule, Dictionary <int, RecordingValidityCode> badSchedules, Dictionary <ScheduleRecording, int> recordingToLine) { while (csvReader.Read()) { if (csvReader.Context.Record.Length != Formats[SupportedFileType.Legacy].Length) { // if the number of fields is not good, then continue to the next record badSchedules.Add(lineNumber, RecordingValidityCode.ParseError); } else { ScheduleRecording record = csvReader.GetRecord <ScheduleRecording>(); ParseCommon(rrMgr, rrAuth, sessionMgr, sessionAuth, record, lineNumber, schedule, badSchedules, recordingToLine); } lineNumber++; } }
/// <summary> /// Common method calls an actions for all parsers. /// </summary> /// <param name="rrMgr">The client in which holds the information about the recorders available.</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <param name="sessionMgr">The client in which holds the information about the sessions.</param> /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param> /// <param name="record">The line currently being parsed.</param> /// <param name="lineNumber">The line number on the original file.</param> /// <param name="schedule">The schedule to update after <paramref name="record"/> is parsed.</param> /// <param name="badSchedules">The mappings from line number to error code to be populated, if needed.</param> /// <param name="recordingToLine">The mappings from recording to line number.</param> public static void ParseCommon(IRemoteRecorderManagement rrMgr, Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, ISessionManagement sessionMgr, Utilities.SessionManagement46.AuthenticationInfo sessionAuth, ScheduleRecording record, int lineNumber, List <ScheduleRecording> schedule, Dictionary <int, RecordingValidityCode> badSchedules, Dictionary <ScheduleRecording, int> recordingToLine) { // Now grab the IDs if possible and set them in the object record.RecorderID = Checker.GetRecorderID(record.RecorderName, rrMgr, rrAuth); if (record.FolderName != "" && record.FolderID == Guid.Empty) { // a specific folder was specified so try to look it up record.FolderID = Checker.GetFolderID(record.FolderName, sessionMgr, sessionAuth); } else if (record.FolderName == "" && record.RecorderID != Guid.Empty) { // case for a default folder/unspecified folder // Each RR has their own default folder, so call that and directly get folderID from that record.FolderID = rrMgr.GetDefaultFolderForRecorder(rrAuth, record.RecorderID); // Need to update the FolderName if we used the remote recorder's default folder Folder[] folder = sessionMgr.GetFoldersById(sessionAuth, new Guid[] { record.FolderID }); record.FolderName = folder[0].Name; } if (record.CheckValidity() != RecordingValidityCode.Valid) { badSchedules.Add(lineNumber, record.CheckValidity()); } recordingToLine.Add(record, lineNumber); schedule.Add(record); }
/// <summary> /// Takes the recording client and authentication, and attempts to schedule sessions provided in <paramref name="schedule"/>. /// </summary> /// <param name="rrMgr">The client in which holds the information about the recorders available.</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <param name="schedule">The recording schedule.</param> /// <returns>The results of the scheduling attempt.</returns> public static Dictionary <ScheduleRecording, ScheduledRecordingResult> ScheduleRecordings( IRemoteRecorderManagement rrMgr, Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, List <ScheduleRecording> schedule) { return(ScheduleRecordings(rrMgr, rrAuth, schedule, sender: null)); }
/// <summary> /// Gets the unique ID of the recorder specified by <paramref name="recorderName"/>. /// </summary> /// <param name="recorderName">Name of the recorder to get the ID for.</param> /// <param name="rrMgr">The client in which holds the information about the recorder <paramref name="recorderName"/>.</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <returns>Returns the unique ID, if found. Else, will return Guid.Empty.</returns> public static Guid GetRecorderID(string recorderName, IRemoteRecorderManagement rrMgr, RemoteRecorderManagement42.AuthenticationInfo rrAuth) { Guid rrID = Guid.Empty; // Handle no recorder name here if (recorderName.Equals("")) { return(rrID); } // set the recorderName to lowercase for insensitive lookup recorderName = recorderName.ToLowerInvariant(); if (recorderIds.ContainsKey(recorderName)) { return(recorderIds[recorderName]); } if (recorderIds.Count > 0) { return(Guid.Empty); } bool lastPage = false; int resultsPerPage = 5; int pageNumber = 0; while (!lastPage) { RemoteRecorderManagement42.Pagination rrPage = new RemoteRecorderManagement42.Pagination() { MaxNumberResults = resultsPerPage, PageNumber = pageNumber }; ListRecordersResponse rrResponse = rrMgr.ListRecorders(rrAuth, rrPage, RecorderSortField.Name); if (resultsPerPage * (pageNumber + 1) >= rrResponse.TotalResultCount) { lastPage = true; } // Populate the lookup map with the lowercase'd names of the recorders foreach (RemoteRecorder rr in rrResponse.PagedResults) { recorderIds[rr.Name.ToLowerInvariant()] = rr.Id; } // keep looking pageNumber++; } // If rrID stays empty then remote recorder wasn't found or handle the case in which not found return(GetRecorderID(recorderName, rrMgr, rrAuth)); }
/// <summary> /// Sets up the access to the server. /// </summary> /// <param name="userName">The username of the account that has access to schedule recordings.</param> /// <param name="password">The password associated with the account <paramref name="userName"/>.</param> /// <param name="rrMgr">The client in which holds the information about the recorders available.</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <param name="sessionMgr">The client in which holds the information about the sessions.</param> /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param> public static void SetupSiteAccess(string userName, string password, out IRemoteRecorderManagement rrMgr, out Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, out ISessionManagement sessionMgr, out Utilities.SessionManagement46.AuthenticationInfo sessionAuth) { SetupSiteAccess(userName: userName, password: password, siteName: Properties.Settings.Default.sitename, rrMgr: out rrMgr, rrAuth: out rrAuth, sessionMgr: out sessionMgr, sessionAuth: out sessionAuth); }
public static void Parse(CsvReader csvReader, IRemoteRecorderManagement rrMgr, Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, ISessionManagement sessionMgr, Utilities.SessionManagement46.AuthenticationInfo sessionAuth, DateTime startDate, DateTime endDate, int lineNumber, string term, List <ScheduleRecording> schedule, Dictionary <int, RecordingValidityCode> badSchedules, Dictionary <ScheduleRecording, int> recordingToLine) { while (csvReader.Read()) { // maybe problem due to inconsistent header lengths (with/without exclusion date header) or can just ignore and continue // and the Sunday sheet example where there is nothing, header check might catch and ignore this case though if (csvReader.Context.Record.Length != Formats[SupportedFileType.Georgetown].Length) { // if the number of fields is not good, then continue to the next record badSchedules.Add(lineNumber, RecordingValidityCode.ParseError); } else if (csvReader.Context.Record[1] == "") { // skip it: this line was probably scheduled manually } else { RecurringRecording record = csvReader.GetRecord <RecurringRecording>(); record.FolderName += "." + term; ParseCommon(rrMgr, rrAuth, sessionMgr, sessionAuth, record, lineNumber, schedule, badSchedules, recordingToLine); } lineNumber++; if (lineNumber % 10 == 0) { Console.WriteLine(lineNumber); } } }
public static void Parse(CsvReader csvReader, IRemoteRecorderManagement rrMgr, Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, ISessionManagement sessionMgr, Utilities.SessionManagement46.AuthenticationInfo sessionAuth, int lineNumber, DateTime startDate, DateTime endDate, string term, List <ScheduleRecording> schedule, Dictionary <int, RecordingValidityCode> badSchedules, Dictionary <ScheduleRecording, int> recordingToLine) { while (csvReader.Read()) { if (csvReader.Context.Record.Length != Formats[SupportedFileType.Banner].Length) { // if the number of fields is not good, then continue to the next record badSchedules.Add(lineNumber, RecordingValidityCode.ParseError); } else { RecurringRecording record = csvReader.GetRecord <RecurringRecording>(); // Put in start date and end date record index 6 and 7 for times // Don't adjust the start date onto the cadence here, adjust at schedule time. record.StartDate = ParseTime(startDate, csvReader.Context.Record[6], BannerTimeFormat); record.EndDate = ParseTime(endDate, csvReader.Context.Record[7], BannerTimeFormat); // Use local time to calculate recording duration due to UTC conversion causing negative durations // with the use of TimeOfDay. Alternate solutions include subtracting days from end and start so that they are // on the same day but that introduces lots of overhead and more calculations. record.Duration = record.EndDate.ToLocalTime().TimeOfDay - record.StartDate.ToLocalTime().TimeOfDay; record.FolderName += term; ParseCommon(rrMgr, rrAuth, sessionMgr, sessionAuth, record, lineNumber, schedule, badSchedules, recordingToLine); } lineNumber++; } }
/// <summary> /// Sets up the access to the server. /// </summary> /// <param name="userName">The username of the account that has access to schedule recordings.</param> /// <param name="password">The password associated with the account <paramref name="userName"/>.</param> /// <param name="siteName">The name of the site in which to gain access to.</param> /// <param name="rrMgr">The client in which holds the information about the recorders available.</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <param name="sessionMgr">The client in which holds the information about the sessions.</param> /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param> public static void SetupSiteAccess(string userName, string password, string siteName, out IRemoteRecorderManagement rrMgr, out Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, out ISessionManagement sessionMgr, out Utilities.SessionManagement46.AuthenticationInfo sessionAuth) { if (siteName == "") { // sitename was not configured throw new System.Configuration.ConfigurationErrorsException("Sitename was not configured."); } // rr manager setup rrMgr = new RemoteRecorderManagementClient( new BasicHttpBinding(BasicHttpSecurityMode.Transport) { MaxReceivedMessageSize = Properties.Settings.Default.HttpBindingMessageSize, SendTimeout = Properties.Settings.Default.HttpBindingTimeout, ReceiveTimeout = Properties.Settings.Default.HttpBindingTimeout }, new EndpointAddress("https://" + siteName + "/Panopto/PublicAPI/4.2/RemoteRecorderManagement.svc") ); // rr auth info setup rrAuth = new Utilities.RemoteRecorderManagement42.AuthenticationInfo(); rrAuth.UserKey = userName; rrAuth.Password = password; // session manager setup sessionMgr = new SessionManagementClient( new BasicHttpBinding(BasicHttpSecurityMode.Transport) { MaxReceivedMessageSize = Properties.Settings.Default.HttpBindingMessageSize, SendTimeout = Properties.Settings.Default.HttpBindingTimeout, ReceiveTimeout = Properties.Settings.Default.HttpBindingTimeout }, new EndpointAddress("https://" + siteName + "/Panopto/PublicAPI/4.6/SessionManagement.svc") ); // session auth info sessionAuth = new Utilities.SessionManagement46.AuthenticationInfo(); sessionAuth.UserKey = userName; sessionAuth.Password = password; }
/// <summary> /// Parses the given <paramref name="filepath"/> and returns the recording schedule. /// </summary> /// <param name="filepath">The path at which the file is located.</param> /// <param name="rrMgr">The client in which holds the information about the recorders available.</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <param name="sessionMgr">The client in which holds the information about the sessions.</param> /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param> /// <param name="badSchedules">The mappings from line number to error code to be populated, if needed.</param> /// <param name="conflicts">All the recordings that conflicted with an earlier recording or are invalid.</param> /// <returns>The recording schedule, as well as the output parameters <paramref name="badSchedules"/> and <paramref name="conflicts"/>.</returns> public static List <ScheduleRecording> ParseFile(string filepath, IRemoteRecorderManagement rrMgr, Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, ISessionManagement sessionMgr, Utilities.SessionManagement46.AuthenticationInfo sessionAuth, out Dictionary <int, RecordingValidityCode> badSchedules, out List <ScheduleRecording> conflicts) { return(ParseFile(filepath: filepath, rrMgr: rrMgr, rrAuth: rrAuth, sessionMgr: sessionMgr, sessionAuth: sessionAuth, startDate: DateTime.MinValue, endDate: DateTime.MinValue, term: null, folderId: null, badSchedules: out badSchedules, conflicts: out conflicts)); }
/// <summary> /// Attempts to get any remote recorder with the provided <paramref name="rrAuth"/> credentials. /// </summary> /// <param name="rrMgr">The client in which holds the information about the recorders</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <returns>A code that determines the result of the attempted login.</returns> public static LoginResults TryLoginGetRecorder(IRemoteRecorderManagement rrMgr, RemoteRecorderManagement42.AuthenticationInfo rrAuth) { try { var pagination = new RemoteRecorderManagement42.Pagination { MaxNumberResults = 1, PageNumber = 0 }; var recorderListResponse = rrMgr.ListRecorders(rrAuth, pagination, RecorderSortField.Name); // no Remote Recorders found if (recorderListResponse.TotalResultCount < 1) { return(LoginResults.NoAccess); } } catch { // ListRecorders throws an exception if authentication fails either incorrect credentials or not admin. return(LoginResults.Failure); } return(LoginResults.Success); }
/// <summary> /// Parses the given <paramref name="filepath"/> and returns the recording schedule. /// </summary> /// <param name="filepath">The path at which the file is located.</param> /// <param name="rrMgr">The client in which holds the information about the recorders available.</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <param name="sessionMgr">The client in which holds the information about the sessions.</param> /// <param name="sessionAuth">The authentication information for which to access the information from <paramref name="sessionMgr"/>.</param> /// <param name="startDate">The start date of the term.</param> /// <param name="endDate">The end date of the term.</param> /// <param name="term">The string representation of the term.</param> /// <param name="badSchedules">The mappings from line number to error code to be populated, if needed.</param> /// <param name="conflicts">All the recordings that conflicted with an earlier recording or are invalid.</param> /// <returns>The recording schedule, as well as the output parameters <paramref name="badSchedules"/> and <paramref name="conflicts"/>.</returns> public static List <ScheduleRecording> ParseFile(string filepath, IRemoteRecorderManagement rrMgr, Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, ISessionManagement sessionMgr, Utilities.SessionManagement46.AuthenticationInfo sessionAuth, DateTime startDate, DateTime endDate, string term, Guid?folderId, out Dictionary <int, RecordingValidityCode> badSchedules, out List <ScheduleRecording> conflicts) { List <ScheduleRecording> result = new List <ScheduleRecording>(); // Handle CSV style case using (TextReader reader = File.OpenText(filepath)) { // Create the CsvReader CsvReader csvReader = new CsvReader(reader); // Ignore missing fields since we don't know the format yet // The corresponding classmap class will and should handle those missing fields csvReader.Configuration.MissingFieldFound = null; // Now read the header to determine its format. badSchedules = new Dictionary <int, RecordingValidityCode>(); conflicts = null; Dictionary <ScheduleRecording, int> recordingToLine = new Dictionary <ScheduleRecording, int>(); List <ScheduleRecording> schedule = new List <ScheduleRecording>(); int lineNumber = 1; SupportedFileType fileType = SupportedFileType.NotSupported; bool foundHeader = false; while (csvReader.Read()) { if (!foundHeader) { csvReader.ReadHeader(); // see if this line is a header we recognize foreach (SupportedFileType sft in Enum.GetValues(typeof(SupportedFileType))) { string[] format = Formats[sft]; foundHeader = IsHeader(format, csvReader.Context.Record); if (foundHeader) { // set the filetype and the appropriate map. fileType = sft; switch (fileType) { // Call appropriate parser here, with lineNumber + 1 case SupportedFileType.Legacy: csvReader.Configuration.RegisterClassMap <ScheduleRecordingMap>(); LegacyParser.Parse(csvReader, rrMgr, rrAuth, sessionMgr, sessionAuth, lineNumber + 1, schedule, badSchedules, recordingToLine); // Need to check the schedule for internal conflicts // done parsing so check the schedule conflicts = Checker.CheckConflicts(schedule, recordingToLine, badSchedules); break; case SupportedFileType.Banner: csvReader.Configuration.RegisterClassMap <RecurringRecordingMap>(); BannerParser.Parse(csvReader, rrMgr, rrAuth, sessionMgr, sessionAuth, lineNumber + 1, startDate, endDate, term, schedule, badSchedules, recordingToLine); // We trust that the Banner format is internally consistent so set conflicts to new empty list. conflicts = new List <ScheduleRecording>(); break; case SupportedFileType.Georgetown: csvReader.Configuration.RegisterClassMap <GeorgetownMap>(); GeorgetownParser.Parse(csvReader, rrMgr, rrAuth, sessionMgr, sessionAuth, startDate, endDate, lineNumber + 1, term, schedule, badSchedules, recordingToLine); // We trust that Georgetown has scrubbed their file so that there are no conflicts conflicts = new List <ScheduleRecording>(); break; case SupportedFileType.Mediasite: csvReader.Configuration.RegisterClassMap <MediasiteMap>(); MediasiteParser.Parse(csvReader, rrMgr, rrAuth, sessionMgr, sessionAuth, folderId, lineNumber + 1, schedule, badSchedules, recordingToLine); // Need to check the schedule for internal conflicts // done parsing so check the schedule conflicts = Checker.CheckConflicts(schedule, recordingToLine, badSchedules); break; default: break; } break; } } } lineNumber++; } // This step can still be done for all formats for (int i = 0; i < schedule.Count; i++) { if (!badSchedules.ContainsKey(recordingToLine[schedule[i]]) && schedule[i].CheckValidity() == RecordingValidityCode.Valid) { result.Add(schedule[i]); } } // we are done reading but no SupportedFileType detected. if (!foundHeader) { // give a special line number to badSchedules badSchedules.Add(-1, RecordingValidityCode.ParseError); conflicts = new List <ScheduleRecording>(); } } return(result); }
/// <summary> /// Takes the recording client and authentication, and attempts to schedule sessions provided in <paramref name="schedule"/>. /// </summary> /// <param name="rrMgr">The client in which holds the information about the recorders available.</param> /// <param name="rrAuth">The authentication information for which to access the information from <paramref name="rrMgr"/>.</param> /// <param name="schedule">The recording schedule.</param> /// <param name="sender">The BackgroundWorker to make this method asynchronous.</param> /// <returns>The results of the scheduling attempt.</returns> public static Dictionary <ScheduleRecording, ScheduledRecordingResult> ScheduleRecordings( IRemoteRecorderManagement rrMgr, Utilities.RemoteRecorderManagement42.AuthenticationInfo rrAuth, List <ScheduleRecording> schedule, BackgroundWorker sender) { Dictionary <ScheduleRecording, ScheduledRecordingResult> result = new Dictionary <ScheduleRecording, ScheduledRecordingResult>(); for (int i = 0; i < schedule.Count; i++) { if (sender != null) { sender.ReportProgress(i + 1); } else { Console.WriteLine("Scheduling recording " + (i + 1) + "/" + schedule.Count + "..."); } ScheduleRecording scheduleRecording = schedule[i]; try { // Currently only concerned with 1 RR for each session RecorderSettings rs = new RecorderSettings() { RecorderId = scheduleRecording.RecorderID }; RecurringRecording recurring = null; // need to check to make sure start date is on cadence and adjust as needed if recurring. if ((scheduleRecording as RecurringRecording) != null) { scheduleRecording.StartDate = AdjustDateOntoCadence( scheduleRecording.StartDate, ((RecurringRecording)scheduleRecording).Cadence); // since we need to schedule the first occurrence, this is for accurate success/conflict counting recurring = new RecurringRecording((RecurringRecording)scheduleRecording); } ScheduledRecordingResult scheduledResult = rrMgr.ScheduleRecording( rrAuth, scheduleRecording.SessionName, scheduleRecording.FolderID, scheduleRecording.IsBroadcast || Properties.Settings.Default.ScheduleBroadcasts, scheduleRecording.StartDate, scheduleRecording.StartDate + scheduleRecording.Duration, new RecorderSettings[] { rs }); result.Add(scheduleRecording, scheduledResult); if ((scheduleRecording as RecurringRecording) != null && !result[scheduleRecording].ConflictsExist) { // need to transform recurring.Cadence to a DayOfWeek[] DayOfWeek[] days = CadenceToArray(recurring.Cadence); // update the dictionary since this is recurring recording. scheduledResult = rrMgr.ScheduleRecurringRecording(rrAuth, result[scheduleRecording].SessionIDs[0], days, recurring.EndDate); result.Add(recurring, scheduledResult); } } catch { // Since something went wrong with scheduling, still log it in result to report it later. result.Add(scheduleRecording, new ScheduledRecordingResult() { ConflictsExist = true }); } } return(result); }