def remove_article_from_brainspell_database_collection(collection, pmid, api_key, cold_run=True): """ Remove an article from the Brainspell repo. Do not affect GitHub. Takes collection_name *without* "brainspell-collection". Similar implementation to add_article_to_brainspell_database_collection. """ user = get_user_object_from_api_key(api_key) if user.count > 0: user = list(user)[0] if user.collections: # assumes collections are well-formed JSON target = json_decode(user.collections) if collection in target: pmids_list = list( map(lambda x: str(x), target[collection]["pmids"])) if str(pmid) in pmids_list: pmids_list.remove(str(pmid)) target[collection]["pmids"] = pmids_list if not cold_run: q = User.update(collections=json_encode(target)).where( User.password == api_key) q.execute() return True else: return False # article not in collection else: return False # collection doesn't exist else: return False # user has no collections; violates assumptions return False # user does not exist
def bulk_add_articles_to_brainspell_database_collection( collection, pmids, api_key, cold_run=True): """ Adds the PMIDs to collection_name, if such a collection exists under the given user. Assumes that the collection exists. Does not add repeats. Takes collection_name *without* "brainspell-collection". Return False if an assumption is violated, True otherwise. """ user = get_user_object_from_api_key(api_key) if user.count > 0: user = list(user)[0] if user.collections: # assumes collections are well-formed JSON target = json_decode(user.collections) if collection not in target: target[collection] = {"description": "None", "pmids": []} pmid_set = set(map(lambda x: str(x), target[collection]["pmids"])) for pmid in pmids: pmid_set.add(str(pmid)) target[collection]["pmids"] = list(pmid_set) if not cold_run: q = User.update(collections=json_encode(target)).where( User.password == api_key) q.execute() return True else: return False # user has no collections; violates assumptions return False # user does not exist
def get_boolean_map_from_article_object(article, width=5): """ Return a Brain of 0s and 1s corresponding to if any coordinate exists at that location, in any of the article's experiment tables. """ brain = Brain() try: experiments = json_decode(article.experiments) for exp in experiments: locations = exp["locations"] for coord_string in locations: coord = coord_string.split(",") try: # assumes that coordinates are well-formed coord_tuple = (int(float(coord[0])), int(float(coord[1])), int(float(coord[2]))) brain.insert_at_location(1, *coord_tuple, width=width) except BaseException as e: # malformed coordinate print(e) pass except BaseException as e: # article not valid, or malformed JSON print(e) pass return brain
def __get_current_github_object__(self): """ Return an object representing the user's name, avatar, and access_token, or None is the user is not logged in. Technically a "private" method; please use the get_current_* methods. """ try: return json_decode(self.get_secure_cookie("user")) except BaseException: return None
def get_brainspell_collections_from_api_key(api_key): """ Return a user's collections from Brainspell's database given an API key. May be inconsistent with GitHub. """ response = {} if valid_api_key(api_key): user = list(get_user_object_from_api_key(api_key))[0] if user.collections: return json_decode(user.collections) return response
def add_article_to_brainspell_database_collection( collection, pmid, api_key, cold_run=True): """ Add a collection to our local database. Do not add to GitHub in this function. Assumes that the collection already exists. Assumes that the user exists. Takes collection_name *without* "brainspell-collection". Returns False if the article is already in the collection, or if an assumption is violated. This is an O(N) operation with respect to the collection size. If you're adding many articles, it's O(N^2). If you're adding multiple articles, please use bulk_add_articles_to_brainspell_database_collection. Called by AddToCollectionEndpointHandler. """ user = get_user_object_from_api_key(api_key) if user.count > 0: user = list(user)[0] if user.collections: # assumes collections are well-formed JSON target = json_decode(user.collections) if collection not in target: target[collection] = { "description": "None", "pmids": [] } pmids_list = set( map(lambda x: str(x), target[collection]["pmids"])) # provide a check for if the PMID is already in the collection if str(pmid) not in pmids_list: pmids_list.add(str(pmid)) target[collection]["pmids"] = list(pmids_list) if not cold_run: q = User.update( collections=json_encode(target)).where( User.password == api_key) q.execute() return True else: return False # article already in collection else: return False # user has no collections; violates assumptions return False # user does not exist
def register_github_user(user_dict): """ Add a GitHub user to our database. """ user_dict = json_decode(user_dict) # if the user doesn't already exist if (User.select().where(User.username == user_dict["login"]).execute().count == 0): username = user_dict["login"] email = user_dict["email"] hasher = hashlib.sha1() # password (a.k.a. API key) is a hash of the Github ID hasher.update(str(user_dict["id"]).encode('utf-8')) password = hasher.hexdigest() User.create(username=username, emailaddress=email, password=password) return True else: return False # user already exists
def get_current_user(self): user_json = self.get_secure_cookie("user") if not user_json: return None return json_decode(user_json)
def get_current_user(self): user_json = self.get_secure_cookie("user") if not user_json: return None return json_decode(user_json)
def process(self, response, args): collection = args["name"] pmid = args["pmid"] if remove_article_from_brainspell_database_collection( collection, pmid, args["key"]): github_username = get_github_username_from_api_key(args["key"]) github_collection_name = "brainspell-collection-{}".format( collection) try: content_data = yield torngithub.github_request( self.get_auth_http_client(), '/repos/{owner}/{repo}/contents/{path}'.format( owner=github_username, repo=github_collection_name, path="manifest.json"), access_token=args["github_access_token"], method="GET") content = content_data["body"]["content"] # get the SHA so we can update this file manifest_sha = content_data["body"]["sha"] # parse the manifest.json file for the collection collection_contents = json_decode( b64decode(content.encode('utf-8')).decode('utf-8')) collection_contents = [ c for c in collection_contents if str(c["pmid"]) != pmid ] manifest_contents_encoded = b64encode( json_encode(collection_contents).encode("utf-8")).decode( 'utf-8') update_manifest_body = { "message": "creating manifest.json file", "content": manifest_contents_encoded, "sha": manifest_sha } update_manifest_ress = yield [ torngithub.github_request( self.get_auth_http_client(), '/repos/{owner}/{repo}/contents/{path}'.format( owner=github_username, repo=github_collection_name, path="manifest.json"), access_token=args["github_access_token"], method="PUT", body=update_manifest_body) ] except Exception as e: print(e) response["success"] = 0 response[ "description"] = "There was some failure in communicating with GitHub." finally: if response["success"] != 0: # only remove from Brainspell collection if the GitHub # operation succeeded remove_article_from_brainspell_database_collection( collection, pmid, args["key"], False) else: response["success"] = 0 response[ "description"] = "That article doesn't exist in that collection." self.finish_async(response)
def callback_function(github_response=None): # check if the article is already in this collection # doesn't matter if we're bulk adding if args["bulk_add"] == 1 or add_article_to_brainspell_database_collection( name, args["pmid"], args["key"]): pmid = args["pmid"] # idempotent operation to create the Brainspell collection # if it doesn't already exist (guaranteed that it exists on # GitHub) add_collection_to_brainspell_database(name, "None", args["key"], False) # make a single PMID into a list so we can treat it the same # way if args["bulk_add"] == 0: pmid = "[" + pmid + "]" pmid_list = json_decode(pmid) # add all of the PMIDs to GitHub, then insert to Brainspell github_username = get_github_username_from_api_key(args["key"]) github_collection_name = "brainspell-collection-{}".format( name) content_data = yield torngithub.github_request( self.get_auth_http_client(), '/repos/{owner}/{repo}/contents/{path}'.format( owner=github_username, repo=github_collection_name, path="manifest.json"), access_token=args["github_access_token"], method="GET") content = content_data["body"]["content"] # get the SHA so we can update this file manifest_sha = content_data["body"]["sha"] # parse the manifest.json file for the collection collection_contents = json_decode( b64decode(content.encode('utf-8')).decode('utf-8')) article_set = set([c["pmid"] for c in collection_contents]) for p in pmid_list: if p not in article_set: # create the entry to add to the GitHub repo article = list(get_article_object(p))[0] article_entry = { "pmid": p, "title": article.title, "reference": article.reference, "doi": article.doi, "notes": "Here are my notes on this article." } collection_contents.append(article_entry) article_set.add(p) manifest_contents_encoded = b64encode( json_encode(collection_contents).encode("utf-8")).decode( 'utf-8') update_manifest_body = { "message": "creating manifest.json file", "content": manifest_contents_encoded, "sha": manifest_sha } update_manifest_ress = yield [ torngithub.github_request( self.get_auth_http_client(), '/repos/{owner}/{repo}/contents/{path}'.format( owner=github_username, repo=github_collection_name, path="manifest.json"), access_token=args["github_access_token"], method="PUT", body=update_manifest_body) ] # actually add the article(s) if the request succeeds bulk_add_articles_to_brainspell_database_collection( name, pmid_list, args["key"], False) else: response["success"] = 0 response[ "description"] = "That article already exists in that collection." self.finish_async(response)
def process(self, response, args): collections_list = [] # get all repos for an authenticated user using GitHub # need to use GitHub, because not storing "contributors_url" in # Brainspell's database data = yield get_user_repos(self.get_auth_http_client(), args["github_access_token"]) repos = [ d for d in data if d["name"].startswith("brainspell-collection-") ] if args["force_github_refresh"] == 1: remove_all_brainspell_database_collections(args["key"]) # get all repos using the Brainspell database brainspell_cache = get_brainspell_collections_from_api_key(args["key"]) # for each repo for repo_contents in repos: # guaranteed that the name starts with "brainspell-collection" # (from above) collection_name = repo_contents["name"][ len("brainspell-collection-"):] repo = { # take the "brainspell-collection" off of the name "name": collection_name, "description": repo_contents["description"] } # get the contributor info for this collection contributor_info = yield torngithub.github_request( self.get_auth_http_client(), repo_contents["contributors_url"].replace( "https://api.github.com", ""), access_token=args["github_access_token"], method="GET") repo["contributors"] = [] if contributor_info["body"]: repo["contributors"] = contributor_info["body"] # get the PMIDs in the collection description = repo_contents["description"] valid_collection = True # if there's a new GitHub collection added to the user's profile, # then add it if collection_name not in brainspell_cache: try: # fetch the PMIDs from GitHub github_username = get_github_username_from_api_key( args["key"]) content_data = yield torngithub.github_request( self.get_auth_http_client(), '/repos/{owner}/{repo}/contents/{path}'.format( owner=github_username, repo=repo_contents["name"], path="manifest.json"), access_token=args["github_access_token"], method="GET") content = content_data["body"]["content"] # parse the manifest.json file for the collection collection_contents = json_decode( b64decode(content.encode('utf-8')).decode('utf-8')) pmids = [c["pmid"] for c in collection_contents] add_collection_to_brainspell_database( collection_name, description, args["key"], False) brainspell_cache[collection_name] = { "description": description, "pmids": pmids } if len(pmids) != 0: # if PMIDs were fetched from GitHub bulk_add_articles_to_brainspell_database_collection( collection_name, pmids, args["key"], False) except BaseException: # some error occurred with GitHub # there was potentially no manifest file valid_collection = False if valid_collection: # accounts for malformed collections, and excludes them pmids = brainspell_cache[collection_name]["pmids"] # determine if the pmid (if given) is in this collection repo["in_collection"] = any( [str(pmid) == args["pmid"] for pmid in pmids]) # convert PeeWee article object to dict def parse_article_object(article_object): return { "title": article_object.title, "reference": article_object.reference, "pmid": article_object.pmid } # get article information from each pmid from the database repo["contents"] = [ parse_article_object(next(get_article_object(p))) for p in pmids ] collections_list.append(repo) response["collections"] = collections_list self.finish_async(response)
def get_oauth_login_info(self): try: user_json = self.get_secure_cookie("user") return json_decode(user_json) except Exception: return None