diff --git a/baseunits/WebsiteModules.pas b/baseunits/WebsiteModules.pas index c8da2289d..50d33a9a3 100644 --- a/baseunits/WebsiteModules.pas +++ b/baseunits/WebsiteModules.pas @@ -59,6 +59,7 @@ TModuleContainer = class; TOnLogin = function(const AHTTP: THTTPSendThread; const AModule: TModuleContainer): Boolean; TOnAccountState = function(const AModule: TModuleContainer): Boolean; + TOnCheckSite = function(const AModule: TModuleContainer): Boolean; TModuleMethod = (MMGetDirectoryPageNumber, MMGetNameAndLink, MMGetInfo, MMTaskStart, MMGetPageNumber, MMGetImageURL, MMBeforeDownloadImage, @@ -149,6 +150,7 @@ TModuleContainer = class OnAfterImageSaved: TOnAfterImageSaved; OnLogin: TOnLogin; OnAccountState: TOnAccountState; + OnCheckSite: TOnCheckSite; constructor Create; destructor Destroy; override; public diff --git a/baseunits/lua/LuaMangaCheck.pas b/baseunits/lua/LuaMangaCheck.pas new file mode 100644 index 000000000..bf3357152 --- /dev/null +++ b/baseunits/lua/LuaMangaCheck.pas @@ -0,0 +1,40 @@ +unit LuaMangaCheck; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, {$ifdef luajit}lua{$else}{$ifdef lua54}lua54{$else}lua53{$endif}{$endif}; + +procedure luaMangaCheckAddMetaTable(const L: Plua_State; const Obj: Pointer; + const MetaTable, UserData: Integer); + +implementation + +uses + uBaseUnit, LuaClass, LuaStrings; + +procedure luaMangaCheckAddMetaTable(const L: Plua_State; const Obj: Pointer; + const MetaTable, UserData: Integer); +begin + with TMangaCheck(Obj) do + begin + luaClassAddStringProperty(L, MetaTable, 'MangaURL', @MangaURL); + luaClassAddStringProperty(L, MetaTable, 'MangaTitle', @MangaTitle); + luaClassAddStringProperty(L, MetaTable, 'ChapterURL', @ChapterURL); + luaClassAddStringProperty(L, MetaTable, 'ChapterURLPrefix', + @ChapterURLPrefix); + luaClassAddStringProperty(L, MetaTable, 'ChapterTitle', @ChapterTitle); + luaClassAddBooleanProperty(L, MetaTable, 'MangaURLAddRootHost', + @MangaURLAddRootHost); + luaClassAddBooleanProperty(L, MetaTable, 'ChapterURLAddRootHost', + @ChapterURLAddRootHost); + end; +end; + +initialization + luaClassRegister(TMangaCheck, @luaMangaCheckAddMetaTable); + +end. + diff --git a/baseunits/lua/LuaWebsiteModules.pas b/baseunits/lua/LuaWebsiteModules.pas index c75ecd18d..c5183c06e 100644 --- a/baseunits/lua/LuaWebsiteModules.pas +++ b/baseunits/lua/LuaWebsiteModules.pas @@ -30,6 +30,7 @@ TLuaWebsiteModule = class OnAfterImageSaved: String; OnLogin: String; OnAccountState: String; + OnCheckSite: String; Storage: TStringsStorage; LastUpdated: String; Container: TLuaWebsiteModulesContainer; @@ -143,7 +144,7 @@ implementation uses FMDOptions, FileUtil, MultiLog, LuaClass, LuaBase, LuaMangaInfo, LuaHTTPSend, LuaXQuery, LuaUtils, LuaDownloadTask, LuaUpdateListManager, LuaStrings, - LuaCriticalSection, LuaPackage, uData, + LuaCriticalSection, LuaPackage, uData, LuaMangaCheck, uDownloadsManager, xquery, httpsendthread, FMDVars, uBaseUnit, LuaWebsiteBypass, LuaWebsiteModuleHandler; @@ -445,6 +446,24 @@ function DoAccountState(const AModule: TModuleContainer): Boolean; end; end; +function DoCheckSite(const AModule: TModuleContainer): Boolean; +var + L: TLuaWebsiteModuleHandler; +begin + Result := False; + with TLuaWebsiteModule(AModule.LuaModule) do + try + L := GetLuaWebsiteModuleHandler(AModule); + LuaPushAccountStatus(L.Handle); + + L.CallFunction(OnCheckSite); + Result := lua_toboolean(L.Handle, -1); + except + on E: Exception do + SendLogException('LUA>DoCheckSite("' + ExtractFileName(Container.FileName) + '")>', E); + end; +end; + function _newwebsitemodule(L: Plua_State): Integer; cdecl; begin luaClassPushObject(L, TLuaWebsiteModule.Create, '', False, @luaWebsiteModuleAddMetaTable); @@ -560,6 +579,8 @@ procedure TLuaWebsiteModulesLoaderThread.LoadLuaWebsiteModule( Module.OnLogin := @DoLogin; if OnAccountState <> '' then Module.OnAccountState := @DoAccountState; + if OnCheckSite <> '' then + Module.OnCheckSite := @DoCheckSite; end; finally Modules.Unlock; @@ -1002,6 +1023,7 @@ procedure luaWebsiteModuleAddMetaTable(const L: Plua_State; const Obj: Pointer; luaClassAddStringProperty(L, MetaTable, 'OnAccountState', @OnAccountState); luaClassAddStringProperty(L, MetaTable, 'LastUpdated', @LastUpdated); luaClassAddIntegerProperty(L, MetaTable, 'CurrentDirectoryIndex', @Module.CurrentDirectoryIndex); + luaClassAddStringProperty(L, MetaTable, 'OnCheckSite', @OnCheckSite); luaClassAddProperty(L, MetaTable, UserData, 'TotalDirectory', @lua_gettotaldirectory, @lua_settotaldirectory); luaClassAddProperty(L, MetaTable, UserData, 'AccountSupport', @lua_getaccountsupport, @lua_setaccountsupport); diff --git a/baseunits/uBaseUnit.pas b/baseunits/uBaseUnit.pas index 6321214dc..06378cb31 100644 --- a/baseunits/uBaseUnit.pas +++ b/baseunits/uBaseUnit.pas @@ -344,6 +344,30 @@ TMangaInfo = class function Clone: TMangaInfo; end; + PMangaCheck = ^TMangaCheck; + + { TMangaCheck } + + TMangaCheck = class + public + MangaURL, + MangaTitle, + ChapterURL, + ChapterTitle, + ChapterURLPrefix: String; + TestToCheck: Integer; + MangaURLAddRootHost: Boolean; + ChapterURLAddRootHost: Boolean; + Module: Pointer; + constructor Create; + destructor Destroy; override; + function ModuleID: String; inline; + function ModuleName: String; inline; + function ModuleFilename: String; inline; + procedure Clear; + function Clone: TMangaCheck; + end; + PDownloadInfo = ^TDownloadInfo; { TDownloadInfo } @@ -638,7 +662,8 @@ procedure SendLogException(const AText: String; AException: Exception); inline; implementation uses - frmMain, WebsiteModules, webp, DCPrijndael, DCPsha512, FPWriteJPEG; + frmMain, WebsiteModules, webp, DCPrijndael, DCPsha512, FPWriteJPEG, + LuaWebsiteModules; {$IFDEF WINDOWS} // thanks Leledumbo for the code @@ -3013,6 +3038,53 @@ function TMangaInfo.Clone: TMangaInfo; Result.Module := Module; end; +{ TMangaCheck } + +constructor TMangaCheck.Create; +begin + inherited Create; + ChapterURLPrefix := ''; + MangaURLAddRootHost := True; + ChapterURLAddRootHost := True; +end; + +destructor TMangaCheck.Destroy; +begin + inherited Destroy; +end; +function TMangaCheck.ModuleID: String; +begin + Result := TModuleContainer(Module).ID; +end; +function TMangaCheck.ModuleName: String; +begin + Result := TModuleContainer(Module).Name; +end; +function TMangaCheck.ModuleFilename: String; +begin + Result := ExtractFileName(TLuaWebsiteModule( + TModuleContainer(Module).LuaModule).Container.FileName); +end; + +procedure TMangaCheck.Clear; +begin + MangaURL := ''; + MangaTitle := ''; + ChapterURL := ''; + ChapterTitle := ''; + Module := nil; +end; + +function TMangaCheck.Clone: TMangaCheck; +begin + Result := TMangaCheck.Create; + Result.MangaURL := MangaURL; + Result.MangaTitle := MangaTitle; + Result.ChapterURL := ChapterURL; + Result.ChapterTitle := ChapterTitle; + Result.Module := Module; +end; + constructor TDownloadPageThread.Create(CreateSuspended: Boolean); begin inherited Create(CreateSuspended); diff --git a/baseunits/uData.pas b/baseunits/uData.pas index 2204c49b9..363bcac4e 100644 --- a/baseunits/uData.pas +++ b/baseunits/uData.pas @@ -28,6 +28,7 @@ TMangaInformation = class(TObject) public HTTP: THTTPSendThread; MangaInfo: TMangaInfo; + MangaCheck: TMangaCheck; isGetByUpdater: Boolean; isGenerateFolderChapterName: Boolean; isRemoveUnicode: Boolean; @@ -58,6 +59,7 @@ constructor TMangaInformation.Create(const AOwnerThread: TBaseThread); FOwner := AOwnerThread; HTTP := THTTPSendThread.Create(AOwnerThread); MangaInfo := TMangaInfo.Create; + MangaCheck := TMangaCheck.Create; isGetByUpdater := False; isRemoveHostFromChapterLinks := True; end; @@ -66,6 +68,8 @@ destructor TMangaInformation.Destroy; begin if Assigned(MangaInfo) then MangaInfo.Free; + if Assigned(MangaCheck) then + MangaCheck.Free; HTTP.Free; inherited Destroy; end; diff --git a/lua/modules/KDTScans.lua b/lua/modules/KDTScans.lua index 5a17df4dc..15de9de40 100644 --- a/lua/modules/KDTScans.lua +++ b/lua/modules/KDTScans.lua @@ -12,6 +12,7 @@ function Init() m.OnGetInfo = 'GetInfo' m.OnGetPageNumber = 'GetPageNumber' m.OnBeforeDownloadImage = 'BeforeDownloadImage' + m.OnCheckSite = 'CheckSite' end ---------------------------------------------------------------------------------------------------- @@ -24,6 +25,13 @@ local Template = require 'templates.MangaThemesia' -- Event Functions ---------------------------------------------------------------------------------------------------- +function CheckSite() + MANGACHECK.MangaURL = "https://www.silentquill.net/the-rise-of-the-errand-boy-who-was-kicked-out-of-the-guild-worlds-strongest-with-ultra-versatile-living-skills/" + MANGACHECK.MangaTitle = 'The Rise of the Errand Boy Who was Kicked Out of the Guild: World’s Strongest with Ultra-Versatile Living Skills' + MANGACHECK.ChapterURL = "https://www.silentquill.net/the-rise-of-the-errand-boy-who-was-kicked-out-of-the-guild-worlds-strongest-with-ultra-versatile-living-skills-ch-1/" + MANGACHECK.ChapterTitle = 'Chapter 1' +end + -- Get links and names from the manga list of the current website. function GetNameAndLink() Template.GetNameAndLink() diff --git a/lua/modules/WeebCentral.lua b/lua/modules/WeebCentral.lua index a070bef64..07f158ca3 100644 --- a/lua/modules/WeebCentral.lua +++ b/lua/modules/WeebCentral.lua @@ -16,6 +16,7 @@ function Init() m.MaxTaskLimit = 2 m.MaxConnectionLimit = 4 m.SortedList = true + m.OnCheckSite = 'CheckSite' end ---------------------------------------------------------------------------------------------------- @@ -28,7 +29,12 @@ local DirectoryPageLimit = 32 ---------------------------------------------------------------------------------------------------- -- Event Functions ---------------------------------------------------------------------------------------------------- - +function CheckSite() + MANGACHECK.MangaURL = "/series/01J76XYGGM22WZP7T4TKA4ZFAF/Kagurabachi" + MANGACHECK.MangaTitle = 'Kagurabachi' + MANGACHECK.ChapterURL = "/chapters/01K4JBY7YN9XEZ35F5GECH6ZWP" + MANGACHECK.ChapterTitle = 'Chapter 92.5' +end -- Get the page count of the manga list of the current website. function GetDirectoryPageNumber() local u = MODULE.RootURL .. DirectoryPagination .. 0 diff --git a/mangadownloader/forms/frmAccountManager.lfm b/mangadownloader/forms/frmAccountManager.lfm index fa2079dcb..add900258 100644 --- a/mangadownloader/forms/frmAccountManager.lfm +++ b/mangadownloader/forms/frmAccountManager.lfm @@ -130,7 +130,7 @@ object AccountManagerForm: TAccountManagerForm Colors.FocusedSelectionBorderColor = clHotLight Colors.SelectionRectangleBorderColor = clHotLight Colors.UnfocusedSelectionBorderColor = clBtnShadow - Header.AutoSizeIndex = 0 + Header.AutoSizeIndex = -1 Header.Columns = < item MinWidth = 25 @@ -149,10 +149,11 @@ object AccountManagerForm: TAccountManagerForm item Position = 3 Text = 'Status' + Width = 174 end> Header.DefaultHeight = 17 Header.Height = 23 - Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible] + Header.Options = [hoAutoResize, hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible] NodeDataSize = 1 TabOrder = 0 TreeOptions.AutoOptions = [toAutoDropExpand, toAutoScrollOnExpand, toAutoTristateTracking, toAutoDeleteMovedNodes, toDisableAutoscrollOnFocus] diff --git a/mangadownloader/forms/frmCheckModules.lfm b/mangadownloader/forms/frmCheckModules.lfm new file mode 100644 index 000000000..e915aa5cd --- /dev/null +++ b/mangadownloader/forms/frmCheckModules.lfm @@ -0,0 +1,268 @@ +object FormCheckModules: TFormCheckModules + Left = 402 + Height = 600 + Top = 182 + Width = 900 + Caption = 'Check Modules' + ClientHeight = 600 + ClientWidth = 900 + LCLVersion = '4.4.0.0' + OnCreate = FormCreate + OnDestroy = FormDestroy + OnShow = FormShow + object pnlFilter: TPanel + Left = 0 + Height = 32 + Top = 24 + Width = 900 + Align = alTop + BevelOuter = bvNone + ClientHeight = 32 + ClientWidth = 900 + TabOrder = 4 + object edtFilter: TCustomEditButton + Left = 0 + Height = 23 + Top = 5 + Width = 300 + ButtonWidth = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000064000000640000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00000000010000 + 00070000000E00000014000000190000001A0000001900000017000000150000 + 00120000000E0000000B00000008000000050000000200000001000000020000 + 000D0000001B000000280000003100000033001A3064002D57CC002C56CC0018 + 305D0000001C000000160000000F0000000A0000000400000001000000000000 + 0000000000000000000001131F0000214048002B55CC5494B7FF34679AFF0030 + 5ACA00224248000D170000000000000000000000000000000000000000000000 + 00000116210000214000014D7C41014B79BB3A719FFF386F9DFF5F9FC0FF4578 + ABFF003763C600356046002D4E00010101000000000000000000013048000021 + 400001568600002B5548002B55CC4F8DB3FF68ACC8FF4880ACFF5087B3FF6AAA + C8FF5588BBFF00416EC1003E6A440101010001385B0001263D00015F9000002B + 55000157873F015585B65FA1C0FF3F79A3FF4278A7FF66A6C5FF619DC2FF5E95 + C1FF74B4D1FF6598CBFF010101AB0101013C014B7900014B7A00015F9000002B + 5548002B55CC336898FF508CB3FF69ABC8FF67A7C6FF4D80B3FF71B1CEFF6EA9 + CDFF6CA3CEFF6D6D6DFFAA9999FF010101A5014C7A42014B7A000160913E015E + 8FB16AAEC9FF66A8C5FF5692B8FF4B80AFFF5D97BFFF77B9D2FF669DC8FF7BBA + D5FF7E7E7EFFCEC0C0FF797979FF5588BBFF014F7EA6014E7D0001629383126D + 9BB82078A2C33385ABD058A2C0E774B9D1FB6EACCCFF669DC8FF83C7DAFF8888 + 88FFD3CACAFF838383FF60A4C6FF63A7C9FF015382A501528100016395050163 + 9414016293280161924101619277106C9AAB4B9BBADB79B9D5FC919191FFD9D4 + D4FF8D8D8DFF68ACCEFF74B8D4FF015887B40156864001558400016395000163 + 9400016293000161920001629300016293100162936D00000069DDDCDCFF9494 + 94FF70B4D6FF80C4DBFF015C8DB2001A63CC0013584800226E00016395000163 + 94000162930001619200016293000162930001639400000000240000006788CC + DDFF87CBDDFF016091AF003080CC3F72B6FF002774CC00247048016395000163 + 940001629300016192000162930001629300016394000000000001334C390165 + 969C0164959C0163943E00398B48003688CC5285C9FF002E7ECC016395000163 + 940001629300016192000162930001629300016394000000000001334C000165 + 97000164960001639400003A8C00003E9248003C8FCC00378A48FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + MaxLength = 0 + NumGlyphs = 1 + PasswordChar = #0 + TabOrder = 0 + TextHint = 'Type to filter modules...' + OnButtonClick = edtFilterButtonClick + OnChange = edtFilterChange + end + end + object lvModules: TListView + Left = 0 + Height = 344 + Top = 56 + Width = 900 + Align = alClient + AutoWidthLastColumn = True + Checkboxes = True + Columns = <> + TabOrder = 1 + ViewStyle = vsReport + end + object pnlTop: TPanel + Left = 0 + Height = 24 + Top = 0 + Width = 900 + Align = alTop + BevelOuter = bvNone + ClientHeight = 24 + ClientWidth = 900 + TabOrder = 0 + object tbCheckModules: TToolBar + Left = 0 + Height = 26 + Top = 0 + Width = 900 + Images = imlCheckModules + List = True + ShowCaptions = True + TabOrder = 0 + object tbWebsitesSelectAll: TToolButton + Left = 381 + Top = 2 + AutoSize = True + Caption = 'Select All' + ImageIndex = 0 + OnClick = tbWebsitesSelectAllClick + end + object tbWebsitesSelectInverse: TToolButton + Left = 458 + Top = 2 + AutoSize = True + Caption = 'Inverse Selection' + ImageIndex = 1 + OnClick = tbWebsitesSelectInverseClick + end + object tbWebsitesSelectNone: TToolButton + Left = 575 + Top = 2 + AutoSize = True + Caption = 'Select None' + ImageIndex = 2 + OnClick = tbWebsitesSelectNoneClick + end + object btnStopCheck: TToolButton + Left = 292 + Top = 2 + AutoSize = True + Caption = 'Stop Check' + Enabled = False + ImageIndex = 5 + OnClick = btnStopCheckClick + end + object btnCheckIntegrity: TToolButton + Left = 134 + Top = 2 + AutoSize = True + Caption = 'Check Modules Integrity' + ImageIndex = 4 + OnClick = btnCheckIntegrityClick + end + object btnRefreshModules: TToolButton + Left = 1 + Top = 2 + AutoSize = True + Caption = 'Refresh Module List' + ImageIndex = 3 + OnClick = btnRefreshModulesClick + end + end + end + object sptCheckModules: TSplitter + Cursor = crVSplit + Left = 0 + Height = 5 + Top = 400 + Width = 900 + Align = alBottom + ResizeAnchor = akBottom + end + object memCheckModules: TMemo + Left = 0 + Height = 174 + Top = 405 + Width = 900 + Align = alBottom + ReadOnly = True + ScrollBars = ssVertical + TabOrder = 2 + end + object pnlBottom: TPanel + Left = 0 + Height = 21 + Top = 579 + Width = 900 + Align = alBottom + BevelOuter = bvNone + ClientHeight = 21 + ClientWidth = 900 + TabOrder = 3 + object StatusBar: TStatusBar + Left = 0 + Height = 23 + Top = -2 + Width = 900 + Panels = <> + end + end + object imlCheckModules: TImageList + Left = 856 + Top = 576 + Bitmap = { + 4C7A0600000010000000100000006F0800000000000078DAED97695454471680 + 0B641144A011193080D08851181D149421A3E2C2E8C864408371217644503C66 + C431B40B4631EE88460D28E0A0B68A1201C32E5BD3415189A80F48ABA02C8D06 + 32E891887A46A33D73E0CEBDAF9BC8265B3239F9913AE7ABF7DEADFAAA5E55D7 + 3DDD0D000C7E02A6098C0D4D64064393981891225C0F48F9BEE890AB46EC5A38 + 4211787F9E72F5BF44D096A0EF16B763D93D1FE5C40B760A7278379E47BAACD6 + 47B9A4C20B7A835F95B7921C7287C4F1702B6AE7C382D2996FC4B3D00DE6164F + E5EFFDEE780339E49A4878388A79154DEE128F7C67A072B64EC23F2F2C9B05E4 + 902B88E5E17CE5B36156C14498923586BF4ECB7302D7D49130E68C25D4D5D541 + 7D7D3D3C78F000464A86825BFA2820875CE3681EEE7DCE0326653AC2AB57AF60 + 4C8225D8C59980F084006A6B6B79BFA1A101841201084F09E0F7496F0139E41A + 45F270EF5D9B068977E2A0BCBC1C1A1B1B4118DFC13D8D6E928A51A9BF0372C8 + 35DCCFC34DBBEC04762926BC5F5555D5DE4D40EFFC6BECB34C811C720787F370 + E3BEB6016101B6277798179FF9781BEC0A4C801C720D76F2708EDC3010160B54 + 6408546E86E075AC03E490AB1FCA23B5BF3E542994635B2BD96DEE3B60536CA4 + 24875C4D2BC6748298D82472A0C28633560A2BB14F370CE78C94C691BA0A72C8 + C562A261C89C353DD90E4D1193215C0FC8A82F39E4227A881932AC8F90A307BF + E5FF2F92FFB8D760337A78BFF2DFCACA0A2C2D2DC1DCDCBCC7FCD7D5D56D97FF + B6B6B6BC6F6161D163FED3FB39383880A9A9299FFFEDDC5EE63FF9F6F6F6EDDD + 3EE67F3BB79FF9CFBBBFE5FFFF3DFF19C3246489068C25891129C2F58054D597 + 9C04B59F207670B8AA080878A20C0A7A016F62D5AAE7E0EFDFA41C3DBA48418E + CA8D27A47E7EDF2B3FF8A01E7AC70325392A378EE0FCFD1F81B7F71D1E2AADF7 + 5DC57C7DEB801C952B21388A4D9F7E1DDA167AEE2AE6E55501E4A8DC58829B33 + E72EB8BA5E003BBB737CBF972F5FC2C3870FF9EFC2EAEA6A50281420101C0533 + B393E0E89805E4A8DC6882F3F4BC09CECEF930766C2E0C1972024A4B4B412E97 + 43454505D4D4D4A02B414EF158597D09E4A8DC48829B39B314468ECCC2DC3F87 + 7D92DAB9F45D4CB156CCCDD3801C95BB9FE05C5CAE8289C9796C3FDFC9A5EFE2 + 478F1EF16D84A9693690A372C3094E282CC6B6820EEF9CCC436E5353130FF531 + 3129007254EE4E82B3B42CC5361A2343ED66A89F553195FB3A468ECA0D25A466 + 66379402811C5464C3EBFBCE3123A36225392A979238483C70E02185B1318763 + 5442771819714A5DDD4805392A9772D81073D97307632219C2F5804CD5D7F067 + C97FD645099F3796793B0ED5DDBC708AD576BF99B601D3461B50AEEB69B06ECB + 1ACF3F301F0743ADD3616B661725FFF35CF95709772B646714579322F2E277AD + 5AE437C94E77BD8F1B0B796FC28FB4966DA2E92C70B2956E5AF4F6CDB72EA436 + 7D5B227BD9585ED8FCBCFA123CBB9D0D3505275FA41C08DEE63DCA5067F96C37 + EDDDCB66BB6C5EF08E2DB9340EBDDFE1B58B5764C4861564C6867D783434F08F + C9919B3EAAF8EA8BAAA7B773E1993C05AAA5B1FF8EDFB16287346ACD89CC83AB + B92DBEEE0EADFE8639CE23B62E9EBA67EF4773AD330F8730D76183D9930A19C3 + 71DE29979EBAF7549E068F6FC4B7D4E67EDE7C2F7D0BE446FC3DE96D1DA64DEE + F249D66CFD1C67B7B57F73B25EE73D9E6D98EBC2A2D78BD816DF297A924F57FC + F96A7294BC498E67903B0B8D578E4075CA9696B85051E0E5139BF9BEFC9E077A + 4E3D1222F2FC54E461FDA7B7066905B859181CFCC7FC8DD7D28FD53F28CB8127 + B7B2E049E939785C2C81D284AD0D6101331DF706FE85ADF31AC74630A69D1919 + 9C54991BF5DFB2F4433585F1FB5253233FD918BB296011321FEF3FC6D899D2F4 + C3B72A73637EC88B09C99C65A3A38BEFCC762E99C170DDF6D74E6FAA7BFCF531 + 682A4984273733E16159365CCF38FE30227851D84A771B131DC63442E64F368B + D9209ABC77C5BBEE2267534D7AF7EC43C1EC78C8A2A577BFDCD4DC78290A1E5F + 8F8726793A14A74455E2DABDB68AA60D2E4A93F0EB5CE73D8EE11E59E0BC533F + 99E7AA417B678DEF7EFEC0CA84DAD450A8CEFAACF9FB6BA75B9E7C930215F9A7 + 1A8E8506CE80FFDC631E42018BDBB69CED5EFEAEF9A7BEEE7B702CA7D6B3B369 + C12487E4BD2BAF6747041D97842E0DBD931DFDECE937C9F014CF4CB9ECCCBD73 + 0737AE8E0959EA9A12B575615ACCCEFCC860DFF5FC5A5AFDF7DD866F5FE2E1F4 + E17467ADE9C398766278D0E62AD9F1E7CF70BF9F57174263F9C5E6FB9CF4879B + 05294FD36276848BFF3A76D02EFF593F9EDBDC2D7399F6004DBAA54ACBC9D2C8 + 2062ADC83FFF64D895B22C4943594E5C7DFE99085964C8B2C5E3AD8D06531F75 + DFB685324B1BD1470C11818DE960DBD913DF9EE0314EE86C66A0634D31C40819 + 84E8743146FF0AFCCCBCC0FA5BA401E98FCF615D87D0B5A61F635CC0FA3B3545 + C8FD3E8E918D752552AD7665C8ED3E8C918AF54D35B7D564A9C7EC8DFF05D6D7 + DA70032945285ED28B3124585F440AD55C5443EB4AEC851F85750E92ABBE9297 + 8EC423577AE1EFC73A4D0DED4512128B5CEEE5FA77637D56BDDE53C821F5FBF7 + 76FF69FE38F59CE1C8853E7EFE34E7516497FAB3EFEBF9AB57AF3BBF9FE7FF97 + E65752B4B4D68D37360EFBD8C22242DC1D02C19E606DED0DE33BFA868661C113 + 276637FBF8C861DEBC9B6D6969BD625B8B9B5B5EB340F05970475F2038287677 + BF81FF2F1E434040D750DB8C19A5F8FB355ADCD1D7D3DB2F160A2F818B4B2D4C + 98D035D466675704FAFA873AF99A9AFBC4FAFA52FC7D28EF167D7D190C181021 + EEBC83FBC41A1A39A0A15182706F80DAF25A18FBBC4B9FB11C3C112508D70D79 + D07FBFA4079FDAE43D2043BA5AFF018C15615B3D52F706A88D7EFB1FEEC20FC3 + 3391D3DC61BE96CEF34B31B63FB8B34F6792CED51171F71CC03E1B9D7F2D79F7 + 3FE490224D + } + end +end diff --git a/mangadownloader/forms/frmCheckModules.lrj b/mangadownloader/forms/frmCheckModules.lrj new file mode 100644 index 000000000..bfd68803e --- /dev/null +++ b/mangadownloader/forms/frmCheckModules.lrj @@ -0,0 +1,10 @@ +{"version":1,"strings":[ +{"hash":196100051,"name":"tformcheckmodules.caption","sourcebytes":[67,104,101,99,107,32,77,111,100,117,108,101,115],"value":"Check Modules"}, +{"hash":184680222,"name":"tformcheckmodules.edtfilter.texthint","sourcebytes":[84,121,112,101,32,116,111,32,102,105,108,116,101,114,32,109,111,100,117,108,101,115,46,46,46],"value":"Type to filter modules..."}, +{"hash":195288076,"name":"tformcheckmodules.tbwebsitesselectall.caption","sourcebytes":[83,101,108,101,99,116,32,65,108,108],"value":"Select All"}, +{"hash":192785374,"name":"tformcheckmodules.tbwebsitesselectinverse.caption","sourcebytes":[73,110,118,101,114,115,101,32,83,101,108,101,99,116,105,111,110],"value":"Inverse Selection"}, +{"hash":171874549,"name":"tformcheckmodules.tbwebsitesselectnone.caption","sourcebytes":[83,101,108,101,99,116,32,78,111,110,101],"value":"Select None"}, +{"hash":38551803,"name":"tformcheckmodules.btnstopcheck.caption","sourcebytes":[83,116,111,112,32,67,104,101,99,107],"value":"Stop Check"}, +{"hash":90280153,"name":"tformcheckmodules.btncheckintegrity.caption","sourcebytes":[67,104,101,99,107,32,77,111,100,117,108,101,115,32,73,110,116,101,103,114,105,116,121],"value":"Check Modules Integrity"}, +{"hash":24971044,"name":"tformcheckmodules.btnrefreshmodules.caption","sourcebytes":[82,101,102,114,101,115,104,32,77,111,100,117,108,101,32,76,105,115,116],"value":"Refresh Module List"} +]} diff --git a/mangadownloader/forms/frmCheckModules.pas b/mangadownloader/forms/frmCheckModules.pas new file mode 100644 index 000000000..5167ab820 --- /dev/null +++ b/mangadownloader/forms/frmCheckModules.pas @@ -0,0 +1,1179 @@ +unit frmCheckModules; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, + ComCtrls, Buttons, uCustomControls, WebsiteModules, LuaMangaInfo, + LuaMangaCheck, LuaHTTPSend, LuaWebsiteModuleHandler, LuaWebsiteModules, uData, + LuaUtils, uBaseUnit, uDownloadsManager, LuaDownloadTask, httpsendthread, + StrUtils, frmCustomMessageDlg, StatusBarDownload, + {$ifdef luajit}lua{$else}{$ifdef lua54}lua54{$else}lua53{$endif}{$endif}; + +type + TTestResult = record + Success: Boolean; + Message: string; + Data: string; + MangaTitle: string; + ChapterTitle: string; + end; + + TModuleScanThread = class; + TModuleCheckThread = class; + + { TFormCheckModules } + TFormCheckModules = class(TForm) + btnCheckIntegrity: TToolButton; + btnRefreshModules: TToolButton; + btnStopCheck: TToolButton; + edtFilter: TCustomEditButton; + imlCheckModules: TImageList; + lvModules: TListView; + pnlTop: TPanel; + pnlFilter: TPanel; // Add this line + pnlBottom: TPanel; + StatusBar: TStatusBar; + memCheckModules: TMemo; + sptCheckModules: TSplitter; + tbWebsitesSelectAll: TToolButton; + tbWebsitesSelectInverse: TToolButton; + tbWebsitesSelectNone: TToolButton; + tbCheckModules: TToolBar; + procedure btnCheckIntegrityClick(Sender: TObject); + procedure btnRefreshModulesClick(Sender: TObject); + procedure btnStopCheckClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormShow(Sender: TObject); + procedure FormDestroy(Sender: TObject); + procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); + procedure tbWebsitesSelectAllClick(Sender: TObject); + procedure tbWebsitesSelectInverseClick(Sender: TObject); + procedure tbWebsitesSelectNoneClick(Sender: TObject); + procedure UpdateProgress; + procedure edtFilterChange(Sender: TObject); // Add this line + procedure edtFilterButtonClick(Sender: TObject); + private + FIsScanning: Boolean; + FIsChecking: Boolean; + FCheckedCount: Integer; + FSuccessCount: Integer; + FFailCount: Integer; + FModulesList: TList; + FScanThread: TModuleScanThread; + FCheckThread: TModuleCheckThread; + FFilterText: string; + procedure FilterModules; + procedure InitializeListView; + procedure ScanLuaModules; + procedure CheckModuleIntegrity; + function CalcTotalToCheck: Integer; + procedure SetModuleSelection(AChecked: Boolean; AInverse: Boolean = False); + procedure AddModuleToList(const AMangaCheck: TMangaInformation); + function TestGetInfo(const AMangaCheck: TMangaInformation): TTestResult; + function TestGetPageNumber( + const AMangaCheck: TMangaInformation): TTestResult; + function MaybeFillPrefix(const Prefix, URL: String): String; + procedure LogMessage(const AMsg: string); + procedure EnableStopCheck(const AEnable: Boolean); + procedure ClearModulesList; + procedure UpdateItemStatus(AItem: TListItem; + const AStatus, ADetails: string); + // Thread callbacks + procedure OnScanComplete(Sender: TObject); + procedure OnScanProgress(const AMsg: string; + AModule: TMangaInformation); + procedure OnCheckComplete(Sender: TObject); + procedure OnCheckProgress(AIndex: Integer; const AStatus, ADetails, + AMsg: string); + public + end; + + { TModuleScanThread } + TModuleScanThread = class(TThread) + private + FForm: TFormCheckModules; + FProgressMsg: string; + FProgressModule: TMangaInformation; + FModuleCount: Integer; + procedure SyncProgress; + procedure SyncComplete; + protected + procedure Execute; override; + public + constructor Create(AForm: TFormCheckModules); + end; + + { TModuleCheckThread } + TModuleCheckThread = class(TStatusBarDownload) + private + FForm: TFormCheckModules; + FProgressIndex: Integer; + PCheckedCount: PInteger; // Pointer to the integer + FProgressStatus: string; + FProgressDetails: string; + FProgressMsg: string; + PSuccessCount: PInteger; // Pointer to the integer + PFailCount: PInteger; // Pointer to the integer + procedure SyncProgress; + procedure SyncComplete; + protected + procedure Execute; override; + procedure CallUpdateProgress; // Wrapper for Synchronize + public + constructor Create(AForm: TFormCheckModules); + procedure LinkVariable(ACheckedCountPtr, ASuccessCountPtr, + AFailCountPtr: PInteger); + end; + +var + FormCheckModules: TFormCheckModules; + +implementation + +uses + FileUtil, LazUTF8, LazFileUtils, frmMain; + +{$R *.lfm} + +{ TModuleScanThread } + +constructor TModuleScanThread.Create(AForm: TFormCheckModules); +begin + inherited Create(True); + FForm := AForm; + FModuleCount := 0; + FreeOnTerminate := True; +end; + +procedure TModuleScanThread.SyncProgress; +begin + if Assigned(FProgressModule) then + FForm.OnScanProgress(FProgressMsg, FProgressModule); +end; + +procedure TModuleScanThread.SyncComplete; +begin + FForm.OnScanComplete(Self); +end; + +procedure TModuleScanThread.Execute; +var + i: Integer; + L: TLuaWebsiteModuleHandler; + AMangaCheck: TMangaInformation; +begin + try + if Modules = nil then + begin + FProgressMsg := 'Warning: No modules loaded'; + Synchronize(@SyncProgress); + Exit; + end; + + for i := 0 to Modules.Count - 1 do + begin + if Terminated then Break; + + with Modules.List[i] do + begin + if not Assigned(OnCheckSite) then + Continue; + + AMangaCheck := nil; + with TLuaWebsiteModule(LuaModule) do + try + begin + L := GetLuaWebsiteModuleHandler(Modules.List[i]); + LuaPushNetStatus(L.Handle); + AMangaCheck := TMangaInformation.Create(); + AMangaCheck.MangaCheck.TestToCheck := 0; + AMangaCheck.MangaCheck.Module := Modules.List[i]; + L.LoadObject('MANGACHECK', AMangaCheck.MangaCheck, + @luaMangaCheckAddMetaTable); + L.CallFunction(OnCheckSite); + + with AMangaCheck.MangaCheck do + begin + if MangaURL <> '' then + begin + if AMangaCheck.MangaCheck.MangaURLAddRootHost then + MangaURL := MaybeFillHost(RootURL, MangaURL); + Inc(AMangaCheck.MangaCheck.TestToCheck); + if MangaTitle <> '' then + begin + Inc(AMangaCheck.MangaCheck.TestToCheck); + end; + end; + if ChapterURL <> '' then + begin + if AMangaCheck.MangaCheck.ChapterURLPrefix <> '' then + ChapterURL := FForm.MaybeFillPrefix( + AMangaCheck.MangaCheck.ChapterURLPrefix, ChapterURL) + else + ChapterURL := AppendURLDelimLeft(ChapterURL); + + if AMangaCheck.MangaCheck.ChapterURLAddRootHost then + ChapterURL := MaybeFillHost(RootURL, ChapterURL); + Inc(AMangaCheck.MangaCheck.TestToCheck); + if ChapterTitle <> '' then + begin + Inc(AMangaCheck.MangaCheck.TestToCheck); + end; + end; + + if (MangaURL <> '') or (ChapterURL <> '') then + begin + AMangaCheck.MangaInfo.URL := MangaURL; + Inc(FModuleCount); + FProgressMsg := Format('Found: %s (CheckSite: %s, CheckChapter: %s)', + [ModuleName, + IfThen(MangaURL <> '', 'Yes' + IfThen(MangaTitle <> '', + ' with Title', ' without Title'), 'No'), + IfThen(ChapterURL <> '', 'Yes' + IfThen(ChapterTitle <> '', + ' with Title', ' without Title'), 'No')]); + FProgressModule := AMangaCheck; + Synchronize(@SyncProgress); + end + else + AMangaCheck.Free; + end; + end; + except + on E: Exception do + begin + FProgressMsg := 'Error loading module ' + + ExtractFileName(Container.FileName) + ': ' + E.Message; + FProgressModule := nil; + Synchronize(@SyncProgress); + if Assigned(AMangaCheck) then + AMangaCheck.Free; + end; + end; + end; + end; + + if not Terminated then + begin + FProgressMsg := Format('Scan complete: Found %d modules with check data', + [FModuleCount]); + FProgressModule := nil; + Synchronize(@SyncProgress); + end; + finally + Synchronize(@SyncComplete); + end; +end; + +{ TModuleCheckThread } + +constructor TModuleCheckThread.Create(AForm: TFormCheckModules); +begin + inherited Create(False, frmMain.MainForm, AForm.imlCheckModules, 16); + FForm := AForm; + FreeOnTerminate := True; +end; + +procedure TModuleCheckThread.SyncProgress; +var + i, TotalToCheck: Integer; + Item: TListItem; + AMangaCheck: TMangaInformation; +begin + TotalToCheck := 0; + for i := 0 to FForm.lvModules.Items.Count - 1 do + begin + Item := FForm.lvModules.Items[i]; + if not Item.Checked then Continue; + + AMangaCheck := TMangaInformation(Item.Data); + TotalToCheck := TotalToCheck + AMangaCheck.MangaCheck.TestToCheck; + end; + + FForm.OnCheckProgress(FProgressIndex, FProgressStatus, FProgressDetails, + FProgressMsg); + UpdateProgressBar(PCheckedCount^ ,TotalToCheck); + UpdateStatusText(Format('Checking: %d/%d (Success: %d, Failed: %d)', + [PCheckedCount^ ,TotalToCheck, PSuccessCount^, PFailCount^])); +end; + +procedure TModuleCheckThread.SyncComplete; +begin + FForm.OnCheckComplete(Self); +end; + +procedure TModuleCheckThread.LinkVariable(ACheckedCountPtr, + ASuccessCountPtr, AFailCountPtr: PInteger); +begin + // Store the address + PCheckedCount := ACheckedCountPtr; + PSuccessCount := ASuccessCountPtr; + PFailCount := AFailCountPtr; +end; + +procedure TModuleCheckThread.CallUpdateProgress; +begin + FForm.UpdateProgress; +end; + +procedure TModuleCheckThread.Execute; +var + i: Integer; + Item: TListItem; + AMangaCheck: TMangaInformation; + GetInfoResult, GetPageResult: TTestResult; + Details, ExtraDetails: string; + AllTestsPassed: Boolean; +begin + try + FProgressMsg := '=== Starting Integrity Check ==='; + PCheckedCount^ := 0; + FProgressIndex := -1; + PSuccessCount^ := 0; + PFailCount^ := 0; + Synchronize(@SyncProgress); + + for i := 0 to FForm.lvModules.Items.Count - 1 do + begin + if Terminated then Break; + + Item := FForm.lvModules.Items[i]; + if not Item.Checked then Continue; + + AMangaCheck := TMangaInformation(Item.Data); + if AMangaCheck = nil then Continue; + + Details := ''; + ExtraDetails := ''; + AllTestsPassed := True; + FProgressIndex := i; + + // Update status to "Checking..." + FProgressStatus := 'Checking...'; + FProgressDetails := ''; + FProgressMsg := 'Checking module: ' + AMangaCheck.MangaCheck.ModuleName; + Synchronize(@SyncProgress); + + try + // Test GetInfo if MangaURL exists + if AMangaCheck.MangaCheck.MangaURL <> '' then + begin + FProgressMsg := ' Testing GetInfo with: ' + + AMangaCheck.MangaCheck.MangaURL; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + + GetInfoResult := FForm.TestGetInfo(AMangaCheck); + + if GetInfoResult.Success then + begin + Details := 'OnGetInfo: PASS'; + Inc(PSuccessCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + FProgressMsg := ' OnGetInfo: PASS - ' + GetInfoResult.Message; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + + // Validate manga title if provided + if AMangaCheck.MangaCheck.MangaTitle <> '' then + begin + FProgressMsg := ' Testing Manga Title with: ' + + AMangaCheck.MangaCheck.MangaTitle; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + + if AMangaCheck.MangaCheck.MangaTitle + = GetInfoResult.MangaTitle then + begin + Inc(PSuccessCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + ExtraDetails := ' | Extra Test Check Manga Title: PASS'; + FProgressMsg := ' Check Manga Title: PASS'; + end + else + begin + Inc(PFailCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + ExtraDetails := ' | Extra Test Check Manga Title: FAIL'; + FProgressMsg := Format(' Check Manga Title: FAIL -' + + ' Returned "%s" vs Expected "%s"', + [GetInfoResult.MangaTitle, + AMangaCheck.MangaCheck.MangaTitle]); + end; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + end; + + // Validate chapter title if provided + if (AMangaCheck.MangaCheck.ChapterURL <> '') and + (AMangaCheck.MangaCheck.ChapterTitle <> '') then + begin + FProgressMsg := ' Testing Chapter Title with: ' + + AMangaCheck.MangaCheck.ChapterTitle; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + + if not ContainsStr(GetInfoResult.ChapterTitle, + 'Don''t Match Any Chapter URL') then + begin + if AMangaCheck.MangaCheck.ChapterTitle + = GetInfoResult.ChapterTitle then + begin + Inc(PSuccessCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + ExtraDetails := ExtraDetails + + ' | Extra Test Check Chapter Title: PASS'; + FProgressMsg := ' Check Chapter Title: PASS'; + end + else + begin + Inc(PFailCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + ExtraDetails := ExtraDetails + + ' | Extra Test Check Chapter Title: FAIL'; + FProgressMsg := Format(' Check Chapter Title: FAIL -' + + ' Returned "%s" vs Expected "%s"', + [GetInfoResult.ChapterTitle, + AMangaCheck.MangaCheck.ChapterTitle]); + end; + end + else + begin + Inc(PFailCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + ExtraDetails := ExtraDetails + + ' | Extra Test Check Chapter Title: FAIL'; + FProgressMsg := ' Check Chapter Title: FAIL - ' + + GetInfoResult.ChapterTitle; + end; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + end + else if AMangaCheck.MangaCheck.ChapterURL = '' then + begin + FProgressMsg := ' No chapter link provided,' + + ' using first chapter link'; + AMangaCheck.MangaCheck.ChapterURL := GetInfoResult.Data; + FProgressIndex := -1; + Inc(AMangaCheck.MangaCheck.TestToCheck); + Synchronize(@SyncProgress); + FProgressIndex := i; + end; + end + else + begin + Details := 'OnGetInfo: FAIL (' + GetInfoResult.Message + ')'; + Inc(PFailCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + AllTestsPassed := False; + FProgressMsg := ' OnGetInfo: FAIL - ' + GetInfoResult.Message; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + end; + end; + + // Test GetPageNumber if ChapterURL exists + if AMangaCheck.MangaCheck.ChapterURL <> '' then + begin + if Details <> '' then + Details := Details + ' | '; + + FProgressMsg := ' Testing GetPageNumber with: ' + + AMangaCheck.MangaCheck.ChapterURL; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + + GetPageResult := FForm.TestGetPageNumber(AMangaCheck); + + if GetPageResult.Success then + begin + Details := Details + 'OnGetPageNumber: PASS'; + Inc(PSuccessCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + FProgressMsg := ' OnGetPageNumber: PASS - ' + + GetPageResult.Message; + end + else + begin + Details := Details + 'OnGetPageNumber: FAIL (' + + GetPageResult.Message + ')'; + Inc(PFailCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + AllTestsPassed := False; + FProgressMsg := ' OnGetPageNumber: FAIL - ' + + GetPageResult.Message; + end; + FProgressIndex := -1; + Synchronize(@SyncProgress); + FProgressIndex := i; + end; + + // Update final status + FProgressMsg := ''; //clear FProgressMsg befoer Update final status + if AllTestsPassed then + begin + if (ExtraDetails = '') or not ContainsStr(ExtraDetails, 'FAIL') then + FProgressStatus := 'PASSED' + else + FProgressStatus := 'PASSED (FAILED Extra Tests)'; + end + else + FProgressStatus := 'FAILED'; + + FProgressDetails := Details + ExtraDetails; + Synchronize(@SyncProgress); + + except + on E: Exception do + begin + FProgressStatus := 'ERROR'; + FProgressDetails := 'Exception: ' + E.Message; + FProgressMsg := ' ERROR: ' + E.Message; + Inc(PFailCount^); + Inc(PCheckedCount^); + Queue(@CallUpdateProgress); + Synchronize(@SyncProgress); + end; + end; + end; + + if not Terminated then + begin + FProgressMsg := '=== Check Complete ==='; + FProgressIndex := -1; + Synchronize(@SyncProgress); + + FProgressMsg := Format('Total tests passed: %d', [PSuccessCount^]); + Synchronize(@SyncProgress); + + FProgressMsg := Format('Total tests failed: %d', [PFailCount^]); + Synchronize(@SyncProgress); + end; + finally + Synchronize(@SyncComplete); + end; +end; + +{ TFormCheckModules } + +procedure TFormCheckModules.FormCreate(Sender: TObject); +begin + FIsScanning := False; + FIsChecking := False; + FCheckedCount := 0; + FSuccessCount := 0; + FFailCount := 0; + FFilterText := ''; // Add this line + FModulesList := TList.Create; + FScanThread := nil; + FCheckThread := nil; + InitializeListView; + memCheckModules.Clear; + memCheckModules.ScrollBars := ssVertical; + memCheckModules.ReadOnly := True; +end; + +procedure TFormCheckModules.InitializeListView; +begin + lvModules.ViewStyle := vsReport; + lvModules.RowSelect := True; + lvModules.GridLines := True; + lvModules.Columns.Clear; + + with lvModules.Columns.Add do + begin + Caption := 'Module Name'; + Width := 180; + AutoSize := True; + end; + + with lvModules.Columns.Add do + begin + Caption := 'Filename'; + Width := 180; + AutoSize := True; + end; + + with lvModules.Columns.Add do + begin + Caption := 'CheckSite'; + Width := 80; + end; + + with lvModules.Columns.Add do + begin + Caption := 'CheckChapter'; + Width := 90; + end; + + with lvModules.Columns.Add do + begin + Caption := 'Status'; + Width := 250; + end; + + with lvModules.Columns.Add do + begin + Caption := 'Details'; + Width := 250; + end; +end; + +procedure TFormCheckModules.FormShow(Sender: TObject); +begin + // User should explicitly click refresh +end; + +procedure TFormCheckModules.FormDestroy(Sender: TObject); +begin + // Terminate threads if running + if Assigned(FScanThread) then + begin + FScanThread.Terminate; + FScanThread.WaitFor; + end; + if Assigned(FCheckThread) then + begin + FCheckThread.Terminate; + FCheckThread.WaitFor; + end; + + ClearModulesList; + FModulesList.Free; +end; + +procedure TFormCheckModules.FormCloseQuery(Sender: TObject; + var CanClose: Boolean); +begin + if FIsScanning or FIsChecking then + begin + CanClose := CenteredMessageDlg(frmMain.MainForm, + 'An operation is in progress. Are you sure you want to close?', + mtConfirmation, [mbYes, mbNo], 0) = mrYes; + + if CanClose then + begin + if Assigned(FScanThread) then + FScanThread.Terminate; + if Assigned(FCheckThread) then + FCheckThread.Terminate; + end; + end + else + CanClose := True; +end; + +procedure TFormCheckModules.tbWebsitesSelectAllClick(Sender: TObject); +begin + SetModuleSelection(True); +end; + +procedure TFormCheckModules.tbWebsitesSelectInverseClick(Sender: TObject); +begin + SetModuleSelection(False, True); +end; + +procedure TFormCheckModules.tbWebsitesSelectNoneClick(Sender: TObject); +begin + SetModuleSelection(False); +end; + +procedure TFormCheckModules.ClearModulesList; +var + i: Integer; +begin + for i := 0 to FModulesList.Count - 1 do + TMangaInformation(FModulesList[i]).Free; + FModulesList.Clear; +end; + +procedure TFormCheckModules.LogMessage(const AMsg: string); +begin + memCheckModules.Lines.Add(FormatDateTime('hh:nn:ss', Now) + ' - ' + AMsg); +end; + +procedure TFormCheckModules.EnableStopCheck(const AEnable: Boolean); +begin + if AEnable then + begin + btnStopCheck.Enabled := True; + btnRefreshModules.Enabled := False; + btnCheckIntegrity.Enabled := False; + tbWebsitesSelectAll.Enabled := False; + tbWebsitesSelectInverse.Enabled := False; + tbWebsitesSelectNone.Enabled := False; + end + else + begin + btnStopCheck.Enabled := False; + btnRefreshModules.Enabled := True; + btnCheckIntegrity.Enabled := True; + tbWebsitesSelectAll.Enabled := True; + tbWebsitesSelectInverse.Enabled := True; + tbWebsitesSelectNone.Enabled := True; + end; +end; + +procedure TFormCheckModules.ScanLuaModules; +begin + if FIsScanning then + begin + CenteredMessageDlg(frmMain.MainForm, 'A scan is already in progress.', + mtInformation, [mbOK], 0); + Exit; + end; + + FIsScanning := True; + EnableStopCheck(True); + memCheckModules.Clear; + + lvModules.Items.BeginUpdate; + try + lvModules.Clear; + ClearModulesList; + finally + lvModules.Items.EndUpdate; + end; + + LogMessage('Scanning loaded modules...'); + + FScanThread := TModuleScanThread.Create(Self); + FScanThread.Start; +end; + +procedure TFormCheckModules.OnScanProgress(const AMsg: string; + AModule: TMangaInformation); +begin + LogMessage(AMsg); + if Assigned(AModule) then + AddModuleToList(AModule); +end; + +procedure TFormCheckModules.OnScanComplete(Sender: TObject); +begin + FIsScanning := False; + FScanThread := nil; + EnableStopCheck(False); + StatusBar.SimpleText := Format('Scan complete: %d modules found', + [lvModules.Items.Count]); +end; + +procedure TFormCheckModules.AddModuleToList(const AMangaCheck: + TMangaInformation); +var + Item: TListItem; +begin + Item := lvModules.Items.Add; + Item.Caption := AMangaCheck.MangaCheck.ModuleName; + Item.SubItems.Add(AMangaCheck.MangaCheck.ModuleFilename); + Item.SubItems.Add(IfThen(AMangaCheck.MangaCheck.MangaURL <> '', + 'Yes' + IfThen(AMangaCheck.MangaCheck.MangaTitle <> '', ' with Title', + ' without Title'), 'No')); + Item.SubItems.Add(IfThen(AMangaCheck.MangaCheck.ChapterURL <> '', + 'Yes' + IfThen(AMangaCheck.MangaCheck.ChapterTitle <> '', ' with Title', + ' without Title'), 'No')); + Item.SubItems.Add('Not Checked'); + Item.SubItems.Add(''); + Item.Checked := True; + Item.Data := AMangaCheck; + FModulesList.Add(AMangaCheck); + FilterModules; // Refilter to show the new module if it matches +end; + +procedure TFormCheckModules.btnRefreshModulesClick(Sender: TObject); +begin + ScanLuaModules; +end; + +procedure TFormCheckModules.btnCheckIntegrityClick(Sender: TObject); +begin + CheckModuleIntegrity; +end; + +procedure TFormCheckModules.btnStopCheckClick(Sender: TObject); +begin + if not FIsChecking then Exit; + + LogMessage('Stop requested, waiting for active checks to complete...'); + if Assigned(FScanThread) then + begin + FScanThread.Terminate; + FScanThread.WaitFor; + end; + if Assigned(FCheckThread) then + begin + FCheckThread.Terminate; + FCheckThread.WaitFor; + end; +end; + +procedure TFormCheckModules.SetModuleSelection(AChecked: Boolean; + AInverse: Boolean = False); +var + i: Integer; +begin + for i := 0 to lvModules.Items.Count - 1 do + begin + if AInverse then + lvModules.Items[i].Checked := not lvModules.Items[i].Checked + else + lvModules.Items[i].Checked := AChecked; + end; +end; + +procedure TFormCheckModules.UpdateItemStatus(AItem: TListItem; const AStatus, + ADetails: string); +begin + AItem.SubItems[3] := AStatus; + AItem.SubItems[4] := ADetails; +end; + +procedure TFormCheckModules.CheckModuleIntegrity; +var + i: Integer; +begin + if lvModules.Items.Count = 0 then + begin + CenteredMessageDlg(frmMain.MainForm, 'No modules to check.' + + ' Please refresh the module list first.', + mtError, [mbOK], 0); + Exit; + end; + + if FIsChecking then + begin + CenteredMessageDlg(frmMain.MainForm, 'An integrity check is already in progress.', + mtInformation, [mbOK], 0); + Exit; + end; + if CalcTotalToCheck = 0 then + begin + CenteredMessageDlg(frmMain.MainForm, + 'No modules selected. Please check at least one module.', + mtError, [mbOK], 0); + FIsChecking := False; + Exit; + end; + + FIsChecking := True; + EnableStopCheck(True); + + FCheckThread := TModuleCheckThread.Create(Self); + FCheckThread.LinkVariable(@Self.FCheckedCount, + @Self.FSuccessCount, @Self.FFailCount); + FCheckThread.Start; +end; + +procedure TFormCheckModules.OnCheckProgress(AIndex: Integer; + const AStatus, ADetails, AMsg: string); +begin + if AMsg <> '' then + LogMessage(AMsg); + + if AIndex >= 0 then + UpdateItemStatus(lvModules.Items[AIndex], AStatus, ADetails); +end; + +procedure TFormCheckModules.UpdateProgress; +begin + // Progress bar is handled by TStatusBarDownload base class + StatusBar.SimpleText := Format('Checking: %d/%d (Success: %d, Failed: %d)', + [FCheckedCount, CalcTotalToCheck, FSuccessCount, FFailCount]); +end; + +procedure TFormCheckModules.OnCheckComplete(Sender: TObject); +begin + FIsChecking := False; + FCheckThread := nil; + + EnableStopCheck(False); + + StatusBar.SimpleText := Format('Check complete: %d tests passed, %d tests failed', + [FSuccessCount, FFailCount]); + + CenteredMessageDlg(frmMain.MainForm, Format('Integrity check complete.'#13#10 + + 'Tests Passed: %d'#13#10 + + 'Tests Failed: %d', [FSuccessCount, FFailCount]), + mtInformation, [mbOK], 0); +end; + +function TFormCheckModules.CalcTotalToCheck: Integer; +var + i: Integer; + Item: TListItem; + AMangaCheck: TMangaInformation; +begin + Result := 0; + for i := 0 to lvModules.Items.Count - 1 do + begin + Item := lvModules.Items[i]; + if not Item.Checked then Continue; + + AMangaCheck := TMangaInformation(Item.Data); + Result := Result + AMangaCheck.MangaCheck.TestToCheck; + end; +end; + +function TFormCheckModules.TestGetInfo(const AMangaCheck: + TMangaInformation): TTestResult; +var + L: TLuaWebsiteModuleHandler; + ModuleCheck: TModuleContainer; + ChapterIndex, i: Integer; +begin + Result.Success := False; + Result.Message := 'Unknown error'; + Result.Data := ''; + Result.MangaTitle := ''; + Result.ChapterTitle := ''; + + ModuleCheck := Modules.LocateModule(AMangaCheck.MangaCheck.ModuleID); + if ModuleCheck = nil then + begin + Result.Message := 'Module not found in loaded modules'; + Exit; + end; + + try + with TLuaWebsiteModule(ModuleCheck.LuaModule) do + begin + L := GetLuaWebsiteModuleHandler(ModuleCheck); + luaPushStringGlobal(L.Handle, 'URL', AMangaCheck.MangaCheck.MangaURL); + LuaPushNetStatus(L.Handle); + + L.LoadObject('MANGAINFO', AMangaCheck.MangaInfo, @luaMangaInfoAddMetaTable); + L.LoadObject('HTTP', AMangaCheck.HTTP, @luaHTTPSendThreadAddMetaTable); + + L.CallFunction(OnGetInfo); + + if lua_tointeger(L.Handle, -1) <> 0 then + begin + Result.Message := 'Runtime error: ' + lua_tostring(L, -1); + lua_pop(L, 2); + Exit; + end; + + if lua_isboolean(L, -1) and lua_toboolean(L, -1) then + begin + if AMangaCheck.MangaInfo.Title = '' then + begin + Result.Message := 'OnGetInfo returned true, but no title found'; + Exit; + end; + + if AMangaCheck.MangaInfo.ChapterLinks.Count = 0 then + begin + Result.Message := 'OnGetInfo returned true, but no chapters found'; + Exit; + end + else + begin + if AMangaCheck.MangaCheck.ChapterURLPrefix <> '' then + begin + for i := 0 to AMangaCheck.MangaInfo.ChapterLinks.Count - 1 do + begin + AMangaCheck.MangaInfo.ChapterLinks[i] := + MaybeFillPrefix(AMangaCheck.MangaCheck.ChapterURLPrefix, + AMangaCheck.MangaInfo.ChapterLinks[i]) + end; + end + else + begin + for i := 0 to AMangaCheck.MangaInfo.ChapterLinks.Count - 1 do + begin + AMangaCheck.MangaInfo.ChapterLinks[i] := AppendURLDelimLeft( + AMangaCheck.MangaInfo.ChapterLinks[i]) + end; + end; + if AMangaCheck.MangaCheck.ChapterURLAddRootHost then + begin + for i := 0 to AMangaCheck.MangaInfo.ChapterLinks.Count - 1 do + begin + AMangaCheck.MangaInfo.ChapterLinks[i] := + MaybeFillHost(GetHostURL(AMangaCheck.MangaInfo.URL), + AMangaCheck.MangaInfo.ChapterLinks[i]); + end; + end; + end; + + Result.Success := True; + Result.Message := 'Success'; + Result.MangaTitle := AMangaCheck.MangaInfo.Title; + + if AMangaCheck.MangaCheck.ChapterURL = '' then + Result.Data := AMangaCheck.MangaInfo.ChapterLinks[0] + else + begin + ChapterIndex := AMangaCheck.MangaInfo.ChapterLinks.IndexOf( + AMangaCheck.MangaCheck.ChapterURL); + if ChapterIndex <> -1 then + Result.ChapterTitle := AMangaCheck.MangaInfo.ChapterNames[ChapterIndex] + else + Result.ChapterTitle := AMangaCheck.MangaCheck.ChapterURL + + ' Don''t Match Any Chapter URL'; + end; + end + else + Result.Message := 'OnGetInfo returned false or unexpected type'; + end; + except + on E: Exception do + Result.Message := 'Exception: ' + E.Message; + end; +end; + +function TFormCheckModules.TestGetPageNumber(const AMangaCheck: + TMangaInformation): TTestResult; +var + L: TLuaWebsiteModuleHandler; + ModuleCheck: TModuleContainer; + ATaskContainer: TTaskContainer; +begin + Result.Success := False; + Result.Message := 'Unknown error'; + + ModuleCheck := Modules.LocateModule(AMangaCheck.MangaCheck.ModuleID); + if ModuleCheck = nil then + begin + Result.Message := 'Module not found in loaded modules'; + Exit; + end; + + ATaskContainer := nil; + try + with TLuaWebsiteModule(ModuleCheck.LuaModule) do + begin + L := GetLuaWebsiteModuleHandler(ModuleCheck); + luaPushStringGlobal(L.Handle, 'URL', AMangaCheck.MangaCheck.ChapterURL); + + ATaskContainer := TTaskContainer.Create; + + L.LoadObject('TASK', ATaskContainer, @luaDownloadTaskMetaTable); + L.LoadObject('HTTP', AMangaCheck.HTTP, @luaHTTPSendThreadAddMetaTable); + + L.CallFunction(OnGetPageNumber); + + if lua_tointeger(L.Handle, -1) <> 0 then + begin + Result.Message := 'Runtime error: ' + lua_tostring(L, -1); + lua_pop(L, 2); + Exit; + end; + + if lua_isboolean(L, -1) and lua_toboolean(L, -1) then + begin + if ATaskContainer.PageLinks.Count = 0 then + begin + Result.Message := 'OnGetPageNumber returned true, but no pages found'; + Exit; + end; + + Result.Success := True; + Result.Message := 'Success'; + end + else + Result.Message := 'OnGetPageNumber returned false or unexpected type'; + end; + except + on E: Exception do + Result.Message := 'Exception: ' + E.Message; + end; + + if Assigned(ATaskContainer) then + ATaskContainer.Free; +end; + +function TFormCheckModules.MaybeFillPrefix(const Prefix, URL: String): String; +var + UrlHost, UrlPath: string; +begin + UrlHost := GetHostURL(URL); + UrlPath := RemoveHostFromURL(URL); + if ContainsStr(UrlPath, Prefix) then + begin + Result := UrlHost + UrlPath; + end + else + begin + Result := UrlHost + Prefix + UrlPath; + end; +end; + +procedure TFormCheckModules.FilterModules; +var + i: Integer; + Item: TListItem; + AMangaCheck: TMangaInformation; + FilterLower: string; + ModuleName: string; +begin + if FModulesList.Count = 0 then Exit; + + FilterLower := LowerCase(Trim(FFilterText)); + + lvModules.Items.BeginUpdate; + try + lvModules.Clear; + + for i := 0 to FModulesList.Count - 1 do + begin + AMangaCheck := TMangaInformation(FModulesList[i]); + ModuleName := LowerCase(AMangaCheck.MangaCheck.ModuleName); + + // If filter is empty or module name contains filter text + if (FilterLower = '') or (Pos(FilterLower, ModuleName) > 0) then + begin + Item := lvModules.Items.Add; + Item.Caption := AMangaCheck.MangaCheck.ModuleName; + Item.SubItems.Add(AMangaCheck.MangaCheck.ModuleFilename); + Item.SubItems.Add(IfThen(AMangaCheck.MangaCheck.MangaURL <> '', + 'Yes' + IfThen(AMangaCheck.MangaCheck.MangaTitle <> '', ' with Title', + ' without Title'), 'No')); + Item.SubItems.Add(IfThen(AMangaCheck.MangaCheck.ChapterURL <> '', + 'Yes' + IfThen(AMangaCheck.MangaCheck.ChapterTitle <> '', ' with Title', + ' without Title'), 'No')); + Item.SubItems.Add('Not Checked'); + Item.SubItems.Add(''); + Item.Checked := True; + Item.Data := AMangaCheck; + end; + end; + finally + lvModules.Items.EndUpdate; + end; + + StatusBar.SimpleText := Format('Showing %d of %d modules', + [lvModules.Items.Count, FModulesList.Count]); +end; + +// Add event handler for the filter edit box: +procedure TFormCheckModules.edtFilterChange(Sender: TObject); +begin + FFilterText := TEdit(Sender).Text; + FilterModules; +end; + +procedure TFormCheckModules.edtFilterButtonClick(Sender: TObject); +begin + edtFilter.Clear; +end; +end. diff --git a/mangadownloader/forms/frmLuaModulesUpdater.lfm b/mangadownloader/forms/frmLuaModulesUpdater.lfm index 90397981d..24bb8927f 100644 --- a/mangadownloader/forms/frmLuaModulesUpdater.lfm +++ b/mangadownloader/forms/frmLuaModulesUpdater.lfm @@ -25,7 +25,7 @@ object LuaModulesUpdaterForm: TLuaModulesUpdaterForm Top = 36 Width = 572 Anchors = [akTop, akLeft, akRight, akBottom] - Header.AutoSizeIndex = 0 + Header.AutoSizeIndex = 2 Header.Columns = < item Position = 0 @@ -44,7 +44,7 @@ object LuaModulesUpdaterForm: TLuaModulesUpdaterForm end> Header.DefaultHeight = 17 Header.Height = 23 - Header.Options = [hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible] + Header.Options = [hoAutoResize, hoColumnResize, hoDrag, hoShowSortGlyphs, hoVisible] HintMode = hmHint Images = imStates ParentShowHint = False diff --git a/mangadownloader/forms/frmMain.lfm b/mangadownloader/forms/frmMain.lfm index 8c9b51ce8..7e5ffb756 100644 --- a/mangadownloader/forms/frmMain.lfm +++ b/mangadownloader/forms/frmMain.lfm @@ -4996,6 +4996,9 @@ object MainForm: TMainForm object tsWebsiteModules: TTabSheet Caption = 'Modules' end + object tsWebsiteCheckModules: TTabSheet + Caption = 'Check Modules' + end end end object tsMisc: TTabSheet @@ -5196,6 +5199,16 @@ object MainForm: TMainForm OnButtonClick = edLogFileNameButtonClick PasswordChar = #0 TabOrder = 1 + OnButtonClick = edLogFileNameButtonClick + end + object ckEnableModuleDebug: TCheckBox + Left = 4 + Height = 19 + Top = 136 + Width = 135 + Caption = 'Enable Module Debug' + TabOrder = 4 + OnChange = ckEnableModuleDebugChange end end end diff --git a/mangadownloader/forms/frmMain.lrj b/mangadownloader/forms/frmMain.lrj index a022e736d..ded1f0548 100644 --- a/mangadownloader/forms/frmMain.lrj +++ b/mangadownloader/forms/frmMain.lrj @@ -284,6 +284,7 @@ {"hash":108725763,"name":"tmainform.tswebsiteoptions.caption","sourcebytes":[79,112,116,105,111,110,115],"value":"Options"}, {"hash":197676484,"name":"tmainform.tswebsiteadvanced.caption","sourcebytes":[65,100,118,97,110,99,101,100],"value":"Advanced"}, {"hash":73122451,"name":"tmainform.tswebsitemodules.caption","sourcebytes":[77,111,100,117,108,101,115],"value":"Modules"}, +{"hash":196100051,"name":"tmainform.tswebsitecheckmodules.caption","sourcebytes":[67,104,101,99,107,32,77,111,100,117,108,101,115],"value":"Check Modules"}, {"hash":344211,"name":"tmainform.tsmisc.caption","sourcebytes":[77,105,115,99],"value":"Misc"}, {"hash":197593650,"name":"tmainform.tscustomcolor.caption","sourcebytes":[67,117,115,116,111,109,32,99,111,108,111,114],"value":"Custom color"}, {"hash":21335,"name":"tmainform.tslog.caption","sourcebytes":[76,111,103],"value":"Log"}, @@ -291,6 +292,7 @@ {"hash":120491445,"name":"tmainform.btclearlogfile.caption","sourcebytes":[67,108,101,97,114,32,108,111,103,32,102,105,108,101],"value":"Clear log file"}, {"hash":158118362,"name":"tmainform.lblogfilename.caption","sourcebytes":[76,111,103,32,102,105,108,101,58],"value":"Log file:"}, {"hash":113276983,"name":"tmainform.btopenlog.caption","sourcebytes":[79,112,101,110,32,108,111,103],"value":"Open log"}, +{"hash":248026023,"name":"tmainform.ckenablemoduledebug.caption","sourcebytes":[69,110,97,98,108,101,32,77,111,100,117,108,101,32,68,101,98,117,103],"value":"Enable Module Debug"}, {"hash":4749113,"name":"tmainform.btoptionapply.caption","sourcebytes":[65,112,112,108,121],"value":"Apply"}, {"hash":4691652,"name":"tmainform.tsabout.caption","sourcebytes":[65,98,111,117,116],"value":"About"}, {"hash":101464798,"name":"tmainform.btchecklatestversion.caption","sourcebytes":[67,104,101,99,107,32,102,111,114,32,108,97,116,101,115,116,32,118,101,114,115,105,111,110],"value":"Check for latest version"}, diff --git a/mangadownloader/forms/frmMain.pas b/mangadownloader/forms/frmMain.pas index 5bdd0b995..a58170928 100644 --- a/mangadownloader/forms/frmMain.pas +++ b/mangadownloader/forms/frmMain.pas @@ -26,7 +26,7 @@ interface frmAccountSet, frmWebsiteOptionCustom, frmCustomColor, frmLogger, frmTransferFavorites, frmLuaModulesUpdater, CheckUpdate, DBDataProcess, uDarkStyleParams, uWin32WidgetSetDark, SimpleTranslator, httpsendthread, DateUtils, SimpleException, uCustomControls, - uCustomControlsMultiLog, ImageMagickManager; + uCustomControlsMultiLog, ImageMagickManager, frmCheckModules; type @@ -78,6 +78,7 @@ TMainForm = class(TForm) cbUseRegExpr: TCheckBox; cbOptionProxyType: TComboBox; cbOptionOneInstanceOnly: TCheckBox; + ckEnableModuleDebug: TCheckBox; ckImageMagick: TCheckBox; ckPNGSaveAsJPEG: TCheckBox; ckOptionsAlwaysStartTaskFromFailedChapters: TCheckBox; @@ -212,6 +213,7 @@ TMainForm = class(TForm) seOptionRetryFailedTask: TSpinEdit; seJPEGQuality: TSpinEdit; spThumb: TSplitter; + tsWebsiteCheckModules: TTabSheet; tbWebsitesSelectAll: TToolButton; tbWebsitesUnselectAll: TToolButton; tsAccounts: TTabSheet; @@ -495,6 +497,7 @@ TMainForm = class(TForm) Shift: TShiftState); procedure cbSelectMangaMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); + procedure ckEnableModuleDebugChange(Sender: TObject); procedure ckImageMagickChange(Sender: TObject); procedure clbChapterListBeforeCellPaint(Sender: TBaseVirtualTree; TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; @@ -1340,6 +1343,9 @@ procedure TMainForm.FormCreate(Sender: TObject); LuaModulesUpdaterForm := TLuaModulesUpdaterForm.Create(Self); EmbedForm(LuaModulesUpdaterForm, tsWebsiteModules); + FormCheckModules := TFormCheckModules.Create(Self); + EmbedForm(FormCheckModules, tsWebsiteCheckModules); + // init vt vtDownload.NodeDataSize := SizeOf(TDownloadInfo); vtFavorites.NodeDataSize := SizeOf(TFavoriteInfo); @@ -3004,6 +3010,18 @@ procedure TMainForm.cbSelectMangaMouseDown(Sender: TObject; cbSelectMangaEditingDone(Sender); end; +procedure TMainForm.ckEnableModuleDebugChange(Sender: TObject); +begin + if ckEnableModuleDebug.Checked then + begin + tsWebsiteCheckModules.TabVisible:= True; + end + else + begin + tsWebsiteCheckModules.TabVisible:= False; + end; +end; + procedure TMainForm.ckImageMagickChange(Sender: TObject); begin if ckImageMagick.Checked then @@ -5863,6 +5881,7 @@ procedure TMainForm.LoadOptions; // misc frmCustomColor.LoadFromIniFile(settingsfile); ckEnableLogging.Checked := ReadBool('logger', 'Enabled', False); + ckEnableModuleDebug.Checked := ReadBool('Modules', 'Debug', False); edLogFileName.Text := ReadString('logger', 'LogFileName', ''); if edLogFileName.Text = '' then begin @@ -6045,6 +6064,7 @@ procedure TMainForm.SaveOptions(const AShowDialog: Boolean); // misc frmCustomColor.SaveToIniFile(settingsfile); WriteBool('logger', 'Enabled', ckEnableLogging.Checked); + WriteBool('Modules', 'Debug', ckEnableModuleDebug.Checked); if edLogFileName.Text = '' then begin @@ -6262,6 +6282,15 @@ procedure TMainForm.ApplyOptions; Logger.Enabled := False; end; + if ckEnableModuleDebug.Checked then + begin + tsWebsiteCheckModules.TabVisible:= True; + end + else + begin + tsWebsiteCheckModules.TabVisible:= False; + end; + //languages ApplyLanguage; except diff --git a/mangadownloader/images/checkrev.png b/mangadownloader/images/checkrev.png new file mode 100644 index 000000000..341486e24 Binary files /dev/null and b/mangadownloader/images/checkrev.png differ diff --git a/mangadownloader/md.lpi b/mangadownloader/md.lpi index ac004ad05..317694fb8 100644 --- a/mangadownloader/md.lpi +++ b/mangadownloader/md.lpi @@ -24,8 +24,9 @@ - - + + + @@ -55,7 +56,7 @@ - + @@ -330,6 +331,8 @@ + + @@ -353,7 +356,7 @@ - + @@ -523,6 +526,13 @@ + + + + + + + diff --git a/mangadownloader/md.lpr b/mangadownloader/md.lpr index 8ad5081f9..9cee143c4 100644 --- a/mangadownloader/md.lpr +++ b/mangadownloader/md.lpr @@ -11,11 +11,11 @@ windows, {$endif} Interfaces, // this includes the LCL widgetset - Forms, LazFileUtils, jsonini, simpleipc, sqlite3dyn, uBaseUnit, - FMDVars, webp, CheckUpdate, DBUpdater, SelfUpdater, uDownloadsManager, - LuaWebsiteModules, LuaBase, SimpleException, Classes, sysutils, frmMain, - uDarkStyle, uMetaDarkStyle, uDarkStyleSchemes, uDarkStyleParams, - MultiLog, FileChannel, ssl_openssl3_lib, blcksock, ssl_openssl3, SQLiteData; + Forms, LazFileUtils, jsonini, simpleipc, sqlite3dyn, uBaseUnit, FMDVars, webp, + CheckUpdate, DBUpdater, SelfUpdater, uDownloadsManager, LuaWebsiteModules, + LuaBase, SimpleException, Classes, sysutils, frmMain, frmCheckModules, + uDarkStyle, uMetaDarkStyle, uDarkStyleSchemes, uDarkStyleParams, MultiLog, + FileChannel, ssl_openssl3_lib, blcksock, ssl_openssl3, SQLiteData; var CheckInstance: Boolean = True; @@ -196,7 +196,7 @@ windows.SetEnvironmentVariable('PATH', pchar(evpath)); {$endif} - Application.Title := 'Free Manga Downloader'; + Application.Title:='Free Manga Downloader'; RequireDerivedFormResource := True; //Logger.ThreadSafe := True; //Automatically uses safe thread code Logger.Enabled := EnableLogging; @@ -266,10 +266,11 @@ 2: PreferredAppMode := pamForceLight; end; - Application.Scaled := True; + Application.Scaled:=True; uMetaDarkStyle.ApplyMetaDarkStyle(DefaultDark); Application.Initialize; Application.CreateForm(TMainForm, MainForm); MainForm.winBuildNumber := g_buildNumber; + Application.CreateForm(TFormCheckModules, FormCheckModules); Application.Run; end.