The little things give you away... A collection of various small helper stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

95 lines
3.5 KiB

  1. #!/usr/bin/env python3
  2. import html
  3. import logging
  4. import re
  5. import requests
  6. import shlex
  7. import sys
  8. import time
  9. GIT_URLS_OPTION = '--git-urls'
  10. GITGUD_COMPLETE_ITEMS_OPTION = '--gitgud-complete-items'
  11. NAME_OPTION = '--name'
  12. MODES = (GIT_URLS_OPTION, GITGUD_COMPLETE_ITEMS_OPTION, NAME_OPTION)
  13. mode = None
  14. users = sys.argv[1:]
  15. if users and users[0] in MODES:
  16. mode = users[0]
  17. users = users[1:]
  18. assert users and (mode is None or mode in MODES) and not users[0].startswith('--'), f'Usage: github-list-repos [{" | ".join(MODES)}] USER [USER...]'
  19. def get(url):
  20. while True:
  21. logging.info(f'Fetching {url}')
  22. r = requests.get(url, headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:60.0) Gecko/20100101 Firefox/60.0'})
  23. if r.status_code == 429:
  24. logging.warning(f'Got 429, sleeping and retrying')
  25. time.sleep(5)
  26. else:
  27. break
  28. return r
  29. def p(repoName):
  30. if mode is None:
  31. print(f'https://github.com/{repoName}')
  32. elif mode == GIT_URLS_OPTION:
  33. print(f'https://github.com/{repoName}.git')
  34. print(f'https://github.com/{repoName}.wiki.git')
  35. elif mode == GITGUD_COMPLETE_ITEMS_OPTION:
  36. print(f'web:complete:{repoName}')
  37. for user in users:
  38. r = get(f'https://github.com/{user}')
  39. if '<div id="org-repositories"' in r.text:
  40. # Organisation, complete list under /orgs/ with ?page=2 pagination
  41. if mode == NAME_OPTION:
  42. musername = re.search(r'<meta property="profile:username" content="([^"]*)" />', r.text)
  43. if not musername:
  44. print('Error: could not find profile:username meta tag', file = sys.stderr)
  45. sys.exit(1)
  46. mfullname = re.search(r'<h1\s(?:[^>]*\s)?class="(?:[^"]*\s)?h2(?:\s[^"]*)?"(?:\s[^>]*)?>(.*?)</h1>', r.text, flags = re.DOTALL)
  47. if not mfullname:
  48. print('Error: could not find name h1', file = sys.stderr)
  49. sys.exit(1)
  50. print(html.unescape(musername.group(1).strip().replace('\n', ' ').replace('\r', ' ')))
  51. print(html.unescape(mfullname.group(1).strip().replace('\n', ' ').replace('\r', ' ')))
  52. sys.exit(0)
  53. r = get(f'https://github.com/orgs/{user}/repositories')
  54. page = 1
  55. while True:
  56. for m in re.finditer(r'<a itemprop="name codeRepository"\s(?:[^>]*\s)?data-hovercard-url="/([^/>"]+/[^/>"]+)/hovercard"', r.text):
  57. p(m.group(1))
  58. if '<a class="next_page"' not in r.text:
  59. # End of pagination
  60. break
  61. page += 1
  62. r = get(f'https://github.com/orgs/{user}/repositories?page={page}')
  63. else:
  64. # User, ?tab=repositories + cursor pagination
  65. if mode == NAME_OPTION:
  66. musername = re.search(r'<span\s(?:[^>]*\s)?class="(?:[^"]*\s)?vcard-username(?:\s[^"]*)?"(?:\s[^>]*)?>(.*?)</span>', r.text, flags = re.DOTALL)
  67. if not musername:
  68. print('Error: could not find vcard-username span', file = sys.stderr)
  69. sys.exit(1)
  70. if (m := re.search(r'<span\s(?:[^>]*\s)?class="(?:[^"]*\s)?vcard-fullname(?:\s[^"]*)?"(?:\s[^>]*)?>(.*?)</span>', r.text, flags = re.DOTALL)):
  71. fullname = html.unescape(m.group(1).strip())
  72. else:
  73. fullname = ''
  74. print(html.unescape(musername.group(1).strip()).replace('\n', ' ').replace('\r', ' '))
  75. print(fullname.replace('\n', ' ').replace('\r', ' '))
  76. sys.exit(0)
  77. r = get(f'https://github.com/{user}?tab=repositories')
  78. while True:
  79. for m in re.finditer(r'<a href="/([^/>"]+/[^/>"]+)" itemprop="name codeRepository"(\s[^>]*)?>', r.text):
  80. p(m.group(1))
  81. if not (m := re.search(r'<a\s(?=(?:[^>]*\s)?class="next_page"(?:\s[^>]*)?>)(?:[^>]*\s)?href="/[^/?"]+\?page=([^&]+)&amp;tab=repositories"(?:\s[^>]*)?>', r.text)):
  82. # End of pagination
  83. break
  84. r = get(f'https://github.com/{user}?page={m.group(1)}&tab=repositories')