/// <summary> /// コンストラクタ /// </summary> public Kindle(IBlogger blogger, ILogger <Kindle> logger, IOptions <KindleOptions> kindleOptions, IOptions <AmazonOptions> amazonOptions) : base(logger, amazonOptions) { this.logger = logger; options = kindleOptions?.Value; this.blogger = blogger; if (this.blogger != null) { this.blogger.BlogId = options?.BlogId; } // データベースの作成 using (var db = new KindleDbContext()) { db.Database.EnsureCreated(); } //var serializer = new XmlSerializer(typeof(KindleData)); //try //{ // using (var fs = new FileStream(options.GetDataFilePath(), FileMode.Open)) // { // data = (KindleData)serializer.Deserialize(fs); // } // logger.LogInformation("デシリアライズ完了"); //} //catch //{ // logger.LogError("デシリアライズ失敗"); // data = new KindleData(); //} }
public void InsertTest() { using (var context = new KindleDbContext(fixture.DataSource)) { var saleInformation = new SaleInformation { Url = "http://blogs.msdn.com/dotnet", Items = new List <ItemDetail> { new ItemDetail { Title = "Intro to C#" }, new ItemDetail { Title = "Intro to VB.NET" }, new ItemDetail { Title = "Intro to F#" } } }; context.SaleInformations.Add(saleInformation); context.SaveChanges(); } }
// Setup public KindleDbContextFixture() { // データベースの作成 using (var db = new KindleDbContext(DataSource)) { db.Database.EnsureCreated(); } }
/// <summary> /// 開催中セール一覧のページを更新する /// </summary> /// <returns></returns> void UpdateCurrentSaleListPage() { // 逆順で表示 //var saleInformations = data.SaleInformations.Reverse<SaleInformation>(); string content = $@"<p> Amazon Product Advertising API から取得した、現在開催中の Kindle セールの一覧です。<br> </p> <p> 更新日時:{lastUpdate} </p>"; int count = 0; content += @"<div class=""table-responsive""> <table class=""table""> <tr><th>No.</th><th>開催期間</th><th>タイトル</th><th>Amazon</th></tr>"; using (var context = new KindleDbContext()) { foreach (var saleInformation in context.SaleInformations.OrderByDescending(x => x.NodeId)) { if ((saleInformation.Error == false) && (saleInformation.SaleStarted == true) && (saleInformation.SaleFinished == false)) { string entry; if (saleInformation.Url == null) { entry = saleInformation.Name; } else { entry = $"<a href='{saleInformation.Url}'>{saleInformation.Name}</a>"; } content += $@"<tr> <td>{count++}</td> <td>{saleInformation.GetSalePeriod()}</td> <td>{entry}</td> <td><a class='amazon' href='{GetAssociateLinkByBrowseNode(saleInformation.NodeId)}' target='_blank'>Amazon</a></td> </tr>"; } } } content += "</table></div>"; try { blogger.UpdatePage(options.CurrentSaleListPageId, content); } catch { logger?.LogError("開催中セール一覧のページ更新失敗"); throw; } }
/// <summary> /// 最新セール情報一覧のページを更新する /// </summary> /// <returns></returns> void UpdateLatestSaleListPage() { // 逆順で表示 //var saleInformations = data.SaleInformations.Reverse<SaleInformation>(); string content = $@"<p> Amazon Product Advertising API から取得した Kindle のセールページ一覧です。<br> この中にはまだセールを開始していないものや、既に終了したセールなど、セールではないものもありますのでご注意ください。 </p> <p> 更新日時:{lastUpdate} </p>"; int count = 0; content += @"<div class=""table-responsive""> <table class=""table""> <tr><th>No.</th><th>開催期間</th><th>タイトル</th><th>Amazon</th><th>ESF</th></tr>"; using (var context = new KindleDbContext()) { foreach (var saleInformation in context.SaleInformations.OrderByDescending(x => x.NodeId)) { string entry; if (saleInformation.Url == null) { entry = saleInformation.Name; } else { entry = $"<a href='{saleInformation.Url}'>{saleInformation.Name}</a>"; } content += $@"<tr> <td>{count++}</td> <td>{saleInformation.GetSalePeriod()}</td> <td>{entry}</td> <td><a class='amazon' href='{GetAssociateLinkByBrowseNode(saleInformation.NodeId)}' target='_blank'>Amazon</a></td> <td>{(saleInformation.Error ? "1" : "0")}{(saleInformation.SaleStarted ? "1" : "0")}{(saleInformation.SaleFinished ? "1" : "0")}</td> </tr>"; } } content += "</table></div>"; try { blogger.UpdatePage(options.LatestSaleListPageId, content); } catch { logger?.LogError("最新セール情報一覧のページ更新失敗"); throw; } }
/// <summary> /// 処理の開始 /// </summary> /// <param name="args"></param> public void Run() { logger?.LogInformation("----- Begin -----"); try { // セールの一覧を取得 BrowseNodeLookup("2275277051"); Task.Delay(requestWaitTimerMSec).Wait(); lastUpdate = DateTime.Now;//. ToString("yyyy/MM/dd (ddd) HH:mm:ss"); // 個々の URL を取得 int count = 0; using (var context = new KindleDbContext()) { var saleInformations = context.SaleInformations .Include(SaleInformation => SaleInformation.Items) .ToList(); int total = saleInformations.Count(); foreach (var saleInformation in saleInformations) { logger?.LogInformation($"[{count + 1}/{total}件開始]"); if ((total - options.ActiveCount) <= count && count < total) { // 最新の数件のみ処理 // 既にセールが終了していないかどうかチェック if (saleInformation.SaleFinished == true) { logger?.LogInformation($"{saleInformation.NodeId} は既にセール終了"); } else { // ブログに投稿済みかどうかチェック if (saleInformation.Url != null) { try { logger?.LogInformation($"{saleInformation.NodeId} は既に投稿済み"); CheckSalePeriod(saleInformation, count, saleInformations.Count()); // 終了した場合はタイトルを終了済みにする UpdateArticle(saleInformation); } catch (Exception e) { logger?.LogError(e.Message); } } else { // まだ投稿していない場合は商品情報を取得して投稿する try { logger?.LogInformation($"----- {saleInformation.NodeId} の商品情報取得開始 -----"); if (ItemSearchAll(saleInformation) == true) { CheckSalePeriod(saleInformation, count, saleInformations.Count()); PostToBlog(saleInformation); } } catch (Exception e) { logger?.LogError(e.Message); } } } } else { logger?.LogInformation($"Skip {saleInformation.NodeId}"); } logger?.LogInformation($"[{count + 1}/{saleInformations.Count()}件完了]"); count++; context.SaveChanges(); } } } catch (Exception e) { logger?.LogError(e.Message); throw; } // 開催中セール一覧のページを更新 UpdateCurrentSaleListPage(); // 最新セール一覧のページを更新 UpdateLatestSaleListPage(); logger?.LogInformation("----- End -----"); }
/// <summary> /// セールの一覧を取得 /// </summary> /// <param name="nodeId">基準となるノードID</param> void BrowseNodeLookup(string browseNodeId) { IDictionary <string, string> request = new Dictionary <string, String> { ["Service"] = service, ["Version"] = apiVersion, ["Operation"] = "BrowseNodeLookup", ["SearchIndex"] = "KindleStore", ["BrowseNodeId"] = browseNodeId }; using (var context = new KindleDbContext()) { logger?.LogInformation($"現在の件数:{context.SaleInformations.Count()}件"); } logger?.LogInformation($"セール情報一覧取得開始"); // リクエストを送信して xml を取得 var result = GetXml(request); // 取得した XML を読み込む XmlDocument doc = new XmlDocument(); doc.Load(result); // 名前空間の指定 XmlNamespaceManager xmlNsManager = new XmlNamespaceManager(doc.NameTable); xmlNsManager.AddNamespace("ns", ns); // XML をパースしてノードリストを取得 XmlNodeList nodeList = doc.SelectNodes("ns:BrowseNodeLookupResponse/ns:BrowseNodes/ns:BrowseNode/ns:Children/ns:BrowseNode", xmlNsManager); List <SaleInformation> newSaleInformations = new List <SaleInformation>(); foreach (XmlNode node in nodeList) { newSaleInformations.Add(new SaleInformation() { NodeId = node.SelectSingleNode("ns:BrowseNodeId", xmlNsManager).InnerText, Name = node.SelectSingleNode("ns:Name", xmlNsManager).InnerText }); } logger?.LogInformation($"セール情報一覧取得完了({newSaleInformations.Count()}件)"); // 現在のリストの項目が最新のリスト中になければ古い情報と判断して削除する int deleteCount = 0; using (var context = new KindleDbContext()) { var saleInformations = context.SaleInformations.ToList(); foreach (var saleInformation in saleInformations) { var foundItem = newSaleInformations.Find(item => item.NodeId == saleInformation.NodeId); if (foundItem == null) { context.SaleInformations.Remove(saleInformation); deleteCount++; } } context.SaveChanges(); logger?.LogInformation($"{deleteCount}件の古いデータを削除(残り{context.SaleInformations.Count()}件)"); } // 最新のリストのうち、現在のリスト中にないものだけ現在のリストに新規に追加する int addCount = 0; using (var context = new KindleDbContext()) { foreach (var newSaleInformation in newSaleInformations) { var foundItem = context.SaleInformations.Where(item => item.NodeId == newSaleInformation.NodeId).FirstOrDefault(); if (foundItem == null) { context.SaleInformations.Add(newSaleInformation); addCount++; } } context.SaveChanges(); logger?.LogInformation($"{addCount}件の新規データを追加(計{context.SaleInformations.Count()}件)"); } // ソート //data.SaleInformations.Sort((a, b) => string.Compare(a.NodeId, b.NodeId)); }