update elicense mod to make a reservation

This commit is contained in:
falsycat 2023-02-12 01:57:09 +09:00
parent 5c866c3b71
commit 727ab29d10
2 changed files with 77 additions and 25 deletions

View File

@ -36,7 +36,7 @@ class Handler:
self.app.reply(self.st, "accepted") self.app.reply(self.st, "accepted")
mod = self.app.mods["elicense"] mod = self.app.mods["elicense"]
mod.watch(self.st["id"], date, slots) mod.watch(date, slots, lambda: self.app.reply(self.st, "reservation made"))
class App: class App:

View File

@ -1,9 +1,10 @@
import datetime
import dateutil
import logging import logging
import json import json
import re
import requests import requests
from html.parser import HTMLParser
def init(CONFIG, logger): def init(CONFIG, logger):
logger.setLevel(logging.DEBUG) logger.setLevel(logging.DEBUG)
@ -15,12 +16,16 @@ class Mod:
self.URL = "https://www.e-license.jp/el25/pc/" self.URL = "https://www.e-license.jp/el25/pc/"
self.CONFIG = CONFIG self.CONFIG = CONFIG
self.logging = logging self.logging = logging
self.targets = [] self.targets = []
self.calender = None
self.ss = self.authenticate() self.ss = self.authenticate()
def cycle(self): def cycle(self):
if len(self.targets) == 0:
return
res = self.ss.post( res = self.ss.post(
url = self.URL+"p04a.action", url = self.URL+"p04a.action",
data = { data = {
@ -30,15 +35,46 @@ class Mod:
"b.schoolCd" : self.CONFIG["school"], "b.schoolCd" : self.CONFIG["school"],
}) })
res.encoding = "shift_jis" res.encoding = "shift_jis"
self.calender = Calender(res.text)
parser = ReservationListParser() now = datetime.datetime.utcnow() + datetime.timedelta(hours=9)
parser.feed(res.text) today = now.strftime("%Y%m%d")
return for target in self.targets:
for slot in target[1]:
begins = now.combine(now.date(), TIMETABLE[slot])
border = begins - datetime.timedelta(hours=2)
def watch(self, date, slots): if target[0] != today or now < border:
self.logging.debug("watch request accepted: {} {}".format(+date+slots)) if self.calender.checkAvailable(target[0], slot):
self.targets.append((date, slots)) self.make_reserve(target[0], slot)
target[2]()
break
self.targets = []
def watch(self, date, slots, cb):
self.logging.debug("watch request accepted, {} {}".format(date, slots))
self.targets.append((date, slots, cb))
def make_reserve(self, date, slot):
res = self.ss.post(
url = self.URL+"p03a.action",
data = {
"b.schoolCd" : self.CONFIG["school"],
"b.processCd" : "V",
"b.kamokuCd" : 0,
"b.instructorTypeCd" : 0,
"b.dateInformationType": date,
"b.infoPeriodNumber" : slot,
"b.carModelCd" : self.calender.carModel,
"b.instructorCd" : 0,
"b.page" : 1,
"b.groupCd" : self.calender.group,
})
res.encoding = "shift_jis"
self.calender = Calender(res.text)
self.logging.info("reservation made, {}:{}".format(date, slots))
def authenticate(self): def authenticate(self):
ss = requests.Session() ss = requests.Session()
@ -53,6 +89,8 @@ class Mod:
"b.kamokuCd" : "", "b.kamokuCd" : "",
"method:doLogin" : "ログイン".encode("shift_jis"), "method:doLogin" : "ログイン".encode("shift_jis"),
}) })
res.encoding = "shift_jis"
self.calender = Calender(res.text)
self.logging.info("authenticated") self.logging.info("authenticated")
return ss return ss
except Exception as e: except Exception as e:
@ -60,22 +98,36 @@ class Mod:
return None return None
class ReservationListParser(HTMLParser): class Calender:
path = [] def __init__(self, text):
m = re.search(RE_ERROR, text)
if m is None:
m = re.search(RE_ALERT, text)
if m is not None:
raise Exception(m[1])
def handle_starttag(self, tag, attrs): self.avails = re.findall(RE_AVAIL_SLOT, text)
self.path.append(tag)
c = [x[1] for x in attrs if x[0] == "class"] def checkAvailable(self, date, slot):
if len(c) == 0: for avail in self.avails:
return if avail[0] == date and avail[1] == str(slot):
return True
return False
if tag == "td":
print(c)
return
def handle_data(self, data): TIMETABLE = {
return 1: datetime.time( 9,20),
2: datetime.time(10,20),
3: datetime.time(11,20),
4: datetime.time(12,20),
5: datetime.time(14,10),
6: datetime.time(15,10),
7: datetime.time(16,10),
8: datetime.time(17,10),
9: datetime.time(18,10),
10: datetime.time(19,10),
}
def handle_endtag(self, tag): RE_ALERT = re.compile(r"window\.alert\('(.*)'\)")
self.path.pop() RE_ERROR = re.compile(r"<.*? class=\"errorTitle\">メッセージ<\/.*?>\s*<.*? class=\"errorDisp\">(.*?)<\/.*?>", re.MULTILINE)
RE_AVAIL_SLOT = re.compile(r"^\s*<a href=\"#\" onclick=\"sendContent\('(\d+)','(\d+)','V',document\.getElementById\('formId'\)\)\">$")