Ejemplo n.º 1
0
def talks_parser(info, query):
    parse_subject(info, query, prefix="talk")
    parse_topic(info, query, prefix="talk")
    parse_institution_talk(info, query)
    #parse_venue(info, query, prefix="talk")
    parse_substring(info, query, "talk_keywords", [
        "title", "abstract", "speaker", "speaker_affiliation", "seminar_id",
        "comments", "speaker_homepage", "paper_link"
    ])
    parse_access(info, query, prefix="talk")

    parse_substring(info, query, "speaker", ["speaker"])
    parse_substring(info, query, "affiliation", ["speaker_affiliation"])
    parse_substring(info, query, "title", ["title"])
    parse_date(info, query)
    parse_video(info, query)
    parse_language(info, query, prefix="talk")
    query["display"] = True
    # TODO: remove this temporary measure allowing hidden to be None
    query["hidden"] = {"$or": [False, {"$exists": False}]}
    # These are necessary but not succificient conditions to display the talk
    # Also need that the seminar has visibility 2.

    # FIXME: temporary measure during addition of physics
    if topdomain() == "mathseminars.org":
        query["subjects"] = ["math"]
Ejemplo n.º 2
0
def ctx_proc_userdata():
    # insert an empty info={} as default
    # set the body class to some default, blueprints should
    # overwrite it with their name, using @<blueprint_object>.context_processor
    # see http://flask.pocoo.org/docs/api/?highlight=context_processor#flask.Blueprint.context_processor
    data = {"info": {}, "body_class": ""}

    # insert the default bread crumb hierarchy
    # overwrite this variable when you want to customize it
    # For example, [ ('Bread', '.'), ('Crumb', '.'), ('Hierarchy', '.')]
    data["bread"] = None

    # default title - Research seminars already included in base.html
    data["title"] = r""

    # meta_description appears in the meta tag "description"
    data[
        "meta_description"] = r"Welcome to {topdomain}, a list of research seminars and conferences!".format(
            topdomain=topdomain())
    data[
        "feedbackpage"] = r"https://docs.google.com/forms/d/e/1FAIpQLSdJNJ0MwBXzqZleN5ibAI9u1gPPu9Aokzsy08ot802UitiDRw/viewform"
    data["LINK_EXT"] = lambda a, b: '<a href="%s" target="_blank">%s</a>' % (b,
                                                                             a)

    # debug mode?
    data["DEBUG"] = is_debug_mode()

    data["top_menu"] = top_menu()

    data["talks_header"] = talks_header
    data["series_header"] = series_header
    data["static_knowl"] = static_knowl
    data["domain"] = domain()
    data["topdomain"] = topdomain()
    data["toggle"] = toggle
    data["toggle3way"] = toggle3way
    data["topic_dag"] = topic_dag
    data["languages"] = languages
    data["url_for_with_args"] = url_for_with_args
    data["db_read_only"] = db._read_only

    return data
Ejemplo n.º 3
0
def parse_topic(info, query):
    # of the talk
    topic = info.get("topic")
    if topic:
        # FIXME: temporary bridge during addition of physics
        if "_" not in topic:
            topic = "math_" + topic
        query["topics"] = {"$or": [{"$contains": topic}, {"$contains": topic[5:]}]}
    # FIXME: temporary measure during addition of physics
    elif topdomain() == "mathseminars.org":
        query["topic"] = {"$contains": "math"}
Ejemplo n.º 4
0
def seminars_parser(info, query):
    parse_subject(info, query, prefix="seminar")
    parse_topic(info, query, prefix="seminar")
    parse_institution_sem(info, query)
    #parse_venue(info, query, prefix="seminar")
    parse_substring(
        info, query, "seminar_keywords",
        ["name", "description", "homepage", "shortname", "comments"])
    parse_access(info, query, prefix="seminar")
    parse_language(info, query, prefix="seminar")

    parse_substring(info, query, "name", ["name"])
    query["display"] = True
    query["visibility"] = 2

    # FIXME: temporary measure during addition of physics
    if topdomain() == "mathseminars.org":
        query["subjects"] = ["math"]
Ejemplo n.º 5
0
def _talks_index(query={}, sort=None, subsection=None, past=False):
    # Eventually want some kind of cutoff on which talks are included.
    query = dict(query)
    subs = subject_pairs()
    hide_filters = []
    if "subjects" in query:
        subject = query["subjects"]["$contains"]
        hide_filters = ["subject"]
        subs = ((subject, subject.capitalize()), )
    elif "topics" in query:
        hide_filters = ["subject", "topic"]
    elif topdomain() == "mathseminars.org":
        query["subjects"] = ["math"]
    query["display"] = True
    query["hidden"] = {"$or": [False, {"$exists": False}]}
    if past:
        query["end_time"] = {"$lt": datetime.now()}
        if sort is None:
            sort = [("start_time", -1), "seminar_id"]
    else:
        query["end_time"] = {"$gte": datetime.now()}
        if sort is None:
            sort = ["start_time", "seminar_id"]
    talks = list(talks_search(query, sort=sort, seminar_dict=all_seminars()))
    # Filtering on display and hidden isn't sufficient since the seminar could be private
    talks = [talk for talk in talks if talk.searchable()]
    counters = _get_counters(talks)
    row_attributes = _get_row_attributes(talks)
    return render_template("browse_talks.html",
                           title="Browse talks",
                           hide_filters=hide_filters,
                           subjects=subs,
                           section="Browse",
                           subsection=subsection,
                           talk_row_attributes=zip(talks, row_attributes),
                           past=past,
                           **counters)
Ejemplo n.º 6
0
def get_endorsing_link():
    email = request.form["email"].strip()
    try:
        email = validate_email(email)["email"]
    except EmailNotValidError as e:
        flash_error("""Oops, email '%s' is not allowed. %s""", email, str(e))
        return redirect(url_for(".info"))
    rec = userdb.lookup(email, ["name", "creator", "email_confirmed"])
    if rec is None or not rec["email_confirmed"]:  # No account or email unconfirmed
        if db.preendorsed_users.count({'email':email}):
            endorsing_link = "<p>{0} has already been pre-endorsed.</p>".format(email)
        else:
            db.preendorsed_users.insert_many([{"email": email, "endorser": current_user._uid}])
            to_send = """Hello,

    I am offering you permission to add content (e.g., create a seminar)
    on the {topdomain} website.

    To accept this invitation:

    1. Register at {register} using this email address.

    2. Click on the link the system emails you, to confirm your email address.

    3. Now any content you create will be publicly viewable.


    Best,
    {name}
    """.format(
                name = current_user.name,
                topdomain = topdomain(),
                register = url_for('.register', _external=True, _scheme='https'),
            )
            data = {
                "body": to_send,
                "subject": "An invitation to collaborate on " + topdomain(),
            }
            endorsing_link = """
    <p>
    When {email} registers and confirms their email they will be able to create content.</br>
    <button onClick="window.open('mailto:{email}?{msg}')">
    Send email
    </button> to let them know.
    </p>
    """.format(
                email=email, msg=urlencode(data, quote_via=quote)
            )
    else:
        target_name = rec["name"]
        if rec["creator"]:
            endorsing_link = "<p>{target_name} is already able to create content.</p>".format(target_name=target_name)
        else:
            welcome = "Hello" if not target_name else ("Dear " + target_name)
            to_send = """{welcome},<br>
<p>
You have been endorsed you on {topdomain} and any content you create will
be publicly viewable.
</p>
<p>
Thanks for using {topdomain}!
</p>

""".format(
                welcome = welcome,
                topdomain = topdomain()
            )
            subject = "Endorsement to create content on " + topdomain()
            send_email(email, subject, to_send)
            userdb.make_creator(email, int(current_user.id))
            endorsing_link = "<p>{target_name} is now able to create content.</p> ".format(
                target_name=target_name if target_name else email
            )
    session["endorsing link"] = endorsing_link
    return redirect(url_for(".info"))
Ejemplo n.º 7
0
def _talks_index(
    query={},
    sort=None,
    subsection=None,
    past=False,
    keywords="",
    limit=None,  # this is an upper bound on desired number of talks, we might filter some extra out
    limitbuffer=1000,  # the number of extra talks that we give ourselves to try to get the limit right
    asblock=False,  # the number of talks returned is based on star time blocks
    getcounters=True,  # doesn't limit the SQL search to get the full counters
    visible_counter=0,
    fully_filtered=True,
):
    # Eventually want some kind of cutoff on which talks are included.
    search_array = TalkSearchArray(past=past)
    info = to_dict(read_search_cookie(search_array), search_array=search_array)
    info.update(request.args)
    if keywords:
        info["keywords"] = keywords
    keywords = info.get("keywords", "")
    query = dict(query)
    parse_substring(info, query, "keywords", [
        "title", "abstract", "speaker", "speaker_affiliation", "seminar_id",
        "comments", "speaker_homepage", "paper_link"
    ])
    more = {
    }  # we will be selecting talks satsifying the query and recording whether they satisfy the "more" query
    # Note that talks_parser ignores the "time" field at the moment; see below for workaround
    talks_parser(info, more)
    if topdomain() == "mathseminars.org":
        query["topics"] = {"$contains": "math"}
    query["display"] = True
    query["hidden"] = {"$or": [False, {"$exists": False}]}
    query["audience"] = {"$lte": DEFAULT_AUDIENCE}
    now = datetime.now(pytz.UTC)
    if past:
        query["end_time"] = {"$lt": now}
        query["seminar_ctr"] = {"$gt": 0}  # don't show rescheduled talks
        if sort is None:
            sort = [("start_time", -1), "seminar_id"]
    else:
        query["end_time"] = {"$gte": now}
        if sort is None:
            sort = ["start_time", "seminar_id"]

    def dosearch(limit=limit, limitbuffer=limitbuffer):
        if limit and not getcounters:
            # we fetch extra talks to account for filtering
            talks = talks_search(query,
                                 sort=sort,
                                 seminar_dict=all_seminars(),
                                 more=more,
                                 limit=limit + limitbuffer)
        else:
            talks = talks_search(query,
                                 sort=sort,
                                 seminar_dict=all_seminars(),
                                 more=more)
        # Filtering on display and hidden isn't sufficient since the seminar could be private
        talks = [talk for talk in talks if talk.searchable()]
        return talks

    def truncateasblock(talks, retry=True):
        if not talks:
            return talks
        last_time = None
        # find enough talks such that the next talk has a different starting time
        for i, t in enumerate(talks):
            if last_time is None:
                last_time = t.start_time
                continue
            if t.start_time != last_time:
                if i > limit:
                    return talks[:i - 1]
                else:
                    last_time = t.start_time
        else:
            if retry and limit and not getcounters:
                # redo the search without limits
                talks = dosearch(limit=None)
                return truncateasblock(talks, retry=False)
            return talks

    def truncate(talks):
        if asblock and limit:
            return truncateasblock(talks)
        elif limit:
            return talks[:limit]
        else:
            return talks

    talks = dosearch()
    if getcounters:
        counters = _get_counters(talks)
    else:
        counters = _get_counters([])

    if getcounters and fully_filtered:
        # the initial query was not limited as getcounters = True
        # we will first filter after figuring out the more attribute
        # and then truncate
        pass
    else:
        # we are not going to filter or the query was already limited, so we can truncate
        talks = truncate(talks)
    # While we may be able to write a query specifying inequalities on the timestamp in the user's timezone, it's not easily supported by talks_search.  So we filter afterward
    timerange = info.get("timerange", "").strip()
    if timerange:
        tz = current_user.tz
        try:
            timerange = process_user_input(timerange,
                                           col="search",
                                           typ="daytimes")
        except ValueError:
            try:
                onetime = process_user_input(timerange,
                                             col="search",
                                             typ="daytime")
            except ValueError:
                flash_error("Invalid time range input: %s", timerange)
            else:
                for talk in talks:
                    if talk.more:
                        talkstart = adapt_datetime(talk.start_time, tz)
                        t = date_and_daytime_to_time(talkstart.date(), onetime,
                                                     tz)
                        talk.more = (t == talkstart)
        else:
            for talk in talks:
                if talk.more:
                    talkstart = adapt_datetime(talk.start_time, tz)
                    talkend = adapt_datetime(talk.end_time, tz)
                    t0, t1 = date_and_daytimes_to_times(
                        talkstart.date(), timerange, tz)
                    talk.more = (t0 <= talkstart) and (talkend <= t1)

    # get last_time before potential filtering
    last_time = int(talks[-1].start_time.timestamp()) if talks else None
    if fully_filtered:  # first filter then truncate
        row_attributes, talks = _get_row_attributes(talks, visible_counter,
                                                    fully_filtered)
        if getcounters:  # we have not yet truncated the results
            if limit and len(talks) > limit:
                talks = truncate(talks)
                row_attributes = row_attributes[:len(talks)]
                last_time = int(
                    talks[-1].start_time.timestamp()) if talks else None
    else:
        row_attributes = _get_row_attributes(talks, visible_counter)

    response = make_response(
        render_template("browse_talks.html",
                        title="Browse past talks" if past else "Browse talks",
                        section="Browse",
                        info=info,
                        subsection=subsection,
                        talk_row_attributes=zip(talks, row_attributes),
                        past=past,
                        last_time=last_time,
                        extraargs=urlencode({'keywords': keywords}),
                        **counters))
    if request.cookies.get("topics", ""):
        # TODO: when we move cookie data to server with ajax calls, this will need to get updated again
        # For now we set the max_age to 30 years
        response.set_cookie("topics_dict",
                            topic_dag.port_cookie(),
                            max_age=60 * 60 * 24 * 365 * 30)
        response.set_cookie("topics", "", max_age=0)

    # disable cache
    response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
    response.headers['Pragma'] = 'no-cache'
    return response
Ejemplo n.º 8
0
    def show_live_link(self, user=None, raw=False):
        if user is None: user = current_user
        now = datetime.now(pytz.utc)
        if any([self.deleted, not self.online, self.is_really_over()]):
            return ""
        link = self.live_link

        def show_link(self, user=None, raw=False):
            if user is None: user = current_user
            link = self.live_link
            if raw:
                return link if link else ''
            if not link:
                return '<div class=access_button no_link">Livestream link not yet posted by organizers</div>'
            if self.access_control == 4 and not self.user_is_registered(user):
                link = url_for("register_for_talk", seminar_id=self.seminar_id, talkid=self.seminar_ctr)
                if self.is_starting_soon():
                    return '<div class="access_button is_link starting_soon"><b> <a href="%s">Instantly register and join livestream <i class="play filter-white"></i> </a></b></div>' % link
                else:
                    return '<div class="access_button is_link"> <a href="%s">Instantly register</a> for livestream access</div>' % link
            if self.is_starting_soon():
                return '<div class="access_button is_link starting_soon"><b> <a href="%s">Join livestream <i class="play filter-white"></i> </a></b></div>' % link
            else:
                return '<div class="access_button is_link"> Livestream access <a href="%s">available</a></div>' % link

        if self.access_control in [0,2]: # password hint will be shown nearby, not our problem
            return show_link(self, user=user, raw=raw)
        elif self.access_control == 1:
            show_link_time = self.start_time - timedelta(minutes=self.access_time)
            if show_link_time <= now:
                return show_link(self, user=user, raw=raw)
            else:
                return "" if raw else '<div class="access_button no_link">Livestream access available in %s</div>' % how_long(show_link_time-now)
        elif self.access_control == 2:
            return show_link(self, user=user, raw=raw)
        elif self.access_control in [3,4]:
            if raw:
                return url_for("show_talk", seminar_id=self.seminar_id, talkid=self.seminar_ctr)
            if user.is_anonymous:
                link = url_for("user.info", next=url_for("register_for_talk", seminar_id=self.seminar_id, talkid=self.seminar_ctr))
                return '<div class="access_button no_link"><a href="%s">Login required</a> for livestream access</b></div>' % link
            elif not user.email_confirmed:
                return '<div class="access_button no_link">Please confirm your email address for livestream access</div>'
            else:
                return show_link(self, user=user, raw=raw)
        elif self.access_control == 5:
            if not user.is_anonymous and db.seminar_registrations.lucky({'seminar_id':self.seminar_id,'email':user.email}):
                if not user.email_confirmed:
                    return '<div class="access_button no_link">Please confirm your email address for livestream access</div>'
                else:
                    return show_link(self, user=user, raw=raw)
            # If there is a view-only link, show that rather than an external registration link
            if raw:
                return url_for("show_talk", seminar_id=self.seminar_id, talkid=self.seminar_ctr)
            if not self.access_registration:
                # This should never happen, registration link is required, but just in case...
                return "" if raw else '<div class="access_button no_link">Registration required, see comments or external site.</a></div>' % link
            if "@" in self.access_registration:
                body = """Dear organizers,

I am interested in attending the talk

    {talk}

by {speaker}, in the series

    {series}

listed at https://{domain}{url}.

Thank you,

{user}
""".format(
                    talk = self.title,
                    speaker = self.show_speaker(raw=True),
                    series = self.seminar.name,
                    domain = topdomain(),
                    url = url_for('show_talk', seminar_id=self.seminar.shortname, talkid=self.seminar_ctr),
                    user = user.name)
                msg = { "body": body, "subject": "Request to attend %s" % self.seminar.shortname }
                link = "mailto:%s?%s" % (self.access_registration, urlencode(msg, quote_via=quote))
            else:
                link = self.access_registration
            return '<div class="access_button no_link"><a href="%s">Register</a> for livestream access</div>' % link
        else:  # should never happen
            log_error("invalid or unknown access control value %s for talk %s/%s" % (self.access_control, self.seminar_id, self.seminar_ctr))
            return ""
Ejemplo n.º 9
0
def _talks_index(query={}, sort=None, subsection=None, past=False):
    # Eventually want some kind of cutoff on which talks are included.
    search_array = TalkSearchArray(past=past)
    info = to_dict(read_search_cookie(search_array), search_array=search_array)
    info.update(request.args)
    query = dict(query)
    parse_substring(info, query, "keywords",
                    ["title",
                     "abstract",
                     "speaker",
                     "speaker_affiliation",
                     "seminar_id",
                     "comments",
                     "speaker_homepage",
                     "paper_link"])
    more = {} # we will be selecting talks satsifying the query and recording whether they satisfy the "more" query
    # Note that talks_parser ignores the "time" field at the moment; see below for workaround
    talks_parser(info, more)
    if topdomain() == "mathseminars.org":
        query["topics"] = {"$contains": "math"}
    query["hidden"] = {"$or": [False, {"$exists": False}]}
    if past:
        query["end_time"] = {"$lt": datetime.now()}
        if sort is None:
            sort = [("start_time", -1), "seminar_id"]
    else:
        query["end_time"] = {"$gte": datetime.now()}
        if sort is None:
            sort = ["start_time", "seminar_id"]
    talks = list(talks_search(query, sort=sort, seminar_dict=all_seminars(), more=more))
    # Filtering on display and hidden isn't sufficient since the seminar could be private
    talks = [talk for talk in talks if talk.searchable()]
    # While we may be able to write a query specifying inequalities on the timestamp in the user's timezone, it's not easily supported by talks_search.  So we filter afterward
    timerange = info.get("timerange", "").strip()
    if timerange:
        tz = current_user.tz
        try:
            timerange = process_user_input(timerange, col="search", typ="daytimes")
        except ValueError:
            try:
                onetime = process_user_input(timerange, col="search", typ="daytime")
            except ValueError:
                flash_error("Invalid time range input: %s", timerange)
            else:
                for talk in talks:
                    if talk.more:
                        talkstart = adapt_datetime(talk.start_time, tz)
                        t = date_and_daytime_to_time(talkstart.date(), onetime, tz)
                        talk.more = (t == talkstart)
        else:
            for talk in talks:
                if talk.more:
                    talkstart = adapt_datetime(talk.start_time, tz)
                    talkend = adapt_datetime(talk.end_time, tz)
                    t0, t1 = date_and_daytimes_to_times(talkstart.date(), timerange, tz)
                    talk.more = (t0 <= talkstart) and (talkend <= t1)
    counters = _get_counters(talks)
    row_attributes = _get_row_attributes(talks)
    response = make_response(render_template(
        "browse_talks.html",
        title="Browse talks",
        section="Browse",
        info=info,
        subsection=subsection,
        talk_row_attributes=zip(talks, row_attributes),
        past=past,
        **counters
    ))
    if request.cookies.get("topics", ""):
        # TODO: when we move cookie data to server with ajax calls, this will need to get updated again
        # For now we set the max_age to 30 years
        response.set_cookie("topics_dict", topic_dag.port_cookie(), max_age=60*60*24*365*30)
        response.set_cookie("topics", "", max_age=0)
    return response