From 05a93ba3166e5cc3dd0e09aec7eaf1af4e2ce750 Mon Sep 17 00:00:00 2001 From: alexbcberio Date: Wed, 5 Jan 2022 18:13:59 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Cleaned=20lots=20of=20code?= =?UTF-8?q?=20and=20change=20getvip=20implementation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit getVip is no longer time limited, it will remove it once a limit of vip users is reached (to be implemented) --- .../chatClient/clientActions/addVip/index.ts | 16 ++-- .../chatClient/clientActions/hasVip/index.ts | 27 +++++++ src/backend/chatClient/clientActions/index.ts | 3 +- .../clientActions/removeVip/index.ts | 16 ++-- src/backend/chatClient/index.ts | 15 ++-- src/backend/pubSubClient/actions/getVip.ts | 29 +++++++ src/backend/pubSubClient/actions/stealVip.ts | 79 ++++++------------- src/backend/pubSubClient/index.ts | 17 +++- src/enums/ActionType.ts | 7 ++ src/enums/Redemptions.ts | 9 +++ src/interfaces/RedemptionMessage.ts | 11 +++ src/interfaces/actions/Action.ts | 14 ++-- src/interfaces/actions/SayAction.ts | 11 +-- 13 files changed, 162 insertions(+), 92 deletions(-) create mode 100644 src/backend/chatClient/clientActions/hasVip/index.ts create mode 100644 src/backend/pubSubClient/actions/getVip.ts create mode 100644 src/enums/ActionType.ts create mode 100644 src/enums/Redemptions.ts create mode 100644 src/interfaces/RedemptionMessage.ts diff --git a/src/backend/chatClient/clientActions/addVip/index.ts b/src/backend/chatClient/clientActions/addVip/index.ts index cf93db9..f5cec51 100644 --- a/src/backend/chatClient/clientActions/addVip/index.ts +++ b/src/backend/chatClient/clientActions/addVip/index.ts @@ -1,18 +1,22 @@ import { chatClient } from "../.."; import { say } from ".."; -// adds a user to vips async function addVip( channel: string, username: string, message?: string -): Promise { - if (!message) { - message = `Otorgado VIP a @${username}.`; +): Promise { + try { + await chatClient.addVip(channel, username); + } catch (e) { + return false; } - await chatClient.addVip(channel, username); - say(channel, message); + if (message) { + await say(channel, message); + } + + return true; } export { addVip }; diff --git a/src/backend/chatClient/clientActions/hasVip/index.ts b/src/backend/chatClient/clientActions/hasVip/index.ts new file mode 100644 index 0000000..8c3c57a --- /dev/null +++ b/src/backend/chatClient/clientActions/hasVip/index.ts @@ -0,0 +1,27 @@ +import { chatClient } from "../.."; + +type CacheType = Record>; +const cache: CacheType = {}; + +async function hasVip(channel: string, username: string): Promise { + if (!username) { + return false; + } + + if (!cache[channel]) { + const vips = await chatClient.getVips(channel); + + // * last VIP has a "." at the end of the username (bug on library?) + cache[channel] = vips.map(vip => vip.replace(/\.$/, "")); + + setTimeout(() => { + delete cache[channel]; + }, 2500); + } + + const vips = cache[channel]; + + return vips.includes(username); +} + +export { hasVip }; diff --git a/src/backend/chatClient/clientActions/index.ts b/src/backend/chatClient/clientActions/index.ts index 9a8a92b..fd337e9 100644 --- a/src/backend/chatClient/clientActions/index.ts +++ b/src/backend/chatClient/clientActions/index.ts @@ -1,6 +1,7 @@ import { addVip } from "./addVip"; +import { hasVip } from "./hasVip"; import { removeVip } from "./removeVip"; import { say } from "./say"; import { timeout } from "./timeout"; -export { say, timeout, addVip, removeVip }; +export { say, timeout, addVip, removeVip, hasVip }; diff --git a/src/backend/chatClient/clientActions/removeVip/index.ts b/src/backend/chatClient/clientActions/removeVip/index.ts index 1b9c3ac..5780ce9 100644 --- a/src/backend/chatClient/clientActions/removeVip/index.ts +++ b/src/backend/chatClient/clientActions/removeVip/index.ts @@ -1,18 +1,22 @@ import { chatClient } from "../.."; import { say } from ".."; -// removes a user from vips async function removeVip( channel: string, username: string, message?: string -): Promise { - if (!message) { - message = `VIP de @${username} eliminado.`; +): Promise { + try { + await chatClient.removeVip(channel, username); + } catch (e) { + return false; } - await chatClient.removeVip(channel, username); - say(channel, message); + if (message) { + await say(channel, message); + } + + return true; } export { removeVip }; diff --git a/src/backend/chatClient/index.ts b/src/backend/chatClient/index.ts index 85aeafd..f3e016f 100644 --- a/src/backend/chatClient/index.ts +++ b/src/backend/chatClient/index.ts @@ -2,6 +2,7 @@ import { addVip, removeVip, say, timeout } from "./clientActions"; import { getAuthProvider, getUsernameFromId } from "../helpers/twitch"; import { Action } from "../../interfaces/actions/Action"; +import { ActionType } from "../../enums/ActionType"; import { ChatClient } from "twitch-chat-client"; import { broadcast } from "../helpers/webServer"; import { start } from "../helpers/scheduledActions"; @@ -52,20 +53,20 @@ async function handleClientAction(action: Action): Promise { } switch (action.type) { - case "say": + case ActionType.Say: say(channel, action.data.message); break; - case "timeout": + case ActionType.Timeout: await timeout(channel, username, action.data.time, action.data.reason); break; - case "broadcast": + case ActionType.Broadcast: broadcast(action.data.message); break; - case "addVip": - await addVip(channel, username); + case ActionType.AddVip: + await addVip(channel, username, `Otorgado VIP a @${username}`); break; - case "removeVip": - await removeVip(channel, username); + case ActionType.RemoveVip: + await removeVip(channel, username, `Eliminado VIP de @${username}`); break; default: console.log(`${[LOG_PREFIX]}Couldn't handle action:`, action); diff --git a/src/backend/pubSubClient/actions/getVip.ts b/src/backend/pubSubClient/actions/getVip.ts new file mode 100644 index 0000000..f457dd8 --- /dev/null +++ b/src/backend/pubSubClient/actions/getVip.ts @@ -0,0 +1,29 @@ +import { addVip, hasVip } from "../../chatClient/clientActions"; + +import { LOG_PREFIX } from ".."; +import { RedemptionMessage } from "../../../interfaces/RedemptionMessage"; +import { getUsernameFromId } from "../../helpers/twitch"; + +async function getVip(msg: RedemptionMessage): Promise { + const channel = await getUsernameFromId(parseInt(msg.channelId)); + + if (!channel) { + console.log(`${LOG_PREFIX}No channel found`); + + return false; + } + + const addVipUser = msg.userDisplayName; + + if (await hasVip(channel, addVipUser)) { + console.log(`${LOG_PREFIX}@${addVipUser} is already VIP`); + + return false; + } + + const addedVip = await addVip(channel, addVipUser, msg.message); + + return addedVip; +} + +export { getVip }; diff --git a/src/backend/pubSubClient/actions/stealVip.ts b/src/backend/pubSubClient/actions/stealVip.ts index dd385a9..868d0f5 100644 --- a/src/backend/pubSubClient/actions/stealVip.ts +++ b/src/backend/pubSubClient/actions/stealVip.ts @@ -1,18 +1,17 @@ -import { chatClient, say } from "../../chatClient"; -import { - saveScheduledActions, - scheduledActions -} from "../../helpers/scheduledActions"; +import { addVip, hasVip, removeVip } from "../../chatClient/clientActions"; import { LOG_PREFIX } from ".."; +import { RedemptionMessage } from "../../../interfaces/RedemptionMessage"; import { getUsernameFromId } from "../../helpers/twitch"; // remove vip from a user to grant it to yourself -async function stealVip(msg: { - channelId: string; - userDisplayName: string; - message: string; -}): Promise { +async function stealVip(msg: RedemptionMessage): Promise { + if (!msg.message) { + console.log(`${LOG_PREFIX}Redemption has no message`); + + return false; + } + const channel = await getUsernameFromId(parseInt(msg.channelId)); if (!channel) { @@ -24,60 +23,26 @@ async function stealVip(msg: { const addVipUser = msg.userDisplayName; const removeVipUser = msg.message; - if (await hasVip(channel, removeVipUser)) { - await removeVip(channel, removeVipUser); - await addVip(channel, addVipUser); + if (!(await hasVip(channel, removeVipUser))) { + console.log(`${LOG_PREFIX}@${removeVipUser} is not VIP`); - const scheduledRemoveVipIndex = scheduledActions.findIndex( - s => s.action === "removeVip" && s.username === removeVipUser - ); - - if (scheduledRemoveVipIndex > -1) { - scheduledActions[scheduledRemoveVipIndex].username = addVipUser; - saveScheduledActions(); - } - - return true; - } - - return false; -} - -// adds a user to vips -async function addVip( - channel: string, - username: string, - message?: string -): Promise { - if (!message) { - message = `Otorgado VIP a @${username}.`; - } - - await chatClient.addVip(channel, username); - say(channel, message); -} - -async function hasVip(channel: string, username: string): Promise { - if (!username) { return false; } - const vips = await chatClient.getVips(channel); - return vips.includes(username); -} + if (await hasVip(channel, addVipUser)) { + console.log(`${LOG_PREFIX}@${addVipUser} is already VIP`); -// removes a user from vips -async function removeVip( - channel: string, - username: string, - message?: string -): Promise { - if (!message) { - message = `Se ha acabado el chollo, VIP de @${username} eliminado.`; + return false; } - await chatClient.removeVip(channel, username); - say(channel, message); + const removed = await removeVip(channel, removeVipUser); + const added = await addVip( + channel, + addVipUser, + `@${addVipUser} ha "tomado prestado" el VIP de @${removeVipUser}` + ); + + return removed && added; } export { stealVip }; diff --git a/src/backend/pubSubClient/index.ts b/src/backend/pubSubClient/index.ts index b49453e..1010cf3 100644 --- a/src/backend/pubSubClient/index.ts +++ b/src/backend/pubSubClient/index.ts @@ -1,8 +1,11 @@ import { PubSubClient, PubSubRedemptionMessage } from "twitch-pubsub-client"; +import { RedemptionIds } from "../../enums/Redemptions"; +import { RedemptionMessage } from "../../interfaces/RedemptionMessage"; import { UserIdResolvable } from "twitch"; import { broadcast } from "../helpers/webServer"; import { getApiClient } from "../helpers/twitch"; +import { getVip } from "./actions/getVip"; import { stealVip } from "./actions/stealVip"; const LOG_PREFIX = "[PubSub] "; @@ -24,7 +27,7 @@ async function onRedemption(message: PubSubRedemptionMessage) { // @ts-ignore const reward = message._data.data.redemption.reward; - const msg = { + const msg: RedemptionMessage = { id: message.id, channelId: message.channelId, rewardId: message.rewardId, @@ -40,14 +43,20 @@ async function onRedemption(message: PubSubRedemptionMessage) { }; switch (msg.rewardId) { - // robar vip - case "ac750bd6-fb4c-4259-b06d-56953601243b": + case RedemptionIds.StealVip: if (await stealVip(msg)) { - msg.message = `@${msg.userDisplayName} ha robado el VIP a @${msg.message}.`; + msg.message = `@${msg.userDisplayName} ha "tomado prestado" el VIP de @${msg.message}`; broadcast(JSON.stringify(msg)); } break; + case RedemptionIds.GetVip: + msg.message = `@${msg.userDisplayName} ha encontrado diamantes!`; + + if (await getVip(msg)) { + broadcast(JSON.stringify(msg)); + } + break; default: console.log(LOG_PREFIX, msg); diff --git a/src/enums/ActionType.ts b/src/enums/ActionType.ts new file mode 100644 index 0000000..e784b47 --- /dev/null +++ b/src/enums/ActionType.ts @@ -0,0 +1,7 @@ +export enum ActionType { + Say = "say", + Timeout = "timeout", + Broadcast = "broadcast", + AddVip = "addVip", + RemoveVip = "removeVip" +} diff --git a/src/enums/Redemptions.ts b/src/enums/Redemptions.ts new file mode 100644 index 0000000..5e69da1 --- /dev/null +++ b/src/enums/Redemptions.ts @@ -0,0 +1,9 @@ +export enum RedemptionIds { + KaraokeTime = "27faa7e4-f496-4e91-92ae-a51f99b9e854", + RussianRoulette = "a73247ee-e33e-4e9b-9105-bd9d11e111fc", + TimeoutFriend = "638c642d-23d8-4264-9702-e77eeba134de", + HighlightMessage = "a26c0d9e-fd2c-4943-bc94-c5c2f2c974e4", + GetVip = "a215d6a0-2c11-4503-bb29-1ca98ef046ac", + StealVip = "ac750bd6-fb4c-4259-b06d-56953601243b", + Hidrate = "232e951f-93d1-4138-a0e3-9e822b4852e0" +} diff --git a/src/interfaces/RedemptionMessage.ts b/src/interfaces/RedemptionMessage.ts new file mode 100644 index 0000000..a7fbb69 --- /dev/null +++ b/src/interfaces/RedemptionMessage.ts @@ -0,0 +1,11 @@ +export interface RedemptionMessage { + id: string; + channelId: string; + rewardId: string; + rewardName: string; + rewardImage: string; + message?: string; + userId: string; + userDisplayName: string; + backgroundColor: string; +} diff --git a/src/interfaces/actions/Action.ts b/src/interfaces/actions/Action.ts index 69731df..5b9670b 100644 --- a/src/interfaces/actions/Action.ts +++ b/src/interfaces/actions/Action.ts @@ -1,7 +1,9 @@ +import { ActionType } from "../../enums/ActionType"; + export interface Action { - type: string; - channelId: string; - userId: string; - scheduledAt?: number; - data: any; -} \ No newline at end of file + type: ActionType; + channelId: string; + userId: string; + scheduledAt?: number; + data: any; +} diff --git a/src/interfaces/actions/SayAction.ts b/src/interfaces/actions/SayAction.ts index 37b637b..55d522a 100644 --- a/src/interfaces/actions/SayAction.ts +++ b/src/interfaces/actions/SayAction.ts @@ -1,8 +1,9 @@ import { Action } from "./Action"; +import { ActionType } from "../../enums/ActionType"; export interface SayAction extends Action { - type: "say"; - data: { - message: "string"; - } -} \ No newline at end of file + type: ActionType.Say; + data: { + message: string; + }; +}