Update group chats internal format to support multiple chats per group and duplicate name handling

This commit is contained in:
SillyLossy
2023-04-30 19:49:49 +03:00
parent 4a5f1e6069
commit 13f50db09c
3 changed files with 121 additions and 70 deletions

View File

@ -732,7 +732,6 @@ function printCharacters() {
} }
async function getCharacters() { async function getCharacters() {
await getGroups();
var response = await fetch("/getcharacters", { var response = await fetch("/getcharacters", {
method: "POST", method: "POST",
headers: getRequestHeaders(), headers: getRequestHeaders(),
@ -752,6 +751,7 @@ async function getCharacters() {
if (this_chid != undefined && this_chid != "invalid-safety-id") { if (this_chid != undefined && this_chid != "invalid-safety-id") {
$("#avatar_url_pole").val(characters[this_chid].avatar); $("#avatar_url_pole").val(characters[this_chid].avatar);
} }
await getGroups();
printCharacters(); printCharacters();
} }
} }
@ -1212,12 +1212,20 @@ function cleanGroupMessage(getMessage) {
if (group && Array.isArray(group.members) && group.members) { if (group && Array.isArray(group.members) && group.members) {
for (let member of group.members) { for (let member of group.members) {
// Skip current speaker. const character = characters.find(x => x.avatar == member);
if (member === name2) {
if (!character) {
continue; continue;
} }
const indexOfMember = getMessage.indexOf(member + ":"); const name = character.name;
// Skip current speaker.
if (name === name2) {
continue;
}
const indexOfMember = getMessage.indexOf(`${name}:`);
if (indexOfMember != -1) { if (indexOfMember != -1) {
getMessage = getMessage.substr(0, indexOfMember); getMessage = getMessage.substr(0, indexOfMember);
} }
@ -2399,6 +2407,7 @@ function saveReply(type, getMessage, this_mes_is_name, title) {
} }
chat[chat.length - 1]['is_name'] = true; chat[chat.length - 1]['is_name'] = true;
chat[chat.length - 1]['force_avatar'] = avatarImg; chat[chat.length - 1]['force_avatar'] = avatarImg;
chat[chat.length - 1]['original_avatar'] = characters[this_chid].avatar;
chat[chat.length - 1]['extra']['gen_id'] = group_generation_id; chat[chat.length - 1]['extra']['gen_id'] = group_generation_id;
} }

View File

@ -115,19 +115,20 @@ async function regenerateGroup() {
generateGroupWrapper(); generateGroupWrapper();
} }
export async function getGroupChat(id) { export async function getGroupChat(groupId) {
const group = groups.find((x) => x.id === groupId);
const chat_id = group.chat_id;
const response = await fetch("/getgroupchat", { const response = await fetch("/getgroupchat", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-CSRF-Token": token, "X-CSRF-Token": token,
}, },
body: JSON.stringify({ id: id }), body: JSON.stringify({ id: chat_id }),
}); });
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
const group = groups.find((x) => x.id === id);
if (Array.isArray(data) && data.length) { if (Array.isArray(data) && data.length) {
data[0].is_group = true; data[0].is_group = true;
for (let key of data) { for (let key of data) {
@ -137,8 +138,8 @@ export async function getGroupChat(id) {
} else { } else {
sendSystemMessage(system_message_types.GROUP); sendSystemMessage(system_message_types.GROUP);
if (group && Array.isArray(group.members)) { if (group && Array.isArray(group.members)) {
for (let name of group.members) { for (let member of group.members) {
const character = characters.find((x) => x.name === name); const character = characters.find(x => x.avatar === member || x.name === member);
if (!character) { if (!character) {
continue; continue;
@ -156,7 +157,7 @@ export async function getGroupChat(id) {
updateChatMetadata(metadata, true); updateChatMetadata(metadata, true);
} }
await saveGroupChat(id, true); await saveGroupChat(groupId, true);
} }
} }
@ -182,18 +183,20 @@ function resetSelectedGroup() {
is_group_generating = false; is_group_generating = false;
} }
async function saveGroupChat(id, shouldSaveGroup) { async function saveGroupChat(groupId, shouldSaveGroup) {
const group = groups.find(x => x.id == groupId);
const chat_id = group.chat_id;
const response = await fetch("/savegroupchat", { const response = await fetch("/savegroupchat", {
method: "POST", method: "POST",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
"X-CSRF-Token": token, "X-CSRF-Token": token,
}, },
body: JSON.stringify({ id: id, chat: [...chat] }), body: JSON.stringify({ id: chat_id, chat: [...chat] }),
}); });
if (shouldSaveGroup && response.ok) { if (shouldSaveGroup && response.ok) {
await editGroup(id); await editGroup(groupId);
} }
} }
@ -209,10 +212,21 @@ async function getGroups() {
if (response.ok) { if (response.ok) {
const data = await response.json(); const data = await response.json();
groups = data.sort((a, b) => a.id - b.id); groups = data.sort((a, b) => a.id - b.id);
// Convert groups to new format
for (const group of groups) {
if (group.chat_id == undefined) {
group.chat_id = group.id;
group.chats = [group.id];
group.members = group.members
.map(x => characters.find(y => y.name == x)?.avatar)
.filter(x => x)
.filter(onlyUnique)
}
}
} }
} }
function printGroups() { function printGroups() {
for (let group of groups) { for (let group of groups) {
const template = $("#group_list_template .group_select").clone(); const template = $("#group_list_template .group_select").clone();
@ -248,7 +262,7 @@ function getGroupAvatar(group) {
const memberAvatars = []; const memberAvatars = [];
if (group && Array.isArray(group.members) && group.members.length) { if (group && Array.isArray(group.members) && group.members.length) {
for (const member of group.members) { for (const member of group.members) {
const charIndex = characters.findIndex((x) => x.name === member); const charIndex = characters.findIndex(x => x.avatar === member);
if (charIndex !== -1 && characters[charIndex].avatar !== "none") { if (charIndex !== -1 && characters[charIndex].avatar !== "none") {
const avatar = getThumbnailUrl('avatar', characters[charIndex].avatar); const avatar = getThumbnailUrl('avatar', characters[charIndex].avatar);
memberAvatars.push(avatar); memberAvatars.push(avatar);
@ -466,34 +480,49 @@ function getLastMessageGenerationId() {
function activateImpersonate(members) { function activateImpersonate(members) {
const randomIndex = Math.floor(Math.random() * members.length); const randomIndex = Math.floor(Math.random() * members.length);
const activatedNames = [members[randomIndex]]; const activatedMembers = [members[randomIndex]];
const memberIds = activatedNames const memberIds = activatedMembers
.map((x) => characters.findIndex((y) => y.name === x)) .map((x) => characters.findIndex((y) => y.avatar === x))
.filter((x) => x !== -1); .filter((x) => x !== -1);
return memberIds; return memberIds;
} }
function activateSwipe(members) { function activateSwipe(members) {
const name = chat[chat.length - 1].name; let activatedNames = [];
const activatedNames = members.includes(name) ? [name] : [];
// pre-update group chat swipe
if (!chat[chat.length -1].original_avatar) {
const matches = characters.filter(x => x.name == chat[chat.length - 1].name);
for (const match of matches) {
if (members.includes(match.avatar)) {
activatedNames.push(match.avatar);
break;
}
}
}
else {
activatedNames.push(chat[chat.length -1].original_avatar);
}
const memberIds = activatedNames const memberIds = activatedNames
.map((x) => characters.findIndex((y) => y.name === x)) .map((x) => characters.findIndex((y) => y.avatar === x))
.filter((x) => x !== -1); .filter((x) => x !== -1);
return memberIds; return memberIds;
} }
function activateListOrder(members) { function activateListOrder(members) {
let activatedNames = members.filter(onlyUnique); let activatedMembers = members.filter(onlyUnique);
// map to character ids // map to character ids
const memberIds = activatedNames const memberIds = activatedMembers
.map((x) => characters.findIndex((y) => y.name === x)) .map((x) => characters.findIndex((y) => y.avatar === x))
.filter((x) => x !== -1); .filter((x) => x !== -1);
return memberIds; return memberIds;
} }
function activateNaturalOrder(members, input, lastMessage, allowSelfResponses, isUserInput) { function activateNaturalOrder(members, input, lastMessage, allowSelfResponses, isUserInput) {
let activatedNames = []; let activatedMembers = [];
// prevents the same character from speaking twice // prevents the same character from speaking twice
let bannedUser = !isUserInput && lastMessage && !lastMessage.is_user && lastMessage.name; let bannedUser = !isUserInput && lastMessage && !lastMessage.is_user && lastMessage.name;
@ -507,12 +536,14 @@ function activateNaturalOrder(members, input, lastMessage, allowSelfResponses, i
if (input && input.length) { if (input && input.length) {
for (let inputWord of extractAllWords(input)) { for (let inputWord of extractAllWords(input)) {
for (let member of members) { for (let member of members) {
if (member === bannedUser) { const character = characters.find(x => x.avatar === member)
if (!character || character.name === bannedUser) {
continue; continue;
} }
if (extractAllWords(member).includes(inputWord)) { if (extractAllWords(character.name).includes(inputWord)) {
activatedNames.push(member); activatedMembers.push(member);
break; break;
} }
} }
@ -522,13 +553,9 @@ function activateNaturalOrder(members, input, lastMessage, allowSelfResponses, i
// activation by talkativeness (in shuffled order, except banned) // activation by talkativeness (in shuffled order, except banned)
const shuffledMembers = shuffle([...members]); const shuffledMembers = shuffle([...members]);
for (let member of shuffledMembers) { for (let member of shuffledMembers) {
if (member === bannedUser) { const character = characters.find((x) => x.avatar === member);
continue;
}
const character = characters.find((x) => x.name === member); if (!character || character.name === bannedUser) {
if (!character) {
continue; continue;
} }
@ -538,22 +565,28 @@ function activateNaturalOrder(members, input, lastMessage, allowSelfResponses, i
? talkativeness_default ? talkativeness_default
: talkativeness; : talkativeness;
if (talkativeness >= rollValue) { if (talkativeness >= rollValue) {
activatedNames.push(member); activatedMembers.push(member);
} }
} }
// pick 1 at random if no one was activated // pick 1 at random if no one was activated
if (activatedNames.length === 0) { while (activatedMembers.length === 0) {
const randomIndex = Math.floor(Math.random() * members.length); const randomIndex = Math.floor(Math.random() * members.length);
activatedNames.push(members[randomIndex]); const character = characters.find((x) => x.avatar === members[randomIndex]);
if (!character) {
continue;
}
activatedMembers.push(members[randomIndex]);
} }
// de-duplicate array of names // de-duplicate array of character avatars
activatedNames = activatedNames.filter(onlyUnique); activatedMembers = activatedMembers.filter(onlyUnique);
// map to character ids // map to character ids
const memberIds = activatedNames const memberIds = activatedMembers
.map((x) => characters.findIndex((y) => y.name === x)) .map((x) => characters.findIndex((y) => y.avatar === x))
.filter((x) => x !== -1); .filter((x) => x !== -1);
return memberIds; return memberIds;
} }
@ -706,28 +739,28 @@ async function reorderGroupMember(chat_id, groupMember, direction) {
} }
} }
function select_group_chats(chat_id, skipAnimation) { function select_group_chats(groupId, skipAnimation) {
const group = chat_id && groups.find((x) => x.id == chat_id); const group = groupId && groups.find((x) => x.id == groupId);
const groupName = group?.name ?? ""; const groupName = group?.name ?? "";
group_rm_panel_mode = !!group ? 'edit' : 'create'; group_rm_panel_mode = !!group ? 'edit' : 'create';
$("#rm_group_chat_name").val(groupName); $("#rm_group_chat_name").val(groupName);
$("#rm_group_chat_name").off(); $("#rm_group_chat_name").off();
$("#rm_group_chat_name").on("input", async function () { $("#rm_group_chat_name").on("input", async function () {
if (chat_id) { if (groupId) {
let _thisGroup = groups.find((x) => x.id == chat_id); let _thisGroup = groups.find((x) => x.id == groupId);
_thisGroup.name = $(this).val(); _thisGroup.name = $(this).val();
$("#rm_button_selected_ch").children("h2").text(_thisGroup.name); $("#rm_button_selected_ch").children("h2").text(_thisGroup.name);
await editGroup(chat_id); await editGroup(groupId);
} }
}); });
$("#rm_group_filter").val("").trigger("input"); $("#rm_group_filter").val("").trigger("input");
$('input[name="rm_group_activation_strategy"]').off(); $('input[name="rm_group_activation_strategy"]').off();
$('input[name="rm_group_activation_strategy"]').on("input", async function (e) { $('input[name="rm_group_activation_strategy"]').on("input", async function (e) {
if (chat_id) { if (groupId) {
let _thisGroup = groups.find((x) => x.id == chat_id); let _thisGroup = groups.find((x) => x.id == groupId);
_thisGroup.activation_strategy = Number(e.target.value); _thisGroup.activation_strategy = Number(e.target.value);
await editGroup(chat_id); await editGroup(groupId);
} }
}); });
const replyStrategy = Number(group?.activation_strategy ?? group_activation_strategy.NATURAL); const replyStrategy = Number(group?.activation_strategy ?? group_activation_strategy.NATURAL);
@ -746,7 +779,7 @@ function select_group_chats(chat_id, skipAnimation) {
? getThumbnailUrl('avatar', character.avatar) ? getThumbnailUrl('avatar', character.avatar)
: default_avatar; : default_avatar;
const template = $("#group_member_template .group_member").clone(); const template = $("#group_member_template .group_member").clone();
template.data("id", character.name); template.data("id", character.avatar);
template.find(".avatar img").attr("src", avatar); template.find(".avatar img").attr("src", avatar);
template.find(".ch_name").text(character.name); template.find(".ch_name").text(character.name);
template.attr("chid", characters.indexOf(character)); template.attr("chid", characters.indexOf(character));
@ -754,9 +787,9 @@ function select_group_chats(chat_id, skipAnimation) {
if ( if (
group && group &&
Array.isArray(group.members) && Array.isArray(group.members) &&
group.members.includes(character.name) group.members.includes(character.avatar)
) { ) {
template.css({ 'order': group.members.indexOf(character.name) }); template.css({ 'order': group.members.indexOf(character.avatar) });
$("#rm_group_members").append(template); $("#rm_group_members").append(template);
} else { } else {
$("#rm_group_add_members").append(template); $("#rm_group_add_members").append(template);
@ -770,7 +803,7 @@ function select_group_chats(chat_id, skipAnimation) {
$("#rm_group_allow_self_responses").prop("checked", group && group.allow_self_responses); $("#rm_group_allow_self_responses").prop("checked", group && group.allow_self_responses);
// bottom buttons // bottom buttons
if (chat_id) { if (groupId) {
$("#rm_group_submit").hide(); $("#rm_group_submit").hide();
$("#rm_group_delete").show(); $("#rm_group_delete").show();
} else { } else {
@ -785,7 +818,7 @@ function select_group_chats(chat_id, skipAnimation) {
return; return;
} }
$("#dialogue_popup").data("group_id", chat_id); $("#dialogue_popup").data("group_id", groupId);
callPopup("<h3>Delete the group?</h3>", "del_group"); callPopup("<h3>Delete the group?</h3>", "del_group");
}); });
@ -795,19 +828,19 @@ function select_group_chats(chat_id, skipAnimation) {
$("#group_favorite_button").on('click', async function () { $("#group_favorite_button").on('click', async function () {
updateFavButtonState(!fav_grp_checked); updateFavButtonState(!fav_grp_checked);
if (group) { if (group) {
let _thisGroup = groups.find((x) => x.id == chat_id); let _thisGroup = groups.find((x) => x.id == groupId);
_thisGroup.fav = fav_grp_checked; _thisGroup.fav = fav_grp_checked;
await editGroup(chat_id); await editGroup(groupId);
} }
}); });
$("#rm_group_allow_self_responses").off(); $("#rm_group_allow_self_responses").off();
$("#rm_group_allow_self_responses").on("input", async function () { $("#rm_group_allow_self_responses").on("input", async function () {
if (group) { if (group) {
let _thisGroup = groups.find((x) => x.id == chat_id); let _thisGroup = groups.find((x) => x.id == groupId);
const value = $(this).prop("checked"); const value = $(this).prop("checked");
_thisGroup.allow_self_responses = value; _thisGroup.allow_self_responses = value;
await editGroup(chat_id); await editGroup(groupId);
} }
}); });
@ -828,15 +861,15 @@ function select_group_chats(chat_id, skipAnimation) {
const member = $(this).closest('.group_member'); const member = $(this).closest('.group_member');
if (action == 'remove') { if (action == 'remove') {
await modifyGroupMember(chat_id, member, true); await modifyGroupMember(groupId, member, true);
} }
if (action == 'add') { if (action == 'add') {
await modifyGroupMember(chat_id, member, false); await modifyGroupMember(groupId, member, false);
} }
if (action == 'up' || action == 'down') { if (action == 'up' || action == 'down') {
await reorderGroupMember(chat_id, member, action); await reorderGroupMember(groupId, member, action);
} }
sortCharactersList("#rm_group_add_members .group_member"); sortCharactersList("#rm_group_add_members .group_member");
@ -852,24 +885,24 @@ function updateFavButtonState(state) {
$(document).ready(() => { $(document).ready(() => {
$(document).on("click", ".group_select", async function () { $(document).on("click", ".group_select", async function () {
const id = $(this).data("id"); const groupId = $(this).data("id");
if (!is_send_press && !is_group_generating) { if (!is_send_press && !is_group_generating) {
if (selected_group !== id) { if (selected_group !== groupId) {
selected_group = id; selected_group = groupId;
setCharacterId(undefined); setCharacterId(undefined);
setCharacterName(''); setCharacterName('');
setEditedMessageId(undefined); setEditedMessageId(undefined);
clearChat(); clearChat();
updateChatMetadata({}, true); updateChatMetadata({}, true);
chat.length = 0; chat.length = 0;
await getGroupChat(id); await getGroupChat(groupId);
//to avoid the filter being lit up yellow and left at true while the list of character and group reseted. //to avoid the filter being lit up yellow and left at true while the list of character and group reseted.
$("#filter_by_fav").removeClass("fav_on"); $("#filter_by_fav").removeClass("fav_on");
filterByFav = false; filterByFav = false;
} }
select_group_chats(id); select_group_chats(groupId);
} }
}); });
@ -895,13 +928,18 @@ $(document).ready(() => {
.map((_, x) => $(x).data("id")) .map((_, x) => $(x).data("id"))
.toArray(); .toArray();
const memberNames = characters.filter(x => members.includes(x.avatar)).map(x => x.name).join(", ");
if (!name) { if (!name) {
name = `Chat with ${members.join(", ")}`; name = `Chat with ${memberNames}`;
} }
// placeholder // placeholder
const avatar_url = 'img/five.png'; const avatar_url = 'img/five.png';
const chatName = humanizedDateTime();
const chats = [chatName];
const createGroupResponse = await fetch("/creategroup", { const createGroupResponse = await fetch("/creategroup", {
method: "POST", method: "POST",
headers: { headers: {
@ -916,6 +954,8 @@ $(document).ready(() => {
activation_strategy: activation_strategy, activation_strategy: activation_strategy,
chat_metadata: {}, chat_metadata: {},
fav: fav_grp_checked, fav: fav_grp_checked,
chat_id: chatName,
chats: chats,
}), }),
}); });

View File

@ -1739,7 +1739,7 @@ app.post('/creategroup', jsonParser, (request, response) => {
} }
const id = Date.now(); const id = Date.now();
const chatMetadata = { const groupMetadata = {
id: id, id: id,
name: request.body.name ?? 'New Group', name: request.body.name ?? 'New Group',
members: request.body.members ?? [], members: request.body.members ?? [],
@ -1748,16 +1748,18 @@ app.post('/creategroup', jsonParser, (request, response) => {
activation_strategy: request.body.activation_strategy ?? 0, activation_strategy: request.body.activation_strategy ?? 0,
chat_metadata: request.body.chat_metadata ?? {}, chat_metadata: request.body.chat_metadata ?? {},
fav: request.body.fav, fav: request.body.fav,
chat_id: request.body.chat_id ?? id,
chats: request.body.chats ?? [id],
}; };
const pathToFile = path.join(directories.groups, `${id}.json`); const pathToFile = path.join(directories.groups, `${id}.json`);
const fileData = JSON.stringify(chatMetadata); const fileData = JSON.stringify(groupMetadata);
if (!fs.existsSync(directories.groups)) { if (!fs.existsSync(directories.groups)) {
fs.mkdirSync(directories.groups); fs.mkdirSync(directories.groups);
} }
fs.writeFileSync(pathToFile, fileData); fs.writeFileSync(pathToFile, fileData);
return response.send(chatMetadata); return response.send(groupMetadata);
}); });
app.post('/editgroup', jsonParser, (request, response) => { app.post('/editgroup', jsonParser, (request, response) => {