| 323 | } | 324 | } |
| 324 | | 325 | |
| 325 | async function downloadChubLorebook(id) { | 326 | async function downloadChubLorebook(id) { |
| 326 | const result = await fetch('https://api.chub.ai/api/lorebooks/download', { | 327 | const [lorebooks, creatorName, projectName] = id.split('/'); |
| 327 | method: 'POST', | 328 | const result = await fetch(`https://api.chub.ai/api/${lorebooks}/${creatorName}/${projectName}`, { |
| 328 | headers: { 'Content-Type': 'application/json' }, | 329 | method: 'GET', |
| 329 | body: JSON.stringify({ | 330 | headers: { 'Accept': 'application/json', 'User-Agent': USER_AGENT }, |
| 330 | 'fullPath': id, | | |
| 331 | 'format': 'SILLYTAVERN', | | |
| 332 | }), | | |
| 333 | }); | 331 | }); |
| 334 | | 332 | |
| 335 | if (!result.ok) { | 333 | if (!result.ok) { |
| 336 | const text = await result.text(); | 334 | const text = await result.text(); |
| 337 | console.error('Chub returned error', result.statusText, text); | 335 | console.error('Chub returned error', result.statusText, text); |
| | 336 | throw new Error('Failed to fetch lorebook metadata'); |
| | 337 | } |
| | 338 | |
| | 339 | /** @type {any} */ |
| | 340 | const metadata = await result.json(); |
| | 341 | const projectId = metadata.node?.id; |
| | 342 | |
| | 343 | if (!projectId) { |
| | 344 | throw new Error('Project ID not found in lorebook metadata'); |
| | 345 | } |
| | 346 | |
| | 347 | const downloadUrl = `https://api.chub.ai/api/v4/projects/${projectId}/repository/files/raw%252Fsillytavern_raw.json/raw`; |
| | 348 | const downloadResult = await fetch(downloadUrl, { |
| | 349 | method: 'GET', |
| | 350 | headers: { 'Accept': 'application/json', 'User-Agent': USER_AGENT }, |
| | 351 | }); |
| | 352 | |
| | 353 | if (!downloadResult.ok) { |
| | 354 | const text = await downloadResult.text(); |
| | 355 | console.error('Chub returned error', downloadResult.statusText, text); |
| 338 | throw new Error('Failed to download lorebook'); | 356 | throw new Error('Failed to download lorebook'); |
| 339 | } | 357 | } |
| 340 | | 358 | |
| 341 | const name = id.split('/').pop(); | 359 | const name = projectName; |
| 342 | const buffer = Buffer.from(await result.arrayBuffer()); | 360 | const buffer = Buffer.from(await downloadResult.arrayBuffer()); |
| 343 | const fileName = `${sanitize(name)}.json`; | 361 | const fileName = `${sanitize(name)}.json`; |
| 344 | const fileType = result.headers.get('content-type'); | 362 | const fileType = downloadResult.headers.get('content-type'); |
| 345 | | 363 | |
| 346 | return { buffer, fileName, fileType }; | 364 | return { buffer, fileName, fileType }; |
| 347 | } | 365 | } |
| 348 | | 366 | |
| 349 | async function downloadChubCharacter(id) { | 367 | async function downloadChubCharacter(id) { |
| 350 | const result = await fetch('https://api.chub.ai/api/characters/download', { | 368 | const [creatorName, projectName] = id.split('/'); |
| 351 | method: 'POST', | 369 | const result = await fetch(`https://api.chub.ai/api/characters/${creatorName}/${projectName}`, { |
| 352 | headers: { 'Content-Type': 'application/json' }, | 370 | method: 'GET', |
| 353 | body: JSON.stringify({ | 371 | headers: { 'Accept': 'application/json', 'User-Agent': USER_AGENT }, |
| 354 | 'format': 'tavern', | | |
| 355 | 'fullPath': id, | | |
| 356 | }), | | |
| 357 | }); | 372 | }); |
| 358 | | 373 | |
| 359 | if (!result.ok) { | 374 | if (!result.ok) { |
| 360 | const text = await result.text(); | 375 | const text = await result.text(); |
| 361 | console.error('Chub returned error', result.statusText, text); | 376 | console.error('Chub returned error', result.statusText, text); |
| | 377 | throw new Error('Failed to fetch character metadata'); |
| | 378 | } |
| | 379 | |
| | 380 | /** @type {any} */ |
| | 381 | const metadata = await result.json(); |
| | 382 | const downloadUrl = metadata.node?.max_res_url; |
| | 383 | |
| | 384 | if (!downloadUrl) { |
| | 385 | throw new Error('Download URL not found in character metadata'); |
| | 386 | } |
| | 387 | |
| | 388 | const downloadResult = await fetch(downloadUrl); |
| | 389 | |
| | 390 | if (!downloadResult.ok) { |
| | 391 | const text = await downloadResult.text(); |
| | 392 | console.error('Chub returned error', downloadResult.statusText, text); |
| 362 | throw new Error('Failed to download character'); | 393 | throw new Error('Failed to download character'); |
| 363 | } | 394 | } |
| 364 | | 395 | |
| 365 | const buffer = Buffer.from(await result.arrayBuffer()); | 396 | const buffer = Buffer.from(await downloadResult.arrayBuffer()); |
| 366 | const fileName = result.headers.get('content-disposition')?.split('filename=')[1] || `${sanitize(id)}.png`; | 397 | const fileName = |
| 367 | const fileType = result.headers.get('content-type'); | 398 | downloadResult.headers.get('content-disposition')?.split('filename=')[1]?.replace(/["']/g, '') || |
| | 399 | `${sanitize(projectName)}.png`; |
| | 400 | const fileType = downloadResult.headers.get('content-type'); |
| 368 | | 401 | |
| 369 | return { buffer, fileName, fileType }; | 402 | return { buffer, fileName, fileType }; |
| 370 | } | 403 | } |