Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Auto Rename v1.1 #151

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
6 changes: 5 additions & 1 deletion client/src/stores/autoRename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ export const useAutoRenameStore = defineStore("autoRename", () => {
return false;
}

async function getAssociations() {
async function getAssociations(forceRefresh: boolean = false) {
loadingAssociations.value = true;
associationsError.value = "";

if (forceRefresh) {
associations.value.clear();
}

const url = "/api/v1/autoRename/associations";
const result = await fetch(url);

Expand Down
3 changes: 3 additions & 0 deletions client/src/views/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ import { useMatchStore } from "@/stores/match";
import { useMatchListStore } from "@/stores/matchList";
import AutoRenameFileNamePatterns from "@/components/autoRename/AutoRenameFileNamePatterns.vue";
import { useUploadedVideosStore } from "@/stores/uploadedVideos";
import { useAutoRenameStore } from "@/stores/autoRename";

const loading = computed(() => {
return settingsStore.loading;
Expand All @@ -483,6 +484,7 @@ const matchStore = useMatchStore();
const matchListStore = useMatchListStore();
const settingsStore = useSettingsStore();
const uploadedVideosStore = useUploadedVideosStore();
const autoRenameStore = useAutoRenameStore();

const dataRefreshKey = ref(1);
const youTubeOAuth2RedirectUriCopied = ref(false);
Expand Down Expand Up @@ -537,6 +539,7 @@ async function submitEventCode(settingName: string, value: string | boolean, set
await matchListStore.getMatchList(true);
matchStore.clearSelectedMatch();
await uploadedVideosStore.getMatchUploadStatuses();
await autoRenameStore.getAssociations(true);
return submitResult;
}

Expand Down
2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"mustache": "^4.2.0",
"mv": "^2.1.1",
"node-fetch": "2",
"prisma": "^6.0.0",
"prisma": "^6.2.1",
"sanitize-filename": "^1.6.3",
"socket.io": "^4.8.1",
"socket.io-client": "^4.8.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
Warnings:

- The primary key for the `AutoRenameAssociation` table will be changed. If it partially fails, the table could be left without primary key constraint.
- A unique constraint covering the columns `[eventKey,filePath]` on the table `AutoRenameAssociation` will be added. If there are existing duplicate values, this will fail.
- Added the required column `eventKey` to the `AutoRenameAssociation` table without a default value. This is not possible if the table is not empty.

*/
-- DropIndex
DROP INDEX "AutoRenameAssociation_filePath_key";

-- AlterTable
ALTER TABLE "AutoRenameAssociation" DROP CONSTRAINT "AutoRenameAssociation_pkey",
ADD COLUMN "eventKey" TEXT NOT NULL DEFAULT 'legacy_no_event_key';

UPDATE "AutoRenameAssociation" SET "eventKey" = 'legacy_no_event_key' WHERE "eventKey" IS NULL;
ALTER TABLE "AutoRenameAssociation" ALTER COLUMN "eventKey" DROP DEFAULT,

ADD CONSTRAINT "AutoRenameAssociation_pkey" PRIMARY KEY ("eventKey", "filePath");

-- CreateIndex
CREATE UNIQUE INDEX "AutoRenameAssociation_eventKey_filePath_key" ON "AutoRenameAssociation"("eventKey", "filePath");
7 changes: 6 additions & 1 deletion server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ enum JobStatus {
COMPLETED
}

// FIXME: Generate migration for changes
model AutoRenameAssociation {
filePath String @id @unique
eventKey String // FIXME: Add a legacy default value for this for backwards-compatibility in migration script
filePath String
videoFile String
status AutoRenameAssociationStatus @default(UNMATCHED)
statusReason String?
Expand All @@ -77,6 +79,9 @@ model AutoRenameAssociation {

createdAt DateTime @default(now())
updatedAt DateTime @updatedAt

@@id([eventKey, filePath], name: "id")
@@unique([eventKey, filePath], name: "associationIdentifier")
}

enum AutoRenameAssociationStatus {
Expand Down
7 changes: 5 additions & 2 deletions server/src/repos/AutoRenameRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,14 @@ export async function queueRenameJob(
{
directory: `${videoSearchDirectory}/${association.videoLabel}`,
oldFileName: association.videoFile,
associationId: association.filePath,
associationId: {
eventKey: association.eventKey,
filePath: association.filePath,
},
},
{
maxAttempts: 1,
jobKey: `autoRename-${association.filePath}`,
jobKey: `autoRename-${association.eventKey}-${association.filePath}`,
jobKeyMode: "replace",
runAt: renameAfter.toJSDate(),
priority,
Expand Down
15 changes: 13 additions & 2 deletions server/src/routes/autoRename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { body, matchedData, query, validationResult } from "express-validator";
import { type AutoRenameAssociationStatus } from "@prisma/client";
import { markAssociationIgnored, undoRename, updateAssociationData } from "@src/services/AutoRenameService";
import { getSettings } from "@src/services/SettingsService";

export const autoRenameRouter = Router();

Expand Down Expand Up @@ -36,11 +37,16 @@
status,
} = matchedData(req);

const { eventTbaCode } = await getSettings();

const where = status
? {
status: status as AutoRenameAssociationStatus,
eventKey: eventTbaCode,
}
: undefined;
: {
eventKey: eventTbaCode,
};

const associations = await prisma.autoRenameAssociation.findMany(
{
Expand Down Expand Up @@ -142,9 +148,14 @@
filePath,
} = matchedData(req);

const { eventTbaCode } = await getSettings();

const association = await prisma.autoRenameAssociation.findUniqueOrThrow({
where: {
filePath: filePath as string,
id: {
eventKey: eventTbaCode as string,

Check failure on line 156 in server/src/routes/autoRename.ts

View workflow job for this annotation

GitHub Actions / eslint / server

server/src/routes/autoRename.ts#L156

[@typescript-eslint/no-unnecessary-type-assertion] This assertion is unnecessary since it does not change the type of the expression.
filePath: filePath as string,
},
},
});

Expand Down
24 changes: 20 additions & 4 deletions server/src/services/AutoRenameService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
): Promise<string | undefined> {
const {
autoRenameFileRenameJobDelaySecs,
eventTbaCode,
playoffsType,
videoSearchDirectory,
} = await getSettings();
const existingAssociation = await prisma.autoRenameAssociation.findFirst({
where: {
videoLabel,
filePath,
eventKey: eventTbaCode,
},
});

Expand Down Expand Up @@ -91,8 +93,11 @@
const association = await prisma.autoRenameAssociation.update({
where: {
videoLabel,
filePath,
id: {
filePath,
eventKey: eventTbaCode,
}
},

Check failure on line 100 in server/src/services/AutoRenameService.ts

View workflow job for this annotation

GitHub Actions / eslint / server

server/src/services/AutoRenameService.ts#L99-L100

[comma-dangle] Missing trailing comma.
data: {
status: AutoRenameAssociationStatus.STRONG,
statusReason: `Weak association approved at ${new Date().toISOString()}`,
Expand Down Expand Up @@ -150,10 +155,12 @@
}

export async function markAssociationIgnored(videoLabel: string, filePath: string): Promise<string | undefined> {
const { eventTbaCode } = await getSettings();
const existingAssociation = await prisma.autoRenameAssociation.findFirst({
where: {
videoLabel,
filePath,
eventKey: eventTbaCode,
},
});

Expand All @@ -169,7 +176,10 @@
const association = await prisma.autoRenameAssociation.update({
where: {
videoLabel,
filePath,
id: {
filePath,
eventKey: eventTbaCode,
},
},
data: {
status: AutoRenameAssociationStatus.IGNORED,
Expand Down Expand Up @@ -228,7 +238,10 @@

const updatedAssociation = await prisma.autoRenameAssociation.update({
where: {
filePath: association.filePath,
id: {
filePath: association.filePath,
eventKey: association.eventKey,
},
},
data: {
renameCompleted: false,
Expand Down Expand Up @@ -258,7 +271,10 @@

const association: AutoRenameAssociation = await prisma.autoRenameAssociation.findUniqueOrThrow({
where: {
filePath: data.filePath,
id: {
filePath: data.filePath,
eventKey: data.eventKey,
},
},
});

Expand Down
39 changes: 31 additions & 8 deletions server/src/tasks/autoRename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@

const existingAssoc = await prisma.autoRenameAssociation.findUnique({
where: {
filePath: file,
id: {
filePath: file,
eventKey: eventTbaCode,
},
},
});

Expand All @@ -188,9 +191,13 @@
logger.info(`File: ${file} / Parsed date: ${parsedDate.toISO()}`);
await prisma.autoRenameAssociation.upsert({
where: {
filePath: file,
id: {
filePath: file,
eventKey: eventTbaCode,
}
},

Check failure on line 198 in server/src/tasks/autoRename.ts

View workflow job for this annotation

GitHub Actions / eslint / server

server/src/tasks/autoRename.ts#L197-L198

[comma-dangle] Missing trailing comma.
create: {
eventKey: eventTbaCode,
filePath: file,
videoFile,
videoLabel,
Expand All @@ -204,9 +211,13 @@
} else {
await prisma.autoRenameAssociation.upsert({
where: {
filePath: file,
id: {
filePath: file,
eventKey: eventTbaCode,
}
},

Check failure on line 218 in server/src/tasks/autoRename.ts

View workflow job for this annotation

GitHub Actions / eslint / server

server/src/tasks/autoRename.ts#L217-L218

[comma-dangle] Missing trailing comma.
create: {
eventKey: eventTbaCode,
filePath: file,
videoFile,
videoLabel,
Expand Down Expand Up @@ -238,7 +249,10 @@
if (!(await fs.exists(`${videoSearchDirectory}/${association.filePath}`))) {
await prisma.autoRenameAssociation.update({
where: {
filePath: association.filePath,
id: {
eventKey: eventTbaCode,
filePath: association.filePath,
},
},
data: {
status: AutoRenameAssociationStatus.FAILED,
Expand All @@ -265,7 +279,7 @@
}
}

// TODO: Would be good to catch errors here
// FIXME: Need to catch errors here

Check warning on line 282 in server/src/tasks/autoRename.ts

View workflow job for this annotation

GitHub Actions / eslint / server

server/src/tasks/autoRename.ts#L282

[no-warning-comments] Unexpected 'fixme' comment: 'FIXME: Need to catch errors here'.
const videoDurationSecs = (await getVideoDuration(`${videoSearchDirectory}/${association.filePath}`)).seconds;

let {
Expand Down Expand Up @@ -349,7 +363,10 @@

await prisma.autoRenameAssociation.update({
where: {
filePath: association.filePath,
id: {
eventKey: eventTbaCode,
filePath: association.filePath,
},
},
data: {
status: associationStatus,
Expand All @@ -374,8 +391,11 @@
if (association.associationAttempts + 1 >= association.maxAssociationAttempts) {
await prisma.autoRenameAssociation.update({
where: {
filePath: association.filePath,
id: {
eventKey: eventTbaCode,
filePath: association.filePath,
}
},

Check failure on line 398 in server/src/tasks/autoRename.ts

View workflow job for this annotation

GitHub Actions / eslint / server

server/src/tasks/autoRename.ts#L397-L398

[comma-dangle] Missing trailing comma.
data: {
status: AutoRenameAssociationStatus.FAILED,
associationAttempts: {
Expand All @@ -389,8 +409,11 @@
} else {
await prisma.autoRenameAssociation.update({
where: {
filePath: association.filePath,
id: {
eventKey: eventTbaCode,
filePath: association.filePath,
}
},

Check failure on line 416 in server/src/tasks/autoRename.ts

View workflow job for this annotation

GitHub Actions / eslint / server

server/src/tasks/autoRename.ts#L415-L416

[comma-dangle] Missing trailing comma.
data: {
status: AutoRenameAssociationStatus.UNMATCHED,
associationAttempts: {
Expand Down
19 changes: 12 additions & 7 deletions server/src/tasks/renameFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@ import { AUTO_RENAME_ASSOCIATION_UPDATE } from "@src/tasks/types/events";
export interface RenameFilePayload {
directory: string;
oldFileName: string;
associationId: string;
associationId: {
eventKey: string;
filePath: string;
};
}

function assertIsRenameFilePayload(payload: unknown): asserts payload is RenameFilePayload {
if (payload === null) {
throw new Error(`Invalid payload (null): ${JSON.stringify(payload)}`);
} else if (typeof payload === "undefined") {
throw new Error(`Invalid payload (undefined): ${JSON.stringify(payload)}`);
} else if (!(payload as unknown as RenameFilePayload).directory ||
!(payload as unknown as RenameFilePayload).oldFileName ||
!(payload as unknown as RenameFilePayload).associationId
} else if (typeof (payload as RenameFilePayload).directory !== "string" ||
typeof (payload as RenameFilePayload).oldFileName !== "string" ||
typeof (payload as RenameFilePayload).associationId !== "object" ||
typeof (payload as RenameFilePayload).associationId.eventKey !== "string" ||
typeof (payload as RenameFilePayload).associationId.filePath !== "string"
) {
throw new Error(`Invalid payload (missing required prop): ${JSON.stringify(payload)}`);
throw new Error(`Invalid payload (missing or invalid required prop): ${JSON.stringify(payload)}`);
}
}

Expand All @@ -30,7 +35,7 @@ export async function renameFile(payload: unknown, {

const association = await prisma.autoRenameAssociation.findUniqueOrThrow({
where: {
filePath: payload.associationId,
id: payload.associationId,
},
});

Expand All @@ -52,7 +57,7 @@ export async function renameFile(payload: unknown, {

await prisma.autoRenameAssociation.update({
where: {
filePath: payload.associationId,
id: payload.associationId,
},
data: {
renameCompleted: true,
Expand Down
4 changes: 3 additions & 1 deletion server/src/tasks/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface CommonEvents {
success: boolean;
};
[AUTO_RENAME_ASSOCIATION_UPDATE]: {
eventKey: string;
filePath: string;
};
}
Expand Down Expand Up @@ -65,5 +66,6 @@ export function isAutoRenameAssociationUpdateEvent(
): x is CommonEvents[typeof AUTO_RENAME_ASSOCIATION_UPDATE] {
return typeof x === "object" &&
x !== null &&
"filePath" in x;
"filePath" in x &&
"eventKey" in x;
}
Loading
Loading