private static bool GetMd5ScheduleEntries(string[] dates, int start) { // reject 0 requests if (SdMxf.With.Services.Count - start < 1) { return(true); } // build request for station schedules var requests = new ScheduleRequest[Math.Min(SdMxf.With.Services.Count - start, MaxQueries / dates.Length)]; for (var i = 0; i < requests.Length; ++i) { requests[i] = new ScheduleRequest() { StationId = SdMxf.With.Services[start + i].StationId, Date = dates }; } // request schedule md5s from Schedules Direct var stationResponses = SdApi.GetScheduleMd5s(requests); if (stationResponses == null) { return(false); } // build request of daily schedules not downloaded yet var newRequests = new List <ScheduleRequest>(); foreach (var request in requests) { var requestErrors = new Dictionary <int, string>(); var mxfService = SdMxf.GetService(request.StationId); if (stationResponses.TryGetValue(request.StationId, out var stationResponse)) { // if the station return is empty, go to next station if (stationResponse.Count == 0) { var comment = $"Failed to parse the schedule Md5 return for stationId {mxfService.StationId} ({mxfService.CallSign}) on {dates[0]} and after."; if (CheckSuppressWarnings(mxfService.CallSign)) { Logger.WriteInformation(comment); } else { Logger.WriteWarning(comment); } processedObjects += dates.Length; ReportProgress(); continue; } // scan through all the dates returned for the station and request dates that are not cached var newDateRequests = new List <string>(); var dupeMd5s = new HashSet <string>(); foreach (var day in dates) { if (stationResponse.TryGetValue(day, out var dayResponse) && (dayResponse.Code == 0) && !string.IsNullOrEmpty(dayResponse.Md5)) { var filepath = $"{Helper.Epg123CacheFolder}\\{SafeFilename(dayResponse.Md5)}"; var file = new FileInfo(filepath); if (file.Exists && (file.Length > 0) && !epgCache.JsonFiles.ContainsKey(dayResponse.Md5)) { using (var reader = File.OpenText(filepath)) { epgCache.AddAsset(dayResponse.Md5, reader.ReadToEnd()); } } if (epgCache.JsonFiles.ContainsKey(dayResponse.Md5)) { ++processedObjects; ReportProgress(); ++cachedSchedules; } else { newDateRequests.Add(day); } if (!ScheduleEntries.ContainsKey(dayResponse.Md5)) { ScheduleEntries.Add(dayResponse.Md5, new[] { request.StationId, day }); } else { var previous = ScheduleEntries[dayResponse.Md5][1]; var comment = $"Duplicate schedule Md5 return for stationId {mxfService.StationId} ({mxfService.CallSign}) on {day} with {previous}."; Logger.WriteWarning(comment); dupeMd5s.Add(dayResponse.Md5); } } else if ((dayResponse != null) && (dayResponse.Code != 0) && !requestErrors.ContainsKey(dayResponse.Code)) { requestErrors.Add(dayResponse.Code, dayResponse.Message); } } // clear out dupe entries foreach (var dupe in dupeMd5s) { var previous = ScheduleEntries[dupe][1]; var comment = $"Removing duplicate Md5 schedule entry for stationId {mxfService.StationId} ({mxfService.CallSign}) on {previous}."; Logger.WriteWarning(comment); ScheduleEntries.Remove(dupe); } // create the new request for the station if (newDateRequests.Count > 0) { newRequests.Add(new ScheduleRequest() { StationId = request.StationId, Date = newDateRequests.ToArray() }); } } else { // requested station was not in response Logger.WriteWarning($"Requested stationId {mxfService.StationId} ({mxfService.CallSign}) was not present in schedule Md5 response."); processedObjects += dates.Length; ReportProgress(); continue; } if (requestErrors.Count <= 0) { continue; } foreach (var keyValuePair in requestErrors) { Logger.WriteError($"Requests for MD5 schedule entries of station {request.StationId} returned error code {keyValuePair.Key} , message: {keyValuePair.Value}"); } } ReportProgress(); // download the remaining daily schedules to the cache directory if (newRequests.Count > 0) { // request daily schedules from Schedules Direct var responses = SdApi.GetScheduleListings(newRequests.ToArray()); if (responses == null) { return(false); } // process the responses foreach (var response in responses) { ++processedObjects; ReportProgress(); if (response?.Programs == null) { continue; } ++downloadedSchedules; // serialize JSON directly to a file if (ScheduleEntries.TryGetValue(response.Metadata.Md5, out var serviceDate)) { using (var writer = new StringWriter()) { try { var serializer = new JsonSerializer(); serializer.Serialize(writer, response); epgCache.AddAsset(response.Metadata.Md5, writer.ToString()); } catch { Logger.WriteInformation($"Failed to write station daily schedule file to cache file. station: {serviceDate[0]} ; date: {serviceDate[1]}"); } } } else { try { var compare = ScheduleEntries .Where(arg => arg.Value[0].Equals(response.StationId)) .Single(arg => arg.Value[1].Equals(response.Metadata.StartDate)); Logger.WriteWarning($"Md5 mismatch for station {compare.Value[0]} on {compare.Value[1]}. Expected: {compare.Key} - Downloaded {response.Metadata.Md5}"); } catch { Logger.WriteWarning($"Md5 mismatch for station {response.StationId} on {response.Metadata.StartDate}. Downloaded {response.Metadata.Md5}"); } } } } ReportProgress(); return(true); }