Restore Core Functionality

This commit is contained in:
DeSqBlocki
2025-02-08 02:03:18 +01:00
parent 43958830cf
commit 21115a66fb
12 changed files with 427 additions and 73 deletions
+205 -72
View File
@@ -1,93 +1,132 @@
const { MongoClient } = require('mongodb');
require('dotenv').config()
const mClient = new MongoClient(process.env.mongo_uri)
exports.mClient = mClient;
require('dotenv').config();
const fs = require('node:fs');
const { Client, GatewayIntentBits } = require('discord.js');
const tmi = require('tmi.js');
const axios = require('axios');
// Validate required environment variables
function validateEnvVariables() {
const requiredVars = ['MONGO_URI', 'MONGO_DB'];
const missingVars = requiredVars.filter((varName) => !process.env[varName]);
async function connectToMongo() {
await mClient.connect();
console.log('Connected to MongoDB');
async function getChannelInformation(broadcasterId) {
const endpoint = `channels?broadcaster_id=${broadcasterId}`;
const channelInfo = await makeTwitchRequest(endpoint);
if (channelInfo) {
console.log('Channel Information:', channelInfo);
} else {
console.log('Failed to retrieve channel information.');
}
if (missingVars.length > 0) {
console.error(`Missing required environment variables: ${missingVars.join(', ')}`);
process.exit(1);
}
getChannelInformation(process.env.test_id);
}
connectToMongo();
async function saveToken(accessToken, refreshToken, expires_in) {
let db = mClient.db(process.env.mongo_db);
let tokenCollection = db.collection("twitch-token");
validateEnvVariables();
// Initialize MongoDB Client
const mClient = new MongoClient(process.env.MONGO_URI);
async function initializeMongoClient() {
try {
await mClient.connect();
console.log('MongoDB connected successfully.');
// Emit event or proceed with dependent initializations here
} catch (error) {
console.error('Failed to connect to MongoDB:', error);
process.exit(1); // Exit the process if the connection fails
}
}
initializeMongoClient();
// Function to save tokens to MongoDB
async function saveToken(access_token, refresh_token, expiresIn, scope) {
const db = mClient.db(process.env.MONGO_DB);
const credentialCollection = db.collection('credentials');
const tokenData = {
accessToken,
refreshToken,
expires_in,
obtainedAt: Date.now()
access_token,
refresh_token,
scope,
expiresIn,
obtainedAt: Date.now(),
};
await tokenCollection.updateOne({}, { $set: tokenData }, { upsert: true });
console.log('TTV Token updated in MongoDB');
await credentialCollection.updateOne(
{ service: 'twitch' },
{ $set: { token: tokenData } },
{ upsert: true }
);
console.log('Twitch token updated in MongoDB');
}
async function getStoredToken() {
let db = mClient.db(process.env.mongo_db);
let tokenCollection = db.collection("twitch-token");
const tokenData = await tokenCollection.findOne({});
if (tokenData) {
// Function to retrieve stored tokens from MongoDB
async function getStoredToken() {
const db = mClient.db(process.env.MONGO_DB);
const credentialCollection = db.collection('credentials');
const tCreds = await credentialCollection.findOne({ service: 'twitch' });
if (tCreds) {
console.log('Loaded token from MongoDB');
return tokenData;
return tCreds.token;
} else {
console.log('No token found in MongoDB');
return null;
}
}
const axios = require('axios');
// Function to refresh the access token
let isRefreshingToken = false;
let refreshPromise = null;
async function refreshAccessToken() {
let db = mClient.db(process.env.mongo_db)
let credentialCollection = db.collection('credentials')
let credentials = await credentialCollection.find({ service: 'twitch' }).toArray()
if (isRefreshingToken) {
return refreshPromise; // Return the existing refresh promise if a refresh is already in progress
}
isRefreshingToken = true;
refreshPromise = (async () => {
try {
const db = mClient.db(process.env.MONGO_DB);
const credentialCollection = db.collection('credentials');
const credentials = await credentialCollection.findOne({ service: 'twitch' });
const token = await getStoredToken();
if (!token) {
throw new Error('No token found! Please authenticate manually.');
}
const response = await axios.post('https://id.twitch.tv/oauth2/token', null, {
params: {
grant_type: 'refresh_token',
refresh_token: token.refresh_token,
client_id: credentials.client_id,
scope: token.scope,
client_secret: credentials.client_secret,
},
});
const newAccessToken = response.data.access_token;
const newRefreshToken = response.data.refresh_token || token.refresh_token;
const newExpirationDate = response.data.expires_in || 0;
await saveToken(newAccessToken, newRefreshToken, newExpirationDate, token.scope);
console.log('Access token refreshed successfully.');
return newAccessToken;
} catch (error) {
console.error('Failed to refresh access token:', error.response?.data || error.message);
throw error;
} finally {
isRefreshingToken = false;
refreshPromise = null;
}
})();
return refreshPromise;
}
// Function to make requests to the Twitch API
async function makeTwitchRequest(endpoint) {
const db = mClient.db(process.env.MONGO_DB);
const credentialCollection = db.collection('credentials');
const credentials = await credentialCollection.findOne({ service: 'twitch' });
const token = await getStoredToken();
if (!token) {
console.error('No token found! Please authenticate manually.');
return;
}
try {
const response = await axios.post('https://id.twitch.tv/oauth2/token', null, {
params: {
grant_type: 'refresh_token',
refresh_token: token.refreshToken,
client_id: credentials.client_id,
client_secret: credentials.client_secret
}
});
const newAccessToken = response.data.access_token;
const newRefreshToken = response.data.refresh_token || token.refreshToken;
const newExpirationDate = response.data.expires_in || 0
await saveToken(newAccessToken, newRefreshToken, newExpirationDate);
console.log('Access token refreshed successfully');
} catch (error) {
console.error('Failed to refresh access token:', error.response?.data || error.message);
}
}
async function makeTwitchRequest(endpoint) {
let db = mClient.db(process.env.mongo_db)
let credentialCollection = db.collection('credentials')
let credentials = await credentialCollection.findOne({ service: 'twitch' })
let token = await getStoredToken();
if (!token.access_token) {
console.error('No access token available.');
return;
@@ -97,14 +136,13 @@ async function makeTwitchRequest(endpoint) {
const response = await axios.get(`https://api.twitch.tv/helix/${endpoint}`, {
headers: {
'Client-Id': credentials.client_id,
'Authorization': `Bearer ${token.access_token}`
}
'Authorization': `Bearer ${token.access_token}`,
},
});
return response.data;
} catch (error) {
if (error.response?.status === 401) {
console.log(error)
console.log('Access token expired. Refreshing...');
const newToken = await refreshAccessToken();
if (newToken) {
@@ -114,4 +152,99 @@ async function makeTwitchRequest(endpoint) {
console.error('Twitch API request failed:', error.response?.data || error.message);
}
}
}
// Initialize Discord Client
const dClient = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
],
});
exports.dClient = dClient;
// Load Discord event handlers
fs.readdirSync('./handlers').forEach((handler) => {
require(`./handlers/${handler}`)(dClient);
});
// Function to log in to Discord
async function dLogin() {
try {
const db = mClient.db(process.env.MONGO_DB);
const credentialCollection = db.collection('credentials');
const dCreds = await credentialCollection.findOne({ service: 'discord' });
if (!dCreds || !dCreds.token) {
throw new Error('Discord credentials not found.');
}
await dClient.login(dCreds.token);
console.log('Discord client logged in successfully.');
} catch (error) {
console.error('Discord login failed:', error);
}
}
dLogin();
// Function to log in to Twitch
async function tLogin() {
const channels = ['desq_blocki'];
const db = mClient.db(process.env.MONGO_DB);
const credentialCollection = db.collection('credentials');
const tCreds = await credentialCollection.findOne({ service: 'twitch' });
if (!tCreds || !tCreds.username || !tCreds.token || !tCreds.token.access_token) {
console.error('Twitch credentials are missing or incomplete.');
return;
}
const tClient = new tmi.Client({
options: { debug: false },
connection: {
reconnect: true,
secure: true,
},
identity: {
username: tCreds.username,
password: `oauth:${tCreds.token.access_token}`,
},
channels: channels,
});
tClient.connect();
// Handle Twitch events
tClient.on('connected', (address, port) => {
dClient.emit('Twitch/Connected', address, port);
});
tClient.on('message', async (channel, userstate, message, self) => {
dClient.emit('Twitch/Message', channel, userstate, message, self);
});
tClient.on('raided', (channel, username, viewers) => {
dClient.emit('Twitch/Raided', channel, username, viewers);
});
tClient.on('subscribers', (channel, enabled) => {
dClient.emit('Twitch/Subscribers', channel, enabled);
});
tClient.on('disconnected', (reason) => {
console.log('Twitch client disconnected:', reason);
if (reason.includes('Login authentication failed')) {
refreshAccessToken()
.then(() => tClient.connect())
.catch((error) => {
console.error('Failed to refresh token and reconnect:', error);
});
}
});
}
tLogin();