Exemple #1
0
def clear_reservations(preferences):
    logger.info("Cancelling appointments made by the device")

    appointments = get_appointments(preferences)

    if appointments is None:
        logger.error("Failed to cancel requested appointment. Perhaps there is an issue with network connectivity.")
        return

    now = tz.localize(EWSDateTime.utcnow())

    if(len(appointments) > 0):
        for app in appointments:
            start_time = tz.localize(app.start.replace(tzinfo=None))
            end_time    = tz.localize(app.end.replace(tzinfo=None))
            if "Pikavaraus" in app.subject and "Naurunappula" in app.body and now < end_time:
                logger.info("Cancelling an appointment named {0} at {1} - {2}".format(app.subject, start_time, end_time))
                try:
                    app.start = app.start.astimezone(tz)
                    app.end = tz.localize(EWSDateTime.now())
                    app.save()
                    return True
                except Exception as e:
                    logger.exception("Couldn't cancel appointment.")
                    return False
    else:
        logger.info("No appointments to cancel.")
        return False
 def test_super_methods(self):
     tz = EWSTimeZone('Europe/Copenhagen')
     self.assertIsInstance(EWSDateTime.now(), EWSDateTime)
     self.assertIsInstance(EWSDateTime.now(tz=tz), EWSDateTime)
     self.assertIsInstance(EWSDateTime.utcnow(), EWSDateTime)
     self.assertIsInstance(EWSDateTime.fromtimestamp(123456789),
                           EWSDateTime)
     self.assertIsInstance(EWSDateTime.fromtimestamp(123456789, tz=tz),
                           EWSDateTime)
     self.assertIsInstance(EWSDateTime.utcfromtimestamp(123456789),
                           EWSDateTime)
Exemple #3
0
def verify_availability(appointments, timeslot):
    now = tz.localize(EWSDateTime.utcnow())
    nowplusdelta = now + timedelta(minutes=timeslot)

    for app in appointments:
        # the timeslot has to pass a few rules before it can be reserved
        start_time = tz.localize(app.start.replace(tzinfo=None))
        end_time = tz.localize(app.end.replace(tzinfo=None))
        if now >= start_time and now < end_time:
            logger.info("Meeting room is marked as reserved by rule #1")
            return app, False
        if now >= start_time and nowplusdelta <= start_time:
            logger.info("Meeting room is marked as reserved by rule #2")
            return app, False
        if now <= start_time and (nowplusdelta >= (start_time - timedelta(minutes=1)) and nowplusdelta <= end_time):
            logger.info("Meeting room is marked as reserved by rule #3")
            return app, False

    logger.info("Meeting room is free at the moment.")
    return None, True
Exemple #4
0
def get_appointments(preferences):
    now = tz.localize(EWSDateTime.utcnow())
    items = {}

    try:
        credentials = Credentials(username=preferences["username"], password=preferences["password"])
        config = Configuration(service_endpoint=preferences["server"], credentials=credentials, auth_type=NTLM)
        account = Account(primary_smtp_address=preferences["email"], config=config, autodiscover=False, access_type=DELEGATE)
        logger.info("Getting reservations for {0}".format(account.primary_smtp_address))
        items = account.calendar.view(
            start=tz.localize(EWSDateTime(now.year, now.month, now.day, 0, 0)),
            end=tz.localize(EWSDateTime(now.year, now.month, now.day, 23, 59)),
        ).order_by('start')
    except requests.exceptions.RequestException as e: # failure in data communication
        logger.exception("Failure while contacting the server.")
        return None
    except Exception as e:
        logger.exception("Failed to get appointments. Try again later.")
        return None

    return items
Exemple #5
0
def poll_availability(preferences):
    available = True
    now = tz.localize(EWSDateTime.utcnow())

    logger.info("Getting appointments for today and checking availability.")

    try:
        appointments = get_appointments(preferences)
        if appointments is None:
            return "{\"subject\": \"Error\", \"start\": \"\", \"end\": \"\", \"duration\": \"0\", \"available\": \"False\"}"
        blocking_appointment, available = verify_availability(appointments, 5)
    except Exception as e:
        logger.exception("Failed to parse appointments.")
        return "{\"subject\": \"Error\", \"start\": \"\", \"end\": \"\", \"duration\": \"0\", \"available\": \"False\"}"

    event_subject = ""
    event_start_time = ""
    event_end_time = ""
    event_found = False
    duration = 0

    if not available:
        logger.info("Meeting room reserved at the moment!")

        event_subject = blocking_appointment.subject

        duration = (tz.localize(blocking_appointment.end.replace(tzinfo=None)) - now).total_seconds() / 60

        if event_subject is None or event_subject is "":
            event_subject = "Nimetön varaus"

        event_subject = event_subject.replace("\"", "'")

        event_start_time = blocking_appointment.start.astimezone(tz) #adjust timezone to local timezone
        event_end_time   = blocking_appointment.end.astimezone(tz)   #adjust timezone to local timezone

        return "{\"subject\": \"" + event_subject + "\", \"start\": \"" + event_start_time.strftime('%H:%M') + "\", \"end\": \"" + event_end_time.strftime('%H:%M') + "\", \"duration\": " + str(duration) + ", \"available\": \"False\"}"

    else: # find if there are upcoming events
        try:
            for app in appointments:
                event_subject = app.subject

                if event_subject is None or event_subject is "":
                    event_subject = "Nimetön varaus"

                event_subject = event_subject.replace("\"", "'")
                event_start_time = app.start.astimezone(tz) #adjust timezone to local timezone for rendering
                event_end_time   = app.end.astimezone(tz)   #adjust timezone to local timezone for rendering

                if(now < tz.localize(app.start.replace(tzinfo=None)) and event_found == False):
                    event_found = True
                    duration = (tz.localize(app.start.replace(tzinfo=None)) - now).total_seconds() / 60
                    break

        except requests.exceptions.RequestException as e: # failure in data communication
            logger.exception("Failed to parse data.")
            return "{\"subject\": \"Error\", \"start\": \"\", \"end\": \"\", \"duration\": \"0\", \"available\": \"False\"}"

        if event_found:
            return "{\"subject\": \"" + event_subject + "\", \"start\": \"" + event_start_time.strftime('%H:%M') + "\", \"end\": \"" + event_end_time.strftime('%H:%M') + "\", \"duration\": " + str(duration) + ", \"available\": \"True\"}"
        else:
            return "{\"subject\": \"\", \"start\": \"\", \"end\": \"\", \"duration\": \"0\", \"available\": \"True\"}"
    def work(self):
        logger.debug("Starting work thread")
        calendar_data = {}  #dictionary containing the data

        progress_step = 100 / len(self.calendars)
        progress_now = 0

        try:
            for key, value in self.calendars.items():
                calendar_name = key
                calendar_email = value

                logger.debug(
                    "Fetching data for calendar: {0}".format(calendar_name))
                logger.debug("Setting up EWS account for calendar: {0}".format(
                    calendar_email))

                try:
                    account = Account(primary_smtp_address=str(calendar_email),
                                      config=self.config,
                                      autodiscover=False,
                                      access_type=DELEGATE)
                except Exception as e:
                    logger.error("Failure: {0}".format(traceback.print_exc()))
                    continue

                calendar_data[calendar_name], result = self.get_appointments(
                    account)

                if result is not True:
                    logger.error(
                        "Failed to fetch calendar data for calendar: {0}".
                        format(calendar_email))

                progress_now += progress_step
                self.progress.emit(progress_now)

                logger.debug("Done with calendar: {0}".format(calendar_email))
        except Exception as e:
            logger.debug(
                "General failure occured when fetching calendar data! Error: {0}"
                .format(traceback.print_exc()))
            self.statusupdate.emit(-1, "Failure while fetching calendar data!")
            self.progress.emit(100)
            return

        logger.debug("Calendar data retrieved. Outputting webpage...")

        if not os.path.exists(self.workdirectory + "/web/"):
            os.makedirs(self.workdirectory + "/web/")

        try:
            content = ""
            content += "<table>\n"
            content += "<colgroup\n"
            content += "<col class=\"column10\"/>\n"
            content += "<col class=\"column30\"/>\n"
            content += "<col class=\"column15\"/>\n"
            content += "<col class=\"column30\"/>\n"
            content += "<col class=\"column15\"/>\n"
            content += "</colgroup>\n"
            content += "<tr>"
            content += "<th>Huone</th>"
            content += "<th>Tällä hetkellä / Seuraavaksi</th>"
            content += "<th></th>"
            content += "<th>Myöhemmin tänä päivänä</th>"
            content += "<th></th>"
            content += "</tr>"

            now = self.tz.localize(EWSDateTime.utcnow())

            for calendar in calendar_data:
                primary_event_found = False
                secondary_event_found = False
                content += "<tr>\n"
                content += "<td class=\"meetingroom\">" + calendar + "</td>\n"

                try:
                    for item in calendar_data[calendar]:
                        subject = item.subject

                        item.start = item.start.astimezone(
                            self.tz)  #adjust timezone to local timezone
                        item.end = item.end.astimezone(
                            self.tz)  #adjust timezone to local timezone

                        if subject is None or subject is "":
                            subject = "Varaus ilman otsikkoa"

                        if (now < item.end and primary_event_found == False):
                            primary_event_found = True
                            content += "<td class=\"event_primary\">" + str(
                                subject) + "</td>\n"
                            content += "<td class=\"eventdate_primary\">%s - %s</td>\n" % (
                                item.start.strftime("%H:%M"),
                                item.end.strftime("%H:%M"))

                        elif (now < item.end
                              and secondary_event_found == False):
                            secondary_event_found = True
                            content += "<td class=\"event_secondary\">" + str(
                                subject) + "</td>\n"
                            content += "<td class=\"eventdate_secondary\">%s - %s</td>\n" % (
                                item.start.strftime("%H:%M"),
                                item.end.strftime("%H:%M"))
                            break

                except Exception as e:  # failure in data communication
                    logger.error("Failed to parse calendar data: {0}".format(
                        traceback.print_exc()))
                    content += "<td class=\"event_primary\">Virhe tiedonsiirrossa</td>\n"
                    content += "<td class=\"eventdate_primary\"></td>\n"
                    content += "<td class=\"event_secondary\">Virhe tiedonsiirrossa</td>\n"
                    content += "<td class=\"eventdate_secondary\"></td>\n"
                    primary_event_found = True
                    secondary_event_found = True
                    continue

                if (primary_event_found != True):
                    logger.debug("Ei varauksia kalenterille " + calendar)
                    content += "<td class=\"event_primary\">Vapaa</td>\n"
                    content += "<td class=\"eventdate_primary\"></td>\n"
                if (secondary_event_found != True):
                    logger.debug("Ei toissijaisia kalenterille " + calendar)
                    content += "<td class=\"event_secondary\">Vapaa</td>\n"
                    content += "<td class=\"eventdate_secondary\"></td>\n"

                content += "</tr>\n"
            content += "</table>"

            logger.debug("Updating webpage content!")

            with codecs.open(self.workdirectory + "/web/content.html", "w+",
                             "utf-8") as f:
                f.write(content)  # write the file first

            if os.path.isfile(
                    self.workdirectory + "/web/index.html"
            ) is False:  # if index.html already exists. Don't rewrite it constantly
                with codecs.open(self.workdirectory + "/web/index.html", "w+",
                                 "utf-8") as f:
                    f.write(
                        WebpageTemplate.template.replace(
                            "%REPLACE_THIS_WITH_CONTENT%", ""))

            if os.path.isfile(
                    self.workdirectory + "/web/stylesheet.css"
            ) is False:  # if the stylesheet already exists. Don't rewrite it constantly
                with codecs.open(self.workdirectory + "/web/stylesheet.css",
                                 "w+", "utf-8") as f:
                    f.write(WebpageTemplate.css_template)

        except FileNotFoundError:
            logger.error("Failed to open files for page generation.")
            self.statusupdate.emit(
                -1, "Failed to open files for page generation.")
            self.progress.emit(100)
            return

        self.statusupdate.emit(1, "Calendar data succesfully fetched!")