Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 217 additions & 10 deletions baseunits/uFavoritesManager.pas
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ TFavoriteThread = class(TBaseThread)
protected
procedure Execute; override;
procedure DoCheck;
procedure DoCheckMissing;
public
FContainer: TfavoriteContainer;
constructor Create(const ATask: TFavoriteTask);
Expand All @@ -49,6 +50,7 @@ TFavoriteTask = class(TBaseThread)
FManager: TFavoriteManager;
FCS_Threads: TRTLCriticalSection;
FCS_GetNext: TRTLCriticalSection;
FCheckMissing: Boolean;
protected
procedure DoCustomTerminate(Sender: TObject);
procedure TimerRepaintOnTimer(Sender: TObject);
Expand All @@ -63,7 +65,7 @@ TFavoriteTask = class(TBaseThread)
procedure RemoveThread(const T: TFavoriteThread);
public
procedure UpdateBtnCaption(Cap: String);
constructor Create(const AManager: TFavoriteManager);
constructor Create(const AManager: TFavoriteManager; const ACheckMissing: Boolean = False);
destructor Destroy; override;
end;

Expand Down Expand Up @@ -128,6 +130,7 @@ TFavoriteManager = class

//Check favorites
procedure CheckForNewChapter(FavoriteIndex: Integer = -1);
procedure CheckForMissingChapters(FavoriteIndex: Integer = -1);
procedure StopChekForNewChapter(WaitFor: Boolean = True; FavoriteIndex: Integer = -1);

// Show notification form after checking completed
Expand Down Expand Up @@ -173,6 +176,9 @@ TFavoriteManager = class
RS_DlgNewChapterCaption = 'Found new chapter(s)';
RS_LblNewChapterFound = 'Found %d new chapter from %d manga(s):';
RS_FavoriteHasNewChapter = '%s <%s> has %d new chapter(s).';
RS_DlgMissingChapterCaption = 'Found missing chapter(s)';
RS_LblMissingChapterFound = 'Found %d missing chapter(s) from %d manga(s):';
RS_FavoriteHasMissingChapter = '%s <%s> has %d missing chapter(s).';
RS_BtnDownload = '&Download';
RS_BtnAddToQueue = '&Add to queue';
RS_BtnCancel = '&Cancel';
Expand Down Expand Up @@ -297,7 +303,10 @@ procedure TFavoriteThread.Execute;
begin
while FTask.GetNext(FContainer) do
begin
DoCheck;
if FTask.FCheckMissing then
DoCheckMissing
else
DoCheck;

if Terminated then
begin
Expand Down Expand Up @@ -385,6 +394,141 @@ procedure TFavoriteThread.DoCheck;
end;
end;

procedure TFavoriteThread.DoCheckMissing;
var
i: Integer;
chapterName, chapterPath, savePath, ext: String;
sr: TSearchRec;
cbzCount, zipCount, pdfCount, epubCount, dirCount, maxCount, detectedFormat: Integer;
chapterExists: Boolean;
begin
if FContainer.FavoriteInfo.Link = '' then Exit;

FContainer.Status := STATUS_CHECKING;
FTask.UpdateStatus;

with FContainer do
try
FMangaInformation.HTTP.Reset;
FMangaInformation.MangaInfo.Clear;
FMangaInformation.Module := FavoriteInfo.Module;
FMangaInformation.isGetByUpdater := False;
// get manga info from site
FMangaInformation.GetInfoFromURL(FavoriteInfo.Link);
if not Terminated then
begin
FreeAndNil(NewMangaInfo);
FreeAndNil(NewMangaInfoChaptersPos);
NewMangaInfo := FMangaInformation.MangaInfo.Clone;
NewMangaInfoChaptersPos := TCardinalList.Create;
// update current chapter count immediately
FavoriteInfo.CurrentChapter := IntToStr(NewMangaInfo.ChapterLinks.Count);
FavoriteInfo.Status := NewMangaInfo.Status;
if NewMangaInfo.ChapterLinks.Count > 0 then
begin
// detect format by counting existing chapter files in SaveTo
savePath := IncludeTrailingPathDelimiter(FavoriteInfo.SaveTo);
cbzCount := 0;
zipCount := 0;
pdfCount := 0;
epubCount := 0;
dirCount := 0;
if FindFirst(savePath + '*', faAnyFile, sr) = 0 then
try
repeat
if (sr.Name = '.') or (sr.Name = '..') then Continue;
if (sr.Attr and faDirectory) <> 0 then
Inc(dirCount)
else
begin
ext := LowerCase(ExtractFileExt(sr.Name));
if ext = '.cbz' then Inc(cbzCount)
else if ext = '.zip' then Inc(zipCount)
else if ext = '.pdf' then Inc(pdfCount)
else if ext = '.epub' then Inc(epubCount);
end;
until FindNext(sr) <> 0;
finally
FindClose(sr);
end;

// fall back to the app setting when SaveTo has no existing chapters yet
if (cbzCount + zipCount + pdfCount + epubCount + dirCount) = 0 then
detectedFormat := FTask.FManager.DLManager.CompressType
else
begin
detectedFormat := 0;
maxCount := dirCount;
if cbzCount > maxCount then
begin
maxCount := cbzCount;
detectedFormat := 2;
end;
if zipCount > maxCount then
begin
maxCount := zipCount;
detectedFormat := 1;
end;
if pdfCount > maxCount then
begin
maxCount := pdfCount;
detectedFormat := 3;
end;
if epubCount > maxCount then
detectedFormat := 4;
end;

for i := 0 to NewMangaInfo.ChapterLinks.Count - 1 do
begin
chapterName := CustomRename(
OptionChapterCustomRename,
FavoriteInfo.Website,
FavoriteInfo.Title,
NewMangaInfo.Authors,
NewMangaInfo.Artists,
NewMangaInfo.ChapterNames[i],
Format('%.4d', [i + 1]),
OptionChangeUnicodeCharacter,
OptionChangeUnicodeCharacterStr);
chapterPath := savePath + chapterName;

case detectedFormat of
1: chapterExists := FileExists(chapterPath + '.zip');
2: chapterExists := FileExists(chapterPath + '.cbz');
3: chapterExists := FileExists(chapterPath + '.pdf');
4: chapterExists := FileExists(chapterPath + '.epub');
else chapterExists := DirectoryExists(chapterPath);
end;

// a folder when format is compressed = images downloaded but compression
// failed or was interrupted; treat as missing so it re-downloads cleanly
if chapterExists and (detectedFormat > 0) and DirectoryExists(chapterPath) then
chapterExists := False;

if not chapterExists then
NewMangaInfoChaptersPos.Add(i);
end;
end;

if not Terminated then
begin
FContainer.FavoriteInfo.DateLastChecked := Now;
if NewMangaInfoChaptersPos.Count <> 0 then
FContainer.FavoriteInfo.DateLastUpdated := Now;
end;

if NewMangaInfoChaptersPos.Count = 0 then
begin
FreeAndNil(NewMangaInfo);
FreeAndNil(NewMangaInfoChaptersPos);
end;
end;
except
on E: Exception do
ExceptionHandle(Self, E);
end;
end;

constructor TFavoriteThread.Create(const ATask: TFavoriteTask);
begin
inherited Create(False);
Expand Down Expand Up @@ -531,8 +675,9 @@ procedure TFavoriteTask.UpdateBtnCaption(Cap: String);
Synchronize(SyncUpdateBtnCaption);
end;

constructor TFavoriteTask.Create(const AManager: TFavoriteManager);
constructor TFavoriteTask.Create(const AManager: TFavoriteManager; const ACheckMissing: Boolean);
begin
FCheckMissing := ACheckMissing;
inherited Create(False);
FManager := AManager;
OnCustomTerminate := DoCustomTerminate;
Expand Down Expand Up @@ -735,6 +880,52 @@ procedure TFavoriteManager.CheckForNewChapter(FavoriteIndex: Integer);
end;
end;

procedure TFavoriteManager.CheckForMissingChapters(FavoriteIndex: Integer);
var
i: Integer;
toCheckCount: Integer;
begin
if isDlgCounter then Exit;
if Items.Count = 0 then Exit;
try
toCheckCount := 0;
if FavoriteIndex > -1 then
begin
with Items[FavoriteIndex] do
if Assigned(FavoriteInfo.Module) and FEnabled and (Status = STATUS_IDLE) then
begin
Status := STATUS_CHECK;
Inc(toCheckCount);
if Assigned(TaskThread) then
InterLockedIncrement(TaskThread.FPendingCount);
end;
end
else
if isRunning then
CenteredMessageDlg(MainForm, RS_DlgFavoritesCheckIsRunning, mtInformation, [mbOK], 0)
else
begin
EnterCriticalsection(FGuardian);
try
for i := 0 to Items.Count - 1 do
with Items[i] do
if Assigned(FavoriteInfo.Module) and FEnabled and (Status = STATUS_IDLE) and (Trim(FavoriteInfo.Link) <> '') then
begin
Status := STATUS_CHECK;
Inc(toCheckCount);
end;
finally
LeaveCriticalsection(FGuardian);
end;
end;
if (toCheckCount > 0) and (TaskThread = nil) then
TaskThread := TFavoriteTask.Create(Self, True);
except
on E: Exception do
ExceptionHandle(Self, E);
end;
end;

procedure TFavoriteManager.StopChekForNewChapter(WaitFor: Boolean; FavoriteIndex: Integer);
begin
if not isRunning then Exit;
Expand Down Expand Up @@ -769,12 +960,14 @@ procedure TFavoriteManager.ShowResult;
LNCResult: TNewChapterResult = ncrCancel;
newChapterListStr: String = '';
removeListStr: String = '';
isMissingCheck: Boolean;
begin
if isDlgCounter then Exit;
if (Self.DLManager = nil) and Assigned(DLManager) then
Self.DLManager := DLManager;
if Self.DLManager = nil then Exit;

isMissingCheck := Assigned(TaskThread) and TaskThread.FCheckMissing;
Self.Sort(Self.FSortColumn);
Lock;
try
Expand All @@ -789,12 +982,17 @@ procedure TFavoriteManager.ShowResult;
begin
if Assigned(NewMangaInfo) then
begin
// new chapters add to notification
// new/missing chapters add to notification
if NewMangaInfoChaptersPos.Count > 0 then
begin
newChapterListStr += LineEnding + '- ' + Format(
RS_FavoriteHasNewChapter, [FavoriteInfo.Title, FavoriteInfo.Website,
NewMangaInfoChaptersPos.Count]);
if isMissingCheck then
newChapterListStr += LineEnding + '- ' + Format(
RS_FavoriteHasMissingChapter, [FavoriteInfo.Title, FavoriteInfo.Website,
NewMangaInfoChaptersPos.Count])
else
newChapterListStr += LineEnding + '- ' + Format(
RS_FavoriteHasNewChapter, [FavoriteInfo.Title, FavoriteInfo.Website,
NewMangaInfoChaptersPos.Count]);
Inc(numOfMangaNewChapters);
Inc(numOfNewChapters, NewMangaInfoChaptersPos.Count);
end
Expand Down Expand Up @@ -854,9 +1052,18 @@ procedure TFavoriteManager.ShowResult;
else
with TNewChapter.Create(MainForm) do
try
Caption := RS_DlgNewChapterCaption;
lbNotification.Caption :=
Format(RS_LblNewChapterFound, [numOfNewChapters, numOfMangaNewChapters]);
if isMissingCheck then
begin
Caption := RS_DlgMissingChapterCaption;
lbNotification.Caption :=
Format(RS_LblMissingChapterFound, [numOfNewChapters, numOfMangaNewChapters]);
end
else
begin
Caption := RS_DlgNewChapterCaption;
lbNotification.Caption :=
Format(RS_LblNewChapterFound, [numOfNewChapters, numOfMangaNewChapters]);
end;
mmMemo.Lines.Text := Trim(newChapterListStr);
btDownload.Caption := RS_BtnDownload;
btQueue.Caption := RS_BtnAddToQueue;
Expand Down
5 changes: 5 additions & 0 deletions mangadownloader/forms/frmMain.lfm
Original file line number Diff line number Diff line change
Expand Up @@ -5684,6 +5684,11 @@ object MainForm: TMainForm
ImageIndex = 21
OnClick = miFavoritesCheckNewChapterClick
end
object miFavoritesCheckMissingChapters: TMenuItem
Caption = 'Check for missing chapters'
ImageIndex = 21
OnClick = miFavoritesCheckMissingChaptersClick
end
object miFavoritesStopCheckNewChapter: TMenuItem
Caption = 'Stop check for new chapter'
ImageIndex = 7
Expand Down
20 changes: 20 additions & 0 deletions mangadownloader/forms/frmMain.pas
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ TMainForm = class(TForm)
TransferRateToolset: TChartToolset;
miFavoritesStopCheckNewChapter: TMenuItem;
miFavoritesCheckNewChapter: TMenuItem;
miFavoritesCheckMissingChapters: TMenuItem;
pnDownloadToolbarLeft: TPanel;
pnDownloadToolbar: TPanel;
TransferRateGraphArea: TAreaSeries;
Expand Down Expand Up @@ -581,6 +582,7 @@ TMainForm = class(TForm)
procedure miDownloadDeleteTaskClick(Sender: TObject);
procedure miDownloadMergeCompletedClick(Sender: TObject);
procedure miFavoritesCheckNewChapterClick(Sender: TObject);
procedure miFavoritesCheckMissingChaptersClick(Sender: TObject);
procedure miFavoritesDownloadAllClick(Sender: TObject);
procedure miFavoritesStopCheckNewChapterClick(Sender: TObject);
procedure miFavoritesViewInfosClick(Sender: TObject);
Expand Down Expand Up @@ -2396,6 +2398,24 @@ procedure TMainForm.miFavoritesCheckNewChapterClick(Sender: TObject);
end;
end;

procedure TMainForm.miFavoritesCheckMissingChaptersClick(Sender: TObject);
var
xNode: PVirtualNode;
begin
if vtFavorites.SelectedCount > 0 then
begin
xNode := vtFavorites.GetFirstSelected;
repeat
if Assigned(xNode) then
begin
FavoriteManager.CheckForMissingChapters(xNode^.Index);
xNode := vtFavorites.GetNextSelected(xNode);
end;
until xNode = nil;
vtFavorites.Repaint;
end;
end;

procedure TMainForm.miFavoritesDownloadAllClick(Sender: TObject);
var
i: Integer;
Expand Down