Exemple #1
0
    def select_option(self, options, find_arg=None):
        if self.serv_name:
            self.choices[self.state] = options[self.serv_path[self.state]]
            self._next_state()
            return

        print(f'Select your {self.state} from below choices:')
        if self.state == 'continent':
            choice = get_choice(options, find_arg, None)
            if choice == -1:
                print_quit()
        else:
            choice = get_choice(options, find_arg)

        if choice == -1:
            if self.state in self.choices:
                del self.choices[self.state]
            self._prev_state()
            if self.state in self.cache:
                self.select_option(**self.cache[self.state])
        else:
            self.choices[self.state] = options[choice]
            self.serv_path[self.state] = choice
            name = options[choice].select_one(find_arg).text
            print(f"You have selected {name}.")
            self.cache[self.state] = {'options': options, 'find_arg': find_arg}
            self._next_state()
Exemple #2
0
    def get_serv_details(self):
        serv = self.choices.get('server')
        if not serv:
            print_quit('No server selected')

        if not self.serv_name:
            print("Details:")
            for item in serv.select('li.list-group-item'):
                print(item.text.strip())
        else:
            print("Selected", self.serv_name)

        form = serv.form
        config_url = form.a['href']
        config_name = config_url[config_url.rfind('/') + 1:]
        self.server = {
            'name': config_name[:config_name.find('.com')].lower(),
            'create_url': form['action'],
            'id': form.find('input')['value'],
            'config_url': config_url,
            'config_name': config_name
        }
        self.serv_name = self.server['name']
        self.save_serv_path()
        self.download_serv_config()
Exemple #3
0
 def state_loop(self):
     for _ in range(25):
         if self.state == 'END':
             break
         if self.state == 'continent':
             self._get_continent()
         elif self.state == 'country':
             self._get_country()
         elif self.state == 'protocol':
             self._get_protocol()
         elif self.state == 'server':
             self._get_server()
     else:
         print_quit("Too many choices")
def parse_lec_ranges(ranges: str, total_lecs: int) -> set:
    if not ranges:
        return set(range(1, total_lecs + 1))
    lecture_ids = set()
    ranges = ranges.split(",") if ranges.find(",") else (ranges, )
    for r in ranges:
        m = RANGE_PAT.match(r)
        if not m:
            print_quit(f'Invalid range "{r}"')
        start = int(m["l"] or 1)
        end = start + 1 if m["r"] is None else int(m["r"] or total_lecs + 1)
        if start >= end:
            print_quit(f'Invalid range "{r}"')
        lecture_ids.update(range(start, min(end, total_lecs + 1)))
    return lecture_ids
Exemple #5
0
def login(username, password):
    payload = {"username": username, "password": password}
    try:
        response = requests.post(IMP_BASE_URL + IMP_LOGIN_URL, data=payload, timeout=3)
    except (requests.ConnectionError, requests.Timeout) as e:
        print_quit(f"Connection Error {e}")
    if response.status_code >= 500:
        print_quit("Impartus not responding properly")
    elif response.status_code == 400:
        print_quit("Invalid login request. Impartus changed something.")
    elif response.status_code == 401:
        print_quit("Invalid login credentials!")
    resp = response.json()
    if not resp["success"]:
        print_quit(f"Impartus: {resp.get('message', resp)}", 1)
    return resp["token"]
def login(username, password):
    payload = {"username": username, "password": password}
    try:
        response = requests.post(IMP_BASE_URL + IMP_LOGIN_URL,
                                 data=payload,
                                 timeout=3)
    except (requests.ConnectionError, requests.Timeout) as e:
        print_quit(f"Connection Error {e}")
    if response.status_code >= 500:
        print_quit("Impartus not responding properly", 1)
    resp = response.json()
    if not resp["success"]:
        print_quit("Impartus:" + resp["message"], 1)
    return resp["token"]
def main():
    try:
        sp.check_call(["ffmpeg", "-version"], **dict(sp_args,
                                                     stdout=sp.DEVNULL))
    except FileNotFoundError:
        print_quit("ffmpeg not found. Ensure it is present in PATH.")
    config = read_json(CONFIG_FILE, verbose=True)
    data = read_json(DATA_FILE) or {"urls": {}}
    args = parse_args(config, data["urls"])
    if not args.username or not args.password:
        print_quit("Email and password not provided.")
    if args.save_creds:
        config["creds"] = {
            "username": args.username,
            "password": args.password
        }
        store_json(config, CONFIG_FILE)

    course_lectures_url = get_course_url(args, data["urls"])
    token = login(args.username, args.password)

    headers = {"Authorization": "Bearer " + token}
    response = requests.get(course_lectures_url, headers=headers)
    if not response.ok:
        print_quit("Error fetching course info. Is the url proper?")

    lectures = response.json()
    total_lecs = len(lectures)
    subject_name = "{subjectName} {sessionName}".format(**lectures[0])
    working_dir: Path = args.dest / subject_name
    working_dir.mkdir(exist_ok=True, parents=True)
    print(f'Saving to "{working_dir}"')
    data["urls"][subject_name.upper()] = course_lectures_url
    store_json(data, DATA_FILE)

    lecture_ids = parse_lec_ranges(args.range, total_lecs)

    downloaded: dict = {
        int(file.stem[:2]): file
        for file in working_dir.glob("[0-9][0-9].*.mkv")
        if int(file.stem[:2]) in lecture_ids
    }
    if downloaded:
        if args.rename:
            rename_old(downloaded, lectures)
        if args.only_new:
            lecture_ids.difference_update(range(max(downloaded) + 1))
        elif args.force:
            print("Force option enabled. Deleting old lectures:",
                  *sorted(downloaded))
            for file in downloaded.values():
                file.unlink()
        else:
            print("Skipping already downloaded lectures:", *sorted(downloaded))
            lecture_ids.difference_update(downloaded)
    if not lecture_ids:
        print_quit("No lectures to download. Exiting.", 0)

    no_class = []
    task_args = []
    for lecture in reversed(lectures):  # Download lecture #1 first
        lec_no = lecture["seqNo"]

        if lec_no not in lecture_ids:
            continue

        file_name = make_filename(lecture)

        if not args.keep_no_class and "no class" in file_name.lower():
            no_class.append(lec_no)
            continue

        stream_url = IMP_BASE_URL + IMP_STREAM_URL.format(
            lecture["ttid"], token)
        task_args.append((
            token,
            stream_url,
            working_dir / file_name,
            args.quality,
            ANGLE_CHOICES.index(args.angle),
        ))

    if no_class:
        print("Skipping lectures with 'no class' in title:", *no_class)

    print("Downloading lecture numbers:",
          *sorted(lecture_ids.difference(no_class)))

    with DirServer(), ThreadPool(args.worker_processes) as pool:
        try:
            pool.starmap(download_stream, task_args)
            pool.close()
            pool.join()
        except KeyboardInterrupt:
            print_quit("Aborted.", 1)
    print("Finished!")