Compare commits

...

9 Commits

Author SHA1 Message Date
kinoshitakenta f9792b99e0
chore: add Beerware license 2025-08-18 14:05:10 +08:00
kinoshitakenta 42ca15bfbd
docs: updates README documentation
Updates a README file to describe the project, including instructions on how to configure and run the application, and explains the project's purpose.
2025-08-18 13:41:46 +08:00
kinoshitakenta 82fb61ec26
fix: prompt re-login on expired Selenium session to prevent crash 2025-07-03 17:06:25 +08:00
kinoshitakenta 982e70a4e4
docs: use straight quotes (') instead of typographic apostrophes (’)
Typographic apostrophes can lead to formatting or encoding issues in technical documents.
Straight quotes are preferred in source-controlled files to ensure consistency and portability.
2025-07-03 13:26:29 +08:00
kinoshitakenta e1ec580ce1
fix: missing import `ctypes` library 2025-07-03 10:29:12 +08:00
kinoshitakenta 5b87c86223
fix: skip handling alerts that are already closed
Avoids handling alerts that have already been dismissed at the time of operation.
2025-07-03 10:18:35 +08:00
kinoshitakenta 2c5ca3c3d3
docs: removes outdated `TODO.txt`
Removed TODO.txt as the mentioned feature has been implemented.
2025-06-20 14:50:27 +08:00
kinoshitakenta 86bd790f1c
feat: added the function to open the booking meeting room page 2025-06-20 14:30:33 +08:00
kinoshitakenta ccd5dee807
Merge branch 'env/migrate-to-uv' 2025-06-20 13:52:19 +08:00
6 changed files with 81 additions and 10 deletions

8
LICENSE Normal file
View File

@ -0,0 +1,8 @@
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <ybs0306748@gmail.com> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return Kinoshita Kenta
* ----------------------------------------------------------------------------
*/

View File

@ -1,7 +1,50 @@
# auto_login_EIP # auto_login_EIP
- 執行 太常要訂便當了,所以寫個自動登入 EIP 的東西
省的每次都要找 EIP 的網址是什麼
## env
* Python
* uv
* 剩下的 uv 會幫你裝
## repository structure
```text
./auto_login_EIP/
├── main.py # main file
├── config.toml # config file
├── utils/
├── pyproject.toml
├── .gitignore
└── README.md
```
## usage
### 配置
`config.toml` 設定好登入資訊,如果員工 ID 與密碼留空則會在登入時詢問你
專案路徑下有一個 `config.toml.example` 提供作為修改模板
### 執行
```shell ```shell
# uv run python main.py --config_path .\config.toml.example # uv run python main.py
``` ```
或指定 config 檔
```shell
# uv run python main.py --config_path .\YOUR_CONFIG.toml
```
---
如果要酷一點的話串個 Windows 工作排程器或 Linux crontab
這樣每天早上就會自動幫你把 EIP 開起來,就能當個認真的模範打工仔了
我要繼續去 coding ㄌ各位88

View File

@ -1,2 +0,0 @@
1. 過久沒登入,然後重登之後,要操作的頁面被關掉
2. 重新一個新指令時,把其他開啟的頁面全部關掉

View File

@ -4,10 +4,12 @@
__author__ = 'kinoshitakenta' __author__ = 'kinoshitakenta'
__email__ = "ybs0306748@gmail.com" __email__ = "ybs0306748@gmail.com"
import ctypes
import logging import logging
import os import os
from pathlib import Path from pathlib import Path
from selenium.common.exceptions import InvalidSessionIdException
from utils.cli import cli from utils.cli import cli
from utils.driver import get_driver from utils.driver import get_driver
from utils.EIP_action import ActionType, Action from utils.EIP_action import ActionType, Action
@ -51,6 +53,7 @@ def display_usage():
clear_screen() clear_screen()
for cmd, msg in get_usage(): for cmd, msg in get_usage():
print(f"{cmd}: {msg}") print(f"{cmd}: {msg}")
print()
def main(opt): def main(opt):
@ -62,11 +65,12 @@ def main(opt):
login_info = LoginInfo(config_path) login_info = LoginInfo(config_path)
driver = get_driver() driver = get_driver()
keep_login_status(driver, login_info)
action_agent = Action(driver) action_agent = Action(driver)
display_usage() display_usage()
keep_login_status(driver, login_info)
try: try:
while True: while True:
cmd = input("\nInput action code: ").strip() cmd = input("\nInput action code: ").strip()
@ -95,6 +99,9 @@ def main(opt):
if keep_login_status(driver, login_info): if keep_login_status(driver, login_info):
action_agent.run(action_code) action_agent.run(action_code)
except InvalidSessionIdException:
print("Session has expired, please re-login.")
except KeyboardInterrupt: except KeyboardInterrupt:
pass pass

View File

@ -14,6 +14,7 @@ class ActionType(IntEnum):
請假 = 1 請假 = 1
補卡 = 2 補卡 = 2
訂便當 = 3 訂便當 = 3
訂會議室 = 4
@classmethod @classmethod
def has_value(cls, value): def has_value(cls, value):
@ -25,7 +26,8 @@ class Action():
self.action_list = {ActionType.登入: self.__登入, self.action_list = {ActionType.登入: self.__登入,
ActionType.請假: self.__請假, ActionType.請假: self.__請假,
ActionType.補卡: self.__補卡, ActionType.補卡: self.__補卡,
ActionType.訂便當: self.__訂便當 ActionType.訂便當: self.__訂便當,
ActionType.訂會議室: self.__訂會議室
} }
self.driver = driver self.driver = driver
@ -143,3 +145,16 @@ class Action():
print("沒有尚未訂購的團購訂單") print("沒有尚未訂購的團購訂單")
self.driver.switch_to.default_content() self.driver.switch_to.default_content()
def __訂會議室(self):
"""訂會議室"""
self.driver.switch_to.frame(self.driver.find_element(By.ID, "main"))
all_meeting_room_tag = self.driver.find_element(By.ID, "WPPublicResource_TreeTagt0") # 會議室
ActionChains(self.driver).move_to_element(all_meeting_room_tag).move_to_element(all_meeting_room_tag).click(all_meeting_room_tag).perform()
Zhubei_tag = self.driver.find_element(By.ID, "WPPublicResource_TreeTagt1") # 竹北
ActionChains(self.driver).move_to_element(Zhubei_tag).move_to_element(Zhubei_tag).click(Zhubei_tag).perform()
meeting_room_500_tag = self.driver.find_element(By.ID, "WPPublicResource_TreeTagt2") # 500會議室
ActionChains(self.driver).move_to_element(meeting_room_500_tag).move_to_element(meeting_room_500_tag).click(meeting_room_500_tag).perform()

View File

@ -8,7 +8,7 @@ if sys.version_info >= (3, 11):
else: else:
import tomli as tomllib import tomli as tomllib
from selenium import webdriver from selenium import webdriver
from selenium.common.exceptions import NoAlertPresentException, UnexpectedAlertPresentException from selenium.common.exceptions import NoAlertPresentException, NoSuchWindowException, UnexpectedAlertPresentException
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select from selenium.webdriver.support.ui import Select
@ -49,7 +49,7 @@ def keep_login_status(driver: webdriver.Chrome, login_info: LoginInfo) -> bool:
""" """
Attempt to log into the CHI MotorWeb ERP system using the provided login information. Attempt to log into the CHI MotorWeb ERP system using the provided login information.
This function navigates to the login page, fills in the login form with the users credentials, This function navigates to the login page, fills in the login form with the user's credentials,
and attempts to log in. It handles unexpected alert pop-ups that indicate login failure, and attempts to log in. It handles unexpected alert pop-ups that indicate login failure,
and manages browser windows to ensure only the relevant page remains open. and manages browser windows to ensure only the relevant page remains open.
@ -101,7 +101,7 @@ def keep_login_status(driver: webdriver.Chrome, login_info: LoginInfo) -> bool:
print(f"Login error message: {alert.text}") print(f"Login error message: {alert.text}")
alert.accept() alert.accept()
return False # Skip remaining logic, login failed return False # Skip remaining logic, login failed
except NoAlertPresentException: except (NoAlertPresentException, NoSuchWindowException):
pass # No alert, proceed pass # No alert, proceed
time.sleep(2) time.sleep(2)
@ -119,7 +119,7 @@ def keep_login_status(driver: webdriver.Chrome, login_info: LoginInfo) -> bool:
print(f"Unexpected alert: {alert.text}") print(f"Unexpected alert: {alert.text}")
alert.accept() alert.accept()
continue continue
except NoAlertPresentException: except (NoAlertPresentException, NoSuchWindowException):
continue continue
if "CHI MotorWeb - " in title: if "CHI MotorWeb - " in title: