Skip to content

Commit

Permalink
refactor: start to implement prescanner with the one in the scanner #50
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhykos committed Oct 31, 2024
1 parent 7e4c4ef commit 24e7122
Show file tree
Hide file tree
Showing 18 changed files with 172 additions and 154 deletions.
29 changes: 15 additions & 14 deletions src/cli/domain/aggregate/CLI.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
import type { File } from "../../../common/domain/valueobject/File.ts";
import type { Action } from "../valueobject/Action.ts";
import { BlueskyCredentials } from "../valueobject/BlueskyCredentials.ts";
import { BlueskyPublisherAction } from "../valueobject/BlueskyPublisherAction.ts";
import { PreScannerAction } from "../valueobject/PreScannerAction.ts";
import { ScannerAction } from "../valueobject/ScannerAction.ts";

export class CLI {
constructor(
public readonly configuration: File,
public readonly action: Action,
public readonly databaseFilepath = "./db.autophoto.sqlite3",
public readonly debugDatabase = false,
public readonly debug = false,
) {}

static builder() {
return new CLIBuilder();
}
}

class ScannerAction implements Action {
isScan(): boolean {
return true;
}
}

export class CLIBuilder {
private configuration: File | undefined;
private action: Action | undefined;
private databaseFilepath: string | undefined;
private debugDatabase = false;
private debug = false;

withConfiguration(configuration: File) {
this.configuration = configuration;
Expand All @@ -43,12 +39,17 @@ export class CLIBuilder {
}

withBluesky(host: URL, login: string, password: string) {
this.action = new BlueskyCredentials(host, login, password);
this.action = new BlueskyPublisherAction(host, login, password);
return this;
}

withDebug() {
this.debug = true;
return this;
}

withDebugDatabase() {
this.debugDatabase = true;
withPreScanner(configuration: File) {
this.action = new PreScannerAction(configuration);
return this;
}

Expand All @@ -58,14 +59,14 @@ export class CLIBuilder {
}

if (!this.action) {
throw new Error("Action is required: scanner or bluesky publisher");
throw new Error("Action is required: prescanner, publisher or scanner");
}

return new CLI(
this.configuration,
this.action,
this.databaseFilepath,
this.debugDatabase,
this.debug,
);
}
}
8 changes: 7 additions & 1 deletion src/cli/domain/valueobject/Action.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export interface Action {
isScan(): boolean;
type(): ActionType;
}

export enum ActionType {
PRESCANNER = "PRESCANNER",
PUBLISHER = "PUBLISHER",
SCANNER = "SCANNER",
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { DomainError } from "../../../common/domain/DomainError.ts";
import type { ValueObject } from "../../../common/domain/ValueObject.ts";
import type { Action } from "./Action.ts";
import { type Action, ActionType } from "./Action.ts";

export class BlueskyCredentials implements ValueObject, Action {
export class BlueskyPublisherAction implements ValueObject, Action {
constructor(
public readonly host: URL,
public readonly login: string,
Expand All @@ -22,7 +22,7 @@ export class BlueskyCredentials implements ValueObject, Action {
}

equals(other: unknown): boolean {
if (other instanceof BlueskyCredentials) {
if (other instanceof BlueskyPublisherAction) {
return (
this.login === other.login &&
this.password === other.password &&
Expand All @@ -32,7 +32,7 @@ export class BlueskyCredentials implements ValueObject, Action {
return false;
}

isScan(): boolean {
return false;
type(): ActionType {
return ActionType.PUBLISHER;
}
}
10 changes: 10 additions & 0 deletions src/cli/domain/valueobject/PreScannerAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { File } from "../../../common/domain/valueobject/File.ts";
import { type Action, ActionType } from "./Action.ts";

export class PreScannerAction implements Action {
constructor(public readonly configuration: File) {}

type(): ActionType {
return ActionType.PRESCANNER;
}
}
7 changes: 7 additions & 0 deletions src/cli/domain/valueobject/ScannerAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { type Action, ActionType } from "./Action.ts";

export class ScannerAction implements Action {
type(): ActionType {
return ActionType.SCANNER;
}
}
18 changes: 13 additions & 5 deletions src/cli/service/CLIService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ import { CLI, type CLIBuilder } from "../domain/aggregate/CLI.ts";
export class CLIService {
read(cliArgs: string[]): CLI {
const args: Args = parseArgs(cliArgs, {
boolean: ["debug-database", "publish", "scan"],
string: ["bluesky_host", "bluesky_login", "bluesky_passord", "database"],
boolean: ["debug", "publish", "scan"],
string: [
"bluesky_host",
"bluesky_login",
"bluesky_passord",
"database",
"prescan",
],
});

const cliParameters: (string | number)[] = args._;
Expand Down Expand Up @@ -41,8 +47,8 @@ export class CLIService {
.withConfiguration(new File(new Path(filepath)))
.withDatabaseFilepath(databaseFilepath);

if (args["debug-database"] === true) {
cliBuilder.withDebugDatabase();
if (args.debug === true) {
cliBuilder.withDebug();
}

if (args.publish === true) {
Expand All @@ -55,8 +61,10 @@ export class CLIService {
);
} else if (args.scan === true) {
cliBuilder.withScanner();
} else if (args.prescan) {
cliBuilder.withPreScanner(new File(new Path(args.prescan)));
} else {
throw new Error('Missing option: "--scan" or "--publish"');
throw new Error('Missing option: "--prescan" or "--publish" or "--scan"');
}

return cliBuilder.build();
Expand Down
39 changes: 4 additions & 35 deletions src/common/domain/valueobject/Directory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DomainError } from "../../../common/domain/DomainError.ts";
import type { ValueObject } from "../../../common/domain/ValueObject.ts";
import { isDirectory } from "../../../utils/file.ts";
import { scanDirectory } from "../../../utils/scan-directory.ts";
import { File } from "./File.ts";
import { Path } from "./Path.ts";

Expand All @@ -22,43 +23,11 @@ export class Directory implements ValueObject {
return false;
}

public async scanDirectories(pattern: RegExp): Promise<File[]> {
public scanDirectories(pattern: RegExp): File[] {
const files: File[] = [];
await Directory.scanDirectory(this.path.value, pattern, (file: File) =>
files.push(file),
scanDirectory(this.path.value, pattern, (file: string) =>
files.push(new File(new Path(file))),
);
return files;
}

private static async scanDirectory(
directory: string,
pattern: RegExp,
onFileAdded: (file: File) => void,
): Promise<void> {
for await (const dirEntry of Deno.readDir(directory)) {
if (dirEntry.isDirectory) {
if (dirEntry.name === "@eaDir") {
continue;
}

await Directory.scanDirectory(
`${directory}/${dirEntry.name}`,
pattern,
onFileAdded,
);
} else if (dirEntry.isFile) {
if (dirEntry.name === ".DS_Store") {
continue;
}

const fullPath = `${directory}/${dirEntry.name}`;
if (!pattern.test(fullPath)) {
continue;
}

const file = new File(new Path(fullPath));
onFileAdded(file);
}
}
}
}
3 changes: 3 additions & 0 deletions src/main-cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { main } from "./main";

Deno.exit((await main(Deno.args)) ? 0 : 1);
36 changes: 23 additions & 13 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,47 @@
import type { CLI } from "./cli/domain/aggregate/CLI.ts";
import type { BlueskyCredentials } from "./cli/domain/valueobject/BlueskyCredentials.ts";
import { ActionType } from "./cli/domain/valueobject/Action.ts";
import type { BlueskyPublisherAction } from "./cli/domain/valueobject/BlueskyPublisherAction.ts";
import type { PreScannerAction } from "./cli/domain/valueobject/PreScannerAction.ts";
import { CLIService } from "./cli/service/CLIService.ts";
import { KvDriver } from "./common/dbdriver/KvDriver.ts";
import type { Configuration } from "./configuration/domain/aggregate/Configuration.ts";
import { ConfigurationService } from "./configuration/service/ConfigurationService.ts";
import { preScan } from "./prescan.ts";
import { publish } from "./publish.ts";
import { runScanner } from "./scan.ts";

await main(Deno.args);

export async function main(cliArgs: string[]): Promise<void> {
export async function main(cliArgs: string[]): Promise<boolean> {
console.log("Starting Autophoto...");

const cli: CLI = new CLIService().read(cliArgs);
const kvDriver = new KvDriver(cli.databaseFilepath);

try {
const configuration: Configuration = new ConfigurationService().loadFile(
cli.configuration.path.value,
);

if (cli.action.isScan()) {
if (cli.action.type() === ActionType.SCANNER) {
console.log("Scanning...");
await runScanner(configuration, kvDriver, cli.debugDatabase);
} else {
const configuration: Configuration = new ConfigurationService().loadFile(
cli.configuration.path.value,
);
await runScanner(configuration, kvDriver, cli.debug);
return true;
}

if (cli.action.type() === ActionType.PUBLISHER) {
console.log("Publishing...");
const result: string | undefined = await publish(
cli.action as BlueskyCredentials,
cli.action as BlueskyPublisherAction,
kvDriver,
cli.debugDatabase,
cli.debug,
);
console.log("Publication result:", result ?? "Nothing to publish.");
return true;
}

console.log("Pre-scanning...");
const configuration: Configuration = new ConfigurationService().loadFile(
(cli.action as PreScannerAction).configuration.path.value,
);
return preScan(configuration);
} finally {
kvDriver.close();
console.log("Autophoto finished.");
Expand Down
43 changes: 43 additions & 0 deletions src/prescan.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { Configuration } from "./configuration/domain/aggregate/Configuration.ts";
import { VideoGamePlatform } from "./scanner/domain/valueobject/VideoGamePlatform.ts";
import { scanDirectory } from "./utils/scan-directory.ts";

export const preScan = (configuration: Configuration): boolean => {
let filesCount = 0;
let errorsCount = 0;

for (const scan of configuration.scans) {
const directory: string = scan.directory.path.value;
console.log(`Pre-scanning ${directory}...`);

const platIndex: number = scan.pattern.groups.indexOf("platform");
if (platIndex === -1) {
console.error(
` - The pattern "${scan.pattern.regex.source}" does not have a "platform" group.`,
);
errorsCount++;
continue;
}

scanDirectory(directory, scan.pattern.regex, (filepath) => {
const regexResult: RegExpExecArray = scan.pattern.regex.exec(
filepath,
) as RegExpExecArray;

const group3: string = regexResult[3];
try {
new VideoGamePlatform(group3);
filesCount++;
} catch (_) {
console.error(` - "${filepath}" has an invalid platform: ${group3}`);
errorsCount++;
}
});
}

console.log("Pre-scan completed!");
console.log(`Found ${filesCount} files.`);
console.log(`Had ${errorsCount} errors.`);

return errorsCount > 0;
};
8 changes: 4 additions & 4 deletions src/publish.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { AtpAgent } from "@atproto/api";
import type { BlueskyCredentials } from "./cli/domain/valueobject/BlueskyCredentials.ts";
import type { BlueskyPublisherAction } from "./cli/domain/valueobject/BlueskyPublisherAction.ts";
import type { KvDriver } from "./common/dbdriver/KvDriver.ts";
import { File } from "./common/domain/valueobject/File.ts";
import { Path } from "./common/domain/valueobject/Path.ts";
Expand All @@ -19,7 +19,7 @@ import { BlueskyPublisherService } from "./publisher/service/BlueskyPublisherSer
import { pluralFinalS } from "./utils/plural-final-s.ts";

export const publish = async (
blueskyCredentials: BlueskyCredentials,
blueskyAction: BlueskyPublisherAction,
kvDriver: KvDriver,
debugDatabase: boolean,
): Promise<string | undefined> => {
Expand All @@ -41,9 +41,9 @@ export const publish = async (
const resultPublication: string = await new BlueskyPublisherService().publish(
new BlueskyPublication(
new AtpAgent({
service: blueskyCredentials.host.toString(),
service: blueskyAction.host.toString(),
}),
new Credentials(blueskyCredentials.login, blueskyCredentials.password),
new Credentials(blueskyAction.login, blueskyAction.password),
new Publication(
`${pluralFinalS(pickedVideoGameScreeshots.screenshots.length, "Screenshot", false)} from video game "${pickedVideoGameScreeshots.title}" (${pickedVideoGameScreeshots.releaseYear}) taken on ${pickedVideoGameScreeshots.platform}`,
pickedVideoGameScreeshots.screenshots.map(
Expand Down
Loading

0 comments on commit 24e7122

Please sign in to comment.