111 lines
4.0 KiB
JavaScript
111 lines
4.0 KiB
JavaScript
const { WebcastPushConnection } = require('tiktok-live-connector');
|
|
const mysql = require('mysql2/promise');
|
|
|
|
const [,, username, dbHost, dbUser, dbPass, dbName, userId] = process.argv;
|
|
|
|
if (!username) {
|
|
console.error('Usage: node tiktok_bridge.js <username> <dbHost> <dbUser> <dbPass> <dbName> <userId>');
|
|
process.exit(1);
|
|
}
|
|
|
|
async function start() {
|
|
console.log(`[${new Date().toISOString()}] TikTok Bridge starting for @${username} (User ID: ${userId})`);
|
|
|
|
let connection;
|
|
try {
|
|
connection = await mysql.createConnection({
|
|
host: dbHost || '127.0.0.1',
|
|
user: dbUser || 'root',
|
|
password: dbPass || '',
|
|
database: dbName || 'app_db'
|
|
});
|
|
console.log(`[${new Date().toISOString()}] Connected to database: ${dbName} at ${dbHost}`);
|
|
} catch (err) {
|
|
console.error(`[${new Date().toISOString()}] DB Connection failed:`, err.message);
|
|
process.exit(1);
|
|
}
|
|
|
|
// Create a new connection instance
|
|
let tiktokConnection = new WebcastPushConnection(username, {
|
|
processInitialData: false,
|
|
enableExtendedGiftInfo: true,
|
|
requestPollingIntervalMs: 2000
|
|
});
|
|
|
|
tiktokConnection.connect().then(state => {
|
|
console.log(`[${new Date().toISOString()}] Connected to TikTok Live @${username} (Room ID: ${state.roomId})`);
|
|
}).catch(err => {
|
|
console.error(`[${new Date().toISOString()}] TikTok Connection failed:`, err.message);
|
|
console.error('Check if the username is correct and the user is currently LIVE.');
|
|
process.exit(1);
|
|
});
|
|
|
|
tiktokConnection.on('chat', async (data) => {
|
|
console.log(`[Chat] ${data.uniqueId}: ${data.comment}`);
|
|
try {
|
|
await connection.execute(
|
|
'INSERT INTO tiktok_history (username, comment_author, comment_text, user_id, created_at) VALUES (?, ?, ?, ?, NOW())',
|
|
[username, data.uniqueId, data.comment, userId || null]
|
|
);
|
|
} catch (err) {
|
|
console.error('Error inserting chat:', err.message);
|
|
}
|
|
});
|
|
|
|
tiktokConnection.on('gift', async (data) => {
|
|
if (data.giftType === 1 && !data.repeatEnd) {
|
|
// Wait for repeatEnd for streaks
|
|
return;
|
|
}
|
|
const giftMsg = `sent ${data.repeatCount}x ${data.giftName}!`;
|
|
console.log(`[Gift] ${data.uniqueId}: ${giftMsg}`);
|
|
try {
|
|
await connection.execute(
|
|
'INSERT INTO tiktok_history (username, comment_author, comment_text, user_id, created_at) VALUES (?, ?, ?, ?, NOW())',
|
|
[username, data.uniqueId, giftMsg, userId || null]
|
|
);
|
|
} catch (err) {
|
|
console.error('Error inserting gift:', err.message);
|
|
}
|
|
});
|
|
|
|
tiktokConnection.on('member', (data) => {
|
|
console.log(`[Join] ${data.uniqueId} joined the stream`);
|
|
});
|
|
|
|
tiktokConnection.on('disconnected', () => {
|
|
console.log(`[${new Date().toISOString()}] TikTok connection disconnected`);
|
|
process.exit(0);
|
|
});
|
|
|
|
tiktokConnection.on('streamEnd', () => {
|
|
console.log(`[${new Date().toISOString()}] Stream ended by host`);
|
|
process.exit(0);
|
|
});
|
|
|
|
tiktokConnection.on('error', (err) => {
|
|
console.error(`[${new Date().toISOString()}] TikTok error:`, err.message);
|
|
});
|
|
|
|
// Keep DB connection alive
|
|
setInterval(async () => {
|
|
try {
|
|
await connection.query('SELECT 1');
|
|
} catch (err) {
|
|
console.log(`[${new Date().toISOString()}] DB connection lost, reconnecting...`);
|
|
try {
|
|
connection = await mysql.createConnection({
|
|
host: dbHost, user: dbUser, password: dbPass, database: dbName
|
|
});
|
|
} catch (reconnectErr) {
|
|
console.error('Reconnection failed:', reconnectErr.message);
|
|
}
|
|
}
|
|
}, 30000);
|
|
}
|
|
|
|
// Handle termination signals
|
|
process.on('SIGINT', () => process.exit(0));
|
|
process.on('SIGTERM', () => process.exit(0));
|
|
|
|
start(); |