Compare commits

...

2 Commits

Author SHA1 Message Date
Niels Simenon 750997f3cc 1.26.0 2023-04-11 00:37:05 +02:00
Niels Simenon da9c85d90c Added PM support to chat. 2023-04-11 00:37:03 +02:00
8 changed files with 79 additions and 36 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "schat2-clive",
"version": "1.25.5",
"version": "1.26.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "schat2-clive",
"version": "1.25.5",
"version": "1.26.0",
"license": "ISC",
"dependencies": {
"better-sqlite3": "^8.3.0",

View File

@ -1,6 +1,6 @@
{
"name": "schat2-clive",
"version": "1.25.5",
"version": "1.26.0",
"description": "Game host for SChat 2-powered chat sites",
"main": "src/app.js",
"scripts": {

View File

@ -7,9 +7,11 @@ const style = require('../utils/style');
const knex = require('../knex');
const promptRegex = new RegExp(`^${config.usernamePrefix ? `${config.usernamePrefix}?` : ''}${config.user.username}[:,\\s]`, 'ui');
const history = new Map();
const settings = config.chat;
const settings = { ...config.chat };
const history = new Map();
const processing = new Set();
async function onStart(context) {
const totalExists = await knex.schema.hasTable('chat_tokens');
@ -40,7 +42,7 @@ async function onStart(context) {
function setHistory(value, context) {
if (!value) {
context.sendMessage(`Chat history is set to ${style.bold(settings.history)}`, context.room.id, { label: false });
context.sendMessage(`Chat history is set to ${style.bold(settings.history)}`, context.room?.id, { label: false }, context.user.username);
return;
}
@ -50,17 +52,17 @@ function setHistory(value, context) {
settings.history = newHistory;
context.logger.info(`Chat history set to ${newHistory} by ${context.user.username}`);
context.sendMessage(`Chat history set to ${style.bold(newHistory)} by ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Chat history set to ${style.bold(newHistory)} by ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
return;
}
context.sendMessage(`Chat history must be a valid number between 0 and 10, ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Chat history must be a valid number between 0 and 10, ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
}
function setReplyWordLimit(value, context) {
if (!value) {
context.sendMessage(`Chat reply word limit is set to ${style.bold(settings.replyWordLimit)}`, context.room.id, { label: false });
context.sendMessage(`Chat reply word limit is set to ${style.bold(settings.replyWordLimit)}`, context.room?.id, { label: false }, context.user.username);
return;
}
@ -70,17 +72,17 @@ function setReplyWordLimit(value, context) {
settings.replyWordLimit = newReplyWordLimit;
context.logger.info(`Chat reply word limit set to ${newReplyWordLimit} by ${context.user.username}`);
context.sendMessage(`Chat reply word limit set to ${style.bold(newReplyWordLimit)} by ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Chat reply word limit set to ${style.bold(newReplyWordLimit)} by ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
return;
}
context.sendMessage(`Chat reply word limit must be a valid number between 3 and 200, ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Chat reply word limit must be a valid number between 3 and 200, ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
}
function setTemperature(value, context) {
if (!value) {
context.sendMessage(`Chat temperature is set to ${style.bold(settings.temperature)}`, context.room.id, { label: false });
context.sendMessage(`Chat temperature is set to ${style.bold(settings.temperature)}`, context.room?.id, { label: false }, context.user.username);
return;
}
@ -90,17 +92,17 @@ function setTemperature(value, context) {
settings.temperature = newTemperature;
context.logger.info(`Chat temperature set to ${newTemperature} by ${context.user.username}`);
context.sendMessage(`Chat temperature set to ${style.bold(newTemperature)} by ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Chat temperature set to ${style.bold(newTemperature)} by ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
return;
}
context.sendMessage(`Chat temperature must be a valid number between 0 and 2, ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Chat temperature must be a valid number between 0 and 2, ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
}
function setModel(model, context) {
if (!model) {
context.sendMessage(`Chat model is set to ${style.bold(settings.model)}`, context.room.id, { label: false });
context.sendMessage(`Chat model is set to ${style.bold(settings.model)}`, context.room?.id, { label: false }, context.user.username);
return;
}
@ -108,17 +110,17 @@ function setModel(model, context) {
settings.model = model;
context.logger.info(`Chat model set to '${model}' by ${context.user.username}`);
context.sendMessage(`Chat model set to '${style.bold(model)}' by ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Chat model set to '${style.bold(model)}' by ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
return;
}
context.sendMessage(`Model '${model}' is not supported right now, ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Model '${model}' is not supported right now, ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
}
function setRule(rule, context) {
if (!rule) {
context.sendMessage(`Chat is ${style.bold(settings.rule)}`, context.room.id, { label: false });
context.sendMessage(`Chat is ${style.bold(settings.rule)}`, context.room?.id, { label: false }, context.user.username);
return;
}
@ -126,7 +128,7 @@ function setRule(rule, context) {
settings.rule = config.chat.rule;
context.logger.info(`Chat reset by ${context.user.username} to be ${config.chat.rule}`);
context.sendMessage(`Chat reset by ${context.user.prefixedUsername} to be ${style.bold(config.chat.rule)}`, context.room.id, { label: false });
context.sendMessage(`Chat reset by ${context.user.prefixedUsername} to be ${style.bold(config.chat.rule)}`, context.room?.id, { label: false }, context.user.username);
return;
}
@ -135,12 +137,12 @@ function setRule(rule, context) {
settings.rule = `${rule.replace(/\.+$/, '')}`;
context.logger.info(`Chat set by ${context.user.username} to be ${rule}`);
context.sendMessage(`Chat set by ${context.user.prefixedUsername} to be ${style.bold(rule)}`, context.room.id, { label: false });
context.sendMessage(`Chat set by ${context.user.prefixedUsername} to be ${style.bold(rule)}`, context.room?.id, { label: false }, context.user.username);
return;
}
context.sendMessage(`Chat rule must be at least 3 characters long, ${context.user.prefixedUsername}`, context.room.id, { label: false });
context.sendMessage(`Chat rule must be at least 3 characters long, ${context.user.prefixedUsername}`, context.room?.id, { label: false }, context.user.username);
}
async function getTokens(username) {
@ -163,7 +165,7 @@ async function resetTokens(username) {
.delete();
}
async function onCommand(args, context) {
async function onCommand(args, context, isConversation) {
if (context.subcommand === 'history' && config.operators.includes(context.user.username)) {
setHistory(args[0], context);
return;
@ -193,7 +195,7 @@ async function onCommand(args, context) {
const username = args[0] ? args[0].replace(new RegExp(`^${config.usernamePrefix}`), '') : context.user.username;
const tokens = await getTokens(username);
context.sendMessage(`${args[0] ? `${style.bold(username)} has` : 'You have'} ${style.bold(config.chat.userTokenLimit - tokens)} chat tokens remaining. They will be returned gradually over ${config.chat.userTokenPeriod} hours.`, context.room.id, { label: false });
context.sendMessage(`${args[0] ? `${style.bold(username)} has` : 'You have'} ${style.bold(config.chat.userTokenLimit - tokens)} chat tokens remaining. They will be returned gradually over ${config.chat.userTokenPeriod} hours.`, context.room?.id, { label: false }, context.user.username);
return;
}
@ -203,19 +205,26 @@ async function onCommand(args, context) {
await resetTokens(username);
context.sendMessage(args[0] ? `Chat tokens reset for ${style.bold(username)}` : 'Chat tokens reset', context.room.id, { label: false });
context.sendMessage(args[0] ? `Chat tokens reset for ${style.bold(username)}` : 'Chat tokens reset', context.room?.id, { label: false }, context.user.username);
return;
}
if (processing.has(context.user.username)) {
context.logger.info(`Skipped prompt from ${context.user.username} due processing lock`);
return;
}
const prompt = args.join(' ');
processing.add(context.user.username);
try {
const usedTokens = await getTokens(context.user.username);
if (usedTokens >= config.chat.userTokenLimit) {
context.logger.info(`${context.user.username} was rate limited at ${usedTokens}: ${prompt}`);
context.sendMessage(`Sorry, I love talking with you ${context.user.prefixedUsername}, but I need to take a break :( Check ${config.prefix}chat:tokens for more information.`, context.room.id, { label: false });
context.sendMessage(`Sorry, I love talking with you ${context.user.prefixedUsername}, but I need to take a break :( Check ${config.prefix}chat:tokens for more information.`, context.room?.id, { label: false }, context.user.username);
return;
}
@ -247,7 +256,12 @@ async function onCommand(args, context) {
const curatedContent = reply.content.replace(/\n+/g, '. ');
context.logger.info(`OpenAI ${config.chat.model} replied to ${context.user.username} (${res.body.usage.total_tokens} tokens, ${(usedTokens || 0) + res.body.usage.total_tokens}/${config.chat.userTokenLimit} used): ${curatedContent}`);
context.sendMessage(`${context.user.prefixedUsername}: ${curatedContent}`, context.room.id, { label: false });
if (isConversation) {
context.sendMessage(`${curatedContent}`, context.room?.id, { label: false }, context.user.username);
} else {
context.sendMessage(`${context.user.prefixedUsername}: ${curatedContent}`, context.room.id, { label: false });
}
await knex('chat_tokens').insert({
user_id: context.user.username,
@ -260,13 +274,17 @@ async function onCommand(args, context) {
}
} catch (error) {
context.logger.error(error.response ? `${error.response.status}: ${JSON.stringify(error.response.data)}` : error.message);
context.sendMessage('Sorry, I can\'t think right now', context.room.id, { label: false });
context.sendMessage('Sorry, I can\'t think right now', context.room?.id, { label: false }, context.user.username);
}
processing.delete(context.user.username);
}
function onMessage(message, context) {
if (promptRegex.test(message.body)) {
onCommand([message.body.replace(promptRegex, '').trim()], context);
const isConversation = message.recipient === config.user.username && !context.room && !context.containsCommand;
if (promptRegex.test(message.body) || isConversation) {
onCommand([message.body.replace(promptRegex, '').trim()], context, isConversation);
}
}

View File

@ -97,7 +97,7 @@ async function onCommand(args, context) {
async function onMessage(message, context) {
['countries', 'states', 'flags'].forEach(async (type) => {
const game = games[type].get(context.room.id);
const game = games[type].get(context.room?.id);
if (!game) {
return;

View File

@ -145,7 +145,7 @@ function onCommand(args, context) {
}
function onMessage(message, context) {
if (games.has(context.room.id)) {
if (games.has(context.room?.id)) {
const letter = message.body.match(/^\s*\w\s*$/)?.[0];
const word = message.body.match(/^\s*\w{2,}\s*$/)?.[0];

View File

@ -88,7 +88,7 @@ async function play(context) {
game.state = 'words';
game.counts = countLetters(game.word);
context.sendMessage(`${getBoard(context)} You have ${style.bold(style.green(settings.timeout))}, let's start!`, context.room.id);
context.sendMessage(`${getBoard(context)} You have ${style.bold(style.green(settings.timeout))} seconds, let's start!`, context.room.id);
try {
await timers.setTimeout((settings.timeout / 3) * 1000, null, { signal: game.ac.signal });

View File

@ -44,7 +44,7 @@ mathImport({
divide,
}, { override: true });
const settings = config.numbers;
const settings = { ...config.numbers };
const games = new Map();
/* eslint-disable no-irregular-whitespace */
@ -89,6 +89,24 @@ function countNumbers(numbers) {
return numbers.reduce((acc, number) => ({ ...acc, [number]: (acc[number] || 0) + 1 }), {});
}
function setTimeout(timeout, context) {
if (!timeout) {
context.sendMessage(`Timeout is set to ${style.bold(settings.timeout)}`, context.room.id);
return;
}
const parsedTimeout = Number(timeout);
if (Number.isNaN(parsedTimeout) || parsedTimeout < 10 || parsedTimeout > 300) {
context.sendMessage('Timeout must be a number between 10 and 300', context.room.id);
return;
}
settings.timeout = parsedTimeout;
context.sendMessage(`Timeout set to ${style.bold(settings.timeout)} by ${context.user.prefixedUsername}`, context.room.id);
}
function getWinnerText(game) {
if (game.state === 'pick') {
return null;
@ -327,6 +345,11 @@ function onCommand(args, context) {
return;
}
if (context.subcommand === 'timeout') {
setTimeout(args[0], context);
return;
}
if (['calculate', 'calc', 'solve'].includes(context.subcommand || context.command)) {
solve(args.join(' '), context); // two from the top, four from the bottom, please Rachel
return;
@ -343,7 +366,7 @@ function onCommand(args, context) {
}
function onMessage(message, context) {
const game = games.get(context.room.id);
const game = games.get(context.room?.id);
const body = message.originalBody || message.body; // * gets resolved to <em>
if (game?.state === 'pick') {

View File

@ -124,8 +124,8 @@ async function getGames(bot, identifier) {
if (config.platform === 'schat') {
bot.socket.transmit('message', {
roomId,
recipient,
type: recipient && options?.type !== 'message' ? 'whisper' : 'message',
recipient: options?.type === 'whisper' || !roomId ? recipient : null,
type: options?.type || 'message',
body: curatedBody,
style: { ...config.style, ...options?.style },
});
@ -248,6 +248,8 @@ function onMessage(message, bot, games) {
...game,
bot,
message,
containsCommand: command,
containsSubcommand: subcommand,
user: user && {
...user,
points: points[game.key]?.[`${user.id}:${user.username}`] || 0,