Skip to content

Commit

Permalink
[ModPlayVOD, ws_util] Add support for streaming VODs
Browse files Browse the repository at this point in the history
  • Loading branch information
m4heshd committed May 21, 2024
1 parent b4f0120 commit 516ec08
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 2 deletions.
29 changes: 29 additions & 0 deletions backend/src/ws_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ fn handle_ws_client(socket: &SocketRef) {

socket.on("verify-url", handle_verify_url_event);

socket.on("get-playable", handle_get_playable_event);

socket.on("download", handle_download_event);

socket.on("cancel-download", handle_cancel_download_event);
Expand Down Expand Up @@ -267,6 +269,33 @@ async fn handle_verify_url_event(ack: AckSender, Data(data): Data<JSON>) {
}
}

/// Handles the `get-playable` WS event.
async fn handle_get_playable_event(ack: AckSender, Data(data): Data<JSON>) {
if let Ok(url) = serde_json::from_value::<String>(data) {
match get_vod_meta(url.as_str()).await {
Ok(mut vod) => {
if !vod.access {
return send_error(
ack,
"You need a Fight Pass subscription to watch this video",
);
}

match get_vod_stream_url(vod.id).await {
Ok(hls) => {
vod.hls = hls;
ack.send(vod).ok();
}
Err(error) => send_error(ack, error),
}
}
Err(error) => send_error(ack, error),
}
} else {
send_error(ack, "Invalid video play request");
}
}

/// Handles the `download` WS event.
async fn handle_download_event(ack: AckSender, Data(mut data): Data<JSON>) {
if let (Ok(mut vod), Some(is_restart)) = (
Expand Down
1 change: 1 addition & 0 deletions frontend/src/assets/styles/common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ body {
}

& > i {
border-radius: 0;
font-size: 26rem;
}
}
Expand Down
15 changes: 14 additions & 1 deletion frontend/src/components/BlockVODCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@

<div class="block-vod-card__details__thumbnail__actions">
<div class="center-content block-vod-card__details__thumbnail__actions__buttons">
<button
class="circle fill medium"
title="Play video"
:disabled="vBusyState"
@click="$emit('play', vVODData.id)"
>
<i>play_arrow</i>
</button>
<button
class="circle fill medium"
title="Download"
Expand All @@ -23,7 +31,7 @@
</button>
<button
class="circle fill medium"
title="Get available formats"
title="View available formats"
:disabled="vBusyState"
@click="$emit('getFormats', vVODData.id)"
>
Expand Down Expand Up @@ -83,6 +91,7 @@ const props = defineProps({
// Emits
defineEmits([
'play',
'download',
'getFormats',
'openExternal'
Expand Down Expand Up @@ -176,6 +185,10 @@ onMounted(() => nextTick(loadThumbnailImg));
height: 55%;
transform: translateY(20rem);
transition: transform .2s ease-in-out;
& > button {
margin: 0 6rem;
}
}
&__bg {
Expand Down
42 changes: 42 additions & 0 deletions frontend/src/components/ModPlayVOD.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<template>
<VModal
class="mod-play-vod"
v-model="modPlayVOD.active"
vIcon="live_tv"
:vTitle="modPlayVOD.VOD.title"
>
<template #content>
<VMediaPlayer
:vPoster="modPlayVOD.VOD.thumb"
:v-source="modPlayVOD.VOD.hls"
></VMediaPlayer>
</template>

<template #controls>
<button @click="modPlayVOD.closeModPlayVOD()">
<i>close</i>
<span>Close</span>
</button>
</template>
</VModal>
</template>

<script setup>
// Store
import {useModPlayVODStore} from '@/store/modPlayVOD';
// Components
import VModal from '@/components/VModal.vue';
import VMediaPlayer from '@/components/VMediaPlayer.vue';
// Store
const modPlayVOD = useModPlayVODStore();
</script>

<style lang="scss">
.mod-play-vod {
width: 100%;
max-width: 950rem;
max-height: 80%;
overflow: hidden;
}
</style>
5 changes: 5 additions & 0 deletions frontend/src/modules/ws-util.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ export function useWSUtil() {
return emitPromise('verify-url', url);
}

function getPlayableVOD(url) {
return emitPromise('get-playable', url);
}

function searchVODs(query, page) {
return emitPromise('search-vods', query, page);
}
Expand Down Expand Up @@ -168,6 +172,7 @@ export function useWSUtil() {
saveConfig,
login,
verifyURL,
getPlayableVOD,
getFormats,
downloadVOD,
cancelDownload,
Expand Down
22 changes: 21 additions & 1 deletion frontend/src/pages/Landing.vue
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
:vShowDuration="store.config.showDuration"
:vShowDesc="store.config.showDesc"
:vBusyState="busy"
@play="(id) => playVOD(store.getFightPassURLByID(id))"
@download="(id) => verifyVODURL(store.getFightPassURLByID(id))"
@getFormats="(id) => getAvailableFormats(store.getFightPassURLByID(id))"
@openExternal="(id) => store.openVODInFightPass(id)"
Expand Down Expand Up @@ -218,6 +219,7 @@
<ModViewFormats
@download="onModViewFormatsDownload"
></ModViewFormats>
<ModPlayVOD></ModPlayVOD>
<ModSearchHelp></ModSearchHelp>
<ModSupport></ModSupport>
<ModMsgBox
Expand All @@ -238,10 +240,11 @@

<script setup>
// Core
import {ref, nextTick, onMounted} from 'vue';
import {nextTick, onMounted, ref} from 'vue';
// Store
import {useAppStore} from '@/store';
import {useModViewFormatsStore} from '@/store/modViewFormats';
import {useModPlayVODStore} from '@/store/modPlayVOD';
// Modules
import {useWSUtil} from '@/modules/ws-util';
// Components
Expand All @@ -251,6 +254,7 @@ import BlockVODCard from '@/components/BlockVODCard.vue';
import ModVODConfirm from '@/components/ModVODConfirm.vue';
import ModConfig from '@/components/ModConfig.vue';
import ModBinDL from '@/components/ModBinDL.vue';
import ModPlayVOD from '@/components/ModPlayVOD.vue';
import ModViewFormats from '@/components/ModViewFormats.vue';
import ModSupport from '@/components/ModSupport.vue';
import ModMsgBox from '@/components/ModMsgBox.vue';
Expand All @@ -260,6 +264,7 @@ import Overlay from '@/components/Overlay.vue';
// Store
const store = useAppStore();
const modViewFormats = useModViewFormatsStore();
const modPlayVOD = useModPlayVODStore();
// Websocket
const {
Expand All @@ -270,6 +275,7 @@ const {
openDownloadsDir,
searchVODs,
verifyURL,
getPlayableVOD,
getFormats
} = useWSUtil();
Expand Down Expand Up @@ -354,6 +360,20 @@ function searchPreviousPage() {
searchVOD(store.search.result.query, store.search.result.page - 1);
}
function playVOD(url) {
if (!store.isLoggedIn) return store.popError('You need to be logged in to play videos');
switchBusyState();
getPlayableVOD(url)
.then((VOD) => {
modPlayVOD.setVOD(VOD);
modPlayVOD.showModPlayVOD();
})
.catch(store.popError)
.finally(switchBusyState);
}
function verifyVODURL(url) {
if (!store.isLoggedIn) return store.popError('You need to be logged in to download videos');
Expand Down
20 changes: 20 additions & 0 deletions frontend/src/store/modPlayVOD.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Store
import {defineStore} from 'pinia';

export const useModPlayVODStore = defineStore('modPlayVOD', {
state: () => ({
active: false,
VOD: {}
}),
actions: {
showModPlayVOD() {
this.active = true;
},
closeModPlayVOD() {
this.active = false;
},
setVOD(VOD) {
Object.assign(this.VOD, VOD);
}
}
});

0 comments on commit 516ec08

Please sign in to comment.