🎨 Format code
This commit is contained in:
@@ -7,10 +7,10 @@ import { start } from "./scheduledActions";
|
|||||||
let chatClient: ChatClient;
|
let chatClient: ChatClient;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
chatClient,
|
chatClient,
|
||||||
connect,
|
connect,
|
||||||
handleClientAction,
|
handleClientAction,
|
||||||
say
|
say
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: clean/refactor code
|
// TODO: clean/refactor code
|
||||||
@@ -18,76 +18,88 @@ export {
|
|||||||
const LOG_PREFIX = "[ChatClient] ";
|
const LOG_PREFIX = "[ChatClient] ";
|
||||||
|
|
||||||
async function connect(channels: Array<any>): Promise<void> {
|
async function connect(channels: Array<any>): Promise<void> {
|
||||||
const authProvider = await getAuthProvider();
|
const authProvider = await getAuthProvider();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
chatClient &&
|
chatClient &&
|
||||||
(
|
(
|
||||||
chatClient.isConnecting ||
|
chatClient.isConnecting ||
|
||||||
chatClient.isConnected
|
chatClient.isConnected
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chatClient = new ChatClient(authProvider, { channels: channels });
|
chatClient = new ChatClient(authProvider, { channels: channels });
|
||||||
|
|
||||||
chatClient.onConnect(onConnect);
|
chatClient.onConnect(onConnect);
|
||||||
|
|
||||||
chatClient.onDisconnect((e: any) => {
|
chatClient.onDisconnect((e: any) => {
|
||||||
console.log(`${LOG_PREFIX}Disconnected ${e.message}`);
|
console.log(`${LOG_PREFIX}Disconnected ${e.message}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
chatClient.onNoPermission((channel, message) => {
|
chatClient.onNoPermission((channel, message) => {
|
||||||
console.log(`${LOG_PREFIX}No permission on ${channel}: ${message}`);
|
console.log(`${LOG_PREFIX}No permission on ${channel}: ${message}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
await chatClient.connect();
|
await chatClient.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onConnect(): Promise<void> {
|
async function onConnect(): Promise<void> {
|
||||||
console.log(`${LOG_PREFIX}Connected`);
|
console.log(`${LOG_PREFIX}Connected`);
|
||||||
|
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleClientAction(action: any): Promise<void> {
|
async function handleClientAction(action: any): Promise<void> {
|
||||||
if (action.channel && !isNaN(action.channel)) {
|
if (
|
||||||
action.channel = await getUsernameFromId(parseInt(action.channel));
|
action.channel &&
|
||||||
}
|
!isNaN(action.channel)
|
||||||
if (action.username && !isNaN(action.username)) {
|
) {
|
||||||
action.username = await getUsernameFromId(parseInt(action.username));
|
action.channel = await getUsernameFromId(parseInt(action.channel));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: create a interface for action messages
|
if (
|
||||||
if (!action.channel) {
|
action.username &&
|
||||||
action.channel = "alexbcberio";
|
!isNaN(action.username)
|
||||||
}
|
) {
|
||||||
|
action.username = await getUsernameFromId(parseInt(action.username));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: create a interface for action messages
|
||||||
|
if (!action.channel) {
|
||||||
|
action.channel = "alexbcberio";
|
||||||
|
}
|
||||||
|
|
||||||
switch (action.action) {
|
switch (action.action) {
|
||||||
case "say":
|
case "say":
|
||||||
say(action.channel, action.message);
|
say(action.channel, action.message);
|
||||||
break;
|
break;
|
||||||
case "timeout":
|
case "timeout":
|
||||||
await timeout(action.channel, action.username, action.time, action.reason);
|
await timeout(
|
||||||
break;
|
action.channel,
|
||||||
case "broadcast":
|
action.username,
|
||||||
broadcast(action.message);
|
action.time,
|
||||||
break;
|
action.reason
|
||||||
case "addVip":
|
);
|
||||||
await addVip(action.channel, action.username);
|
break;
|
||||||
break;
|
case "broadcast":
|
||||||
case "removeVip":
|
broadcast(action.message);
|
||||||
await removeVip(action.channel, action.username);
|
break;
|
||||||
break;
|
case "addVip":
|
||||||
default:
|
await addVip(action.channel, action.username);
|
||||||
console.log(`${[LOG_PREFIX]}Couldn't handle action:`, action);
|
break;
|
||||||
}
|
case "removeVip":
|
||||||
|
await removeVip(action.channel, action.username);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(`${[LOG_PREFIX]}Couldn't handle action:`, action);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// send a chat message
|
// send a chat message
|
||||||
async function say(channel: string, message: string): Promise<void> {
|
async function say(channel: string, message: string): Promise<void> {
|
||||||
await chatClient.say(channel, message);
|
await chatClient.say(channel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// timeouts a user in a channel
|
// timeouts a user in a channel
|
||||||
@@ -97,37 +109,45 @@ async function timeout(
|
|||||||
time?: number,
|
time?: number,
|
||||||
reason?: string
|
reason?: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!time) {
|
if (!time) {
|
||||||
time = 60;
|
time = 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reason) {
|
if (!reason) {
|
||||||
reason = "";
|
reason = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await chatClient.timeout(channel, username, time, reason);
|
await chatClient.timeout(channel, username, time, reason);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// user cannot be timed out
|
// user cannot be timed out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds a user to vips
|
// adds a user to vips
|
||||||
async function addVip(channel: string, username: string, message?: string): Promise<void> {
|
async function addVip(
|
||||||
if (!message) {
|
channel: string,
|
||||||
message = `Otorgado VIP a @${username}.`;
|
username: string,
|
||||||
}
|
message?: string
|
||||||
|
): Promise<void> {
|
||||||
|
if (!message) {
|
||||||
|
message = `Otorgado VIP a @${username}.`;
|
||||||
|
}
|
||||||
|
|
||||||
await chatClient.addVip(channel, username);
|
await chatClient.addVip(channel, username);
|
||||||
say(channel, message);
|
say(channel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes a user from vips
|
// removes a user from vips
|
||||||
async function removeVip(channel: string, username: string, message?: string): Promise<void> {
|
async function removeVip(
|
||||||
if (!message) {
|
channel: string,
|
||||||
message = `VIP de @${username} eliminado.`;
|
username: string,
|
||||||
}
|
message?: string
|
||||||
|
): Promise<void> {
|
||||||
|
if (!message) {
|
||||||
|
message = `VIP de @${username} eliminado.`;
|
||||||
|
}
|
||||||
|
|
||||||
await chatClient.removeVip(channel, username);
|
await chatClient.removeVip(channel, username);
|
||||||
say(channel, message);
|
say(channel, message);
|
||||||
}
|
}
|
@@ -7,59 +7,59 @@ import { UserIdResolvable } from "twitch";
|
|||||||
import { broadcast } from "./webServer";
|
import { broadcast } from "./webServer";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
registerUserListener
|
registerUserListener
|
||||||
}
|
};
|
||||||
|
|
||||||
// TODO: clean/refactor code
|
// TODO: clean/refactor code
|
||||||
|
|
||||||
const LOG_PREFIX = "[PubSub] ";
|
const LOG_PREFIX = "[PubSub] ";
|
||||||
|
|
||||||
async function registerUserListener(user: UserIdResolvable) {
|
async function registerUserListener(user: UserIdResolvable) {
|
||||||
const apiClient = await getApiClient();
|
const apiClient = await getApiClient();
|
||||||
|
|
||||||
const pubSubClient = new PubSubClient();
|
const pubSubClient = new PubSubClient();
|
||||||
const userId = await pubSubClient.registerUserListener(apiClient, user);
|
const userId = await pubSubClient.registerUserListener(apiClient, user);
|
||||||
/*const listener = */ await pubSubClient.onRedemption(userId, onRedemption);
|
/*const listener = */ await pubSubClient.onRedemption(userId, onRedemption);
|
||||||
|
|
||||||
console.log(`${LOG_PREFIX}Connected & registered`);
|
console.log(`${LOG_PREFIX}Connected & registered`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onRedemption(message: PubSubRedemptionMessage) {
|
async function onRedemption(message: PubSubRedemptionMessage) {
|
||||||
console.log(
|
console.log(
|
||||||
`${LOG_PREFIX}Reward: "${message.rewardName}" (${message.rewardId}) redeemed by ${message.userDisplayName}`
|
`${LOG_PREFIX}Reward: "${message.rewardName}" (${message.rewardId}) redeemed by ${message.userDisplayName}`
|
||||||
);
|
);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const reward = message._data.data.redemption.reward;
|
const reward = message._data.data.redemption.reward;
|
||||||
|
|
||||||
const msg = {
|
const msg = {
|
||||||
id: message.id,
|
id: message.id,
|
||||||
channelId: message.channelId,
|
channelId: message.channelId,
|
||||||
rewardId: message.rewardId,
|
rewardId: message.rewardId,
|
||||||
rewardName: message.rewardName,
|
rewardName: message.rewardName,
|
||||||
rewardImage: message.rewardImage
|
rewardImage: message.rewardImage
|
||||||
? message.rewardImage.url_4x
|
? message.rewardImage.url_4x
|
||||||
: "https://static-cdn.jtvnw.net/custom-reward-images/default-4.png",
|
: "https://static-cdn.jtvnw.net/custom-reward-images/default-4.png",
|
||||||
message: message.message,
|
message: message.message,
|
||||||
userDisplayName: message.userDisplayName,
|
userDisplayName: message.userDisplayName,
|
||||||
// non directly available values from PubSubRedemptionMessage
|
// non directly available values from PubSubRedemptionMessage
|
||||||
backgroundColor: reward.background_color
|
backgroundColor: reward.background_color
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (msg.rewardId) {
|
switch (msg.rewardId) {
|
||||||
// robar vip
|
// robar vip
|
||||||
case "ac750bd6-fb4c-4259-b06d-56953601243b":
|
case "ac750bd6-fb4c-4259-b06d-56953601243b":
|
||||||
if (await stealVip(msg)) {
|
if (await stealVip(msg)) {
|
||||||
msg.message = `@${msg.userDisplayName} ha robado el VIP a @${msg.message}.`;
|
msg.message = `@${msg.userDisplayName} ha robado el VIP a @${msg.message}.`;
|
||||||
|
|
||||||
broadcast(JSON.stringify(msg));
|
broadcast(JSON.stringify(msg));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.log(LOG_PREFIX, msg);
|
console.log(LOG_PREFIX, msg);
|
||||||
|
|
||||||
broadcast(JSON.stringify(msg));
|
broadcast(JSON.stringify(msg));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: extract methods
|
// TODO: extract methods
|
||||||
@@ -70,61 +70,69 @@ async function stealVip(msg: {
|
|||||||
userDisplayName: string;
|
userDisplayName: string;
|
||||||
message: string;
|
message: string;
|
||||||
}): Promise<boolean> {
|
}): Promise<boolean> {
|
||||||
const channel = await getUsernameFromId(parseInt(msg.channelId));
|
const channel = await getUsernameFromId(parseInt(msg.channelId));
|
||||||
|
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
console.log(`${LOG_PREFIX}No channel found`);
|
console.log(`${LOG_PREFIX}No channel found`);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const addVipUser = msg.userDisplayName;
|
const addVipUser = msg.userDisplayName;
|
||||||
const removeVipUser = msg.message;
|
const removeVipUser = msg.message;
|
||||||
|
|
||||||
if (await hasVip(channel, removeVipUser)) {
|
if (await hasVip(channel, removeVipUser)) {
|
||||||
await removeVip(channel, removeVipUser);
|
await removeVip(channel, removeVipUser);
|
||||||
await addVip(channel, addVipUser);
|
await addVip(channel, addVipUser);
|
||||||
|
|
||||||
const scheduledRemoveVipIndex = scheduledActions.findIndex(
|
const scheduledRemoveVipIndex = scheduledActions.findIndex(
|
||||||
s => s.action === "removeVip" && s.username === removeVipUser
|
s => s.action === "removeVip" && s.username === removeVipUser
|
||||||
);
|
);
|
||||||
|
|
||||||
if (scheduledRemoveVipIndex > -1) {
|
if (scheduledRemoveVipIndex > -1) {
|
||||||
scheduledActions[scheduledRemoveVipIndex].username = addVipUser;
|
scheduledActions[scheduledRemoveVipIndex].username = addVipUser;
|
||||||
saveScheduledActions();
|
saveScheduledActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds a user to vips
|
// adds a user to vips
|
||||||
async function addVip(channel: string, username: string, message?: string): Promise<void> {
|
async function addVip(
|
||||||
if (!message) {
|
channel: string,
|
||||||
message = `Otorgado VIP a @${username}.`;
|
username: string,
|
||||||
}
|
message?: string
|
||||||
|
): Promise<void> {
|
||||||
|
if (!message) {
|
||||||
|
message = `Otorgado VIP a @${username}.`;
|
||||||
|
}
|
||||||
|
|
||||||
await chatClient.addVip(channel, username);
|
await chatClient.addVip(channel, username);
|
||||||
say(channel, message);
|
say(channel, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function hasVip(channel: string, username: string): Promise<boolean> {
|
async function hasVip(channel: string, username: string): Promise<boolean> {
|
||||||
if (!username) {
|
if (!username) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vips = await chatClient.getVips(channel);
|
const vips = await chatClient.getVips(channel);
|
||||||
return vips.includes(username);
|
return vips.includes(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
// removes a user from vips
|
// removes a user from vips
|
||||||
async function removeVip(channel: string, username: string, message?: string): Promise<void> {
|
async function removeVip(
|
||||||
if (!message) {
|
channel: string,
|
||||||
message = `Se ha acabado el chollo, VIP de @${username} eliminado.`;
|
username: string,
|
||||||
}
|
message?: string
|
||||||
|
): Promise<void> {
|
||||||
|
if (!message) {
|
||||||
|
message = `Se ha acabado el chollo, VIP de @${username} eliminado.`;
|
||||||
|
}
|
||||||
|
|
||||||
await chatClient.removeVip(channel, username);
|
await chatClient.removeVip(channel, username);
|
||||||
say(channel, message);
|
say(channel, message);
|
||||||
}
|
}
|
@@ -3,10 +3,10 @@ import { handleClientAction } from "./chatClient";
|
|||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
start,
|
start,
|
||||||
scheduledActions,
|
scheduledActions,
|
||||||
checkScheduledActions,
|
checkScheduledActions,
|
||||||
saveScheduledActions
|
saveScheduledActions
|
||||||
};
|
};
|
||||||
|
|
||||||
const LOG_PREFIX = "[Scheduled] ";
|
const LOG_PREFIX = "[Scheduled] ";
|
||||||
@@ -44,7 +44,7 @@ async function start(): Promise<void> {
|
|||||||
async function checkScheduledActions(): Promise<void> {
|
async function checkScheduledActions(): Promise<void> {
|
||||||
if (checkingScheduled) {
|
if (checkingScheduled) {
|
||||||
return;
|
return;
|
||||||
};
|
}
|
||||||
|
|
||||||
checkingScheduled = true;
|
checkingScheduled = true;
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { TokenData } from "../../interfaces/TokenData";
|
import { TokenData } from "../../interfaces/TokenData";
|
||||||
import {promises as fs} from "fs";
|
import { promises as fs } from "fs";
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
|
|
||||||
const TOKENS_FILE = "tokens.json";
|
const TOKENS_FILE = "tokens.json";
|
||||||
@@ -8,44 +8,45 @@ const LOG_PREFIX = "[TokenData] ";
|
|||||||
export {
|
export {
|
||||||
getTokenData,
|
getTokenData,
|
||||||
saveTokenData
|
saveTokenData
|
||||||
}
|
};
|
||||||
|
|
||||||
function getTokenDataFilePath(): string {
|
function getTokenDataFilePath(): string {
|
||||||
return resolve(process.cwd(), TOKENS_FILE);
|
return resolve(process.cwd(), TOKENS_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getTokenData(): Promise<TokenData> {
|
async function getTokenData(): Promise<TokenData> {
|
||||||
const tokenDataFilePath = getTokenDataFilePath();
|
const tokenDataFilePath = getTokenDataFilePath();
|
||||||
let buffer: Buffer;
|
let buffer: Buffer;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
buffer = await fs.readFile(tokenDataFilePath);
|
buffer = await fs.readFile(tokenDataFilePath);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(`${LOG_PREFIX}${TOKENS_FILE} not found on ${tokenDataFilePath}.`);
|
console.error(
|
||||||
process.exit(1);
|
`${LOG_PREFIX}${TOKENS_FILE} not found on ${tokenDataFilePath}.`
|
||||||
}
|
);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
const tokenData = await JSON.parse(buffer.toString());
|
const tokenData = await JSON.parse(buffer.toString());
|
||||||
|
|
||||||
checkTokenData(tokenData);
|
checkTokenData(tokenData);
|
||||||
|
|
||||||
return tokenData;
|
return tokenData;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveTokenData(tokenData: TokenData): Promise<void> {
|
async function saveTokenData(tokenData: TokenData): Promise<void> {
|
||||||
const tokenDataFilePath = getTokenDataFilePath();
|
const tokenDataFilePath = getTokenDataFilePath();
|
||||||
const jsonTokenData = JSON.stringify(tokenData);
|
const jsonTokenData = JSON.stringify(tokenData);
|
||||||
|
|
||||||
await fs.writeFile(tokenDataFilePath, jsonTokenData);
|
await fs.writeFile(tokenDataFilePath, jsonTokenData);
|
||||||
console.log(`${LOG_PREFIX}Token data saved`);
|
console.log(`${LOG_PREFIX}Token data saved`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkTokenData(tokenData: TokenData): void {
|
function checkTokenData(tokenData: TokenData): void {
|
||||||
if (
|
if (!tokenData.access_token || !tokenData.refresh_token) {
|
||||||
!tokenData.access_token ||
|
console.error(
|
||||||
!tokenData.refresh_token
|
`${LOG_PREFIX}Missing refresh_token or access_token in ${TOKENS_FILE}.`
|
||||||
) {
|
);
|
||||||
console.error(`${LOG_PREFIX}Missing refresh_token or access_token in ${TOKENS_FILE}.`);
|
process.exit(1);
|
||||||
process.exit(1);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
@@ -1,4 +1,8 @@
|
|||||||
import { AccessToken, RefreshableAuthProvider, StaticAuthProvider } from "twitch-auth";
|
import {
|
||||||
|
AccessToken,
|
||||||
|
RefreshableAuthProvider,
|
||||||
|
StaticAuthProvider
|
||||||
|
} from "twitch-auth";
|
||||||
import { getTokenData, saveTokenData } from "./tokenData";
|
import { getTokenData, saveTokenData } from "./tokenData";
|
||||||
|
|
||||||
import { ApiClient } from "twitch";
|
import { ApiClient } from "twitch";
|
||||||
@@ -13,92 +17,91 @@ export {
|
|||||||
getAuthProvider,
|
getAuthProvider,
|
||||||
getApiClient,
|
getApiClient,
|
||||||
getUsernameFromId
|
getUsernameFromId
|
||||||
}
|
};
|
||||||
|
|
||||||
function getClientCredentials(): ClientCredentials {
|
function getClientCredentials(): ClientCredentials {
|
||||||
if (
|
if (
|
||||||
!process.env.TWITCH_CLIENT_ID ||
|
!process.env.TWITCH_CLIENT_ID ||
|
||||||
!process.env.TWITCH_CLIENT_SECRET
|
!process.env.TWITCH_CLIENT_SECRET
|
||||||
) {
|
) {
|
||||||
console.error(
|
console.error(
|
||||||
`${LOG_PREFIX}Missing environment parameters TWITCH_CLIENT_ID or TWITCH_CLIENT_SECRET`
|
`${LOG_PREFIX}Missing environment parameters TWITCH_CLIENT_ID or TWITCH_CLIENT_SECRET`
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
clientId: process.env.TWITCH_CLIENT_ID,
|
clientId: process.env.TWITCH_CLIENT_ID,
|
||||||
clientSecret: process.env.TWITCH_CLIENT_SECRET
|
clientSecret: process.env.TWITCH_CLIENT_SECRET
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createStaticAuthProvider(): Promise<StaticAuthProvider> {
|
async function createStaticAuthProvider(): Promise<StaticAuthProvider> {
|
||||||
let tokenData = await getTokenData();
|
let tokenData = await getTokenData();
|
||||||
const credentials = getClientCredentials();
|
const credentials = getClientCredentials();
|
||||||
|
|
||||||
return new StaticAuthProvider(
|
return new StaticAuthProvider(credentials.clientId, tokenData.access_token);
|
||||||
credentials.clientId,
|
|
||||||
tokenData.access_token
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getAuthProvider(): Promise<RefreshableAuthProvider> {
|
async function getAuthProvider(): Promise<RefreshableAuthProvider> {
|
||||||
if (refreshAuthProvider) {
|
if (refreshAuthProvider) {
|
||||||
return refreshAuthProvider;
|
return refreshAuthProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tokenData = await getTokenData();
|
let tokenData = await getTokenData();
|
||||||
|
|
||||||
const staticAuthProvider = await createStaticAuthProvider();
|
const staticAuthProvider = await createStaticAuthProvider();
|
||||||
const credentials = getClientCredentials();
|
const credentials = getClientCredentials();
|
||||||
|
|
||||||
const expiry = tokenData.expiryTimestamp === null
|
const expiry =
|
||||||
? null
|
tokenData.expiryTimestamp === null
|
||||||
: new Date(tokenData.expiryTimestamp);
|
? null
|
||||||
|
: new Date(tokenData.expiryTimestamp);
|
||||||
|
|
||||||
refreshAuthProvider = new RefreshableAuthProvider(
|
refreshAuthProvider = new RefreshableAuthProvider(staticAuthProvider, {
|
||||||
staticAuthProvider,
|
clientSecret: credentials.clientSecret,
|
||||||
{
|
refreshToken: tokenData.refresh_token,
|
||||||
clientSecret: credentials.clientSecret,
|
expiry,
|
||||||
refreshToken: tokenData.refresh_token,
|
onRefresh: onRefresh
|
||||||
expiry,
|
});
|
||||||
onRefresh: onRefresh
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return refreshAuthProvider;
|
return refreshAuthProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onRefresh(refreshData: AccessToken): Promise<void> {
|
async function onRefresh(refreshData: AccessToken): Promise<void> {
|
||||||
const { accessToken, refreshToken, expiryDate } = refreshData;
|
const {
|
||||||
console.log(`${LOG_PREFIX}Tokens refreshed`);
|
accessToken,
|
||||||
|
refreshToken,
|
||||||
|
expiryDate
|
||||||
|
} = refreshData;
|
||||||
|
console.log(`${LOG_PREFIX}Tokens refreshed`);
|
||||||
|
|
||||||
const expiryTimestamp = expiryDate === null
|
const expiryTimestamp = expiryDate === null
|
||||||
? 0
|
? 0
|
||||||
: expiryDate.getTime()
|
: expiryDate.getTime();
|
||||||
|
|
||||||
const newTokenData: TokenData = {
|
const newTokenData: TokenData = {
|
||||||
access_token: accessToken,
|
access_token: accessToken,
|
||||||
refresh_token: refreshToken,
|
refresh_token: refreshToken,
|
||||||
expiryTimestamp
|
expiryTimestamp
|
||||||
};
|
};
|
||||||
|
|
||||||
await saveTokenData(newTokenData);
|
await saveTokenData(newTokenData);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getApiClient(): Promise<ApiClient> {
|
async function getApiClient(): Promise<ApiClient> {
|
||||||
const authProvider = await getAuthProvider();
|
const authProvider = await getAuthProvider();
|
||||||
|
|
||||||
return await new ApiClient({ authProvider });
|
return await new ApiClient({ authProvider });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getUsernameFromId(userId: number): Promise<string | null> {
|
async function getUsernameFromId(userId: number): Promise<string | null> {
|
||||||
const apiClient = await getApiClient();
|
const apiClient = await getApiClient();
|
||||||
const user = await apiClient.helix.users.getUserById(userId);
|
const user = await apiClient.helix.users.getUserById(userId);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return user.displayName;
|
return user.displayName;
|
||||||
}
|
}
|
@@ -22,40 +22,44 @@ const wsServer = new WebSocket.Server({
|
|||||||
let server: Server;
|
let server: Server;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
listen,
|
listen,
|
||||||
broadcast
|
broadcast
|
||||||
}
|
};
|
||||||
|
|
||||||
wsServer.on("connection", onConnection);
|
wsServer.on("connection", onConnection);
|
||||||
|
|
||||||
app.use(express.static(join(process.cwd(), "client")));
|
app.use(express.static(join(process.cwd(), "client")));
|
||||||
|
|
||||||
function listen() {
|
function listen() {
|
||||||
if (server) {
|
if (server) {
|
||||||
console.log(`${LOG_PREFIX_HTTP}Server is already running`);
|
console.log(`${LOG_PREFIX_HTTP}Server is already running`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
server = app.listen(!isDevelopment ? 8080 : 8081, "0.0.0.0");
|
server = app.listen(!isDevelopment ? 8080 : 8081, "0.0.0.0");
|
||||||
|
|
||||||
server.on("listening", onListening);
|
server.on("listening", onListening);
|
||||||
server.on("upgrade", onUpgrade);
|
server.on("upgrade", onUpgrade);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onListening() {
|
function onListening() {
|
||||||
console.log(
|
console.log(
|
||||||
`${LOG_PREFIX_HTTP}Listening on port ${(server.address() as AddressInfo).port}`
|
`${LOG_PREFIX_HTTP}Listening on port ${
|
||||||
);
|
(server.address() as AddressInfo).port
|
||||||
|
}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onUpgrade(req: IncomingMessage, socket: Socket, head: Buffer) {
|
function onUpgrade(req: IncomingMessage, socket: Socket, head: Buffer) {
|
||||||
wsServer.handleUpgrade(req, socket, head, socket => {
|
wsServer.handleUpgrade(req, socket, head, socket => {
|
||||||
wsServer.emit("connection", socket, req);
|
wsServer.emit("connection", socket, req);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onConnection(socket: WebSocket, req: IncomingMessage) {
|
function onConnection(socket: WebSocket, req: IncomingMessage) {
|
||||||
console.log(`${LOG_PREFIX_WS}${req.socket.remoteAddress} New connection established`);
|
console.log(
|
||||||
|
`${LOG_PREFIX_WS}${req.socket.remoteAddress} New connection established`
|
||||||
|
);
|
||||||
sockets.push(socket);
|
sockets.push(socket);
|
||||||
socket.send(
|
socket.send(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
@@ -69,11 +73,11 @@ function onConnection(socket: WebSocket, req: IncomingMessage) {
|
|||||||
|
|
||||||
// broadcast a message to all clients
|
// broadcast a message to all clients
|
||||||
function broadcast(msg: string, socket?: any) {
|
function broadcast(msg: string, socket?: any) {
|
||||||
const filteredSockets = socket
|
const filteredSockets = socket
|
||||||
? sockets.filter(s => s !== socket)
|
? sockets.filter(s => s !== socket)
|
||||||
: sockets;
|
: sockets;
|
||||||
|
|
||||||
filteredSockets.forEach(s => s.send(msg));
|
filteredSockets.forEach(s => s.send(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onMessage(msg: string) {
|
async function onMessage(msg: string) {
|
||||||
@@ -81,7 +85,10 @@ async function onMessage(msg: string) {
|
|||||||
const socket = this as WebSocket;
|
const socket = this as WebSocket;
|
||||||
const data = JSON.parse(msg);
|
const data = JSON.parse(msg);
|
||||||
|
|
||||||
if (!data.actions || data.actions.length === 0) {
|
if (
|
||||||
|
!data.actions ||
|
||||||
|
data.actions.length === 0
|
||||||
|
) {
|
||||||
broadcast(msg, socket);
|
broadcast(msg, socket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -96,14 +103,17 @@ async function onMessage(msg: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`${LOG_PREFIX_WS}Received message with ${data.actions.length} actions:`, data);
|
console.log(
|
||||||
|
`${LOG_PREFIX_WS}Received message with ${data.actions.length} actions:`,
|
||||||
|
data
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClose() {
|
function onClose() {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const socket: WebSocket = this as WebSocket;
|
const socket: WebSocket = this as WebSocket;
|
||||||
|
|
||||||
const socketIdx = sockets.indexOf(socket);
|
const socketIdx = sockets.indexOf(socket);
|
||||||
sockets.splice(socketIdx, 1);
|
sockets.splice(socketIdx, 1);
|
||||||
console.log(`${LOG_PREFIX_WS}Connection closed`);
|
console.log(`${LOG_PREFIX_WS}Connection closed`);
|
||||||
}
|
}
|
Reference in New Issue
Block a user