Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format the code #98

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions .idea/aws.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions .idea/doctoshotgun.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

104 changes: 58 additions & 46 deletions doctoshotgun.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
try:
from playsound import playsound as _playsound, PlaysoundException


def playsound(*args):
try:
return _playsound(*args)
Expand Down Expand Up @@ -107,7 +108,7 @@ def get_next_page(self):
# JavaScript:
# var t = (e = r()(e)).data("u")
# , n = atob(t.replace(/\s/g, '').split('').reverse().join(''));

import base64
href = base64.urlsafe_b64decode(''.join(span.attrib['data-u'].split())[::-1]).decode()
query = dict(parse.parse_qsl(parse.urlsplit(href).query))
Expand All @@ -121,9 +122,10 @@ def get_next_page(self):

if 'page' in query:
return int(query['page'])

return None


class CenterResultPage(JsonPage):
pass

Expand Down Expand Up @@ -162,8 +164,8 @@ def get_agenda_ids(self, motive_id, practice_id=None):
agenda_ids = []
for a in self.doc['data']['agendas']:
if motive_id in a['visit_motive_ids'] and \
not a['booking_disabled'] and \
(not practice_id or a['practice_id'] == practice_id):
not a['booking_disabled'] and \
(not practice_id or a['practice_id'] == practice_id):
agenda_ids.append(str(a['id']))

return agenda_ids
Expand Down Expand Up @@ -250,7 +252,8 @@ def __init__(self, *args, **kwargs):
self.session.headers['sec-fetch-dest'] = 'document'
self.session.headers['sec-fetch-mode'] = 'navigate'
self.session.headers['sec-fetch-site'] = 'same-origin'
self.session.headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'
self.session.headers[
'User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'

self.patient = None

Expand All @@ -259,8 +262,9 @@ def do_login(self, code):
self.open(self.BASEURL + '/sessions/new')
except ServerError as e:
if e.response.status_code in [503] \
and 'text/html' in e.response.headers['Content-Type'] \
and ('cloudflare' in e.response.text or 'Checking your browser before accessing' in e .response.text):
and 'text/html' in e.response.headers['Content-Type'] \
and (
'cloudflare' in e.response.text or 'Checking your browser before accessing' in e.response.text):
log('Request blocked by CloudFlare', color='red')
if e.response.status_code in [520]:
log('Cloudflare is unable to connect to Doctolib server. Please retry later.', color='red')
Expand All @@ -279,7 +283,9 @@ def do_login(self, code):
print("Requesting 2fa code...")
if not code:
if not sys.__stdin__.isatty():
log("Auth Code input required, but no interactive terminal available. Please provide it via command line argument '--code'.", color='red')
log(
"Auth Code input required, but no interactive terminal available. Please provide it via command line argument '--code'.",
color='red')
return False
self.send_auth_code.go(
json={'two_factor_auth_method': 'email'}, method="POST")
Expand All @@ -299,12 +305,12 @@ def find_centers(self, where, motives=None, page=1):
for city in where:
try:
self.centers.go(where=city, params={
'ref_visit_motive_ids[]': motives, 'page': page})
'ref_visit_motive_ids[]': motives, 'page': page})
except ServerError as e:
if e.response.status_code in [503]:
if 'text/html' in e.response.headers['Content-Type'] \
and ('cloudflare' in e.response.text or
'Checking your browser before accessing' in e .response.text):
and ('cloudflare' in e.response.text or
'Checking your browser before accessing' in e.response.text):
log('Request blocked by CloudFlare', color='red')
return
if e.response.status_code in [520]:
Expand Down Expand Up @@ -359,7 +365,8 @@ def try_to_book(self, center, vaccine_list, start_date, end_date, only_second, o
motives_id = dict()
for vaccine in vaccine_list:
motives_id[vaccine] = self.page.find_motive(
r'.*({})'.format(vaccine), singleShot=(vaccine == self.vaccine_motives[self.KEY_JANSSEN] or only_second or only_third))
r'.*({})'.format(vaccine),
singleShot=(vaccine == self.vaccine_motives[self.KEY_JANSSEN] or only_second or only_third))

motives_id = dict((k, v)
for k, v in motives_id.items() if v is not None)
Expand All @@ -379,12 +386,14 @@ def try_to_book(self, center, vaccine_list, start_date, end_date, only_second, o
# do not filter to give a chance
agenda_ids = center_page.get_agenda_ids(motive_id)

if self.try_to_book_place(profile_id, motive_id, practice_id, agenda_ids, vac_name.lower(), start_date, end_date, only_second, only_third, dry_run):
if self.try_to_book_place(profile_id, motive_id, practice_id, agenda_ids, vac_name.lower(), start_date,
end_date, only_second, only_third, dry_run):
return True

return False

def try_to_book_place(self, profile_id, motive_id, practice_id, agenda_ids, vac_name, start_date, end_date, only_second, only_third, dry_run=False):
def try_to_book_place(self, profile_id, motive_id, practice_id, agenda_ids, vac_name, start_date, end_date,
only_second, only_third, dry_run=False):
date = start_date.strftime('%Y-%m-%d')
while date is not None:
self.availabilities.go(
Expand Down Expand Up @@ -435,9 +444,9 @@ def try_to_book_place(self, profile_id, motive_id, practice_id, agenda_ids, vac_
log(' ├╴ Best slot found: %s', parse_date(
slot_date_first).strftime('%c'))

appointment = {'profile_id': profile_id,
appointment = {'profile_id': profile_id,
'source_action': 'profile',
'start_date': slot_date_first,
'start_date': slot_date_first,
'visit_motive_ids': str(motive_id),
}

Expand Down Expand Up @@ -548,6 +557,33 @@ def try_to_book_place(self, profile_id, motive_id, practice_id, agenda_ids, vac_
return self.page.doc['confirmed']


class DoctolibFR(Doctolib):
BASEURL = 'https://www.doctolib.fr'
KEY_PFIZER = '6970'
KEY_PFIZER_SECOND = '6971'
KEY_PFIZER_THIRD = None
KEY_MODERNA = '7005'
KEY_MODERNA_SECOND = '7004'
KEY_MODERNA_THIRD = None
KEY_JANSSEN = '7945'
KEY_ASTRAZENECA = '7107'
KEY_ASTRAZENECA_SECOND = '7108'
vaccine_motives = {
KEY_PFIZER: 'Pfizer',
KEY_PFIZER_SECOND: '2de.*Pfizer',
KEY_PFIZER_THIRD: '3e.*Pfizer',
KEY_MODERNA: 'Moderna',
KEY_MODERNA_SECOND: '2de.*Moderna',
KEY_MODERNA_THIRD: '3e.*Moderna',
KEY_JANSSEN: 'Janssen',
KEY_ASTRAZENECA: 'AstraZeneca',
KEY_ASTRAZENECA_SECOND: '2de.*AstraZeneca',
}

centers = URL(r'/vaccination-covid-19/(?P<where>\w+)', CentersPage)
center = URL(r'/centre-de-sante/.*', CenterPage)


class DoctolibDE(Doctolib):
BASEURL = 'https://www.doctolib.de'
KEY_PFIZER = '6768'
Expand All @@ -574,33 +610,6 @@ class DoctolibDE(Doctolib):
center = URL(r'/praxis/.*', CenterPage)


class DoctolibFR(Doctolib):
BASEURL = 'https://www.doctolib.fr'
KEY_PFIZER = '6970'
KEY_PFIZER_SECOND = '6971'
KEY_PFIZER_THIRD = '8192'
KEY_MODERNA = '7005'
KEY_MODERNA_SECOND = '7004'
KEY_MODERNA_THIRD = '8193'
KEY_JANSSEN = '7945'
KEY_ASTRAZENECA = '7107'
KEY_ASTRAZENECA_SECOND = '7108'
vaccine_motives = {
KEY_PFIZER: 'Pfizer',
KEY_PFIZER_SECOND: '2de.*Pfizer',
KEY_PFIZER_THIRD: '3e.*Pfizer',
KEY_MODERNA: 'Moderna',
KEY_MODERNA_SECOND: '2de.*Moderna',
KEY_MODERNA_THIRD: '3e.*Moderna',
KEY_JANSSEN: 'Janssen',
KEY_ASTRAZENECA: 'AstraZeneca',
KEY_ASTRAZENECA_SECOND: '2de.*AstraZeneca',
}

centers = URL(r'/vaccination-covid-19/(?P<where>\w+)', CentersPage)
center = URL(r'/centre-de-sante/.*', CenterPage)


class Application:
@classmethod
def create_default_logger(cls):
Expand Down Expand Up @@ -688,7 +697,8 @@ def main(self, cli_args=None):

patients = docto.get_patients()
if len(patients) == 0:
print("It seems that you don't have any Patient registered in your Doctolib account. Please fill your Patient data on Doctolib Website.")
print(
"It seems that you don't have any Patient registered in your Doctolib account. Please fill your Patient data on Doctolib Website.")
return 1
if args.patient >= 0 and args.patient < len(patients):
docto.patient = patients[args.patient]
Expand Down Expand Up @@ -830,7 +840,8 @@ def main(self, cli_args=None):

log('Center %(name_with_title)s (%(city)s):' % center)

if docto.try_to_book(center, vaccine_list, start_date, end_date, args.only_second, args.only_third, args.dry_run):
if docto.try_to_book(center, vaccine_list, start_date, end_date, args.only_second, args.only_third,
args.dry_run):
log('')
log('💉 %s Congratulations.' %
colored('Booked!', 'green', attrs=('bold',)))
Expand All @@ -839,7 +850,8 @@ def main(self, cli_args=None):
sleep(SLEEP_INTERVAL_AFTER_CENTER)

log('')
log('No free slots found at selected centers. Trying another round in %s sec...', SLEEP_INTERVAL_AFTER_RUN)
log('No free slots found at selected centers. Trying another round in %s sec...',
SLEEP_INTERVAL_AFTER_RUN)
sleep(SLEEP_INTERVAL_AFTER_RUN)
except CityNotFound as e:
print('\n%s: City %s not found. Make sure you selected a city from the available countries.' % (
Expand Down