BotPub
Code a enregistrer dans un fichier .js:
const irc = require('irc');
const fs = require('fs'); // pour écrire dans système de fichier
const axios = require('axios');
const sleep = require('system-sleep');
// Tableau de strings qui contiendra l'historique des 10 derniers messages reçus
let messages = [];
// String variable used to contain GPT's answer
let results = '';
// Variable de comptage pour le fichier 'GPT.log'
let count = 0;
// Variable qui contiendra le client iRC
let client = null;
async function validateArguments(nickname, message) {
const nicknameBoundary = /^[A-Za-z0-9-]{3,20}$/;
if (!nickname || nickname.length < 3 || nickname.length > 20) {
console.error('[!] Nickname is too large, it must be between 3 and 20 characters long');
process.exit(1);
}
if (!nicknameBoundary.test(nickname)) {
console.error('[!] The nickname contains invalid characters!');
process.exit(1);
}
if (!message || message.length === 0 || message.length > 500) {
console.error(`[!] The message to send is too long or empty!`);
process.exit(1);
}
}
const nickname = process.argv[2];
const message = process.argv[3];
const password = process.env.IRC_PASSWORD;
const GPT_API = process.env.GPT_API_KEY;
validateArguments(nickname, message);
// Configuration du client iRC
const servers = [
{
server: 'irc.quakenet.org',
channels: ['#psychonautfr', '#01', '#02', '#03', '#04', '#05', '#06', '#07', '#08'],
botName: nickname
}
/*{
server: 'openirc.snt.utwente.nl',
channels: ['#070', '#071', '#072', '#073', '#074', '#075', '#076', '#077'],
botName: nickname
}*/
];
async function connectToServer(serversConfig) {
return new Promise((resolve, reject) => {
// Création du client iRC
const client = new irc.Client(
serversConfig.server,
serversConfig.botName,
{ channels: serversConfig.channels }
);
// Evenement lors de la connexion
client.addListener('registered', () => {
console.log(`[+] Connected to ${serversConfig.server} with ${serversConfig.botName} and ready to send messages.`);
client.addListener('join', (channel, nick) => {
if (nick === serversConfig.botName) {
console.log(`[i] The bot has joined ${channel} on ${serversConfig.server}`);
client.say(channel, message);
console.log(`[+] Message sent to ${channel} on ${serversConfig.server}\n`);
}
});
resolve(client);
});
// Evenements pour les messages reçus
client.addListener('message', (from, to, msg) => {
if (typeof msg == 'string' && msg.length < 500) {
console.log(`[i] ${serversConfig.server}: ${from} => ${to}: ${msg}`);
appendMessagesToLog(from, to, msg);
if (messages.length >= 10)
messages.shift();
messages.push(`${from}: ${msg}`);
} else {
console.warn('[!] Received message is too large!');
}
});
// Evenements lors de la déconnexion
client.addListener('error', (msg) => {
console.error('[!] ', msg);
reject(msg);
});
resolve(client);
});
}
// Fonction pour envoyer la requête a GPT afin d'analyser les messages reçus
async function sendRequestToGPT(messages) {
const { ChatGPTAPI } = await import('chatgpt');
const api = new ChatGPTAPI({
apiKey: GPT_API,
completionParams: {
model: 'gpt-3.5-turbo',
temperature: 1.3
}
});
const prompt = messages.join('\n');
const request_p1 = `Generate a custom message to promote HackBBS hacking community. The message should invite people to join HackBBS community of hacker to learn about hacking and participate to activities. The message must promote HackBBS's iRC channel on hackint server #hackbbs and contain the link "https://hackbbs.org". Generate the message based on the history of the messages between double-quotes. The output of your response must ONLY contain the generated message => "`;
try {
response = await api.sendMessage(request_p1 + prompt + '"');
return response.text;
} catch(error) {
console.error('[!] Error during GPT analysis:', error);
return null;
}
}
// Fonction pour créer un fichier de log texte contenant tout les messages reçus
function appendMessagesToLog(from, to, results) {
fs.appendFileSync('./messages.log', `${from} => ${to}: ${results}` + '\n', 'utf-8');
}
// Fonction pour créer un fichier de log texte contenant les analyses de GPT
function appendAnalysisToLog(results) {
fs.appendFileSync('./GPT.log', `[${count}]: ${results} ` + '\n', 'utf-8');
count++;
}
// Pas utilisable pour le moment car fait kick le bot à cause du flood
async function sendPromotionMessage(result) {
if (results) {
for (const serversConfig of servers) {
for (const channel of serversConfig.channels) {
client.say(channel, results);
//console.log(`[+] Promotion message has been sent to ${channel} on ${serversConfig.server}`);
}
}
results = '';
}
}
// Fonction princpale pour se connecter à tous les serveurs
async function main() {
console.log(`[i] Nickname: ${nickname}`);
console.log(`[i] Message: ${message}\n`);
for (const serversConfig of servers) {
try {
client = await connectToServer(serversConfig);
console.log(`[+] Connected to ${serversConfig.server}`);
await new Promise(resolve => setTimeout(resolve, 5000));
} catch (error) {
console.error(`[!] Error connecting to ${serversConfig.server}:`, error);
}
}
// Générer au maximum 3 analyses pour créer un message sur mesure
// à envoyer sur chaque canal iRC (ex: si la langue parlée sur le canal
// est l'allemand -> générer un message en Allemand).
// Puis envoyer le message sur le canal correspondant.
setInterval(async() => {
if (messages.length >= 100) {
results = await sendRequestToGPT(messages);
if (results) {
appendAnalysisToLog(results);
console.log('[+] Results saved to "GPT.log"');
} else {
console.error('[!] Unexpected error while fetching response from GPT');
}
} else {
console.log('[i] No messages to analyze.');
}
}, 30000);
}
main();