Drop Soulkyn import (#4372) * Fix Soulkyn import Generate and supply necessary headers to Soulkyn API request. Fixes #4323 * Drop soulkyn import --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "رابط PNG المباشر (راجع", |
| 1377 | 1377 | "char_import_7": "للمضيفين المسموح بهم)", |
| 1378 | 1378 | "char_import_8": "شخصية RisuRealm (رابط مباشر)", |
| 1379 | - "char_import_9": "شخصية Soulkyn (رابط مباشر)", | |
| 1380 | 1379 | "char_import_10": "شخصية Perchance (رابط مباشر أو UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "يدعم استيراد أحرف متعددة.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "اكتب كل عنوان URL أو معرف في سطر جديد.", |
| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "Direkter PNG-Link (siehe", |
| 1377 | 1377 | "char_import_7": "für erlaubte Hosts)", |
| 1378 | 1378 | "char_import_8": "RisuRealm-Charakter (Direktlink)", |
| 1379 | - "char_import_9": "Soulkyn-Charakter (Direktlink)", | |
| 1380 | 1379 | "char_import_10": "Perchance-Charakter (Direktlink oder UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "Unterstützt den Import mehrerer Zeichen.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "Schreiben Sie jede URL oder ID in eine neue Zeile.", |
| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "Enlace PNG directo (consulte", |
| 1377 | 1377 | "char_import_7": "para hosts permitidos)", |
| 1378 | 1378 | "char_import_8": "Personaje RisuRealm (Enlace directo)", |
| 1379 | - "char_import_9": "Personaje Soulkyn (Enlace directo)", | |
| 1380 | 1379 | "char_import_10": "Personaje Perchance (enlace directo o UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "Admite la importación de múltiples caracteres.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "Escriba cada URL o ID en una nueva línea.", |
| @@ -1298,7 +1298,6 @@ | ||
| 1298 | 1298 | "char_import_6": "Lien PNG direct (voir", |
| 1299 | 1299 | "char_import_7": "pour les hôtes autorisés)", |
| 1300 | 1300 | "char_import_8": "Personnage de RisuRealm (lien direct)", |
| 1301 | - "char_import_9": "Personnage de Soulkyn (lien direct)", | |
| 1302 | 1301 | "char_import_10": "Personnage de Perchance (lien direct ou UUID + .gz)", |
| 1303 | 1302 | "Supports importing multiple characters.": "Prend en charge l'importation de plusieurs caractères.", |
| 1304 | 1303 | "Write each URL or ID into a new line.": "Écrivez chaque URL ou identifiant dans une nouvelle ligne.", |
| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "Beinn PNG hlekkur (sjá", |
| 1377 | 1377 | "char_import_7": "fyrir leyfilega gestgjafa)", |
| 1378 | 1378 | "char_import_8": "RisuRealm karakter (beinn hlekkur)", |
| 1379 | - "char_import_9": "Soulkyn karakter (beinn hlekkur)", | |
| 1380 | 1379 | "char_import_10": "Perchance karakter (beinn hlekkur eða UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "Styður innflutning á mörgum stöfum.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "Skrifaðu hverja vefslóð eða auðkenni í nýja línu.", |
| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "Collegamento PNG diretto (fare riferimento a", |
| 1377 | 1377 | "char_import_7": "per gli host consentiti)", |
| 1378 | 1378 | "char_import_8": "Personaggio RisuRealm (collegamento diretto)", |
| 1379 | - "char_import_9": "Personaggio Soulkyn (collegamento diretto)", | |
| 1380 | 1379 | "char_import_10": "Perchance Personaggio (collegamento diretto o UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "Supporta l'importazione di più caratteri.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "Scrivi ogni URL o ID in una nuova riga.", |
| @@ -1378,7 +1378,6 @@ | ||
| 1378 | 1378 | "char_import_6": "直接PNGリンク(参照", |
| 1379 | 1379 | "char_import_7": "許可されたホストの場合)", |
| 1380 | 1380 | "char_import_8": "RisuRealm キャラクター (直接リンク)", |
| 1381 | - "char_import_9": "Soulkyn キャラクター (直接リンク)", | |
| 1382 | 1381 | "char_import_10": "Perchance キャラクター (直接リンクまたは UUID + .gz)", |
| 1383 | 1382 | "Supports importing multiple characters.": "複数のキャラクターのインポートをサポートします。", |
| 1384 | 1383 | "Write each URL or ID into a new line.": "各 URL または ID を新しい行に入力します。", |
| @@ -1395,7 +1395,6 @@ | ||
| 1395 | 1395 | "char_import_6": "직접 PNG 링크(참조", |
| 1396 | 1396 | "char_import_7": "허용된 호스트의 경우)", |
| 1397 | 1397 | "char_import_8": "RisuRealm 캐릭터 (직접링크)", |
| 1398 | - "char_import_9": "Soulkyn 캐릭터 (직접링크)", | |
| 1399 | 1398 | "char_import_10": "Perchance 캐릭터 (직접 링크 또는 UUID + .gz)", |
| 1400 | 1399 | "Supports importing multiple characters.": "여러 문자 가져오기를 지원합니다.", |
| 1401 | 1400 | "Write each URL or ID into a new line.": "각 URL 또는 ID를 새 줄에 작성합니다.", |
| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "Directe PNG-link (zie", |
| 1377 | 1377 | "char_import_7": "voor toegestane hosts)", |
| 1378 | 1378 | "char_import_8": "RisuRealm-personage (directe link)", |
| 1379 | - "char_import_9": "Soulkyn-personage (directe link)", | |
| 1380 | 1379 | "char_import_10": "Perchance-personage (directe link of UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "Ondersteunt het importeren van meerdere tekens.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "Schrijf elke URL of ID op een nieuwe regel.", |
| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "Link PNG direto (consulte", |
| 1377 | 1377 | "char_import_7": "para hosts permitidos)", |
| 1378 | 1378 | "char_import_8": "Personagem RisuRealm (link direto)", |
| 1379 | - "char_import_9": "Personagem Soulkyn (link direto)", | |
| 1380 | 1379 | "char_import_10": "Personagem Perchance (Link Direto ou UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "Suporta importação de vários caracteres.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "Escreva cada URL ou ID em uma nova linha.", |
| @@ -963,7 +963,6 @@ | ||
| 963 | 963 | "char_import_5": "Персонаж с AICharacterCards.com (прямая ссылка или ID)", |
| 964 | 964 | "char_import_6": "Прямая ссылка на PNG-файл (список разрешённых хостов находится в", |
| 965 | 965 | "char_import_7": ")", |
| 966 | - "char_import_9": "Персонаж с Soulkyn (прямая ссылка)", | |
| 967 | 966 | "char_import_10": "Персонаж с Perchance (прямая ссылка или UUID + .gz)", |
| 968 | 967 | "Grammar String": "Грамматика", |
| 969 | 968 | "GBNF or EBNF, depends on the backend in use. If you're using this you should know which.": "GBNF или EBNF, зависит от бэкенда. Если вы это используете, то, скорее всего, сами знаете, какой именно.", |
| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "Пряме посилання на PNG (див", |
| 1377 | 1377 | "char_import_7": "для дозволених хостів)", |
| 1378 | 1378 | "char_import_8": "Персонаж RisuRealm (пряме посилання)", |
| 1379 | - "char_import_9": "Персонаж Soulkyn (пряме посилання)", | |
| 1380 | 1379 | "char_import_10": "Персонаж Perchance (пряме посилання або UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "Підтримується імпорт кількох символів.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "Напишіть кожну URL-адресу або ідентифікатор у новому рядку.", |
| @@ -1376,7 +1376,6 @@ | ||
| 1376 | 1376 | "char_import_6": "Nhập PNG trực tiếp (tham khảo", |
| 1377 | 1377 | "char_import_7": "đối với các máy chủ được phép)", |
| 1378 | 1378 | "char_import_8": "RisuRealm (URL trực tiếp)", |
| 1379 | - "char_import_9": "Soulkyn (URL trực tiếp)", | |
| 1380 | 1379 | "char_import_10": "Perchance (Nhập URL trực tiếp hoặc UUID + .gz)", |
| 1381 | 1380 | "Supports importing multiple characters.": "Hỗ trợ nhập nhiều ký tự.", |
| 1382 | 1381 | "Write each URL or ID into a new line.": "Viết mỗi URL hoặc ID vào một dòng mới.", |
| @@ -1888,7 +1888,6 @@ | ||
| 1888 | 1888 | "char_import_6": "被允许的PNG直链(请参阅", |
| 1889 | 1889 | "char_import_7": ")", |
| 1890 | 1890 | "char_import_8": "RisuRealm 角色(直链)", |
| 1891 | - "char_import_9": "Soulkyn 角色(直链)", | |
| 1892 | 1891 | "char_import_10": "Perchance 角色(直链或UUID + .gz)", |
| 1893 | 1892 | "Supports importing multiple characters.": "支持导入多个角色。", |
| 1894 | 1893 | "Write each URL or ID into a new line.": "将每个 URL 或 ID 写入新行。", |
| @@ -1381,7 +1381,6 @@ | ||
| 1381 | 1381 | "char_import_6": "直接 PNG 連結(請參閱", |
| 1382 | 1382 | "char_import_7": "對於允許的主機)", |
| 1383 | 1383 | "char_import_8": "RisuRealm 角色(直接連結)", |
| 1384 | - "char_import_9": "Soulkyn 角色(直接連結)", | |
| 1385 | 1384 | "char_import_10": "Perchance 角色(直接連結或 ID + .gz)", |
| 1386 | 1385 | "Supports importing multiple characters.": "支援匯入多個字元。", |
| 1387 | 1386 | "Write each URL or ID into a new line.": "將每個 URL 或 ID 寫入新行。", |
| @@ -10,7 +10,6 @@ | ||
| 10 | 10 | <li><span data-i18n="char_import_5">AICharacterCards.com Character (Direct Link or ID)</span><br><span data-i18n="char_import_example">Example:</span> <tt>AICC/aicharcards/the-game-master</tt></li> |
| 11 | 11 | <li><span data-i18n="char_import_6">Direct PNG Link (refer to</span> <code>config.yaml</code><span data-i18n="char_import_7"> for allowed hosts)</span><br><span data-i18n="char_import_example">Example:</span> <tt>https://files.catbox.moe/notarealfile.png</tt></li> |
| 12 | 12 | <li><span data-i18n="char_import_8">RisuRealm Character (Direct Link)</span><br><span data-i18n="char_import_example">Example:</span> <tt>https://realm.risuai.net/character/3ca54c71-6efe-46a2-b9d0-4f62df23d712</tt></li> |
| 13 | - <li><span data-i18n="char_import_9">Soulkyn Character (Direct Link)</span><br><span data-i18n="char_import_example">Example:</span> <tt>https://soulkyn.com/l/en-US/@haruka-509al</tt></li> | |
| 14 | 13 | <li><span data-i18n="char_import_10">Perchance Character (Direct Link or UUID + .gz)</span><br><span data-i18n="char_import_example">Example:</span> <tt>https://perchance.org/ai-character-chat?data=Loreena~cb3a1b531477378db7cad0148ba62d71.gz</tt><br><span data-i18n="char_import_example">Example:</span> <tt>Loreena~cb3a1b531477378db7cad0148ba62d71.gz</tt></li> |
| 15 | 14 | </ul> |
| 16 | 15 | </div> |
| @@ -639,187 +639,6 @@ async function downloadRisuCharacter(uuid) { | ||
| 639 | 639 | return { buffer, fileName, fileType }; |
| 640 | 640 | } |
| 641 | 641 | |
| 642 | -/** | |
| 643 | - * Parse Soulkyn URL to extract the character slug. | |
| 644 | - * @param {string} url Soulkyn character URL | |
| 645 | - * @returns {string | null} Slug of the character | |
| 646 | - */ | |
| 647 | -function parseSoulkynUrl(url) { | |
| 648 | - // Example: https://soulkyn.com/l/en-US/@kayla-marie | |
| 649 | - const pattern = /^https:\/\/soulkyn\.com\/l\/[a-z]{2}-[A-Z]{2}\/@([\w\d-]+)/i; | |
| 650 | - const match = url.match(pattern); | |
| 651 | - return match ? match[1] : null; | |
| 652 | -} | |
| 653 | - | |
| 654 | -/** | |
| 655 | - * Download Soulkyn character card | |
| 656 | - * @param {string} slug Slug of the character | |
| 657 | - * @returns {Promise<{buffer: Buffer, fileName: string, fileType: string} | null>} | |
| 658 | - */ | |
| 659 | -async function downloadSoulkynCharacter(slug) { | |
| 660 | - const soulkynReplacements = [ | |
| 661 | - // https://soulkyn.com/l/en-US/help/character-backgrounds-advanced#variables-you-can-use-in-character-background-text | |
| 662 | - { pattern: /__USER_?NAME__/gi, replacement: '{{user}}' }, | |
| 663 | - { pattern: /__PERSONA_?NAME__/gi, replacement: '{{char}}' }, | |
| 664 | - // ST doesn't support gender-specific pronoun macros | |
| 665 | - { pattern: /__U_PRONOUN_1__/gi, replacement: 'they' }, | |
| 666 | - { pattern: /__U_PRONOUN_2__/gi, replacement: 'them' }, | |
| 667 | - { pattern: /__U_PRONOUN_3__/gi, replacement: 'their' }, | |
| 668 | - { pattern: /__U_PRONOUN_4__/gi, replacement: 'themselves' }, | |
| 669 | - { pattern: /__(USER_)?PRONOUN__/gi, replacement: 'they' }, | |
| 670 | - { pattern: /__(USER_)?CPRONOUN__/gi, replacement: 'them' }, | |
| 671 | - { pattern: /__(USER_)?UPRONOUN__/gi, replacement: 'their' }, | |
| 672 | - // HTML tags -> Markdown syntax | |
| 673 | - { pattern: /<(strong|b)>/gi, replacement: '**' }, | |
| 674 | - { pattern: /<\/(strong|b)>/gi, replacement: '**' }, | |
| 675 | - { pattern: /<(em|i)>/gi, replacement: '*' }, | |
| 676 | - { pattern: /<\/(em|i)>/gi, replacement: '*' }, | |
| 677 | - ]; | |
| 678 | - | |
| 679 | - const normalizeContent = (str) => soulkynReplacements.reduce((acc, { pattern, replacement }) => acc.replace(pattern, replacement), str); | |
| 680 | - | |
| 681 | - try { | |
| 682 | - const url = `https://soulkyn.com/_special/rest/Sk/public/Persona/${slug}`; | |
| 683 | - const result = await fetch(url, { | |
| 684 | - headers: { 'Content-Type': 'application/json', 'User-Agent': USER_AGENT }, | |
| 685 | - }); | |
| 686 | - if (result.ok) { | |
| 687 | - /** @type {any} */ | |
| 688 | - const soulkynCharData = await result.json(); | |
| 689 | - | |
| 690 | - if (soulkynCharData.result !== 'success') { | |
| 691 | - console.error('Soulkyn returned error', soulkynCharData.message); | |
| 692 | - throw new Error(`Failed to download character: ${soulkynCharData.message}`); | |
| 693 | - } | |
| 694 | - | |
| 695 | - // Fetch avatar | |
| 696 | - let avatarBuffer = null; | |
| 697 | - if (soulkynCharData.data?.Avatar?.FWSUUID) { | |
| 698 | - const avatarUrl = `https://rub.soulkyn.com/${soulkynCharData.data.Avatar.FWSUUID}/`; | |
| 699 | - const avatarResult = await fetch(avatarUrl, { headers: { 'User-Agent': USER_AGENT } }); | |
| 700 | - | |
| 701 | - if (avatarResult.ok) { | |
| 702 | - const avatarContentType = avatarResult.headers.get('content-type'); | |
| 703 | - if (avatarContentType === 'image/png') { | |
| 704 | - avatarBuffer = Buffer.from(await avatarResult.arrayBuffer()); | |
| 705 | - } else { | |
| 706 | - console.warn(`Soulkyn character (${slug}) avatar is not PNG: ${avatarContentType}`); | |
| 707 | - } | |
| 708 | - } else { | |
| 709 | - console.warn(`Soulkyn character (${slug}) avatar download failed: ${avatarResult.status}`); | |
| 710 | - } | |
| 711 | - } else { | |
| 712 | - console.warn(`Soulkyn character (${slug}) does not have an avatar`); | |
| 713 | - } | |
| 714 | - | |
| 715 | - // Fallback to default avatar | |
| 716 | - if (!avatarBuffer) { | |
| 717 | - const defaultAvatarPath = path.join(serverDirectory, DEFAULT_AVATAR_PATH); | |
| 718 | - avatarBuffer = fs.readFileSync(defaultAvatarPath); | |
| 719 | - } | |
| 720 | - | |
| 721 | - const d = soulkynCharData.data; | |
| 722 | - soulkynReplacements.push({ pattern: d.Username, replacement: '{{char}}' }); | |
| 723 | - | |
| 724 | - // Parse Soulkyn data into character chard | |
| 725 | - const charData = { | |
| 726 | - name: d.Username, | |
| 727 | - first_mes: '', | |
| 728 | - tags: [], | |
| 729 | - description: '', | |
| 730 | - creator: d.User.Username, | |
| 731 | - creator_notes: '', | |
| 732 | - alternate_greetings: [], | |
| 733 | - character_version: '', | |
| 734 | - mes_example: '', | |
| 735 | - post_history_instructions: '', | |
| 736 | - system_prompt: '', | |
| 737 | - scenario: '', | |
| 738 | - personality: '', | |
| 739 | - extensions: { | |
| 740 | - soulkyn_slug: slug, | |
| 741 | - soulkyn_id: d.UUID, | |
| 742 | - }, | |
| 743 | - }; | |
| 744 | - | |
| 745 | - if (d?.PersonaIntroText) { | |
| 746 | - const match = d.PersonaIntroText.match(/^(?:\[Scenario:\s*([\s\S]*?)\]\s*)?([\s\S]*)$/); | |
| 747 | - if (match) { | |
| 748 | - if (match[1]) { | |
| 749 | - charData.scenario = normalizeContent(match[1].trim()); | |
| 750 | - } | |
| 751 | - charData.first_mes = normalizeContent(match[2].trim()); | |
| 752 | - } | |
| 753 | - } | |
| 754 | - | |
| 755 | - const descriptionArr = ['Name: {{char}}']; | |
| 756 | - if (d?.Version?.Age) { | |
| 757 | - descriptionArr.push(`Age: ${d.Version.Age}`); | |
| 758 | - } | |
| 759 | - if (d?.Version?.Gender) { | |
| 760 | - descriptionArr.push(`Gender: ${d.Version.Gender}`); | |
| 761 | - } | |
| 762 | - if (d?.Version?.Race?.Name && !d.Version.Race.Name.match(/no preset/i)) { | |
| 763 | - let race = d.Version.Race.Name; | |
| 764 | - if (d.Version.Race?.Description) { | |
| 765 | - race += ` (${d.Version.Race.Description})`; | |
| 766 | - } | |
| 767 | - descriptionArr.push(`Race: ${race}`); | |
| 768 | - } | |
| 769 | - if (d?.PersonalityType) { | |
| 770 | - descriptionArr.push(`Personality type: ${d.PersonalityType}`); | |
| 771 | - } | |
| 772 | - if (Array.isArray(d?.Version?.PropertyPersonality)) { | |
| 773 | - const traits = d.Version.PropertyPersonality.map((t) => t.Value).join(', '); | |
| 774 | - descriptionArr.push(`Personality Traits: ${traits}`); | |
| 775 | - } | |
| 776 | - if (Array.isArray(d?.Version?.PropertyPhysical)) { | |
| 777 | - const traits = d.Version.PropertyPhysical.map((t) => t.Value).join(', '); | |
| 778 | - descriptionArr.push(`Physical Traits: ${traits}`); | |
| 779 | - } | |
| 780 | - if (Array.isArray(d?.Clothes?.Preset)) { | |
| 781 | - descriptionArr.push(`Clothes: ${d.Clothes.Preset.join(', ')}`); | |
| 782 | - } | |
| 783 | - if (d?.Avatar?.Caption) { | |
| 784 | - descriptionArr.push(`Image description featuring {{char}}: ${d.Avatar.Caption.replace(/\n+/g, ' ')}`); | |
| 785 | - } | |
| 786 | - if (d?.Version?.WelcomeMessage) { | |
| 787 | - if (charData.first_mes) { | |
| 788 | - descriptionArr.push(`{{char}}'s self-description: "${d.Version.WelcomeMessage}"`); | |
| 789 | - } else { | |
| 790 | - // Some characters lack `PersonaIntroText`. In that case we use `Version.WelcomeMessage` for `first_mes` | |
| 791 | - charData.first_mes = normalizeContent(d.Version.WelcomeMessage); | |
| 792 | - } | |
| 793 | - } | |
| 794 | - charData.description = normalizeContent(descriptionArr.join('\n')); | |
| 795 | - | |
| 796 | - if (Array.isArray(d?.Version?.ChatExamplesValue)) { | |
| 797 | - charData.mes_example = d.Version.ChatExamplesValue.map((example) => `<START>\n${normalizeContent(example)}`).join('\n'); | |
| 798 | - } | |
| 799 | - | |
| 800 | - if (Array.isArray(d?.PersonaTags)) { | |
| 801 | - charData.tags = d.PersonaTags.map((t) => t.Slug); | |
| 802 | - } | |
| 803 | - | |
| 804 | - // Character card | |
| 805 | - const buffer = write(avatarBuffer, JSON.stringify({ | |
| 806 | - 'spec': 'chara_card_v2', | |
| 807 | - 'spec_version': '2.0', | |
| 808 | - 'data': charData, | |
| 809 | - })); | |
| 810 | - | |
| 811 | - const fileName = `${sanitize(d.UUID)}.png`; | |
| 812 | - const fileType = 'image/png'; | |
| 813 | - | |
| 814 | - return { buffer, fileName, fileType }; | |
| 815 | - } | |
| 816 | - } catch (error) { | |
| 817 | - console.error('Error downloading character:', error); | |
| 818 | - throw error; | |
| 819 | - } | |
| 820 | - return null; | |
| 821 | -} | |
| 822 | - | |
| 823 | 642 | /** * Check if the given string is a valid Perchance UUID. |
| 824 | 643 | * @param {string} uuid UUID string to check |
| 825 | 644 | * @returns {boolean} True if the UUID is valid, false otherwise |
| @@ -921,13 +740,14 @@ async function downloadPerchanceCharacter(slug) { | ||
| 921 | 740 | return null; |
| 922 | 741 | } |
| 923 | 742 | |
| 924 | -/** * Extracts Perchance character data from a gzipped response. | |
| 743 | +/** | |
| 744 | + * Extracts Perchance character data from a gzipped response. | |
| 925 | 745 | * @param {import('node-fetch').Response} result Fetch response containing gzipped character data |
| 926 | 746 | * @returns {Promise<Object>} Parsed Perchance character data |
| 927 | 747 | * @throws {Error} If the character data is invalid or missing required fields |
| 928 | 748 | */ |
| 929 | 749 | async function extractPerchanceCharacterFromGz(result) { |
| 930 | 750 | const compressedBuffer = Buffer.from(await result.arrayBuffer()); |
| 931 | 751 | const decompressedBuffer = zlib.gunzipSync(compressedBuffer); |
| 932 | 752 | |
| 933 | 753 | // inside the gz file, there is a file of the same name without extensions, but it is a json file |
| @@ -1062,7 +882,6 @@ router.post('/importURL', async (request, response) => { | ||
| 1062 | 882 | const isPygmalionContent = host.includes('pygmalion.chat'); |
| 1063 | 883 | const isAICharacterCardsContent = host.includes('aicharactercards.com'); |
| 1064 | 884 | const isRisu = host.includes('realm.risuai.net'); |
| 1065 | - const isSoulkyn = host.includes('soulkyn.com'); | |
| 1066 | 885 | const isPerchance = host.includes('perchance.org'); |
| 1067 | 886 | const isGeneric = isHostWhitelisted(host); |
| 1068 | 887 | |
| @@ -1112,13 +931,6 @@ router.post('/importURL', async (request, response) => { | ||
| 1112 | 931 | |
| 1113 | 932 | type = 'character'; |
| 1114 | 933 | result = await downloadRisuCharacter(uuid); |
| 1115 | - } else if (isSoulkyn) { | |
| 1116 | - const soulkynSlug = parseSoulkynUrl(url); | |
| 1117 | - if (!soulkynSlug) { | |
| 1118 | - return response.sendStatus(404); | |
| 1119 | - } | |
| 1120 | - type = 'character'; | |
| 1121 | - result = await downloadSoulkynCharacter(soulkynSlug); | |
| 1122 | 934 | } else if (isPerchance) { |
| 1123 | 935 | const perchanceSlug = parsePerchanceSlug(url); |
| 1124 | 936 | if (!perchanceSlug) { |