示例#1
0
class ChangeChecker():
    """
        Class to check for empty slots on specific dates
        When a change occurs (#spots increases), it sends an SMS to target number
        A check is performed
    """
    def __init__(self, retries=2, headless=True):
        # Disable data and cache
        # Goal: refresh removes items from the cart
        profile = webdriver.FirefoxProfile()
        profile.set_preference("browser.cache.disk.enable", False)
        profile.set_preference("browser.cache.memory.enable", False)
        profile.set_preference("browser.cache.offline.enable", False)
        profile.set_preference("network.http.use-cache", False)

        if headless:
            fireFoxOptions = webdriver.FirefoxOptions()
            fireFoxOptions.set_headless()
            self.driver = webdriver.Firefox(firefox_profile=profile,
                                            executable_path="./geckodriver",
                                            firefox_options=fireFoxOptions)
        else:
            self.driver = webdriver.Firefox(firefox_profile=profile,
                                            executable_path="./geckodriver")
        self.notifier = Notifier()
        self.change_detected = False
        self.waiting_user_response = False
        self.stop = False
        self.attempts = retries

    def init_slots(self):
        self.slots = {}
        for d in config.DAYS:
            self.slots[d] = {}
            for s in config.SLOTS:
                self.slots[d][s] = -1

    def start(self):
        self.init_slots()
        self.notifier.notify("Change detection started for url %s , " %
                             config.URL +
                             "Send STOP to stop service, START to resume")
        while True:
            self.check_commands()
            if self.stop:
                print("Waiting for user to send START command")
            else:
                current_time = (datetime.datetime.utcnow() -
                                datetime.timedelta(hours=6, minutes=0))
                print("Checking at time:", current_time.strftime("%H:%M:%S"))

                if self.update_slots():
                    report = "Update %s\n" % str(current_time)
                    report += self.get_report()
                    if not self.notifier.notify(report):
                        self.notifier.__init__()

            time.sleep(10)

    def refresh_page(self):
        self.go_to(config.URL)

    def go_to(self, link):
        succeeded = False
        for i in range(self.attempts):
            try:
                self.driver.get(link)
                time.sleep(1)
                succeeded = True
                break
            except:
                self.driver.quit()
                self.__init__()
        return succeeded

    def set_days(self, i):
        select = Select(self.driver.find_element_by_id(config.INPUT_FIELD))
        select.select_by_value(str(i))

    def update_slots(self):
        something_changed = False
        for D in config.DAYS:
            print("Checking %s" % D)
            for S in config.SLOTS:
                print("\t Checking slot %i:00 " % (10 + 2 * S))
                self.refresh_page()
                if not self.not_full():
                    if self.slots[D][S] != 0:
                        something_changed = True
                    self.slots[D][S] = 0
                    print("\t\t %s %i:00 is full" % (D, 10 + 2 * S))
                    continue
                else:
                    print("\t\t %s %i:00 is not full" % (D, 10 + 2 * S))

                for people in range(config.MAX_PEOPLE, 0, -1):

                    self.refresh_page()
                    self.go_to(config.DAYS[D])
                    print("\t\t Checking if it has %i spots" % people,
                          end="\r")
                    # At least one time slot has a free spot
                    # For each number of people
                    try:
                        self.set_days(people)
                        self.go_to(config.SLOTS[S])
                    except:
                        continue

                    if self.not_full():
                        print("\n\t\t Found %i spots" % people)
                        if self.slots[D][S] != people:
                            self.slots[D][S] = people
                            something_changed = True
                            break
                else:
                    print("\n\t\t Found 0 spots")
                    if self.slots[D][S] != 0:
                        something_changed = True
                    self.slots[D][S] = 0
        return something_changed

    def not_full(self):
        # No available slots if page has "full" in teh source
        return "FULL" not in self.driver.page_source

    def get_report(self):
        # Returns a report of available spots per slot
        report = "Check %s \n" % config.URL
        for D in config.DAYS:
            report = report + D + ":\n"
            for S in config.SLOTS:
                report = report + "%i:00:%i, " % (10 + 2 * S, self.slots[D][S])
            report = report + "\n"
        return report

    def check_commands(self):
        message = self.notifier.last_received()
        if message:
            if "STOP" in message.body.upper():
                self.stop = True
            if "START" in message.body.upper():
                self.stop = False
            message.delete()