fp/packages/fetchers/src/findOrCreateVtuber.ts

111 lines
3.6 KiB
TypeScript
Raw Normal View History

2024-09-16 16:31:51 +00:00
import { configs } from "./config.ts"
2024-08-27 07:11:24 +00:00
import type { VtuberRecord, VtuberResponse } from "@futureporn/types"
import qs from 'qs'
interface vTuberSearchQuery {
url: string;
name: string;
}
interface vTuberSearchOptions {
prefer: string;
}
const columns = [
'chaturbate',
'twitter',
'patreon',
'twitch',
'tiktok',
'onlyfans',
'youtube',
'fansly',
'pornhub'
];
2024-12-12 07:23:46 +00:00
// @see https://bobbyhadz.com/blog/javascript-remove-trailing-slash-from-string
2024-08-27 07:11:24 +00:00
function removeTrailingSlash(url: string) {
return url.replace(/\/+$/, '');
}
function buildUrlSearchOrTemplate(columns: string[], url: string): string {
return `(${columns.map(column => `${column}.ilike.*${url}*`).join(',')})`;
}
async function findVtuber(query: Partial<vTuberSearchQuery>, options?: Partial<vTuberSearchOptions>): Promise<string|null> {
const { url, name } = query
const queryOptions: any = {}
// When url argument exists, we try searching against the vtuber's platform urls
if (url) queryOptions.or = buildUrlSearchOrTemplate(columns, removeTrailingSlash(url));
if (!url && !name) throw new Error(`findVtuber requires url or name passed in an object as argument.`);
const fetchUrl = `${configs.postgrestUrl}/vtubers?${qs.stringify(queryOptions, { encode: false })}`
2024-09-16 16:31:51 +00:00
console.info(fetchUrl)
2024-08-27 07:11:24 +00:00
const fetchOptions = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Prefer': 'return=representation',
'Authorization': `Bearer ${configs.automationUserJwt}`,
}
}
const res = await fetch(fetchUrl, fetchOptions)
if (!res.ok) {
const msg = `request failed. status=${res.status}, statusText=${res.statusText}`
2024-09-16 16:31:51 +00:00
console.error(msg)
2024-08-27 07:11:24 +00:00
throw new Error(msg)
}
const json = await res.json() as VtuberResponse[]
2024-09-16 16:31:51 +00:00
// console.info(`vtuber results as follows.`)
// console.info(json)
2024-08-27 07:11:24 +00:00
return json?.at(0)?.id || null
}
async function createVtuber(vtuber: Partial<VtuberRecord>): Promise<string> {
const createVtuberPayload = vtuber
const fetchUrl = `${configs.postgrestUrl}/vtubers`
const fetchOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Prefer': 'return=representation',
'Authorization': `Bearer ${configs.automationUserJwt}`
},
body: JSON.stringify(createVtuberPayload)
}
const res = await fetch(fetchUrl, fetchOptions)
if (!res.ok) {
const body = await res.text()
const msg = `createVtuber fetch failed. status=${res.status}, statusText=${res.statusText}, body=${body}`
2024-09-16 16:31:51 +00:00
console.error(msg)
2024-08-27 07:11:24 +00:00
throw new Error(msg)
}
const json = await res.json() as VtuberResponse[]
2024-09-21 03:01:21 +00:00
// console.info(`createVtuber with vtuber as follows`)
// console.info(vtuber)
// console.info(json)
2024-08-27 07:11:24 +00:00
const vtuberData = json[0]
if (!vtuberData) throw new Error('failed to createVtuber')
return vtuberData.id
}
export default async function findOrCreateVtuber(query: Partial<vTuberSearchQuery>, options?: Partial<vTuberSearchOptions>): Promise<string> {
if (!query) throw new Error(`findOrCreateVtuber requires an object as argument`);
const { url, name } = query
if (!url) throw new Error('findOrCreateVtuber was missing url which is required');
2024-09-16 16:31:51 +00:00
console.info(`findOrCreateVtuber. url=${url}, name=${name}`)
2024-09-21 03:01:21 +00:00
new URL(url) // validate URL, throw if invalid
2024-08-27 07:11:24 +00:00
const foundVtuber = await findVtuber(query)
if (!foundVtuber) {
2024-09-16 16:31:51 +00:00
console.info(`Failed to find vtuber, so we create one.`)
2024-08-31 10:42:28 +00:00
const vtuber = await fetch(`${configs.scoutUrl}/vtuber/data?url=${url}`).then((res): Promise<VtuberRecord> => res.json() as any)
2024-08-27 07:11:24 +00:00
return createVtuber(vtuber)
} else {
return foundVtuber
}
}