Source code for flexget.plugins.input.my_anime_list

from dateutil.parser import parse as parsedate
from loguru import logger

from flexget import plugin
from flexget.config_schema import one_or_more
from flexget.entry import Entry
from flexget.event import event
from flexget.utils.cached_input import cached
from flexget.utils.requests import RequestException

logger = logger.bind(name='my_anime_list')

STATUS = {'watching': 1, 'completed': 2, 'on_hold': 3, 'dropped': 4, 'plan_to_watch': 6, 'all': 7}

AIRING_STATUS = {'airing': 1, 'finished': 2, 'planned': 3, 'all': 6}

ANIME_TYPE = ['all', 'tv', 'ova', 'movie', 'special', 'ona', 'music', 'unknown']


[docs] class MyAnimeList: """Create entries for series and movies from MyAnimeList list. Syntax:: my_anime_list: username: <value> status: - <watching|completed|on_hold|dropped|plan_to_watch> - <watching|completed|on_hold|dropped|plan_to_watch> ... airing_status: - <airing|finished|planned> - <airing|finished|planned> ... type: - <series|ova...> """ schema = { 'type': 'object', 'properties': { 'username': {'type': 'string'}, 'status': one_or_more( {'type': 'string', 'enum': list(STATUS.keys()), 'default': 'all'}, unique_items=True, ), 'airing_status': one_or_more( {'type': 'string', 'enum': list(AIRING_STATUS.keys()), 'default': 'all'}, unique_items=True, ), 'type': one_or_more( {'type': 'string', 'enum': list(ANIME_TYPE), 'default': 'all'}, unique_items=True ), }, 'required': ['username'], 'additionalProperties': False, } @cached('my_anime_list', persist='2 hours') def on_task_input(self, task, config): selected_status = config.get('status', ['all']) if not isinstance(selected_status, list): selected_status = [selected_status] selected_airing_status = config.get('airing_status', ['all']) if not isinstance(selected_airing_status, list): selected_airing_status = [selected_airing_status] selected_types = config.get('type', ['all']) if not isinstance(selected_types, list): selected_types = [selected_types] selected_status = [STATUS[s] for s in selected_status] selected_airing_status = [AIRING_STATUS[s] for s in selected_airing_status] list_json = [] for status in selected_status: # JSON pages are limited to 300 entries offset = 0 results = 300 while results == 300: try: list_json += task.requests.get( f'https://myanimelist.net/animelist/{config.get("username")}/load.json', params={'status': status, 'offset': offset}, ).json() except RequestException as e: logger.error('Error finding list on url: {}', e.request.url) break except (ValueError, TypeError): logger.error('Invalid JSON response') break results = len(list_json) or 1 offset += len(list_json) for anime in list_json: has_selected_status = ( anime['status'] in selected_status or config['status'] == 'all' ) has_selected_airing_status = ( anime['anime_airing_status'] in selected_airing_status or config['airing_status'] == 'all' ) has_selected_type = ( anime['anime_media_type_string'].lower() in selected_types or config['type'] == 'all' ) if has_selected_status and has_selected_type and has_selected_airing_status: entry = Entry() # MAL sometimes returns title as an integer entry['title'] = str(anime['anime_title']) entry['url'] = f'https://myanimelist.net{anime["anime_url"]}' entry['mal_id'] = anime['anime_id'] entry['mal_poster'] = anime['anime_image_path'] entry['mal_type'] = anime['anime_media_type_string'] entry['mal_tags'] = anime['tags'] entry['mal_genres'] = [genre['name'] for genre in anime['genres']] entry['mal_demographics'] = [demo['name'] for demo in anime['demographics']] entry['mal_name'] = entry['title'] entry['mal_episodes'] = anime['anime_num_episodes'] entry['mal_airing_status'] = ( 'Unknown' if anime['anime_airing_status'] not in AIRING_STATUS.values() else [ k for k, v in AIRING_STATUS.items() if v == anime['anime_airing_status'] ].pop().title() ) if anime.get('anime_title_eng'): entry['mal_name_eng'] = str(anime['anime_title_eng']) if anime.get('anime_start_date_string'): entry['mal_start_date'] = parsedate( # Handle undefined Day/Month on unreleased entries anime['anime_start_date_string'].replace('00', '01'), dayfirst=False, ) if anime.get('anime_end_date_string'): entry['mal_end_date'] = parsedate( # Handle undefined Day/Month on ongoing/unreleased entries anime['anime_end_date_string'].replace('00', '01'), dayfirst=False, ) if entry.isvalid(): yield entry
[docs] @event('plugin.register') def register_plugin(): plugin.register(MyAnimeList, 'my_anime_list', api_ver=2)