Skip to content

Commit

Permalink
Merge pull request #154 from slmnio/action-updates
Browse files Browse the repository at this point in the history
Update actions to reduce code duplication
  • Loading branch information
slmnio authored Nov 26, 2022
2 parents 1bd8335 + 9d7e023 commit c8811ce
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 68 deletions.
44 changes: 43 additions & 1 deletion server/src/action-utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const Airtable = require("airtable");
const Cache = require("./cache");
const { StaticAuthProvider } = require("@twurple/auth");
const { ApiClient } = require("@twurple/api");
const { get, auth } = require("./cache");
const airtable = new Airtable({ apiKey: process.env.AIRTABLE_KEY });
const slmngg = airtable.base(process.env.AIRTABLE_APP);

Expand Down Expand Up @@ -109,6 +112,45 @@ async function getValidHeroes() {
return heroes.filter(h => h.game === "Overwatch");
}

async function getTwitchChannel(client, requestedScopes, { success, error }) {
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 (!requestedScopes.every(scope => scopes.includes(scope))) return error("Token doesn't have the required scopes");
return {
broadcast,
channel,
scopes
};
}

async function getMatchData(broadcast, requireAll, { success, error }) {
const match = await get(broadcast?.live_match?.[0]);
if (!match) return error("No match associated");

const team1 = await get(match?.teams?.[0]);
const team2 = await get(match?.teams?.[1]);
if (requireAll && (!team1 || !team2)) return error("Did not find two teams!");

return {
match,
team1,
team2
};
}

async function getTwitchAPIClient(channel) {
const accessToken = await auth.getTwitchAccessToken(channel);
const authProvider = new StaticAuthProvider(process.env.TWITCH_CLIENT_ID, accessToken);
return new ApiClient({authProvider});
}


module.exports = {
getSelfClient, dirtyID, deAirtable, updateRecord, getValidHeroes, createRecord
getSelfClient, dirtyID, deAirtable, updateRecord, getValidHeroes, createRecord, getTwitchChannel, getMatchData, getTwitchAPIClient
};
32 changes: 8 additions & 24 deletions server/src/actions/manage-prediction.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const { ApiClient } = require("@twurple/api");
const { StaticAuthProvider, refreshUserToken } = require("@twurple/auth");
const { getTwitchChannel,
getTwitchAPIClient,
getMatchData
} = require("../action-utils");

const automaticPredictionTitleStartCharacter = "⬥";

Expand Down Expand Up @@ -49,30 +51,12 @@ module.exports = {
if (!(["create", "lock", "resolve", "cancel"].includes(predictionAction))) return error("Invalid action");
console.log(predictionAction);

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:manage:predictions", "channel:read:predictions"].every(scope => scopes.includes(scope))) return error("Token doesn't have the required scopes");

console.log(channel);
const accessToken = await auth.getTwitchAccessToken(channel);

const authProvider = new StaticAuthProvider(process.env.TWITCH_CLIENT_ID, accessToken);
const api = new ApiClient({authProvider});

// TODO: move cancel action to here

const match = await get(broadcast?.live_match?.[0]);
if (!match) return error("No match associated");

const team1 = await get(match?.teams?.[0]);
const team2 = await get(match?.teams?.[1]);
if (!team1 || !team2) return error("Did not find two teams!");
const { broadcast, channel } = getTwitchChannel(client, ["channel:manage:predictions", "channel:read:predictions"], { success, error });
// console.log(channel);
const api = await getTwitchAPIClient(channel);
const { match, team1, team2 } = await getMatchData(broadcast, true, { success, error });

const maps = await Promise.all((match.maps || []).map(async m => {
let map = await get(m);
Expand Down
31 changes: 7 additions & 24 deletions server/src/actions/set-title.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const { ApiClient } = require("@twurple/api");
const { StaticAuthProvider } = require("@twurple/auth");
const { getTwitchChannel,
getMatchData,
getTwitchAPIClient
} = require("../action-utils");
module.exports = {
key: "set-title",
auth: ["client"],
Expand All @@ -15,32 +17,13 @@ module.exports = {
*/
// eslint-disable-next-line no-empty-pattern
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");
const { broadcast, channel } = getTwitchChannel(client, ["channel:manage:broadcast"], { success, error });

const event = await get(broadcast.event?.[0]);
if (!event) return error("No event 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:manage:broadcast"].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});


const match = await get(broadcast?.live_match?.[0]);
if (!match) return error("No match associated");

const team1 = await get(match?.teams?.[0]);
const team2 = await get(match?.teams?.[1]);
if (!team1 || !team2) return error("Did not find two teams!");
const api = await getTwitchAPIClient(channel, auth);
const { match, team1, team2 } = await getMatchData(broadcast, true, { success, error });

const formatOptions = {
"event": event.name,
Expand Down
25 changes: 6 additions & 19 deletions server/src/actions/start-commercial.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { ApiClient } = require("@twurple/api");
const { StaticAuthProvider } = require("@twurple/auth");
const { getTwitchChannel,
getTwitchAPIClient
} = require("../action-utils");
module.exports = {
key: "start-commercial",
auth: ["client"],
Expand All @@ -15,24 +16,10 @@ module.exports = {
* @returns {Promise<void>}
*/
// eslint-disable-next-line no-empty-pattern
async handler(success, error, { commercialDuration }, { client, user }, { get, auth }) {
async handler(success, error, { commercialDuration }, { client }, { 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");

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});

const { channel } = getTwitchChannel(client, ["channel:edit:commercial"], { success, error });
const api = getTwitchAPIClient(channel);
try {
await api.channels.startChannelCommercial(channel.channel_id, commercialDuration);
} catch (e) {
Expand Down

0 comments on commit c8811ce

Please sign in to comment.