/// <summary> /// WebからRSSフィードを取得します。 /// </summary> /// <returns>すぱこーRSSフィードのコンテンツを格納したリスト</returns> private async Task <IEnumerable <SpacomicRSSItem> > GetRSSCore() { List <SpacomicRSSItem> list = new List <SpacomicRSSItem>(); foreach (var sause in spacoSause) { // オフセット位置 int offset = 0; // 続けて取得する必要があるかを表すフラグ bool isContinue = true; do { string url = $"{sause.RSSFeedURL}?offset={offset}"; using (XmlReader reader = await Task.Run(() => SpacoRSSClient.GetXmlReaderAsync(url, cancellationTokenSource.Token))) { SpacoRSSReader srr = await Task.Run(() => SpacoRSSReader.LoadAsync(reader, cancellationTokenSource.Token)); // すぱこーRSSフィードのチャネル情報を設定します。 if (!SauseItems.ContainsKey(sause.Type)) { SauseItems[sause.Type] = new SpacoRSSSause { Title = srr.Title, Description = srr.Description, Author = srr.Author, Link = srr.Link, PubDate = srr.PubDate, BannerURL = srr.BannerURL }; } // 取得したコンテンツの数を取得します。 int count = srr.Items.Count(); if (count > 0) { offset += count; } // なければ、現在ソースからののRSSフィードの取得を終了します。 else { isContinue = false; } // 利用可能なコンテンツを抽出します。 list.AddRange( srr.Items.Where(_ => _.IsAvailable) .Select(_ => new SpacomicRSSItem(sause.Type, _)) .ToList() ); } } while(isContinue); } return(list); }
/// <summary> /// RSSフィードを取得(保存済みのローカルファイルから読み込み or Webから取得)します。 /// </summary> /// <param name="forceReload">強制的にWebから取得するフラグ</param> public async Task GetRSS(bool forceReload = false) { // 初期化 GetRSSResult result = GetRSSResult.Succeeded; SauseItems.Clear(); Items.Clear(); cancellationTokenSource = new CancellationTokenSource(); GetRSSStarted(this, null); try { // Webからの再取得をリクエストされた時 if (forceReload) { try { Items.AddRange((await GetRSSCore()).OrderByDescending(_ => _.PubDate)); // 取得したすぱこーRSSフィードのデータをローカルファイルに保存します。 await SpacomicLocalIO.SaveSpacoRSSSauseFile(SauseItems); await SpacomicLocalIO.SaveRSSCollectionFile(Items); } // Webからの再取得に失敗した場合、ローカルファイルからリストアします。 // Itemsが空であれば、保存済みのローカルファイルは、再取得する前のすぱこーRSSフィードのデータが残っています。 catch (Exception) when(!Items.Any()) { // 保存済みのローカルファイルからリストア var spacoRSSauseFromLocal = await SpacomicLocalIO.LoadSpacoRSSSauseFile(); var spacoRSSListFromLocal = await SpacomicLocalIO.LoadRSSCollectionFile(); // 保存済みのローカルファイルからのリストアが成功した時 if (spacoRSSauseFromLocal.ResultCode == GetRSSResult.Succeeded && spacoRSSListFromLocal.ResultCode == GetRSSResult.Succeeded) { foreach (var item in spacoRSSauseFromLocal.Items) { SauseItems[item.Key] = item.Value; } Items.AddRange(spacoRSSListFromLocal.Items); result = GetRSSResult.LocalDataRestored; } // リストアに失敗した場合、例外をリスローします。 else { throw; } } } else { // 保存済みのローカルファイルから読み込み var spacoRSSauseFromLocal = await SpacomicLocalIO.LoadSpacoRSSSauseFile(); var spacoRSSListFromLocal = await SpacomicLocalIO.LoadRSSCollectionFile(); // 保存済みのローカルファイルからの読み込みが成功した時 if (spacoRSSauseFromLocal.ResultCode == GetRSSResult.Succeeded && spacoRSSListFromLocal.ResultCode == GetRSSResult.Succeeded) { foreach (var item in spacoRSSauseFromLocal.Items) { SauseItems[item.Key] = item.Value; } Items.AddRange(spacoRSSListFromLocal.Items); // Web上に最新話があるかどうかチェックします。 CheckNewContents(); } // ローカルファイルからの読み込みに失敗した場合、Webから取得します else { Items.AddRange((await GetRSSCore()).OrderByDescending(_ => _.PubDate)); await SpacomicLocalIO.SaveSpacoRSSSauseFile(SauseItems); await SpacomicLocalIO.SaveRSSCollectionFile(Items); } } } catch (OperationCanceledException) { SauseItems.Clear(); Items.Clear(); result = GetRSSResult.Canceled; } catch (Exception) { SauseItems.Clear(); Items.Clear(); result = GetRSSResult.Failed; } finally { cancellationTokenSource.Dispose(); } // すぱこーRSSフィードの取得が完了したことをViewModel側に通知します。 GetRSSCompleted?.Invoke(this, result); }