#!/usr/bin/env python3 # mal-show - prints all completed anime/manga from bs4 import BeautifulSoup # for parsing xml import sys # for sys.argv and exit() from datetime import datetime # for getting current date from pathlib import Path # for path import tarfile # for extracting import os # for removing import argparse current_date = datetime.now().strftime('%d-%m-%Y') list_dir_path = Path.home() / 'Downloads' / 'anime-list' parser = argparse.ArgumentParser(prog="mal-show", description="Print your anime/manga list from MAL in human readable format. Mandatory arguments are:\ either -A or -M to list anime or manga; at least one status value: -c, -w, -n, -d or -p.") parser.add_argument("-A", "--anime", action="store_const", const="anime", help="list anime entries") parser.add_argument("-M", "--manga", action="store_const", const="manga", help="list manga entries") parser.add_argument("-c", "--completed", action="store_true", help="list completed entries") parser.add_argument("-w", "--watching", action="store_true", help="list watching/reading entries") parser.add_argument("-o", "--on-hold", action="store_true", help="list on-hold entries") parser.add_argument("-d", "--dropped", action="store_true", help="list dropped entries") parser.add_argument("-p", "--plan-to-watch", action="store_true", help="list plan to watch/plan to read entries") parser.add_argument("-e", "--episodes", action="store_true", help="show episodes watched/chapters read") parser.add_argument("-t", "--tags", action="store_true", help="show user's tags") parser.add_argument("-s", "--score", action="store_true", help="show user's score") args = parser.parse_args() if not (args.anime or args.manga): parser.error("No list type specified, use either -A for anime or -M for manga.") elif (args.anime and args.manga): parser.error("Use one list type at the time") elif not (args.completed or args.watching or args.on_hold or args.dropped or args.plan_to_watch): parser.error("Specify at least one status of entries you want to view, for example -c for completed.") status_list = [status for status, flag in [ ('Completed', args.completed), ('Plan to Watch', args.plan_to_watch), ('Plan to Read', args.plan_to_watch), ('On-Hold', args.on_hold), ('Dropped', args.dropped), ('Watching', args.watching), ('Reading', args.watching) ] if flag] ltype = 'anime' if args.anime else 'manga' liststr = 'list-' + current_date + '.tar' try: listfile = tarfile.open(list_dir_path / liststr) except FileNotFoundError: print('List file not found, do you want to run mal-archive to download it now? (y/n): ', end="") choice = input().strip().lower() if (choice == 'y'): with open('mal-archive.py', 'r') as file: exec(file.read()) sys.exit() else: sys.exit() listfile.extractall() listfile.close() listfile = open(ltype + '-' + current_date + '.xml') soup = BeautifulSoup(listfile, 'xml') list_entries = soup.find_all(ltype) sorted_list_entries = sorted(list_entries, key=lambda anime: int(anime.find('my_score').text), reverse=True) for anime in sorted_list_entries: my_score = anime.find('my_score').text my_status = anime.find('my_status').text my_tags = anime.find('my_tags').text series_title = anime.find('series_title').text if ltype == 'anime' else anime.find('manga_title').text my_eps = anime.find('my_watched_episodes').text if ltype == 'anime' else anime.find('my_read_chapters').text eps = anime.find('series_episodes').text if ltype == 'anime' else anime.find('manga_chapters').text if (my_status not in status_list): # Check if the entry has status specified by a user continue if (args.score): if my_score == '0': # Show '-' instead of '0' my_score = '-' print('[' + my_score + '/10] ', end='') print(series_title, sep='', end='') if (args.episodes): print(' (' + my_eps + '/' + eps + ')', sep='', end='') if (args.tags and len(my_tags) > 1): print(' - ' + my_tags, end='') print() # print a new line os.remove('manga-' + current_date + '.xml') os.remove('anime-' + current_date + '.xml')