Source code for ac_core.auth
from logging import getLogger
from typing import cast
from bs4 import BeautifulSoup
import bs4
from ac_core.constant import _SITE_URL
from ac_core.interfaces.HttpUtil import HttpUtilInterface
from ac_core.utils import HTML_PARSER
logger = getLogger(__name__)
[docs]def is_logged_in(http_util: HttpUtilInterface) -> bool:
"""This method will use ``http_util`` for login check by visit atcoder site and parse html
:param HttpUtilInterface http_util: a http instance, for example ``requests.session()``
:returns: if it is successful logged in.
:examples:
.. code-block::
from ac_core.auth import fetch_login, is_logged_in
import requests
h = requests.session()
#h = Helper(requests.session())
print(is_logged_in(h))
print(fetch_login(h, 'username', 'password'))
print(is_logged_in(h))
"""
html = http_util.get(f"{_SITE_URL}/home").text
soup = BeautifulSoup(html, HTML_PARSER)
dropdown_menus = soup.find_all('ul', class_="dropdown-menu")
found_user_link = False
for menu in dropdown_menus:
a_s = menu.find_all('a')
for a in a_s:
if a['href'].startswith('/users/'):
found_user_link = True
return found_user_link
[docs]def fetch_login(http_util: HttpUtilInterface, username: str, password: str) -> bool:
"""This method will use ``http_util`` for login request and :py:func:`is_logged_in()` for login check
:param http_util: a http instance, for example ``requests.session()``
:param username: AtCoder username
:param password: AtCoder password
:returns: if it is successful post and logged
:examples:
.. code-block::
from ac_core.auth import fetch_login, is_logged_in
import requests
h = requests.session()
#h = Helper(requests.session())
print(is_logged_in(h))
print(fetch_login(h, 'username', 'password'))
print(is_logged_in(h))
"""
try:
res = http_util.get(_SITE_URL + '/login')
soup = BeautifulSoup(res.text, HTML_PARSER)
csrf_token = cast(bs4.Tag, soup.find(attrs={'name': 'csrf_token'})).get('value')
post_data = {
'csrf_token': csrf_token,
'username': username,
'password': password,
}
http_util.post(url='https://atcoder.jp/login', data=post_data)
except Exception as e:
logger.exception(e)
return False
return is_logged_in(http_util)
class InvalidSessionError(Exception):
"""
:meta private:
"""
# not use, hide in doc now
DEFAULT_MESSAGE = "Your login session is invalid. please relogin."
def __init__(self, message: str = DEFAULT_MESSAGE) -> None:
super().__init__(message)
# TODO logout support