/// <summary> /// Sets the current track for the parent book to this track /// Generates BookProgress if required /// </summary> public static void SetCurrentTrack(string userId, Guid trackId) { using (var db = new HonyomiContext()) { IndexedBook book = db.Files.Include(x => x.Book).SingleOrDefault(x => x.IndexedFileId == trackId)?.Book; if (book == null) { //can't update progress on a book the doesn't exist return; } BookProgress prog = db.BookProgresses.SingleOrDefault(x => x.BookId == book.IndexedBookId && x.UserId == userId); if (prog == null) { db.BookProgresses.Add(new BookProgress() { BookId = book.IndexedBookId, FileId = trackId, UserId = userId }); } else { prog.FileId = trackId; } db.SaveChanges(); } }
public static BookWithProgress[] GetUserBooks(string userId) { using (var db = new HonyomiContext()) { return(db.Books.Select(x => GetUserBookProgress(userId, x.IndexedBookId)).ToArray()); } }
public static HonyomiConfig GetConfig() { using (var db = new HonyomiContext()) { return(db.Configs.First()); } }
public static BookWithProgress GetUserBookProgress(string userId, Guid bookId) { using (var db = new HonyomiContext()) { IndexedBook book = db.Books.Include(x => x.Files).Single(x => x.IndexedBookId == bookId); if (book == null) { return(null); } BookProgress bookp = db.BookProgresses.SingleOrDefault(x => x.BookId == bookId && x.UserId == userId); BookWithProgress result = new BookWithProgress { FileProgresses = book.Files.Select(x => GetUserFileProgress(userId, x.IndexedFileId)) .ToArray(), Guid = book.IndexedBookId, CurrentTrackGuid = bookp?.FileId ?? book.Files.First().IndexedFileId, Title = book.Title, Author = book.Author, ISBN = book.ISBN }; return(result); } }
public IActionResult RemoveWatchDirectory([FromBody] string[] paths) { try { using (var db = new HonyomiContext()) { foreach (string path in paths) { var wdRecord = db.WatchDirectories.FirstOrDefault(x => x.Path == path); if (wdRecord == null) { continue; } db.WatchDirectories.Remove(wdRecord); } db.SaveChanges(); return(Json(DataAccess.GetConfigClient())); } } catch (Exception) { return(BadRequest()); } }
public IActionResult SetConfig([FromBody] ConfigClientModel model) { try { using (var db = new HonyomiContext()) { var config = db.Configs.Include(x => x.WatchDirectories).First(); config.ScanInterval = model.ScanInterval; config.ServerPort = model.ServerPort; config.WatchForChanges = model.WatchForChanges; //todo: be smarter about upserting foreach (WatchDirClientModel dir in model.WatchDirectories) { if (config.WatchDirectories.All(x => x.Path != dir.Path)) { db.WatchDirectories.Add(new WatchDirectory() { ConfigId = config.HonyomiConfigId, Path = dir.Path }); } } db.SaveChanges(); } return(Json(model)); } catch (Exception) { return(BadRequest()); } }
public static void ScanWatchDirectories() { using (var db = new HonyomiContext()) { var scanned = db.WatchDirectories.Select(x => x.Path).AsEnumerable().SelectMany(ScanDirectory); DataAccess.InsertNewBooks(scanned); } }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, HonyomiContext dbContext, UserManager <IdentityUser> uMan) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); //delete db for debugging if (File.Exists(RuntimeConstants.DatabaseLocation)) { File.Delete(RuntimeConstants.DatabaseLocation); } } /***MVC***/ app.UseMvc(); /***Authentication ***/ app.UseAuthentication(); /***Configure static files at root address "ui" instead of "wwwroot/dist" ***/ app.UseStaticFiles(new StaticFileOptions() { FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")) }); /***Add Hangfire for Background tasks***/ app.UseHangfireDashboard(); app.UseHangfireServer(); /***Create DB and populate defaults if needed***/ if (dbContext.Database.EnsureCreated()) { dbContext.CreateDefaults(uMan); } HonyomiConfig config = dbContext.Configs.First(); port = config.ServerPort; //debug scan path if (env.IsDevelopment()) { dbContext.WatchDirectories.Add(new WatchDirectory() { ConfigId = config.HonyomiConfigId, Path = Path.Combine(Directory.GetCurrentDirectory(), "..", "HonYomi.Tests", "scanTestDir") }); dbContext.SaveChanges(); } DirectoryScanner.ScanWatchDirectories(); RecurringJob.AddOrUpdate("scan", () => DirectoryScanner.ScanWatchDirectories(), Cron.MinuteInterval(config.ScanInterval)); }
public static ConfigClientModel GetConfigClient() { using (var db = new HonyomiContext()) { var config = db.Configs.Include(x => x.WatchDirectories).First(); return(new ConfigClientModel(config.WatchForChanges, config.ScanInterval, config.ServerPort, config.WatchDirectories .Select(x => new WatchDirClientModel(x.Path, x.WatchDirectoryId)) .ToArray())); } }
public void ScansBooksBasicAndInserts() { var books = DirectoryScanner.ScanDirectory(rootPath).ToArray(); HonyomiContext.DeleteDatabase(); using (var db = new HonyomiContext()) { db.Database.EnsureCreated(); DataAccess.InsertNewBooks(books); Assert.AreEqual(3, db.Books.Count()); Assert.IsTrue(db.Books.Include(x => x.Files).Any(x => x.Title == "A1" && x.Files.Count == 2)); } }
public static void SetTrackProgress(string userId, Guid trackId, double seconds) { using (var db = new HonyomiContext()) { FileProgress prog = db.FileProgresses.SingleOrDefault(x => x.FileId == trackId && x.UserId == userId); if (prog == null) { db.FileProgresses.Add(new FileProgress() { FileId = trackId, UserId = userId, Progress = seconds }); } else { prog.Progress = seconds; } db.SaveChanges(); } }
internal static void InsertNewBooks(IEnumerable <ScannedBook> books) { using (var db = new HonyomiContext()) { foreach (ScannedBook book in books) { if (!db.Books.Any(x => x.DirectoryPath == book.Path)) { var ibook = new IndexedBook() { DirectoryPath = book.Path, Title = book.Name }; var bookInfo = book.Files.Select(x => BookSearch.Search(x.Name)).FirstOrDefault(x => x != null); if (bookInfo != null) { ibook.Author = bookInfo.Author; ibook.ISBN = bookInfo.ISBN; ibook.Title = bookInfo.Title; } else if (book.Files.Count > 1) { ibook.Title = Util.LCS(book.Files[0].Name, book.Files[1].Name); } var files = book.Files.Select(x => new IndexedFile() { TrackIndex = x.Index, Filename = x.Name, Title = x.Name, FilePath = x.Path, MimeType = x.MimeType, Duration = x.Duration.TotalSeconds }).ToList(); ibook.Files = files; db.Books.Add(ibook); } } db.SaveChanges(); } }
public static void RemoveMissing() { using (var db = new HonyomiContext()) { List <Guid> removedFileIds = new List <Guid>(); List <Guid> removedBookIds = new List <Guid>(); foreach (IndexedFile file in db.Files) { if (!File.Exists(file.FilePath)) { db.Files.Remove(file); removedFileIds.Add(file.IndexedFileId); } } foreach (IndexedBook book in db.Books) { if (!book.Files.Any()) { db.Books.Remove(book); removedBookIds.Add(book.IndexedBookId); } } foreach (Guid fileId in removedFileIds) { var referencedFileProgresses = db.FileProgresses.Where(x => x.FileId == fileId); db.FileProgresses.RemoveRange(referencedFileProgresses); } foreach (Guid bookId in removedBookIds) { var referencedBookProgresses = db.BookProgresses.Where(x => x.BookId == bookId); db.BookProgresses.RemoveRange(referencedBookProgresses); } db.SaveChanges(); } }
public IActionResult AddWatchDirectory([FromBody] string[] paths) { try { using (var db = new HonyomiContext()) { foreach (string path in paths) { db.WatchDirectories.Add(new WatchDirectory { Path = path, Config = DataAccess.GetConfig() }); } db.SaveChanges(); return(Json(DataAccess.GetConfigClient())); } } catch (Exception) { return(BadRequest()); } }
//accepts byte range headers public IActionResult GetAudioFile(string location) { (Guid id, string token) = SplitTrackAddress(location); if (!Validate(token)) { return(BadRequest("Invalid JWT")); } string path, mimeType; using (var db = new HonyomiContext()) { var file = db.Files.FirstOrDefault(x => x.IndexedFileId == id); if (file == null) { return(NotFound()); } path = file.FilePath; mimeType = file.MimeType; } return(File(System.IO.File.OpenRead(path), mimeType, true)); }
public static FileWithProgress GetUserFileProgress(string userId, Guid fileId) { using (var db = new HonyomiContext()) { IndexedFile file = db.Files.Include(x => x.Book).ThenInclude(x => x.Files) .SingleOrDefault(x => x.IndexedFileId == fileId); if (file == null) { //bail when such a file does not exist return(null); } FileWithProgress result = new FileWithProgress { Guid = fileId, Title = file.Title, BookGuid = file.BookId, BookTitle = file.Book.Title, TrackIndex = file.TrackIndex, MediaType = file.MimeType, Duration = file.Duration, NextFile = file.Book.Files.FirstOrDefault(x => x.TrackIndex == file.TrackIndex + 1)?.IndexedFileId ?? Guid.Empty }; FileProgress fProg = db.FileProgresses.SingleOrDefault(x => x.FileId == fileId && x.UserId == userId); if (fProg == null) { result.ProgressSeconds = 0; } else { result.ProgressSeconds = fProg.Progress; } return(result); } }