From b62bcc46284866c686c7d2e0a79880ba7f3ebf54 Mon Sep 17 00:00:00 2001 From: Tobias Messner Date: Sat, 15 Oct 2022 22:12:39 +0200 Subject: [PATCH 1/3] Add action to start commercial --- server/src/actions/set-title.js | 4 +-- server/src/actions/start-commercial.js | 42 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 server/src/actions/start-commercial.js diff --git a/server/src/actions/set-title.js b/server/src/actions/set-title.js index 200d59ee..56323736 100644 --- a/server/src/actions/set-title.js +++ b/server/src/actions/set-title.js @@ -6,7 +6,6 @@ module.exports = { /*** * @param {ActionSuccessCallback} success * @param {ActionErrorCallback} error - * @param {PredictionAction} predictionAction * @param {number?} autoLockAfter * @param {ClientData} client * @param {CacheGetFunction} get @@ -15,8 +14,7 @@ module.exports = { * @returns {Promise} */ // eslint-disable-next-line no-empty-pattern - async handler(success, error, { predictionAction, autoLockAfter = 120 }, { client }, { get, auth }) { - + async handler(success, error, { }, { client }, { get, auth }) { const broadcast = await get(client?.broadcast?.[0]); if (!broadcast) return error("No broadcast associated"); if (!broadcast.channel) return error("No channel associated with broadcast"); diff --git a/server/src/actions/start-commercial.js b/server/src/actions/start-commercial.js new file mode 100644 index 00000000..b0816f4e --- /dev/null +++ b/server/src/actions/start-commercial.js @@ -0,0 +1,42 @@ +const { ApiClient } = require("@twurple/api"); +const { StaticAuthProvider } = require("@twurple/auth"); +module.exports = { + key: "start-commercial", + auth: ["client"], + requiredParams: ["commercialDuration"], + /*** + * @param {ActionSuccessCallback} success + * @param {ActionErrorCallback} error + * @param {30 | 60 | 90 | 120 | 150 | 180} commercialDuration + * @param {ClientData} client + * @param {CacheGetFunction} get + * @param {CacheAuthFunctions} auth + * @param {SimpleUpdateRecord} updateRecord + * @returns {Promise} + */ + // eslint-disable-next-line no-empty-pattern + async handler(success, error, { commercialDuration }, { client }, { get, auth }) { + const broadcast = await get(client?.broadcast?.[0]); + if (!broadcast) return error("No broadcast associated"); + if (!broadcast.channel) return error("No channel associated with broadcast"); + + const channel = await auth.getChannel(broadcast?.channel?.[0]); + if (!channel.twitch_refresh_token) return error("No twitch auth token associated with channel"); + if (!channel.channel_id || !channel.name || !channel.twitch_scopes) return error("Invalid channel data"); + let scopes = channel.twitch_scopes.split(" "); + if (!["channel:edit:commercial"].every(scope => scopes.includes(scope))) return error("Token doesn't have the required scopes"); + + const accessToken = await auth.getTwitchAccessToken(channel); + + const authProvider = new StaticAuthProvider(process.env.TWITCH_CLIENT_ID, accessToken); + const api = new ApiClient({authProvider}); + + try { + await api.channels.startChannelCommercial(channel.channel_id, commercialDuration); + } catch (e) { + console.log(e); + return error("Failed to start commercial"); + } + return success(); + } +}; From b5bf86b33de2e86376fffeda9f1774e26621adcb Mon Sep 17 00:00:00 2001 From: Tobias Messner Date: Sat, 15 Oct 2022 22:49:12 +0200 Subject: [PATCH 2/3] Add web ui for commercials --- .../website/dashboard/Commercials.vue | 36 +++++++++++++++++++ website/src/utils/dashboard.js | 8 +++++ website/src/views/Dashboard.vue | 4 ++- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 website/src/components/website/dashboard/Commercials.vue diff --git a/website/src/components/website/dashboard/Commercials.vue b/website/src/components/website/dashboard/Commercials.vue new file mode 100644 index 00000000..3f09ac42 --- /dev/null +++ b/website/src/components/website/dashboard/Commercials.vue @@ -0,0 +1,36 @@ + + + + + diff --git a/website/src/utils/dashboard.js b/website/src/utils/dashboard.js index 1e061bfa..9acd7834 100644 --- a/website/src/utils/dashboard.js +++ b/website/src/utils/dashboard.js @@ -45,6 +45,14 @@ export async function managePred(auth, client, predictionAction) { }); } +export async function startCommercial(auth, client, commercialDuration) { + if (!auth?.user) return { error: true, errorMessage: "Not authenticated" }; + return await authenticatedRequest(auth, "actions/start-commercial", { + client: client.id || client, + commercialDuration + }); +} + export async function updateAutomaticTitle(auth, client) { if (!auth?.user) return { error: true, errorMessage: "Not authenticated" }; return await authenticatedRequest(auth, "actions/set-title", { diff --git a/website/src/views/Dashboard.vue b/website/src/views/Dashboard.vue index 4495133c..c3d9a6a2 100644 --- a/website/src/views/Dashboard.vue +++ b/website/src/views/Dashboard.vue @@ -13,6 +13,7 @@ + Update title @@ -28,10 +29,11 @@ import MatchEditor from "@/components/website/dashboard/MatchEditor"; import { BButton, BFormCheckbox } from "bootstrap-vue"; import { togglePlayerCams, updateAutomaticTitle } from "@/utils/dashboard"; import Predictions from "@/components/website/dashboard/Predictions"; +import Commercials from "@/components/website/dashboard/Commercials"; export default { name: "Dashboard", - components: { Predictions, MatchEditor, MatchThumbnail, BroadcastSwitcher, BFormCheckbox, BButton }, + components: { Commercials, Predictions, MatchEditor, MatchThumbnail, BroadcastSwitcher, BFormCheckbox, BButton }, computed: { user() { if (!this.$root.auth.user?.airtableID) return {}; From fb5356f76df3754350d6d65fae2426e4c2c1f028 Mon Sep 17 00:00:00 2001 From: Solomon Cammack Date: Sat, 26 Nov 2022 16:54:52 +0000 Subject: [PATCH 3/3] Restrict running commercials to staff with full broadcast permissions --- server/src/actions/start-commercial.js | 4 +++- website/src/views/Dashboard.vue | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/server/src/actions/start-commercial.js b/server/src/actions/start-commercial.js index b0816f4e..7e7a9778 100644 --- a/server/src/actions/start-commercial.js +++ b/server/src/actions/start-commercial.js @@ -15,7 +15,9 @@ module.exports = { * @returns {Promise} */ // eslint-disable-next-line no-empty-pattern - async handler(success, error, { commercialDuration }, { client }, { get, auth }) { + async handler(success, error, { commercialDuration }, { client, user }, { get, auth }) { + if (!user.airtable?.website_settings?.includes("Full broadcast permissions")) return error("You don't have permission to start a commercial", 403); + const broadcast = await get(client?.broadcast?.[0]); if (!broadcast) return error("No broadcast associated"); if (!broadcast.channel) return error("No channel associated with broadcast"); diff --git a/website/src/views/Dashboard.vue b/website/src/views/Dashboard.vue index c3d9a6a2..b9630be5 100644 --- a/website/src/views/Dashboard.vue +++ b/website/src/views/Dashboard.vue @@ -13,7 +13,7 @@ - + Update title @@ -76,9 +76,11 @@ export default { methods: { url, togglePlayerCams, - async updateTitle() { await updateAutomaticTitle(this.$root.auth, "self", "create"); + }, + hasPermission(permission) { + return (this.user.website_settings || []).includes(permission); } } };