mirror of
https://github.com/storytold/placeholder-artcraft.git
synced 2026-10-25 08:29:18 +00:00
mirror repo (WIP)
Need to remove secrets before entire repo can be made public.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
export * from "./lib/enums/index.js";
|
||||
export * from "./lib/models/Users.js";
|
||||
export * from "./lib/AnalyticsApi.js";
|
||||
export * from "./lib/BillingApi.js";
|
||||
export * from "./lib/EngineApi.js";
|
||||
export * from "./lib/JobsApi.js";
|
||||
export * from "./lib/MediaFilesApi.js";
|
||||
export * from "./lib/MediaUploadApi.js";
|
||||
export * from "./lib/MiscApi.js";
|
||||
export * from "./lib/LocalApi.js";
|
||||
export * from "./lib/PromptsApi.js";
|
||||
export * from "./lib/TtsApi.js";
|
||||
export * from "./lib/UserBookmarksApi.js";
|
||||
export * from "./lib/UsersApi.js";
|
||||
export * from "./lib/VideoApi.js";
|
||||
export * from "./lib/WeightsApi.js";
|
||||
export * from "./lib/GetCdnOrigin.js";
|
||||
export * from "./lib/GalleryModalApi.js";
|
||||
export * from "./lib/config/StorytellerApiHostStore.js"
|
||||
@@ -0,0 +1,38 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
|
||||
export class AnalyticsApi extends ApiManager {
|
||||
public PostAnalytics({
|
||||
maybeLastAction,
|
||||
maybeLogToken,
|
||||
}: {
|
||||
maybeLastAction: string;
|
||||
maybeLogToken: string;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/analytics/log_session`;
|
||||
|
||||
const body = {
|
||||
maybe_last_action: maybeLastAction,
|
||||
maybe_log_token: maybeLogToken,
|
||||
};
|
||||
|
||||
return this.post<
|
||||
{
|
||||
maybe_last_action: string;
|
||||
maybe_log_token: string;
|
||||
},
|
||||
{
|
||||
success?: boolean;
|
||||
log_token?: string;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
data: response.log_token,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
// import { bool } from "@techstark/opencv-js";
|
||||
import { StorytellerApiHostStore } from "./config/StorytellerApiHostStore.js";
|
||||
import { API_TARGETS } from "./enums/Api.js";
|
||||
//import { fetch } from '@tauri-apps/plugin-http'
|
||||
import { FetchProxy as fetch } from "@storyteller/tauri-utils";
|
||||
|
||||
type NonNullableObject<T extends object> = NonNullable<T>;
|
||||
|
||||
export interface ApiResponse<T, P = undefined> {
|
||||
success: boolean;
|
||||
errorMessage?: string;
|
||||
data?: T;
|
||||
pagination?: P;
|
||||
}
|
||||
|
||||
export class ApiManager {
|
||||
ApiTargets: Record<string, string> = {};
|
||||
|
||||
constructor() {
|
||||
this.ApiTargets = {
|
||||
GoggleApi: API_TARGETS.GOOGLE_API,
|
||||
FunnelApi: API_TARGETS.FUNNEL_API,
|
||||
CdnApi: API_TARGETS.CDN_API,
|
||||
GravatarApi: API_TARGETS.GRAVATAR_API,
|
||||
};
|
||||
}
|
||||
|
||||
protected getApiSchemeAndHost(): string {
|
||||
return StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
|
||||
}
|
||||
|
||||
public async fetch<B, T>(
|
||||
endpoint: string,
|
||||
{
|
||||
method,
|
||||
query,
|
||||
body,
|
||||
}: {
|
||||
method: string;
|
||||
query?: Record<string, string | boolean | number | undefined>;
|
||||
body?: B;
|
||||
},
|
||||
): Promise<T> {
|
||||
const queryInString =
|
||||
query &&
|
||||
Object.entries(query).reduce(
|
||||
(allOptions, [key, value]) => {
|
||||
if (!value) {
|
||||
return allOptions;
|
||||
}
|
||||
allOptions[key] = value.toString();
|
||||
return allOptions;
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
);
|
||||
|
||||
const endpointWithQueries = queryInString
|
||||
? endpoint + "?" + new URLSearchParams(queryInString)
|
||||
: endpoint;
|
||||
|
||||
const bodyInString = JSON.stringify(body);
|
||||
|
||||
const response = await fetch(endpointWithQueries, {
|
||||
method,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
body: bodyInString,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
public async fetchMultipartFormData<T>(
|
||||
endpoint: string,
|
||||
{
|
||||
method,
|
||||
body,
|
||||
}: {
|
||||
method: string;
|
||||
body: FormData;
|
||||
},
|
||||
): Promise<T> {
|
||||
const response = await fetch(endpoint, {
|
||||
method,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
body: body,
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
protected get<T>({
|
||||
endpoint,
|
||||
query,
|
||||
}: {
|
||||
endpoint: string;
|
||||
query?: Record<string, string | boolean | number | undefined>;
|
||||
}): Promise<T> {
|
||||
return this.fetch<null, T>(endpoint, { method: "GET", query });
|
||||
}
|
||||
|
||||
protected post<B, T>({
|
||||
endpoint,
|
||||
query,
|
||||
body,
|
||||
}: {
|
||||
endpoint: string;
|
||||
query?: Record<string, string | boolean | number | undefined>;
|
||||
body?: B;
|
||||
}): Promise<T> {
|
||||
return this.fetch<B, T>(endpoint, {
|
||||
method: "POST",
|
||||
query,
|
||||
body,
|
||||
});
|
||||
}
|
||||
|
||||
protected delete<B, T>({
|
||||
endpoint,
|
||||
query,
|
||||
body,
|
||||
}: {
|
||||
endpoint: string;
|
||||
query?: Record<string, string | boolean | number | undefined>;
|
||||
body?: B;
|
||||
}): Promise<T> {
|
||||
return this.fetch<B, T>(endpoint, {
|
||||
method: "DELETE",
|
||||
query,
|
||||
body,
|
||||
});
|
||||
}
|
||||
|
||||
protected async postFormVideo<T>({
|
||||
endpoint,
|
||||
formRecord,
|
||||
uuid,
|
||||
blob,
|
||||
blobFileName,
|
||||
}: {
|
||||
endpoint: string;
|
||||
formRecord: Record<string, string>;
|
||||
uuid: string;
|
||||
blob?: Blob | File;
|
||||
blobFileName?: string;
|
||||
}): Promise<T> {
|
||||
const formData = new FormData();
|
||||
formData.append("uuid_idempotency_token", uuid);
|
||||
Object.entries(formRecord).forEach(([key, value]) => {
|
||||
formData.append(key, value);
|
||||
});
|
||||
|
||||
if (blob && blobFileName) {
|
||||
formData.append("video", blob, blobFileName);
|
||||
} else if (blob) {
|
||||
formData.append("video", blob);
|
||||
}
|
||||
|
||||
return this.fetchMultipartFormData<T>(endpoint, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
}
|
||||
|
||||
protected async postForm<T>({
|
||||
endpoint,
|
||||
formRecord,
|
||||
uuid,
|
||||
blob,
|
||||
blobFileName,
|
||||
}: {
|
||||
endpoint: string;
|
||||
formRecord: Record<string, string>;
|
||||
uuid: string;
|
||||
blob?: Blob | File;
|
||||
blobFileName?: string;
|
||||
}): Promise<T> {
|
||||
const formData = new FormData();
|
||||
formData.append("uuid_idempotency_token", uuid);
|
||||
Object.entries(formRecord).forEach(([key, value]) => {
|
||||
formData.append(key, value);
|
||||
});
|
||||
|
||||
if (blob && blobFileName) {
|
||||
formData.append("file", blob, blobFileName);
|
||||
} else if (blob) {
|
||||
formData.append("file", blob);
|
||||
}
|
||||
|
||||
return this.fetchMultipartFormData<T>(endpoint, {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
}
|
||||
|
||||
protected camelToSnakeCase(str: string) {
|
||||
return str.replace(/([a-z0])([A-Z])/g, "$1_$2").toLowerCase();
|
||||
}
|
||||
|
||||
protected parseQueryValues(
|
||||
params: Record<string, string | string[] | boolean | number | undefined>,
|
||||
): Record<string, string> {
|
||||
return Object.entries(params).reduce(
|
||||
(allParams, [key, value]) => {
|
||||
if (!value) {
|
||||
return allParams;
|
||||
}
|
||||
const snakeKey = this.camelToSnakeCase(key);
|
||||
if (Array.isArray(value)) {
|
||||
return { ...allParams, [snakeKey]: value.join(",") };
|
||||
}
|
||||
return { ...allParams, [snakeKey]: value.toString() };
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
);
|
||||
}
|
||||
|
||||
protected parseBodyValues<T extends object, B extends object>(
|
||||
params: NonNullableObject<T>,
|
||||
): B {
|
||||
return Object.entries(params).reduce((allParams, [key, value]) => {
|
||||
if (!value) {
|
||||
return allParams;
|
||||
}
|
||||
const snakeKey = this.camelToSnakeCase(key);
|
||||
if (Array.isArray(value)) {
|
||||
return { ...allParams, [snakeKey]: value };
|
||||
}
|
||||
return { ...allParams, [snakeKey]: value };
|
||||
}, {} as B);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { Subscription } from "./models/Billing.js";
|
||||
import { LoyaltyProgram } from "./enums/Billing.js";
|
||||
|
||||
export class BillingApi extends ApiManager {
|
||||
public async ListActiveSubscriptions(): Promise<
|
||||
ApiResponse<{
|
||||
active_subscriptions: Subscription[];
|
||||
maybe_loyalty_program?: LoyaltyProgram;
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/billing/active_subscriptions`;
|
||||
return await this.get<{
|
||||
success: boolean;
|
||||
active_subscriptions?: Subscription[];
|
||||
maybe_loyalty_program?: LoyaltyProgram;
|
||||
error_message?: string;
|
||||
}>({ endpoint: endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: {
|
||||
active_subscriptions: response.active_subscriptions || [],
|
||||
maybe_loyalty_program: response.maybe_loyalty_program,
|
||||
},
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager";
|
||||
|
||||
export class EngineApi extends ApiManager {
|
||||
public async ConvertTbxToGltf({
|
||||
mediaFileToken,
|
||||
uuidIdempotencyToken,
|
||||
}: {
|
||||
mediaFileToken: string;
|
||||
uuidIdempotencyToken: string;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/conversion/enqueue_fbx_to_gltf`;
|
||||
|
||||
const body = {
|
||||
media_file_token: mediaFileToken,
|
||||
uuid_idempotency_token: uuidIdempotencyToken,
|
||||
};
|
||||
|
||||
return this.post<
|
||||
{ media_file_token: string; uuid_idempotency_token: string },
|
||||
{ success?: boolean; inference_job_token?: string; BadInput?: string }
|
||||
>({
|
||||
endpoint,
|
||||
body: body,
|
||||
})
|
||||
.then((response) => {
|
||||
return {
|
||||
success: response.success ?? false,
|
||||
data: response.inference_job_token,
|
||||
errorMessage: response.BadInput,
|
||||
};
|
||||
})
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async uploadSceneSnapshot({
|
||||
screenshot,
|
||||
sceneMediaToken,
|
||||
}: {
|
||||
screenshot: File; // base64 encoded PNG
|
||||
sceneMediaToken?: string;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/scene_snapshot`;
|
||||
const formData = new FormData();
|
||||
formData.append("snapshot", screenshot); // Changed from "screenshot" to "snapshot" to match API spec
|
||||
if (sceneMediaToken) {
|
||||
formData.append("scene_media_token", sceneMediaToken);
|
||||
}
|
||||
|
||||
// for now ...
|
||||
const uuidIdempotencyToken = crypto.randomUUID(); // Generate a new UUID
|
||||
formData.append("uuid_idempotency_token", uuidIdempotencyToken); // Added uuid_idempotency_token
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const postResponse = await response.json();
|
||||
|
||||
console.log(postResponse);
|
||||
|
||||
let result: { success: boolean; data?: string; errorMessage?: string };
|
||||
|
||||
if (postResponse.success) {
|
||||
result = {
|
||||
success: true,
|
||||
data: postResponse.snapshot_media_token,
|
||||
errorMessage: undefined,
|
||||
};
|
||||
} else {
|
||||
result = {
|
||||
success: false,
|
||||
errorMessage: postResponse.BadInput,
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async enqueueImageGeneration({
|
||||
disableSystemPrompt,
|
||||
prompt,
|
||||
snapshotMediaToken,
|
||||
additionalImages,
|
||||
}: {
|
||||
disableSystemPrompt: boolean;
|
||||
prompt: string;
|
||||
snapshotMediaToken: string;
|
||||
additionalImages?: string[];
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/prompt`;
|
||||
|
||||
const uuidIdempotencyToken = crypto.randomUUID(); // Generate a new UUID
|
||||
const body = {
|
||||
uuid_idempotency_token: uuidIdempotencyToken,
|
||||
disable_system_prompt: disableSystemPrompt,
|
||||
prompt,
|
||||
snapshot_media_token: snapshotMediaToken, // Changed from scene_media_token to snapshot_media_token
|
||||
additional_images: additionalImages,
|
||||
};
|
||||
|
||||
const postResponse = await this.post<
|
||||
{
|
||||
uuid_idempotency_token: string;
|
||||
disable_system_prompt: boolean;
|
||||
prompt: string;
|
||||
snapshot_media_token: string;
|
||||
additional_images?: string[];
|
||||
},
|
||||
{ success?: boolean; job_token?: string; BadInput?: string }
|
||||
>({
|
||||
endpoint,
|
||||
body,
|
||||
});
|
||||
|
||||
// Check if the response is successful
|
||||
const isSuccess = postResponse.success ?? false;
|
||||
|
||||
// Prepare the result object
|
||||
const result = {
|
||||
success: isSuccess,
|
||||
data: isSuccess ? postResponse.job_token : undefined,
|
||||
errorMessage: isSuccess ? undefined : postResponse.BadInput,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async pollJobSession(jobToken: string): Promise<
|
||||
ApiResponse<{
|
||||
status: string;
|
||||
result: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/session/${jobToken}`;
|
||||
|
||||
const response = await this.get<{
|
||||
success?: boolean;
|
||||
status?: string;
|
||||
result?: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
BadInput?: string;
|
||||
}>({
|
||||
endpoint,
|
||||
});
|
||||
|
||||
const success = response.success ?? false;
|
||||
const status = response.status ?? "";
|
||||
const result = response.result ?? {
|
||||
generated_images: [],
|
||||
error: undefined,
|
||||
};
|
||||
const errorMessage = response.BadInput;
|
||||
|
||||
return {
|
||||
success,
|
||||
data: { status, result },
|
||||
errorMessage,
|
||||
};
|
||||
}
|
||||
|
||||
public async pollStudioSessionJobs(jobToken: string): Promise<
|
||||
ApiResponse<{
|
||||
status: string;
|
||||
result: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/session_jobs/${jobToken}`;
|
||||
|
||||
const response = await this.get<{
|
||||
success?: boolean;
|
||||
status?: string;
|
||||
result?: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
BadInput?: string;
|
||||
}>({
|
||||
endpoint,
|
||||
});
|
||||
|
||||
const success = response.success ?? false;
|
||||
const status = response.status ?? "";
|
||||
const result = response.result ?? {
|
||||
generated_images: [],
|
||||
error: undefined,
|
||||
};
|
||||
const errorMessage = response.BadInput;
|
||||
|
||||
return {
|
||||
success,
|
||||
data: { status, result },
|
||||
errorMessage,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { MediaFilesApi } from "./MediaFilesApi.js";
|
||||
import {
|
||||
FilterMediaClasses,
|
||||
FilterMediaType,
|
||||
FilterEngineCategories,
|
||||
} from "./enums/QueryFilters.js";
|
||||
|
||||
interface ListUserMediaQuery {
|
||||
username: string;
|
||||
filter_media_classes?: FilterMediaClasses[];
|
||||
filter_media_type?: FilterMediaType[];
|
||||
filter_engine_categories?: FilterEngineCategories[];
|
||||
user_uploads_only?: boolean;
|
||||
include_user_uploads?: boolean;
|
||||
page_index?: number;
|
||||
page_size?: number;
|
||||
}
|
||||
|
||||
export class GalleryModalApi extends MediaFilesApi {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
public async listUserMediaFiles(query: ListUserMediaQuery) {
|
||||
return await this.ListUserMediaFiles({
|
||||
...query,
|
||||
filter_media_classes: query.filter_media_classes,
|
||||
filter_media_type: query.filter_media_type,
|
||||
filter_engine_categories: query.filter_engine_categories,
|
||||
username: query.username,
|
||||
user_uploads_only: query.user_uploads_only,
|
||||
include_user_uploads: query.include_user_uploads,
|
||||
page_index: query.page_index,
|
||||
page_size: query.page_size,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// TODO(bt,2025-05-15): Remove this code
|
||||
export function GetCdnOrigin(): string {
|
||||
return "https://cdn-2.fakeyou.com";
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
// libs/api-client/src/JobsApi.ts
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { Job, JobPreview } from "./models/Job.js";
|
||||
import { JobState } from "./models/JobState.js";
|
||||
|
||||
export class JobsApi extends ApiManager {
|
||||
public GetPreviewStatusByJobToken({
|
||||
token,
|
||||
}: {
|
||||
token: string;
|
||||
}): Promise<ApiResponse<JobPreview>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/workflows/preview_status/${token}`;
|
||||
|
||||
return this.get<ApiResponse<JobPreview>>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: response.data,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public GetJobByToken({
|
||||
token,
|
||||
}: {
|
||||
token: string;
|
||||
}): Promise<ApiResponse<JobState>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/job/${token}`;
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
state: JobState;
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: response.state,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListJobs(): Promise<ApiResponse<JobState[]>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/batch`;
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
job_states: JobState[];
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: response.job_states,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListRecentJobs(): Promise<ApiResponse<Job[]>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/session`;
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
jobs: Job[];
|
||||
error_reason?: string;
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: response.jobs,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public DeleteJobByToken(jobToken: string): Promise<ApiResponse<undefined>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/job/${jobToken}`;
|
||||
|
||||
return this.delete<
|
||||
undefined,
|
||||
{
|
||||
success: boolean;
|
||||
}
|
||||
>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
|
||||
import { download } from "@tauri-apps/plugin-upload";
|
||||
import { downloadDir } from "@tauri-apps/api/path";
|
||||
|
||||
export const downloadFileFromUrl = async (url: string) => {
|
||||
console.log("GOT THE URL", url);
|
||||
try {
|
||||
// Extract filename from URL
|
||||
const urlObj = new URL(url);
|
||||
let filename = urlObj.pathname.split("/").pop();
|
||||
if (!filename || filename === "") {
|
||||
filename = "downloaded_file";
|
||||
}
|
||||
|
||||
// Get downloads directory path
|
||||
const downloadsPath = await downloadDir();
|
||||
const filePath = `${downloadsPath}/${filename}`;
|
||||
|
||||
// Download and save the file
|
||||
await download(url, filePath);
|
||||
|
||||
console.log(
|
||||
`File downloaded and saved as ${filename} in downloads folder`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Error downloading file:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,372 @@
|
||||
import { MediaFile } from "./models/MediaFile.js";
|
||||
import { Pagination, PaginationInfinite } from "./models/Pagination.js";
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { Visibility } from "./enums/Visibility.js";
|
||||
|
||||
import {
|
||||
FilterEngineCategories,
|
||||
FilterMediaClasses,
|
||||
FilterMediaType,
|
||||
} from "./enums/QueryFilters.js";
|
||||
|
||||
interface ListMediaQuery {
|
||||
sort_ascending?: boolean;
|
||||
page_size?: number;
|
||||
cursor?: string;
|
||||
cursor_is_reversed?: boolean;
|
||||
filter_media_classes?: FilterMediaClasses[];
|
||||
filter_media_type?: FilterMediaType[];
|
||||
filter_engine_categories?: FilterEngineCategories[];
|
||||
}
|
||||
|
||||
interface ListUserMediaQuery {
|
||||
username: string;
|
||||
sort_ascending?: boolean;
|
||||
page_size?: number;
|
||||
page_index?: number;
|
||||
filter_media_classes?: FilterMediaClasses[];
|
||||
filter_media_type?: FilterMediaType[];
|
||||
filter_engine_categories?: FilterEngineCategories[];
|
||||
user_uploads_only?: boolean;
|
||||
include_user_uploads?: boolean;
|
||||
}
|
||||
|
||||
interface SearchFeaturedMediaQuery {
|
||||
search_term: string;
|
||||
filter_media_classes?: FilterMediaClasses[];
|
||||
filter_media_type?: FilterMediaType[];
|
||||
filter_engine_categories?: FilterEngineCategories[];
|
||||
}
|
||||
|
||||
export class MediaFilesApi extends ApiManager {
|
||||
public async DeleteMediaFileByToken({
|
||||
mediaFileToken,
|
||||
asMod = true,
|
||||
setDelete = true,
|
||||
}: {
|
||||
mediaFileToken: string;
|
||||
asMod?: boolean;
|
||||
setDelete?: boolean;
|
||||
}): Promise<ApiResponse<MediaFile>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/file/${mediaFileToken}`;
|
||||
|
||||
const body = { as_mod: asMod, set_delete: setDelete };
|
||||
return await this.delete<
|
||||
{
|
||||
as_mod: boolean;
|
||||
set_delete: boolean;
|
||||
},
|
||||
{
|
||||
success?: boolean;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async ListMediaFilesByTokens({
|
||||
mediaTokens,
|
||||
}: {
|
||||
mediaTokens: string[];
|
||||
}): Promise<ApiResponse<MediaFile[]>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/batch`;
|
||||
|
||||
return await this.get<{
|
||||
success: boolean;
|
||||
media_files: MediaFile[];
|
||||
error_reason?: string;
|
||||
}>({ endpoint, query: { tokens: mediaTokens.join(",") } })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: response.media_files,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public async GetMediaFileByToken({
|
||||
mediaFileToken,
|
||||
}: {
|
||||
mediaFileToken: string;
|
||||
}): Promise<ApiResponse<MediaFile>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/file/${mediaFileToken}`;
|
||||
return await this.get<{
|
||||
success: boolean;
|
||||
media_file: MediaFile;
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: response.media_file,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async ListMediaFiles(
|
||||
query: ListMediaQuery
|
||||
): Promise<ApiResponse<MediaFile[], PaginationInfinite>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list`;
|
||||
const queryWithStrings = {
|
||||
...query,
|
||||
filter_media_classes: query.filter_media_classes
|
||||
? query.filter_media_classes.join(",")
|
||||
: undefined,
|
||||
filter_media_type: query.filter_media_type
|
||||
? query.filter_media_type.join(",")
|
||||
: undefined,
|
||||
filter_engine_categories: query.filter_engine_categories
|
||||
? query.filter_engine_categories.join(",")
|
||||
: undefined,
|
||||
};
|
||||
return await this.get<{
|
||||
success: boolean;
|
||||
results: MediaFile[];
|
||||
pagination?: PaginationInfinite;
|
||||
}>({ endpoint, query: queryWithStrings })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: response.results ?? [],
|
||||
pagination: response.pagination,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async ListFeaturedMediaFiles(
|
||||
query: ListMediaQuery
|
||||
): Promise<ApiResponse<MediaFile[], PaginationInfinite>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list_featured`;
|
||||
const queryWithStrings = {
|
||||
...query,
|
||||
filter_media_classes: query.filter_media_classes
|
||||
? query.filter_media_classes.join(",")
|
||||
: undefined,
|
||||
filter_media_type: query.filter_media_type
|
||||
? query.filter_media_type.join(",")
|
||||
: undefined,
|
||||
filter_engine_categories: query.filter_engine_categories
|
||||
? query.filter_engine_categories.join(",")
|
||||
: undefined,
|
||||
};
|
||||
return await this.get<{
|
||||
success: boolean;
|
||||
results: MediaFile[];
|
||||
pagination: PaginationInfinite;
|
||||
}>({ endpoint, query: queryWithStrings })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.results,
|
||||
pagination: response.pagination,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async ListUserMediaFiles(
|
||||
query: ListUserMediaQuery
|
||||
): Promise<ApiResponse<MediaFile[], Pagination>> {
|
||||
const userName = query.username;
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list/user/${userName}`;
|
||||
const queryWithStrings = {
|
||||
...query,
|
||||
include_user_uploads: query.include_user_uploads,
|
||||
filter_media_classes: query.filter_media_classes
|
||||
? query.filter_media_classes.join(",")
|
||||
: undefined,
|
||||
filter_media_type: query.filter_media_type
|
||||
? query.filter_media_type.join(",")
|
||||
: undefined,
|
||||
filter_engine_categories: query.filter_engine_categories
|
||||
? query.filter_engine_categories.join(",")
|
||||
: undefined,
|
||||
};
|
||||
return await this.get<{
|
||||
success: boolean;
|
||||
results: MediaFile[];
|
||||
pagination?: Pagination;
|
||||
}>({ endpoint, query: queryWithStrings })
|
||||
.then((response) => {
|
||||
let results = response.results ?? [];
|
||||
if (query.user_uploads_only) {
|
||||
results = results.filter((file) => file.origin_category === "upload");
|
||||
}
|
||||
return {
|
||||
success: response.success,
|
||||
data: results,
|
||||
pagination: response.pagination,
|
||||
};
|
||||
})
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async SearchFeaturedMediaFiles(
|
||||
query: SearchFeaturedMediaQuery
|
||||
): Promise<ApiResponse<MediaFile[], Pagination>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/search_featured`;
|
||||
const queryWithStrings = {
|
||||
search_term: query.search_term,
|
||||
filter_media_classes: query.filter_media_classes
|
||||
? query.filter_media_classes.join(",")
|
||||
: undefined,
|
||||
filter_media_type: query.filter_media_type
|
||||
? query.filter_media_type.join(",")
|
||||
: undefined,
|
||||
filter_engine_categories: query.filter_engine_categories
|
||||
? query.filter_engine_categories.join(",")
|
||||
: undefined,
|
||||
};
|
||||
return await this.get<{
|
||||
success: boolean;
|
||||
results: MediaFile[];
|
||||
pagination: Pagination;
|
||||
}>({ endpoint, query: queryWithStrings })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.results,
|
||||
pagination: response.pagination,
|
||||
}))
|
||||
.catch((err) => ({
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
}));
|
||||
}
|
||||
|
||||
public async SearchUserMediaFiles(
|
||||
query: SearchFeaturedMediaQuery
|
||||
): Promise<ApiResponse<MediaFile[], Pagination>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/search_session`;
|
||||
const queryWithStrings = {
|
||||
search_term: query.search_term,
|
||||
filter_media_classes: query.filter_media_classes
|
||||
? query.filter_media_classes.join(",")
|
||||
: undefined,
|
||||
filter_media_type: query.filter_media_type
|
||||
? query.filter_media_type.join(",")
|
||||
: undefined,
|
||||
filter_engine_categories: query.filter_engine_categories
|
||||
? query.filter_engine_categories.join(",")
|
||||
: undefined,
|
||||
};
|
||||
return await this.get<{
|
||||
success: boolean;
|
||||
results: MediaFile[];
|
||||
pagination: Pagination;
|
||||
}>({ endpoint, query: queryWithStrings })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.results,
|
||||
pagination: response.pagination,
|
||||
}))
|
||||
.catch((err) => ({
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
}));
|
||||
}
|
||||
|
||||
public async RenameMediaFileByToken({
|
||||
mediaToken,
|
||||
name,
|
||||
}: {
|
||||
mediaToken: string;
|
||||
name: string;
|
||||
}): Promise<ApiResponse<undefined>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/rename/${mediaToken}`;
|
||||
const body = { name };
|
||||
|
||||
return await this.post<
|
||||
{ name: string },
|
||||
{
|
||||
success?: boolean;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public async UpdateCoverImage({
|
||||
mediaFileToken,
|
||||
imageToken,
|
||||
}: {
|
||||
mediaFileToken: string;
|
||||
imageToken: string;
|
||||
}): Promise<ApiResponse<undefined>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/cover_image/${mediaFileToken}`;
|
||||
return await this.post<
|
||||
{ cover_image_media_file_token: string },
|
||||
{
|
||||
success?: boolean;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body: { cover_image_media_file_token: imageToken } })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async UpdateVisibility({
|
||||
mediaFileToken,
|
||||
visibility,
|
||||
}: {
|
||||
mediaFileToken: string;
|
||||
visibility: Visibility;
|
||||
}): Promise<ApiResponse<undefined>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/visibility/${mediaFileToken}`;
|
||||
return await this.post<
|
||||
{ creator_set_visibility: string },
|
||||
{
|
||||
success?: boolean;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body: { creator_set_visibility: visibility } })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,341 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { FilterEngineCategories } from "./enums/QueryFilters.js";
|
||||
import { Visibility } from "./enums/Visibility.js";
|
||||
import { EIntermediateFile } from "./enums/EIntermediateFile.js";
|
||||
export class MediaUploadApi extends ApiManager {
|
||||
private sessionToken = "";
|
||||
|
||||
private async getSessionTokenForUploadStudioShot() {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/session_token`;
|
||||
return await this.get<{
|
||||
maybe_signed_session: string;
|
||||
}>({ endpoint })
|
||||
.then((response) => {
|
||||
return {
|
||||
success: true,
|
||||
data: response["maybe_signed_session"],
|
||||
};
|
||||
})
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async UploadStudioShot({
|
||||
maybe_title,
|
||||
uuid_idempotency_token,
|
||||
blob,
|
||||
fileName,
|
||||
maybe_visibility,
|
||||
}: {
|
||||
maybe_title?: string;
|
||||
uuid_idempotency_token: string;
|
||||
blob: Blob | null;
|
||||
fileName: string;
|
||||
maybe_visibility?: Visibility;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
// This function is a bit special it requires that
|
||||
const endpoint = `${this.ApiTargets.uploadApi}/v1/media_files/upload/studio_shot`;
|
||||
|
||||
if (!this.sessionToken) {
|
||||
console.log("Session Token");
|
||||
const response = await this.getSessionTokenForUploadStudioShot();
|
||||
if (response.success && response.data) {
|
||||
this.sessionToken = response.data;
|
||||
console.log(`Token ${this.sessionToken}`);
|
||||
} else {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: "Could not obtain session tokens.",
|
||||
};
|
||||
}
|
||||
} else {
|
||||
console.log(`Session Token: ${this.sessionToken}`);
|
||||
}
|
||||
|
||||
const options: Record<string, string | number | undefined> = {
|
||||
maybe_title,
|
||||
maybe_frame_rate_fps: 60,
|
||||
maybe_visibility: maybe_visibility?.toString(),
|
||||
};
|
||||
|
||||
const formRecord = Object.entries(options).reduce(
|
||||
(allOptions, [key, value]) => {
|
||||
if (value === undefined) {
|
||||
return allOptions;
|
||||
}
|
||||
return { ...allOptions, [key]: value.toString() };
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append("uuid_idempotency_token", uuid_idempotency_token);
|
||||
Object.entries(formRecord).forEach(([key, value]) => {
|
||||
formData.append(key, value);
|
||||
});
|
||||
if (blob && fileName) {
|
||||
formData.append("file", blob, fileName);
|
||||
} else if (blob) {
|
||||
formData.append("file", blob);
|
||||
}
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
Session: this.sessionToken,
|
||||
},
|
||||
credentials: "include",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.success && result.media_file_token) {
|
||||
return { success: true, data: result.media_file_token };
|
||||
} else {
|
||||
return { success: false, errorMessage: "Failed to Get Media Token" };
|
||||
}
|
||||
}
|
||||
|
||||
private async Upload({
|
||||
endpoint,
|
||||
uuid,
|
||||
blob,
|
||||
fileName,
|
||||
options,
|
||||
}: {
|
||||
endpoint: string;
|
||||
blob: Blob | File;
|
||||
fileName: string;
|
||||
uuid: string;
|
||||
options: Record<string, string | number | undefined>;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const formRecord = Object.entries(options).reduce(
|
||||
(allOptions, [key, value]) => {
|
||||
if (value === undefined) {
|
||||
return allOptions;
|
||||
}
|
||||
return { ...allOptions, [key]: value.toString() };
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
);
|
||||
|
||||
return await this.postForm<{
|
||||
success: boolean;
|
||||
media_file_token?: string;
|
||||
BadInput?: string;
|
||||
}>({ endpoint, formRecord, blob, blobFileName: fileName, uuid })
|
||||
.then((response) => ({
|
||||
success: Boolean(response.success ?? false),
|
||||
data: response.media_file_token,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async UploadAudio({
|
||||
blob,
|
||||
fileName,
|
||||
uuid,
|
||||
maybe_title,
|
||||
maybe_visibility = Visibility.Public,
|
||||
}: {
|
||||
blob: Blob;
|
||||
fileName: string;
|
||||
uuid: string;
|
||||
maybe_title?: string | undefined;
|
||||
maybe_visibility?: Visibility | undefined;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/audio`;
|
||||
const options: Record<string, string | number | undefined> = {
|
||||
maybe_title,
|
||||
maybe_visibility: maybe_visibility?.toString(),
|
||||
};
|
||||
return this.Upload({ endpoint, blob, fileName, uuid, options });
|
||||
}
|
||||
|
||||
public async UploadImage({
|
||||
blob,
|
||||
fileName,
|
||||
uuid,
|
||||
maybe_title,
|
||||
maybe_visibility = Visibility.Public,
|
||||
is_intermediate_system_file = EIntermediateFile.true
|
||||
}: {
|
||||
blob: Blob;
|
||||
fileName: string;
|
||||
uuid: string;
|
||||
maybe_title?: string | undefined;
|
||||
maybe_visibility?: Visibility | undefined;
|
||||
is_intermediate_system_file?: EIntermediateFile;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/image`;
|
||||
const options: Record<string, string | number | undefined> = {
|
||||
is_intermediate_system_file: EIntermediateFile[is_intermediate_system_file],
|
||||
maybe_title,
|
||||
maybe_visibility: maybe_visibility?.toString(),
|
||||
};
|
||||
return this.Upload({ endpoint, blob, fileName, uuid, options });
|
||||
}
|
||||
|
||||
public async UploadNewEngineAsset({
|
||||
file,
|
||||
fileName,
|
||||
uuid,
|
||||
engine_category,
|
||||
maybe_animation_type,
|
||||
maybe_duration_millis,
|
||||
maybe_title,
|
||||
maybe_visibility = Visibility.Public,
|
||||
}: {
|
||||
file: File;
|
||||
fileName: string;
|
||||
uuid: string;
|
||||
engine_category: FilterEngineCategories;
|
||||
maybe_animation_type?: string;
|
||||
maybe_duration_millis?: number;
|
||||
maybe_title?: string;
|
||||
maybe_visibility?: Visibility;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_engine_asset`;
|
||||
const options: Record<string, string | number | undefined> = {
|
||||
engine_category,
|
||||
maybe_title,
|
||||
maybe_visibility: maybe_visibility?.toString(),
|
||||
maybe_animation_type,
|
||||
maybe_duration_millis,
|
||||
};
|
||||
return this.Upload({ endpoint, blob: file, fileName, uuid, options });
|
||||
}
|
||||
|
||||
public async UploadNewScene({
|
||||
blob,
|
||||
fileName,
|
||||
uuid,
|
||||
maybe_title,
|
||||
maybe_visibility = Visibility.Public,
|
||||
}: {
|
||||
blob: Blob;
|
||||
fileName: string;
|
||||
uuid: string;
|
||||
maybe_title?: string;
|
||||
maybe_visibility?: Visibility;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_scene`;
|
||||
const options: Record<string, string | number | undefined> = {
|
||||
maybe_title,
|
||||
maybe_visibility: maybe_visibility?.toString(),
|
||||
};
|
||||
return this.Upload({ endpoint, blob, fileName, uuid, options });
|
||||
}
|
||||
|
||||
public async UploadNewVideo({
|
||||
blob,
|
||||
fileName,
|
||||
uuid,
|
||||
maybe_title,
|
||||
maybe_visibility = Visibility.Public,
|
||||
maybe_style_name,
|
||||
maybe_scene_source_media_file_token,
|
||||
}: {
|
||||
blob: Blob;
|
||||
fileName: string;
|
||||
uuid: string;
|
||||
maybe_title?: string;
|
||||
maybe_visibility?: Visibility;
|
||||
maybe_style_name?: string;
|
||||
maybe_scene_source_media_file_token?: string;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_video`;
|
||||
const options: Record<string, string | number | undefined> = {
|
||||
is_intermediate_system_file: "true",
|
||||
maybe_title,
|
||||
maybe_visibility: maybe_visibility?.toString(),
|
||||
maybe_style_name,
|
||||
maybe_scene_source_media_file_token,
|
||||
};
|
||||
return this.Upload({ endpoint, blob, fileName, uuid, options });
|
||||
}
|
||||
|
||||
public async UploadPmx({
|
||||
file,
|
||||
fileName,
|
||||
uuid,
|
||||
engine_category,
|
||||
maybe_animation_type,
|
||||
maybe_duration_millis,
|
||||
maybe_title,
|
||||
maybe_visibility = Visibility.Public,
|
||||
}: {
|
||||
file: File;
|
||||
fileName: string;
|
||||
uuid: string;
|
||||
engine_category?: string;
|
||||
maybe_animation_type?: string;
|
||||
maybe_duration_millis?: number;
|
||||
maybe_title?: string;
|
||||
maybe_visibility?: Visibility;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/pmx`;
|
||||
const options: Record<string, string | number | undefined> = {
|
||||
is_intermediate_system_file: "true",
|
||||
engine_category,
|
||||
maybe_animation_type,
|
||||
maybe_duration_millis,
|
||||
maybe_title,
|
||||
maybe_visibility,
|
||||
};
|
||||
return this.Upload({ endpoint, blob: file, fileName, uuid, options });
|
||||
}
|
||||
|
||||
public async UploadSavedScene({
|
||||
blob,
|
||||
fileName,
|
||||
uuid,
|
||||
mediaToken,
|
||||
}: {
|
||||
blob: Blob;
|
||||
fileName: string;
|
||||
uuid: string;
|
||||
mediaToken: string;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/saved_scene/${mediaToken}`;
|
||||
const options: Record<string, string | number | undefined> = {};
|
||||
return this.Upload({ endpoint, blob, fileName, uuid, options });
|
||||
}
|
||||
|
||||
// this is used to send the scene snapshot to the vst upload endpoint this creates a snapshot of the scene where in we can remix from the og.
|
||||
public async UploadSceneSnapshotMediaFileForm({
|
||||
blob,
|
||||
uuid,
|
||||
maybe_title, // title of the scene at the time
|
||||
maybe_scene_source_media_file_token, // original token that started it all
|
||||
}: {
|
||||
blob: Blob;
|
||||
uuid: string;
|
||||
maybe_title: string;
|
||||
maybe_scene_source_media_file_token: string | undefined;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/scene_snapshot`;
|
||||
|
||||
const options: Record<string, string | number | undefined> = {
|
||||
maybe_title: maybe_title,
|
||||
maybe_scene_source_media_file_token: maybe_scene_source_media_file_token,
|
||||
};
|
||||
|
||||
const fileName = `${maybe_title}-${uuid}`;
|
||||
return this.Upload({ endpoint, blob, fileName, uuid, options }); // token comes back and send it VST
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { StatusAlert } from "./models/StatusAlert.js";
|
||||
|
||||
export class MiscApi extends ApiManager {
|
||||
public GetStatusAlertCheck(): Promise<ApiResponse<StatusAlert>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/session`;
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
maybe_alert?: Omit<StatusAlert, "refresh_interval_millis">;
|
||||
refresh_interval_millis: number;
|
||||
}>({ endpoint: endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: {
|
||||
...response.maybe_alert,
|
||||
refresh_interval_millis: response.refresh_interval_millis,
|
||||
},
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.mesasge,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { Prompts } from "./models/Prompts.js";
|
||||
import { FetchProxy as fetch } from "@storyteller/tauri-utils";
|
||||
|
||||
export class PromptsApi extends ApiManager {
|
||||
public async enqueueImageGeneration({
|
||||
disableSystemPrompt,
|
||||
prompt,
|
||||
snapshotMediaToken,
|
||||
additionalImages,
|
||||
}: {
|
||||
disableSystemPrompt: boolean;
|
||||
prompt: string;
|
||||
snapshotMediaToken: string;
|
||||
additionalImages?: string[];
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/prompt`;
|
||||
|
||||
const uuidIdempotencyToken = crypto.randomUUID(); // Generate a new UUID
|
||||
const body = {
|
||||
uuid_idempotency_token: uuidIdempotencyToken,
|
||||
disable_system_prompt: disableSystemPrompt,
|
||||
prompt,
|
||||
snapshot_media_token: snapshotMediaToken, // Changed from scene_media_token to snapshot_media_token
|
||||
additional_images: additionalImages,
|
||||
};
|
||||
|
||||
const postResponse = await this.post<
|
||||
{
|
||||
uuid_idempotency_token: string;
|
||||
disable_system_prompt: boolean;
|
||||
prompt: string;
|
||||
snapshot_media_token: string;
|
||||
additional_images?: string[];
|
||||
},
|
||||
{ success?: boolean; job_token?: string; BadInput?: string }
|
||||
>({
|
||||
endpoint,
|
||||
body,
|
||||
});
|
||||
|
||||
// Check if the response is successful
|
||||
const isSuccess = postResponse.success ?? false;
|
||||
// Prepare the result object
|
||||
console.log("postResponse FOR ENQUEUE IMAGE GENERATION");
|
||||
console.log(postResponse);
|
||||
|
||||
const result = {
|
||||
success: isSuccess,
|
||||
data: isSuccess ? postResponse.job_token : undefined,
|
||||
errorMessage: isSuccess ? undefined : postResponse.BadInput,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async pollJobSession(
|
||||
jobToken: string,
|
||||
thumbnailWidth = 256
|
||||
): Promise<
|
||||
ApiResponse<{
|
||||
job_token: string;
|
||||
request: {
|
||||
maybe_model_title: string;
|
||||
};
|
||||
status: {
|
||||
status: string;
|
||||
progress_percentage: number;
|
||||
};
|
||||
result: {
|
||||
image_url: string;
|
||||
thumbnail_url: string;
|
||||
public_bucket_path: string;
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/job/${jobToken}`;
|
||||
|
||||
const response = await this.get<any>({
|
||||
endpoint,
|
||||
});
|
||||
console.log("Job Polling Response:");
|
||||
console.log(response);
|
||||
|
||||
const image_url = response.state.maybe_result?.media_links?.cdn_url;
|
||||
const public_bucket_path =
|
||||
response.state.maybe_result?.maybe_public_bucket_media_path;
|
||||
|
||||
const thumbnail_url =
|
||||
response.state.maybe_result?.media_links?.maybe_thumbnail_template?.replace(
|
||||
"{WIDTH}",
|
||||
thumbnailWidth.toString()
|
||||
);
|
||||
|
||||
const progress_percentage = response.state.status.progress_percentage;
|
||||
const status_string = response.state.status.status;
|
||||
|
||||
console.log("Image URL:", image_url);
|
||||
console.log("Thumbnail URL:", thumbnail_url);
|
||||
console.log("Progress Percentage:", progress_percentage);
|
||||
console.log("Status", status_string);
|
||||
|
||||
console.log("response FROM JOBS");
|
||||
console.log(response);
|
||||
|
||||
const success = response.success ?? false;
|
||||
const status = response.status ?? "";
|
||||
const errorMessage = response.BadInput;
|
||||
|
||||
return {
|
||||
success,
|
||||
data: {
|
||||
result: {
|
||||
image_url: image_url || "",
|
||||
thumbnail_url: thumbnail_url || "",
|
||||
public_bucket_path: public_bucket_path || "",
|
||||
error: undefined,
|
||||
},
|
||||
job_token: jobToken,
|
||||
request: {
|
||||
maybe_model_title: "Image Generation",
|
||||
},
|
||||
status: {
|
||||
status: status_string.toLowerCase(),
|
||||
progress_percentage: progress_percentage,
|
||||
},
|
||||
},
|
||||
errorMessage,
|
||||
};
|
||||
}
|
||||
|
||||
public async pollStudioSessionJobs(jobToken: string): Promise<
|
||||
ApiResponse<{
|
||||
status: string;
|
||||
result: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/session_jobs/${jobToken}`;
|
||||
|
||||
const response = await this.get<{
|
||||
success?: boolean;
|
||||
status?: string;
|
||||
result?: {
|
||||
generated_images?: string[];
|
||||
error?: string;
|
||||
};
|
||||
BadInput?: string;
|
||||
}>({
|
||||
endpoint,
|
||||
});
|
||||
|
||||
const success = response.success ?? false;
|
||||
const status = response.status ?? "";
|
||||
const result = response.result ?? {
|
||||
generated_images: [],
|
||||
error: undefined,
|
||||
};
|
||||
const errorMessage = response.BadInput;
|
||||
|
||||
return {
|
||||
success,
|
||||
data: { status, result },
|
||||
errorMessage,
|
||||
};
|
||||
}
|
||||
|
||||
public GetPromptsByToken({
|
||||
token,
|
||||
}: {
|
||||
token: string;
|
||||
}): Promise<ApiResponse<Prompts>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/prompts/${token}`;
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
prompt: Prompts;
|
||||
error_reason?: string;
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: response.prompt,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public async uploadSceneSnapshot({
|
||||
screenshot,
|
||||
sceneMediaToken,
|
||||
}: {
|
||||
screenshot: File; // base64 encoded PNG
|
||||
sceneMediaToken?: string;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/scene_snapshot`;
|
||||
const formData = new FormData();
|
||||
formData.append("snapshot", screenshot); // Changed from "screenshot" to "snapshot" to match API spec
|
||||
if (sceneMediaToken) {
|
||||
formData.append("scene_media_token", sceneMediaToken);
|
||||
}
|
||||
|
||||
const uuidIdempotencyToken = crypto.randomUUID();
|
||||
formData.append("uuid_idempotency_token", uuidIdempotencyToken);
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const postResponse = await response.json();
|
||||
|
||||
console.log(postResponse);
|
||||
|
||||
let result: { success: boolean; data?: string; errorMessage?: string };
|
||||
|
||||
if (postResponse.success) {
|
||||
result = {
|
||||
success: true,
|
||||
data: postResponse.snapshot_media_token,
|
||||
errorMessage: undefined,
|
||||
};
|
||||
} else {
|
||||
result = {
|
||||
success: false,
|
||||
errorMessage: "Failed to generate snapshot.",
|
||||
};
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { ApiManager } from "./ApiManager.js";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
export interface Coordinates {
|
||||
coordinates: [number, number];
|
||||
include: boolean;
|
||||
}
|
||||
|
||||
export interface ObjectData {
|
||||
style: {
|
||||
color: SegmentationColor;
|
||||
};
|
||||
object_id: number;
|
||||
points: Coordinates[];
|
||||
}
|
||||
|
||||
export type SegmentationColor = [number, number, number];
|
||||
|
||||
export interface RequestFrame {
|
||||
timestamp: number;
|
||||
objects: ObjectData[];
|
||||
}
|
||||
export interface ResponseFrame {
|
||||
b64_image_data: number;
|
||||
idx: number;
|
||||
timestamp: number;
|
||||
objects: ObjectData[];
|
||||
preview_image_url: string;
|
||||
}
|
||||
|
||||
export interface SegmentationRequest {
|
||||
session_id: string;
|
||||
fps: number;
|
||||
frames: RequestFrame[];
|
||||
propagate: boolean;
|
||||
}
|
||||
|
||||
export interface SegmentationResponse {
|
||||
session_id: string;
|
||||
fps: number;
|
||||
masked_video_cdn_url: string;
|
||||
frames: ResponseFrame[];
|
||||
propagate: boolean;
|
||||
}
|
||||
|
||||
export class SegmentationApi extends ApiManager {
|
||||
// returns uuid
|
||||
public async createSession(
|
||||
blobVideo: File | Blob,
|
||||
): Promise<{ session_id: string }> {
|
||||
const endpoint = `https://hax.storyteller.ai/segmentation/new_session`;
|
||||
const id = uuidv4().toString();
|
||||
return this.postFormVideo<{ session_id: "fix-mimetype" }>({
|
||||
endpoint: endpoint,
|
||||
formRecord: {
|
||||
session_id: "fix-mimetype",
|
||||
},
|
||||
uuid: id,
|
||||
blobFileName: id,
|
||||
blob: blobVideo,
|
||||
});
|
||||
}
|
||||
|
||||
public addPointsToSession(
|
||||
session_id: string,
|
||||
fps: number,
|
||||
frames: RequestFrame[],
|
||||
propagate: boolean,
|
||||
): Promise<SegmentationResponse> {
|
||||
const endpoint = `https://hax.storyteller.ai/segmentation/generate_masks`;
|
||||
|
||||
const segmentationRequest: SegmentationRequest = {
|
||||
session_id: session_id,
|
||||
fps: fps,
|
||||
frames: frames,
|
||||
propagate: propagate,
|
||||
};
|
||||
|
||||
return this.post<SegmentationRequest, SegmentationResponse>({
|
||||
endpoint: endpoint,
|
||||
body: segmentationRequest,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { GenerateTtsAudioErrorType } from "./enums/Tts.js";
|
||||
import { Visibility } from "./enums/Visibility.js";
|
||||
|
||||
export interface GenerateTtsAudioRequest {
|
||||
creator_set_visibility?: Visibility;
|
||||
uuid_idempotency_token: string;
|
||||
tts_model_token: string;
|
||||
inference_text: string;
|
||||
is_storyteller_demo?: boolean;
|
||||
}
|
||||
|
||||
export interface GenerateTtsAudioResponse {
|
||||
success?: boolean;
|
||||
inference_job_token?: string;
|
||||
inference_job_token_type?: string;
|
||||
BadInput?: string;
|
||||
}
|
||||
|
||||
export class TtsApi extends ApiManager {
|
||||
public async GenerateTtsAudio(request: GenerateTtsAudioRequest): Promise<
|
||||
ApiResponse<{
|
||||
inference_job_token?: string;
|
||||
inference_job_token_type?: string;
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/tts/inference`;
|
||||
|
||||
const body = {
|
||||
...request,
|
||||
...(request.creator_set_visibility
|
||||
? {}
|
||||
: { creator_set_visibility: Visibility.Public }),
|
||||
};
|
||||
|
||||
return this.post<GenerateTtsAudioRequest, GenerateTtsAudioResponse>({
|
||||
endpoint,
|
||||
body: body,
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.success) {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: response.BadInput,
|
||||
data: {},
|
||||
};
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
inference_job_token: response.inference_job_token,
|
||||
inference_job_token_type: response.inference_job_token_type,
|
||||
},
|
||||
};
|
||||
})
|
||||
.catch(() => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: GenerateTtsAudioErrorType.UnknownError,
|
||||
data: {},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import {
|
||||
UserBookmarkBatch,
|
||||
UserBookmarkByEntity,
|
||||
UserBookmarkByUser,
|
||||
} from "./models/UserBookmark.js";
|
||||
import { Pagination } from "./models/Pagination.js";
|
||||
|
||||
export enum ScopedEntityTypes {
|
||||
USER = "user",
|
||||
TTS_MODEL = "tts-model",
|
||||
TTS_RESULT = "tts-result",
|
||||
W2L_TEMPLATE = "w2l-template",
|
||||
W2L_RESULT = "w2l-result",
|
||||
MEDIA_FILE = "media_file",
|
||||
MODEL_WEIGHT = "model_weight",
|
||||
VOICE_CONVERSION_MODEL = "voice_conversion_model",
|
||||
ZS_VOICE = "z_voice",
|
||||
}
|
||||
|
||||
export enum ScopedWeightTypes {
|
||||
HIFIGAN_TTl2 = "hifigan_tt2",
|
||||
RVC_V2 = "rvc_v2",
|
||||
SD_1_5 = "sd_1.5",
|
||||
SDXL = "sdxl",
|
||||
SO_VITS_SVC = "so_vits_svc",
|
||||
TT2 = "tt2",
|
||||
LORA = "loRA",
|
||||
VALL_E = "vall_e",
|
||||
COMFY_UI = "comfy_ui",
|
||||
}
|
||||
|
||||
export enum ScopedMediaFileType {
|
||||
IMAGE_GENERATION = "image_generation",
|
||||
TEXT_TO_SPEECH = "text_to_speech",
|
||||
VOCODER = "vocoder",
|
||||
VOICE_CONVERSION = "voice_conversion",
|
||||
WORKFLOW_CONFIG = "workflow_config",
|
||||
}
|
||||
|
||||
interface ListUserBookmarksByUserRequest {
|
||||
username: string;
|
||||
sort_ascending?: boolean;
|
||||
page_size?: number;
|
||||
page_index?: number;
|
||||
maybe_scoped_entity_type?: ScopedEntityTypes[];
|
||||
maybe_scoped_weight_type?: ScopedWeightTypes[];
|
||||
maybe_scoped_media_file_type?: ScopedMediaFileType[];
|
||||
}
|
||||
|
||||
export class UserBookmarksApi extends ApiManager {
|
||||
public CreateUserBookmark({
|
||||
entityToken,
|
||||
entityType,
|
||||
}: {
|
||||
entityToken: string;
|
||||
entityType: string;
|
||||
}): Promise<
|
||||
ApiResponse<{
|
||||
new_bookmark_count_for_entity?: number;
|
||||
user_bookmark_token?: string;
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/create`;
|
||||
const body = {
|
||||
entity_token: entityToken,
|
||||
entity_type: entityType,
|
||||
};
|
||||
|
||||
return this.post<
|
||||
{
|
||||
entity_token: string;
|
||||
entity_type: string;
|
||||
},
|
||||
{
|
||||
success?: boolean;
|
||||
new_bookmark_count_for_entity?: number;
|
||||
user_bookmark_token: string;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
data: {
|
||||
new_bookmark_count_for_entity: response.new_bookmark_count_for_entity,
|
||||
user_bookmark_token: response.user_bookmark_token,
|
||||
},
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public DeleteUserBookmark({
|
||||
entityToken,
|
||||
}: {
|
||||
entityToken: string;
|
||||
}): Promise<ApiResponse<undefined>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/delete/${entityToken}`;
|
||||
|
||||
return this.delete<
|
||||
{ as_mod: boolean },
|
||||
{
|
||||
success?: boolean;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body: { as_mod: true } })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListUserBookmarks(): Promise<ApiResponse<UserBookmarkBatch[]>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/batch`;
|
||||
|
||||
return this.get<{
|
||||
success?: boolean;
|
||||
bookmarks?: UserBookmarkBatch[];
|
||||
BadInput?: string;
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
data: response.bookmarks,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListUserBookmarksByUser({
|
||||
username,
|
||||
sort_ascending,
|
||||
page_size,
|
||||
page_index,
|
||||
maybe_scoped_entity_type,
|
||||
maybe_scoped_weight_type,
|
||||
maybe_scoped_media_file_type,
|
||||
}: ListUserBookmarksByUserRequest): Promise<
|
||||
ApiResponse<UserBookmarkByUser[], Pagination>
|
||||
> {
|
||||
const user = username;
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/list/${user}`;
|
||||
|
||||
const query = {
|
||||
sort_ascending,
|
||||
page_size,
|
||||
page_index,
|
||||
maybe_scoped_entity_type: maybe_scoped_entity_type
|
||||
? maybe_scoped_entity_type.join(",")
|
||||
: undefined,
|
||||
maybe_scoped_weight_type: maybe_scoped_weight_type
|
||||
? maybe_scoped_weight_type.join(",")
|
||||
: undefined,
|
||||
maybe_scoped_media_file_type: maybe_scoped_media_file_type
|
||||
? maybe_scoped_media_file_type.join(",")
|
||||
: undefined,
|
||||
};
|
||||
|
||||
return this.get<{
|
||||
success?: boolean;
|
||||
pagination?: Pagination;
|
||||
results: UserBookmarkByUser[];
|
||||
}>({ endpoint, query })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
data: response.results,
|
||||
pagination: response.pagination,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListUserBookmarksByEntity({
|
||||
entityType,
|
||||
entityToken,
|
||||
}: {
|
||||
entityType: string;
|
||||
entityToken: string;
|
||||
}): Promise<ApiResponse<UserBookmarkByEntity[]>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/list/${entityType}/${entityToken}`;
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
user_bookmarks: UserBookmarkByEntity[];
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.user_bookmarks,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
|
||||
export interface UserRating {
|
||||
entity_token: string;
|
||||
entity_type: string;
|
||||
rating_value: string;
|
||||
}
|
||||
|
||||
export class UserRatingApi extends ApiManager {
|
||||
public ListUserRatings(): Promise<ApiResponse<UserRating[]>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/batch`;
|
||||
|
||||
return this.get<{
|
||||
success?: boolean;
|
||||
ratings?: UserRating[];
|
||||
BadInput?: string;
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
data: response.ratings,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public PostUserRating({
|
||||
entityToken,
|
||||
entityType,
|
||||
ratingValue,
|
||||
}: {
|
||||
entityToken: string;
|
||||
entityType: string;
|
||||
ratingValue: string;
|
||||
}): Promise<ApiResponse<number>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/rate`;
|
||||
|
||||
const body = {
|
||||
entity_token: entityToken,
|
||||
entity_type: entityType,
|
||||
rating_value: ratingValue,
|
||||
};
|
||||
|
||||
return this.post<
|
||||
{
|
||||
entity_token: string;
|
||||
entity_type: string;
|
||||
rating_value: string;
|
||||
},
|
||||
{
|
||||
success?: boolean;
|
||||
new_positive_rating_count_for_entity?: number;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
data: response.new_positive_rating_count_for_entity,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListUserRatingByEntity({
|
||||
entityType,
|
||||
entityToken,
|
||||
}: {
|
||||
entityType: string;
|
||||
entityToken: string;
|
||||
}): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/view/${entityType}/${entityToken}`;
|
||||
|
||||
return this.get<{
|
||||
success?: boolean;
|
||||
maybe_rating_value?: string;
|
||||
BadInput?: string;
|
||||
}>({ endpoint })
|
||||
.then((response) => {
|
||||
return {
|
||||
success: response.success ?? false,
|
||||
data: response.maybe_rating_value,
|
||||
errorMessage: response.BadInput,
|
||||
};
|
||||
})
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { UserInfo } from "./models/Users.js";
|
||||
import { FetchProxy as fetch } from "@storyteller/tauri-utils";
|
||||
|
||||
interface SignupRequest {
|
||||
username: string;
|
||||
email_address: string;
|
||||
password: string;
|
||||
password_confirmation: string;
|
||||
signup_source?: string;
|
||||
};
|
||||
|
||||
export class UsersApi extends ApiManager {
|
||||
private async authFetch<B, T>(
|
||||
endpoint: string,
|
||||
{
|
||||
method,
|
||||
body,
|
||||
}: {
|
||||
method: string;
|
||||
body?: B;
|
||||
}
|
||||
): Promise<T> {
|
||||
const bodyInString = JSON.stringify(body);
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method,
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
body: bodyInString,
|
||||
});
|
||||
|
||||
const responseData = await response.json();
|
||||
return responseData as T;
|
||||
}
|
||||
|
||||
public GetSession(): Promise<
|
||||
ApiResponse<{
|
||||
loggedIn: boolean;
|
||||
user?: UserInfo;
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/session`;
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
logged_in: boolean;
|
||||
user?: UserInfo;
|
||||
error_message?: string;
|
||||
}>({ endpoint: endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: {
|
||||
loggedIn: response.logged_in,
|
||||
user: response.user,
|
||||
},
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public GetUserProfile(username: string): Promise<
|
||||
ApiResponse<{
|
||||
user?: UserInfo;
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/user/${username}/profile`;
|
||||
console.log("endpoint", endpoint);
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
user?: UserInfo;
|
||||
error_message?: string;
|
||||
}>({ endpoint: endpoint })
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
data: {
|
||||
user: response.user,
|
||||
},
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async Login({
|
||||
usernameOrEmail,
|
||||
password,
|
||||
}: {
|
||||
usernameOrEmail: string;
|
||||
password: string;
|
||||
}): Promise<ApiResponse<{ signedSession?: string }>> {
|
||||
console.log("libs/api - Logging in with usernameOrEmail:", usernameOrEmail);
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/login`;
|
||||
console.log("libs/api - Login endpoint", endpoint);
|
||||
const body = {
|
||||
username_or_email: usernameOrEmail,
|
||||
password: password,
|
||||
};
|
||||
|
||||
try {
|
||||
const response = await this.authFetch<
|
||||
{ username_or_email: string; password: string },
|
||||
{
|
||||
success: boolean;
|
||||
signed_session?: string;
|
||||
error_message?: string;
|
||||
error_type?: string;
|
||||
}
|
||||
>(endpoint, {
|
||||
method: "POST",
|
||||
body: body,
|
||||
});
|
||||
return {
|
||||
success: response.success,
|
||||
data: response.success
|
||||
? { signedSession: response.signed_session }
|
||||
: undefined,
|
||||
errorMessage: response.error_message,
|
||||
};
|
||||
} catch (err: any) {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public Logout(): Promise<ApiResponse<null>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/logout`;
|
||||
return this.post<null, { success: boolean; error_message?: string }>({
|
||||
endpoint: endpoint,
|
||||
})
|
||||
.then((response) => ({
|
||||
success: response.success,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async Signup({
|
||||
username,
|
||||
email,
|
||||
password,
|
||||
passwordConfirmation,
|
||||
signupSource,
|
||||
}: {
|
||||
username: string;
|
||||
email: string;
|
||||
password: string;
|
||||
passwordConfirmation: string;
|
||||
signupSource?: string;
|
||||
}): Promise<ApiResponse<{ signedSession?: string }>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/create_account`;
|
||||
const body : SignupRequest = {
|
||||
email_address: email,
|
||||
password,
|
||||
password_confirmation: passwordConfirmation,
|
||||
username,
|
||||
};
|
||||
if (!!signupSource) {
|
||||
body.signup_source = signupSource;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.authFetch<
|
||||
SignupRequest,
|
||||
{
|
||||
success: boolean;
|
||||
signed_session?: string;
|
||||
error_fields?: Record<string, string>;
|
||||
error_message?: string;
|
||||
error_type?: string;
|
||||
}
|
||||
>(endpoint, {
|
||||
method: "POST",
|
||||
body: body,
|
||||
});
|
||||
|
||||
return {
|
||||
success: response.success,
|
||||
data: response.success
|
||||
? { signedSession: response.signed_session }
|
||||
: undefined,
|
||||
errorMessage:
|
||||
response.error_message ||
|
||||
Object.values(response.error_fields ?? {}).join(", "),
|
||||
};
|
||||
} catch (err: any) {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(window as any).UsersApi = new UsersApi();
|
||||
@@ -0,0 +1,70 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { Visibility } from "./enums/Visibility.js";
|
||||
|
||||
interface GenerateVideoStyleTransferRequest {
|
||||
creator_set_visibility: string;
|
||||
disable_lcm: boolean;
|
||||
enable_lipsync: boolean;
|
||||
frame_skip: number;
|
||||
global_ipa_media_token: string;
|
||||
input_depth_file: string;
|
||||
input_file: string;
|
||||
input_normal_file: string;
|
||||
input_outline_file: string;
|
||||
negative_prompt: string;
|
||||
prompt: string;
|
||||
remove_watermark: boolean;
|
||||
style: string;
|
||||
travel_prompt: string;
|
||||
trim_end_millis: number;
|
||||
trim_start_millis: number;
|
||||
use_cinematic: boolean;
|
||||
use_face_detailer: boolean;
|
||||
use_strength: number;
|
||||
use_upscaler: boolean;
|
||||
uuid_idempotency_token: string;
|
||||
}
|
||||
|
||||
export class VideoApi extends ApiManager {
|
||||
public async EnqueueStudio({
|
||||
enqueueVideo,
|
||||
}: {
|
||||
enqueueVideo: GenerateVideoStyleTransferRequest;
|
||||
}): Promise<
|
||||
ApiResponse<{
|
||||
inference_job_token?: string;
|
||||
inference_job_token_type?: string;
|
||||
}>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/workflows/enqueue_studio`;
|
||||
|
||||
const body = {
|
||||
...enqueueVideo,
|
||||
...(enqueueVideo.creator_set_visibility
|
||||
? {}
|
||||
: { creator_set_visibility: Visibility.Public }),
|
||||
};
|
||||
|
||||
return await this.post<
|
||||
GenerateVideoStyleTransferRequest,
|
||||
{
|
||||
success?: boolean;
|
||||
inference_job_token?: string;
|
||||
inference_job_token_type?: string;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body: body })
|
||||
.then((response) => ({
|
||||
success: Boolean(response.success ?? false),
|
||||
data: {
|
||||
inference_job_token: response.inference_job_token,
|
||||
inference_job_token_type: response.inference_job_token_type,
|
||||
},
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
console.log(err.message);
|
||||
return { success: false, error_reason: err.message };
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
|
||||
interface VoiceConversionParams {
|
||||
autoPredictF0?: boolean;
|
||||
creatorSetVisibility?: string;
|
||||
isStorytellerDemo?: boolean;
|
||||
overrideF0Method?: string;
|
||||
sourceMediaUploadToken: string;
|
||||
transpose?: number;
|
||||
uuidIdempotencyToken: string;
|
||||
voiceConversionModelToken: string;
|
||||
}
|
||||
|
||||
interface VoiceConversionRequest {
|
||||
auto_predict_f0: boolean;
|
||||
creator_set_visibility: string;
|
||||
is_storyteller_demo: boolean;
|
||||
override_f0_method: string;
|
||||
source_media_upload_token: string;
|
||||
transpose: number;
|
||||
uuid_idempotency_token: string;
|
||||
voice_conversion_model_token: string;
|
||||
}
|
||||
|
||||
export class VoiceConversionApi extends ApiManager {
|
||||
public ConvertVoice(
|
||||
params: VoiceConversionParams,
|
||||
): Promise<ApiResponse<string>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_conversion/inference`;
|
||||
|
||||
const body = this.parseBodyValues<
|
||||
VoiceConversionParams,
|
||||
VoiceConversionRequest
|
||||
>(params);
|
||||
|
||||
return this.post<
|
||||
VoiceConversionRequest,
|
||||
{
|
||||
success?: boolean;
|
||||
inference_job_token?: string;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
data: response.inference_job_token,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { Pagination } from "./models/Pagination.js";
|
||||
import { ZsDataset } from "./models/Dataset.js";
|
||||
|
||||
interface VoiceDesignerParams {
|
||||
text: string;
|
||||
uuidIdempotencyToken: string;
|
||||
voiceToken: string;
|
||||
}
|
||||
|
||||
interface VoiceDesignerRequest {
|
||||
text: string;
|
||||
uuid_idempotency_token: string;
|
||||
voice_token: string;
|
||||
}
|
||||
|
||||
export class VoiceDesignerApi extends ApiManager {
|
||||
public EnqueueTts(
|
||||
params: VoiceDesignerParams,
|
||||
): Promise<
|
||||
ApiResponse<{ inference_job_token?: string; voice_token?: string }>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_designer/enqueue_tts`;
|
||||
|
||||
const body = this.parseBodyValues<
|
||||
VoiceDesignerParams,
|
||||
VoiceDesignerRequest
|
||||
>(params);
|
||||
|
||||
return this.post<
|
||||
VoiceDesignerRequest,
|
||||
{
|
||||
success?: boolean;
|
||||
inference_job_token?: string;
|
||||
voice_token: string;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
...(response.success
|
||||
? {
|
||||
data: {
|
||||
inference_job_token: response.inference_job_token,
|
||||
voice_token: response.voice_token,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListDatasetsByUser({
|
||||
username,
|
||||
}: {
|
||||
username: string;
|
||||
}): Promise<ApiResponse<ZsDataset[]>> {
|
||||
const user = username;
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_designer/user/${user}/list`;
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
datasets: ZsDataset[];
|
||||
pagination: Pagination;
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.datasets,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
import { ApiManager, ApiResponse } from "./ApiManager.js";
|
||||
import { Weight } from "./models/Weight.js";
|
||||
import { Pagination, PaginationInfinite } from "./models/Pagination.js";
|
||||
import {
|
||||
FilterEngineCategories,
|
||||
FilterMediaClasses,
|
||||
FilterMediaType,
|
||||
} from "./enums/QueryFilters.js";
|
||||
import { Visibility } from "./enums/Visibility.js";
|
||||
|
||||
export enum ScopedWeightType {
|
||||
HIFIGAN_TT2 = "hifigan_tt2",
|
||||
RVC_V2 = "rvc_v2",
|
||||
SD_1_5 = "sd_1.5",
|
||||
SDXL = "sdxl",
|
||||
SO_VITS_SVC = "so_vits_svc",
|
||||
TT2 = "tt2",
|
||||
LORA = "loRA",
|
||||
VALL_E = "vall_e",
|
||||
COMFY_UI = "comfy_ui",
|
||||
}
|
||||
export enum ScopedWeightCategory {
|
||||
IMAGE_GENERATION = "image_generation",
|
||||
TEXT_TO_SPEECH = "text_to_speech",
|
||||
VOCODER = "vocoder",
|
||||
VOICE_CONVERSION = "voice_conversion",
|
||||
WORKFLOW_CONFIG = "workflow_config",
|
||||
}
|
||||
|
||||
interface WeightsRequest {
|
||||
pageSize?: number;
|
||||
weightType?: ScopedWeightType[];
|
||||
weightCategory?: ScopedWeightCategory[];
|
||||
//TODO: what is scoped??
|
||||
scopedWeightType?: ScopedWeightType[];
|
||||
scopedWeightCategory?: ScopedWeightCategory[];
|
||||
}
|
||||
|
||||
export interface ListWeightsByUserRequest extends WeightsRequest {
|
||||
username: string;
|
||||
pageIndex?: number;
|
||||
sortAscending?: boolean;
|
||||
}
|
||||
|
||||
export interface ListWeightsRequest extends WeightsRequest {
|
||||
cursor?: string;
|
||||
cursorIsReversed?: boolean;
|
||||
}
|
||||
|
||||
export interface ListFeaturedWeightsRequest {
|
||||
sortAscending?: boolean;
|
||||
pageSize?: number;
|
||||
cursor?: string;
|
||||
cursorIsReversed?: boolean;
|
||||
filterMediaClasses?: FilterMediaClasses[];
|
||||
filterMediaType?: FilterMediaType[];
|
||||
filterEngineCategories?: FilterEngineCategories[];
|
||||
}
|
||||
|
||||
export interface SearchWeightParams {
|
||||
ietfLanguageSubtag: string;
|
||||
searchTerm: string;
|
||||
weightCategory: ScopedWeightCategory;
|
||||
weightType: ScopedWeightType;
|
||||
}
|
||||
|
||||
export interface SearchWeightRequest {
|
||||
ietf_language_subtag: string;
|
||||
search_term: string;
|
||||
weight_category: string;
|
||||
weight_type: string;
|
||||
}
|
||||
|
||||
interface GetWeightByTokenResponse extends Weight {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateWeightByTokenParams {
|
||||
weightToken: string;
|
||||
coverImageMediaFileToken: string;
|
||||
descriptionMarkdown: string;
|
||||
title: string;
|
||||
visibility: Visibility;
|
||||
}
|
||||
export interface UpdateWeightByTokenRequest {
|
||||
cover_image_media_file_token: string;
|
||||
description_markdown: string;
|
||||
title: string;
|
||||
visibility: Visibility;
|
||||
}
|
||||
|
||||
export class WeightsApi extends ApiManager {
|
||||
public ListWeightsByUser({
|
||||
username,
|
||||
...params
|
||||
}: ListWeightsByUserRequest): Promise<ApiResponse<Weight[], Pagination>> {
|
||||
const user = username;
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/by_user/${user}`;
|
||||
|
||||
const query = this.parseQueryValues(params);
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
results: Weight[];
|
||||
pagination: Pagination;
|
||||
}>({ endpoint, query })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.results,
|
||||
pagination: response.pagination,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListWeights({
|
||||
...params
|
||||
}: ListWeightsRequest): Promise<ApiResponse<Weight[], PaginationInfinite>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list`;
|
||||
|
||||
const query = this.parseQueryValues(params);
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
results: Weight[];
|
||||
pagination: PaginationInfinite;
|
||||
}>({ endpoint, query })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.results,
|
||||
pagination: response.pagination,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListWeightsFeatured({
|
||||
...params
|
||||
}: ListFeaturedWeightsRequest): Promise<
|
||||
ApiResponse<Weight[], PaginationInfinite>
|
||||
> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list_featured`;
|
||||
|
||||
const query = this.parseQueryValues(params);
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
results: Weight[];
|
||||
pagination: PaginationInfinite;
|
||||
}>({ endpoint, query })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.results,
|
||||
pagination: response.pagination,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public ListWeightsPinned(): Promise<ApiResponse<Weight[]>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list_pinned`;
|
||||
|
||||
return this.get<{
|
||||
success: boolean;
|
||||
results: Weight[];
|
||||
}>({ endpoint })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.results,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public SearchWeights(
|
||||
params: SearchWeightParams,
|
||||
): Promise<ApiResponse<Weight[]>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/search`;
|
||||
|
||||
const body = this.parseBodyValues<SearchWeightParams, SearchWeightRequest>(
|
||||
params,
|
||||
);
|
||||
|
||||
return this.post<
|
||||
SearchWeightRequest,
|
||||
{
|
||||
success: boolean;
|
||||
weights: Weight[];
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: true,
|
||||
data: response.weights,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public GetWeightByToken({
|
||||
weightToken,
|
||||
}: {
|
||||
weightToken: string;
|
||||
}): Promise<ApiResponse<Weight>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
|
||||
|
||||
return this.get<GetWeightByTokenResponse>({ endpoint })
|
||||
.then(({ success, ...mediaFile }) => ({
|
||||
success: success,
|
||||
data: mediaFile,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public UpdateWeightByToken({
|
||||
weightToken,
|
||||
...params
|
||||
}: UpdateWeightByTokenParams): Promise<ApiResponse<undefined>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
|
||||
|
||||
const body = this.parseBodyValues<
|
||||
Omit<UpdateWeightByTokenParams, "weightToken">,
|
||||
UpdateWeightByTokenRequest
|
||||
>(params);
|
||||
|
||||
return this.post<
|
||||
UpdateWeightByTokenRequest,
|
||||
{ success?: boolean; BadInput?: string }
|
||||
>({ endpoint, body })
|
||||
.then(({ success, BadInput }) => ({
|
||||
success: success ?? false,
|
||||
errorMessage: BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public DeleteWeightByToken({
|
||||
weightToken,
|
||||
}: {
|
||||
weightToken: string;
|
||||
}): Promise<ApiResponse<undefined>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
|
||||
|
||||
const body = {
|
||||
as_mod: true,
|
||||
set_delete: true,
|
||||
};
|
||||
|
||||
return this.delete<
|
||||
{ as_mod: boolean; set_delete: boolean },
|
||||
{ success?: boolean; BadInput?: string }
|
||||
>({ endpoint, body })
|
||||
.then(({ success, BadInput }) => ({
|
||||
success: success ?? false,
|
||||
errorMessage: BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
|
||||
public UpdateWeightCoverImageByToken({
|
||||
weightToken,
|
||||
coverImageMediaFileToken,
|
||||
}: {
|
||||
weightToken: string;
|
||||
coverImageMediaFileToken: string;
|
||||
}): Promise<ApiResponse<undefined>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/${weightToken}/cover_image`;
|
||||
|
||||
const body = {
|
||||
cover_image_media_file_token: coverImageMediaFileToken,
|
||||
};
|
||||
|
||||
return this.post<
|
||||
{ cover_image_media_file_token: string },
|
||||
{ success?: boolean; BadInput?: string }
|
||||
>({ endpoint, body })
|
||||
.then(({ success, BadInput }) => ({
|
||||
success: success ?? false,
|
||||
errorMessage: BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return { success: false, errorMessage: err.message };
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Artcraft / Storyteller API backend
|
||||
const DEFAULT_API_HOST = "https://api.storyteller.ai";
|
||||
|
||||
// NB(bt,2025-09-25): 'nx' is creating multiple copies of the library with name
|
||||
// mangling, so the singleton pattern fails to resolve to a single instance.
|
||||
(window as any).STORYTELLER_API_HOST_STORE = undefined;
|
||||
|
||||
export class StorytellerApiHostStore {
|
||||
// NB(bt,2025-09-25): 'nx' is creating multiple copies of the library with name
|
||||
// mangling, so the singleton pattern fails to resolve to a single instance.
|
||||
// private static instance: StorytellerApiHostStore;
|
||||
|
||||
/**
|
||||
* The scheme and host of the API.
|
||||
* This can optionally include a port, but no path components (including `/`).
|
||||
* eg. http://localhost:12345 or https://api.storyteller.ai
|
||||
*/
|
||||
private apiSchemeAndHost: string;
|
||||
|
||||
// NB(bt,2025-09-25): 'nx' is creating multiple copies of the library with name
|
||||
// mangling, so the singleton pattern fails to resolve to a single instance.
|
||||
// public static getInstance(): StorytellerApiHostStore {
|
||||
// if (StorytellerApiHostStore.instance !== undefined) {
|
||||
// return StorytellerApiHostStore.instance;
|
||||
// }
|
||||
// const instance = new StorytellerApiHostStore(DEFAULT_API_HOST);
|
||||
// StorytellerApiHostStore.instance = instance;
|
||||
// return instance;
|
||||
// }
|
||||
|
||||
public static getInstance(): StorytellerApiHostStore {
|
||||
if ((window as any).STORYTELLER_API_HOST_STORE !== undefined) {
|
||||
return (window as any).STORYTELLER_API_HOST_STORE;
|
||||
}
|
||||
const instance = new StorytellerApiHostStore(DEFAULT_API_HOST);
|
||||
(window as any).STORYTELLER_API_HOST_STORE = instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/** Get the API scheme and host. */
|
||||
public getApiSchemeAndHost(): string {
|
||||
console.debug("StorytellerApiHostStore.getApiSchemeAndHost()", this.apiSchemeAndHost, this.constructor.name);
|
||||
return this.apiSchemeAndHost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Externally update the API host.
|
||||
* This is used to sync with Tauri for enabling easier development.
|
||||
*/
|
||||
public setApiSchemeAndHost(apiSchemeAndHost: string) {
|
||||
console.debug("StorytellerApiHostStore.setApiSchemeAndHost()", apiSchemeAndHost, this.constructor.name);
|
||||
|
||||
// TODO(bt,2025-07-06): Actually parse URL.
|
||||
if (!apiSchemeAndHost.startsWith("http://") && !apiSchemeAndHost.startsWith("https://")) {
|
||||
throw new Error(`Scheme not included in URL: ${apiSchemeAndHost}`);
|
||||
}
|
||||
|
||||
const FINAL_VALID_SLASH = "https://".lastIndexOf("/");
|
||||
if (apiSchemeAndHost.lastIndexOf("/") > FINAL_VALID_SLASH) {
|
||||
throw new Error(`Path components should not be included in URL: ${apiSchemeAndHost}`);
|
||||
}
|
||||
|
||||
this.apiSchemeAndHost = apiSchemeAndHost;
|
||||
}
|
||||
|
||||
private constructor(apiSchemeAndHost: string) {
|
||||
this.apiSchemeAndHost = apiSchemeAndHost;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export enum API_TARGETS {
|
||||
GOOGLE_API = "https://storage.googleapis.com",
|
||||
FUNNEL_API = "https://style.storyteller.ai",
|
||||
CDN_API = "https://cdn.storyteller.ai",
|
||||
GRAVATAR_API = "https://www.gravatar.com",
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export enum SubscriptionNamespace {
|
||||
FAKEYOU = "fakeyou",
|
||||
}
|
||||
export enum SubscriptionProduct {
|
||||
PLUS = "fakeyou_plus",
|
||||
PRO = "fakeyou_pro",
|
||||
ELITE = "fakeyou_elite",
|
||||
}
|
||||
export enum LoyaltyProgram {
|
||||
CONTRIBUTOR = "fakeyou_contributor",
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export enum EIntermediateFile {
|
||||
"true",
|
||||
"false"
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
export enum JobStatus {
|
||||
PENDING = "pending",
|
||||
STARTED = "started",
|
||||
ATTEMPT_FAILED = "attempt_failed",
|
||||
COMPLETE_SUCCESS = "complete_success",
|
||||
COMPLETE_FAILURE = "complete_failure",
|
||||
DEAD = "dead",
|
||||
CANCELLED_BY_USER = "cancelled_by_user",
|
||||
CANCELLED_BY_SYSTEM = "cancelled_by_system",
|
||||
}
|
||||
|
||||
export enum JobType {
|
||||
TextToSpeech = "text_to_speech",
|
||||
VoiceConversion = "voice_conversion",
|
||||
VideoStyleTransfer = "workflow",
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
export enum MediaFileClass {
|
||||
/// Unknown (default value)
|
||||
/// This will be present until we migrate all old files.
|
||||
Unknown = "unknown",
|
||||
|
||||
/// Audio files: wav, mp3, etc.
|
||||
Audio = "audio",
|
||||
|
||||
/// Image files: png, jpeg, etc.
|
||||
Image = "image",
|
||||
|
||||
/// Video files: mp4, etc.
|
||||
Video = "video",
|
||||
|
||||
/// Engine "animations"
|
||||
Animation = "animation",
|
||||
|
||||
/// Engine "characters"
|
||||
Character = "character",
|
||||
|
||||
/// Engine "prop" items
|
||||
Prop = "prop",
|
||||
|
||||
/// Engine scenes (internal and external scenes)
|
||||
Scene = "scene",
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
export enum MediaFileType {
|
||||
Audio = "audio",
|
||||
Video = "video",
|
||||
Image = "image",
|
||||
|
||||
// BVH is a very popular file format for motion capture.
|
||||
// It is compatible with our engine.
|
||||
BVH = "bvh",
|
||||
|
||||
// GLTF is the text-based format of GLB. Unforunately it requires a
|
||||
// second file to include the visual data, so we strongly discourage
|
||||
// the use of this format in favor of GLB.
|
||||
GLTF = "gltf",
|
||||
|
||||
// GLB is the format we convert FBX files into. It's a very popular
|
||||
// open source 3D file format.
|
||||
GLB = "glb",
|
||||
|
||||
// MMD is the format for anime characters.
|
||||
// open source 3D file format.
|
||||
MMD = "mmd",
|
||||
|
||||
// FBX isn't supported by Storyteller Engine, but we can get
|
||||
// uploads in this format. It's a very popular 3D graphics format.
|
||||
FBX = "fbx",
|
||||
|
||||
// Full Storyteller Engine scenes (RON = Rusty Object Notation)
|
||||
// This is a temporary format that will eventually go away.
|
||||
Scene = "scene",
|
||||
|
||||
None = "none",
|
||||
}
|
||||
|
||||
export enum MediaFileSubtype {
|
||||
/// Animation file from Mixamo
|
||||
/// Primarily used for FBX and GLB.
|
||||
Mixamo = "mixamo",
|
||||
|
||||
/// Animation file from MocapNet
|
||||
/// Primarily used for BVH.
|
||||
MocapNet = "mocap_net",
|
||||
|
||||
/// Generic animation case
|
||||
/// Used for BVH files, but can also pertain to animation-only files of other types.
|
||||
AnimationOnly = "animation_only",
|
||||
|
||||
// TODO(bt,2024-03-08): Migrate records and code, then remove
|
||||
/// DEPRECATED: Use `SceneImport` instead.
|
||||
Scene = "scene",
|
||||
|
||||
/// Generic 3D scene file.
|
||||
/// Can pertain to glTF, glB, FBX, etc.
|
||||
SceneImport = "scene_import",
|
||||
|
||||
/// Native Storyteller scene format.
|
||||
/// Typically stored in a `.scn.ron` file.
|
||||
StorytellerScene = "storyteller_scene",
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
export enum FilterMediaClasses {
|
||||
AUDIO = "audio",
|
||||
IMAGE = "image",
|
||||
VIDEO = "video",
|
||||
DIMENSIONAL = "dimensional",
|
||||
}
|
||||
|
||||
export enum FilterMediaType {
|
||||
SCENE_JSON = "scene_json",
|
||||
GLB = "glb",
|
||||
GLTF = "gltf",
|
||||
PMX = "pmx",
|
||||
PMD = "pmd",
|
||||
VMD = "vmd",
|
||||
}
|
||||
|
||||
export enum FilterEngineCategories {
|
||||
ANIMATION = "animation",
|
||||
AUDIO = "audio",
|
||||
CHARACTER = "character",
|
||||
CREATURE = "creature",
|
||||
EXPRESSION = "expression",
|
||||
IMAGE_PLANE = "image_plane",
|
||||
LOCATION = "location",
|
||||
OBJECT = "object",
|
||||
SCENE = "scene",
|
||||
SET_DRESSING = "set_dressing",
|
||||
SKYBOX = "skybox",
|
||||
VIDEO_PLANE = "video_plane",
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export enum GenerateTtsAudioErrorType {
|
||||
BadRequest = "bad_request",
|
||||
NotFound = "not_found",
|
||||
TooManyRequests = "too_many_requests",
|
||||
ServerError = "server_error",
|
||||
UnknownError = "unknown_error",
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export enum USER_FEATURE_FLAGS {
|
||||
EXPLORE_MEDIA = "explore_media",
|
||||
STUDIO = "studio",
|
||||
UPLOAD_3D = "upload_3d",
|
||||
VIDEO_STYLE_TRANSFER = "video_style_transfer",
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export enum Visibility {
|
||||
Public = "public",
|
||||
Hidden = "hidden",
|
||||
Private = "private",
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export enum WeightCategory {
|
||||
TTS = "text_to_speech",
|
||||
VOCODER = "vocoder",
|
||||
VC = "voice_conversion",
|
||||
ZS = "zero_shot",
|
||||
SD = "image_generation",
|
||||
WF = "workflow_config",
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export enum WeightType {
|
||||
TT2 = "tt2",
|
||||
HIFIGAN_TT2 = "hifigan_tt2",
|
||||
RVCv2 = "rvc_v2",
|
||||
SD_15 = "sd_1.5",
|
||||
SDXL = "sdxl",
|
||||
SVC = "so_vits_svc",
|
||||
LORA = "loRA",
|
||||
VALL_E = "vall_e",
|
||||
NONE = "none",
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from "./QueryFilters.js";
|
||||
@@ -0,0 +1,26 @@
|
||||
interface DefaultAvatar {
|
||||
color_index: number;
|
||||
image_index: number;
|
||||
}
|
||||
|
||||
interface User {
|
||||
default_avatar: DefaultAvatar;
|
||||
display_name: string;
|
||||
gravatar_hash: string;
|
||||
user_token: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface BetaKey {
|
||||
created_at: string;
|
||||
creator: User;
|
||||
is_distributed: boolean;
|
||||
key_value: string;
|
||||
maybe_note?: string;
|
||||
maybe_note_html?: string;
|
||||
maybe_redeemed_at?: string;
|
||||
maybe_redeemer?: User;
|
||||
maybe_referrer?: User;
|
||||
product: string;
|
||||
token: string;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import {
|
||||
LoyaltyProgram,
|
||||
SubscriptionNamespace,
|
||||
SubscriptionProduct,
|
||||
} from "../enums/Billing.js";
|
||||
|
||||
export interface ActiveSubscriptions {
|
||||
// user's list of subscriptions
|
||||
active_subscriptions: Subscription[];
|
||||
// special programs that the user could be in
|
||||
maybe_loyalty_program?: LoyaltyProgram;
|
||||
}
|
||||
|
||||
export interface Subscription {
|
||||
namespace: SubscriptionNamespace;
|
||||
product_slug: SubscriptionProduct;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
export interface ZsDataset {
|
||||
created_at: string; // ISO 8601 date-time string
|
||||
creator: UserDetailsLight;
|
||||
creator_set_visibility: string; // Enum or specific string values
|
||||
dataset_token: string;
|
||||
ietf_language_tag: string;
|
||||
ietf_primary_language_subtag: string;
|
||||
title: string;
|
||||
updated_at: string; // ISO 8601 date-time string
|
||||
}
|
||||
|
||||
interface UserDetailsLight {
|
||||
default_avatar: UserDefaultAvatarInfo;
|
||||
display_name: string;
|
||||
gravatar_hash: string;
|
||||
user_token: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
interface UserDefaultAvatarInfo {
|
||||
color_index: number;
|
||||
image_index: number;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import { JobStatus } from "../enums/Job.js";
|
||||
|
||||
export interface Job {
|
||||
created_at: string;
|
||||
job_token: string;
|
||||
maybe_result: JobMaybeResult;
|
||||
request: JobRequest;
|
||||
status: JobStatusResponse;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface JobMaybeResult {
|
||||
entity_token: string;
|
||||
entity_type: string;
|
||||
// maybe_public_bucket_media_path: string;
|
||||
maybe_successfully_completed_at: string;
|
||||
media_links: {
|
||||
cdn_url: string;
|
||||
};
|
||||
}
|
||||
export interface JobRequest {
|
||||
inference_category: string;
|
||||
maybe_model_title: string;
|
||||
maybe_model_token: string;
|
||||
maybe_model_type: string;
|
||||
maybe_raw_inference_text: string;
|
||||
maybe_style_name: string;
|
||||
}
|
||||
|
||||
export interface JobStatusResponse {
|
||||
attempt_count: number;
|
||||
maybe_assigned_cluster: string;
|
||||
maybe_assigned_worker: string;
|
||||
maybe_extra_status_description: string;
|
||||
maybe_failure_category: string;
|
||||
maybe_first_started_at: string;
|
||||
requires_keepalive: boolean;
|
||||
progress_percentage: number;
|
||||
status: JobStatus;
|
||||
}
|
||||
|
||||
export interface JobPreview {
|
||||
success: boolean;
|
||||
state: {
|
||||
job_token: string;
|
||||
request: Record<string, unknown>;
|
||||
status: {
|
||||
status: string;
|
||||
maybe_extra_status_description: string | null;
|
||||
maybe_assigned_worker: string;
|
||||
maybe_assigned_cluster: string;
|
||||
maybe_first_started_at: string;
|
||||
attempt_count: number;
|
||||
requires_keepalive: boolean;
|
||||
maybe_failure_category: string;
|
||||
progress_percentage: number;
|
||||
};
|
||||
maybe_result: {
|
||||
expected_stages: number;
|
||||
currently_active_stage: number;
|
||||
per_stage_frame_count: number;
|
||||
stages: Array<{
|
||||
stage_progress: number;
|
||||
expected_frame_count: number;
|
||||
stage_complete: boolean;
|
||||
frames: string[];
|
||||
}>;
|
||||
};
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
interface MaybeResult {
|
||||
entity_token: string;
|
||||
entity_type: string;
|
||||
maybe_public_bucket_media_path: string;
|
||||
maybe_successfully_completed_at: string;
|
||||
}
|
||||
|
||||
interface Request {
|
||||
inference_category: string;
|
||||
maybe_model_title?: string;
|
||||
maybe_model_token: string;
|
||||
maybe_model_type: string;
|
||||
maybe_raw_inference_text: string;
|
||||
maybe_style_name: string;
|
||||
}
|
||||
|
||||
interface Status {
|
||||
attempt_count: number;
|
||||
maybe_assigned_cluster?: string;
|
||||
maybe_assigned_worker?: string;
|
||||
maybe_extra_status_description?: string;
|
||||
maybe_failure_category?: string;
|
||||
maybe_first_started_at: string;
|
||||
requires_keepalive: boolean;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface JobState {
|
||||
created_at: string;
|
||||
job_token: string;
|
||||
maybe_result?: MaybeResult;
|
||||
request: Request;
|
||||
status: Status;
|
||||
updated_at: string;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import { MediaFileClass } from "../enums/MediaFileClass";
|
||||
import { MediaFileType, MediaFileSubtype } from "../enums/MediaFileType";
|
||||
import { WeightCategory } from "../enums/WeightCategory";
|
||||
import { WeightType } from "../enums/WeightType";
|
||||
import { UserInfo } from "./Users";
|
||||
|
||||
export interface MediaFile {
|
||||
token: string;
|
||||
media_type: MediaFileType;
|
||||
media_class: MediaFileClass | null;
|
||||
maybe_animation_type: string | null;
|
||||
maybe_media_subtype: MediaFileSubtype | null;
|
||||
maybe_engine_extension: string | null;
|
||||
maybe_batch_token: string;
|
||||
maybe_original_filename: string | null;
|
||||
maybe_creator_user: UserInfo | null;
|
||||
maybe_prompt_token: string | null;
|
||||
origin: {
|
||||
origin_category: string;
|
||||
product_category: string;
|
||||
maybe_model: { title: string } | null;
|
||||
};
|
||||
origin_category: string;
|
||||
origin_product_category: string;
|
||||
maybe_origin_model_type: null | string;
|
||||
maybe_origin_model_token: null | string;
|
||||
maybe_duration_millis: number | null;
|
||||
maybe_style_name: null | string;
|
||||
public_bucket_path: string;
|
||||
public_bucket_url: string;
|
||||
media_links: {
|
||||
cdn_url: string;
|
||||
thumbnail_template: string;
|
||||
};
|
||||
cover_image: {
|
||||
maybe_cover_image_public_bucket_path: null | string;
|
||||
default_cover: {
|
||||
image_index: number;
|
||||
color_index: number;
|
||||
};
|
||||
};
|
||||
creator_set_visibility: string;
|
||||
maybe_title: null | string;
|
||||
maybe_text_transcript: null | string;
|
||||
stats: {
|
||||
positive_rating_count: number;
|
||||
bookmark_count: number;
|
||||
};
|
||||
maybe_model_weight_info: {
|
||||
title: string;
|
||||
weight_token: string;
|
||||
weight_category: WeightCategory;
|
||||
weight_type: WeightType;
|
||||
maybe_weight_creator: UserInfo;
|
||||
maybe_cover_image_public_bucket_path: string;
|
||||
};
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface Pagination {
|
||||
current: number;
|
||||
total_page_count: number;
|
||||
}
|
||||
export interface PaginationInfinite {
|
||||
cursor_is_reversed: boolean;
|
||||
maybe_next?: string;
|
||||
maybe_previous?: string;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
export interface Prompts {
|
||||
created_at: string;
|
||||
lcm_disabled: boolean;
|
||||
lipsync_enabled: boolean;
|
||||
maybe_inference_duration_millis: number;
|
||||
maybe_moderator_fields: string;
|
||||
maybe_negative_prompt: string;
|
||||
maybe_positive_prompt: string;
|
||||
maybe_strength: number;
|
||||
maybe_style_name: string;
|
||||
prompt_type: string;
|
||||
token: string;
|
||||
use_cinematic: boolean;
|
||||
used_face_detailer: boolean;
|
||||
used_upscaler: boolean;
|
||||
maybe_model_type: string;
|
||||
maybe_generation_provider: string;
|
||||
maybe_context_images: [
|
||||
{
|
||||
media_links: {
|
||||
cdn_url: string;
|
||||
maybe_thumbnail_template: string;
|
||||
maybe_video_previews: {
|
||||
animated: string;
|
||||
animated_thumbnail_template: string;
|
||||
still: string;
|
||||
still_thumbnail_template: string;
|
||||
};
|
||||
};
|
||||
media_token: string;
|
||||
semantic: string;
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface StatusAlert {
|
||||
maybe_alert?: MaybeAlert;
|
||||
refresh_interval_millis: number;
|
||||
}
|
||||
|
||||
interface MaybeAlert {
|
||||
maybe_category?: string;
|
||||
maybe_message?: string;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
export interface UserBookmarkBatch {
|
||||
entity_token: string;
|
||||
entity_type: string;
|
||||
is_bookmarked: boolean;
|
||||
maybe_bookmark_token: string;
|
||||
}
|
||||
|
||||
interface DefaultAvatar {
|
||||
color_index: number;
|
||||
image_index: number;
|
||||
}
|
||||
|
||||
interface User {
|
||||
default_avatar: DefaultAvatar;
|
||||
display_name: string;
|
||||
gravatar_hash: string;
|
||||
user_token: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface UserBookmarkByEntity {
|
||||
created_at: string;
|
||||
token: string;
|
||||
updated_at: string;
|
||||
user: User;
|
||||
}
|
||||
|
||||
interface DefaultAvatar {
|
||||
color_index: number;
|
||||
image_index: number;
|
||||
}
|
||||
|
||||
interface Creator {
|
||||
default_avatar: DefaultAvatar;
|
||||
display_name: string;
|
||||
gravatar_hash: string;
|
||||
user_token: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
interface MediaFileData {
|
||||
maybe_creator: Creator;
|
||||
media_type: string; // Adjust type as per your specific schema
|
||||
public_bucket_path: string;
|
||||
}
|
||||
|
||||
interface WeightData {
|
||||
maybe_cover_image_public_bucket_path: string;
|
||||
maybe_creator: Creator;
|
||||
title: string;
|
||||
weight_category: string; // Adjust type as per your specific schema
|
||||
weight_type: string; // Adjust type as per your specific schema
|
||||
}
|
||||
|
||||
interface Stats {
|
||||
bookmark_count: number;
|
||||
positive_rating_count: number;
|
||||
}
|
||||
|
||||
interface Details {
|
||||
entity_token: string;
|
||||
entity_type: string; // Adjust type as per your specific schema
|
||||
maybe_media_file_data?: MediaFileData;
|
||||
maybe_summary_text?: string;
|
||||
maybe_thumbnail_url?: string;
|
||||
maybe_weight_data?: WeightData;
|
||||
stats: Stats;
|
||||
}
|
||||
|
||||
export interface UserBookmarkByUser {
|
||||
created_at: string;
|
||||
details: Details;
|
||||
token: string;
|
||||
updated_at: string;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import { USER_FEATURE_FLAGS } from "../../libs/api/src/lib/enums/UserFeatures";
|
||||
|
||||
export interface CoreInfo {
|
||||
default_avatar: {
|
||||
color_index: number;
|
||||
image_index: number;
|
||||
};
|
||||
display_name: string;
|
||||
gravatar_hash: string;
|
||||
user_token: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface UserInfo {
|
||||
user_token: string;
|
||||
username: string;
|
||||
display_name: string;
|
||||
email_gravatar_hash: string;
|
||||
|
||||
core_info: CoreInfo;
|
||||
|
||||
// Rollout feature flags
|
||||
can_access_studio: boolean;
|
||||
maybe_feature_flags: USER_FEATURE_FLAGS[];
|
||||
|
||||
// Usage
|
||||
can_use_tts: boolean;
|
||||
can_use_w2l: boolean;
|
||||
can_delete_own_tts_results: boolean;
|
||||
can_delete_own_w2l_results: boolean;
|
||||
can_delete_own_account: boolean;
|
||||
|
||||
// Contribution
|
||||
can_upload_tts_models: boolean;
|
||||
can_upload_w2l_templates: boolean;
|
||||
can_delete_own_tts_models: boolean;
|
||||
can_delete_own_w2l_templates: boolean;
|
||||
|
||||
// Moderation
|
||||
can_approve_w2l_templates: boolean;
|
||||
can_edit_other_users_profiles: boolean;
|
||||
can_edit_other_users_tts_models: boolean;
|
||||
can_edit_other_users_w2l_templates: boolean;
|
||||
can_delete_other_users_tts_models: boolean;
|
||||
can_delete_other_users_tts_results: boolean;
|
||||
can_delete_other_users_w2l_templates: boolean;
|
||||
can_delete_other_users_w2l_results: boolean;
|
||||
can_ban_users: boolean;
|
||||
can_delete_users: boolean;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
interface CoverImage {
|
||||
default_cover: {
|
||||
color_index: number;
|
||||
image_index: number;
|
||||
};
|
||||
maybe_cover_image_public_bucket_path: string;
|
||||
}
|
||||
|
||||
interface DefaultAvatar {
|
||||
color_index: number;
|
||||
image_index: number;
|
||||
}
|
||||
|
||||
interface Creator {
|
||||
default_avatar: DefaultAvatar;
|
||||
display_name: string;
|
||||
gravatar_hash: string;
|
||||
user_token: string;
|
||||
username: string;
|
||||
}
|
||||
|
||||
interface Stats {
|
||||
bookmark_count: number;
|
||||
positive_rating_count: number;
|
||||
}
|
||||
|
||||
export interface Weight {
|
||||
cover_image: CoverImage;
|
||||
created_at: string;
|
||||
creator: Creator;
|
||||
creator_set_visibility: string;
|
||||
file_checksum_sha2: string;
|
||||
file_size_bytes: number;
|
||||
stats: Stats;
|
||||
title: string;
|
||||
updated_at: string;
|
||||
weight_category: string;
|
||||
weight_token: string;
|
||||
weight_type: string;
|
||||
}
|
||||
Reference in New Issue
Block a user