Skip to content

Instantly share code, notes, and snippets.

@WingTillDie
Last active July 12, 2023 09:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WingTillDie/634d7c55def5c7e0c25c65beecad01aa to your computer and use it in GitHub Desktop.
Save WingTillDie/634d7c55def5c7e0c25c65beecad01aa to your computer and use it in GitHub Desktop.
List GitHub Gist with Gist id and Gist name
#!/usr/bin/env python3
import subprocess
import shlex
import re
import sys
from collections import namedtuple
Entry = namedtuple('Entry', ['user_name', 'gist_id', 'gist_name'])
user_name = None
class Gist_id_name_mapping():
# gist_id_to_name[$gist_id] = $gist_name
# gist_name_to_id[$gist_name] = $gist_id
gist_id_to_name = {}
gist_name_to_id = {}
populated = False
@classmethod
def populate(cls, entries):
# Populate the data
prev_user_name : str = None
for entry in entries:
cls.add(gist_id=entry.gist_id, gist_name=entry.gist_name)
if prev_user_name is None:
prev_user_name = entry.user_name
global user_name
user_name = entry.user_name
assert(entry.user_name == prev_user_name)
cls.populated = True
@classmethod
def list(cls):
# print('gist_id gist_name')
# for item in cls.gist_id_to_name.items():
# print(*item)
print('URL gist_name')
for item in cls.gist_id_to_name.items():
gist_id, gist_name = item
URL = f'https://gist.github.com/{user_name}/{gist_id}'
print(URL, gist_name)
@classmethod
def add(cls, /, *, gist_id: str, gist_name: str):
assert(not cls.populated)
cls.gist_id_to_name[gist_id] = gist_name
cls.gist_name_to_id[gist_name] = gist_id
@classmethod
def clear(cls):
cls.gist_id_to_name = {}
cls.gist_name_to_id = {}
cls.populated = False
@classmethod
def encode(cls, URL: str) -> str:
gist_id = URL.split('/')[-1]
user_name = URL.split('/')[-2]
gist_name = cls.gist_id_to_name[gist_id]
pretty_URL = f'https://gist.github.com/{user_name}/{gist_name}'
return pretty_URL
@classmethod
def decode(cls, pretty_URL: str) -> str:
gist_name = pretty_URL.split('/')[-1]
user_name = pretty_URL.split('/')[-2]
gist_id = cls.gist_name_to_id[gist_name]
URL = f'https://gist.github.com/{user_name}/{gist_id}'
return URL
def main_list():
Gist_id_name_mapping.list()
def main_encode(URL):
return Gist_id_name_mapping.encode(URL)
def main_decode(pretty_URL):
return Gist_id_name_mapping.decode(pretty_URL)
# Input user name or use local file
# list, or conversion between URL types
def usage_str_strip(usage_str: str, indent_level = 1) -> str:
# 1 indent_level is 4 spaces
_ = usage_str.splitlines()
lines = _[1:-1]
for i, line in enumerate(lines):
lines[i] = line[4*indent_level:]
return '\n'.join(lines)
def usage():
usage_str = '''
Usage:
./get_all_gist.py <username>
'''
print(usage_str_strip(usage_str), file=sys.stderr)
if __name__ == '__main__':
# -L, --local <filename>
# -u, --username <username>
# -l, --list
if len(sys.argv) != 2:
usage()
exit()
# Use local file
if sys.argv[1] == '-L':
is_use_local_file = True
else:
is_use_local_file = False
user_name = sys.argv[1]
if is_use_local_file:
output = subprocess.check_output(shlex.split('cat gist.html'))
else:
output = subprocess.check_output(shlex.split(f'''curl https://gist.github.com/{user_name} -k --no-progress-meter'''))
html = output.decode()
if html == 'Not Found':
print("User name not found", file=sys.stderr)
exit()
pattern = '<a href="/(?P<user_name>.+)/(?P<gist_id>[0-9a-f]{32})"><strong class="css-truncate-target">(?P<gist_name>.+)</strong></a>'
entries = [ (entry:=Entry(*m.group('user_name', 'gist_id', 'gist_name'))) for m in re.finditer(pattern, html)]#entries : const list[3-tuple[str]]
Gist_id_name_mapping.clear()
Gist_id_name_mapping.populate(entries)
main_list()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment