示例#1
0
 def handle(self, *args, **options):
     category = 'anime';
     work_query = 'SELECT mangaki_{category}.work_ptr_id, mangaki_work.id, mangaki_work.title, mangaki_work.poster, mangaki_work.nsfw, COUNT(mangaki_work.id) rating_count FROM mangaki_{category}, mangaki_work, mangaki_rating WHERE mangaki_{category}.work_ptr_id = mangaki_work.id AND mangaki_rating.work_id = mangaki_work.id AND mangaki_{category}.anidb_aid = 0 GROUP BY mangaki_work.id, mangaki_{category}.work_ptr_id HAVING COUNT(mangaki_work.id) >= {min_ratings} ORDER BY {order_by}'
     a = AniDB('mangakihttp', 1)
     for anime in Anime.objects.raw(work_query.format(category=category, min_ratings=6, order_by='rating_count DESC')):
         print(anime.title, anime.id)
         for proposal in a.search(r'\%s' % anime.title):
             print(proposal)
         anidb_aid = input('Which one? ')
         if anidb_aid == 'q':
             continue
         anime.anidb_aid = int(anidb_aid)
         anime.save()
示例#2
0
 def handle(self, *args, **options):
     q = Work.objects\
             .only('pk', 'title', 'poster', 'nsfw')\
             .annotate(rating_count=Count('rating'))\
             .filter(anidb_aid=0, category__slug='anime', rating_count__gte=6)\
             .order_by('-rating_count')
     a = AniDB('mangakihttp', 1)
     for anime in q:
         print(anime.title, anime.id)
         for proposal in a.search(r'\%s' % anime.title):
             print(proposal)
         anidb_aid = input('Which one? ')
         if anidb_aid == 'q':
             continue
         anime.anidb_aid = int(anidb_aid)
         anime.save()
示例#3
0
 def handle(self, *args, **options):
     category = 'anime'
     work_query = 'SELECT mangaki_{category}.work_ptr_id, mangaki_work.id, mangaki_work.title, mangaki_work.poster, mangaki_work.nsfw, COUNT(mangaki_work.id) rating_count FROM mangaki_{category}, mangaki_work, mangaki_rating WHERE mangaki_{category}.work_ptr_id = mangaki_work.id AND mangaki_rating.work_id = mangaki_work.id AND mangaki_{category}.anidb_aid = 0 GROUP BY mangaki_work.id, mangaki_{category}.work_ptr_id HAVING COUNT(mangaki_work.id) >= {min_ratings} ORDER BY {order_by}'
     a = AniDB('mangakihttp', 1)
     for anime in Anime.objects.raw(
             work_query.format(category=category,
                               min_ratings=6,
                               order_by='rating_count DESC')):
         print(anime.title, anime.id)
         for proposal in a.search(r'\%s' % anime.title):
             print(proposal)
         anidb_aid = input('Which one? ')
         if anidb_aid == 'q':
             continue
         anime.anidb_aid = int(anidb_aid)
         anime.save()
示例#4
0
class AniDBTest(TestCase):
    @staticmethod
    def create_anime(**kwargs):
        anime = Category.objects.get(slug='anime')
        return Work.objects.create(category=anime, **kwargs)

    @staticmethod
    def read_fixture(filename):
        with open(os.path.join(settings.TEST_DATA_DIR, filename), 'r', encoding='utf-8') as f:
            return f.read()

    def setUp(self):
        self.anidb = AniDB('test_client', 1)
        self.no_anidb = AniDB()
        self.search_fixture = self.read_fixture('search_sangatsu_no_lion.xml')

    def test_to_python_datetime(self):
        self.assertEqual(to_python_datetime('2017-12-25'), datetime(2017, 12, 25, 0, 0))
        self.assertEqual(to_python_datetime('2017-12'), datetime(2017, 12, 1, 0, 0))
        self.assertEqual(to_python_datetime('2017'), datetime(2017, 1, 1, 0, 0))
        self.assertRaises(ValueError, to_python_datetime, '2017-25')

    def test_missing_client(self):
        self.assertRaises(RuntimeError, self.no_anidb._request, 'dummypage')
        self.assertFalse(self.no_anidb.is_available)

    @responses.activate
    def test_anidb_search(self):
        responses.add(
            responses.GET,
            AniDB.SEARCH_URL,
            body=self.search_fixture,
            status=200,
            content_type='application/xml'
        )
        anime_query = 'sangatsu no lion'
        results = self.anidb.search(q=anime_query)
        self.assertEqual(len(results), 2)
        self.assertEqual(len(responses.calls), 1)

    @responses.activate
    def test_anidb_get_methods(self):
        responses.add(
            responses.GET,
            AniDB.BASE_URL,
            body=self.read_fixture('anidb/sangatsu_no_lion.xml'),
            status=200,
            content_type='application/xml'
        )

        titles, main_title = self.anidb.get_titles(anidb_aid=11606)
        creators, studio = self.anidb.get_creators(anidb_aid=11606)
        tags = self.anidb.get_tags(anidb_aid=11606)
        related_animes = self.anidb.get_related_animes(anidb_aid=11606)

        self.assertEqual(len(titles), 9)
        self.assertEqual(main_title, 'Sangatsu no Lion')
        self.assertEqual(len(creators), 4)
        self.assertEqual(studio.title, 'Shaft')
        self.assertEqual(len(tags), 30)
        self.assertEqual(len(related_animes), 2)

    @responses.activate
    def test_anidb_get_animes(self):
        # Fake an artist entry with no AniDB creator ID that will be filled by retrieving Sangatsu
        artist = Artist(name="Shinbou Akiyuki").save()

        filenames = ['anidb/sangatsu_no_lion.xml', 'anidb/sangatsu_no_lion.xml', 'anidb/hibike_euphonium.xml']
        with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps:
            for filename in filenames:
                rsps.add(
                    responses.GET,
                    AniDB.BASE_URL,
                    body=self.read_fixture(filename),
                    status=200,
                    content_type='application/xml'
                )

            sangatsu = self.anidb.get_or_update_work(11606)
            tags_sangatsu_from_anidb = self.anidb.get_tags(11606)
            tags_diff_sangatsu = diff_between_anidb_and_local_tags(sangatsu, tags_sangatsu_from_anidb)
            hibike = self.anidb.get_or_update_work(10889)

        # Retrieve tags
        tags_sangatsu = set(Work.objects.get(pk=sangatsu.pk).taggedwork_set.all().values_list('tag__title', flat=True))
        tags_hibike = set(Work.objects.get(pk=hibike.pk).taggedwork_set.all().values_list('tag__title', flat=True))
        shared_tags = tags_sangatsu.intersection(tags_hibike)

        # Checks on tags
        self.assertEqual(len(tags_sangatsu), 30)
        self.assertEqual(len(tags_hibike), 38)
        self.assertEqual(len(shared_tags), 18)

        # Check for Sangatsu's informations
        self.assertEqual(sangatsu.title, 'Sangatsu no Lion')
        self.assertEqual(sangatsu.nb_episodes, 22)
        self.assertEqual(sangatsu.studio.title, 'Shaft')
        self.assertEqual(sangatsu.date, datetime(2016, 10, 8, 0, 0))
        self.assertEqual(sangatsu.end_date, datetime(2017, 3, 18, 0, 0))

        # Check for Sangatsu's staff
        staff_sangatsu = Work.objects.get(pk=sangatsu.pk).staff_set.all().values_list('artist__name', flat=True)
        self.assertCountEqual(staff_sangatsu, ['Umino Chika', 'Hashimoto Yukari', 'Shinbou Akiyuki', 'Okada Kenjirou'])

        # Check retrieved tags from AniDB
        self.assertEqual(len(tags_diff_sangatsu["deleted_tags"]), 0)
        self.assertEqual(len(tags_diff_sangatsu["added_tags"]), 0)
        self.assertEqual(len(tags_diff_sangatsu["updated_tags"]), 0)
        self.assertEqual(len(tags_diff_sangatsu["kept_tags"]), len(tags_sangatsu))

        # Check for no artist duplication
        artist = Artist.objects.filter(name="Shinbou Akiyuki")
        self.assertEqual(artist.count(), 1)
        self.assertEqual(artist.first().anidb_creator_id, 59)

    @responses.activate
    def test_anidb_duplicate_anime_id(self):
        for _ in range(2):
            responses.add(
                responses.GET,
                AniDB.BASE_URL,
                body=self.read_fixture('anidb/hibike_euphonium.xml'),
                status=200,
                content_type='application/xml'
            )

        self.create_anime(title='Hibike! Euphonium', anidb_aid=10889)
        self.create_anime(title='Hibike! Euphonium Duplicate', anidb_aid=10889)

        self.anidb.get_or_update_work(10889)
        self.assertIs(self.anidb.get_or_update_work(10889), None)

    @responses.activate
    def test_anidb_nsfw(self):
        animes = {}

        animes_sources = {
            # Not NSFW at all
            'anidb/sangatsu_no_lion.xml': (11606, 'Sangatsu no Lion'),
            'anidb/hibike_euphonium.xml': (10889, 'Hibike! Euphonium'),
            # Totally NSFW (restricted on AniDB)
            'anidb/boku_no_piko.xml': (4544, 'Boku no Piko'),
            'anidb/bible_black.xml': (528, 'Bible Black'),
            # Should be marked NSFW
            'anidb/r15.xml': (8396, 'R-15'),
            'anidb/astarotte_no_omocha_ex.xml': (8560, 'Astarotte no Omocha! EX'),
            'anidb/aki_sora.xml': (6782, 'Aki Sora'),
            # Shouldn't be marked NSFW
            'anidb/punchline.xml': (10948, 'Punch Line'),
            'anidb/panty_stocking.xml': (7529, 'Panty & Stocking with Garterbelt'),
            'anidb/shimoneta.xml': (10888, 'Shimoneta to Iu Gainen ga Sonzai Shinai Taikutsu na Sekai')
        }

        are_nsfw = ['anidb/boku_no_piko.xml', 'anidb/bible_black.xml',
                    'anidb/r15.xml', 'anidb/astarotte_no_omocha_ex.xml',
                    'anidb/aki_sora.xml']
        are_sfw = ['anidb/sangatsu_no_lion.xml', 'anidb/hibike_euphonium.xml',
                   'anidb/punchline.xml', 'anidb/panty_stocking.xml',
                   'anidb/shimoneta.xml']

        with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps:
            for filename, infos in animes_sources.items():
                rsps.add(
                    responses.GET,
                    AniDB.BASE_URL,
                    body=self.read_fixture(filename),
                    status=200,
                    content_type='application/xml'
                )
                animes[filename] = self.anidb.get_or_update_work(infos[0])

        for filename in are_nsfw:
            with self.subTest('Asserting NSFW', anime=animes_sources[filename][1]):
                self.assertEqual(animes[filename].title, animes_sources[filename][1])
                self.assertTrue(animes[filename].nsfw)

        for filename in are_sfw:
            with self.subTest('Asserting SFW', anime=animes_sources[filename][1]):
                self.assertEqual(animes[filename].title, animes_sources[filename][1])
                self.assertFalse(animes[filename].nsfw)

    @responses.activate
    def test_anidb_related_animes(self):
        animes = {}
        related_animes = {}

        animes_sources = {
            'anidb/hibike_euphonium.xml': 10889,
            'anidb/hibike_euphonium2.xml': 11746,
            'anidb/hibike_euphonium_movie1.xml': 11747,
            'anidb/hibike_euphonium_movie2.xml': 12962,
            'anidb/hibike_euphonium_original_movies.xml': 13207,
            'anidb/sangatsu_no_lion.xml': 11606
        }

        with responses.RequestsMock(assert_all_requests_are_fired=True) as rsps:
            for filename, anidb_aid in animes_sources.items():
                for _ in range(2):
                    rsps.add(
                        responses.GET,
                        AniDB.BASE_URL,
                        body=self.read_fixture(filename),
                        status=200,
                        content_type='application/xml'
                    )

                animes[filename] = self.anidb.get_or_update_work(anidb_aid)
                related_animes[filename] = self.anidb.get_related_animes(anidb_aid=anidb_aid)

        # Ran once in get_or_update_work but ran again to check that it does not cause errors
        for filename in animes_sources:
            self.anidb._build_related_animes(animes[filename], related_animes[filename])

        relations = RelatedWork.objects.filter(
                        child_work__anidb_aid__in=animes_sources.values(),
                        parent_work__anidb_aid__in=animes_sources.values()
                    )

        # Checks that anime are created if missing but not all data is retrieved from AniDB
        self.assertEqual(Work.objects.get(title='Sangatsu no Lion meets Bump of Chicken').ext_synopsis, '')
        self.assertNotEqual(Work.objects.get(title='Sangatsu no Lion').ext_synopsis, '')

        # Checks on relations
        self.assertTrue(relations.filter(child_work__anidb_aid=11746, parent_work__anidb_aid=10889, type='sequel').exists())
        self.assertTrue(relations.filter(child_work__anidb_aid=10889, parent_work__anidb_aid=11746, type='prequel').exists())

        self.assertTrue(relations.filter(child_work__anidb_aid=11747, parent_work__anidb_aid=10889, type='summary').exists())
        self.assertTrue(relations.filter(child_work__anidb_aid=10889, parent_work__anidb_aid=11747, type='full_story').exists())

        self.assertTrue(relations.filter(child_work__anidb_aid=13207, parent_work__anidb_aid=11746, type='sequel').exists())
        self.assertTrue(relations.filter(child_work__anidb_aid=11746, parent_work__anidb_aid=13207, type='prequel').exists())

        self.assertTrue(relations.filter(child_work__anidb_aid=12962, parent_work__anidb_aid=11746, type='summary').exists())
        self.assertTrue(relations.filter(child_work__anidb_aid=11746, parent_work__anidb_aid=12962, type='full_story').exists())