Source code for annict.models

# -*- coding: utf-8 -*-
import abc

import arrow


[docs]class ResultSet(list): """A list like object that holds results from an Annict API query.""" def __init__(self, total_count, prev_page=None, next_page=None): super().__init__() self.total_count = total_count self.prev_page = prev_page self.next_page = next_page
[docs]class Model(metaclass=abc.ABCMeta): """Abstract class of each models.""" def __init__(self, api=None): self._api = api self._children = []
[docs] @classmethod @abc.abstractmethod def parse(cls, api, json): """Parse a JSON object into a model instance.""" raise NotImplementedError
[docs] @classmethod def parse_list(cls, api, json, payload_type): """Parse JSON objects into list of model instances. :param api: instance of :class:`API <annict.api.API>` . :type api: annict.api.API :param dict json: JSON from Annict API. :param str payload_type: Type of payload. :return: list of Model objects. :rtype: ResultSet """ results = ResultSet( total_count=json["total_count"], prev_page=json["prev_page"], next_page=json["next_page"], ) results._json = json if payload_type == "activity": pluralized_payload_name = "activities" elif payload_type == "person": pluralized_payload_name = "people" else: pluralized_payload_name = "{}s".format(payload_type) for obj in json[pluralized_payload_name]: if obj: results.append(cls.parse(api, obj)) return results
[docs]class User(Model): """User information model""" def __repr__(self): return f"<User:{self.id}:{self.name}:@{self.username}>"
[docs] @classmethod def parse(cls, api, json): """Parse a JSON object into a model instance. :param api: instance of :class:`API <annict.api.API>` . :type api: annict.api.API :param dict json: JSON from Annict API. :return: :class:`User <User>` object :rtype: User """ user = cls(api) user._json = json for k, v in json.items(): if k == "created_at": setattr(user, k, arrow.get(v).datetime) else: setattr(user, k, v) return user
[docs] def following(self, fields=None, page=None, per_page=None, sort_id=None): """Get following information of this user. :param fields: (optional) Narrow down the fields of data contained in the response body. :type fields: list of str :param int page: (optional) Specify the number of pages. :param int per_page: (optional) Specify how many items to acquire per page. :param str sort_id: (optional) Sort the results by their ID. You can specify `asc` or `desc`. :return: list of :class:`User <annict.models.User>` objects. :rtype: annict.models.ResultSet """ return self._api.following( fields=fields, filter_user_id=self.id, page=page, per_page=per_page, sort_id=sort_id, )
[docs] def followers(self, fields=None, page=None, per_page=None, sort_id=None): """Get following information of this user. :param fields: (optional) Narrow down the fields of data contained in the response body. :type fields: list of str :param int page: (optional) Specify the number of pages. :param int per_page: (optional) Specify how many items to acquire per page. :param str sort_id: (optional) Sort the results by their ID. You can specify `asc` or `desc`. :return: list of :class:`User <annict.models.User>` objects. :rtype: annict.models.ResultSet """ return self._api.followers( fields=fields, filter_user_id=self.id, page=page, per_page=per_page, sort_id=sort_id, )
[docs]class Work(Model): """Work information model""" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._episodes = None def __repr__(self): return f"<Work:{self.id}:{self.title}>"
[docs] @classmethod def parse(cls, api, json): """Parse a JSON object into a model instance. :param api: instance of :class:`API <annict.api.API>` . :type api: annict.api.API :param dict json: JSON from Annict API. :return: :class:`Work <Work>` object :rtype: Work """ work = cls(api) work._json = json for k, v in json.items(): if k == "released_on": if v: date = arrow.get(v).date() else: date = None setattr(work, k, date) else: setattr(work, k, v) return work
[docs] def set_status(self, kind): """Set the status of the work. :param str kind: Types of status. You can specify `wanna_watch`, `watching`, `watched`, `on_hold`, `stop_watching`, or `no_select`. :return: Returns `True` if deletion succeeded. """ return self._api.set_status(self.id, kind)
[docs] def episodes( self, fields=None, filter_ids=None, page=None, per_page=None, sort_id=None, sort_sort_number=None, ): """Get episodes information :reference: https://docs.annict.com/ja/api/v1/episodes.html :param fields: (optional) Narrow down the fields of data contained in the response body. :type fields: list of str :param filter_ids: (optional) Filter results by IDs. :type filter_ids: list of int :param int page: (optional) Specify the number of pages. :param int per_page: (optional) Specify how many items to acquire per page. :param str sort_id: (optional) Sort the results by their ID. You can specify `asc` or `desc`. :param str sort_sort_number: (optional) Sort by number for sorting. You can specify `asc` or `desc`. :return: list of :class:`Episode <annict.models.Episode>` objects. :rtype: annict.models.ResultSet """ return self._api.episodes( fields=fields, filter_ids=filter_ids, filter_work_id=self.id, page=page, per_page=per_page, sort_id=sort_id, sort_sort_number=sort_sort_number, )
[docs] def select_episodes(self, *numbers): """Select multiple episodes :param numbers: Episode number. :return: list of :class:`Episode <Episode>` :rtype: list of :class:`Episode <Episode>` """ if not self._episodes: self._episodes = self.episodes(sort_sort_number="asc") if not numbers: return self._episodes return [self._episodes[n - 1] for n in numbers]
[docs] def get_episode(self, number): """Get Episode object :param number: Episode number :return: :class:`Episode <Episode>` object :rtype: Episode """ return self.select_episodes(number)[0]
[docs]class Episode(Model): """Episode information model""" def __repr__(self): return f"<Episode:{self.id}:{self.number_text}:{self.title}:{self.work.title}>"
[docs] @classmethod def parse(cls, api, json): """Parse a JSON object into a model instance. :param api: instance of :class:`API <annict.api.API>` . :type api: annict.api.API :param dict json: JSON from Annict API. :return: :class:`Episode <Episode>` object :rtype: Episode """ episode = cls(api) episode._json = json for k, v in json.items(): if k == "episode": setattr(episode, "episode_id", v) elif k == "work": work = Work.parse(api, v) setattr(episode, k, work) elif k == "prev_episode" and v: prev_episode = cls.parse(api, v) setattr(episode, k, prev_episode) elif k == "next_episode" and v: next_episode = cls.parse(api, v) setattr(episode, k, next_episode) else: setattr(episode, k, v) return episode
[docs] def create_record( self, comment=None, rating=None, share_twitter=False, share_facebook=False ): """Create a record for this episode. :param str comment: (optional) Comment. :param float rating: (optional) Rating. :param bool share_twitter: (optional) Whether to share the record on Twitter. You can enter `True` or `False`. :param bool share_facebook: (optional) Whether to share the record on Facebook. You can enter `True` or `False`. :return: :class:`Record <annict.models.Record>` object. """ return self._api.create_record( self.id, comment, rating, share_twitter, share_facebook )
[docs]class Record(Model): """Record information model""" def __repr__(self): return f"<Record:{self.id}>"
[docs] @classmethod def parse(cls, api, json): """Parse a JSON object into a model instance. :param api: instance of :class:`API <annict.api.API>` . :type api: annict.api.API :param dict json: JSON from Annict API. :return: :class:`Record <Record>` object :rtype: Record """ record = cls(api) record._json = json for k, v in json.items(): if k == "created_at": setattr(record, k, arrow.get(v).datetime) elif k == "user": user = User.parse(api, v) setattr(record, k, user) elif k == "work": work = Work.parse(api, v) setattr(record, k, work) elif k == "episode": episode = Episode.parse(api, v) setattr(record, k, episode) else: setattr(record, k, v) return record
[docs] def edit( self, comment=None, rating=None, share_twitter=False, share_facebook=False ): """Edit the created record. :param str comment: (optional) Comment. :param float rating: (optional) Rating. :param bool share_twitter: (optional) Whether to share the record on Twitter. You can enter `True` or `False`. :param bool share_facebook: (optional) Whether to share the record on Facebook. You can enter `True` or `False`. :return: :class:`Record <annict.models.Record>` object after edit. """ return self._api.edit_record( self.id, comment, rating, share_twitter, share_facebook )
[docs] def delete(self): """Delete the created record. :return: Returns `True` if deletion succeeded. """ return self._api.delete_record(self.id)
[docs]class Program(Model): """Program information model""" def __repr__(self): return f"<Program:{self.id}>"
[docs] @classmethod def parse(cls, api, json): """Parse a JSON object into a model instance. :param api: instance of :class:`API <annict.api.API>` . :type api: annict.api.API :param dict json: JSON from Annict API. :return: :class:`Program <Program>` object :rtype: Program """ program = cls(api) program._json = json for k, v in json.items(): if k == "started_at": setattr(program, k, arrow.get(v).datetime) elif k == "work": work = Work.parse(api, v) setattr(program, k, work) elif k == "episode": episode = Episode.parse(api, v) setattr(program, k, episode) else: setattr(program, k, v) return program
[docs]class Activity(Model): """Activity information model""" def __repr__(self): return f"<Activity:{self.action}:@{self.user.username}>"
[docs] @classmethod def parse(cls, api, json): """Parse a JSON object into a model instance. :param api: instance of :class:`API <annict.api.API>` . :type api: annict.api.API :param dict json: JSON from Annict API. :return: :class:`Activity <Activity>` object :rtype: Activity """ activity = cls(api) activity._json = json for k, v in json.items(): if k == "created_at": setattr(activity, k, arrow.get(v).datetime) elif k == "user": user = User.parse(api, v) setattr(activity, k, user) elif k == "work": work = Work.parse(api, v) setattr(activity, k, work) elif k == "episode": episode = Episode.parse(api, v) setattr(activity, k, episode) else: setattr(activity, k, v) return activity
[docs]class Person(Model): """Person information model such as cast and staff""" def __repr__(self): return f"<Person:{self.id}:{self.name}>"
[docs] @classmethod def parse(cls, api, json): """Parse a JSON object into a model instance. :param api: instance of :class:`API <annict.api.API>` . :type api: annict.api.API :param dict json: JSON from Annict API. :return: :class:`Person <Person>` object :rtype: Person """ person = cls(api) person._json = json for k, v in json.items(): if k == "birthday": if v: date = arrow.get(v).date() else: date = None setattr(person, k, date) else: setattr(person, k, v) return person
MODEL_MAPPING = { "user": User, "work": Work, "episode": Episode, "record": Record, "program": Program, "activity": Activity, "person": Person, }