You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

424 lines
16KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Reflection;
  5. using System.Linq;
  6. using OpenQA.Selenium;
  7. using OpenQA.Selenium.Chrome;
  8. using OpenQA.Selenium.Support.UI;
  9. using SeleniumExtras.WaitHelpers;
  10. using CSVDownloader.File;
  11. using CSVDownloader.Store;
  12. using CSVDownloader.Store.CreditCSVData;
  13. using CSVDownloader.Store.QRCSVData;
  14. using CSVDownloader.Web;
  15. using CSVDownloader.Exceptions;
  16. using MySql.Data.MySqlClient;
  17. namespace CSVDownloader {
  18. class Program {
  19. static void Main(string[] args) {
  20. // 作業ディレクトリを実行ファイルに合わせる。
  21. var exe_path = Assembly.GetEntryAssembly().Location;
  22. var exe_directory_path = Path.GetDirectoryName(exe_path);
  23. Directory.SetCurrentDirectory(exe_directory_path);
  24. var controller = new Controller();
  25. String ret = controller.Start();
  26. if (ret.Length != 0) {
  27. // エラー検知
  28. Console.WriteLine(ret);
  29. Console.WriteLine("エラー発生 詳細はログを参照");
  30. Environment.Exit(1);
  31. }
  32. }
  33. }
  34. class Controller {
  35. private log4net.ILog logger_ = log4net.LogManager.GetLogger("");
  36. private List<WebController> web_controller_list_ = new List<WebController>();
  37. private HistoryDAO history_dao_;
  38. private ParkingCreditCardAgenciesSpotIDDAO parking_credit_card_agencies_spotID_dao_;
  39. private DaitoCreitDataStore daito_credit_store_;
  40. private ZeusCreditDataStore zeus_credit_store_;
  41. private ItecCreditDataStore itec_credit_store_;
  42. private HelloTechnoCreditDataStore hello_techno_credit_store_;
  43. private DaitoQRDataStore daito_qr_store_;
  44. private ParkingCreditCardAgenciesSpotIDErrorDAO parking_credit_card_agencies_spotID_error_dao_;
  45. private IConfigReader config_;
  46. private ChromeDriver driver_;
  47. private MySqlConnection conn_;
  48. private MySqlTransaction transaction_;
  49. private Dictionary<Code.CreditAgent, CreditCSVDataStore> credit_datastore_map_ = new Dictionary<Code.CreditAgent, CreditCSVDataStore>();
  50. private Dictionary<Code.CreditAgent, QRCSVDataStore> qr_datastore_map_ = new Dictionary<Code.CreditAgent, QRCSVDataStore>();
  51. private int save_chunk_num_ = 100;
  52. public String Start() {
  53. Console.WriteLine("★★★★★★自動CSVダウンロード 起動★★★★★");
  54. logger_.Info("★★★★★★自動CSVダウンロード 起動★★★★★");
  55. String returnable = "";
  56. // 各種ストアを用意
  57. history_dao_ = new HistoryDAO();
  58. config_ = new ConfigReader("config/config.ini");
  59. var mysql_param = new MySqlConnectionParameter() {
  60. host = "192.168.0.28",
  61. port = 3306,
  62. database = "ypark",
  63. user = "ypuser2",
  64. password = "ypp@ssw0rd2"
  65. };
  66. //var mysql_param = new MySqlConnectionParameter() {
  67. // host = "localhost",
  68. // port = 3306,
  69. // database = "yp",
  70. // user = "docker",
  71. // password = "docker",
  72. //};
  73. try {
  74. conn_ = MySQL.GetConnection(mysql_param);
  75. parking_credit_card_agencies_spotID_dao_ = new ParkingCreditCardAgenciesSpotIDDAO(conn_);
  76. parking_credit_card_agencies_spotID_error_dao_ = new ParkingCreditCardAgenciesSpotIDErrorDAO(conn_);
  77. daito_credit_store_ = new DaitoCreitDataStore(conn_);
  78. zeus_credit_store_ = new ZeusCreditDataStore(conn_);
  79. itec_credit_store_ = new ItecCreditDataStore(conn_);
  80. hello_techno_credit_store_ = new HelloTechnoCreditDataStore(conn_);
  81. daito_qr_store_ = new DaitoQRDataStore(conn_);
  82. } catch (Exception e) {
  83. logger_.Error("DB接続失敗");
  84. logger_.Error(e.Message);
  85. return "DBへのコネクト失敗";
  86. }
  87. // エラーリストを初期化する(全削除)
  88. parking_credit_card_agencies_spotID_error_dao_.DeleteAll();
  89. // サイトごとにコントローラーを用意する。
  90. MakeConttollers();
  91. // 各コントローラーを起動する。
  92. foreach (var web_controller in web_controller_list_) {
  93. var ret = HandleWebController(web_controller);
  94. if (ret == Code.ResultCode.NG) {
  95. logger_.Error($"処理失敗 {web_controller.GetCreditAgent().ToString()}");
  96. returnable = "処理失敗";
  97. }
  98. }
  99. // ブラウザの終了
  100. if (driver_ != null) {
  101. driver_.Quit();
  102. }
  103. // 終了
  104. logger_.Info("処理成功");
  105. return returnable;
  106. }
  107. private void MakeConttollers() {
  108. driver_ = DriverFactory.GetDriver();
  109. // CREVAS
  110. {
  111. var controller = new DaitoController(driver_);
  112. var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  113. controller.SetParkingDic(dic);
  114. web_controller_list_.Add(controller);
  115. credit_datastore_map_.Add(controller.GetCreditAgent(), daito_credit_store_);
  116. qr_datastore_map_.Add(controller.GetCreditAgent(), daito_qr_store_);
  117. }
  118. // Zeus
  119. {
  120. var controller = new ZeusController(driver_);
  121. var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  122. controller.SetParkingDic(dic);
  123. web_controller_list_.Add(controller);
  124. credit_datastore_map_.Add(controller.GetCreditAgent(), zeus_credit_store_);
  125. }
  126. // Itec
  127. {
  128. var controller = new ItecController(driver_);
  129. var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  130. controller.SetParkingDic(dic);
  131. web_controller_list_.Add(controller);
  132. credit_datastore_map_.Add(controller.GetCreditAgent(), itec_credit_store_);
  133. }
  134. // HelloTechno
  135. {
  136. var controller = new HelloTechnoController(driver_);
  137. var dic = parking_credit_card_agencies_spotID_dao_.GetDictionary(controller.GetCreditAgent());
  138. controller.SetParkingDic(dic);
  139. web_controller_list_.Add(controller);
  140. credit_datastore_map_.Add(controller.GetCreditAgent(), hello_techno_credit_store_);
  141. }
  142. }
  143. private Code.ResultCode HandleWebController(WebController web_controller) {
  144. Code.ResultCode result_code = Code.ResultCode.OK;
  145. try {
  146. // 各ダウンロードディレクトリをクリーンする。
  147. CreanDirectries();
  148. // カード会社を特定する。
  149. Code.CreditAgent agent = web_controller.GetCreditAgent();
  150. logger_.Info($"ダウンロード開始 対象:{agent}");
  151. // 履歴を参照する。
  152. var history = history_dao_.GetHistory(agent);
  153. // 履歴から取得範囲を特定する。
  154. (var from, var to) = GetFromTo(agent, history);
  155. logger_.Info($"取得範囲 {from.ToString("yyyy/MM/dd")} ~ {to.ToString("yyyy/MM/dd")}");
  156. // ログイン情報を取得
  157. var login_info = GetLoginInfo(agent);
  158. // ログインを開始
  159. result_code = web_controller.Login(login_info);
  160. if (result_code != Code.ResultCode.OK) {
  161. throw new Exception("ログイン失敗");
  162. }
  163. logger_.Info("ログイン成功");
  164. // ダウンロード開始
  165. result_code = web_controller.Download(from, to);
  166. if (result_code != Code.ResultCode.OK) {
  167. throw new Exception("ダウンロード失敗");
  168. }
  169. logger_.Info("ダウンロード成功");
  170. // ログアウト
  171. result_code = web_controller.Logout();
  172. if (result_code != Code.ResultCode.OK) {
  173. throw new Exception("ログアウト失敗");
  174. }
  175. logger_.Info("ログアウト成功");
  176. // ロード画面の表示
  177. var load_html_path = Path.GetFullPath(@"static\html\load.html");
  178. driver_.Navigate().GoToUrl($"file://{load_html_path}");
  179. // データリストの取得
  180. // 取得に失敗したものはエラーリストとして登録する。
  181. bool list_get_success = true;
  182. List<CreditCSVData> credit_info_list = null;
  183. List<QRCSVData> qr_info_list = null;
  184. try {
  185. credit_info_list = web_controller.GetCreditCSVDataList();
  186. } catch (SpotNameNotMatchException e) {
  187. list_get_success = false;
  188. parking_credit_card_agencies_spotID_error_dao_.Save(e.GetList());
  189. }
  190. try {
  191. qr_info_list = web_controller.GetQRCSVDataList();
  192. } catch (SpotNameNotMatchException e) {
  193. list_get_success = false;
  194. parking_credit_card_agencies_spotID_error_dao_.Save(e.GetList());
  195. }
  196. if (!list_get_success) {
  197. throw new Exception("データリスト取得失敗");
  198. }
  199. // データ保存
  200. int delete_count_credit = 0;
  201. int delete_count_qr = 0;
  202. transaction_ = conn_.BeginTransaction();
  203. // クレジット
  204. if (0 < credit_info_list.Count) {
  205. ShowTotalCount(credit_info_list.Count);
  206. var store = credit_datastore_map_[agent];
  207. delete_count_credit = store.Delete(from, to);
  208. var current_count = 0;
  209. ShowCurrentCount(current_count);
  210. var chunk_data_list = credit_info_list.Select((CreditCSVData data, int index) => new { data, index })
  211. .GroupBy(x => x.index / save_chunk_num_)
  212. .Select(g => g.Select(r => r.data));
  213. foreach (var data_list in chunk_data_list) {
  214. var list = data_list.ToList();
  215. store.Save(list);
  216. current_count += list.Count;
  217. ShowCurrentCount(current_count);
  218. }
  219. }
  220. // QR
  221. if (0 < qr_info_list.Count) {
  222. ShowTotalCount(qr_info_list.Count);
  223. var store = qr_datastore_map_[agent];
  224. delete_count_qr = store.Delete(from, to);
  225. var current_count = 0;
  226. ShowCurrentCount(current_count);
  227. var chunk_data_list = qr_info_list.Select((QRCSVData data, int index) => new { data, index })
  228. .GroupBy(x => x.index / save_chunk_num_)
  229. .Select(g => g.Select(r => r.data));
  230. foreach (var data_list in chunk_data_list) {
  231. var list = data_list.ToList();
  232. store.Save(list);
  233. current_count += list.Count;
  234. ShowCurrentCount(current_count);
  235. }
  236. }
  237. // コミット処理
  238. transaction_.Commit();
  239. logger_.Info($"削除件数 CREDIT:{delete_count_credit}");
  240. logger_.Info($"削除件数 QR: {delete_count_qr}");
  241. logger_.Info($"登録件数 CREDIT:{credit_info_list.Count}");
  242. logger_.Info($"登録件数 QR :{qr_info_list.Count}");
  243. web_controller.Archive(GetArchiveFilename(agent, DateTime.Now));
  244. // 履歴の登録
  245. history_dao_.Save(agent, DateTime.Now);
  246. logger_.Info($"ダウンロード終了 対象:{agent}");
  247. } catch (Exception e) {
  248. // ロールバック処理
  249. logger_.Error(e.Message);
  250. if (transaction_ != null) {
  251. transaction_.Rollback();
  252. }
  253. transaction_ = null;
  254. return Code.ResultCode.NG;
  255. }
  256. transaction_ = null;
  257. return Code.ResultCode.OK;
  258. }
  259. /// <summary>
  260. /// データ取得範囲を特定する。<br/>
  261. /// </summary>
  262. /// <param name="history"></param>
  263. /// <returns></returns>
  264. private (DateTime, DateTime) GetFromTo(Code.CreditAgent agent, List<History> history) {
  265. DateTime from, to;
  266. if (agent == Code.CreditAgent.Zeus) {
  267. // Zeusの場合は、データが修正されるケースがあるため
  268. // 期間を制御する
  269. // 前回取得日から1か月遡る。
  270. // var prev_date = DateTime.Now.AddMonths(-1);
  271. // from = new DateTime(prev_date.Year, prev_date.Month, 1);
  272. // to = from.AddMonths(1).AddDays(-1);
  273. var now_date = DateTime.Now.Date;
  274. from = now_date.AddMonths(-1);
  275. to = now_date;
  276. } else {
  277. var now_date = DateTime.Now.Date;
  278. from = now_date.AddDays(-20);
  279. to = now_date;
  280. if (history.Count != 0) {
  281. var prev_date = history[0].date;
  282. if (from < prev_date) {
  283. from = prev_date.Date;
  284. }
  285. }
  286. }
  287. return (from, to);
  288. }
  289. /// <summary>
  290. /// コンフィグファイルよりログイン情報を取得する。
  291. /// </summary>
  292. /// <param name="agent"></param>
  293. /// <returns></returns>
  294. private LoginInfo GetLoginInfo(Code.CreditAgent agent) {
  295. var login_info = new LoginInfo();
  296. String sesction = $"LOGIN_INFO_{agent.ToString()}";
  297. login_info.user_name = config_.Read(sesction, "user");
  298. if (login_info.user_name.Length == 0) {
  299. throw new Exception($"ログイン情報不足 host {agent.ToString()}");
  300. }
  301. login_info.password = config_.Read(sesction, "password");
  302. if (login_info.password.Length == 0) {
  303. throw new Exception($"ログイン情報不足 password {agent.ToString()}");
  304. }
  305. return login_info;
  306. }
  307. private String GetArchiveFilename(Code.CreditAgent agent, DateTime now) {
  308. return $"{agent}_{now.ToString("yyyyMMddHHmmss")}.zip";
  309. }
  310. private void CreanDirectries() {
  311. var dir_download = new DirectoryInfo(DriverFactory.GetDownloadDir());
  312. foreach (var file in dir_download.GetFiles()) {
  313. file.Delete();
  314. }
  315. var tmp_download = new DirectoryInfo(DriverFactory.GetTmpDownloadDir());
  316. foreach (var file in tmp_download.GetFiles()) {
  317. file.Delete();
  318. }
  319. }
  320. private void ShowTotalCount(int num) {
  321. driver_.ExecuteScript($"setTotal({num})");
  322. }
  323. private void ShowCurrentCount(int num) {
  324. driver_.ExecuteScript($"setCount({num})");
  325. }
  326. }
  327. }