#!/usr/bin/env python3 import html import logging import re import requests import shlex import sys import time GIT_URLS_OPTION = '--git-urls' GITGUD_COMPLETE_ITEMS_OPTION = '--gitgud-complete-items' MODES = (GIT_URLS_OPTION, GITGUD_COMPLETE_ITEMS_OPTION) mode = None name = False users = sys.argv[1:] if users and users[0] == '--name': name = True users = users[1:] if users and users[0] in MODES: mode = users[0] users = users[1:] assert users and (mode is None or mode in MODES) and not users[0].startswith('--'), f'Usage: github-list-repos [--name] [{" | ".join(MODES)}] USER [USER...]' def get(url): while True: logging.info(f'Fetching {url}') r = requests.get(url, headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0'}) if r.status_code == 429: logging.warning(f'Got 429, sleeping and retrying') time.sleep(5) else: break return r def p(repoName): if mode is None: print(f'https://github.com/{repoName}') elif mode == GIT_URLS_OPTION: print(f'https://github.com/{repoName}.git') print(f'https://github.com/{repoName}.wiki.git') elif mode == GITGUD_COMPLETE_ITEMS_OPTION: print(f'web:complete:{repoName}') for user in users: r = get(f'https://github.com/{user}') if '
', r.text) if not musername: print('Error: could not find profile:username meta tag', file = sys.stderr) sys.exit(1) mfullname = re.search(r']*\s)?class="(?:[^"]*\s)?h2(?:\s[^"]*)?"(?:\s[^>]*)?>(.*?)', r.text, flags = re.DOTALL) if not mfullname: print('Error: could not find name h1', file = sys.stderr) sys.exit(1) print(f'{shlex.quote(html.unescape(musername.group(1).strip()))} {shlex.quote(html.unescape(mfullname.group(1).strip()))}') r = get(f'https://github.com/orgs/{user}/repositories') page = 1 while True: for m in re.finditer(r']*\s)?data-hovercard-url="/([^/>"]+/[^/>"]+)/hovercard"', r.text): p(m.group(1)) if ']*\s)?class="(?:[^"]*\s)?vcard-username(?:\s[^"]*)?"(?:\s[^>]*)?>(.*?)', r.text, flags = re.DOTALL) if not musername: print('Error: could not find vcard-username span', file = sys.stderr) sys.exit(1) if (m := re.search(r']*\s)?class="(?:[^"]*\s)?vcard-fullname(?:\s[^"]*)?"(?:\s[^>]*)?>(.*?)', r.text, flags = re.DOTALL)): fullname = html.unescape(m.group(1).strip()) else: fullname = '' print(f'{shlex.quote(html.unescape(musername.group(1).strip()))} {shlex.quote(fullname)}') r = get(f'https://github.com/{user}?tab=repositories') while True: for m in re.finditer(r'"]+)" itemprop="name codeRepository"(\s[^>]*)?>', r.text): p(m.group(1)) if not (m := re.search(r']*\s)?class="next_page"(?:\s[^>]*)?>)(?:[^>]*\s)?href="/[^/?"]+\?page=([^&]+)&tab=repositories"(?:\s[^>]*)?>', r.text)): # End of pagination break r = get(f'https://github.com/{user}?page={m.group(1)}&tab=repositories')