def validate(self, attrs): code = attrs.get('code') state = attrs.get('state') user = None if not CLIENT_ID or not CLIENT_SECRET: msg = 'Lifebelt not configurated properly. Please contact administrators' raise exceptions.ValidationError(msg) if code and state: headers = {'Accept': 'application/json'} data = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET, "code": code, "state": state} url = 'https://github.com/login/oauth/access_token' r = requests.post(url=url, headers=headers, data=data) if 'access_token' not in r.json(): msg = 'This smells...' if 'error' in r.json(): msg = r.json()['error'] raise exceptions.ValidationError(msg) token = r.json()['access_token'] # https://github3py.readthedocs.org/en/master/ gh = GitHub(token=token) user = Member.objects.get(github_id=gh.me().id) if not user: msg = 'User with this GitHub name is not found' raise exceptions.ValidationError(msg) user.avatar_url = gh.me().as_dict().get('avatar_url') user.github_token = token user.save() else: msg = ('You must provide a valid email and a special code to authenticate') raise exceptions.ValidationError(msg) attrs['user'] = user.user return attrs
def one_repo_only(owner, reponame, gh_token=''): """ Go back and see why this or that denied request. Provide a valid token. """ gh = GitHub(token=gh_token) user = gh.me() body = ISSUE_BODY.format(user) repo = gh.repository(owner, reponame) i = repo.create_issue(ISSUE_TITLE, body=body) print(i)
def one_repo_only(owner, reponame, gh_token=''): """ Go back and see why this or that denied request. Provide a valid token. """ gh = GitHub(token=gh_token) user = gh.me() body = ISSUE_BODY.format(user) repo = gh.repository(owner, reponame) i = repo.create_issue(ISSUE_TITLE, body=body) print(i)
def go_forth_and_multiply(owner, listfile, gh_token=''): """ Open issues! Provide a valid token. """ gh = GitHub(token=gh_token) user = gh.me() body = ISSUE_BODY.format(user) # Only allowed to spam pre-approved list now. with open(listfile) as fin: repositories = [ s.strip() for s in fin.readlines() if not s.startswith('#') ] tot_n = len(repositories) if tot_n == 0: print('No repository to process!') return max_n_per_chunk = 30 n_chunks = math.ceil(tot_n / max_n_per_chunk) i_chunk = 0 while i_chunk < n_chunks: i_start = i_chunk * max_n_per_chunk i_end = min(i_start + max_n_per_chunk, tot_n) for reponame in repositories[i_start:i_end]: time.sleep(0.5) # Prevent API limit but not abuse detection repo = gh.repository(owner, reponame) if repo.archived: print('Skipped {0} -- archived'.format(repo.name)) continue try: i = repo.create_issue('Update the help', body=body) except Exception as e: # denied! print('Skipped {0} -- {1}'.format(repo.name, str(e))) else: print(i) i_chunk += 1 if i_chunk < n_chunks: time.sleep(10) # Prevent abuse detection, maybe
def go_forth_and_multiply(owner, listfile, gh_token=''): """ Open issues! Provide a valid token. """ gh = GitHub(token=gh_token) user = gh.me() body = ISSUE_BODY.format(user) # Only allowed to spam pre-approved list now. with open(listfile) as fin: repositories = [s.strip() for s in fin.readlines() if not s.startswith('#')] tot_n = len(repositories) if tot_n == 0: print('No repository to process!') return max_n_per_chunk = 30 n_chunks = math.ceil(tot_n / max_n_per_chunk) i_chunk = 0 while i_chunk < n_chunks: i_start = i_chunk * max_n_per_chunk i_end = min(i_start + max_n_per_chunk, tot_n) for reponame in repositories[i_start:i_end]: time.sleep(0.5) # Prevent API limit but not abuse detection repo = gh.repository(owner, reponame) if repo.archived: print('Skipped {0} -- archived'.format(repo.name)) continue try: i = repo.create_issue('Update the help', body=body) except Exception as e: # denied! print('Skipped {0} -- {1}'.format(repo.name, str(e))) else: print(i) i_chunk += 1 if i_chunk < n_chunks: time.sleep(10) # Prevent abuse detection, maybe
import re import tempfile import subprocess try: from github3 import GitHub except ImportError: raise ImportError('Please conda or pip install github3.py') BRANCH = 'add_code_of_conduct' CODE_OF_CONDUCT_REPO = ('spacetelescope', 'stsci-package-template') CODE_OF_CONDUCT_FILENAME = 'CODE_OF_CONDUCT.md' GITHUB_API_HOST = 'api.github.com' gh = GitHub(token='') # NOTE: Insert a valid token user = gh.me() PR_MESSAGE_BODY = re.sub('(\S+)\n', r'\1 ', """ This is an automated addition of spacetelescope code of conduct that is copied from https://github.com/{0}/{1}/. *If this is opened in error, please let {2} know!* """).strip() # Get CoC content from template _r = gh.repository(*CODE_OF_CONDUCT_REPO) _c = _r.file_contents(CODE_OF_CONDUCT_FILENAME).decoded.decode('utf-8') def run_command(command):
#!/usr/bin/env python import os from github3 import GitHub from flask.json import jsonify from requests_oauthlib import OAuth2Session from diggit import Digger from flask import Flask, request, redirect, session, url_for GH = GitHub() GH.login(token=os.environ.get('GITHUB_ACCESS_TOKEN')) user_gh_profile = GH.me() gh_scraper = Digger(GH) # GH.ratelimit_remaining app = Flask(__name__) @app.route("/") def home(): return redirect(url_for('profile')) @app.route("/profile", methods=["GET"]) def profile(): """ """ return jsonify(user_gh_profile.as_dict()) @app.route("/search/", methods=["GET"]) @app.route("/search/<type>", methods=["GET"]) def scanner(type="user"): return jsonify(gh_scraper.get_class())
class WsgiApplication(github.GitHub): # pylint:disable=too-many-instance-attributes _URLS = routing.Map(( routing.Rule('/', endpoint='index'), routing.Rule('/<repository_name>/', endpoint='repository'), routing.Rule('/<repository_name>/release/<release_name>.tar.gz', endpoint='download'), )) _cache = None # type: FileSystemCache _users_and_organizations = None # type: (github.Organization | github.User, ...) _index_template = None # type: str _repository_template = None # type: str _auth = None # type: dict[str] _request_domain = None # type: str _request_urls = None # type: routing.MapAdapter @property def repositories(self): """ :rtype: dict[str, repos.ShortRepository] """ value = self._cache.get(CACHE_KEY) if value is None: data = self.get_installable_repositories( *self._users_and_organizations) value = {key: repo._json_data for key, repo in data.items()} # pylint:disable=protected-access self._cache.set(CACHE_KEY, value) return data return { key: repos.ShortRepository(json, self.github_api.session) for key, json in value.items() } # noinspection PyTypeChecker def __init__( self, *users_and_organizations, cache_dir, # Should be an absolute path! index_template=None, repository_template=None, ) -> None: """ :type users_and_organizations: (github.Organization | github.User, ...) :type index_template: str :type repository_template: str :rtype: None """ self._cache = FileSystemCache(cache_dir=cache_dir, default_timeout=900) self._users_and_organizations = users_and_organizations self._index_template = index_template or templates.INDEX self._repository_template = repository_template or templates.REPOSITORY self._auth = None self._request_domain = None self._request_urls = None self.current_user = None self.github_api = None def __call__(self, environ, start_response): """ :type environ: dict :type start_response: werkzeug.serving.WSGIRequestHandler.start_response :rtype: werkzeug.wsgi.ClosingIterator """ request = wrappers.Request(environ) if b'purge_cache' in request.query_string: self._cache.delete(CACHE_KEY) try: self._get_authorization(request) self._authorize_github() self._request_domain = self._get_request_domain(request) self._request_urls = self._URLS.bind_to_environ(request.environ) endpoint, values = self._request_urls.match() func_name = 'dispatch_{}'.format(endpoint) response = (getattr(self, func_name)(request, **values) if hasattr( self, func_name) else exceptions.NotFound()) except exceptions.HTTPException as ex: response = ex return response(environ, start_response) def _get_authorization(self, request): """ :type request: werkzeug.wrappers.request.Request :rtype: dict[str] :raises werkzeug.exceptions.Unauthorized: If authorization information not available in `request` """ auth = request.authorization or {} username = auth.get('username', '').strip() password = auth.get('password', '').strip() if not username: raise exceptions.Unauthorized( www_authenticate='Basic realm="Simple index"') self._auth = { 'username': username, 'password': password } if username and password else { 'token': username } def _authorize_github(self): """ :rtype: None :raises werkzeug.exceptions.Forbidden: If cannot login to GitHub using `auth` credentials """ self.github_api = GitHubApi(**self._auth) try: self.current_user = self.github_api.me() except gh_exc.AuthenticationFailed: raise exceptions.Forbidden() if self.current_user is None: raise exceptions.Forbidden() def _get_request_domain(self, request): """ :type request: werkzeug.wrappers.request.Request :rtype: str """ base_url = parse.urlsplit(request.base_url) # type: parse.SplitResult netloc = ('{scheme}://{token}@{domain}' if 'token' in self._auth else '{scheme}://{username}:{password}@{domain}') format_dict = {'domain': base_url.netloc.split('@')[-1].rstrip('/')} format_dict.update(self._auth) format_dict.update(base_url._asdict()) return netloc.format(**format_dict) # Endpoints def dispatch_download(self, request, repository_name, release_name): # pylint:disable=unused-argument repo_releases = self._get_releases(repository_name) if not repo_releases: raise exceptions.NotFound() wanted_release = repo_releases[release_name] # type: release.Release asset_url = self._find_release_download_link( wanted_release) # type: str with requests.get(asset_url, headers={'Accept': 'application/octet-stream'}, stream=True) as tarball: if tarball.status_code != HTTPStatus.OK: raise exceptions.NotFound() stream = ResponseStream(tarball.iter_content(1024)) return wrappers.Response(stream.read(), direct_passthrough=True, mimetype='application/x-compressed') def dispatch_index(self, request): # pylint:disable=unused-argument """ :type request: werkzeug.wrappers.request.Request :rtype: werkzeug.wrappers.response.Response """ return wrappers.Response( self._index_template % { 'links': '\n'.join( '<a href="%(domain)s%(endpoint)s">%(name)s</a>' % { 'domain': self._request_domain, 'endpoint': self._request_urls.build( 'repository', {'repository_name': repo_name}), 'name': repo.full_name, } for repo_name, repo in self.repositories.items()), }, mimetype='text/html', ) def dispatch_repository(self, request, repository_name): # pylint:disable=unused-argument """ :type request: werkzeug.wrappers.request.Request :type repository_name: str :rtype: werkzeug.wrappers.response.Response :raises werkzeug.exceptions.NotFound: If `repository_name` not found on GitHub """ releases = self._get_repo_releases_links(repository_name) return wrappers.Response( self._repository_template % { 'repository_name': repository_name, 'links': '\n'.join('<a href="%(url)s">%(tag_name)s</a>' % item for item in releases), }, mimetype='text/html', ) # Helpers def _get_repo_releases_links(self, repository_name): """ :type repository_name: str :rtype: (dict[str, str], ...) | None """ repo_releases = self._get_releases(repository_name) if not repo_releases: return None return tuple({ 'url': '%(domain)s%(endpoint)s' % { 'domain': self._request_domain, 'endpoint': self._request_urls.build('download', { 'repository_name': repository_name, 'release_name': tag_name }), }, 'tag_name': tag_name } for tag_name in repo_releases.keys()) def _get_releases(self, repository_name): """ :type repository_name: str :rtype: dict[str, release.Release] | None """ repositories_with_aliases = {} for key, value in self.repositories.items(): repositories_with_aliases[key] = value repositories_with_aliases[key.replace('_', '-')] = value try: repository = repositories_with_aliases[ repository_name] # type: repos.ShortRepository except KeyError: raise exceptions.NotFound() repo_releases = collections.OrderedDict( (item.tag_name, item) for item in sorted(repository.releases(), key=lambda item: item.created_at)) return repo_releases or None def _find_release_download_link(self, release_instance): """ :type: release.Release :rtype: str :raises werkzeug.exceptions.NotFound: """ asset_url = None for asset in release_instance.assets(): # type: release_instance.Asset if asset.name == ASSET_FILENAME: asset_url = '{download_url}?access_token={access_token}'.format( download_url=asset.download_url, access_token=self._auth.get('token', self._auth.get('password')), ) break if not asset_url: raise exceptions.NotFound( 'Asset "{}" not found in release "{}"'.format( ASSET_FILENAME, release_instance.name)) return asset_url