public async void LoadInstruction( BookInstruction B, bool useCache ) { SpiderBook SBook = new SpiderBook( B ); if ( useCache && Shared.Storage.FileExists( B.TOCPath ) ) { B.PackSavedVols( SBook.PSettings ); } else { await SBook.Process(); // Cannot download content, use cache if available if ( !( B.Packed == true || B.Packable ) && Shared.Storage.FileExists( B.TOCPath ) ) { Logger.Log( ID, "Spider failed to produce instructions, using cache instead", LogType.WARNING ); B.PackSavedVols( SBook.PSettings ); } } if ( B.Packed != true && B.Packable ) { B.PackVolumes( SBook.GetPPConvoy() ); } await CacheCover( B ); OnComplete( B ); }
private async Task <bool> _RowAction(IGRRow _Row) { GRRow <BookDisplay> Row = (GRRow <BookDisplay>)_Row; BookInstruction Payload = ( BookInstruction )Row.Source.Payload; if (Payload != null) { // Save the book here Payload.SaveInfo(); // Reload the BookDisplay as Entry might changed from SaveInfo Row.Source = new BookDisplay(Payload.Entry); } SpiderBook Item = await SpiderBook.CreateSAsync(Row.Source.Entry.ZoneId, Row.Source.Entry.ZItemId, Payload?.BookSpiderDef); Item.PropertyChanged += Item_PropertyChanged; XParameter Metadata = Item.PSettings.Parameter("METADATA") ?? new XParameter("METADATA"); Metadata.SetValue(new XKey("payload", Row.Source.Entry.Meta[AppKeys.GLOBAL_SSID])); Item.PSettings.SetParameter(Metadata); if (!Item.ProcessSuccess && Item.CanProcess) { await ItemProcessor.ProcessLocal(Item); } Item.PropertyChanged -= Item_PropertyChanged; (( BookDisplayPageExt )Extension).OpenItem(_Row); return(true); }
private void MessageBus_OnDelivery(Message Mesg) { ProcConvoy Convoy = Mesg.Payload as ProcConvoy; if (Mesg.Content == "RUN_RESULT" && Convoy != null && Convoy.Dispatcher == EditTarget) { TempInst = Convoy.Payload as BookInstruction; ProcConvoy ProcCon = ProcManager.TracePackage(Convoy, (P, C) => P is ProcParameter); if (ProcCon != null) { ProcParameter PPClone = new ProcParameter(); PPClone.ReadParam(ProcCon.Dispatcher.ToXParam()); ProcCon = new ProcConvoy(PPClone, null); } TempInst.PackVolumes(ProcCon); Preview.Navigate( typeof(TableOfContents) , new Tuple <Volume[], SelectionChangedEventHandler>(TempInst.GetVolInsts().Remap(x => x.ToVolume(TempInst.Entry)), PreviewContent) ); Preview.BackStack.Clear(); TestRunning.IsActive = false; } }
private async Task ViewTestResult(BookInstruction Payload) { if (PreviewFile == null) { PreviewFile = await AppStorage.MkTemp(); } await PreviewFile.WriteString(Payload.PlainTextInfo); var j = Dispatcher.RunIdleAsync( x => Frame.Navigate(typeof(DirectTextViewer), PreviewFile) ); }
private async void LoadInstruction(BookInstruction B, bool useCache) { if (!BookInstruction.OpLocks.AcquireLock(B.GID, out AsyncLocks <string, bool> .QueueToken QT)) { await QT.Task; } SpiderBook SBook = await SpiderBook.CreateSAsync(B.ZoneId, B.ZItemId, B.BookSpiderDef); if (Shared.Storage.FileExists(SBook.MetaLocation)) { B.LastCache = Shared.Storage.FileTime(SBook.MetaLocation).LocalDateTime; } if (useCache && (B.Packed == true || Shared.BooksDb.Volumes.Any(x => x.Book == B.Entry))) { if (B.Packed != true) { B.PackSavedVols(SBook.PSettings); } } else { bool UpdateFailed = true; await SBook.Process(); if (SBook.Processed && SBook.ProcessSuccess) { B.LastCache = DateTime.Now; BookInstruction BUpdate = SBook.GetBook(); if (BUpdate.Packable && BUpdate.Packed != true) { BUpdate.PackVolumes(SBook.GetPPConvoy()); B.Update(BUpdate); UpdateFailed = false; } } // Cannot download content, use cache if available if (UpdateFailed && Shared.BooksDb.Volumes.Any(x => x.Book == B.Entry)) { Logger.Log(ID, "Spider failed to produce instructions, using cache instead", LogType.WARNING); B.PackSavedVols(SBook.PSettings); } } QT.TrySetResult(true); OnComplete(B); }
private void MessageBus_OnDelivery(Message Mesg) { ProcConvoy Convoy = Mesg.Payload as ProcConvoy; if (Mesg.Content == "RUN_RESULT" && Convoy != null && Convoy.Dispatcher == EditTarget) { TestRunning.IsActive = false; BookInstruction BookInst = Convoy.Payload as BookInstruction; if (BookInst != null) { var j = ViewTestResult(BookInst); } } }
private async void PinItemToStart(object sender, RoutedEventArgs e) { SpiderBook B = ( SpiderBook )(( FrameworkElement )sender).DataContext; if (B.ProcessSuccess) { BookInstruction Book = B.GetBook(); string TileId = await PageProcessor.PinToStart(Book); if (!string.IsNullOrEmpty(TileId)) { PinManager PM = new PinManager(); PM.RegPin(Book, TileId, true); await PageProcessor.RegLiveSpider(B, Book, TileId); } } }
public async void LoadInst( BookInstruction b ) { IEnumerable<SVolume> Vols = b.GetVolumes().Cast<SVolume>(); foreach ( SVolume Vol in Vols ) { Shared.LoadMessage( "SubProcessRun", Vol.VolumeTitle ); // This should finalize the chapter info await Vol.SubProcRun( b ); } if( Vols.Count() == 0 ) { MessageBus.SendUI( GetType(), AppKeys.HS_NO_VOLDATA, b ); } Shared.LoadMessage( "CompilingTOC", b.Title ); await b.SaveTOC( Vols ); OnComplete( b ); }
private async void LoadChapterInst(Chapter C) { BookInstruction BkInst = ( BookInstruction )CurrentBook ?? new BookInstruction(C.Book); XRegistry Settings = SpiderBook.GetSettings(BkInst.ZoneId, BkInst.ZItemId); EpInstruction Inst = new EpInstruction(C, Settings); IEnumerable <ProcConvoy> Convoys = await Inst.Process(); string ChapterText = ""; foreach (ProcConvoy Konvoi in Convoys) { ProcConvoy Convoy = ProcManager.TracePackage( Konvoi , (d, c) => c.Payload is IEnumerable <IStorageFile> || c.Payload is IStorageFile ); if (Convoy == null) { continue; } if (Convoy.Payload is IStorageFile) { ChapterText += await(( IStorageFile )Convoy.Payload).ReadString(); } else if (Convoy.Payload is IEnumerable <IStorageFile> ) { foreach (IStorageFile ISF in ((IEnumerable <IStorageFile>)Convoy.Payload)) { Shared.LoadMessage("MergingContents", ISF.Name); ChapterText += (await ISF.ReadString()) + "\n"; } } } await new ContentParser().ParseAsync(ChapterText, C); OnComplete(C); }
public static async Task RegLiveSpider(SpiderBook SBook, BookInstruction Book, string TileId) { if (!SBook.HasChakra) { StringResources stx = StringResources.Load("Message"); bool Confirmed = false; await Popups.ShowDialog(UIAliases.CreateDialog( stx.Str("TileUpdateSupport"), stx.Str("ShellTile") , () => Confirmed = true , stx.Str("Yes"), stx.Str("No") )); if (Confirmed) { BackgroundProcessor.Instance.CreateTileUpdateForBookSpider(Book.GID, TileId); } } }
private async Task M0006_LocalBookStorage() { BookStorage BkStore = new BookStorage(); await BkStore.SyncSettings(); List <Book> Books = new List <Book>(); foreach (string[] Item in BkStore.GetList()) { string Id = Item[0]; BookItem Bk = null; if (int.TryParse(Id, out int NOP)) { Bk = X.Instance <BookItem>(XProto.BookItemEx, Id); } else { if (Id[0] == 'Z') { string[] sId = Id.Split('/'); Bk = new BookInstruction(sId[0].Substring(1), sId[1]); } else { Bk = new BookInstruction(AppKeys.ZLOCAL, Id); } } Bk.Entry.Fav = true; Bk.Title = Item[1]; Bk.Info.LastUpdateDate = Item[2]; Bk.Info.LatestSection = Item[3].Replace(BookItem.PropertyName(PropType.LatestSection) + ": ", ""); Books.Add(Bk.Entry); } MesgR(stx.Text("SavingRecords")); Shared.BooksDb.SaveBooks(Books); }
public void OpenBook( Chapter C, bool Reload = false, int Anchor = -1 ) { if ( OpenLock ) return; if ( C == null ) { Logger.Log( ID, "Oops, Chapter is null. Can't open nothing.", LogType.WARNING ); return; } if ( !Reload && C.Equals( CurrentChapter ) ) { if ( Anchor != -1 ) { ContentView.UserStartReading = false; ContentView.GotoIndex( Anchor ); } return; } ClosePane(); OpenMask(); CurrentChapter = C; OpenLock = true; // Throw this into background as it is resources intensive Task.Run( () => { if ( CurrentBook == null || C.aid != CurrentBook.Id ) { Shared.LoadMessage( "BookConstruct" ); if ( C is SChapter ) { CurrentBook = new BookInstruction( C as SChapter ); } else { CurrentBook = X.Instance<BookItem>( XProto.BookItemEx, C ); } } BookLoader BL = new BookLoader( BookLoaded ); BL.Load( CurrentBook, true ); // Fire up Episode stepper, used for stepping next episode if ( ES == null || ES.Chapter.aid != C.aid ) { Shared.LoadMessage( "EpisodeStepper" ); VolumeLoader VL = new VolumeLoader( ( BookItem b ) => { ES = new EpisodeStepper( new VolumesInfo( b ) ); SetInfoTemplate(); } ); VL.Load( CurrentBook ); } else { Worker.UIInvoke( () => SetInfoTemplate() ); } ReloadReader = () => { ContentFrame.Content = null; Shared.LoadMessage( "RedrawingContent" ); ContentView?.Dispose(); ContentView = new ReaderContent( this, Anchor ); SetLayoutAware(); ContentFrame.Content = ContentView; // Load Content at the very end ContentView.Load( false ); }; // Override reload here since // Since the selected index just won't update if ( Reload ) { ChapterLoader CL = new ChapterLoader( CurrentBook, x => { OpenLock = false; Redraw(); } ); // if book is local, use the cache CL.Load( CurrentChapter, CurrentBook.IsLocal ); } else { Worker.UIInvoke( () => { // Lock should be released before redrawing start OpenLock = false; Redraw(); } ); } } ); }
public override async Task<ProcConvoy> Run( ProcConvoy Convoy ) { Convoy = await base.Run( Convoy ); ProcConvoy UsableConvoy; if ( !TryGetConvoy( out UsableConvoy, ( P, C ) => { if ( P.Type.HasFlag( ProcType.FIND ) || P.Type.HasFlag( ProcType.URLLIST ) ) { return C.Payload is IEnumerable<IStorageFile>; } return false; } ) ) return Convoy; IInstructionSet SpTOC = null; // Search for the closest Instruction Set ProcConvoy SpiderInst = ProcManager.TracePackage( Convoy , ( P, C ) => { return C.Payload is IInstructionSet; } ); if( SpiderInst != null ) { SpTOC = SpiderInst.Payload as IInstructionSet; } if( SpTOC == null ) { SpTOC = new BookInstruction(); } IEnumerable<IStorageFile> ISFs = UsableConvoy.Payload as IEnumerable<IStorageFile>; bool VTitleAddOnce = false; ProcPassThru PPass = new ProcPassThru( new ProcConvoy( this, SpTOC ) ); foreach( IStorageFile ISF in ISFs ) { string Content = await ISF.ReadString(); ProcFind.RegItem RegTitle = new ProcFind.RegItem( VolPattern, VolTitle, true ); ProcFind.RegItem RegParam = new ProcFind.RegItem( VolPattern, VolParam, true ); if ( !( RegTitle.Validate() || RegParam.Validate() ) ) continue; MatchCollection matches = RegTitle.RegExObj.Matches( Content ); foreach ( Match match in matches ) { if ( VTitleAddOnce ) break; VolInstruction VInst = null; if( RegTitle.Valid ) { string FTitle = string.Format( RegTitle.Format , match.Groups .Cast<Group>() .Select( g => g.Value ) .ToArray() ); if( string.IsNullOrEmpty( RegTitle.Pattern ) ) { VTitleAddOnce = true; } VInst = new VolInstruction( VTitleAddOnce ? SpTOC.LastIndex : match.Index , FTitle.ToCTrad() ); VInst.ProcMan = VolProcs; SpTOC.PushInstruction( VInst ); } else { ProcManager.PanelMessage( this, () => Res.RSTR( "InvalidPattern" ), LogType.WARNING ); continue; } if ( HasVolProcs && RegParam.Valid ) { string FParam = string.Format( RegParam.Format , match.Groups .Cast<Group>() .Select( g => g.Value ) .ToArray() ); if( VolAsync ) { VInst.SetProcId( VolProcs.GUID ); VInst.PushConvoyParam( FParam ); } else { ProcConvoy VolConvoy = await VolProcs.CreateSpider().Crawl( new ProcConvoy( PPass, VInst ) ); } } } RegTitle = new ProcFind.RegItem( EpPattern, EpTitle, true ); RegParam = new ProcFind.RegItem( EpPattern, EpParam, true ); if ( !( RegTitle.Validate() || RegParam.Validate() ) ) continue; matches = RegTitle.RegExObj.Matches( Content ); foreach ( Match match in matches ) { EpInstruction EInst = null; if( RegTitle.Valid ) { string FTitle = string.Format( RegTitle.Format , match.Groups .Cast<Group>() .Select( g => g.Value ) .ToArray() ); EInst = new EpInstruction( VTitleAddOnce ? SpTOC.LastIndex : match.Index , FTitle.ToCTrad() ); EInst.ProcMan = EpProcs; SpTOC.PushInstruction( EInst ); } else { ProcManager.PanelMessage( this, () => Res.RSTR( "InvalidPattern" ), LogType.WARNING ); continue; } if ( HasEpProcs && RegParam.Valid ) { string FParam = string.Format( RegParam.Format , match.Groups .Cast<Group>() .Select( g => g.Value ) .ToArray() ); if( EpAsync ) { EInst.SetProcId( EpProcs.GUID ); EInst.PushConvoyParam( FParam ); } else { ProcConvoy EpConvoy = await EpProcs.CreateSpider().Crawl( new ProcConvoy( PPass, FParam ) ); } } } } return new ProcConvoy( this, SpTOC ); }
private async void ProcessVols() { StringResources stx = new StringResources( "LoadingMessage" ); string LoadText = stx.Str( "ProgressIndicator_Message" ); IEnumerable<string> BookIds = Shared.Storage.ListDirs( FileLinks.ROOT_LOCAL_VOL ); string[] favs = new BookStorage().GetIdList(); List<LocalBook> Items = new List<LocalBook>(); foreach ( string Id in BookIds ) { Loading = LoadText + ": " + Id; LocalBook LB = await LocalBook.CreateAsync( Id ); if ( LB.ProcessSuccess ) { Items.Add( LB ); LB.IsFav = favs.Contains( Id ); } } Action<string, SpiderBook> ProcessSpider = ( Id, LB ) => { Loading = LoadText + ": " + Id; if ( LB.aid != Id ) { try { Logger.Log( ID, "Fixing misplaced spider book" ); Shared.Storage.MoveDir( FileLinks.ROOT_SPIDER_VOL + Id, LB.MetaLocation ); } catch ( Exception ex ) { Logger.Log( ID , string.Format( "Unable to move script: {0} => {1}, {2} " , Id, LB.aid, ex.Message ) , LogType.WARNING ); } } if ( LB.ProcessSuccess || LB.CanProcess ) { Items.Add( LB ); LB.IsFav = favs.Contains( Id ); } else { try { Logger.Log( ID, "Removing invalid script: " + Id, LogType.INFO ); Shared.Storage.RemoveDir( LB.MetaRoot ); } catch ( Exception ex ) { Logger.Log( ID, "Cannot remove invalid script: " + ex.Message, LogType.WARNING ); } } }; BookIds = Shared.Storage.ListDirs( FileLinks.ROOT_SPIDER_VOL ); foreach ( string Id in BookIds ) { if ( Id[ 0 ] == ZONE_PFX ) { IEnumerable<string> ZoneItems = Shared.Storage.ListDirs( FileLinks.ROOT_SPIDER_VOL + Id + "/" ); foreach ( string SId in ZoneItems ) { /** * This code is a mess. I'll explain a bit more in here * First, the location of the Book.MetaLocation for ZoneItems * can only be retrived from BookInstruction * However ZoneId and Id are assinged by Spider on the fly, * restoring this information is a bit tricky */ // Create BookIntstruction just to retrieve the correct id pattern BookInstruction BInst = new BookInstruction( Id, SId ); /** * After 2 hours of investigations... * Welp, just outsmarted by myself, The CreateAsyncSpide works because: * Inside the TestProcessed method, the BookInstruction are created * using BoockInstruction( Id, Setings ) overload * the provided id is "this.aid" here BUT the full id is restored again * in InitProcMan() method * Fortunately, ssid will be set correctly inside the ReadInfo method */ ProcessSpider( BInst.Id, await SpiderBook.CreateAsyncSpider( BInst.Id ) ); } } else { ProcessSpider( Id, await SpiderBook.CreateAsyncSpider( Id ) ); } } if ( 0 < Items.Count ) SearchSet = Items; Loading = null; }
private async void LoadInst(BookInstruction b) { if (!BookInstruction.OpLocks.AcquireLock(b.GID, out AsyncLocks <string, bool> .QueueToken QT)) { await QT.Task; } foreach (VolInstruction VInst in b.GetVolInsts()) { Shared.LoadMessage("SubProcessRun", VInst.Title); // This should finalize the chapter info var Convoy = await VInst.Process(b); } Shared.LoadMessage("CompilingTOC", b.Title); IEnumerable <Volume> Vols = b.GetVolInsts().Remap(x => x.ToVolume(b.Entry)); if (Vols.Any()) { List <Volume> NewVolumes = new List <Volume>(); Vols.ExecEach(Vol => { string VID = Vol.Meta[AppKeys.GLOBAL_VID]; Volume NVol = b.Entry.Volumes.FirstOrDefault(x => x.Meta[AppKeys.GLOBAL_VID] == VID) ?? Vol; if (NVol != Vol) { NVol.Title = Vol.Title; NVol.Index = Vol.Index; NVol.Json_Meta = Vol.Json_Meta; } Shared.BooksDb.LoadCollection(NVol, x => x.Chapters, x => x.Index); List <Chapter> NewChapters = new List <Chapter>(); Vol.Chapters.ExecEach(Ch => { string CID = Ch.Meta[AppKeys.GLOBAL_CID]; Chapter NCh = NVol.Chapters.FirstOrDefault(x => x.Meta[AppKeys.GLOBAL_CID] == CID) ?? Ch; if (NCh != Ch) { NCh.Title = Ch.Title; NCh.Index = Ch.Index; NCh.Json_Meta = Ch.Json_Meta; } NewChapters.Add(NCh); }); NewVolumes.Add(NVol); }); b.Entry.Volumes = NewVolumes; b.SaveInfo(); } else { MessageBus.SendUI(GetType(), AppKeys.HS_NO_VOLDATA, b); } QT.TrySetResult(true); OnComplete(b); }
private async Task ViewTestResult( BookInstruction Payload ) { await PreviewFile.WriteString( Payload.PlainTextInfo ); var j = Dispatcher.RunIdleAsync( x => Frame.Navigate( typeof( DirectTextViewer ), PreviewFile ) ); }
private async Task UpdateSpiders() { try { XReg.SetParameter(TASK_START, CustomAnchor.TimeKey); XReg.Save(); IEnumerable <XParameter> Updates; List <string> Exists = new List <string>(); if (Retrying) { Updates = XReg.Parameters(AppKeys.BTASK_SPIDER).Where(x => { int r = x.GetSaveInt(AppKeys.BTASK_RETRY); return(0 < r && r < MaxRetry); }); } else { Updates = XReg.Parameters(AppKeys.BTASK_SPIDER).Where(x => { int r = x.GetSaveInt(AppKeys.BTASK_RETRY); if (r == 0 || MaxRetry <= r) { return(true); } else { // Consider Retry Timer dead if LastUpdate is 20 < minutes DateTime LastRun = DateTime.FromFileTimeUtc(x.GetSaveLong(AppKeys.LBS_TIME)); return(30 < DateTime.Now.Subtract(LastRun).TotalMinutes); } }); } foreach (XParameter UpdateParam in Updates) { string TileId = UpdateParam.GetValue("tileId"); if (!SecondaryTile.Exists(TileId)) { UpdateParam.SetValue(new XKey[] { new XKey(AppKeys.SYS_EXCEPTION, "App Tile is missing") , CustomAnchor.TimeKey }); XReg.SetParameter(UpdateParam); continue; } string[] Keys = UpdateParam.Id.Split('.'); if (Keys.Length != 3) { XReg.RemoveParameter(UpdateParam.Id); continue; } SpiderBook SBook = await SpiderBook.CreateSAsync(Keys[0], Keys[2], null); if (!SBook.CanProcess) { XReg.RemoveParameter(UpdateParam.Id); continue; } SBook.MarkUnprocessed(); string OHash = null, NHash = null; SBook.GetBook()?.Entry.Meta.TryGetValue("TOCHash", out OHash); await ItemProcessor.ProcessLocal(SBook); if (SBook.ProcessSuccess) { BookInstruction NBook = SBook.GetBook(); NBook?.Entry.Meta.TryGetValue("TOCHash", out NHash); if (NBook.Packed == true && (NBook.NeedUpdate || OHash != NHash)) { await LiveTileService.UpdateTile(CanvasDevice, NBook, TileId); } UpdateParam.SetValue(new XKey[] { new XKey(AppKeys.SYS_EXCEPTION, false) , new XKey(AppKeys.BTASK_RETRY, 0) , CustomAnchor.TimeKey }); } else { CreateRetryTimer(); int NRetries = UpdateParam.GetSaveInt(AppKeys.BTASK_RETRY); UpdateParam.SetValue(new XKey[] { new XKey(AppKeys.SYS_EXCEPTION, true) , new XKey(AppKeys.BTASK_RETRY, NRetries + 1) , CustomAnchor.TimeKey }); } XReg.SetParameter(UpdateParam); XReg.Save(); } XReg.SetParameter(TASK_END, CustomAnchor.TimeKey); XReg.Save(); } catch (Exception ex) { try { XReg.SetParameter(AppKeys.SYS_EXCEPTION, new XKey(AppKeys.SYS_MESSAGE, ex.Message)); XReg.Save(); } catch (Exception) { } } }
private async Task <Book> MigrateBookSpider(string SRoot, string ZoneId, string ZItemId) { if (!Shared.Storage.FileExists(SRoot + "METADATA.xml")) { return(null); } XRegistry MetaDefs = new XRegistry("<metadata />", SRoot + "METADATA.xml"); XParameter MetaParam = MetaDefs.Parameter("METADATA"); BookInstruction BkInst = new BookInstruction(ZoneId, ZItemId); BkInst.Title = MetaParam.GetValue("Title"); BkInst.Info.Author = MetaParam.GetValue("Author"); BkInst.Info.Press = MetaParam.GetValue("Press"); BkInst.Info.LastUpdateDate = MetaParam.GetValue("LastUpdateDate"); BkInst.Info.TotalHitCount = MetaParam.GetValue("TotalHitCount"); BkInst.Info.DailyHitCount = MetaParam.GetValue("TodayHitCount"); BkInst.Info.PushCount = MetaParam.GetValue("PushCount"); BkInst.Info.FavCount = MetaParam.GetValue("FavCount"); BkInst.Info.Length = MetaParam.GetValue("Length"); BkInst.Info.LatestSection = MetaParam.GetValue("LatestSection"); BkInst.Info.LongDescription = MetaParam.GetValue("Intro"); Book Entry = BkInst.Entry; await Shared.BooksDb.LoadCollectionAsync(Entry, x => x.Volumes, x => x.Index); Entry.Volumes.Clear(); XRegistry TOCDefs = new XRegistry("<metadata />", SRoot + "/" + "toc.txt"); int vi = 0; XParameter VolParam = TOCDefs.Parameter("VolInst" + vi); while (VolParam != null) { Volume Vol = new Volume() { Book = Entry, Title = VolParam.GetValue("Title"), Index = VolParam.GetSaveInt("Index"), Chapters = new List <Chapter>() }; Vol.Meta["ProcId"] = VolParam.GetValue("ProcId"); Vol.Meta[AppKeys.GLOBAL_VID] = Utils.Md5(Vol.Title); XParameter PParam = VolParam.Parameter("0"); for (int p = 1; PParam != null; p++) { Vol.Meta["P" + PParam.Id] = PParam.GetValue("Value"); PParam = VolParam.Parameter(p.ToString()); } string MVolHash = Utils.Md5(Vol.Title); int ei = 0; XParameter ChParam = VolParam.Parameter("EpInst" + ei); while (ChParam != null) { Chapter Ch = new Chapter() { Book = Entry, Volume = Vol, Title = ChParam.GetValue("Title"), Index = ChParam.GetSaveInt("Index") }; Ch.Meta["ProcId"] = ChParam.GetValue("ProcId"); Ch.Meta[AppKeys.GLOBAL_CID] = Utils.Md5(Ch.Title); string MChHash = Utils.Md5(Ch.Title); PParam = ChParam.Parameter("0"); for (int p = 1; PParam != null; p++) { Ch.Meta["P" + PParam.Id] = PParam.GetValue("Value"); PParam = ChParam.Parameter(p.ToString()); } Vol.Chapters.Add(Ch); string ChLocation = SRoot + MVolHash + "/" + MChHash + ".txt"; if (Shared.Storage.FileExists(ChLocation)) { ChapterContent ChCont = new ChapterContent() { Chapter = Ch, }; ChCont.Data.BytesValue = Shared.Storage.GetBytes(ChLocation); Shared.BooksDb.ChapterContents.Add(ChCont); } ChParam = VolParam.Parameter("EpInst" + (++ei)); } Entry.Volumes.Add(Vol); VolParam = TOCDefs.Parameter("VolInst" + (++vi)); } SpiderBook SBk = await SpiderBook.CreateSAsync(ZoneId, ZItemId, MetaDefs.Parameter("Procedures")); // Preserve the process state XParameter ProcState = MetaDefs.Parameter("ProcessState"); if (ProcState != null) { SBk.PSettings.SetParameter(ProcState); } SBk.PSettings.Save(); return(Entry); }