login/logout mostly working.
parent
9c2599d954
commit
81418f3d2f
116
bot_z/bot_z.py
116
bot_z/bot_z.py
|
@ -1,7 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""Main module."""
|
||||
"""
|
||||
Operator is the main object that interacts with the foreign
|
||||
service. It exposes methods to login, logout and check in and out.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
|
@ -15,10 +19,12 @@ from selenium.common.exceptions import WebDriverException, NoSuchElementExceptio
|
|||
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
level=os.environ.get('BOTZ_LOGLEVEL', logging.INFO),
|
||||
format='%(levelname)s: [%(name)s] -> %(message)s'
|
||||
)
|
||||
|
||||
m_logger = logging.getLogger(__name__)
|
||||
m_logger.debug("Init at debug")
|
||||
|
||||
def safely(f: T.Callable) -> T.Callable:
|
||||
def _protection(self, *args, **kwargs):
|
||||
|
@ -30,11 +36,43 @@ def safely(f: T.Callable) -> T.Callable:
|
|||
return _protection
|
||||
|
||||
|
||||
def _is_present(driver: wd.Firefox, xpath: str) -> bool:
|
||||
try:
|
||||
driver.find_element_by_xpath(xpath)
|
||||
return True
|
||||
except NoSuchElementException:
|
||||
return False
|
||||
|
||||
|
||||
def is_present(driver: wd.Firefox,
|
||||
xpath: str,
|
||||
timeout: T.Optional[timedelta]=None
|
||||
) -> bool:
|
||||
"""
|
||||
Helper function. If an element is present in the DOM tree,
|
||||
returns true. False otherwise.
|
||||
"""
|
||||
if timeout is None:
|
||||
return _is_present(driver, xpath)
|
||||
|
||||
_now = datetime.now()
|
||||
_elapsed = timedelta(seconds=0)
|
||||
while _elapsed < timeout:
|
||||
m_logger.debug("Not yet present: %s", xpath)
|
||||
if _is_present(driver, xpath):
|
||||
m_logger.debug("Present: %s", xpath)
|
||||
return True
|
||||
time.sleep(0.5)
|
||||
_elapsed = datetime.now() - _now
|
||||
return False
|
||||
|
||||
|
||||
class Operator(wd.Firefox):
|
||||
def __init__(
|
||||
self,
|
||||
base_uri: str,
|
||||
name: str = None,
|
||||
timeout: int=20,
|
||||
proxy: T.Optional[T.Tuple[str, int]] = None,
|
||||
headless: bool = True,
|
||||
debug: bool = False,
|
||||
|
@ -53,6 +91,7 @@ class Operator(wd.Firefox):
|
|||
|
||||
self.debug = debug
|
||||
self.base_uri = base_uri
|
||||
self.timeout = timedelta(seconds=timeout)
|
||||
|
||||
if proxy:
|
||||
self.profile.set_preference('network.proxy.type', 1)
|
||||
|
@ -72,15 +111,29 @@ class Operator(wd.Firefox):
|
|||
self._checked_in = False
|
||||
|
||||
@safely
|
||||
def do_login(self, user: str, password: str) -> None:
|
||||
def login(self, user: str, password: str, force: bool=False) -> None:
|
||||
"""
|
||||
Do the login and proceed.
|
||||
"""
|
||||
if self._logged_in:
|
||||
self.logger.warning("Already logged in: %s", user)
|
||||
if not force:
|
||||
return
|
||||
self.logger.info("Forcing login: %s", user)
|
||||
# Retrieve login page
|
||||
#self.get('{}/jsp/login.jsp'.format(self.base_uri))
|
||||
self.get(self.base_uri)
|
||||
_correct_url = 'cpccchk' in self.current_url
|
||||
_now = datetime.now()
|
||||
_elapsed = timedelta(seconds=0)
|
||||
while not _correct_url:
|
||||
self.logger.debug("Not yet on login page: %s", self.current_url)
|
||||
time.sleep(0.5)
|
||||
_correct_url = 'cpccchk' in self.current_url
|
||||
_elapsed = datetime.now() - _now
|
||||
if _elapsed > self.timeout:
|
||||
break
|
||||
self.logger.debug("After login get: %s", self.current_url)
|
||||
time.sleep(3)
|
||||
time.sleep(1)
|
||||
# Username
|
||||
user_form = self.find_element_by_name('m_cUserName')
|
||||
# Password
|
||||
|
@ -91,24 +144,51 @@ class Operator(wd.Firefox):
|
|||
user_form.send_keys(user)
|
||||
pass_form.send_keys(password)
|
||||
do_it = True
|
||||
if self.debug:
|
||||
_do_it = input("Really do the login? [y/n]").lower()
|
||||
if self.debug and not force:
|
||||
_do_it = input("Really do the login? [y/n] ").lower()
|
||||
do_it = True if _do_it == "y" else False
|
||||
if do_it:
|
||||
self.logger.debug("Before clicking: %s", self.current_url)
|
||||
login_butt.submit()
|
||||
self.logger.debug("After clicking: %s", self.current_url)
|
||||
time.sleep(5)
|
||||
self.logger.debug("Login result: %s", self.title)
|
||||
if 'Routine window' in self.title:
|
||||
self.logger.debug("Reloading...")
|
||||
self.refresh()
|
||||
try:
|
||||
self.find_element_by_xpath('//input[contains(@value, "Accedi")]')
|
||||
# TODO: reckon a proper timeout mechanism
|
||||
# based on cookie expire time
|
||||
self.switch_to.alert.accept()
|
||||
if is_present(self, '//a[contains(@class, "imgMenu_ctrl")]', self.timeout):
|
||||
self._logged_in = True
|
||||
self.logger.info("Login success for user: %s", user)
|
||||
except NoSuchElementException as e:
|
||||
self.logger.error("Login failed: %s", e)
|
||||
else:
|
||||
self.logger.error("Login failed: %s", user)
|
||||
|
||||
@safely
|
||||
def logout(self, user: str, force: bool=False) -> None:
|
||||
"""
|
||||
Do the logout.
|
||||
"""
|
||||
if not self._logged_in:
|
||||
self.logger.warning("Not yet logged in for user: %s", user)
|
||||
if not force:
|
||||
return
|
||||
self.logger.info("Forcing logout: %s", user)
|
||||
# Find the Profile menu and open it
|
||||
profile_butt = self.find_element_by_xpath('//span[contains(@id, "imgNoPhotoLabel")]')
|
||||
profile_butt.click()
|
||||
time.sleep(1)
|
||||
# Find the logout button
|
||||
logout_butt = self.find_element_by_xpath('//input[@value="Logout user"]')
|
||||
logout_butt.click()
|
||||
if "jsp/usut_wapplogout_portlet.jsp" in self.current_url:
|
||||
self.logger.info("User successfully logged out: %s", user)
|
||||
else:
|
||||
self.logger.warning("Logout failed: %s", user)
|
||||
|
||||
def logged_in(self):
|
||||
"""
|
||||
Check if already logged in. Checks if page is '/jsp/home.jsp'
|
||||
and if login cookie is set (and not expired).
|
||||
"""
|
||||
pass
|
||||
|
||||
@safely
|
||||
def check_in(self, force: bool=False) -> None:
|
||||
|
@ -121,6 +201,8 @@ class Operator(wd.Firefox):
|
|||
self.logger.warn("Already logged in!")
|
||||
if not force:
|
||||
return
|
||||
enter_butt = self.find_element_by_xpath('//input[@value="Entrata"]')
|
||||
enter_butt.submit()
|
||||
# Click the check in button and change
|
||||
# self._checked_in state in case of success
|
||||
pass
|
||||
|
@ -136,9 +218,11 @@ class Operator(wd.Firefox):
|
|||
self.logger.warn("Not yet logged in!")
|
||||
if not force:
|
||||
return
|
||||
exit_butt = self.find_element_by_xpath('//input[@value="Uscita"]')
|
||||
exit_butt.submit()
|
||||
# Click the check in button and change
|
||||
# self._checked_in state in case of success
|
||||
pass
|
||||
|
||||
def __del__(self):
|
||||
def __del__(self) -> None:
|
||||
self.quit()
|
||||
|
|
Loading…
Reference in New Issue