├── .DS_Store ├── .gitignore ├── README.md ├── docs ├── create.png ├── delete.png ├── help.png └── list.png ├── mygist.py ├── requirements.txt ├── scripts ├── __init__.py └── gists.py └── setup.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishichoudhary/mygist/d9a9efafa10d13d6e3c119989debac2382580d80/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | env/ 2 | __pycache__/ 3 | *.pyc 4 | .git/ 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mygist 2 | Command line tool for gist creation,deletion,fetching,editing and many-more. 3 | 4 | # Prerequisites 5 | python3 6 | python-requests, python-json, python-argparse, python-builtins libraries 7 | 8 | ## Commands 9 | 10 | ### 1. Create 11 | python mygist.py -u github_user_name -f file_name1,file_name2..,file_nameN -t description 12 | ![Alt text](https://github.com/vishichoudhary/mygist/blob/master/docs/create.png?raw=true "Image to show create command ") 13 | 14 | ### 2. Delete 15 | python mygist.py -u github_user.name -d gist_id 16 | ![Alt text](https://github.com/vishichoudhary/mygist/blob/master/docs/delete.png?raw=true "Image to show delete command ") 17 | 18 | ### 3. List 19 | python mygist.py -l -u github_user.name 20 | ![Alt text](https://github.com/vishichoudhary/mygist/blob/master/docs/list.png?raw=true "Image to show list command ") 21 | 22 | ### 3. Help 23 | python mygist.py -h 24 | ![Alt text](https://github.com/vishichoudhary/mygist/blob/master/docs/help.png?raw=true "Image to show help command ") 25 | -------------------------------------------------------------------------------- /docs/create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishichoudhary/mygist/d9a9efafa10d13d6e3c119989debac2382580d80/docs/create.png -------------------------------------------------------------------------------- /docs/delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishichoudhary/mygist/d9a9efafa10d13d6e3c119989debac2382580d80/docs/delete.png -------------------------------------------------------------------------------- /docs/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishichoudhary/mygist/d9a9efafa10d13d6e3c119989debac2382580d80/docs/help.png -------------------------------------------------------------------------------- /docs/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishichoudhary/mygist/d9a9efafa10d13d6e3c119989debac2382580d80/docs/list.png -------------------------------------------------------------------------------- /mygist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import argparse, getpass, os, sys 4 | from builtins import input 5 | from scripts.gists import GistHandler, Gist 6 | 7 | parser = argparse.ArgumentParser(description="Auxiliar script to handle migraines related data") 8 | parser.add_argument("-u", "--username", default = None, help="Username of the GitHub account") 9 | parser.add_argument("-p", "--password", default = None, help="Password of the GitHub account") 10 | parser.add_argument("-c", "--create", action="store_true", help="To create a new gist") 11 | parser.add_argument("-d", "--description", default=None, help="Description of the new gist") 12 | parser.add_argument("-f", "--files", default=None, help="File names to use as content") 13 | parser.add_argument("-b", "--public", action="store_true", help="Specifies if the gist will be public") 14 | parser.add_argument("-r", "--remove", default = None, help="To delete an existing gist (by id)") 15 | parser.add_argument("-l", "--list", action = "store_true", help="List the gists of an user (with authentication)") 16 | parser.add_argument("-ls", "--list_starred", action = "store_true", help="List the starred gists of an user (with authentication)") 17 | parser.add_argument("-la", "--list_anonimously", action = "store_true", help="List the gists of an user (without authentication)") 18 | parser.add_argument("-i", "--info", default = None, help="Get detailed info of a gist (by id)") 19 | parser.add_argument("-s", "--star", default = None, help="Star an existing gist (by id)") 20 | parser.add_argument("-n", "--unstar", default = None, help="Untar an existing gist (by id)") 21 | 22 | args = parser.parse_args() 23 | 24 | # Examples: 25 | # Remove a gist: python mygist.py -u [USERNAME] -r [GIST_ID] 26 | # Create a gist: python mygist.py -d [DESCRIPTION] -f [FILE_NAME] -p 27 | # List gists: python mygist.py -l 28 | # See the help: python mygist.py -h 29 | 30 | #print(args) 31 | if args.info is None: 32 | if args.username is None: 33 | args.username = input("Enter your github user name: ") 34 | 35 | if args.info is None and not args.list_anonimously: 36 | if args.password is None: 37 | args.password = getpass.getpass("Enter your github password: ") 38 | 39 | gists = GistHandler(args.username, args.password) 40 | 41 | if args.star is not None: 42 | starred = gists.star(args.star) 43 | 44 | if not starred: 45 | raise Exception("Invalid gist ID") 46 | elif args.unstar is not None: 47 | unstarred = gists.unstar(args.unstar) 48 | 49 | if not unstarred: 50 | raise Exception("Invalid gist ID") 51 | elif args.info is not None: 52 | gist = gists.retrieve(args.info) 53 | 54 | if gist is None: 55 | raise Exception("Invalid gist ID") 56 | 57 | print("\nId: %s" % gist.id) 58 | print("Description: %s" % gist.description) 59 | print("Public: %s" % ("Yes" if gist.public else "No")) 60 | print("Owner: %s" % gist.owner) 61 | print("Created_at: %s" % gist.created_at) 62 | print("Updated_at: %s" % gist.updated_at) 63 | 64 | print("\nFiles:") 65 | for position, gist_file in enumerate(gist.files): 66 | print("\t(%d)" % (position + 1)) 67 | print("\tFilename: %s" % gist_file.filename) 68 | print("\tLanguage: %s" % gist_file.language) 69 | print("\tSize: %s bytes\n" % gist_file.size) 70 | 71 | elif args.remove is not None: 72 | if gists.delete(args.remove): 73 | print("Deleted succesfully!") 74 | else: 75 | raise Exception("Invalid gist ID") 76 | 77 | elif args.list: 78 | gists.list() # It would be better to retrieve the gists data and make here the prints 79 | elif args.list_starred: 80 | gists.list(starred = True) 81 | elif args.list_anonimously: 82 | gists.list(anonymous = True) 83 | else: # Create as default action 84 | if args.description is None: 85 | args.description = input("Enter the description for the gist: ") 86 | 87 | if not args.public: 88 | args.public = input("Make this gist public (y/n): ") in ("y", "Y") 89 | 90 | files = args.files.split(",") if args.files else "" 91 | existing_files = list(filter(os.path.exists, files)) 92 | 93 | if args.files is None or len(existing_files) == 0: 94 | print("No existing files were specified") 95 | alt_file = "" 96 | 97 | while len(existing_files) == 0: 98 | alt_file = input("Enter the file names (separated with commas): ") 99 | files = list(map(lambda s: s.strip(), alt_file.split(","))) 100 | existing_files = list(filter(os.path.exists, files)) 101 | 102 | if len(existing_files) == 0: 103 | print("No existing files were specified") 104 | elif len(existing_files) != len(files): 105 | print("Warning! The following files do not exist:") 106 | for f in files: 107 | if f not in existing_files: 108 | print(f) 109 | if input("Continue anyway? (y/n): ") not in ("y", "Y"): 110 | existing_files = [] 111 | 112 | 113 | file_pairs = [] # (name, content) 114 | for file_path in existing_files: 115 | with open(file_path, "r") as myfile: 116 | file_pairs.append((os.path.basename(file_path), myfile.read())) 117 | 118 | gist_id = gists.create(args.description, file_pairs, args.public) 119 | 120 | if gist_id is not None: 121 | print("Created succesfully. Gist ID: %s" % gist_id) 122 | print("Sharing link is https://gist.github.com/"+args.username+"/"+gist_id) 123 | else: 124 | print("There was a problem creating the gist") 125 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.18.4 2 | -------------------------------------------------------------------------------- /scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishichoudhary/mygist/d9a9efafa10d13d6e3c119989debac2382580d80/scripts/__init__.py -------------------------------------------------------------------------------- /scripts/gists.py: -------------------------------------------------------------------------------- 1 | import datetime, re, requests, json, time 2 | #import global_vars as gv 3 | 4 | class GistFile: 5 | def __init__(self, json_data): 6 | self.filename = json_data["filename"] 7 | self.content = json_data["content"] 8 | self.language = json_data["language"] 9 | self.size = json_data["size"] 10 | self.type = json_data["type"] 11 | self.truncated = json_data["truncated"] 12 | 13 | 14 | class Gist: 15 | def __init__(self, json_data): 16 | self.url = json_data["url"] 17 | self.forks_url = json_data["forks_url"] 18 | self.commits_url = json_data["commits_url"] 19 | self.id = json_data["id"] 20 | self.description = json_data["description"] 21 | self.public = json_data["public"] 22 | self.owner = json_data["owner"]["login"] 23 | self.truncated = json_data["truncated"] 24 | self.comments = json_data["comments"] 25 | self.created_at = json_data["created_at"] 26 | self.updated_at = json_data["updated_at"] 27 | 28 | # Store also the created and updated datetimes as timestamps 29 | dt_pattern = r"([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})Z" 30 | created_groups = map(int, re.match(dt_pattern, self.created_at).groups()) 31 | self.created_at_ts = int(time.mktime(datetime.datetime(*created_groups).timetuple())) 32 | updated_groups = map(int, re.match(dt_pattern, self.updated_at).groups()) 33 | self.updated_at_ts = int(time.mktime(datetime.datetime(*updated_groups).timetuple())) 34 | 35 | self.files = [] 36 | 37 | for file_name in json_data["files"]: 38 | self.files.append(GistFile(json_data["files"][file_name])) 39 | 40 | 41 | class GistHandler: 42 | "Class for gist creation" 43 | def __init__(self, user = None, passwd = None): 44 | self.user = user 45 | self.passwd = passwd 46 | self.gists_number = 0 47 | 48 | def auth(user, passwd): 49 | self.user = user 50 | self.passwd = passwd 51 | 52 | def list(self, anonymous = False, starred = False): 53 | 54 | if anonymous: 55 | if self.user is None: 56 | raise Exception("An username is required") 57 | url='https://api.github.com/users/%s/gists' % self.user 58 | req=requests.get(url) 59 | elif starred: 60 | url='https://api.github.com/gists/starred' 61 | req=requests.get(url, auth = (self.user, self.passwd)) 62 | else: 63 | url='https://api.github.com/users/%s/gists' % self.user 64 | req=requests.get(url, auth = (self.user, self.passwd)) 65 | 66 | res_ans=req.json() 67 | 68 | if req.status_code==200: 69 | self.gists_number = len(res_ans) 70 | #print("Total no of gists are "+str(len(res_ans))) 71 | for i in range(len(res_ans)): 72 | l=list(res_ans[i]['files'].keys()) 73 | new_dict={l[0]:res_ans[i]['files'][l[0]]['raw_url']} 74 | id_temp={l[0]:res_ans[i]['id']} 75 | print("\n"+str(i+1)+" "+l[0]) 76 | print("Gist id is " + res_ans[i]['id']) 77 | else: 78 | raise Exception("Login failed.") 79 | 80 | def retrieve(self, gist_id): 81 | self.url='https://api.github.com/gists/' + gist_id 82 | #req=requests.get(self.url, auth = (self.user,self.passwd)) 83 | req=requests.get(self.url) 84 | return Gist(json.loads(req.text)) if req.status_code == 200 else None 85 | 86 | def create(self, description, files, public = True): 87 | 88 | files_dic = {} 89 | 90 | for file_name, file_cont in files: 91 | files_dic[file_name] = {"content": file_cont} 92 | 93 | self.send_dict={"description":description, 94 | "public": public, 95 | "files": files_dic 96 | } 97 | 98 | req=requests.post('https://api.github.com/gists',auth=(self.user,self.passwd),data=json.dumps(self.send_dict)) 99 | return None if req.status_code != 201 else json.loads(req.text)["id"] 100 | 101 | def delete(self, gist_id): 102 | self.url='https://api.github.com/gists/' + gist_id 103 | req=requests.delete(self.url, auth = (self.user,self.passwd)) 104 | return req.status_code == 204 105 | 106 | def star(self, gist_id): 107 | url = 'https://api.github.com/gists/%s/star' % gist_id 108 | req = requests.put(url, auth = (self.user,self.passwd)) 109 | return req.status_code == 204 110 | 111 | def unstar(self, gist_id): 112 | url = 'https://api.github.com/gists/%s/star' % gist_id 113 | req = requests.delete(url, auth = (self.user,self.passwd)) 114 | return req.status_code == 204 115 | 116 | 117 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | with open("README.md", 'r') as f: 4 | long_description = f.read() 5 | 6 | setup( 7 | name='mygist', 8 | version='1.0', 9 | description='Command line tool for gist creation, deletion, fetching, editing and many-more.', 10 | author='Vishi Choudhary', 11 | #packages=['mygist'], 12 | install_requires=['requests'], 13 | scripts=['scripts/gists.py',] 14 | ) 15 | --------------------------------------------------------------------------------