Skip to content

Commit

Permalink
match all provider vods
Browse files Browse the repository at this point in the history
  • Loading branch information
MrBrax committed Nov 7, 2023
1 parent 273324b commit 7a99e62
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 5 deletions.
30 changes: 30 additions & 0 deletions client-vue/src/components/StreamerItemTools.vue
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@
<span>{{ t("streamer.tools.export-vods") }}</span>
</button>
</li>

<!-- match all provider vods -->
<li>
<button class="context-menu-button white" :title="t('streamer.tools.match-all-provider-vods')" @click="doMatchProviderVods">
<span class="icon"><font-awesome-icon icon="upload" /></span>
<span>{{ t("streamer.tools.match-all-provider-vods") }}</span>
</button>
</li>
</ul>
</template>
</ContextMenu>
Expand Down Expand Up @@ -359,6 +367,28 @@ function doExportVods() {
}
});
}
async function doMatchProviderVods() {
if (!props.streamer) return;
if (!confirm("Do you want to match all provider VODs?")) return;
axios
.post<ApiResponse>(`/api/v0/channels/${props.streamer.uuid}/matchallprovidervods`)
.then((response) => {
const json = response.data;
if (json.message) alert(json.message);
console.log(json);
store.fetchStreamerList();
})
.catch((error) => {
if (axios.isAxiosError(error)) {
console.error("doMatchProviderVods error", error.response);
if (error.response && error.response.data && error.response.data.message) {
alert(error.response.data.message);
}
}
});
}
</script>

<style lang="scss" scoped>
Expand Down
3 changes: 2 additions & 1 deletion client-vue/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@
"clean-up": "Clean up",
"refresh-data": "Refresh data",
"expand-collapse-all-vods": "Expand/collapse all vods",
"more": "More tools"
"more": "More tools",
"match-all-provider-vods": "Match all provider VODs"
}
},
"about": {
Expand Down
39 changes: 39 additions & 0 deletions server/src/Controllers/Channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1769,3 +1769,42 @@ export async function ExportAllVods(
message: `Exported ${completedVods} VODs, ${failedVods} failed`,
});
}

export async function MatchAllProviderVods(
req: express.Request,
res: express.Response
): Promise<void> {
const channel = getChannelFromRequest(req);
const force = req.query.force === "true";

if (!channel || !channel.internalName) {
res.api(400, {
status: "ERROR",
message: req.t("route.channels.channel-not-found"),
});
return;
}

if (!isTwitchChannel(channel)) {
res.api(400, {
status: "ERROR",
message: req.t("route.channels.channel-is-not-a-twitch-channel"),
});
return;
}

try {
await channel.matchAllProviderVods(force);
} catch (error) {
res.api(500, {
status: "ERROR",
message: (error as Error).message,
});
return;
}

res.api(200, {
status: "OK",
message: "Matched vods",
});
}
109 changes: 109 additions & 0 deletions server/src/Core/Providers/Twitch/TwitchChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,115 @@ export class TwitchChannel extends BaseChannel {
);
}

public async matchAllProviderVods(force = false): Promise<void> {
const channel_videos = await TwitchVOD.getLatestVideos(this.internalId);

if (!channel_videos) {
throw new Error("No videos returned from streamer");
}

for (const vod of this.getVods()) {
if (vod.external_vod_id && !force) {
// throw new Error("VOD already has a provider VOD ID");
log(
LOGLEVEL.WARNING,
"channel.matchProviderVod",
`VOD ${vod.basename} already has a provider VOD ID`
);
continue;
}

if (vod.is_capturing || vod.is_converting) {
// throw new Error("VOD is still capturing or converting");
log(
LOGLEVEL.ERROR,
"channel.matchProviderVod",
`VOD ${vod.basename} is still capturing or converting`
);
continue;
}

if (!vod.started_at) {
// throw new Error("VOD has no start time");
log(
LOGLEVEL.ERROR,
"channel.matchProviderVod",
`VOD ${vod.basename} has no start time`
);
continue;
}

log(
LOGLEVEL.INFO,
"channel.matchProviderVod",
`Trying to match ${vod.basename} to provider...`
);

let found = false;
for (const video of channel_videos) {
const video_time = parseJSON(video.created_at);
if (!video_time) continue;

const startOffset = Math.abs(
vod.started_at.getTime() - video_time.getTime()
);
const matchingCaptureId =
video.stream_id &&
vod.capture_id &&
video.stream_id == vod.capture_id;
const maxOffset = 1000 * 60 * 5; // 5 minutes

const videoDuration = TwitchHelper.parseTwitchDuration(
video.duration
);

if (
startOffset < maxOffset || // 5 minutes
matchingCaptureId
) {
log(
LOGLEVEL.SUCCESS,
"channel.matchProviderVod",
`Found matching VOD for ${
vod.basename
} (${vod.started_at.toISOString()}): ${video.id} (${
video.title
})`
);

vod.setProviderVod(video);
vod.external_vod_exists = true;

vod.broadcastUpdate();

found = true;
break;
}
}

if (found) {
await vod.saveJSON("matchProviderVod: found");
continue;
}

vod.twitch_vod_attempted = true;
vod.twitch_vod_neversaved = true;
vod.external_vod_exists = false;

log(
LOGLEVEL.ERROR,
"vod.matchProviderVod",
`No matching VOD for ${vod.basename}`
);

await vod.saveJSON("matchProviderVod: not found");

vod.broadcastUpdate();

// throw new Error(`No matching VOD from ${channel_videos.length} videos`);
}
}

fileWatcher?: chokidar.FSWatcher;
/**
* @test disable
Expand Down
4 changes: 0 additions & 4 deletions server/src/Core/Providers/Twitch/TwitchVOD.ts
Original file line number Diff line number Diff line change
Expand Up @@ -994,10 +994,6 @@ export class TwitchVOD extends BaseVOD {
})`
);

// this.twitch_vod_id = video.id;
// this.twitch_vod_duration = TwitchHelper.parseTwitchDuration(video.duration);
// this.twitch_vod_title = video.title;
// this.twitch_vod_date = video.created_at;
this.setProviderVod(video);
this.external_vod_exists = true;

Expand Down
5 changes: 5 additions & 0 deletions server/src/Routes/Api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,11 @@ router.post(
);
router.get("/channels/:uuid/clips", AuthAdmin, Channels.GetClips);
router.post("/channels/:uuid/exportallvods", AuthAdmin, Channels.ExportAllVods);
router.post(
"/channels/:uuid/matchallprovidervods",
AuthAdmin,
Channels.MatchAllProviderVods
);

router.get("/vod/:uuid", AuthGuest, Vod.GetVod);
router.post("/vod/:uuid", AuthAdmin, Vod.EditVod);
Expand Down

0 comments on commit 7a99e62

Please sign in to comment.