Module github_sync

Expand source code
import os
import json
import requests
from github import Github, InputGitAuthor
import conf

dir_path = os.path.dirname(os.path.realpath(__file__))

# OAUTH APP


clientId = conf.clientID
clientSecret = conf.clientSecret


def ask_user_permission(code):
    """ Get user permission when authenticating via Github.

    Args:
        code (str): an alpha-numeric string that gets a unique code for the user who is attempting to authenticate.

    Returns:
        res (dict): a dictionary containing user info for permission.
    """
    res = None
    body = {
        "client_id": clientId,
        "client_secret": clientSecret,
        "code": code
    }

    req = requests.post('https://github.com/login/oauth/access_token', data=body,
                        headers={"accept": "application/json"})
    print(body, req)
    if req.status_code == 200:
        res = req.json()
    return res


def get_user_login(res):
    """ Get Github user information.

    Args:
        res (dict): a dictionary containing user info for permission, returned by ask_user_permission(code).

    Returns:
        userlogin (str): a string representing the user nickname.
        usermail (str): a string representing the user email address.
        access_token (str): a string representing the user access token.

    """
    userlogin, usermail = None, None
    print("user requesting github login:", res)
    access_token = res["access_token"]
    req_user = requests.get("https://api.github.com/user",
                            headers={"Authorization": "token "+access_token})

    if req_user.status_code == 200:
        res_user = req_user.json()
        userlogin = res_user["login"]
        usermail = res_user["email"]
    return userlogin, usermail, access_token


def get_github_users(userlogin):
    """ Match user with collaborators of Github repository.

    This function checks if the user trying to authenticate is part of a specific Github repository.

    Args:
        userlogin (str): a string representing the user nickname.

    Returns:
        is_valid_user (boolean): a boolean operator that states if user is a collaborator (True) or not (False).

    """
    is_valid_user = False
    if conf.token != '' and conf.owner != '' and conf.repo_name != '':
        req = requests.get("https://api.github.com/repos/"+conf.owner+"/"+conf.repo_name+"/collaborators",
                           headers={"Authorization": "token "+conf.token})
        if req.status_code == 200:
            users = [user['login'] for user in req.json()]
            if userlogin in users:
                is_valid_user = True
    return is_valid_user


def push(local_file_path, branch='main', gituser=None, email=None, bearer_token=None, action=''):
    """ Create a new file or update an existing file in a Github repository.

    This function allows to publish and/or update content on another Github repository.

    Args:
        local_file_path (str): a string representing the local path of the file that needs to be published or updated.
        branch (str): a string representing the branch from/to which publicate or update. 'main' is default.
        gituser (str): a string representing the Github user that will carry out the action. 'None' is default.
        email (str): a string representing the email address of gituser. 'None' is default.
        bearer_token (str): a string representing the token to have permission to carry out the action. 'None' is default.
        action (str): a string representing the optional message text that can be included in the commit. It is ampty by default.

    """
    token = conf.token if bearer_token is None else bearer_token  # editor
    user = conf.author if gituser is None else gituser  # editor
    usermail = conf.author_email if email is None else email
    owner = conf.melody_owner
    repo_name = conf.melody_repo_name
    g = Github(token)
    repo = g.get_repo(owner+"/"+repo_name)
    author = InputGitAuthor(user, usermail)  #  commit author
    # necessary to commit filename without path
    absolute_file_path = os.path.basename(local_file_path)

    try:
        # Retrieve the online file to get its SHA and path
        contents = repo.get_contents(
            conf.melody_sub_dir+'/'+absolute_file_path)
        update = True
        message = "updated file "+absolute_file_path+" "+action
    except:
        update = False
        message = "created file "+absolute_file_path+" "+action

    # Both create/update file replace the file with the local one
    with open(local_file_path) as f:
        data = f.read()  # could be done in a smarter way

    if update == True:  # If file already exists, update it
        # Add, commit and push branch
        repo.update_file(contents.path, message, data,
                         contents.sha, author=author)
    else:
        try:
            # If file doesn't exist, create it in the same relative path of the local file
            # Add, commit and push branch
            repo.create_file(conf.melody_sub_dir+'/'+absolute_file_path, message, data,
                             branch=branch, author=author)
        except Exception as e:
            print(e)

Functions

def ask_user_permission(code)

Get user permission when authenticating via Github.

Args

code : str
an alpha-numeric string that gets a unique code for the user who is attempting to authenticate.

Returns

res (dict): a dictionary containing user info for permission.

Expand source code
def ask_user_permission(code):
    """ Get user permission when authenticating via Github.

    Args:
        code (str): an alpha-numeric string that gets a unique code for the user who is attempting to authenticate.

    Returns:
        res (dict): a dictionary containing user info for permission.
    """
    res = None
    body = {
        "client_id": clientId,
        "client_secret": clientSecret,
        "code": code
    }

    req = requests.post('https://github.com/login/oauth/access_token', data=body,
                        headers={"accept": "application/json"})
    print(body, req)
    if req.status_code == 200:
        res = req.json()
    return res
def get_github_users(userlogin)

Match user with collaborators of Github repository.

This function checks if the user trying to authenticate is part of a specific Github repository.

Args

userlogin : str
a string representing the user nickname.

Returns

is_valid_user (boolean): a boolean operator that states if user is a collaborator (True) or not (False).

Expand source code
def get_github_users(userlogin):
    """ Match user with collaborators of Github repository.

    This function checks if the user trying to authenticate is part of a specific Github repository.

    Args:
        userlogin (str): a string representing the user nickname.

    Returns:
        is_valid_user (boolean): a boolean operator that states if user is a collaborator (True) or not (False).

    """
    is_valid_user = False
    if conf.token != '' and conf.owner != '' and conf.repo_name != '':
        req = requests.get("https://api.github.com/repos/"+conf.owner+"/"+conf.repo_name+"/collaborators",
                           headers={"Authorization": "token "+conf.token})
        if req.status_code == 200:
            users = [user['login'] for user in req.json()]
            if userlogin in users:
                is_valid_user = True
    return is_valid_user
def get_user_login(res)

Get Github user information.

Args

res : dict
a dictionary containing user info for permission, returned by ask_user_permission(code).

Returns

userlogin (str): a string representing the user nickname. usermail (str): a string representing the user email address. access_token (str): a string representing the user access token.

Expand source code
def get_user_login(res):
    """ Get Github user information.

    Args:
        res (dict): a dictionary containing user info for permission, returned by ask_user_permission(code).

    Returns:
        userlogin (str): a string representing the user nickname.
        usermail (str): a string representing the user email address.
        access_token (str): a string representing the user access token.

    """
    userlogin, usermail = None, None
    print("user requesting github login:", res)
    access_token = res["access_token"]
    req_user = requests.get("https://api.github.com/user",
                            headers={"Authorization": "token "+access_token})

    if req_user.status_code == 200:
        res_user = req_user.json()
        userlogin = res_user["login"]
        usermail = res_user["email"]
    return userlogin, usermail, access_token
def push(local_file_path, branch='main', gituser=None, email=None, bearer_token=None, action='')

Create a new file or update an existing file in a Github repository.

This function allows to publish and/or update content on another Github repository.

Args

local_file_path : str
a string representing the local path of the file that needs to be published or updated.
branch : str
a string representing the branch from/to which publicate or update. 'main' is default.
gituser : str
a string representing the Github user that will carry out the action. 'None' is default.
email : str
a string representing the email address of gituser. 'None' is default.
bearer_token : str
a string representing the token to have permission to carry out the action. 'None' is default.
action : str
a string representing the optional message text that can be included in the commit. It is ampty by default.
Expand source code
def push(local_file_path, branch='main', gituser=None, email=None, bearer_token=None, action=''):
    """ Create a new file or update an existing file in a Github repository.

    This function allows to publish and/or update content on another Github repository.

    Args:
        local_file_path (str): a string representing the local path of the file that needs to be published or updated.
        branch (str): a string representing the branch from/to which publicate or update. 'main' is default.
        gituser (str): a string representing the Github user that will carry out the action. 'None' is default.
        email (str): a string representing the email address of gituser. 'None' is default.
        bearer_token (str): a string representing the token to have permission to carry out the action. 'None' is default.
        action (str): a string representing the optional message text that can be included in the commit. It is ampty by default.

    """
    token = conf.token if bearer_token is None else bearer_token  # editor
    user = conf.author if gituser is None else gituser  # editor
    usermail = conf.author_email if email is None else email
    owner = conf.melody_owner
    repo_name = conf.melody_repo_name
    g = Github(token)
    repo = g.get_repo(owner+"/"+repo_name)
    author = InputGitAuthor(user, usermail)  #  commit author
    # necessary to commit filename without path
    absolute_file_path = os.path.basename(local_file_path)

    try:
        # Retrieve the online file to get its SHA and path
        contents = repo.get_contents(
            conf.melody_sub_dir+'/'+absolute_file_path)
        update = True
        message = "updated file "+absolute_file_path+" "+action
    except:
        update = False
        message = "created file "+absolute_file_path+" "+action

    # Both create/update file replace the file with the local one
    with open(local_file_path) as f:
        data = f.read()  # could be done in a smarter way

    if update == True:  # If file already exists, update it
        # Add, commit and push branch
        repo.update_file(contents.path, message, data,
                         contents.sha, author=author)
    else:
        try:
            # If file doesn't exist, create it in the same relative path of the local file
            # Add, commit and push branch
            repo.create_file(conf.melody_sub_dir+'/'+absolute_file_path, message, data,
                             branch=branch, author=author)
        except Exception as e:
            print(e)