﻿#!/usr/bin/env python
# coding: utf-8

from dateutil.relativedelta import relativedelta
import datetime
import os
import csv

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoSuchFrameException
from selenium.common.exceptions import NoSuchWindowException
from selenium.common.exceptions import NoSuchAttributeException
from selenium.common.exceptions import NoAlertPresentException
from selenium.common.exceptions import ElementNotVisibleException
from selenium.common.exceptions import ElementNotSelectableException
from selenium.common.exceptions import TimeoutException

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from time import sleep
from random import randint

USER_AGENTS = [
 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
 "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
 "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
 "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
 "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
 "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
 "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
 "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
 "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
 "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
]
random_agent = USER_AGENTS[randint(0, len(USER_AGENTS)-1)]

MUFG_TOP_URL = 'https://entry11.bk.mufg.jp/ibg/dfw/APLIN/loginib/login?_TRANID=AA000_001'
INFORMATION_TITLE = 'お知らせ - 三菱東京ＵＦＪ銀行'
# MUFG_ID&Pass
ACCOUNT_ID = os.environ['ACCOUNT_ID']
IB_PASSWORD = os.environ['IB_PASSWORD']
caps = DesiredCapabilities.PHANTOMJS
caps["phantomjs.page.settings.userAgent"] = random_agent

##driver = webdriver.PhantomJS( executable_path='./phantomjs' , desired_capabilities=caps)

Options = webdriver.FirefoxOptions()
# ヘッドレス化
Options.headless = True
# 必須
Options.add_argument('--no-sandbox')
Options.add_argument('--disable-gpu')
# エラーの許容
Options.add_argument('--ignore-certificate-errors')
Options.add_argument('--allow-running-insecure-content')
#####Options.add_argument('--disable-web-security')
# headless では不要そうな機能を除外
#####Options.add_argument('--disable-desktop-notifications')
#####Options.add_argument("--disable-extensions")
# UA設定 （なくてもいい）
Options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0')
# 言語 (なくてもいいが言語によって表示されるページが変わる可能性があるので念のため)
Options.add_argument('--lang=ja')
# 画像を読み込まないで軽くする
Options.add_argument('--blink-settings=imagesEnabled=false')

log_path = os.path.join(os.path.dirname(__file__), 'geckodriver.log')
driver = webdriver.Firefox(  executable_path='./geckodriver', options=Options, service_log_path=log_path)
driver.implicitly_wait(3)

def login(account_id: str, ib_password: str):
	global str_error
	str_error = None
	for x in range(0, 5):  # try 4 times
		try:
			error_num = 0
			## r = 1/0
			##print("====10===")
			driver.get(MUFG_TOP_URL)
			sleep(3)
			##print("====11===")
			error_num = 1000
			#driver.find_element_by_id('tx-contract-number').send_keys(account_id)
			number_input = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "tx-contract-number")))
			number_input.send_keys(account_id)
			##print("====12===")
			error_num = 10000
			#driver.find_element_by_id('tx-ib-password').send_keys(ib_password)
			# 等待密码输入框可见并可交互
			password_input = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "tx-ib-password")))
			password_input.send_keys(ib_password)
			##print("====13===")
			#driver.find_element_by_xpath('//img[@alt="ログイン"]').click()
			error_num = 100000
			## driver.find_element_by_xpath('//button[@class="gonext"]').click()
			element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//button[@class="gonext"]')))
			element.location_once_scrolled_into_view
			element.click()
			##print("====14===")
			error_num = 0
		except NoSuchElementException as ex:
			str_error  = ex
			error_num += 1
		except NoSuchFrameException as ex:
			str_error  = ex
			error_num += 2
		except NoSuchWindowException as ex:
			str_error  = ex
			error_num += 3
		except NoSuchAttributeException as ex:
			str_error  = ex
			error_num += 4
		except NoAlertPresentException as ex:
			str_error  = ex
			error_num += 5
		except ElementNotVisibleException as ex:
			str_error  = ex
			error_num += 6
		except ElementNotSelectableException as ex:
			str_error  = ex
			error_num += 7
		except TimeoutException as ex:
			str_error  = ex
			error_num += 8
		except Exception as ex:
			str_error  = ex
			error_num += 99
		if error_num>0:
			if x == 0:
				dataline = '------------------{}----------------'.format(datetime.datetime.now().strftime('%Y-%m-%d  %H:%M:%S'))
				print(dataline)
			print("{}{}".format("login error_num=", error_num))
			##driver.navigate().refresh();
			sleep(2)  # wait for 2 seconds before trying to fetch the data again
			if x == 4:
				dataline = '------------------{}----------------'.format(datetime.datetime.now().strftime('%Y-%m-%d  %H:%M:%S'))
				
				error_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'error.txt')
				fp_error= open(error_path, "w", encoding="utf-8")
				fp_error.write("{}:{};{}{}".format("login error_num", error_num,str_error,'\n'))
				###fp_error.write(str_error.message + ':'  + str_error.args + '\n')
				###fp_error.write( err.args + '\n')
				fp_error.write(dataline + '\n')
				fp_error.flush()
				fp_error.close()
				status_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'status.txt')
				status_book = open(status_path, "w", encoding="utf-8")
				status_book.write(dataline + '\n')
				status_book.write("ng" + '\n' )
				status_book.flush()
				status_book.close()
				exit()
		else:
			break


def logout():
	# <li class="logout"><a href="#" onClick="JavaScript:logoutFromAD001(); return false;">ログアウト</a></li>
	#driver.find_element_by_link_text('ログアウト').click()
	button = driver.find_element_by_xpath("//button[contains(text(), 'ログアウト')]")
	button.click()  # 执行按钮点击操作


def read_information():
	"""
	お知らせがある場合は既読にします
	:return:
	"""
	while True:
		if not driver.title == INFORMATION_TITLE:
			return
		information = driver.find_element_by_xpath(
			'//table[@class="data"]/tbody/tr')
		information.find_element_by_name('hyouzi').click()
		driver.find_element_by_xpath('//img[@alt="トップページへ"]').click()


def select_selectbox_value(element_name: str, value: str):
	"""
	セレクトボックスの値を選択します
	:param element_name:
	:param value:
	:return:
	"""
	selectbox = Select(driver.find_element_by_name(element_name))
	#print(str(value))
	selectbox.select_by_visible_text(str(value))


def select_time_period(_from: datetime, _to: datetime):
	"""
	指定した表示期間を選択します
	:param _from:
	:param _to:
	:return:
	"""

	wait = WebDriverWait(driver, 30)
	wait.until(ec.presence_of_element_located((By.ID, 'appoint')))

	driver.find_element_by_id('appoint').click()
	# driver.find_element_by_name('SHOUKAIKIKAN_RADIO').click()

	select_selectbox_value('SHOUKAIKIKAN_FROM_Y', str(_from.year))
	select_selectbox_value('SHOUKAIKIKAN_FROM_M', str(_from.month))
	select_selectbox_value('SHOUKAIKIKAN_FROM_D', str(_from.day))
	select_selectbox_value('SHOUKAIKIKAN_TO_Y', str(_to.year))
	select_selectbox_value('SHOUKAIKIKAN_TO_M', str(_to.month))
	select_selectbox_value('SHOUKAIKIKAN_TO_D', str(_to.day))


def show_details(_fp_list, _fp_book, _last: str,  _dataline: str):
	#banking_list = driver.find_elements_by_xpath( '//table[@class="data memo yen_nyushutsukin_003"]/tbody/tr')
	banking_list = driver.find_elements_by_xpath( '//table[@class="add-tbl-01"]/tbody/tr')

	flg = 0
	lastflg = 0
	year=""
	for banking in banking_list:
		detail = banking.find_elements_by_tag_name('td')
		str_date=detail[0].text
		if str_date.endswith("年"):
			year = str_date[:4]
			#print('year:'+ year)
			#YYYY = datetime.datetime.strptime(str_date.replace('\n', ''), '%Y年')
			#year = str_date[:4]
		else:
			#payment = in_or_out_payment(detail[1].text, detail[2].text)
			_date= year + '-' + str_date.replace('\n', '').replace('/', '-')
			date=datetime.datetime.strptime(_date, '%Y-%m-%d')
			content = detail[3].text
			conlist = content.split("　")
			cont1=conlist[0]
			del conlist[0]
			cont2=''.join(conlist)
			total = to_number(detail[4].text)
			pay = to_number(detail[1].text)
			income = to_number(detail[2].text)
			line = '{}\t{}\t{}\t{}\t{}\t{}'.format(date.strftime('%Y-%m-%d'),cont1, cont2, pay, income , total )
			#line = '{}\t{}\t{}\t{}\t{}\t{}'.format(date,cont1, cont2, pay, income , total )
			_fp_list.write(line + '\n')
			print(line)
			
			if flg == 1:
				if lastflg == 0:
					#print(dataline)
					_fp_book.write(_dataline + '\n')
				_fp_book.write(line + '\n')
				lastflg = flg
			else:
				lastflg = flg
				if _last == '':
					flg=1
				if _last == line + '\n':
					flg=1
	
	try:
		driver.find_element_by_xpath('//a/img[@alt="新しい明細"]').click()
	except NoSuchElementException:
		return
	else:
		# 例外がない(=次のページがある)から次のページへ
		show_details()


def to_number(yen: str) -> int:
	"""
	xxx,xxx,xxx円からカンマと「円」を削除します
	:param yen:
	:return: int:
	"""
	if yen == '':
		return ''
	return int(yen.replace(',', '').replace('円', ''))


def in_or_out_payment(_out: str, _in: str) -> int:
	"""
	入出金の判定を行います
	:param _out:
	:param _in:
	:return:
	"""
	if not _out == '':
		# 出金
		return to_number(_out) * -1
	# 入金
	return to_number(_in)


def main(_from: datetime, _to: datetime):
	global str_error
	try:
		#account_id = os.environ['ACCOUNT_ID']
		#ib_password = os.environ['IB_PASSWORD']
		account_id = ACCOUNT_ID
		ib_password = IB_PASSWORD

		str_error = None
		login(account_id, ib_password)
		
		for x in range(0, 5):  # try 4 times
			try:
				##driver.find_element_by_link_text('入出金明細').click()
				##driver.find_element_by_xpath('//div[@class="detail ng-tns-c16-0"]').click()
				element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="detail ng-tns-c16-0"]')))
				element.location_once_scrolled_into_view
				## element.click()
				element2 = driver.find_element_by_xpath("//div[@class='navigation-nav nav-right']")
				driver.execute_script("arguments[0].style.visibility='hidden'", element2)
				try:
					element3 = driver.find_element_by_xpath("//div[@class='navigation']")
					driver.execute_script("arguments[0].style.visibility='hidden'", element3)
				except NoSuchElementException:
					str_error = None
				# 定位到被遮挡的元素
				# 定位到被遮挡的元素
				element = driver.find_element_by_class_name("detail")
				element.click()


				# 模拟鼠标移动到元素上并点击
				#actions = ActionChains(driver)
				#actions.move_to_element(element).click().perform()
				str_error = None
				error_num = 0
			except NoSuchElementException as ex:
				str_error  = ex
				error_num = 1
			except NoSuchFrameException as ex:
				str_error  = ex
				error_num = 2
			except NoSuchWindowException as ex:
				str_error  = ex
				error_num = 3
			except NoSuchAttributeException as ex:
				str_error  = ex
				error_num = 4
			except NoAlertPresentException as ex:
				str_error  = ex
				error_num = 5
			except ElementNotVisibleException as ex:
				str_error  = ex
				error_num = 6
			except ElementNotSelectableException as ex:
				str_error  = ex
				error_num = 7
			except TimeoutException as ex:
				str_error  = ex
				error_num = 8
			except Exception as ex:
				str_error  = ex
				error_num = 99
				pass
			if error_num>0:
				print("{}{}".format("main error_num=", error_num))
				##driver.navigate().refresh();
				if x == 4:
					dataline = '------------------{}----------------'.format(datetime.datetime.now().strftime('%Y-%m-%d  %H:%M:%S'))
					print(dataline)
					error_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'error.txt')
					fp_error= open(error_path, "w", encoding="utf-8")
					fp_error.write(dataline + '\n')
					fp_error.write("{}:{};{}{}".format("login error_num", error_num,str_error,'\n'))
					fp_error.flush()
					fp_error.close()
					status_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'status.txt')
					status_book = open(status_path, "w", encoding="utf-8")
					status_book.write(dataline + '\n')
					status_book.write("ng" + '\n' )
					status_book.flush()
					status_book.close()
					exit()
			else:
				break


		# お知らせ画面がある場合は既読にする
		read_information()
		
		## WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="w40"]/p/fw-money/span[@class="plusClass"]')))	
		## WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="main__content"]/div[@class="bg-gray"]/div[@class="add-lyt-01"]/div[@class="w40"]/p/fw-money/span[@class="plusClass"]')))	
		WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="main__content"]/div[@class="bg-gray"]')))	

		# 残高を取得
		#total = driver.find_element_by_id('setAmountDisplay')
		#total = driver.find_element_by_xpath('//td[@class="number"]/strong')
		#total = driver.find_element_by_xpath('//div[@class="w40"]/p/fw-money/span[@class="plusClass"]')
		##total = driver.find_element_by_xpath('//div[@class="main__content"]/div[@class="bg-gray"]/div[@class="add-lyt-01"]/div[@class="w40"]/p/fw-money/span[@class="plusClass"]')
		total = driver.find_element_by_xpath('//div[@class="main__content"]/div[@class="bg-gray"]/div[@class="add-lyt-01"]/div[@class="w40"]/p/fw-money')
		# total = driver.find_element_by_xpath('//fw-money/span[@class="plusClass"]')
		print(total.text )
		total_amount = to_number(total.text)
		##total = driver.find_element_by_id('account')
		##total_amount = to_number(total.text)

		print('{:,d}円'.format(total_amount))

		##driver.find_element_by_xpath('//img[@alt="入出金明細をみる"]').click()

		# 期間を指定する
		# select_time_period(_from, _to)a

		# driver.find_element_by_xpath('//img[@alt="照会"]').click()
		flist_path ='{}/{}'.format( os.environ['BKLIST_PATH'], os.environ['BKLIST_NAME'])
		fbook_path ='{}/{}'.format( os.environ['BKLIST_PATH'], os.environ['BKBOOK_NAME'])
		
		targetLine = ""
		if os.path.isfile(fbook_path):
			fcheck = open(fbook_path, "r", encoding="utf-8")
			while 1:
				mLine = fcheck.readline();
				if not mLine:
					break;
				targetLine = mLine;
			fcheck.close()
		fp_list = open(flist_path, "a", encoding="utf-8")
		fp_book = open(fbook_path, "a", encoding="utf-8")
		
		dataline = '------------------{}----------------'.format(datetime.datetime.now().strftime('%Y-%m-%d  %H:%M:%S'))
		print(dataline)
		fp_list.write(dataline + '\n' )
		show_details(fp_list, fp_book, targetLine, dataline)
		fp_book.flush()
		fp_book.close()
		
		fp_list.flush()
		fp_list.close()
		##driver.find_element_by_xpath('//img[@alt="明細をダウンロード"]').click()
		##
		##select_time_period(_from, _to)
		##driver.find_element_by_xpath('//img[@alt="ダウンロード（CSV形式）"]').click

		logout()
		status_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'status.txt')
		status_book = open(status_path, "w", encoding="utf-8")
		status_book.write(dataline + '\n')
		status_book.write("ok" + '\n' )
		status_book.flush()
		status_book.close()
	finally:
		driver.close()

if __name__ == '__main__':
	td_1m =relativedelta(months=1) 
	end = datetime.datetime.now()
	tmp_start = end - td_1m
	start = datetime.datetime(year=tmp_start.year, month=tmp_start.month, day=1)
	main(start, end)
