Esempio n. 1
0
def show_talk(seminar_id, talkid):
    token = request.args.get("token", "")  # save the token so user can toggle between view and edit
    talk = talks_lucky({"seminar_id": seminar_id, "seminar_ctr": talkid}, prequery={})
    if talk is None:
        return abort(404, "Talk not found")
    if not talk.visible():
        # There may be a non-API version of the seminar that can be shown
        talk = talks_lucky({"seminar_id": seminar_id, "seminar_ctr": talkid})
        if talk is None or not talk.visible():
            flash_error("You do not have permission to view %s/%s", seminar_id, talkid)
            return redirect(url_for("semseries_index"))
    kwds = dict(
        title="View talk", talk=talk, seminar=talk.seminar, subsection="viewtalk", token=token
    )
    if token:
        kwds["section"] = "Manage"
        # Also want to override top menu
        from seminars.utils import top_menu

        menu = top_menu()
        menu[1] = (url_for("create.index"), "", "Manage")
        kwds["top_menu"] = menu
    elif (
        current_user.is_subject_admin(talk)
        or current_user.email_confirmed
        and (
            current_user.email in talk.seminar.editors() or current_user.email == talk.speaker_email
        )
    ):
        kwds["section"] = "Manage"
    return render_template("talk.html", **kwds)
Esempio n. 2
0
def register_for_talk(seminar_id, talkid):
    from flask import flash
    talk = talks_lucky({"seminar_id": seminar_id, "seminar_ctr": talkid})
    if talk is None:
        return abort(404, "Talk not found")
    # If registration isn't required just send them to the talk page
    # where the user will see an appropriate livestream link
    if talk.access_control != 4:
        return redirect(
            url_for('show_talk', seminar_id=seminar_id, talkid=talkid))
    if current_user.is_anonymous or len(current_user.name) < 2:
        return redirect(
            url_for("user.info",
                    next=url_for("register_for_talk",
                                 seminar_id=seminar_id,
                                 talkid=talkid)))
    if not current_user.email_confirmed:
        flash_error("You need to confirm your email before you can register.")
        return redirect(
            url_for('show_talk', seminar_id=seminar_id, talkid=talkid))
    if not talk.live_link:
        return abort(404, "Livestream link for talk not found")
    if talk.register_user():
        flash("You have been registered; enjoy the talk!")
    else:
        flash("Previous registration confirmed; enjoy the talk!")
    if talk.is_starting_soon():
        return redirect(talk.live_link)
    else:
        return redirect(
            url_for('show_talk', seminar_id=seminar_id, talkid=talkid))
Esempio n. 3
0
def ics_talk_file(seminar_id, talkid):
    talk = talks_lucky({"seminar_id": seminar_id, "seminar_ctr": talkid})
    if talk is None:
        return abort(404, "Talk not found")
    return ics_file([talk],
                    filename="{}_{}.ics".format(seminar_id, talkid),
                    user=current_user)
Esempio n. 4
0
def show_talk(semid, talkid):
    token = request.args.get(
        "token", "")  # save the token so user can toggle between view and edit
    talk = talks_lucky({"seminar_id": semid, "seminar_ctr": talkid})
    if talk is None:
        return not_found_404("Talk not found")
    kwds = dict(title="View talk",
                talk=talk,
                seminar=talk.seminar,
                subsection="viewtalk",
                token=token)
    if token:
        kwds["section"] = "Manage"
        # Also want to override top menu
        from seminars.utils import top_menu

        menu = top_menu()
        menu[2] = (url_for("create.index"), "", "Manage")
        kwds["top_menu"] = menu
    elif (current_user.is_subject_admin(talk)
          or current_user.email_confirmed and
          (current_user.email in talk.seminar.editors()
           or current_user.email == talk.speaker_email)):
        kwds["section"] = "Manage"
    return render_template("talk.html", **kwds)
Esempio n. 5
0
def show_talk(semid, talkid):
    talk = talks_lucky({"seminar_id": semid, "seminar_ctr": talkid})
    if talk is None:
        return render_template("404.html", title="Talk not found")
    utcoffset = int(talk.start_time.utcoffset().total_seconds() / 60)
    return render_template(
        "talk.html",
        title="View talk",
        talk=talk,
        utcoffset=utcoffset,
        top_menu=basic_top_menu(),
    )
Esempio n. 6
0
def next_talk(shortname):
    """
    Gets the next talk time in a single seminar.  Note that if you need this information for many seminars, the `next_talks` function will be faster.
    """
    from seminars.talk import talks_lucky
    return talks_lucky(
        {
            "seminar_id": shortname,
            "start_time": {
                "$gte": datetime.now(pytz.UTC)
            }
        },
        projection="start_time",
        sort=["start_time"])
Esempio n. 7
0
def layout_schedule(seminar, data):
    """ Returns a list of schedule slots in specified date range (date, daytime-interval, talk)
        where talk is a WebTalk or none.  Picks default dates if none specified
    """
    tz = seminar.tz

    def parse_date(key):
        date = data.get(key)
        if date:
            try:
                return process_user_input(date, "date", "date", tz)
            except ValueError:
                flash_warning(
                    "Invalid date %s ignored, please use a format like mmm dd, yyyy or dd-mmm-yyyy or mm/dd/yyyy",
                    date)

    def slot_start_time(s):
        # put slots with no time specified at the end of the day
        return date_and_daytimes_to_times(parse_time(s[0]),
                                          s[1] if s[1] else "23:59-23:59",
                                          tz)[0]

    begin = parse_date("begin")
    end = parse_date("end")
    shortname = seminar.shortname
    now = datetime.now(tz=tz)
    today = now.date()
    day = timedelta(days=1)
    if seminar.is_conference and (seminar.start_date is None
                                  or seminar.end_date is None):
        flash_warning(
            "You have not specified the start and end dates of your conference (we chose a date range to layout your schedule)."
        )
    begin = seminar.start_date if begin is None and seminar.is_conference else begin
    begin = today if begin is None else begin
    end = seminar.end_date if end is None and seminar.is_conference else end
    if end is None:
        if seminar.is_conference:
            if seminar.per_day:
                end = begin + day * ceil(SCHEDULE_LEN / seminar.per_day)
            else:
                end = begin + 7 * day
        else:
            if seminar.frequency:
                end = begin + day * ceil(
                    SCHEDULE_LEN * seminar.frequency / len(seminar.time_slots))
            else:
                end = begin + 14 * day
    if end < begin:
        end = begin
    data["begin"] = seminar.show_input_date(begin)
    data["end"] = seminar.show_input_date(end)
    midnight_begin = midnight(begin, tz)
    midnight_end = midnight(end, tz)
    query = {"$gte": midnight_begin, "$lt": midnight_end + day}
    talks = list(
        talks_search({
            "seminar_id": shortname,
            "start_time": query
        },
                     sort=["start_time"]))
    slots = [(t.show_date(tz), t.show_daytimes(tz), t) for t in talks]
    if seminar.is_conference:
        newslots = []
        d = midnight_begin
        while d < midnight_end + day:
            newslots += [(seminar.show_schedule_date(d), "", None)
                         for i in range(seminar.per_day)]
            d += day
        for t in slots:
            if (t[0], "", None) in newslots:
                newslots.remove((t[0], "", None))
        slots = sorted(slots + newslots, key=lambda t: slot_start_time(t))
        return slots
    if not seminar.frequency:
        for i in range(max(SCHEDULE_LEN - len(slots), 3)):
            slots.append(("", "", None))
    else:
        # figure out week to start in.
        # use the week of the first seminar after begin if any, otherwise last seminar before begin, if any
        # otherwise just use the week containing begin
        t = talks_lucky(
            {
                "seminar_id": shortname,
                "start_time": {
                    "$gte": midnight_begin
                }
            },
            sort=[("start_time", 1)])
        if not t:
            t = talks_lucky(
                {
                    "seminar_id": shortname,
                    "start_time": {
                        "$lt": midnight_begin
                    }
                },
                sort=[("start_time", -1)])
        if t:
            t = adapt_datetime(t.start_time, newtz=tz)
            w = t - t.weekday() * day
            while w > midnight_begin:
                w -= day * seminar.frequency
            while w + day * seminar.frequency < midnight_begin:
                w += day * seminar.frequency
        else:
            w = midnight_begin - midnight_begin.weekday() * day
        # make a list of all seminar time slots in [begin,end)
        newslots = []
        while w < midnight_end:
            for i in range(len(seminar.weekdays)):
                d = w + day * seminar.weekdays[i]
                if d >= midnight_begin and d < midnight_end + day:
                    newslots.append((seminar.show_schedule_date(d),
                                     seminar.time_slots[i], None))
            w = w + day * seminar.frequency
        # remove slots that are (exactly) matched by an existing talk
        # this should handle slots that occur with multiplicity
        for t in slots:
            if (t[0], t[1], None) in newslots:
                newslots.remove((t[0], t[1], None))
        slots = sorted(slots + newslots, key=lambda t: slot_start_time(t))
    return slots
Esempio n. 8
0
def import_talks(csv_file):
    talks = []
    ctr = {}
    with open(csv_file) as F:
        for i, line in enumerate(reader(F)):
            if i == 0:
                assert line == [
                    "Timestamp",
                    "Title",
                    "Speaker",
                    "Speaker_inst",
                    "Abstract",
                    "Host",
                    "Seminar",
                    "Site",
                    "In_Charge",
                    "arXiv",
                    "Date",
                    "Start_Time",
                    "End_Time",
                    "Timezone",
                    "Approved",
                ]
                continue
            (
                timestamp,
                title,
                speaker,
                speaker_affiliation,
                abstract,
                host,
                seminar_id,
                site,
                in_charge,
                arXiv,
                date,
                start_time,
                end_time,
                timezone,
                approved,
            ) = line
            # Make sure seminar exists
            seminar = seminars_lookup(seminar_id)
            if not seminar:
                continue
            if seminar is None:
                print("Warning: seminar %s does not exist" % seminar_id)
                continue
            if seminar_id not in ctr:
                m = talks_max("seminar_ctr", {"seminar_id": seminar_id})
                if m is None:
                    m = -1
                ctr[seminar_id] = m + 1
            # This time zone info is specific to importing in early April
            # There is some broken data, where time zones were incrementing the minute.  We reset them all to zero.
            tzdict = {
                -7: "America/Los_Angeles",
                -4: "America/New_York",
                -5: "America/Chicago",
                -3: "America/Buenos_Aires",
                2: "Europe/Paris",
                1: "Europe/London",
            }
            timezone = tzdict[int(timezone[4:7])]
            tz = pytz.timezone(timezone)
            date = parse(date, dayfirst=True).date()
            start_time = tz.localize(
                datetime.datetime.combine(date,
                                          parse(start_time).time()))
            end_time = tz.localize(
                datetime.datetime.combine(date,
                                          parse(end_time).time()))
            # Check to see if a talk at this time in the seminar already exists
            curtalk = talks_lucky({
                "seminar_id": seminar_id,
                "speaker": speaker
            })
            if curtalk is not None:
                print(
                    "Talk with speaker %s already exists in seminar %s; continuing"
                    % (speaker, seminar_id))
                continue
            curtalk = talks_lucky({
                "seminar_id": seminar_id,
                "start_time": start_time
            })
            if curtalk is not None:
                print(
                    "Talk at time %s (speaker %s) already exists in seminar %s; continuing"
                    % (start_time.strftime("%a %b %d %-H:%M"), speaker,
                       seminar_id))
                continue
            topics = (arXiv.replace(" ", "").replace("Math.", "").replace(
                "math.", "").lower().split(","))
            if not topics:
                topics = []
            talks.append(
                dict(
                    title=title,
                    speaker=speaker,
                    speaker_affiliation=speaker_affiliation,
                    abstract=abstract,
                    topics=topics,
                    timezone=timezone,
                    start_time=start_time,
                    end_time=end_time,
                    display=True,
                    token="%016x" % random.randrange(16**16),
                    online=True,
                    live_link=seminar.live_link,
                    room=seminar.room,
                    access=seminar.access,
                    comments=seminar.comments,
                    seminar_id=seminar_id,
                    seminar_ctr=ctr[seminar_id],
                ))
            ctr[seminar_id] += 1
    return talks
Esempio n. 9
0
    def cleanse(self):
        """
        This function is used to ensure backward compatibility across changes to the schema and/or validation
        This is the only place where columns we plan to drop should be referenced 
        """
        from seminars.talk import talks_lucky

        if self.is_conference:
            self.frequency = None
            if not self.per_day:
                self.per_day = 4
        if self.frequency is None:
            self.weekdays = []
            self.time_slots = []
        else:
            if self.frequency > 1 and self.frequency <= 7:
                self.frequency = 7
            elif self.frequency > 7 and self.frequency <= 14:
                self.frequency = 14
            elif self.frequency > 14 and self.frequency <= 21:
                self.frequency = 21
            else:
                self.frequency = None
                self.weekdays = []
                self.time_slots = []
        if self.frequency and (not self.weekdays or not self.time_slots):
            self.weekdays = []
            self.time_slots = []
            if self.weekday is not None and self.start_time is not None and self.end_time is not None:
                self.weekdays = [self.weekday]
                self.time_slots = [self.start_time.strftime("%H:%M") + "-" + self.end_time.strftime("%H:%M")]
            else:
                now = datetime.now(tz=self.tz)
                t = talks_lucky(
                    {"seminar_id": self.shortname, "start_time": {"$gte": now}},
                    projection=["start_time", "end_time"],
                    sort=[("start_time",1)],
                    objects=False,
                )
                if not t:
                    t = talks_lucky(
                        {"seminar_id": self.shortname, "start_time": {"$lt": now}},
                        projection=["start_time", "end_time"],
                        sort=[("start_time", -1)],
                        objects=False,
                    )
                if t:
                    self.weekdays = [t["start_time"].weekday()]
                    self.time_slots = [t["start_time"].strftime("%H:%M") + "-" + t["end_time"].strftime("%H:%M")]
                else:
                    # Create a slot with an obviously bogus time in the hope that the user will notice and set it
                    self.weekdays = [0]
                    self.time_slots = ["00:00-01:00"]
        n = min(len(self.weekdays),len(self.time_slots))
        self.weekdays = self.weekdays[0:n]
        self.time_slots = self.time_slots[0:n]
        s = self.description
        self.description = s[0].upper() + s[1:] if s else ""
        if self.online and self.access_control is None:
            self.access_control = 0 if self.access == 'open' else self.access_control
            self.access_control = 3 if self.access in ['users', 'endorsed'] else self.access_control
            if self.live_link and "comments" in self.live_link:
                self.live_link = ""
                if self.homepage:
                    self.access_control = 5
                    self.access_registration = self.homepage
        if self.online and self.live_link and "comments" in self.live_link:
            self.live_link = ""
        # Port old subjects and topics to the new topic scheme
        if getattr(self, "subjects", []):
            def update_topic(topic):
                if topic in ["math", "physics", "bio"]:
                    return [topic]
                if topic in ["math_mp", "mp", "physics_math-ph"]:
                    return ["math", "physics", "math-ph"]
                if topic == "math_na":
                    return ["math", "cs", "math_NA"]
                if len(topic) == 2:
                    return ["math", "math_" + topic.upper()]
                if topic.startswith("math_"):
                    return ["math", "math_" + topic[5:].upper()]
                if topic.startswith("bio_bio_"):
                    return ["bio", "bio_" + topic[8:].upper()]
                assert topic.startswith("physics_")
                topic = topic[8:]
                if topic.startswith("nlin_"):
                    return ["physics", "nlin", topic]
                if topic.startswith("cond-mat_"):
                    return ["physics", "cond-mat", topic]
                if topic.startswith("nucl-"):
                    return ["physics", "nucl-ph", topic]
                if topic.startswith("hep-"):
                    return ["physics", "hep", topic]
                if topic.startswith("astro-ph_"):
                    return ["physics", "astro-ph", topic]
                return ["physics", topic]
            self.topics = sorted(set(sum([update_topic(topic) for topic in self.subjects + self.topics], [])))
        self.subjects = []
        # remove columns we plan to drop
        for attr in ["start_time","end_time","start_times","end_times","weekday","archived"]:
            killattr(self, attr)
        if self.level is None:
            self.level = 0
Esempio n. 10
0
    def convert_time_to_times(self):
        from seminars.talk import talks_lucky

        if self.is_conference:
            self.frequency = None
        if self.frequency is None:
            self.weekdays = []
            self.time_slots = []
            return
        if self.frequency > 1 and self.frequency <= 7:
            self.frequency = 7
        elif self.frequency > 7 and self.frequency <= 14:
            self.frequency = 14
        elif self.frequency > 14 and self.frequency <= 21:
            self.frequency = 21
        else:
            self.frequency = None
            self.weekdays = []
            self.time_slots = []
            return
        if not self.weekdays or not self.time_slots:
            self.weekdays = []
            self.time_slots = []
            if self.weekday is not None and self.start_time is not None and self.end_time is not None:
                self.weekdays = [self.weekday]
                self.time_slots = [
                    self.start_time.strftime("%H:%M") + "-" +
                    self.end_time.strftime("%H:%M")
                ]
            else:
                now = datetime.now(tz=self.tz)
                t = talks_lucky(
                    {
                        "seminar_id": self.shortname,
                        "start_time": {
                            "$gte": now
                        }
                    },
                    projection=["start_time", "end_time"],
                    sort=[("start_time", 1)],
                    objects=False,
                )
                if not t:
                    t = talks_lucky(
                        {
                            "seminar_id": self.shortname,
                            "start_time": {
                                "$lt": now
                            }
                        },
                        projection=["start_time", "end_time"],
                        sort=[("start_time", -1)],
                        objects=False,
                    )
                if t:
                    self.weekdays = [t["start_time"].weekday()]
                    self.time_slots = [
                        t["start_time"].strftime("%H:%M") + "-" +
                        t["end_time"].strftime("%H:%M")
                    ]
                else:
                    # Create a slot with an obviously bogus time in the hope that the user will notice and set it
                    self.weekdays = [0]
                    self.time_slots = ["00:00-01:00"]
        n = min(len(self.weekdays), len(self.time_slots))
        self.weekdays = self.weekdays[0:n]
        self.time_slots = self.time_slots[0:n]
Esempio n. 11
0
def make_date_data(seminar, data):
    tz = seminar.tz

    def parse_date(key):
        date = data.get(key)
        if date:
            try:
                return process_user_input(date, "date", tz)
            except ValueError:
                pass

    begin = parse_date("begin")
    end = parse_date("end")
    frequency = data.get("frequency")
    try:
        frequency = int(frequency)
    except Exception:
        frequency = None
    if not frequency or frequency < 0:
        frequency = seminar.frequency
        if not frequency or frequency < 0:
            frequency = 1 if seminar.is_conference else 7
    try:
        weekday = short_weekdays.index(data.get("weekday", "")[:3])
    except ValueError:
        weekday = None
    if weekday is None:
        weekday = seminar.weekday
    shortname = seminar.shortname
    day = datetime.timedelta(days=1)
    now = datetime.datetime.now(tz=tz)
    today = now.date()
    midnight_today = now.replace(hour=0, minute=0, second=0, microsecond=0)
    if begin is None or seminar.start_time is None or seminar.end_time is None:
        future_talk = talks_lucky(
            {
                "seminar_id": shortname,
                "start_time": {
                    "$exists": True,
                    "$gte": midnight_today
                }
            },
            sort=["start_time"])
        last_talk = talks_lucky(
            {
                "seminar_id": shortname,
                "start_time": {
                    "$exists": True,
                    "$lt": midnight_today
                }
            },
            sort=[("start_time", -1)],
        )

    if begin is None:
        if seminar.is_conference:
            if seminar.start_date:
                begin = seminar.start_date
            else:
                begin = today
        else:
            if weekday is not None and frequency == 7:
                begin = today
                # Will set to next weekday below
            else:
                # Try to figure out a plan from future and past talks
                if future_talk is None:
                    if last_talk is None:
                        # Give up
                        begin = today
                    else:
                        begin = last_talk.start_time.date()
                        while begin < today:
                            begin += frequency * day
                else:
                    begin = future_talk.start_time.date()
                    while begin >= today:
                        begin -= frequency * day
                    begin += frequency * day
    if not seminar.is_conference and seminar.weekday is not None:
        # Weekly meetings: take the next one
        while begin.weekday() != weekday:
            begin += day
    if end is None:
        if seminar.is_conference:
            if seminar.end_date:
                end = seminar.end_date
                schedule_len = int((end - begin) / (frequency * day)) + 1
            else:
                end = begin + 6 * day
                schedule_len = 7
        else:
            end = begin + (SCHEDULE_LEN - 1) * frequency * day
            schedule_len = SCHEDULE_LEN
    else:
        schedule_len = abs(int((end - begin) / (frequency * day))) + 1
    seminar.frequency = frequency
    data["begin"] = seminar.show_input_date(begin)
    data["end"] = seminar.show_input_date(end)
    midnight_begin = localize_time(
        datetime.datetime.combine(begin, datetime.time()), tz)
    midnight_end = localize_time(
        datetime.datetime.combine(end, datetime.time()), tz)
    # add a day since we want to allow talks on the final day
    if end < begin:
        # Only possible by user input
        frequency = -frequency
        query = {"$gte": midnight_end, "$lt": midnight_begin + day}
    else:
        query = {"$gte": midnight_begin, "$lt": midnight_end + day}
    schedule_days = [begin + i * frequency * day for i in range(schedule_len)]
    scheduled_talks = list(
        talks_search({
            "seminar_id": shortname,
            "start_time": query
        }))
    by_date = defaultdict(list)
    for T in scheduled_talks:
        by_date[adapt_datetime(T.start_time, tz).date()].append(T)
    all_dates = sorted(set(schedule_days + list(by_date)),
                       reverse=(end < begin))
    # Fill in by_date with Nones up to the per_day value
    for date in all_dates:
        by_date[date].extend([None] * (seminar.per_day - len(by_date[date])))
    if seminar.start_time is None:
        if future_talk is not None and future_talk.start_time:
            seminar.start_time = future_talk.start_time.time()
        elif last_talk is not None and last_talk.start_time:
            seminar.start_time = last_talk.start_time.time()
    if seminar.end_time is None:
        if future_talk is not None and future_talk.start_time:
            seminar.end_time = future_talk.end_time.time()
        elif last_talk is not None and last_talk.start_time:
            seminar.end_time = last_talk.end_time.time()
    return seminar, all_dates, by_date
Esempio n. 12
0
def make_date_data(seminar):
    shortname = seminar.shortname
    if not seminar.frequency or seminar.frequency < 0 or not seminar.schedule_len or seminar.schedule_len < 0 or seminar.schedule_len > 400:
        print(seminar.frequency, seminar.schedule_len)
        flash_error(
            "You must specify a meeting frequence to use the scheduler")
        return redirect(url_for("show_seminar", shortname=shortname),
                        301), None, None, None
    now = datetime.datetime.now(tz=pytz.utc)
    today = now.date()
    day = datetime.timedelta(days=1)
    last_talk = talks_lucky(
        {
            'seminar_id': shortname,
            'start_time': {
                '$lte': now
            }
        },
        sort=[('start_time', -1)])
    future_talks = list(
        talks_search({
            'seminar_id': shortname,
            'start_time': {
                '$gte': now
            }
        },
                     sort=['start_time']))
    by_date = {T.start_time.date(): T for T in future_talks}
    if len(by_date) != len(future_talks):
        flash_error(
            "Cannot use scheduler when there are multiple talks on the same day"
        )
        return redirect(url_for("show_seminar", shortname=shortname),
                        301), None, None, None
    if last_talk is None:
        if seminar.weekday is None:
            if not future_talks:
                flash_error(
                    "You must specify a weekday or add a talk to the seminar")
                return redirect(url_for("show_seminar", shortname=shortname),
                                301), None, None, None
            seminar.weekday = future_talks[0].start_time.date().weekday()
        next_date = today
        while next_date.weekday() != seminar.weekday:
            next_date += day
    else:
        next_date = last_talk.start_time.date()
        today = now.date()
        while next_date < today:
            next_date += seminar.frequency * day
    all_dates = sorted(
        set([
            next_date + i * seminar.frequency * day
            for i in range(seminar.schedule_len)
        ] + list(by_date)))
    if seminar.start_time is None:
        if future_talks:
            seminar.start_time = future_talks[0].start_time.time()
        elif last_talk is not None:
            seminar.start_time = last_talk.start_time.time()
    if seminar.end_time is None:
        if future_talks:
            seminar.end_time = future_talks[0].end_time.time()
        elif last_talk is not None:
            seminar.end_time = last_talk.end_time.time()
    return None, seminar, all_dates, by_date