예제 #1
0
def test_center_to_centerdict():
    center = CenterInfo(
        "28", 
        "Delphine ROUSSEAU", 
        "https://patient.avecmondoc.com/fiche/structure/delphine-rousseau-159"
    )
    center.metadata = {
        "address": "21 Rue Nicole 28000 Chartres",
        "phone_number": "0033143987678",
        "business_hours": {
            "Lundi": "08:30-12:30 13:30-17:00",
            "Mardi": "08:30-12:30 13:30-17:00",
            "Mercredi": "08:30-12:30 13:30-17:00",
            "Jeudi": "08:30-12:30 13:30-17:00",
            "Vendredi": "08:30-12:30 13:30-17:00",
            "Samedi": "",
            "Dimanche": "",
            }
    }
    center.location = CenterLocation(1.481373, 48.447586, "Chartres", "28000")
    center.internal_id = "amd159"

    data_file = Path("tests/fixtures/avecmondoc/centerdict.json")
    data = json.loads(data_file.read_text(encoding='utf8'))
    
    assert avecmondoc.center_to_centerdict(center) == data
예제 #2
0
def test_get_last_scans():

    center_info1 = CenterInfo("01", "Centre 1", "https://example1.fr")
    center_info2 = CenterInfo("01", "Centre 2", "https://example2.fr")

    center_info2.prochain_rdv = "2021-06-06T00:00:00"

    centres_cherchés = [center_info1, center_info2]

    fake_now = dt.datetime(2021, 5, 5)
    with mock_datetime_now(fake_now):
        centres_cherchés = get_last_scans(centres_cherchés)

    assert centres_cherchés[0].last_scan_with_availabilities == None
    assert centres_cherchés[1].last_scan_with_availabilities == "2021-05-05T00:00:00"
예제 #3
0
def test_get_appointments():

    """get_appointments should return first available appointment date"""

    center_data = dict()
    center_data = json.load(io.open(TEST_CENTRE_INFO, "r", encoding="utf-8-sig"))
    center_info = CenterInfo.from_csv_data(center_data)

    # This center has availabilities and should return a date, non null appointment_count and vaccines
    request = ScraperRequest(
        "https://server.bimedoc.com/vmd/pharmacy-with-slots/9cf46288-0080-4a8d-8856-8e9998ced9f7?start_date=2021-08-10&end_date=2021-08-17",
        "2021-08-10",
        center_info,
        "Bimedoc9cf46288-0080-4a8d-8856-8e9998ced9f",
    )
    center_with_availability = bimedoc.BimedocSlots()
    slots = json.load(io.open(Path("tests", "fixtures", "bimedoc", "slots_available.json"), "r", encoding="utf-8-sig"))

    assert center_with_availability.get_appointments(request, slots_api=slots) == "2021-08-11T08:15:00Z"
    assert request.appointment_count == 133
    assert request.vaccine_type == [Vaccine.PFIZER]

    # This one should return no date, neither appointment_count nor vaccine.
    request = ScraperRequest(
        "https://server.bimedoc.com/vmd/pharmacy-with-slots/9cf46288-0080-4a8d-8856-8e9998ced9f7?start_date=2021-08-10&end_date=2021-08-17",
        "2021-08-10",
        center_info,
    )
    center_without_availability = bimedoc.BimedocSlots()
    slots = json.load(
        io.open(Path("tests", "fixtures", "bimedoc", "slots_unavailable.json"), "r", encoding="utf-8-sig")
    )
    assert center_without_availability.get_appointments(request, slots_api=slots) == None
    assert request.appointment_count == 0
    assert request.vaccine_type == None
예제 #4
0
def test_fetch():
    mesoigner.PLATFORM_ENABLED = True

    center_data = dict()
    center_data = json.load(
        io.open(TEST_CENTRE_INFO, "r", encoding="utf-8-sig"))

    center_info = CenterInfo.from_csv_data(center_data)

    # This center has availabilities and should return a date, non null appointment_count and vaccines
    request = ScraperRequest(
        "https://pharmacie-des-pyrenees.pharmaxv.fr/rendez-vous/vaccination/269-vaccination-covid-19/pre-inscription",
        "2021-06-16",
        center_info,
    )
    slots = json.load(
        io.open(Path("tests", "fixtures", "mesoigner", "slots_available.json"),
                "r",
                encoding="utf-8-sig"))

    def app(requested: httpx.Request) -> httpx.Response:
        assert "User-Agent" in requested.headers

        return httpx.Response(200, json=slots)

    client = httpx.Client(transport=httpx.MockTransport(app))

    center_with_availability = mesoigner.MesoignerSlots(client=client)

    response = center_with_availability.fetch(request)
    assert response == "2021-06-16T14:50:00+02:00"
예제 #5
0
def test_fetch():
    def app(requested: httpx.Request) -> httpx.Response:
        assert "User-Agent" in requested.headers
        return httpx.Response(responsecode, json=slots)

    bimedoc.PLATFORM_ENABLED = True

    center_data = dict()
    center_data = json.load(io.open(TEST_CENTRE_INFO, "r", encoding="utf-8-sig"))

    center_info = CenterInfo.from_csv_data(center_data)

    # This center has availabilities and should return a date, non null appointment_count and vaccines
    request = ScraperRequest(
        "https://server.bimedoc.com/vmd/pharmacy-with-slots/9cf46288-0080-4a8d-8856-8e9998ced9f7?start_date=2021-08-10&end_date=2021-08-17",
        "2021-08-10",
        center_info,
    )
    slots = json.load(io.open(Path("tests", "fixtures", "bimedoc", "slots_available.json"), "r", encoding="utf-8-sig"))

    # Response 200
    responsecode = 200
    client = httpx.Client(transport=httpx.MockTransport(app))
    center_with_availability = bimedoc.BimedocSlots(client=client)
    response = center_with_availability.fetch(request)
    assert response == "2021-08-11T08:15:00Z"

    # Response 403

    responsecode = 403
    client = httpx.Client(transport=httpx.MockTransport(app))
    center_with_availability = bimedoc.BimedocSlots(client=client)
    with pytest.raises(Exception):
        response = center_with_availability.fetch(request)
        assert response == None
예제 #6
0
def test_doctolib_next_slot():
    # Cas de repli : c'est surprenant, mais parfois la liste des dispos
    # est vide, mais il y a un champ 'next_slot' qui contient la date de
    # la prochaine visite, que l'on utilise dans ce cas.

    start_date = "2021-04-03"
    base_url = "https://partners.doctolib.fr/centre-de-vaccinations-internationales/ville1/centre1?pid=practice-165752&enable_cookies_consent=1"  # noqa
    center_info = CenterInfo(departement="07",
                             nom="Mon Super Centre",
                             url=base_url)
    scrap_request = ScraperRequest(base_url, start_date, center_info)

    def app(request: httpx.Request) -> httpx.Response:
        assert "User-Agent" in request.headers

        if request.url.path == "/booking/centre1.json":
            path = Path("tests", "fixtures", "doctolib",
                        "next-slot-booking.json")
            return httpx.Response(200,
                                  json=json.loads(
                                      path.read_text(encoding="utf-8")))

        assert request.url.path == "/availabilities.json"
        path = Path("tests", "fixtures", "doctolib",
                    "next-slot-availabilities.json")
        return httpx.Response(200,
                              json=json.loads(
                                  path.read_text(encoding="utf-8")))

    client = httpx.Client(transport=httpx.MockTransport(app))
    slots = DoctolibSlots(client=client, cooldown_interval=0)

    next_date = slots.fetch(scrap_request)
    # Next slot should not be used
    assert next_date is None
예제 #7
0
def test_doctolib_motive_categories():
    # Certains centres opèrent une distinction de motifs pour les professionnels de santé /
    # non professionnels de santé.
    # On doit gérer ces cas-là.

    start_date = "2021-04-03"
    base_url = "https://partners.doctolib.fr/centre-de-vaccinations-internationales/ville1/centre1?pid=practice-165752&enable_cookies_consent=1"  # noqa
    center_info = CenterInfo(departement="07",
                             nom="Mon Super Centre",
                             url=base_url)
    scrap_request = ScraperRequest(base_url, start_date, center_info)

    def app(request: httpx.Request) -> httpx.Response:
        assert "User-Agent" in request.headers

        if request.url.path == "/booking/centre1.json":
            path = Path("tests", "fixtures", "doctolib",
                        "category-booking.json")
            return httpx.Response(200,
                                  json=json.loads(
                                      path.read_text(encoding="utf-8")))

        assert request.url.path == "/availabilities.json"
        path = Path("tests", "fixtures", "doctolib",
                    "category-availabilities.json")
        return httpx.Response(200,
                              json=json.loads(
                                  path.read_text(encoding="utf-8")))

    client = httpx.Client(transport=httpx.MockTransport(app))
    slots = DoctolibSlots(client=client, cooldown_interval=0)

    next_date = slots.fetch(scrap_request)
    assert next_date == "2021-04-10"
예제 #8
0
def test_blocked_by_doctolib_par_availabilities():
    # Cas de base.

    start_date = "2021-04-03"
    base_url = "https://partners.doctolib.fr/centre-de-vaccinations-internationales/ville1/centre1?pid=practice-165752&enable_cookies_consent=1"  # noqa
    center_info = CenterInfo(departement="07",
                             nom="Mon Super Centre",
                             url=base_url)
    scrap_request = ScraperRequest(base_url, start_date, center_info)

    def app(request: httpx.Request) -> httpx.Response:
        assert "User-Agent" in request.headers

        if request.url.path == "/booking/centre1.json":
            path = Path("tests", "fixtures", "doctolib", "basic-booking.json")
            return httpx.Response(200,
                                  json=json.loads(
                                      path.read_text(encoding="utf-8")))

        return httpx.Response(403, text="Anti dDos")

    client = httpx.Client(transport=httpx.MockTransport(app))
    slots = DoctolibSlots(client=client, cooldown_interval=0)

    with pytest.raises(Blocked403):
        slots.fetch(scrap_request)
예제 #9
0
def test_fetch():
    def app(requested: httpx.Request) -> httpx.Response:
        assert "User-Agent" in requested.headers
        return httpx.Response(responsecode, json=slots)

    valwin.PLATFORM_ENABLED = True

    center_data = dict()
    center_data = json.load(io.open(TEST_CENTRE_INFO, "r", encoding="utf-8-sig"))

    center_info = CenterInfo.from_csv_data(center_data)

    # This center has availabilities and should return a date, non null appointment_count and vaccines
    request = ScraperRequest(
        "https://pharma-api.epharmacie.pro/global/api/meetings/v2/pharmabest75-plateau-lyon/slots",
        "2021-08-10",
        center_info,
    )
    slots = json.load(io.open(Path("tests", "fixtures", "valwin", "slots_available.json"), "r", encoding="utf-8-sig"))

    # Response 200
    responsecode = 200
    client = httpx.Client(transport=httpx.MockTransport(app))
    center_with_availability = valwin.Slots(client=client)
    response = center_with_availability.fetch(request)
    assert response == "2021-09-17T10:00:00"

    # Response 403

    responsecode = 403
    client = httpx.Client(transport=httpx.MockTransport(app))
    center_with_availability = valwin.Slots(client=client)
    with pytest.raises(Exception):
        response = center_with_availability.fetch(request)
        assert response == None
예제 #10
0
def test_no_center_data():
    path_centerinfo = Path("tests", "fixtures", "keldoc",
                           "cabinet-16913-centerinfo.json")
    centerinfo_1 = json.loads(path_centerinfo.read_text(encoding="utf-8"))

    center_info = CenterInfo.from_csv_data(centerinfo_1)

    center1_url = "https://www.keldoc.com/centre-hospitalier-regional/lorient-56100/groupe-hospitalier-bretagne-sud-lorient-hopital-du-scorff?specialty=144"
    request = ScraperRequest(center1_url,
                             "2020-04-04",
                             center_info=center_info)

    def app(request: httpx.Request) -> httpx.Response:
        if (request.url.path ==
                "/centre-hospitalier-regional/lorient-56100/groupe-hospitalier-bretagne-sud-lorient-hopital-du-scorff"
            ):
            return httpx.Response(
                302,
                headers={
                    "Location":
                    "https://vaccination-covid.keldoc.com/redirect/?dom=centre-hospitalier-regional&inst=lorient-56100&user=groupe-hospitalier-bretagne-sud-lorient-hopital-du-scorff&specialty=144 "
                },
            )
        if request.url.path == "/redirect/":
            return httpx.Response(200, json={})
        return httpx.Response(403, json={})

    keldoc.session = httpx.Client(transport=httpx.MockTransport(app))
    date = fetch_slots(request)
    assert not date
예제 #11
0
def test_center_info_next_availability():
    center = CenterInfo("Paris", "Centre 1", "https://.../centre")
    center.prochain_rdv = "TEST"
    data = center.handle_next_availability()
    assert not data
    center.prochain_rdv = "2021-06-06"
    data = center.handle_next_availability()
    assert center.prochain_rdv == "2021-06-06"
    center.prochain_rdv = "2042-04-10T00:00:00"
    data = center.handle_next_availability()
    assert center.prochain_rdv is None
예제 #12
0
def organization_to_center(organization) -> Optional[CenterInfo]:
    if organization is None:
        return None
    url = AVECMONDOC_CONF.get("patient_url", "").format(slug=organization.get("slug"))
    id = organization["id"]
    zip = organization["zipCode"]
    dept = departementUtils.to_departement_number(departementUtils.cp_to_insee(zip))
    reasons = organization["consultationReasons"]
    if reasons is None:
        logger.warning(f"no reasons found in organization")
        return None
    if get_valid_reasons(reasons) == []:
        return None
    center = CenterInfo(dept, organization["name"], url)
    location = CenterLocation(0, 0, organization["city"], organization["zipCode"])
    if organization.get("coordinates") is not None:
        location.longitude = organization["coordinates"].get("lng", 0.0)
        location.latitude = organization["coordinates"].get("lat", 0.0)
    center.metadata = {
        "address": organization["address"],
        "phone_number": organization["phone"],
    }
    center.location = location
    center.internal_id = f"amd{id}"
    if "schedules" not in organization:
        return center
    business_hours = {}
    for day, day_name in AVECMONDOC_SCRAPER.get("business_days", {}).items():
        value = ""
        if organization["schedules"][day]["enabled"]:
            value = " ".join(f'{sc["start"]}-{sc["end"]}' for sc in organization["schedules"][day]["schedules"])
        business_hours[day_name] = value
    center.metadata["business_hours"] = business_hours
    return center
예제 #13
0
def test_fetch_slots():
    def app(request: httpx.Request) -> httpx.Response:
        try:
            with open(Path("tests", "fixtures", "mapharma", "slots.json"),
                      encoding="utf8") as f:
                return httpx.Response(200, content=f.read())
        except IOError:
            return httpx.Response(404, content="")

    client = httpx.Client(transport=httpx.MockTransport(app))

    center_info = CenterInfo(
        departement="49",
        nom="Pharmacie Grand Maine",
        url="https://mapharma.net/49100-3?c=257&l=0",
        location=CenterLocation(longitude=-0.595416,
                                latitude=47.468377,
                                city="ANGERS",
                                cp="49100"),
        metadata={
            "address":
            "CENTRE CIAL GRAND MAINE RUE DU GRAND LAUNAY, 49100 ANGERS",
            "business_hours": {
                "lundi": "09:30 – 20:00",
                "mardi": "09:30 – 20:00",
                "mercredi": "09:30 – 20:00",
                "jeudi": "09:30 – 20:00",
                "vendredi": "09:30 – 20:00",
                "samedi": "09:30 – 20:00",
                "dimanche": "Fermé",
            },
        },
    )

    request = ScraperRequest(url="https://mapharma.net/97200?c=60&l=1",
                             start_date="2021-04-14",
                             center_info=center_info)
    first_availability = fetch_slots(request,
                                     creneau_q=DummyQueue(),
                                     client=client,
                                     opendata_file=TEST_OPEN_DATA_FILE)

    assert first_availability == "2021-04-19T17:15:00"

    # test campagne["total_libres"]: 0
    request = ScraperRequest("https://mapharma.net/88400?c=92&l=1",
                             "2021-04-14",
                             center_info=center_info)
    first_availability = fetch_slots(request,
                                     client=client,
                                     opendata_file=TEST_OPEN_DATA_FILE)
    assert first_availability == None
예제 #14
0
def test_fetch_slots():
    valwin.PLATFORM_ENABLED = False
    center_data = dict()
    center_data = json.load(io.open(TEST_CENTRE_INFO, "r", encoding="utf-8-sig"))
    center_info = CenterInfo.from_csv_data(center_data)

    request = ScraperRequest(
        "https://pharma-api.epharmacie.pro/global/api/meetings/v2/pharmabest75-plateau-lyon/slots",
        "2021-08-10",
        center_info,
    )
    response = valwin.fetch_slots(request)
    # On devrait trouver None puisque la plateforme est désactivée
    assert response == None
예제 #15
0
def test_fetch_slots():
    bimedoc.PLATFORM_ENABLED = False
    center_data = dict()
    center_data = json.load(io.open(TEST_CENTRE_INFO, "r", encoding="utf-8-sig"))
    center_info = CenterInfo.from_csv_data(center_data)

    request = ScraperRequest(
        "https://server.bimedoc.com/vmd/pharmacy-with-slots/9cf46288-0080-4a8d-8856-8e9998ced9f7?start_date=2021-08-10&end_date=2021-08-17",
        "2021-08-10",
        center_info,
    )
    response = bimedoc.fetch_slots(request)
    # On devrait trouver None puisque la plateforme est désactivée
    assert response == None
예제 #16
0
def test_doctolib_sends_creneau():
    # Given
    start_date = "2021-04-03"
    base_url = "https://partners.doctolib.fr/centre-de-vaccinations-internationales/ville1/centre1?pid=practice-165752&enable_cookies_consent=1"  # noqa
    center_info = CenterInfo(departement="07",
                             nom="Mon Super Centre",
                             url=base_url)
    scrap_request = ScraperRequest(base_url, start_date, center_info)

    def app(request: httpx.Request) -> httpx.Response:
        assert "User-Agent" in request.headers

        if request.url.path == "/booking/centre1.json":
            path = Path("tests", "fixtures", "doctolib", "basic-booking.json")
            return httpx.Response(200,
                                  json=json.loads(
                                      path.read_text(encoding="utf-8")))

        assert request.url.path == "/availabilities.json"
        path = Path("tests", "fixtures", "doctolib",
                    "basic-availabilities.json")
        return httpx.Response(200,
                              json=json.loads(
                                  path.read_text(encoding="utf-8")))

    client = httpx.Client(transport=httpx.MockTransport(app))
    q = SimpleQueue()
    slots = DoctolibSlots(client=client, cooldown_interval=0, creneau_q=q)

    # When
    slots.fetch(scrap_request)
    actual = []
    while not q.empty():
        actual.append(q.get())
    # Then
    assert len(actual) == 1
    assert actual[0] == Creneau(
        reservation_url=base_url,
        horaire=dateutil.parser.parse("2021-04-10T21:45:00.000+02:00"),
        type_vaccin=[Vaccine.PFIZER],
        lieu=Lieu(
            departement="07",
            plateforme=Plateforme.DOCTOLIB,
            url=base_url,
            nom="Mon Super Centre",
            internal_id="doctolib123456789pid165752",
            lieu_type="vaccination-center",
        ),
        dose=["1"],
    )
예제 #17
0
def online_keldoc_test():

    path_centerinfo = Path("tests", "fixtures", "keldoc",
                           "cabinet-16913-centerinfo.json")
    centerinfo_1 = json.loads(path_centerinfo.read_text(encoding="utf-8"))

    center_info = CenterInfo.from_csv_data(centerinfo_1)

    request = ScraperRequest(
        "https://www.keldoc.com/cabinet-medical/grenoble-38000/centre-de-vaccination-universite-inter-age-du-dauphine-uiad",
        "2021-04-13",
        center_info=center_info,
    )

    fetch_slots(request)
예제 #18
0
파일: scraper.py 프로젝트: a2br/vitemadose
def cherche_prochain_rdv_dans_centre(
        centre: dict) -> CenterInfo:  # pragma: no cover
    center_data = CenterInfo.from_csv_data(centre)
    start_date = get_start_date()
    has_error = None
    result = None
    try:
        result = fetch_centre_slots(centre["rdv_site_web"],
                                    start_date,
                                    input_data=centre.get("booking"))
        center_data.fill_result(result)
    except ScrapeError as scrape_error:
        logger.error(
            f"erreur lors du traitement de la ligne avec le gid {centre['gid']} {str(scrape_error)}"
        )
        has_error = scrape_error
    except CircuitBreakerOffException as error:
        logger.error(
            f"circuit '{error.name}' désactivé lors du traîtement de la ligne avec le gid {centre['gid']}: {str(error)}"
        )
        has_error = error
    except Exception:
        logger.error(
            f"erreur lors du traitement de la ligne avec le gid {centre['gid']}"
        )
        traceback.print_exc()

    if has_error is None:
        logger.info(
            f'{centre.get("gid", "")!s:>8} {center_data.plateforme!s:16} {center_data.prochain_rdv or ""!s:32} {center_data.departement!s:6}'
        )
    else:
        logger.info(
            f'{centre.get("gid", "")!s:>8} {center_data.plateforme!s:16} {"Erreur" or ""!s:32} {center_data.departement!s:6}'
        )

    if result is not None and result.request.url is not None:
        center_data.url = result.request.url.lower()
        if result.request.internal_id is None:
            center_data.internal_id = f'{result.platform.lower()}{centre.get("gid", "")}'

    if "type" in centre:
        center_data.type = centre["type"]
    if not center_data.type:
        center_data.type = VACCINATION_CENTER
    center_data.gid = centre.get("gid", "")
    logger.debug(center_data.default())
    return center_data
예제 #19
0
 def centre(self, lieu: Lieu):
     return CenterInfo(
         departement=lieu.departement,
         nom=lieu.nom,
         url=lieu.url,
         location=self.location_to_dict(lieu.location),
         metadata=lieu.metadata,
         prochain_rdv=None,
         plateforme=lieu.plateforme.value,
         type=lieu.lieu_type,
         appointment_count=0,
         internal_id=lieu.internal_id,
         vaccine_type=[],
         erreur=None,
         atlas_gid=lieu.atlas_gid,
     )
예제 #20
0
def test_fetch_slots():
    def app(request: httpx.Request) -> httpx.Response:
        if request.url.path == "/api/BusinessHours/availabilitiesPerDay":
            path = Path("tests/fixtures/avecmondoc/get_availabilities.json")
            return httpx.Response(200,
                                  json=json.loads(
                                      path.read_text(encoding="utf8")))
        if request.url.path == "/api/Organizations/slug/delphine-rousseau-159":
            path = Path("tests/fixtures/avecmondoc/get_organization_slug.json")
            return httpx.Response(200,
                                  json=json.loads(
                                      path.read_text(encoding="utf8")))
        return httpx.Response(404)

    center_info = CenterInfo(
        departement="69",
        nom="Pharmacie AVENUE (Picard)",
        url=
        "https://patient.avecmondoc.com/fiche/structure/pharmacie-avenue-picard-583",
        location=CenterLocation(longitude=4.77231,
                                latitude=45.742216,
                                city="Francheville",
                                cp="69340"),
        metadata={
            "address": "29 avenue du Chater, 69340 Francheville",
            "business_hours": {
                "Lundi": "08:45-12:15 15:00-19:15",
                "Mardi": "08:45-12:15 15:00-19:15",
                "Mercredi": "08:45-12:15 15:00-19:15",
                "Jeudi": "08:45-12:15 15:00-19:15",
                "Vendredi": "08:45-12:15 15:00-19:15",
                "Samedi": "08:45-12:15",
                "Dimanche": "",
            },
            "phone_number": "+33478342931",
        },
        plateforme="Avecmondoc",
        type="drugstore",
        internal_id="amd583",
    )
    client = httpx.Client(transport=httpx.MockTransport(app))
    url = "https://patient.avecmondoc.com/fiche/structure/delphine-rousseau-159"
    request = ScraperRequest(url, "2021-05-20", center_info=center_info)
    first_availability = fetch_slots(request, client=client)
    assert first_availability == "2021-05-20T09:00:00+00:00"
    assert request.vaccine_type == ["Pfizer-BioNTech", "Janssen"]
예제 #21
0
def test_get_first_availability():

    request = ScraperRequest(
        url=
        "https://www.maiia.com/centre-de-vaccination/42400-saint-chamond/centre-de-vaccination-covid---hopital-du-gier-?centerid=5ffc744c68dedf073a5b87a2",
        start_date="2021-07-17",
        center_info=CenterInfo(
            departement="42",
            nom="Centre de vaccination COVID - Hôpital du Gier ",
            url=
            "https://www.maiia.com/centre-de-vaccination/42400-saint-chamond/centre-de-vaccination-covid---hopital-du-gier-?centerid=5ffc744c68dedf073a5b87a2",
            location=CenterLocation(longitude=4.50184989506,
                                    latitude=45.4698319517,
                                    city="Saint-Chamond",
                                    cp="42400"),
            metadata={
                "address": "19 rue victor hugo 42400 Saint-Chamond",
                "business_hours": {
                    "Lundi": "08:15-17:15",
                    "Mardi": "08:15-17:15",
                    "Mercredi": "08:15-17:15",
                    "Jeudi": "08:15-17:15",
                    "Vendredi": "08:15-17:15",
                    "Samedi": "08:15-17:15",
                    "Dimanche": "08:15-17:15",
                },
            },
            type="vaccination-center",
            internal_id="5ffc744c",
        ),
    )
    reasons = get_reasons("5ffc744c68dedf073a5b87a2",
                          limit=MAIIA_LIMIT,
                          client=client)
    instance = MaiiaSlots(creneau_q=DummyQueue, client=None)
    fake_now = dt.datetime(2021, 4, 29, 18, 20)
    with mock_datetime_now(fake_now):
        first_availability, slots_count = instance.get_first_availability(
            "5ffc744c68dedf073a5b87a2",
            "2021-04-29",
            reasons,
            client=client,
            request=request)

    assert slots_count == 7182
    assert first_availability.isoformat() == "2021-05-13T13:40:00+00:00"
예제 #22
0
def test_convert_ordoclic():
    center = CenterInfo("Paris", "Centre 1", "https://.../centre")
    data = {
        "location": {
            "coordinates": {
                "lon": 1.1281,
                "lat": 93.182,
            },
            "city": "Foobar",
            "address": "12 Avenue de la ville",
            "zip": "22000",
        },
        "phone_number": "06 06 06 06 06",
    }
    center = convert_ordoclic_to_center_info(data, center)
    assert center.metadata["address"] == "12 Avenue de la ville, 22000 Foobar"
    assert center.metadata["phone_number"] == "+33606060606"
    assert center.metadata["business_hours"] is None
예제 #23
0
def test_convert_ordoclic():
    center = CenterInfo("Paris", "Centre 1", "https://.../centre")
    data = {
        'location': {
            'coordinates': {
                'lon': 1.1281,
                'lat': 93.182,
            },
            'city': 'Foobar',
            'address': '12 Avenue de la ville',
            'zip': '22000'
        },
        'phone_number': '06 06 06 06 06'
    }
    center = convert_ordoclic_to_center_info(data, center)
    assert center.metadata['address'] == '12 Avenue de la ville, 22000 Foobar'
    assert center.metadata['phone_number'] == '+33606060606'
    assert center.metadata['business_hours'] is None
예제 #24
0
def test_center_info_fill():
    center = CenterInfo("Paris", "Centre 1", "https://.../centre")
    newloc = CenterLocation(1.122, 2.391, "Ok", "Cp")
    request = ScraperRequest(center.url, "2021-05-04")
    result = ScraperResult(request, "Doctolib", "2021-05-06")
    center.fill_localization(newloc)
    request.update_appointment_count(42)
    request.add_vaccine_type(Vaccine.PFIZER)
    request.add_vaccine_type(Vaccine.ASTRAZENECA)
    request.add_vaccine_type(Vaccine.MODERNA)
    request.update_internal_id("doctolibcentre1")
    request.update_practitioner_type(DRUG_STORE)
    request.set_appointments_only_by_phone(False)
    center.fill_result(result)

    assert center.location == newloc
    assert center.prochain_rdv == "2021-05-06"
    assert center.plateforme == "Doctolib"
    assert center.type == "drugstore"
    assert center.appointment_count == 42
    assert center.internal_id == "doctolibcentre1"
    assert center.vaccine_type == ["Pfizer-BioNTech", "AstraZeneca", "Moderna"]
    assert not center.appointment_by_phone_only
    assert center.default() == {
        "departement": "Paris",
        "nom": "Centre 1",
        "url": "https://.../centre",
        "location": {
            "longitude": 1.122,
            "latitude": 2.391,
            "city": "Ok",
            "cp": "Cp"
        },
        "metadata": None,
        "prochain_rdv": "2021-05-06",
        "plateforme": "Doctolib",
        "type": "drugstore",
        "appointment_count": 42,
        "internal_id": "doctolibcentre1",
        "vaccine_type": ["Pfizer-BioNTech", "AstraZeneca", "Moderna"],
        "appointment_by_phone_only": False,
        "erreur": None,
        "last_scan_with_availabilities": None,
        "appointment_schedules": None,
        "request_counts": None,
    }
예제 #25
0
def test_center_info_fill():
    center = CenterInfo("Paris", "Centre 1", "https://.../centre")
    newloc = CenterLocation(1.122, 2.391, "Ok")
    request = ScraperRequest(center.url, "2021-05-04")
    result = ScraperResult(request, "Doctolib", "2021-05-06")
    center.fill_localization(newloc)
    request.update_appointment_count(42)
    request.add_vaccine_type(Vaccine.PFIZER)
    request.add_vaccine_type(Vaccine.ASTRAZENECA)
    request.add_vaccine_type(Vaccine.MODERNA)
    request.update_internal_id("doctolibcentre1")
    request.update_practitioner_type(DRUG_STORE)
    request.set_appointments_only_by_phone(False)
    center.fill_result(result)

    assert center.location == newloc
    assert center.prochain_rdv == "2021-05-06"
    assert center.plateforme == "Doctolib"
    assert center.type == "drugstore"
    assert center.appointment_count == 42
    assert center.internal_id == "doctolibcentre1"
    assert center.vaccine_type == ["Pfizer-BioNTech", "AstraZeneca", "Moderna"]
    assert not center.appointment_by_phone_only
    assert center.default() == {
        'departement': 'Paris',
        'nom': 'Centre 1',
        'url': 'https://.../centre',
        'location': {
            'longitude': 1.122,
            'latitude': 2.391,
            'city': 'Ok'
        },
        'metadata': None,
        'prochain_rdv': '2021-05-06',
        'plateforme': 'Doctolib',
        'type': 'drugstore',
        'appointment_count': 42,
        'internal_id': 'doctolibcentre1',
        'vaccine_type': ['Pfizer-BioNTech', 'AstraZeneca', 'Moderna'],
        'appointment_by_phone_only': False,
        'erreur': None,
        'last_scan_with_availabilities': None,
        'appointment_schedules': None
    }
예제 #26
0
def test_keldoc_scrape_nodate():
    center1_url = (
        "https://www.keldoc.com/centre-hospitalier-regional/lorient-56100/groupe-hospitalier"
        "-bretagne-sud-lorient-hopital-du-scorff?specialty=144 ")

    keldoc.KELDOC_ENABLED = True

    def app_center2(request: httpx.Request) -> httpx.Response:
        if "timetables/" in request.url.path:
            return httpx.Response(200, json={})
        if (request.url.path ==
                "/centre-hospitalier-regional/lorient-56100/groupe-hospitalier-bretagne-sud-lorient-hopital-du-scorff"
            ):
            return httpx.Response(
                302,
                headers={
                    "Location":
                    "https://vaccination-covid.keldoc.com/redirect/?dom=centre-hospitalier-regional&inst=lorient-56100&user=groupe-hospitalier-bretagne-sud-lorient-hopital-du-scorff&specialty=144 "
                },
            )
        for path in CENTER1_KELDOC:
            if request.url.path == path:
                return httpx.Response(200,
                                      json=get_test_data(CENTER1_KELDOC[path]))
        return httpx.Response(200, json={})

    path_centerinfo = Path("tests", "fixtures", "keldoc",
                           "cabinet-16913-centerinfo.json")
    centerinfo_1 = json.loads(path_centerinfo.read_text(encoding="utf-8"))

    center_info = CenterInfo.from_csv_data(centerinfo_1)

    request = ScraperRequest(center1_url,
                             "2099-12-12",
                             center_info=center_info)
    keldoc.session = httpx.Client(transport=httpx.MockTransport(app_center2))

    date = fetch_slots(request)
    assert not date
예제 #27
0
def test_blocked_by_doctolib_par_centre():
    # Cas de base.

    start_date = "2021-04-03"
    base_url = "https://partners.doctolib.fr/centre-de-vaccinations-internationales/ville1/centre1?pid=practice-165752&enable_cookies_consent=1"  # noqa
    center_info = CenterInfo(departement="07",
                             nom="Mon Super Centre",
                             url=base_url)
    scrap_request = ScraperRequest(base_url, start_date, center_info)

    def app(request: httpx.Request) -> httpx.Response:
        assert "User-Agent" in request.headers

        if request.url.path == "/booking/centre1.json":
            path = Path("tests", "fixtures", "doctolib", "basic-booking.json")
            return httpx.Response(403, text="Anti dDos")

        assert request.url.path == "/availabilities.json"
        params = dict(httpx.QueryParams(request.url.query))
        assert params == {
            "start_date": start_date,
            "visit_motives_ids": "2",
            "agenda_ids": "3",
            "insurance_sector": "public",
            "practice_ids": "4",
            "destroy_temporary": "true",
            "limit": str(DOCTOLIB_CONF.pagination["pages"]),
        }
        path = Path("tests", "fixtures", "doctolib",
                    "basic-availabilities.json")
        return httpx.Response(200,
                              json=json.loads(
                                  path.read_text(encoding="utf-8")))

    client = httpx.Client(transport=httpx.MockTransport(app))
    slots = DoctolibSlots(client=client, cooldown_interval=0)

    with pytest.raises(Blocked403):
        slots.fetch(scrap_request)
예제 #28
0
def test_convert_ordoclic_second():
    data = {
        "nom": "Centre 2",
        "com_insee": "35238",
        "rdv_site_web": "https://site.fr/",
        "iterator": "ordoclic",
        "location": {
            "coordinates": {
                "lon": 1.1281,
                "lat": 93.182,
            },
            "city": "Foobar",
            "address": "12 Avenue de la ville",
            "zip": "22000",
        },
        "phone_number": "06 06 06 06 06",
    }
    center = CenterInfo.from_csv_data(data)
    assert center.nom == "Centre 2"
    assert center.metadata["address"] == "12 Avenue de la ville, 22000 Foobar"
    assert center.metadata["phone_number"] == "+33606060606"
    assert center.metadata["business_hours"] is None
예제 #29
0
def test_export_reserved_centers(tmp_path):
    centres_cherchés_dict = [{
        "departement": "01",
        "nom": "Bugey Sud - Réservé aux médecins du groupe hospitalier",
        "url": "https://example.com/bugey-sud",
        "plateforme": "Doctolib",
        "prochain_rdv": "2021-04-10T00:00:00",
        "location": None,
        "metadata": None,
        "type": None,
        "appointment_by_phone_only": False,
        "appointment_count": 1,
        "internal_id": None,
    }]
    centres_cherchés = [
        CenterInfo.from_dict(center) for center in centres_cherchés_dict
    ]

    out_dir = tmp_path / "out"
    out_dir.mkdir()
    outpath_format = str(out_dir / "{}.json")

    fake_now = dt.datetime(2021, 4, 4)
    get_start_date()
    with mock_datetime_now(fake_now):
        export_data(centres_cherchés, [], outpath_format=outpath_format)

    # Departements 01 and 59 should contain expected data.

    content = json.loads((out_dir / "01.json").read_text())
    assert content == {
        "version": 1,
        "centres_disponibles": [],
        "centres_indisponibles": [],
        "last_scrap": [],
        "last_updated": "2021-04-04T00:00:00",
    }
예제 #30
0
def test_convert_centerinfo_invalid():
    data = {
        "nom": "Centre 1",
        "gid": "d001",
        "rdv_site_web": "https://site.fr",
        "com_insee": "0095238",
        "rdv_tel": "06 06 06 06 06",
        "phone_number": "06 06 06 06 07",
        "adr_num": "1",
        "adr_voie": "Rue de la Fraise",
        "com_cp": "75016",
        "com_nom": "Paris",
        "business_hours": {
            "lundi": "09:50-10:10",
            "mardi": "09:10-10:10",
            "mercredi": "10:00-10:10",
            "jeudi": "10:20-10:40",
            "vendredi": "09:50-10:10",
            "samedi": "09:00-10:20",
            "dimanche": "Fermé",
        },
    }

    center = CenterInfo.from_csv_data(data)
    assert center.departement == ""
    assert center.url == "https://site.fr"
    assert center.metadata["address"] == "1 Rue de la Fraise, 75016 Paris"
    assert center.metadata["phone_number"] == "+33606060607"
    assert center.metadata["business_hours"] == {
        "lundi": "09:50-10:10",
        "mardi": "09:10-10:10",
        "mercredi": "10:00-10:10",
        "jeudi": "10:20-10:40",
        "vendredi": "09:50-10:10",
        "samedi": "09:00-10:20",
        "dimanche": "Fermé",
    }