current status
This commit is contained in:
parent
1b80d11a2c
commit
2ac0d2de6f
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules/
|
||||
conversations/
|
||||
config.json
|
10
config.example.json
Normal file
10
config.example.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"api": {
|
||||
"host": "localhost",
|
||||
"port": 5001,
|
||||
"bearer": ""
|
||||
},
|
||||
"initiative": [],
|
||||
"stops": ["###"],
|
||||
"clients": []
|
||||
}
|
34
src/inc/lib.mjs
Normal file
34
src/inc/lib.mjs
Normal file
|
@ -0,0 +1,34 @@
|
|||
import { exec as _exec } from 'node:child_process';
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
export default new class {
|
||||
exec(cmd) {
|
||||
return new Promise((resolve, reject) => {
|
||||
_exec(cmd, { maxBuffer: 5e3 * 1024 }, (err, stdout, stderr) => {
|
||||
if(err)
|
||||
return reject(err);
|
||||
if(stderr)
|
||||
console.error(stderr);
|
||||
resolve({ stdout: stdout });
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
rand(max = 1) {
|
||||
return ~~(Math.random() * (max - 1) + 1);
|
||||
};
|
||||
|
||||
async getPlayerlist(world, clanid) {
|
||||
const res = await (await fetch(`https://${world}.freewar.de/freewar/dump_players.php`)).text();
|
||||
return res.split("\n").map(p => {
|
||||
const player = p.split("\t");
|
||||
return {
|
||||
id: +player[0],
|
||||
name: player[1],
|
||||
xp: +player[2],
|
||||
rasse: player[3],
|
||||
clanid: +player[4]
|
||||
};
|
||||
}).filter(p => p.clanid === clanid)
|
||||
};
|
||||
};
|
235
src/index.mjs
235
src/index.mjs
|
@ -2,100 +2,205 @@ import fs from 'node:fs/promises';
|
|||
import cuffeo from 'cuffeo';
|
||||
import fetch from 'node-fetch';
|
||||
import oger from './inc/oger.mjs';
|
||||
import lib from './inc/lib.mjs';
|
||||
import config from '../config.json' assert { type: 'json' };
|
||||
import initials from './inc/initials.json' assert { type: 'json' };
|
||||
import initials from '../data/initials.json' assert { type: 'json' };
|
||||
|
||||
const conversations = new Map();
|
||||
const bot = await new cuffeo(config.clients);
|
||||
let last = false;
|
||||
let playerlist = false;
|
||||
|
||||
bot.on('message', async e => {
|
||||
if(typeof e.message === 'undefined' || e.message.length <= 2)
|
||||
return;
|
||||
|
||||
console.log(e.user.nick + ": " + e.message);
|
||||
const constr = `${e.network}::${e.channelid}`;
|
||||
|
||||
if(e.message?.match(/^!perf/i)) {
|
||||
return await e.reply(JSON.stringify(await (await fetch(`http://${config.api.host}:${config.api.port}/api/extra/perf`)).json()));
|
||||
if(e.message.match(/^!claninfo/i)) {
|
||||
playerlist = await lib.getPlayerlist("welt13", 4760);
|
||||
|
||||
return await e.reply(
|
||||
playerlist.map(p => p.name).join(", ")
|
||||
);
|
||||
}
|
||||
|
||||
if(e.message?.match(/^!model/i)) {
|
||||
if(e.message.match(/^!gens/i)) {
|
||||
const perf = await (await fetch(`http://${config.api.host}:${config.api.port}/api/extra/perf`)).json();
|
||||
return await e.reply(`total_gens: ${perf.total_gens}`);
|
||||
}
|
||||
|
||||
if(e.message.match(/^!model/i)) {
|
||||
return await e.reply((await (await fetch(`http://${config.api.host}:${config.api.port}/api/v1/model`)).json()).result);
|
||||
}
|
||||
|
||||
if(e.message?.match(/^!channelid/i)) {
|
||||
if(e.message.match(/^!messages/i)) {
|
||||
try {
|
||||
const cons = (await fs.readdir("./data/conversations")).filter(f => f.endsWith(".json"));
|
||||
let messages = 0;
|
||||
for(const con of cons) {
|
||||
messages += JSON.parse(await fs.readFile(`./data/conversations/${con}`, 'utf8')).length;
|
||||
}
|
||||
|
||||
let output = [];
|
||||
output.push(`Nachrichten insgesamt: ${messages}`);
|
||||
|
||||
if(cons.includes(constr+'.json')) {
|
||||
output.push(`Davon in diesem Kanal: ${JSON.parse(await fs.readFile(`./data/conversations/${constr}.json`, 'utf8')).length}`);
|
||||
}
|
||||
|
||||
return await e.reply(output.join(' | '));
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(e.message.match(/^!gpustat/i)) {
|
||||
const gpustat = JSON.parse((await lib.exec('gpustat -a --json')).stdout);
|
||||
const gpu = gpustat.gpus[0];
|
||||
|
||||
const output = [
|
||||
`${gpu['temperature.gpu']}°C, ${gpu['fan.speed']} rpm`,
|
||||
`${gpu['memory.used']} / ${gpu['memory.total']} MB`,
|
||||
`${gpu['power.draw']} / ${gpu['enforced.power.limit']} W`
|
||||
].join(' | ');
|
||||
return await e.reply(`${gpustat.hostname}: ${gpu.name}\n${output}`);
|
||||
}
|
||||
|
||||
if(e.message.match(/^!channelid/i)) {
|
||||
return await e.reply(e.channelid);
|
||||
}
|
||||
|
||||
if(!conversations.has(constr)) { // get conv from json
|
||||
try {
|
||||
const tmpcon = JSON.parse(await fs.readFile(`./src/conversations/${constr}.json`, 'utf8'));
|
||||
if(e.message.match(/^!reset/i)) {
|
||||
conversations.set(constr, []);
|
||||
await fs.writeFile(`./data/conversations/${constr}.json`, JSON.stringify([]));
|
||||
return await e.reply("Konversation wurde erfolgreich zurückgesetzt.");
|
||||
}
|
||||
|
||||
let conv = conversations.has(constr) ? conversations.get(constr) : [];
|
||||
|
||||
if(!conv.length) {
|
||||
try { // get conv from json
|
||||
const tmpcon = JSON.parse(await fs.readFile(`./data/conversations/${constr}.json`, 'utf8'));
|
||||
if(tmpcon) {
|
||||
conversations.set(constr, tmpcon);
|
||||
conv = tmpcon;
|
||||
console.log(`Konversation von ${constr} geladen. ${tmpcon.length} Einträge.`);
|
||||
}
|
||||
} catch(err) {}
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
conversations.set(constr, conv);
|
||||
}
|
||||
}
|
||||
|
||||
if(e.message?.match(/ra+i+ne+r/i)) {
|
||||
conv.push({
|
||||
role: 'user',
|
||||
content: `${e.user.nick} schreibt: ${e.message.trim()}`
|
||||
});
|
||||
await fs.writeFile(`./data/conversations/${constr}.json`, JSON.stringify(conv));
|
||||
conversations.set(constr, conv);
|
||||
|
||||
if(last)
|
||||
return await e.reply(`ich antworte bereits ${last}!`);
|
||||
if(!e.message?.match(/ra+i+ne+r/i)) {
|
||||
if(!config.initiative.includes(constr))
|
||||
return;
|
||||
|
||||
const actcon = [];
|
||||
let probability = 20; // default, 5%
|
||||
|
||||
if(conversations.has(constr))
|
||||
actcon.push(...conversations.get(constr));
|
||||
else {
|
||||
actcon.push({
|
||||
"role": "system",
|
||||
"content": initials[e.channelid] ? initials[e.channelid].lore : initials['default'].lore
|
||||
});
|
||||
actcon.push({
|
||||
"role": "system",
|
||||
"content": "eingehende Chatnachrichten sind immer folgendermaßen aufgebaut: \"%USERNAME% schreibt: %COMMAND%\". Du schreibst das aber nicht."
|
||||
});
|
||||
if(e.message.match(/.*\?$/)) {
|
||||
probability = 5; // 20%
|
||||
}
|
||||
|
||||
if(lib.rand(probability) !== 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Rainer matched
|
||||
if(last)
|
||||
return await e.reply(`ich antworte bereits ${last}!`);
|
||||
|
||||
const actcon = [{
|
||||
"role": "system",
|
||||
"content": initials[ initials[constr] ? constr : 'default' ].lore
|
||||
}, {
|
||||
"role": "system",
|
||||
"content": "eingehende Chatnachrichten sind immer folgendermaßen aufgebaut: \"%USERNAME% schreibt: %COMMAND%\". Du schreibst das aber nicht."
|
||||
}, {
|
||||
"role": "system",
|
||||
"content": `Aktuelles Datum und Zeit: ${(new Date()).toLocaleString()}`
|
||||
}];
|
||||
|
||||
if(constr === 'Discord::1143415824539992206') {
|
||||
if(!playerlist)
|
||||
playerlist = await lib.getPlayerlist('welt13', 4760);
|
||||
|
||||
actcon.push({
|
||||
role: 'user',
|
||||
content: `${e.user.nick} schreibt: ${e.message.trim()}`
|
||||
"role": "user",
|
||||
"content": "Unser Clan besteht aus folgenden Mitgliedern:\n" + playerlist.map(p => `${p.name}: ${p.xp} XP, Rasse: ${p.rasse}`).join("\n")
|
||||
});
|
||||
|
||||
const opts = {
|
||||
method: 'POST',
|
||||
port: 5001,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Bearer ${config.api.bearer}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
mode: "chat",
|
||||
instruction_template: "Alpaca",
|
||||
stream: false,
|
||||
max_tokens: 1024,
|
||||
stop: ['###', ' <|endoftext|>', '---'],
|
||||
messages: actcon
|
||||
})
|
||||
};
|
||||
|
||||
last = e.user.nick;
|
||||
|
||||
const res = await (await fetch(`http://${config.api.host}:${config.api.port}/v1/chat/completions`, opts)).json();
|
||||
|
||||
if(res.choices[0]?.message) {
|
||||
if(res.choices[0].message.length <= 2)
|
||||
return await e.reply('ich habe dazu nichts zu sagen, du Birne.');
|
||||
|
||||
res.choices[0].message.content = res.choices[0].message.content.split(/(###|---)/)[0];
|
||||
|
||||
actcon.push(res.choices[0].message);
|
||||
conversations.set(constr, actcon);
|
||||
|
||||
console.log("Rainer: " + res.choices[0].message.content.trim());
|
||||
last = false;
|
||||
|
||||
await fs.writeFile(`./src/conversations/${constr}.json`, JSON.stringify(conversations.get(constr)));
|
||||
return await e.reply(res.choices[0].message.content.trim());
|
||||
}
|
||||
last = false;
|
||||
}
|
||||
|
||||
actcon.push(...conv, {
|
||||
role: 'user',
|
||||
content: `${e.user.nick} schreibt: ${e.message.trim()}`
|
||||
});
|
||||
|
||||
const opts = {
|
||||
method: 'POST',
|
||||
port: 5001,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Bearer ${config.api.bearer}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
mode: "chat",
|
||||
instruction_template: "Alpaca",
|
||||
stream: false,
|
||||
max_tokens: 768,
|
||||
stop: config.stops,
|
||||
messages: actcon
|
||||
})
|
||||
};
|
||||
|
||||
last = e.user.nick;
|
||||
|
||||
let res;
|
||||
|
||||
try {
|
||||
res = await (await fetch(`http://${config.api.host}:${config.api.port}/v1/chat/completions`, opts)).json();
|
||||
} catch(err) {
|
||||
last = false;
|
||||
return await e.reply('Backend ist gerade offline. Sorreh.');
|
||||
}
|
||||
|
||||
if(res?.choices?.[0]?.message) {
|
||||
if(res.choices[0].message.length <= 2)
|
||||
return await e.reply('ich habe dazu nichts zu sagen, du Birne.');
|
||||
|
||||
res.choices[0].message.content = res.choices[0].message.content.split(/(###|---|ASSISTANT)/)[0];
|
||||
res.choices[0].message.content = res.choices[0].message.content.replace(/^Rainer( schreibt| antwortet)?: /, '');
|
||||
|
||||
conv.push(res.choices[0].message);
|
||||
conversations.set(constr, conv);
|
||||
await fs.writeFile(`./data/conversations/${constr}.json`, JSON.stringify(conv));
|
||||
|
||||
console.log("Rainer: " + res.choices[0].message.content.trim());
|
||||
|
||||
try {
|
||||
if(initials[constr] && initials[constr].langmod === 'oger')
|
||||
await e.reply(oger(res.choices[0].message.content.trim()));
|
||||
else
|
||||
await e.reply(res.choices[0].message.content.trim());
|
||||
} catch(err) {
|
||||
await e.reply('ups, kann ich nicht schreiben, wäre zu viel gewesen.');
|
||||
}
|
||||
}
|
||||
else {
|
||||
await e.reply('Hilfe, Fehler!');
|
||||
}
|
||||
|
||||
last = false;
|
||||
return;
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user