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.