static void Main(string[] args) { // No logging support for MalApi in .NET Core yet. // At this time there is no Common.Logging adapter for NLog that supports .NET core. using (MyAnimeListApi api = new MyAnimeListApi()) { api.UserAgent = "MalApiExample"; api.TimeoutInMs = 15000; MalUserLookupResults userLookup = api.GetAnimeListForUser("LordHighCaptain"); 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)); } }
public void IncorrectUsernameMangaChapterUpdateTest() { string username = System.Environment.GetEnvironmentVariable("MAL_USERNAME"); username += "test"; string password = System.Environment.GetEnvironmentVariable("MAL_PASSWORD"); // Monster int mangaId = 1; MangaUpdate partialBaseInfo = new MangaUpdate() { Chapter = 1 }; using (MyAnimeListApi api = new MyAnimeListApi()) { using (GetUserMangaDetailsTest helper = new GetUserMangaDetailsTest()) { Assert.Throws <MalApiRequestException>(() => helper.Login(username, password)); Assert.Throws <MalApiRequestException>(() => api.UpdateMangaForUser(mangaId, partialBaseInfo, username, password)); } } }
public void GetAnimeListForNonexistentUserThrowsCorrectExceptionAsync() { using (MyAnimeListApi api = new MyAnimeListApi()) { Assert.ThrowsAsync <MalUserNotFoundException>(() => api.GetAnimeListForUserAsync("oijsfjisfdjfsdojpfsdp")); } }
public void UpdateMangaForUserCanceled() { string username = System.Environment.GetEnvironmentVariable("MAL_USERNAME"); string password = System.Environment.GetEnvironmentVariable("MAL_PASSWORD"); // Monster int mangaId = 1; MangaUpdate updateInfo = new MangaUpdate() { Chapter = 162, Volume = 18, Status = MangaCompletionStatus.Completed, Score = 10, TimesReread = 2, RereadValue = 4, // high DateStart = new DateTime(2017, 12, 10), DateFinish = new DateTime(2017, 12, 15), Priority = 1, // medium EnableDiscussion = 1, EnableRereading = 1, Comments = "test updated comment, test updated comment2", // ScanGroup = "scan_group_updated", Tags = "test updated tag, test updated tag 2" }; using (MyAnimeListApi api = new MyAnimeListApi()) { CancellationTokenSource tokenSource = new CancellationTokenSource(); Task <string> userLookupTask = api.UpdateMangaForUserAsync(mangaId, updateInfo, username, password, tokenSource.Token); tokenSource.Cancel(); Assert.Throws <TaskCanceledException>(() => userLookupTask.GetAwaiter().GetResult()); } }
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)); } }
public void GetAnimeDetailsForInvalidAnimeId() { int animeId = 99999; using (MyAnimeListApi api = new MyAnimeListApi()) { Assert.Throws<MalAnimeNotFoundException>(() => api.GetAnimeDetails(animeId)); } }
public void GetRecentOnlineUsers() { using (MyAnimeListApi api = new MyAnimeListApi()) { RecentUsersResults results = api.GetRecentOnlineUsers(); Assert.That(results.RecentUsers.Count, Is.GreaterThan(0)); } }
public void GetRecentOnlineUsers() { using (MyAnimeListApi api = new MyAnimeListApi()) { RecentUsersResults results = api.GetRecentOnlineUsers(); Assert.NotEmpty(results.RecentUsers); } }
public void GetAnimeDetailsForInvalidAnimeId() { int animeId = 99999; using (MyAnimeListApi api = new MyAnimeListApi()) { Assert.Throws <MalAnimeNotFoundException>(() => api.GetAnimeDetails(animeId)); } }
public void UpdateMangaTagsForUserTest() { string username = System.Environment.GetEnvironmentVariable("MAL_USERNAME"); string password = System.Environment.GetEnvironmentVariable("MAL_PASSWORD"); // Monster int mangaId = 1; MangaUpdate partialBaseInfo = new MangaUpdate() { Tags = "test base tag, test base tag 2" }; MangaUpdate partialUpdateInfo = new MangaUpdate() { Tags = "test updated tag, test updated tag 2" }; using (MyAnimeListApi api = new MyAnimeListApi()) { using (GetUserMangaDetailsTest helper = new GetUserMangaDetailsTest()) { helper.Login(username, password); string result = api.UpdateMangaForUser(mangaId, partialBaseInfo, username, password); Assert.Equal("Updated", result); MangaUpdate baseReults = helper.GetUserMangaDetailsAsync(username, mangaId); // Assert first update against base info Assert.Equal(partialBaseInfo.Tags, baseReults.Tags); result = api.UpdateMangaForUser(mangaId, partialUpdateInfo, username, password); Assert.Equal("Updated", result); MangaUpdate updatedResults = helper.GetUserMangaDetailsAsync(username, mangaId); // Assert second update with update info Assert.Equal(partialUpdateInfo.Tags, updatedResults.Tags); // Assert that only the tags has been changed Assert.Equal(baseReults.Chapter, updatedResults.Chapter); Assert.Equal(baseReults.Volume, updatedResults.Volume); Assert.Equal(baseReults.Status, updatedResults.Status); Assert.Equal(baseReults.Score, updatedResults.Score); Assert.Equal(baseReults.TimesReread, updatedResults.TimesReread); Assert.Equal(baseReults.RereadValue, updatedResults.RereadValue); Assert.Equal(baseReults.DateStart, updatedResults.DateStart); Assert.Equal(baseReults.DateFinish, updatedResults.DateFinish); Assert.Equal(baseReults.Priority, updatedResults.Priority); Assert.Equal(baseReults.EnableDiscussion, updatedResults.EnableDiscussion); Assert.Equal(baseReults.EnableRereading, updatedResults.EnableRereading); Assert.Equal(baseReults.Comments, updatedResults.Comments); Assert.NotEqual(baseReults.Tags, updatedResults.Tags); } } }
public void GetRecentOnlineUsersCanceled() { using (MyAnimeListApi api = new MyAnimeListApi()) { CancellationTokenSource tokenSource = new CancellationTokenSource(); Task <RecentUsersResults> task = api.GetRecentOnlineUsersAsync(tokenSource.Token); tokenSource.Cancel(); Assert.Throws <TaskCanceledException>(() => task.GetAwaiter().GetResult()); } }
public void GetAnimeListForUser() { string username = "******"; using (MyAnimeListApi api = new MyAnimeListApi()) { MalUserLookupResults userLookup = api.GetAnimeListForUser(username); // Just a smoke test that checks that getting an anime list returns something Assert.That(userLookup.AnimeList, Is.Not.Empty); } }
public void GetMangaListForUser() { string username = "******"; using (MyAnimeListApi api = new MyAnimeListApi()) { MalUserLookupResults userLookup = api.GetMangaListForUser(username); Assert.NotEmpty(userLookup.MangaList); } }
public void GetAnimeListForUserCanceled() { string username = "******"; using (MyAnimeListApi api = new MyAnimeListApi()) { CancellationTokenSource tokenSource = new CancellationTokenSource(); Task <MalUserLookupResults> userLookupTask = api.GetAnimeListForUserAsync(username, tokenSource.Token); tokenSource.Cancel(); Assert.Throws <TaskCanceledException>(() => userLookupTask.GetAwaiter().GetResult()); } }
public void GetAnimeListForUser() { string username = "******"; using (MyAnimeListApi api = new MyAnimeListApi()) { MalUserLookupResults userLookup = api.GetAnimeListForUser(username); // Just a smoke test that checks that getting an anime list returns something Assert.NotEmpty(userLookup.AnimeList); } }
public void GetAnimeDetailsCanceled() { int animeId = 237; // Eureka Seven using (MyAnimeListApi api = new MyAnimeListApi()) { CancellationTokenSource tokenSource = new CancellationTokenSource(); Task <AnimeDetailsResults> task = api.GetAnimeDetailsAsync(animeId, tokenSource.Token); tokenSource.Cancel(); Assert.Throws <TaskCanceledException>(() => task.GetAwaiter().GetResult()); } }
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 void TestScrapeUserMangaDetailsFromHtml() { string html; using (StreamReader reader = Helpers.GetResourceStream("Monster.htm")) { html = reader.ReadToEnd(); } MangaUpdate info = new MangaUpdate() { Chapter = 162, Volume = 18, Status = MangaCompletionStatus.Completed, Score = 10, TimesReread = 2, RereadValue = 4, // high DateStart = new DateTime(2017, 12, 10), DateFinish = new DateTime(2017, 12, 15), Priority = 1, // medium EnableDiscussion = 1, EnableRereading = 1, Comments = "test updated comment, test updated comment2", // ScanGroup = "scan_group_updated", Tags = "test updated tag, test updated tag 2" }; using (MyAnimeListApi api = new MyAnimeListApi()) { MangaUpdate results = MalDetailScrapingUtils.ScrapeUserMangaDetailsFromHtml(html); Assert.Equal(info.Chapter, results.Chapter); Assert.Equal(info.Volume, results.Volume); Assert.Equal(info.Status, results.Status); Assert.Equal(info.Score, results.Score); Assert.Equal(info.TimesReread, results.TimesReread); Assert.Equal(info.RereadValue, results.RereadValue); 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.EnableRereading, results.EnableRereading); Assert.Equal(info.Comments, results.Comments); Assert.Equal(info.Tags, results.Tags); } }
public void GetAnimeDetails() { int animeId = 237; // Eureka Seven using (MyAnimeListApi api = new MyAnimeListApi()) { AnimeDetailsResults results = api.GetAnimeDetails(animeId); List<Genre> expectedGenres = new List<Genre>() { new Genre(2, "Adventure"), new Genre(8, "Drama"), new Genre(18, "Mecha"), new Genre(22, "Romance"), new Genre(24, "Sci-Fi"), new Genre(27, "Shounen") }; Assert.That(results.Genres, Is.EquivalentTo(expectedGenres)); } }
public void GetAnimeDetails() { int animeId = 237; // Eureka Seven using (MyAnimeListApi api = new MyAnimeListApi()) { AnimeDetailsResults results = api.GetAnimeDetails(animeId); List <Genre> expectedGenres = new List <Genre>() { new Genre(2, "Adventure"), new Genre(8, "Drama"), new Genre(18, "Mecha"), new Genre(22, "Romance"), new Genre(24, "Sci-Fi"), }; results.Genres.Should().BeEquivalentTo(expectedGenres); } }
static void Main(string[] args) { using (MyAnimeListApi api = new MyAnimeListApi()) { api.TimeoutInMs = 15000; MalUserLookupResults userLookup = api.GetAnimeListForUser("LordHighCaptain"); 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); } } }
public void TestScrapeAnimeDetailsFromHtml() { string thisAssemblyPath = Assembly.GetExecutingAssembly().CodeBase.Replace("file:///", ""); Console.WriteLine(thisAssemblyPath); string htmlFilePath = Path.Combine(Path.GetDirectoryName(thisAssemblyPath), "Eureka_Seven.htm"); string html = File.ReadAllText(htmlFilePath); using (MyAnimeListApi api = new MyAnimeListApi()) { AnimeDetailsResults results = api.ScrapeAnimeDetailsFromHtml(html, 237); List<Genre> expectedGenres = new List<Genre>() { new Genre(2, "Adventure"), new Genre(8, "Drama"), new Genre(18, "Mecha"), new Genre(22, "Romance"), new Genre(24, "Sci-Fi"), new Genre(27, "Shounen") }; Assert.That(results.Genres, Is.EquivalentTo(expectedGenres)); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddMvc() // Use property names as is on classes that get serialized, instead of camelcasing. .AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()); services.AddOptions(); services.Configure <Config.HtmlConfig>(Configuration.GetSection("Html")); services.Configure <Config.MalApiConfig>(Configuration.GetSection("MalApi")); services.Configure <Config.RecommendationsConfig>(Configuration.GetSection("Recommendations")); services.Configure <Config.ConnectionStringsConfig>(Configuration.GetSection("ConnectionStrings")); services.AddTransient <IAnimeRecsClientFactory, ConfigBasedRecClientFactory>(); services.AddTransient <IAnimeRecsDbConnectionFactory, ConfigBasedAnimeRecsDbConnectionFactory>(); IMyAnimeListApi api; Config.MalApiConfig apiConfig = Configuration.GetSection("MalApi").Get <Config.MalApiConfig>(); if (apiConfig.Type == Config.MalApiType.Normal) { api = new MyAnimeListApi() { UserAgent = apiConfig.UserAgentString, TimeoutInMs = apiConfig.TimeoutMilliseconds, }; } else if (apiConfig.Type == Config.MalApiType.DB) { api = new PgMyAnimeListApi(Configuration.GetConnectionString("AnimeRecs")); } else { throw new Exception($"Don't know how to construct MAL API type {apiConfig.Type}."); } CachingMyAnimeListApi cachingApi = new CachingMyAnimeListApi(api, TimeSpan.FromSeconds(apiConfig.AnimeListCacheExpirationSeconds), ownApi: true); SingletonMyAnimeListApiFactory factory = new SingletonMyAnimeListApiFactory(cachingApi); services.AddSingleton <IMyAnimeListApiFactory>(factory); }
public void TestScrapeAnimeDetailsFromHtml() { string html; using (StreamReader reader = Helpers.GetResourceStream("Eureka_Seven.htm")) { html = reader.ReadToEnd(); } using (MyAnimeListApi api = new MyAnimeListApi()) { AnimeDetailsResults results = api.ScrapeAnimeDetailsFromHtml(html, 237); List <Genre> expectedGenres = new List <Genre>() { new Genre(2, "Adventure"), new Genre(8, "Drama"), new Genre(18, "Mecha"), new Genre(22, "Romance"), new Genre(24, "Sci-Fi"), }; results.Genres.Should().BeEquivalentTo(expectedGenres); } }
static void Main(string[] args) { Logging.SetUpLogging(); try { config = new Config(); using (IMyAnimeListApi basicApi = new MyAnimeListApi() { TimeoutInMs = config.MalTimeoutInMs, UserAgent = config.MalApiUserAgentString }) using (IMyAnimeListApi rateLimitingApi = new RateLimitingMyAnimeListApi(basicApi, TimeSpan.FromMilliseconds(config.DelayBetweenRequestsInMs))) using (IMyAnimeListApi malApi = new RetryOnFailureMyAnimeListApi(rateLimitingApi, config.NumMalRequestFailuresBeforeGivingUp, config.DelayAfterMalRequestFailureInMs)) using (NpgsqlConnection conn = new NpgsqlConnection(config.PostgresConnectionString)) { conn.Open(); int usersAddedSoFar = 0; while (usersAddedSoFar < config.UsersPerRun) { RecentUsersResults recentMalUsers = malApi.GetRecentOnlineUsers(); foreach (string user in recentMalUsers.RecentUsers) { using (var transaction = conn.BeginTransaction(System.Data.IsolationLevel.RepeatableRead)) { if (!UserIsInDatabase(user, conn, transaction)) { MalUserLookupResults userLookup = malApi.GetAnimeListForUser(user); if (UserMeetsCriteria(userLookup, conn, transaction)) { InsertUserAndRatingsInDatabase(userLookup, conn, transaction); usersAddedSoFar++; Logging.Log.Debug("Committing transaction."); transaction.Commit(); Logging.Log.Debug("Transaction committed."); if (usersAddedSoFar == config.UsersPerRun) { break; } } else { Logging.Log.InfoFormat("{0} does not meet criteria for inclusion, skipping", user); } } else { Logging.Log.InfoFormat("{0} is already in the database, skipping.", user); } } } } using (var transaction = conn.BeginTransaction(System.Data.IsolationLevel.RepeatableRead)) { TrimDatabaseToMaxUsers(config.MaxUsersInDatabase, conn, transaction); transaction.Commit(); } } } catch (Exception ex) { Logging.Log.FatalFormat("Fatal error: {0}", ex, ex.Message); Environment.ExitCode = 1; } }
public void UpdateMangaForUserTest() { string username = System.Environment.GetEnvironmentVariable("MAL_USERNAME"); string password = System.Environment.GetEnvironmentVariable("MAL_PASSWORD"); // Monster int mangaId = 1; MangaUpdate baseInfo = new MangaUpdate() { Chapter = 1, Volume = 2, Status = MangaCompletionStatus.Reading, Score = 3, TimesReread = 1, RereadValue = 2, // low DateStart = new DateTime(2017, 10, 1), DateFinish = new DateTime(2017, 10, 5), Priority = 0, // low EnableDiscussion = 0, EnableRereading = 0, Comments = "base comment,base comment 2", // ScanGroup = "scan_group", Tags = "test base tag, test base tag 2" }; MangaUpdate updateInfo = new MangaUpdate() { Chapter = 162, Volume = 18, Status = MangaCompletionStatus.Completed, Score = 10, TimesReread = 2, RereadValue = 4, // high DateStart = new DateTime(2017, 12, 10), DateFinish = new DateTime(2017, 12, 15), Priority = 1, // medium EnableDiscussion = 1, EnableRereading = 1, Comments = "test updated comment, test updated comment2", // ScanGroup = "scan_group_updated", Tags = "test updated tag, test updated tag 2" }; using (MyAnimeListApi api = new MyAnimeListApi()) { using (GetUserMangaDetailsTest helper = new GetUserMangaDetailsTest()) { helper.Login(username, password); string result = api.UpdateMangaForUser(mangaId, baseInfo, username, password); Assert.Equal("Updated", result); MangaUpdate baseReults = helper.GetUserMangaDetailsAsync(username, mangaId); // Assert first update against base info Assert.Equal(baseInfo.Chapter, baseReults.Chapter); Assert.Equal(baseInfo.Volume, baseReults.Volume); Assert.Equal(baseInfo.Status, baseReults.Status); Assert.Equal(baseInfo.Score, baseReults.Score); Assert.Equal(baseInfo.TimesReread, baseReults.TimesReread); Assert.Equal(baseInfo.RereadValue, baseReults.RereadValue); Assert.Equal(baseInfo.DateStart, baseReults.DateStart); Assert.Equal(baseInfo.DateFinish, baseReults.DateFinish); Assert.Equal(baseInfo.Priority, baseReults.Priority); Assert.Equal(baseInfo.EnableDiscussion, baseReults.EnableDiscussion); Assert.Equal(baseInfo.EnableRereading, baseReults.EnableRereading); Assert.Equal(baseInfo.Comments, baseReults.Comments); Assert.Equal(baseInfo.Tags, baseReults.Tags); result = api.UpdateMangaForUser(mangaId, updateInfo, username, password); Assert.Equal("Updated", result); MangaUpdate updatedResults = helper.GetUserMangaDetailsAsync(username, mangaId); // Assert second update with update info Assert.Equal(updateInfo.Chapter, updatedResults.Chapter); Assert.Equal(updateInfo.Volume, updatedResults.Volume); Assert.Equal(updateInfo.Status, updatedResults.Status); Assert.Equal(updateInfo.Score, updatedResults.Score); Assert.Equal(updateInfo.TimesReread, updatedResults.TimesReread); Assert.Equal(updateInfo.RereadValue, updatedResults.RereadValue); Assert.Equal(updateInfo.DateStart, updatedResults.DateStart); Assert.Equal(updateInfo.DateFinish, updatedResults.DateFinish); Assert.Equal(updateInfo.Priority, updatedResults.Priority); Assert.Equal(updateInfo.EnableDiscussion, updatedResults.EnableDiscussion); Assert.Equal(updateInfo.EnableRereading, updatedResults.EnableRereading); Assert.Equal(updateInfo.Comments, updatedResults.Comments); Assert.Equal(updateInfo.Tags, updatedResults.Tags); // Assert all values have been changed Assert.NotEqual(baseReults.Chapter, updatedResults.Chapter); Assert.NotEqual(baseReults.Volume, updatedResults.Volume); Assert.NotEqual(baseReults.Status, updatedResults.Status); Assert.NotEqual(baseReults.Score, updatedResults.Score); Assert.NotEqual(baseReults.TimesReread, updatedResults.TimesReread); Assert.NotEqual(baseReults.RereadValue, updatedResults.RereadValue); Assert.NotEqual(baseReults.DateStart, updatedResults.DateStart); Assert.NotEqual(baseReults.DateFinish, updatedResults.DateFinish); Assert.NotEqual(baseReults.Priority, updatedResults.Priority); Assert.NotEqual(baseReults.EnableDiscussion, updatedResults.EnableDiscussion); Assert.NotEqual(baseReults.EnableRereading, updatedResults.EnableRereading); Assert.NotEqual(baseReults.Comments, updatedResults.Comments); Assert.NotEqual(baseReults.Tags, updatedResults.Tags); } } }
// Called once protected override void ConfigureApplicationContainer(TinyIoCContainer container) { List<IDisposable> disposablesInitialized = new List<IDisposable>(); try { // This seems to be called before ApplicationStartup, so read config if it hasn't been read yet LoadConfigIfNotLoaded(); container.Register<IConfig>(AppGlobals.Config); IAnimeRecsClientFactory recServiceClientFactory = new RecClientFactory(AppGlobals.Config.RecServicePort, AppGlobals.Config.SpecialRecSourcePorts); container.Register<IAnimeRecsClientFactory>(recServiceClientFactory); IAnimeRecsDbConnectionFactory dbConnectionFactory = new AnimeRecsDbConnectionFactory(AppGlobals.Config.PostgresConnectionString); container.Register<IAnimeRecsDbConnectionFactory>(dbConnectionFactory); IMyAnimeListApi api; if (AppGlobals.Config.UseLocalDbMalApi) { api = new PgMyAnimeListApi(AppGlobals.Config.PostgresConnectionString); } else { api = new MyAnimeListApi() { UserAgent = AppGlobals.Config.MalApiUserAgentString, TimeoutInMs = AppGlobals.Config.MalTimeoutInMs }; } disposablesInitialized.Add(api); CachingMyAnimeListApi cachingApi = new CachingMyAnimeListApi(api, AppGlobals.Config.AnimeListCacheExpiration, ownApi: true); disposablesInitialized.Add(cachingApi); SingletonMyAnimeListApiFactory factory = new SingletonMyAnimeListApiFactory(cachingApi); // TinyIoC will dispose of the factory when the Nancy host stops container.Register<IMyAnimeListApiFactory>(factory); } catch { foreach (IDisposable disposable in disposablesInitialized) { disposable.Dispose(); } throw; } }
static int Main(string[] args) { CommandLineArgs commandLine; try { commandLine = new CommandLineArgs(args); if (commandLine.ShowHelp) { commandLine.DisplayHelp(Console.Out); return((int)ExitCode.Success); } IConfigurationBuilder configBuilder = new ConfigurationBuilder() .AddXmlFile(commandLine.ConfigFile); IConfigurationRoot rawConfig = configBuilder.Build(); config = rawConfig.Get <Config>(); if (config.LoggingConfigPath != null) { Logging.SetUpLogging(config.LoggingConfigPath); } else { Console.Error.WriteLine("No logging configuration file set. Logging to console."); Logging.SetUpConsoleLogging(); } } catch (Exception ex) { Console.Error.WriteLine("Fatal error: {0}", ex, ex.Message); return((int)ExitCode.Failure); } try { Logging.Log.Debug($"Command line args parsed. ConfigFile={commandLine.ConfigFile}"); using (IMyAnimeListApi basicApi = new MyAnimeListApi() { TimeoutInMs = config.MalTimeoutInMs, UserAgent = config.MalApiUserAgentString }) using (IMyAnimeListApi rateLimitingApi = new RateLimitingMyAnimeListApi(basicApi, TimeSpan.FromMilliseconds(config.DelayBetweenRequestsInMs))) using (IMyAnimeListApi malApi = new RetryOnFailureMyAnimeListApi(rateLimitingApi, config.NumMalRequestFailuresBeforeGivingUp, config.DelayAfterMalRequestFailureInMs)) using (NpgsqlConnection conn = new NpgsqlConnection(config.ConnectionStrings.AnimeRecs)) { conn.Open(); int usersAddedSoFar = 0; while (usersAddedSoFar < config.UsersPerRun) { RecentUsersResults recentMalUsers = malApi.GetRecentOnlineUsers(); foreach (string user in recentMalUsers.RecentUsers) { using (var transaction = conn.BeginTransaction(System.Data.IsolationLevel.RepeatableRead)) { if (!UserIsInDatabase(user, conn, transaction)) { MalUserLookupResults userLookup = malApi.GetAnimeListForUser(user); if (UserMeetsCriteria(userLookup, conn, transaction)) { InsertUserAndRatingsInDatabase(userLookup, conn, transaction); usersAddedSoFar++; Logging.Log.Debug("Committing transaction."); transaction.Commit(); Logging.Log.Debug("Transaction committed."); if (usersAddedSoFar == config.UsersPerRun) { break; } } else { Logging.Log.InfoFormat("{0} does not meet criteria for inclusion, skipping", user); } } else { Logging.Log.InfoFormat("{0} is already in the database, skipping.", user); } } } } using (var transaction = conn.BeginTransaction(System.Data.IsolationLevel.RepeatableRead)) { TrimDatabaseToMaxUsers(config.MaxUsersInDatabase, conn, transaction); transaction.Commit(); } } } catch (Exception ex) { Logging.Log.FatalFormat("Fatal error: {0}", ex, ex.Message); return((int)ExitCode.Failure); } return((int)ExitCode.Success); }