Exemple #1
0
        static void Main(string[] args)
        {
            // MalApi uses the Common.Logging logging abstraction.
            // You can hook it up to any logging library that has a Common.Logging adapter.
            // See App.config for an example of hooking up MalApi to NLog.
            // Note that you will also need the appropriate NLog and Common.Logging.NLogXX packages installed.
            // Hooking up logging is not necessary but can be useful.
            // With the configuration in this example and with this example program, you will see lines like:

            // Logged from MalApi: Getting anime list for MAL user LordHighCaptain using URI https://myanimelist.net/malappinfo.php?status=all&type=anime&u=LordHighCaptain
            // Logged from MalApi: Successfully retrieved anime list for user LordHighCaptain

            using (MyAnimeListApi api = new MyAnimeListApi())
            {
                api.UserAgent   = "MalApiExample";
                api.TimeoutInMs = 15000;

                var animeUpdateInfo = new AnimeUpdate()
                {
                    Episode = 26,
                    Status  = AnimeCompletionStatus.Completed,
                    Score   = 9,
                };
                string userUpdateAnime = api.UpdateAnimeForUser(1, animeUpdateInfo, "user", "password");

                var mangaUpdateInfo = new MangaUpdate()
                {
                    Chapter = 20,
                    Volume  = 3,
                    Score   = 8,
                    Status  = MangaCompletionStatus.Completed
                };
                string userUpdateManga = api.UpdateMangaForUser(952, mangaUpdateInfo, "user", "password");



                MalUserLookupResults userLookup = api.GetAnimeListForUser("user");
                foreach (MyAnimeListEntry listEntry in userLookup.AnimeList)
                {
                    Console.WriteLine("Rating for {0}: {1}", listEntry.AnimeInfo.Title, listEntry.Score);
                }

                Console.WriteLine();
                Console.WriteLine();

                RecentUsersResults recentUsersResults = api.GetRecentOnlineUsers();
                foreach (string user in recentUsersResults.RecentUsers)
                {
                    Console.WriteLine("Recent user: {0}", user);
                }

                Console.WriteLine();
                Console.WriteLine();

                int eurekaSevenID = 237;
                AnimeDetailsResults eurekaSeven = api.GetAnimeDetails(eurekaSevenID);
                Console.WriteLine("Eureka Seven genres: {0}", string.Join(", ", eurekaSeven.Genres));
            }
        }
Exemple #2
0
        /// <summary>
        /// Push user details to MAL.
        /// This method automatically figures out if the anime should be added to the user's list or if it should simply be updated
        /// </summary>
        /// <param name="details">Update details</param>
        /// <param name="username">Username for authentication</param>
        /// <param name="password">Password for authentication</param>
        /// <returns>True - Update succeeded, otherwise false</returns>
        public async Task <DataPushResponseWrapper> PushAnimeDetailsToMal(AnimeUpdate details, string username, string password)
        {
            var userlist = await _listRetrievalWorker.RetrieveUserListAsync(username);

            var item = userlist.Anime.FirstOrDefault(t => t.SeriesId == details.AnimeId);

            return(item == null
                ? await UpdateAnimeDetails(details, username, password)
                : await UpdateAnimeDetails(details, username, password, true));
        }
        public async Task <AnimeUpdate> GetUserAnimeDetailsAsync(string username, int animeId, CancellationToken cancellationToken)
        {
            string             url     = string.Format(UserAnimeDetailsUri, animeId);
            HttpRequestMessage request = InitNewRequest(url, HttpMethod.Get);

            AnimeUpdate results = await ProcessRequestAsync(request, ScrapeUserAnimeDetailsFromHtml,
                                                            cancellationToken : cancellationToken,
                                                            baseErrorMessage : string.Format("Failed getting user anime details for user {0} anime ID {1}.", username, animeId))
                                  .ConfigureAwait(continueOnCapturedContext: false);

            return(results);
        }
Exemple #4
0
        public void TestScrapeUserAnimeDetailsFromHtml()
        {
            string html;

            using (StreamReader reader = Helpers.GetResourceStream("Cowboy_Bebop.htm"))
            {
                html = reader.ReadToEnd();
            }

            AnimeUpdate info = new AnimeUpdate()
            {
                Episode          = 26,
                Status           = AnimeCompletionStatus.Completed,
                Score            = 8,
                StorageType      = 5, // VHS
                StorageValue     = 123,
                TimesRewatched   = 2,
                RewatchValue     = 4, // high
                DateStart        = new DateTime(2017, 12, 10),
                DateFinish       = new DateTime(2017, 12, 15),
                Priority         = 1, // medium
                EnableDiscussion = 1,
                EnableRewatching = 1,
                Comments         = "test updated comment, test updated comment2",
                Tags             = "test updated tag, test updated tag 2"
            };

            using (MyAnimeListApi api = new MyAnimeListApi())
            {
                AnimeUpdate results = MalDetailScrapingUtils.ScrapeUserAnimeDetailsFromHtml(html);

                Assert.Equal(info.Episode, results.Episode);
                Assert.Equal(info.Status, results.Status);
                Assert.Equal(info.Score, results.Score);
                Assert.Equal(info.StorageType, results.StorageType);
                Assert.Equal(info.StorageValue, results.StorageValue);
                Assert.Equal(info.TimesRewatched, results.TimesRewatched);
                Assert.Equal(info.RewatchValue, results.RewatchValue);
                Assert.Equal(info.DateStart, results.DateStart);
                Assert.Equal(info.DateFinish, results.DateFinish);
                Assert.Equal(info.Priority, results.Priority);
                Assert.Equal(info.EnableDiscussion, results.EnableDiscussion);
                Assert.Equal(info.EnableRewatching, results.EnableRewatching);
                Assert.Equal(info.Comments, results.Comments);
                Assert.Equal(info.Tags, results.Tags);
            }
        }
        public async Task <IEnumerable <AnimeUpdate> > GetAnimeUpdatesFromPage(int pageNumber)
        {
            if (pageNumber <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(pageNumber), pageNumber, "Page number cannot be less or equal to 0");
            }

            var animeUpdates = new List <AnimeUpdate>();
            var updateNodes  = (await GetLastUpdateNodes(pageNumber));

            foreach (var node in updateNodes)
            {
                var nodeInnerText = node.QuerySelector(".update-info").InnerText;
                var episodeNums   = Regex.Split(nodeInnerText, @"\D+").Where(num => !string.IsNullOrEmpty(num)).ToList();
                if (episodeNums.Count == 0)
                {
                    continue;
                }

                var animePageSrc = $"https://yummyanime.com{node.Attributes.FirstOrDefault(a => a.Name == "href").Value}";
                var anime        = new Anime {
                    Name = node.QuerySelector(".update-title").InnerText, PageSrc = animePageSrc
                };
                var publisher = new Publisher {
                    Name = Regex.Replace(nodeInnerText, @"[^a-zA-Z]", "")
                };
                var     updateDate = node.QuerySelector(".update-date").InnerText;
                DubType dubType    = nodeInnerText.Contains("озвучкой") ? DubType.Voiceover : DubType.Subtitiles;
                var     num1       = int.Parse(episodeNums[0]);
                var     num2       = int.Parse(episodeNums.ElementAtOrDefault(1) ?? episodeNums[0]);
                for (int i = num1; i <= num2; i++)
                {
                    var animeUpdate = new AnimeUpdate
                    {
                        Anime      = anime,
                        Publisher  = publisher,
                        EpisodeNum = i,
                        UpdateDate = updateDate,
                        DubType    = dubType
                    };
                    animeUpdates.Add(animeUpdate);
                }
            }

            return(animeUpdates);
        }
Exemple #6
0
        /// <summary>
        /// Push update/add details to MAL
        /// </summary>
        /// <param name="details">Update details</param>
        /// <param name="username">Username for authentication</param>
        /// <param name="password">Password for authentication</param>
        /// <param name="isupdate">Indicate if this is an update or an add</param>
        /// <returns>True - Update succeeded, otherwise false</returns>
        private async Task <DataPushResponseWrapper> UpdateAnimeDetails(AnimeUpdate details, string username, string password,
                                                                        bool isupdate = false)
        {
            try
            {
                var url = isupdate
                    ? MalRouteBuilder.UpdateAnime(details.AnimeId)
                    : MalRouteBuilder.AddAnime(details.AnimeId);
                var client = _httpClientFactory.GetHttpClient(username, password);
                var result = await client.PostAsync(url, new FormUrlEncodedContent(new[]
                {
                    new KeyValuePair <string, string>("data", _xmlHelper.SerializeData(details))
                }));

                return(new DataPushResponseWrapper(result.StatusCode, result.IsSuccessStatusCode));
            }
            catch (Exception exception)
            {
                return(new DataPushResponseWrapper(exception));
            }
        }
        public static AnimeUpdate ScrapeUserAnimeDetailsFromHtml(string userAnimeDetailsHtml)
        {
            AnimeUpdate results = new AnimeUpdate();

            var doc = new HtmlDocument();

            doc.LoadHtml(userAnimeDetailsHtml);

            // Episode
            results.Episode = doc.GetElementbyId("add_anime_num_watched_episodes").GetAttributeValue("value", -1);

            // Status
            var parentNode = doc.GetElementbyId("add_anime_status");

            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    results.Status = (AnimeCompletionStatus)childNode.GetAttributeValue("value", -1);
                    break;
                }
            }

            // Enable rewatching
            results.EnableRewatching = doc.GetElementbyId("add_anime_is_rewatching").Attributes["checked"] == null ? 0 : 1;

            // Score
            parentNode = doc.GetElementbyId("add_anime_score");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    results.Score = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }

            // Start date
            int day   = -1;
            int month = -1;
            int year  = -1;

            parentNode = doc.GetElementbyId("add_anime_start_date_month");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    month = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }
            parentNode = doc.GetElementbyId("add_anime_start_date_day");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    day = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }
            parentNode = doc.GetElementbyId("add_anime_start_date_year");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    year = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }
            if (month == -1 || day == -1 || year == -1)
            {
                results.DateStart = null;
            }
            else
            {
                results.DateStart = new DateTime(year, month, day);
            }

            // Date finish
            parentNode = doc.GetElementbyId("add_anime_finish_date_month");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    month = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }
            parentNode = doc.GetElementbyId("add_anime_finish_date_day");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    day = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }
            parentNode = doc.GetElementbyId("add_anime_finish_date_year");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    year = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }
            if (month == -1 || day == -1 || year == -1)
            {
                results.DateFinish = null;
            }
            else
            {
                results.DateFinish = new DateTime(year, month, day);
            }

            // Tags
            results.Tags = doc.GetElementbyId("add_anime_tags").InnerText;

            // Priority
            parentNode = doc.GetElementbyId("add_anime_priority");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    results.Priority = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }

            // Storage type
            parentNode = doc.GetElementbyId("add_anime_storage_type");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    results.StorageType = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }

            // Storage value
            results.StorageValue = doc.GetElementbyId("add_anime_storage_value").GetAttributeValue("value", -1);

            // Times rewatched
            results.TimesRewatched = doc.GetElementbyId("add_anime_num_watched_times").GetAttributeValue("value", -1);

            // Rewatch value
            parentNode = doc.GetElementbyId("add_anime_rewatch_value");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    results.RewatchValue = childNode.GetAttributeValue("value", -1);
                    break;
                }
            }

            // Comments
            results.Comments = doc.GetElementbyId("add_anime_comments").InnerText;

            // Enable discussion
            parentNode = doc.GetElementbyId("add_anime_is_asked_to_discuss");
            foreach (var childNode in parentNode.ChildNodes)
            {
                if (childNode.Attributes["selected"] != null)
                {
                    // Because 'Enable discussion = 1' sent for update sets the first options of the dropdown, which corresponds to 0 and vice versa...
                    int temp = childNode.GetAttributeValue("value", -1);
                    temp = temp == 1 ? 0 : 1;
                    results.EnableDiscussion = temp;
                    break;
                }
            }

            return(results);
        }