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> /// 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> /// Writes the successfully scheduled recordings to an output CSV file. /// </summary> /// <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="scheduleSuccesses">The list of unique identifiers for each successfully scheduled recording.</param> /// <param name="sender">The BackgroundWorker to make this method asynchronous.</param> public static void WriteSuccessFile(ISessionManagement sessionMgr, Utilities.SessionManagement46.AuthenticationInfo sessionAuth, List <Guid> scheduleSuccesses, BackgroundWorker sender) { // Get the information for each scheduled session and put it into a ScheduleResult object. List <ScheduleResult> scheduled = new List <ScheduleResult>(); Session[] session = sessionMgr.GetSessionsById(sessionAuth, scheduleSuccesses.ToArray()); for (int j = 0; j < session.Length; j++) { if (sender != null) { // NOTE: This method runs so quickly even at many lines, that this progress report may not be necessary // to update the UI. Still good to have in the event this stalls here though. sender.ReportProgress(j); } // Use 0 for RemoteRecorderIds since currently only dealing with 1 remote recorder. ScheduleResult sr = new ScheduleResult(session[j].RemoteRecorderIds[0], session[j].FolderId, session[j].Id, session[j].Name, session[j].StartTime?.ToLocalTime(), (session[j].StartTime + TimeSpan.FromSeconds(session[j].Duration.GetValueOrDefault()))?.ToLocalTime()); scheduled.Add(sr); } // write what was successfully scheduled to output.csv // output.csv will only have a header if there were no session scheduled. using (TextWriter writer = new StreamWriter(Properties.Settings.Default.LogsLocation + DateTime.Now.ToString("yyyyMMdd_HHmmss") + @"_success_output.csv")) { if (sender != null) { sender.ReportProgress(session.Length); } var csv = new CsvWriter(writer); csv.WriteRecords(scheduled); } }
/// <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> /// Writes the successfully scheduled recordings to an output CSV file. /// </summary> /// <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="scheduleSuccesses">The list of unique identifiers for each successfully scheduled recording.</param> public static void WriteSuccessFile(ISessionManagement sessionMgr, Utilities.SessionManagement46.AuthenticationInfo sessionAuth, List <Guid> scheduleSuccesses) { WriteSuccessFile(sessionMgr, sessionAuth, scheduleSuccesses, sender: null); }