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
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|