def proxy_comments(number): """XHR endpoint for GitHub issue comments. * GET an issue comments * POST a comment on an issue (only as an authorized GitHub user) """ params = request.args.copy() path = 'repos/{0}/{1}/comments'.format(ISSUES_PATH, number) if request.method == 'POST' and g.user: new_comment = api_request('post', path, params=params, data=get_comment_data(request.data), mime_type=JSON_MIME_HTML) return get_html_comments(new_comment) else: # TODO: handle the (rare) case for more than 1 page of comments # for now, we just get the first 100 and rely on the client to # fetch more params.update({'per_page': 100}) comments_data = api_request('get', path, params=params, mime_type=JSON_MIME_HTML) comments_status = comments_data[1:2] if comments_status != 304: return get_html_comments(comments_data) else: # in the case of a 304, the browser cache will handle it. return '', 304, get_response_headers(comments_data, HTML_MIME)
def proxy_comments(number): '''XHR endpoint to get issues comments from GitHub. Either as an authed user, or as one of our proxy bots. ''' if request.method == 'POST': path = 'repos/{0}/{1}/comments'.format(ISSUES_PATH, number) return api_request('post', path, data=get_comment_data(request.data)) else: path = 'repos/{0}/{1}/comments'.format(ISSUES_PATH, number) return api_request('get', path)
def proxy_comments(number): """XHR endpoint to get issues comments from GitHub. Either as an authed user, or as one of our proxy bots. """ params = request.args.copy() if request.method == 'POST' and g.user: path = 'repos/{0}/{1}/comments'.format(ISSUES_PATH, number) return api_request('post', path, params=params, data=get_comment_data(request.data)) else: path = 'repos/{0}/{1}/comments'.format(ISSUES_PATH, number) return api_request('get', path, params=params)
def get_issue_category(issue_category): """Return all issues for a specific category.""" category_list = app.config['OPEN_STATUSES'] issues_path = 'repos/{0}'.format(ISSUES_PATH) params = request.args.copy() if issue_category in category_list: STATUSES = app.config['STATUSES'] params.add('milestone', STATUSES[issue_category]['id']) return api_request('get', issues_path, params=params) elif issue_category == 'closed': params['state'] = 'closed' return api_request('get', issues_path, params=params) else: # The path doesn’t exist. 404 Not Found. abort(404)
def get_search_results(query_string=None, params=None): """XHR endpoint to get results from GitHub's Search API. We're specifically searching "issues" here, which seems to make the most sense. Note that the rate limit is different for Search: 30 requests per minute. If a user hits the rate limit, the Flask Limiter extension will send a 429. See @app.error_handler(429) in views.py. This method can take a query_string argument, to be called from other endpoints, or the query_string can be passed in via the Request object. """ params = params or request.args.copy() query_string = query_string or params.get('q') # Fail early if no appropriate query_string if not query_string: abort(404) # restrict results to our repo. query_string += " repo:{0}".format(REPO_PATH) params['q'] = query_string # convert issues api to search api params here. params = normalize_api_params(params) path = 'search/issues' return api_request('get', path, params=params, mime_type=JSON_MIME_HTML)
def get_rate_limit(): '''Endpoint to display the current GitHub API rate limit. Will display for the logged in user, or webcompat-bot if not logged in. See https://developer.github.com/v3/rate_limit/. ''' return api_request('get', 'rate_limit')
def proxy_issue(number): '''XHR endpoint to get issue data from GitHub. either as an authed user, or as one of our proxy bots. ''' path = 'repos/{0}/{1}'.format(ISSUES_PATH, number) return api_request('get', path)
def proxy_issue(number): """XHR endpoint to get issue data from GitHub. either as an authed user, or as one of our proxy bots. """ path = 'repos/{0}/{1}'.format(ISSUES_PATH, number) return api_request('get', path, mime_type=JSON_MIME_HTML)
def proxy_issue(number): """XHR endpoint to get issue data from GitHub. either as an authed user, or as one of our proxy bots. """ path = 'repos/{0}/{1}'.format(ISSUES_PATH, number) return api_request('get', path)
def get_issue_category(issue_category): '''Return all issues for a specific category. issue_category can be of N types: * new * closed * contactready * needscontact * needsdiagnosis * sitewait ''' category_list = [ 'contactready', 'needscontact', 'needsdiagnosis', 'sitewait' ] issues_path = 'repos/{0}'.format(ISSUES_PATH) params = request.args.copy() if issue_category in category_list: # add "status-" before the filter param to match the naming scheme # of the repo labels. params.add('labels', 'status-' + issue_category) # Turns out the GitHub API considers &labels=x&labels=y an OR query # &labels=x,y is an AND query. Join the labels with a comma params['labels'] = ','.join(params.getlist('labels')) return api_request('get', issues_path, params=params) elif issue_category == 'closed': params['state'] = 'closed' return api_request('get', issues_path, params=params) # Note that 'new' here is primarily used on the homepage. # For paginated results on the /issues page, see /issues/search/new. elif issue_category == 'new': issues = api_request('get', issues_path, params=params) # api_request returns a tuple of format: # (content, status_code, response_headers) # So we make a dict here for improved readability content, status_code, response_headers = issues if status_code != 304: content = filter_new(json.loads(content)) return (content, status_code, response_headers) else: # The path doesn’t exist. 404 Not Found. abort(404)
def get_issue_category(issue_category): '''Return all issues for a specific category. issue_category can be of N types: * new * closed * contactready * needscontact * needsdiagnosis * sitewait ''' category_list = ['contactready', 'needscontact', 'needsdiagnosis', 'sitewait'] issues_path = 'repos/{0}'.format(ISSUES_PATH) params = request.args.copy() if issue_category in category_list: # add "status-" before the filter param to match the naming scheme # of the repo labels. params['labels'] = 'status-' + issue_category return api_request('get', issues_path, params=params) elif issue_category == 'closed': params['state'] = 'closed' return api_request('get', issues_path, params=params) # Note that 'new' here is primarily used on the homepage. # For paginated results on the /issues page, see /issues/search/new. elif issue_category == 'new': issues = api_request('get', issues_path, params=params) # api_request returns a tuple of format: # (content, status_code, response_headers) # So we make a dict here for improved readability new_issues = { 'content': filter_new(json.loads(issues[0])), 'status_code': issues[1], 'response_headers': issues[2] } return (new_issues['content'], new_issues['status_code'], new_issues['response_headers']) else: # The path doesn’t exist. 404 Not Found. abort(404)
def get_issue_category(issue_category): '''Return all issues for a specific category. issue_category can be of N types: * new * closed * contactready * needscontact * needsdiagnosis * sitewait ''' category_list = ['contactready', 'needscontact', 'needsdiagnosis', 'sitewait'] issues_path = 'repos/{0}'.format(ISSUES_PATH) params = request.args.copy() if issue_category in category_list: # add "status-" before the filter param to match the naming scheme # of the repo labels. params.add('labels', 'status-' + issue_category) # Turns out the GitHub API considers &labels=x&labels=y an OR query # &labels=x,y is an AND query. Join the labels with a comma params['labels'] = ','.join(params.getlist('labels')) return api_request('get', issues_path, params=params) elif issue_category == 'closed': params['state'] = 'closed' return api_request('get', issues_path, params=params) # Note that 'new' here is primarily used on the homepage. # For paginated results on the /issues page, see /issues/search/new. elif issue_category == 'new': issues = api_request('get', issues_path, params=params) # api_request returns a tuple of format: # (content, status_code, response_headers) # So we make a dict here for improved readability content, status_code, response_headers = issues if status_code != 304: content = filter_new(json.loads(content)) return (content, status_code, response_headers) else: # The path doesn’t exist. 404 Not Found. abort(404)
def get_issue_category(issue_category): '''Return all issues for a specific category. issue_category can be of N types: * needstriage * closed * contactready * needscontact * needsdiagnosis * sitewait ''' category_list = [ 'contactready', 'needscontact', 'needsdiagnosis', 'needstriage', 'sitewait' ] issues_path = 'repos/{0}'.format(ISSUES_PATH) params = request.args.copy() if issue_category in category_list: # add "status-" before the filter param to match the naming scheme # of the repo labels. params.add('labels', 'status-' + issue_category) # Turns out the GitHub API considers &labels=x&labels=y an OR query # &labels=x,y is an AND query. Join the labels with a comma params['labels'] = ','.join(params.getlist('labels')) return api_request('get', issues_path, params=params) elif issue_category == 'closed': params['state'] = 'closed' return api_request('get', issues_path, params=params) # Note that 'needstriage' here is primarily used on the homepage. # For paginated results on the /issues page, # see /issues/search/needstriage. # We abort with 301 here because the new endpoint has # been replaced with needstriage. elif issue_category == 'new': abort(301) else: # The path doesn’t exist. 404 Not Found. abort(404)
def get_issue_category(issue_category): '''Return all issues for a specific category. issue_category can be of N types: * needstriage * closed * contactready * needscontact * needsdiagnosis * sitewait ''' category_list = ['contactready', 'needscontact', 'needsdiagnosis', 'needstriage', 'sitewait'] issues_path = 'repos/{0}'.format(ISSUES_PATH) params = request.args.copy() if issue_category in category_list: # add "status-" before the filter param to match the naming scheme # of the repo labels. params.add('labels', 'status-' + issue_category) # Turns out the GitHub API considers &labels=x&labels=y an OR query # &labels=x,y is an AND query. Join the labels with a comma params['labels'] = ','.join(params.getlist('labels')) return api_request('get', issues_path, params=params) elif issue_category == 'closed': params['state'] = 'closed' return api_request('get', issues_path, params=params) # Note that 'needstriage' here is primarily used on the homepage. # For paginated results on the /issues page, # see /issues/search/needstriage. # We abort with 301 here because the new endpoint has # been replaced with needstriage. elif issue_category == 'new': abort(301) else: # The path doesn’t exist. 404 Not Found. abort(404)
def proxy_issues(): """List all issues from GitHub on the API endpoint.""" params = request.args.copy() # If there's a q param, then we need to use the Search API # and load those results. For logged in users, we handle this at the # server level. if g.user and params.get('q'): return get_search_results(params.get('q'), params) # Non-authed users should never get here--the request is made to # GitHub client-side)--but return out of paranoia anyways. elif params.get('q'): abort(404) path = 'repos/{0}'.format(ISSUES_PATH) return api_request('get', path, params=params)
def get_issue_category(issue_category, other_params=None): """Return all issues for a specific category.""" category_list = app.config['OPEN_STATUSES'] issues_path = 'repos/{0}'.format(ISSUES_PATH) params = request.args.copy() # Used by the dashboard to adjust the list of issues if other_params: params.update(other_params) if issue_category in category_list: STATUSES = app.config['STATUSES'] params.add('milestone', STATUSES[issue_category]['id']) return api_request('get', issues_path, params=params, mime_type=JSON_MIME_HTML) elif issue_category == 'closed': params['state'] = 'closed' return api_request('get', issues_path, params=params, mime_type=JSON_MIME_HTML) else: # The path doesn’t exist. 404 Not Found. abort(404)
def get_user_activity_issues(username, parameter): '''API endpoint to return issues related to a user. cf. https://developer.github.com/v3/issues/#list-issues-for-a-repository This is only used for "creator" and "mentioned" right now. Any logged in user can see details for any other logged in user. We can extend this to non-logged in users in the future if we want. ''' if not g.user: abort(401) # copy the params so we can add to the dict. params = request.args.copy() params['state'] = 'all' params['{0}'.format(parameter)] = '{0}'.format(username) path = 'repos/{path}'.format(path=ISSUES_PATH) return api_request('get', path, params=params)
def get_user_activity_issues(username, parameter): """Return issues related to a user at the API endpoint. cf. https://developer.github.com/v3/issues/#list-issues-for-a-repository This is only used for "creator" and "mentioned" right now. Any logged in user can see details for any other logged in user. We can extend this to non-logged in users in the future if we want. """ if not g.user: abort(401) # copy the params so we can add to the dict. params = request.args.copy() params['state'] = 'all' params['{0}'.format(parameter)] = '{0}'.format(username) path = 'repos/{path}'.format(path=ISSUES_PATH) return api_request('get', path, params=params)
def get_user_activity_issues(username, parameter): """Return issues related to a user at the API endpoint. cf. https://developer.github.com/v3/issues/#list-issues-for-a-repository This is used for "creator" and "mentioned". A special "needsinfo" parameter value is converted into a request for labels of the format: `status-needsinfo-username` Any logged in user can see details for any other logged in user. We can extend this to non-logged in users in the future if we want. """ if not g.user: abort(401) # copy the params so we can add to the dict. params = request.args.copy() params['state'] = 'all' if parameter == 'needsinfo': params['labels'] = 'status-needsinfo-{0}'.format(username) else: params[parameter] = username path = 'repos/{path}'.format(path=ISSUES_PATH) return api_request('get', path, params=params)
def get_repo_labels(): """XHR endpoint to get all possible labels in a repo.""" params = request.args.copy() path = 'repos/{0}/labels'.format(REPO_PATH) return api_request('get', path, params=params)