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"]
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
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"}
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"]
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)
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"))
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
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 ""
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