mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
button to duplicate solo characters
This commit is contained in:
@ -989,48 +989,48 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="kobold_horde" style="position: relative;"> <!-- shows the kobold settings -->
|
<div id="kobold_horde" style="position: relative;"> <!-- shows the kobold settings -->
|
||||||
<form action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
<form action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||||
<div id="kobold_horde_block">
|
<div id="kobold_horde_block">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="https://horde.koboldai.net/register">Register a Horde account for faster queue times</a>
|
<a target="_blank" href="https://horde.koboldai.net/register">Register a Horde account for faster queue times</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a target="_blank" href="https://github.com/db0/AI-Horde-Worker#readme">Learn how to contribute your idle GPU cycles to the Horde</a>
|
<a target="_blank" href="https://github.com/db0/AI-Horde-Worker#readme">Learn how to contribute your idle GPU cycles to the Horde</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<label for="horde_auto_adjust_context_length" class="checkbox_label">
|
<label for="horde_auto_adjust_context_length" class="checkbox_label">
|
||||||
<input id="horde_auto_adjust_context_length" type="checkbox" />
|
<input id="horde_auto_adjust_context_length" type="checkbox" />
|
||||||
Adjust context size to worker capabilities
|
Adjust context size to worker capabilities
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label for="horde_auto_adjust_response_length" class="checkbox_label">
|
<label for="horde_auto_adjust_response_length" class="checkbox_label">
|
||||||
<input id="horde_auto_adjust_response_length" type="checkbox" />
|
<input id="horde_auto_adjust_response_length" type="checkbox" />
|
||||||
Adjust response length to worker capabilities
|
Adjust response length to worker capabilities
|
||||||
</label>
|
</label>
|
||||||
<h4>API key</h4>
|
<h4>API key</h4>
|
||||||
<h5>Get it here: <a target="_blank" href="https://horde.koboldai.net/register">Register</a><br>
|
<h5>Get it here: <a target="_blank" href="https://horde.koboldai.net/register">Register</a><br>
|
||||||
Enter <span class="monospace">0000000000</span> to use anonymous mode.
|
Enter <span class="monospace">0000000000</span> to use anonymous mode.
|
||||||
</h5>
|
</h5>
|
||||||
<div>
|
<div>
|
||||||
<a id="horde_kudos" href="javascript:void(0);">View my Kudos</a>
|
<a id="horde_kudos" href="javascript:void(0);">View my Kudos</a>
|
||||||
</div>
|
|
||||||
<div class="flex-container">
|
|
||||||
<input id="horde_api_key" name="horde_api_key" class="text_pole flex1" maxlength="500" type="text" placeholder="0000000000" autocomplete="off">
|
|
||||||
<div title="Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_horde"></div>
|
|
||||||
</div>
|
|
||||||
<div class="neutral_warning">For privacy reasons, your API key will be hidden after you reload the page.</div>
|
|
||||||
<h4 class="horde_model_title">
|
|
||||||
Model
|
|
||||||
<div id="horde_refresh" title="Refresh models" class="right_menu_button">
|
|
||||||
<div class="fa-solid fa-repeat "></div>
|
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
<div class="flex-container">
|
||||||
<small class="horde_multiple_hint">Hold Control / Command key to select multiple models.</small>
|
<input id="horde_api_key" name="horde_api_key" class="text_pole flex1" maxlength="500" type="text" placeholder="0000000000" autocomplete="off">
|
||||||
<select id="horde_model" multiple>
|
<div title="Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_horde"></div>
|
||||||
<option>-- Horde models not loaded --</option>
|
</div>
|
||||||
</select>
|
<div class="neutral_warning">For privacy reasons, your API key will be hidden after you reload the page.</div>
|
||||||
</div>
|
<h4 class="horde_model_title">
|
||||||
|
Model
|
||||||
|
<div id="horde_refresh" title="Refresh models" class="right_menu_button">
|
||||||
|
<div class="fa-solid fa-repeat "></div>
|
||||||
|
</div>
|
||||||
|
</h4>
|
||||||
|
<small class="horde_multiple_hint">Hold Control / Command key to select multiple models.</small>
|
||||||
|
<select id="horde_model" multiple>
|
||||||
|
<option>-- Horde models not loaded --</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div id="online_status_horde">
|
<div id="online_status_horde">
|
||||||
<div id="online_status_indicator_horde"></div>
|
<div id="online_status_indicator_horde"></div>
|
||||||
<div id="online_status_text_horde">Not connected</div>
|
<div id="online_status_text_horde">Not connected</div>
|
||||||
@ -1931,6 +1931,7 @@
|
|||||||
<input type="hidden" id="fav_checkbox" name="fav" />
|
<input type="hidden" id="fav_checkbox" name="fav" />
|
||||||
<div id="advanced_div" class="menu_button fa-solid fa-book " title="Advanced Definitions"></div>
|
<div id="advanced_div" class="menu_button fa-solid fa-book " title="Advanced Definitions"></div>
|
||||||
<div id="export_button" class="menu_button fa-solid fa-file-export " title="Export and Download"></div>
|
<div id="export_button" class="menu_button fa-solid fa-file-export " title="Export and Download"></div>
|
||||||
|
<div id="dupe_button" class="menu_button fa-solid fa-clone " title="Duplicate Character"></div>
|
||||||
<label for="create_button" id="create_button_label" class="menu_button fa-solid fa-user-check" title="Create Character">
|
<label for="create_button" id="create_button_label" class="menu_button fa-solid fa-user-check" title="Create Character">
|
||||||
<input type="submit" id="create_button" name="create_button">
|
<input type="submit" id="create_button" name="create_button">
|
||||||
</label>
|
</label>
|
||||||
@ -2221,7 +2222,7 @@
|
|||||||
<div id="context_editor_template" class="template_element">
|
<div id="context_editor_template" class="template_element">
|
||||||
<div class="context_editor">
|
<div class="context_editor">
|
||||||
<h3>Context Template Editor</h3>
|
<h3>Context Template Editor</h3>
|
||||||
<h4 class="template_name"></h4>
|
<h4 class="template_name"></h4>
|
||||||
|
|
||||||
<div class="inline-drawer wide100p">
|
<div class="inline-drawer wide100p">
|
||||||
<div class="inline-drawer-toggle inline-drawer-header">
|
<div class="inline-drawer-toggle inline-drawer-header">
|
||||||
|
@ -4258,30 +4258,38 @@ function select_rm_info(type, charId, previousCharId = null) {
|
|||||||
toastr.error(`Invalid process (no 'type')`);
|
toastr.error(`Invalid process (no 'type')`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (type !== 'group_create') {
|
||||||
|
var displayName = String(charId).replace('.png', '');
|
||||||
|
}
|
||||||
|
|
||||||
if (type === 'char_delete') {
|
if (type === 'char_delete') {
|
||||||
toastr.warning(`Character Deleted: ${charId}`);
|
toastr.warning(`Character Deleted: ${displayName}`);
|
||||||
}
|
}
|
||||||
if (type === 'char_create') {
|
if (type === 'char_create') {
|
||||||
toastr.success(`Character Created: ${charId}`);
|
toastr.success(`Character Created: ${displayName}`);
|
||||||
}
|
}
|
||||||
if (type === 'group_create') {
|
if (type === 'group_create') {
|
||||||
toastr.success(`Group Created`);
|
toastr.success(`Group Created`);
|
||||||
}
|
}
|
||||||
if (type === 'char_import') {
|
if (type === 'group_delete') {
|
||||||
toastr.success(`Character Imported: ${charId}`);
|
toastr.warning(`Group Deleted`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type === 'char_import') {
|
||||||
|
toastr.success(`Character Imported: ${displayName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
getCharacters();
|
||||||
selectRightMenuWithAnimation('rm_characters_block');
|
selectRightMenuWithAnimation('rm_characters_block');
|
||||||
|
|
||||||
if (type === 'char_import' || type === 'char_create') {
|
if (type === 'char_import' || type === 'char_create') {
|
||||||
|
|
||||||
//$(`#rm_characters_block [title="${charId + '.png'}"]`).scrollIntoView({ behavior: "smooth", block: "end" });
|
const element = $(`#rm_characters_block [title="${charId}"]`).get(0);
|
||||||
const element = $(`#rm_characters_block [title="${charId + '.png'}"]`).get(0);
|
|
||||||
element.scrollIntoView({ behavior: 'smooth', block: 'end' });
|
element.scrollIntoView({ behavior: 'smooth', block: 'end' });
|
||||||
|
|
||||||
$(`#rm_characters_block [title="${charId + '.png'}"]`).parent().addClass('flash animated');
|
$(`#rm_characters_block [title="${charId}"]`).parent().addClass('flash animated');
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
$(`#rm_characters_block [title="${charId + '.png'}"]`).parent().removeClass('flash animated');
|
$(`#rm_characters_block [title="${charId}"]`).parent().removeClass('flash animated');
|
||||||
}, 5000);
|
}, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4319,7 +4327,8 @@ export function select_selected_character(chid) {
|
|||||||
$("#rm_button_back").css("display", "none");
|
$("#rm_button_back").css("display", "none");
|
||||||
//$("#character_import_button").css("display", "none");
|
//$("#character_import_button").css("display", "none");
|
||||||
$("#create_button").attr("value", "Save"); // what is the use case for this?
|
$("#create_button").attr("value", "Save"); // what is the use case for this?
|
||||||
$("#create_button_label").css("display", "none");
|
$("#dupe_button").show();
|
||||||
|
//$("#create_button_label").css("display", "none");
|
||||||
|
|
||||||
// Don't update the navbar name if we're peeking the group member defs
|
// Don't update the navbar name if we're peeking the group member defs
|
||||||
if (!selected_group) {
|
if (!selected_group) {
|
||||||
@ -4376,8 +4385,7 @@ function select_rm_create() {
|
|||||||
$("#export_button").css("display", "none");
|
$("#export_button").css("display", "none");
|
||||||
$("#create_button_label").css("display", "");
|
$("#create_button_label").css("display", "");
|
||||||
$("#create_button").attr("value", "Create");
|
$("#create_button").attr("value", "Create");
|
||||||
//RossAscends: commented this out as part of the auto-loading token counter
|
$("#dupe_button").hide();
|
||||||
//$('#result_info').html(' ');
|
|
||||||
|
|
||||||
//create text poles
|
//create text poles
|
||||||
$("#rm_button_back").css("display", "");
|
$("#rm_button_back").css("display", "");
|
||||||
@ -4511,7 +4519,7 @@ function read_bg_load(input) {
|
|||||||
url: "/downloadbackground",
|
url: "/downloadbackground",
|
||||||
data: formData,
|
data: formData,
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
//$('#create_button').attr('value','Creating...');
|
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
contentType: false,
|
contentType: false,
|
||||||
@ -5412,7 +5420,6 @@ $(document).ready(function () {
|
|||||||
url: "/deletecharacter",
|
url: "/deletecharacter",
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
select_rm_info("char_delete", characters[this_chid].name);
|
select_rm_info("char_delete", characters[this_chid].name);
|
||||||
//$('#create_button').attr('value','Deleting...');
|
|
||||||
},
|
},
|
||||||
data: msg,
|
data: msg,
|
||||||
cache: false,
|
cache: false,
|
||||||
@ -5593,7 +5600,7 @@ $(document).ready(function () {
|
|||||||
$("#rm_info_block").transition({ opacity: 0, duration: 0 });
|
$("#rm_info_block").transition({ opacity: 0, duration: 0 });
|
||||||
var $prev_img = $("#avatar_div_div").clone();
|
var $prev_img = $("#avatar_div_div").clone();
|
||||||
$("#rm_info_avatar").append($prev_img);
|
$("#rm_info_avatar").append($prev_img);
|
||||||
select_rm_info(`char_create`, save_name, oldSelectedChar);
|
select_rm_info(`char_create`, html, oldSelectedChar);
|
||||||
|
|
||||||
$("#rm_info_block").transition({ opacity: 1.0, duration: 2000 });
|
$("#rm_info_block").transition({ opacity: 1.0, duration: 2000 });
|
||||||
crop_data = undefined;
|
crop_data = undefined;
|
||||||
@ -5617,7 +5624,7 @@ $(document).ready(function () {
|
|||||||
url: url,
|
url: url,
|
||||||
data: formData,
|
data: formData,
|
||||||
beforeSend: function () {
|
beforeSend: function () {
|
||||||
//$("#create_button").attr("disabled", true);
|
$("#create_button").attr("disabled", true);
|
||||||
$("#create_button").attr("value", "Save");
|
$("#create_button").attr("value", "Save");
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
@ -6548,6 +6555,20 @@ $(document).ready(function () {
|
|||||||
select_rm_characters();
|
select_rm_characters();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#dupe_button").click(async function () {
|
||||||
|
|
||||||
|
const body = { avatar_url: characters[this_chid].avatar };
|
||||||
|
const response = await fetch('/dupecharacter', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: getRequestHeaders(),
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
if (response.ok) {
|
||||||
|
toastr.success("Character Duplicated");
|
||||||
|
getCharacters();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on("click", ".select_chat_block, .bookmark_link, .mes_bookmark", async function () {
|
$(document).on("click", ".select_chat_block, .bookmark_link, .mes_bookmark", async function () {
|
||||||
let file_name = $(this).hasClass('mes_bookmark')
|
let file_name = $(this).hasClass('mes_bookmark')
|
||||||
? $(this).closest('.mes').attr('bookmark_link')
|
? $(this).closest('.mes').attr('bookmark_link')
|
||||||
|
@ -762,7 +762,7 @@ async function deleteGroup(id) {
|
|||||||
|
|
||||||
$("#rm_info_avatar").html("");
|
$("#rm_info_avatar").html("");
|
||||||
$("#rm_info_block").transition({ opacity: 0, duration: 0 });
|
$("#rm_info_block").transition({ opacity: 0, duration: 0 });
|
||||||
select_rm_info("Group deleted!");
|
select_rm_info("group_delete", id);
|
||||||
$("#rm_info_block").transition({ opacity: 1.0, duration: 2000 });
|
$("#rm_info_block").transition({ opacity: 1.0, duration: 2000 });
|
||||||
|
|
||||||
$("#rm_button_selected_ch").children("h2").text('');
|
$("#rm_button_selected_ch").children("h2").text('');
|
||||||
|
33
server.js
33
server.js
@ -1545,6 +1545,39 @@ app.post("/importcharacter", urlencodedParser, async function (request, response
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.post("/dupecharacter", jsonParser, async function (request, response) {
|
||||||
|
try {
|
||||||
|
if (!request.body.avatar_url) {
|
||||||
|
console.log("avatar URL not found in request body");
|
||||||
|
console.log(request.body);
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
let filename = path.join(directories.characters, sanitize(request.body.avatar_url));
|
||||||
|
if (!fs.existsSync(filename)) {
|
||||||
|
console.log('file for dupe not found');
|
||||||
|
console.log(filename);
|
||||||
|
return response.sendStatus(404);
|
||||||
|
}
|
||||||
|
let suffix = 1;
|
||||||
|
let newFilename = filename;
|
||||||
|
while (fs.existsSync(newFilename)) {
|
||||||
|
let suffixStr = "_" + suffix;
|
||||||
|
let ext = path.extname(filename);
|
||||||
|
newFilename = filename.slice(0, -ext.length) + suffixStr + ext;
|
||||||
|
suffix++;
|
||||||
|
}
|
||||||
|
fs.copyFile(filename, newFilename, (err) => {
|
||||||
|
if (err) throw err;
|
||||||
|
console.log(`${filename} was copied to ${newFilename}`);
|
||||||
|
response.sendStatus(200);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return response.send({ error: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.post("/exportcharacter", jsonParser, async function (request, response) {
|
app.post("/exportcharacter", jsonParser, async function (request, response) {
|
||||||
if (!request.body.format || !request.body.avatar_url) {
|
if (!request.body.format || !request.body.avatar_url) {
|
||||||
return response.sendStatus(400);
|
return response.sendStatus(400);
|
||||||
|
Reference in New Issue
Block a user