Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

475 lines
18KB

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