def summary(): error = '' respheaders = None results = None try: results, respheaders = helpers.rxapi(f"/v1/data/summary", headers=True) except Exception as e: print(e) error = f"Sorry—there was a problem retrieving the results: {e}" bottle.response.status = 500 # Figure out the top categories: top_cats = [] for cat in results['submissions_categorical']: top_cats.append({ 'category': cat['label'], 'count': cat['data'][-1]['count'] }) def sorter(x): # little helper function that sorts the categories # based on the most recent month's submissions return x['count'] top_cats = sorted(top_cats, key=sorter, reverse=True) stats = helpers.rxapi("/v1/data/stats") return bottle.template('summary', results=results, top_cats=top_cats, error=error, stats=stats, google_tag=config.google_tag)
def display_author_details(id): try: get = requests.get(f"{config.rxapi}/v1/authors/{id}") if get.status_code == 404: raise helpers.NotFoundError(id) # make sure the URL we ended at matches the URL we asked for: new_id = re.search('/(\d+)$', get.url) if new_id and len(new_id.groups()) > 0: try: new_id = int(new_id.group(1)) except Exception: bottle.response.status = 500 return {"error": "Server errror."} if new_id != id: # if we got redirected to a new URL return bottle.redirect(f"{config.host}/authors/{new_id}", 301) author = get.json() except helpers.NotFoundError as e: bottle.response.status = 404 return e.message except ValueError as e: bottle.response.status = 500 print(e) return {"error": "Server error."} distro = helpers.rxapi("/v1/data/distributions/author/downloads") download_distribution = distro["histogram"] averages = distro["averages"] stats = helpers.rxapi("/v1/data/stats") return bottle.template('author_details', author=author, download_distribution=download_distribution, averages=averages, stats=stats, google_tag=config.google_tag)
def topyear(year): error = '' respheaders = None results = None if year < 2013: error = "Lists currently available only for 2013 through 2018." bottle.response.status = 404 try: results, respheaders = helpers.rxapi(f"/v1/top/{year}", headers=True) except Exception as e: print(e) error = f"Sorry—there was a problem retrieving the results: {e}" bottle.response.status = 500 # if respheaders is not None and "Cache-Control" in respheaders.keys(): # bottle.response.set_header("Cache-Control", respheaders["Cache-Control"]) bottle.response.set_header("Cache-Control", 'max-age=600, stale-while-revalidate=172800') stats = helpers.rxapi("/v1/data/stats") yearstats = { # TODO: Put this in the API 2013: { "papers": 109, "downloads": 17268 }, 2014: { "papers": 886, "downloads": 311046 }, 2015: { "papers": 1774, "downloads": 679159 }, 2016: { "papers": 4718, "downloads": 2182836 }, 2017: { "papers": 11342, "downloads": 3995108 }, 2018: { "papers": 20050, "downloads": 5730324 } } return bottle.template('top_year', results=results['results'], year=year, yearpapers=yearstats[year]['papers'], yeardownloads = yearstats[year]['downloads'], error=error, stats=stats, google_tag=config.google_tag)
def build_docs(): category_list = helpers.rxapi("/v1/data/categories")[ "results"] # list of all article categories return docmodels.Documentation("https://api.rxivist.org/v1", [ papers(category_list), authors(category_list), apidetails(), ])
def display_paper_details(paper_id): try: paper = requests.get(f"{config.rxapi}/v1/papers/{paper_id}") except helpers.NotFoundError as e: bottle.response.status = 404 return e.message except ValueError as e: bottle.response.status = 500 print(e) return {"error": "Server error."} # make sure the URL we ended at matches the URL we asked for: new_id = re.search('/(\d+)$', paper.url) if new_id and len(new_id.groups()) > 0: try: new_id = str(new_id.group(1)) paper_id = str(paper_id) except Exception: bottle.response.status = 500 return {"error": "Server error."} if new_id != paper_id: # if we got redirected to a new URL return bottle.redirect(f"{config.host}/papers/{new_id}", 301) paper = paper.json() downloads = helpers.rxapi(f"/v1/downloads/{paper_id}")["results"] # Convert the API response into something we can pass to the generic # template for the graph: traffic = [{ 'month': x['month'], 'year': x['year'], 'count': x['downloads'] } for x in downloads] distro = helpers.rxapi("/v1/data/distributions/paper/downloads") download_distribution = distro["histogram"] averages = distro["averages"] stats = helpers.rxapi("/v1/data/stats") return bottle.template('paper_details', paper=paper, traffic=traffic, download_distribution=download_distribution, averages=averages, stats=stats, google_tag=config.google_tag)
def index(): error = "" view = bottle.request.query.view if view is None or view not in ["standard", "print"]: view = "standard" entity = bottle.request.query.entity if entity is None or entity == "": entity = "papers" category_list = helpers.rxapi("/v1/data/categories")["results"] stats = helpers.rxapi("/v1/data/stats") results = {} # a list of articles for the current page respheaders = None try: if entity == "authors": category_filter = bottle.request.query.getall('category') if len(category_filter) == 0: category = "" else: category = category_filter[0] # just one category for author ranks for now category_filter = [category_filter[0]] results = helpers.rxapi(f"/v1/authors?category={category}") elif entity == "papers": results, respheaders = helpers.rxapi(f"/v1/papers?{bottle.request.query_string}", headers=True) except Exception as e: print(e) error = f"There was a problem with the submitted query: {e}" bottle.response.status = 500 # Take the current query string and turn it into a template that any page # number can get plugged into: if "page=" in bottle.request.query_string: pagelink = "/?{}".format(re.sub(r"page=\d*", "page=", bottle.request.query_string)) else: pagelink = f"/?{bottle.request.query_string}&page=" metric = "" timeframe = "" page = "" page_size = "" totalcount = "" query = "" if entity == "papers": try: metric = results["query"]["metric"] timeframe = results["query"]["timeframe"] category_filter = results["query"]["categories"] page = results["query"]["current_page"] page_size = results["query"]["page_size"] totalcount = results["query"]["total_results"] query = results["query"]["text_search"] except Exception as e: if "error" in results.keys(): error = results["error"] else: error = str(e) # TODO: this is bad return error results = results["results"] # figure out the page title if entity == "papers": title = "Most " if metric == "twitter": title += "tweeted" elif metric == "downloads": title += "downloaded" if query != "": title += f" papers related to \"{query},\" " else: title += " bioRxiv papers, " printable_times = { "alltime": "all time", "ytd": "year to date", "lastmonth": "since beginning of last month", "day": "last 24 hours", "week": "last 7 days", "month": "last 30 days", "year": "last 365 days" } title += printable_times[timeframe] elif entity == "authors": title = "Authors with most downloads, all-time" if bottle.request.query_string == "": bottle.response.set_header("Cache-Control", f"max-age={config.front_page_cache}, stale-while-revalidate=172800") # use whatever cache-control headers are sent to us from the API if respheaders is not None and "Cache-Control" in respheaders.keys(): bottle.response.set_header("Cache-Control", respheaders["Cache-Control"]) temp = 'print' if view == "print" else 'index' return bottle.template(temp, results=results, query=query, category_filter=category_filter, title=title, error=error, stats=stats, category_list=category_list, view=view, timeframe=timeframe, metric=metric, entity=entity, google_tag=config.google_tag, page=page, page_size=page_size, totalcount=totalcount, pagelink=pagelink, querystring=bottle.request.query_string)
def api_docs(): stats = helpers.rxapi("/v1/data/stats") documentation = docs.build_docs() return bottle.template("api_docs", google_tag=config.google_tag, stats=stats, docs=documentation)
def privacy(): stats = helpers.rxapi("/v1/data/stats") return bottle.template("newsletter", google_tag=config.google_tag, stats=stats)
def emailcode(): results, _ = helpers.rxapi(f"/v1/papers?timeframe=week&page_size=20", headers=True) results = results["results"] bottle.response.set_header("Cache-Control", f"max-age=0, stale-while-revalidate=0") return bottle.template('emailtemplate', results=results)