#! /usr/bin/env python3 # liste les sections de interview-preparation-kit # crée les liens symboliques sur les challenges déjà réalisés par ailleurs import os import requests import requests_cache import glob import argparse from hrinit import Colors import sys import logging import datetime from collections import defaultdict class Interview: def __init__(self): self.basedir = os.path.dirname(__file__) self.session = requests.Session() def get(self, playlist, content=None): if content: url = 'https://www.hackerrank.com/rest/playlists/{}/{}'.format(playlist, content) else: url = 'https://www.hackerrank.com/rest/playlists/{}'.format(playlist) return self.session.get(url).json() def run(self, create_links=False): # get challenges from algorithms, data-structures, tutorials # (interview-preparation-kit ones are picked among them) files = defaultdict(lambda: []) for i in ['algorithms', 'data-structures', 'tutorials']: pattern = os.path.join(self.basedir, i, "**", "*.*") for j in glob.iglob(pattern, recursive=True): if not os.path.isfile(j): continue path, name = os.path.split(j) slug, lang = os.path.splitext(name) if name == "CMakeLists.txt" or name == "README.md" or lang == ".hpp": continue files[slug].append(j) # get the playlist of playlists data = self.get('interview-preparation-kit') name = data['name'] print("{}{}{}".format(Colors.BLUE, name, Colors.END)) for playlist in data['playlists']: print(" {}{}{}".format(Colors.LIGHT_BLUE, playlist['name'], Colors.END)) section_dir = os.path.join(self.basedir, 'interview-preparation-kit', playlist['slug']) os.makedirs(section_dir, exist_ok=True) if playlist['videos_count'] != 0: for video in self.get(playlist['slug'], 'videos')['videos']: # Nota: duration field is in ISO-8601 duration format print(" {}{:60}{} http://youtu.be/{}".format( Colors.LIGHT_CYAN, video['title'], Colors.END, video['youtube_id'])) if playlist['challenges_count'] == 0: print(" {}{}{}".format(Colors.LIGHT_RED, "no challenge", Colors.END)) else: challenges = self.get(playlist['slug'], 'challenges') for challenge in challenges['challenges']: print(" {}{}{}".format(Colors.GREEN, challenge['name'], Colors.END)) slug = challenge['slug'] if slug in files: for i in files[slug]: dest = os.path.join(section_dir, os.path.basename(i)) src = os.path.relpath(i, section_dir) if not os.path.exists(dest): print(" LINK", src) if create_links: os.symlink(src, dest) def set_logging(verbose): """ set up a colorized logger """ if sys.stdout.isatty(): logging.addLevelName(logging.DEBUG, "\033[0;32m%s\033[0m" % logging.getLevelName(logging.DEBUG)) logging.addLevelName(logging.INFO, "\033[1;33m%s\033[0m" % logging.getLevelName(logging.INFO)) logging.addLevelName(logging.WARNING, "\033[1;35m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) logging.addLevelName(logging.ERROR, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) if verbose: logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.DEBUG, datefmt='%H:%M:%S') else: logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.ERROR, datefmt='%H:%M:%S') def set_cache(refresh=False): """ install the static Requests cache """ if refresh: expire_after = datetime.timedelta(seconds=0) else: expire_after = datetime.timedelta(days=30) requests_cache.install_cache( cache_name=os.path.join(os.path.dirname(__file__), "cache"), allowable_methods=('GET', 'POST'), expire_after=expire_after) requests_cache.core.remove_expired_responses() def main(): parser = argparse.ArgumentParser(description='Offliner for Interview Preparation Kit') parser.add_argument("-v", "--verbose", help="increase verbosity", action='store_true') parser.add_argument('-R', '--refresh', help="refresh the catalogs (do not use cache)", action="store_true") # noqa parser.add_argument('-l', '--links', help="create symlinks", action='store_true') args = parser.parse_args() set_logging(args.verbose) set_cache(args.refresh) interview = Interview() interview.run(args.links) if __name__ == '__main__': main()