using CliWrap; using CloudBuilder.AI.Data; using CloudBuilder.AI.Entity; using CloudBuilder.AI.Policy; using CloudBuilder.AI.SearchCriteria; using CloudBuilder.AI.Utility; using CloudBuilder.Core.DatabaseAccessor; using CloudBuilder.Core.DatabaseAccessor.Entity; using CloudBuilder.Core.Service; using CloudBuilder.Security.Data; using CloudBuilder.Security.Entity; using CloudBuilder.Security.Policy; using CloudBuilder.Security.Service; using CloudBuilder.Security.Utility; using DocumentFormat.OpenXml.ExtendedProperties; using DocumentFormat.OpenXml.Presentation; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using System.Diagnostics.Contracts; using System.IO; using System.Net; using System.Text; using System.Transactions; namespace CloudBuilder.AI.Service { public class AiBookService : IAiBookService { private readonly IApplicationService service; private IRepository repository; public AiBookService(IApplicationService service) { this.service = service; repository = service.GetRepository>(); } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Find)] public AiBookData FindByKey(string key) { AiBookData data = new AiBookData(); data.AiBook = repository.DetachedEntities.Where(x => x.BookId == key).FirstOrDefault()!; if (data.AiBook.FileId > 0) { IRepository repositoryUploadDmsFile = service.GetRepository>(); BookDmsFileViewEntity dms; dms = repositoryUploadDmsFile.DetachedEntities.Where(x => x.FileId == data.AiBook.FileId).FirstOrDefault()!; data.FileName = dms.OrgFileName; } return data; } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Find)] public AiBookEntity FindByTitle(string title) { return repository.DetachedEntities.Where(x => x.Title == title).FirstOrDefault()!; } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Find)] public AiBookResultData FindBySearchCriteria(AiBookSearchCriteria criteria) { AiBookResultData data = new AiBookResultData(); AiBookEntity[] list = null; int count = 0; string sqlWhere = null; if (criteria.Filter != null && criteria.Filter.Length > 0) { sqlWhere = SearchFilter.ComposeWhereClause(criteria.Filter); } AiBookEntity entity = AiBookEntity.GetInstance(); string sql = entity.GetSelectTopFrom(criteria.limit, criteria.page, criteria.orderby.StringToDbField(), criteria.orderbytag, sqlWhere); string err = null; try { list = repository.FromSql(sql).ToArray(); } catch (System.Exception ex) { err = ex.Message; } if (list != null && list.Length > 0) { sql = entity.GetSelectCountFrom(sqlWhere); count = (int)repository.ExecuteScalar(sql); } data.Limit = criteria.limit; data.Page = criteria.page; data.Datas = list; data.Total = count; //data.Sql = sql; data.ErrorMessage = err; return data; } //[PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Print)] public dynamic PrintBySearchCriteria(AiBookSearchCriteria criteria) { throw new NotImplementedException(); } //[PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Insert)] //[UnitOfWork] //public AiBookEntity Insert(AiBookEntity data) //{ // throw new NotImplementedException(); //} [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Insert)] [UnitOfWork] public AiBookData Insert(AiBookData data) { AiBookEntity entity = repository.DetachedEntities.Where(x => x.Title == data.AiBook.Title).FirstOrDefault(); if (entity != null) { throw new ValidatedException("记录已存在."); } ISecurityGeneratorNumberService securityGeneratorNumberService = service.ServiceProvider.GetService()!; data.AiBook.BookId = securityGeneratorNumberService.GetNo(AIPrefixPolicy.AI_BOOK, AIPrefixPolicy.GUID, AIPrefixPolicy.AI_BOOK_PREFIX, YesNoPolicy.NO, AIPrefixPolicy.AI_BOOK_GUID_FORMAT); repository.InsertNow(data.AiBook); IRepository repositoryAiChapterEntity = repository.GetRepository>(); if (data.AiChapters != null && data.AiChapters.Length > 0) repositoryAiChapterEntity.InsertNow(data.AiChapters); return data; } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Update)] [UnitOfWork] public AiBookData Update(AiBookData data) { AiBookEntity aiBook = repository.DetachedEntities.Where(x => x.BookId == data.AiBook.BookId).FirstOrDefault(); if (aiBook == null) { throw new ValidatedException("记录不存在."); } ValidateHelper.Validate(service, data.AiBook, AiBookEntity.DB_NAME_AI_BOOK); ObjectCopyHelper.Copy(data.AiBook, aiBook); repository.UpdateNow(aiBook); return data; } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Delete)] [UnitOfWork] public void Delete(string key) { var ent = repository.DetachedEntities.Where(x => x.BookId == key).FirstOrDefault()!; if (ent != null) { repository.DeleteNow(ent); } } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Delete)] [UnitOfWork] public void Deletes(string[] keys) { foreach (string key in keys) { Delete(key); } } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Update)] [UnitOfWork] public AiBookData ProcessBook(string key, string encoding, string pattern) { AiBookData data = FindByKey(key); ChapterSplitter chapterSplitter = new ChapterSplitter(); ParagraphSplitter paragraphSplitter = new ParagraphSplitter(); IRepository repositoryDmsFile = repository.GetRepository>(); DmsFileEntity entity = repositoryDmsFile.DetachedEntities.Where(x => x.FileId == data.AiBook.FileId && x.CreatedBy == service.UserId).FirstOrDefault()!; if (entity == null) throw new ValidatedException("文件不存在."); var fileExtension = Path.GetExtension(entity.OrderKey);//获取文件格式,拓展名 string file = FileTypePolicy.PackFilePath(service, entity.CreatedBy, entity.OrderKey); if (!File.Exists(file)) throw new ValidatedException("文件不存在."); System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance); string context = File.ReadAllText(file, Encoding.GetEncoding(encoding)); List aiChapterEntities = chapterSplitter.SplitNovelIntoChapters(context, pattern); if (aiChapterEntities == null || aiChapterEntities.Count() == 0) return data; int chapterIndex = 1; foreach (var chapter in aiChapterEntities) { chapter.ChapterId = chapterIndex++; chapter.BookId = data.AiBook.BookId; chapter.Status = ChapterStatusPolicy.PROCESS; } data.AiChapters = aiChapterEntities.ToArray(); paragraphSplitter.PackParagraphs(data); IRepository repositoryAiChapterEntity = repository.GetRepository>(); IRepository repositoryAiSentenceEntity = repository.GetRepository>(); AiChapterEntity[] aiChapters = repositoryAiChapterEntity.DetachedEntities.Where(x => x.BookId == data.AiBook.BookId).ToArray(); if (aiChapters != null && aiChapters.Length > 0) { AiSentenceEntity[] aiSentences = repositoryAiSentenceEntity.DetachedEntities.Where(x => x.BookId == data.AiBook.BookId).ToArray(); if (aiSentences != null && aiSentences.Length > 0) { repositoryAiSentenceEntity.DeleteNow(aiSentences); } repositoryAiChapterEntity.DeleteNow(aiChapters); } repositoryAiChapterEntity.InsertNow(data.AiChapters); if (data.AiSentences == null || data.AiSentences.Count() == 0) return data; repositoryAiSentenceEntity.InsertNow(data.AiSentences); return FindByKey(key); } //public IActionResult GetTtsStream(string text) //{ // string fileDownloadName = Path.Combine(service.Configuration["FileServiceSettings:BackupDmsFileDirectory"], @"voice", DateTime.Now.ToString("yyyyMMddHHmmss") + ".mp3"); // string param = PackParameters(ChineseTtsVoice.Sherpa2.ToString(), fileDownloadName, text); // RunMyProcess(service.Configuration["CloudBuilder.Topshelf:Path"], param); // var stream = System.IO.File.OpenRead(fileDownloadName); // string contentType = "application/octet-stream"; // return new FileStreamResult(stream, contentType) { FileDownloadName = fileDownloadName }; //} [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Find)] public IActionResult GetMp3Stream(AiSentenceViewEntity aiSentence) { string fileDownloadName = Path.Combine(service.Configuration["FileServiceSettings:BackupDmsFileDirectory"], @"voice", string.Format("{0}_{1}.mp3", aiSentence.BookId, aiSentence.ChapterId)); var stream = System.IO.File.OpenRead(fileDownloadName); string contentType = "application/octet-stream"; return new FileStreamResult(stream, contentType) { FileDownloadName = fileDownloadName }; } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Find)] public void GenerateMp3(AiChapterEntity[] chapters) { string save_path = Path.Combine(service.Configuration["FileServiceSettings:BackupDmsFileDirectory"], @"voice"); foreach (AiChapterEntity sentence in chapters) { string param = PackTtsParameters(ChineseTtsVoice.Sherpa2.ToString(), save_path, sentence.BookId, sentence.ChapterId.ToString()); RunMyProcess(service.Configuration["CloudBuilder.Topshelf:Path"], param); } } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Find)] public void GenerateMp3ByBookId(string bookId) { IRepository repositoryAiChapterEntity = repository.GetRepository>(); AiChapterEntity[] chapters = repositoryAiChapterEntity.DetachedEntities.Where(x => x.BookId == bookId).OrderBy(x => x.ChapterId).ToArray(); string save_path = Path.Combine(service.Configuration["FileServiceSettings:BackupDmsFileDirectory"], @"voice"); foreach (AiChapterEntity sentence in chapters) { string param = PackTtsParameters(ChineseTtsVoice.Sherpa2.ToString(), save_path, sentence.BookId, sentence.ChapterId.ToString()); RunMyProcess(service.Configuration["CloudBuilder.Topshelf:Path"], param); } } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Find)] public void PackPersonNameByBookId(string bookId) { IRepository repositoryAiChapterEntity = repository.GetRepository>(); AiChapterEntity[] chapters = repositoryAiChapterEntity.DetachedEntities.Where(x => x.BookId == bookId).OrderBy(x => x.ChapterId).ToArray(); string save_path = Path.Combine(service.Configuration["FileServiceSettings:BackupDmsFileDirectory"], @"voice"); foreach (AiChapterEntity aiChapter in chapters) { string param = PackPersonNameParameters(ChineseTtsVoice.Sherpa2.ToString(), save_path, aiChapter.BookId, aiChapter.ChapterId.ToString()); RunMyProcess(service.Configuration["CloudBuilder.Topshelf:Path"], param); } } [PermissionOperate(name: AIPermissionPolicy.AiBook, operate: Operate.Find)] public void PackPersonName(AiChapterEntity[] chapters) { string save_path = Path.Combine(service.Configuration["FileServiceSettings:BackupDmsFileDirectory"], @"voice"); foreach (AiChapterEntity aiChapter in chapters) { string param = PackPersonNameParameters(ChineseTtsVoice.Sherpa2.ToString(), save_path, aiChapter.BookId, aiChapter.ChapterId.ToString()); RunMyProcess(service.Configuration["CloudBuilder.Topshelf:Path"], param); } } private string PackPersonNameParameters(string voice, string save_path, string bookId, string chapterId) { //task:ChineseNameExtractorTask book_id:B000008 chapter_id:3 List para = new List(); para.Add("task:" + "ChineseNameExtractorTask"); para.Add("book_id:" + bookId); para.Add("chapter_id:" + chapterId); return para.ToArray().ToDelimiteredList(' '); } private string PackTtsParameters(string voice, string save_path, string bookId, string chapterId) { //task:TtsTask book_id:B000008 chapter_id:3 speed:1 voice:Sherpa2 actor:韩立 actor_voice:Sherpa1 save_path:D:\\Net8\\FileServer\\Backup\\DmsFile\\voice List para = new List(); para.Add("task:" + "TtsTask"); para.Add("book_id:" + bookId); para.Add("chapter_id:" + chapterId); para.Add("voice:" + voice); para.Add("save_path:" + save_path); para.Add("speed:1"); para.Add("actor:NA"); return para.ToArray().ToDelimiteredList(' '); } /// /// 执行cmd指令(同步等待,await要求等待返回,转码太耗时) /// /// public void RunMyProcess(string exePath, string Parameters) { try { if (string.IsNullOrEmpty(exePath)) return; var result = Cli.Wrap(exePath) .WithWorkingDirectory(Path.GetDirectoryName(exePath)) .WithArguments(Parameters) .ExecuteAsync().GetAwaiter().GetResult(); Thread.Sleep(300); } catch (Exception ex) { throw new ValidatedException(ex.Message); } } /// /// 执行cmd指令(异步不等待,await要求等待返回,转码太耗时) /// /// public void RunMyProcessAsync(string exePath, string Parameters) { try { if (string.IsNullOrEmpty(exePath)) return; Cli.Wrap(exePath) .WithWorkingDirectory(Path.GetDirectoryName(exePath)) .WithArguments(Parameters) .ExecuteAsync(); Thread.Sleep(300); } catch (Exception ex) { throw new ValidatedException(ex.Message); } } } }