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.

488 lines
19KB

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