Compare commits

...
Author SHA1 Message Date
Brandon Thomas 3b60db68c2 Update MediaUploadApi.ts
this endpoint can't be served via the default hostname
2025-07-06 21:18:22 -04:00
Brandon Thomas 3a564c70e0 comments 2025-07-06 20:52:59 -04:00
Brandon Thomas 7bff690451 force session refresh if api configs change 2025-07-06 20:50:41 -04:00
Brandon Thomas e0d3bcbd05 cleanup apis, sync apis with tauri 2025-07-06 20:34:25 -04:00
Brandon Thomas e7238bdbb4 continued frontend cleanup 2025-07-06 19:53:19 -04:00
Brandon Thomas c62a6a6d6a ability to change API hostname on the fly 2025-07-06 19:18:39 -04:00
Brandon Thomas e156d9608d more local server env fixes 2025-07-06 01:21:42 -04:00
67 changed files with 347 additions and 580 deletions
@@ -44,8 +44,6 @@ pub async fn upload_new_engine_asset_from_file<P: AsRef<Path>>(
debug!("Requesting {:?}", &url);
//let mut file = File::open(path)?;
let client = Client::builder()
.gzip(true)
.build()?;
@@ -80,8 +78,8 @@ pub async fn upload_new_engine_asset_from_file<P: AsRef<Path>>(
}
fn get_route(api_host: &ApiHost) -> String {
let api_hostname = api_host.to_api_hostname();
format!("https://{}/v1/media_files/upload/new_engine_asset", api_hostname)
let api_hostname_and_scheme = api_host.to_api_hostname_and_scheme();
format!("{}/v1/media_files/upload/new_engine_asset", api_hostname_and_scheme)
}
// TODO(bt,2025-04-22): Share API definitions between client and server in common crate.
@@ -50,8 +50,6 @@ pub async fn upload_video_media_file_from_file<P: AsRef<Path>>(
debug!("Requesting {:?}", &url);
//let mut file = File::open(path)?;
let client = Client::builder()
.gzip(true)
.build()?;
@@ -85,7 +83,7 @@ pub async fn upload_video_media_file_from_file<P: AsRef<Path>>(
}
fn get_route(api_host: &ApiHost) -> String {
let api_hostname = api_host.to_api_hostname();
format!("https://{}/v1/media_files/upload/new_video", api_hostname)
let api_hostname_and_scheme = api_host.to_api_hostname_and_scheme();
format!("{}/v1/media_files/upload/new_video", api_hostname_and_scheme)
}
@@ -28,7 +28,7 @@ pub fn get_app_info_command(
let git_commit_short_id = build_metadata::git_commit_short_id();
let git_commit_timestamp = build_metadata::git_commit_timestamp();
let storyteller_host = app_env_configs.storyteller_host.to_api_hostname();
let storyteller_host = app_env_configs.storyteller_host.to_api_hostname_and_scheme();
AppInfoResponse {
build_timestamp,
@@ -1,10 +1,10 @@
import { GetCdnOrigin } from "~/api/GetCdnOrigin";
import environmentVariables from "./EnvironmentVariables";
import { StorytellerApiHostStore } from "@storyteller/api";
export async function get_media_url(mediaId: string) {
//This is for prod when we have the proper info on the url.
const api_base_url = environmentVariables.values.BASE_API;
const url = `${api_base_url}/v1/media_files/file/${mediaId}`;
const apiSchemeAndHost = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
const url = `${apiSchemeAndHost}/v1/media_files/file/${mediaId}`;
const response = await fetch(url);
const json = await JSON.parse(await response.text());
@@ -8,7 +8,7 @@ export class AnalyticsApi extends ApiManager {
maybeLastAction: string;
maybeLogToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/analytics/log_session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/analytics/log_session`;
const body = {
maybe_last_action: maybeLastAction,
@@ -1,8 +1,8 @@
import { GetBuildEnvironment } from "~/BuildEnvironment";
import environmentVariables from "../EnvironmentVariables";
import { Configs } from "~/configs";
//import { fetch } from '@tauri-apps/plugin-http'
import { FetchProxy as fetch } from "@storyteller/tauri-utils";
import { StorytellerApiHostStore } from "@storyteller/api";
type NonNullableObject<T extends object> = NonNullable<T>;
@@ -19,12 +19,12 @@ export class ApiManager {
constructor() {
const environmentType = GetBuildEnvironment().getBuildEnvironmentType();
const configs = new Configs(environmentType);
const baseApi = configs.baseApi;
// TODO(bt,2025-07-06): Not sure that any of this is used anymore.
// If so, try to use Configs, StorytellerApiHostStore, or another configuration source.
// look at the .env file
this.ApiTargets = {
//BaseApi: environmentVariables.values.BASE_API as string,
BaseApi: baseApi,
GoggleApi: environmentVariables.values.GOOGLE_API as string,
FunnelApi: environmentVariables.values.FUNNEL_API as string,
CdnApi: environmentVariables.values.CDN_API as string,
@@ -33,6 +33,10 @@ export class ApiManager {
};
}
protected getApiSchemeAndHost(): string {
return StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
}
public async fetch<B, T>(
endpoint: string,
{
@@ -14,7 +14,7 @@ export class BetaKeysApi extends ApiManager {
numberOfKeys: number;
uuidIdempotencyToken: string;
}): Promise<ApiResponse<string[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/beta_keys/create`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/beta_keys/create`;
const body = {
maybe_note: maybeNote,
@@ -59,7 +59,7 @@ export class BetaKeysApi extends ApiManager {
maybeReferrerUsername?: string;
onlyListRemaining?: boolean;
}): Promise<ApiResponse<BetaKey[], Pagination>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/beta_keys/list`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/beta_keys/list`;
const query = {
sort_ascending: sortAscending,
@@ -91,7 +91,7 @@ export class BetaKeysApi extends ApiManager {
}: {
betaKey: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/beta_keys/redeem`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/beta_keys/redeem`;
return this.post<
{
@@ -118,7 +118,7 @@ export class BetaKeysApi extends ApiManager {
betaKey: string;
isDistributed: boolean;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/beta_keys/${betaKey}/distributed`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/beta_keys/${betaKey}/distributed`;
return this.post<
{
@@ -145,7 +145,7 @@ export class BetaKeysApi extends ApiManager {
token: string;
note?: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/beta_keys/${token}/note`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/beta_keys/${token}/note`;
return this.post<
{
@@ -9,7 +9,7 @@ export class BillingApi extends ApiManager {
maybe_loyalty_program?: LoyaltyProgram;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/billing/active_subscriptions`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/billing/active_subscriptions`;
return await this.get<{
success: boolean;
active_subscriptions?: Subscription[];
@@ -12,7 +12,7 @@ export class CommentsApi extends ApiManager {
entityType: string;
uuidIdempotencyToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/comments/new`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/comments/new`;
const body = {
comment_markdown: commentMarkdown,
@@ -49,7 +49,7 @@ export class CommentsApi extends ApiManager {
}: {
commentToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/comments/delete/${commentToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/comments/delete/${commentToken}`;
return this.post<
{ as_mod: boolean },
@@ -74,7 +74,7 @@ export class CommentsApi extends ApiManager {
entityType: string;
entityToken: string;
}): Promise<ApiResponse<string[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/comments/list/${entityType}/${entityToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/comments/list/${entityType}/${entityToken}`;
return this.get<{
success: boolean;
@@ -8,7 +8,7 @@ export class EngineApi extends ApiManager {
mediaFileToken: string;
uuidIdempotencyToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/conversion/enqueue_fbx_to_gltf`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/conversion/enqueue_fbx_to_gltf`;
const body = {
media_file_token: mediaFileToken,
@@ -44,7 +44,7 @@ export class EngineApi extends ApiManager {
screenshot: File; // base64 encoded PNG
sceneMediaToken?: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/scene_snapshot`;
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) {
@@ -97,7 +97,7 @@ export class EngineApi extends ApiManager {
snapshotMediaToken: string;
additionalImages?: string[];
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/prompt`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/prompt`;
const uuidIdempotencyToken = crypto.randomUUID(); // Generate a new UUID
const body = {
@@ -144,7 +144,7 @@ export class EngineApi extends ApiManager {
};
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/session/${jobToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/session/${jobToken}`;
const response = await this.get<{
success?: boolean;
@@ -182,7 +182,7 @@ export class EngineApi extends ApiManager {
};
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/session_jobs/${jobToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/session_jobs/${jobToken}`;
const response = await this.get<{
success?: boolean;
@@ -8,7 +8,7 @@ export class FeaturedItemsApi extends ApiManager {
entityToken: string;
entityType: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/featured_item/create`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/featured_item/create`;
const body = {
entity_token: entityToken,
@@ -41,7 +41,7 @@ export class FeaturedItemsApi extends ApiManager {
entityToken: string;
entityType: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/featured_item/delete`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/featured_item/delete`;
const body = {
entity_token: entityToken,
@@ -74,7 +74,7 @@ export class FeaturedItemsApi extends ApiManager {
entityType: string;
entityToken: string;
}): Promise<ApiResponse<boolean>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/featured_item/is_featured/${entityType}/${entityToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/featured_item/is_featured/${entityType}/${entityToken}`;
return this.post<
undefined,
@@ -7,7 +7,7 @@ export class JobsApi extends ApiManager {
}: {
token: string;
}): Promise<ApiResponse<JobState>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/job/${token}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/job/${token}`;
return this.get<{
success: boolean;
@@ -23,7 +23,7 @@ export class JobsApi extends ApiManager {
}
public ListJobs(): Promise<ApiResponse<JobState[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/batch`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/batch`;
return this.get<{
success: boolean;
@@ -39,7 +39,7 @@ export class JobsApi extends ApiManager {
}
public ListRecentJobs(): Promise<ApiResponse<Job[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/session`;
return this.get<{
success: boolean;
@@ -56,7 +56,7 @@ export class JobsApi extends ApiManager {
}
public DeleteJobByToken(jobToken: string): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/job/${jobToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/job/${jobToken}`;
return this.delete<
undefined,
@@ -51,7 +51,7 @@ export class MediaFilesApi extends ApiManager {
asMod?: boolean;
setDelete?: boolean;
}): Promise<ApiResponse<MediaFile>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/file/${mediaFileToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/file/${mediaFileToken}`;
const body = { as_mod: asMod, set_delete: setDelete };
return await this.delete<
@@ -81,7 +81,7 @@ export class MediaFilesApi extends ApiManager {
}: {
mediaTokens: string[];
}): Promise<ApiResponse<MediaFile[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/batch`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/batch`;
return await this.get<{
success: boolean;
@@ -102,7 +102,7 @@ export class MediaFilesApi extends ApiManager {
}: {
mediaFileToken: string;
}): Promise<ApiResponse<MediaFile>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/file/${mediaFileToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/file/${mediaFileToken}`;
return await this.get<{
success: boolean;
media_file: MediaFile;
@@ -122,7 +122,7 @@ export class MediaFilesApi extends ApiManager {
public async ListMediaFiles(
query: ListMediaQuery,
): Promise<ApiResponse<MediaInfo[], PaginationInfinite>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/list`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list`;
const queryWithStrings = {
...query,
filter_media_classes: query.filter_media_classes
@@ -156,7 +156,7 @@ export class MediaFilesApi extends ApiManager {
public async ListFeaturedMediaFiles(
query: ListMediaQuery,
): Promise<ApiResponse<MediaInfo[], PaginationInfinite>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/list_featured`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list_featured`;
const queryWithStrings = {
...query,
filter_media_classes: query.filter_media_classes
@@ -191,7 +191,7 @@ export class MediaFilesApi extends ApiManager {
query: ListUserMediaQuery,
): Promise<ApiResponse<MediaInfo[], Pagination>> {
const userName = authentication.userInfo.value?.username;
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/list/user/${userName}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list/user/${userName}`;
const queryWithStrings = {
...query,
include_user_uploads: true,
@@ -226,7 +226,7 @@ export class MediaFilesApi extends ApiManager {
public async SearchFeaturedMediaFiles(
query: SearchFeaturedMediaQuery,
): Promise<ApiResponse<MediaInfo[], Pagination>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/search_featured`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/search_featured`;
const queryWithStrings = {
search_term: query.search_term,
filter_media_classes: query.filter_media_classes
@@ -258,7 +258,7 @@ export class MediaFilesApi extends ApiManager {
public async SearchUserMediaFiles(
query: SearchFeaturedMediaQuery,
): Promise<ApiResponse<MediaInfo[], Pagination>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/search_session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/search_session`;
const queryWithStrings = {
search_term: query.search_term,
filter_media_classes: query.filter_media_classes
@@ -294,7 +294,7 @@ export class MediaFilesApi extends ApiManager {
mediaToken: string;
name: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/rename/${mediaToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/rename/${mediaToken}`;
const body = { name };
return await this.post<
@@ -320,7 +320,7 @@ export class MediaFilesApi extends ApiManager {
mediaFileToken: string;
imageToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/cover_image/${mediaFileToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/cover_image/${mediaFileToken}`;
return await this.post<
{ cover_image_media_file_token: string },
{
@@ -347,7 +347,7 @@ export class MediaFilesApi extends ApiManager {
mediaFileToken: string;
visibility: Visibility;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/visibility/${mediaFileToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/visibility/${mediaFileToken}`;
return await this.post<
{ creator_set_visibility: string },
{
@@ -6,7 +6,7 @@ export class MediaUploadApi extends ApiManager {
private sessionToken: string = undefined;
private async getSessionTokenForUploadStudioShot() {
const endpoint = `${this.ApiTargets.BaseApi}/v1/session_token`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/session_token`;
return await this.get<{
maybe_signed_session: string;
}>({ endpoint })
@@ -156,7 +156,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title?: string | undefined;
maybe_visibility?: Visibility | undefined;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/audio`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/audio`;
const options: Record<string, string | number | undefined> = {
maybe_title,
maybe_visibility: maybe_visibility?.toString(),
@@ -179,7 +179,7 @@ export class MediaUploadApi extends ApiManager {
maybe_visibility?: Visibility | undefined;
is_intermediate_system_file?: EIntermediateFile;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/image`;
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,
@@ -207,7 +207,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title?: string;
maybe_visibility?: Visibility;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/new_engine_asset`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_engine_asset`;
const options: Record<string, string | number | undefined> = {
engine_category,
maybe_title,
@@ -231,7 +231,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title?: string;
maybe_visibility?: Visibility;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/new_scene`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_scene`;
const options: Record<string, string | number | undefined> = {
maybe_title,
maybe_visibility: maybe_visibility?.toString(),
@@ -256,7 +256,7 @@ export class MediaUploadApi extends ApiManager {
maybe_style_name?: string;
maybe_scene_source_media_file_token?: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/new_video`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_video`;
const options: Record<string, string | number | undefined> = {
is_intermediate_system_file: "true",
maybe_title,
@@ -286,7 +286,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title?: string;
maybe_visibility?: Visibility;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/pmx`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/pmx`;
const options: Record<string, string | number | undefined> = {
is_intermediate_system_file: "true",
engine_category,
@@ -309,7 +309,7 @@ export class MediaUploadApi extends ApiManager {
uuid: string;
mediaToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/saved_scene/${mediaToken}`;
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 });
}
@@ -326,7 +326,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title: string;
maybe_scene_source_media_file_token: string | undefined;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/scene_snapshot`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/scene_snapshot`;
const options: Record<string, string | number | undefined> = {
maybe_title: maybe_title,
@@ -3,7 +3,7 @@ import { StatusAlert } from "~/models/StatusAlert";
export class MiscApi extends ApiManager {
public GetStatusAlertCheck(): Promise<ApiResponse<StatusAlert>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/session`;
return this.get<{
success: boolean;
maybe_alert?: Omit<StatusAlert, "refresh_interval_millis">;
@@ -13,7 +13,7 @@ export class ModerationApi extends ApiManager {
inference_job_token_type?: string;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/moderation/user_feature_flags/${usernameOrToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/moderation/user_feature_flags/${usernameOrToken}`;
const body = {
action: {
@@ -7,7 +7,7 @@ export class PromptsApi extends ApiManager {
}: {
token: string;
}): Promise<ApiResponse<Prompts>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/prompts/${token}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/prompts/${token}`;
return this.get<{
success: boolean;
@@ -27,7 +27,7 @@ export class StudioGen2Api extends ApiManager {
inference_job_token_type?: string;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/studio_gen2/enqueue`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/studio_gen2/enqueue`;
const body = {
...enqueueVideo,
@@ -24,7 +24,7 @@ export class TtsApi extends ApiManager {
inference_job_token_type?: string;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/tts/inference`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/tts/inference`;
const body = {
...request,
@@ -62,7 +62,7 @@ export class UserBookmarksApi extends ApiManager {
user_bookmark_token?: string;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/create`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/create`;
const body = {
entity_token: entityToken,
entity_type: entityType,
@@ -98,7 +98,7 @@ export class UserBookmarksApi extends ApiManager {
}: {
entityToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/delete/${entityToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/delete/${entityToken}`;
return this.delete<
{ as_mod: boolean },
@@ -117,7 +117,7 @@ export class UserBookmarksApi extends ApiManager {
}
public ListUserBookmarks(): Promise<ApiResponse<UserBookmarkBatch[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/batch`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/batch`;
return this.get<{
success?: boolean;
@@ -146,7 +146,7 @@ export class UserBookmarksApi extends ApiManager {
ApiResponse<UserBookmarkByUser[], Pagination>
> {
const user = username ?? authentication.userInfo.value?.username;
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/list/${user}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/list/${user}`;
const query = {
sort_ascending,
@@ -185,7 +185,7 @@ export class UserBookmarksApi extends ApiManager {
entityType: string;
entityToken: string;
}): Promise<ApiResponse<UserBookmarkByEntity[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/list/${entityType}/${entityToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/list/${entityType}/${entityToken}`;
return this.get<{
success: boolean;
@@ -8,7 +8,7 @@ export interface UserRating {
export class UserRatingApi extends ApiManager {
public ListUserRatings(): Promise<ApiResponse<UserRating[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_rating/batch`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/batch`;
return this.get<{
success?: boolean;
@@ -34,7 +34,7 @@ export class UserRatingApi extends ApiManager {
entityType: string;
ratingValue: string;
}): Promise<ApiResponse<number>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_rating/rate`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/rate`;
const body = {
entity_token: entityToken,
@@ -71,7 +71,7 @@ export class UserRatingApi extends ApiManager {
entityType: string;
entityToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_rating/view/${entityType}/${entityToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/view/${entityType}/${entityToken}`;
return this.get<{
success?: boolean;
@@ -8,7 +8,7 @@ export class UsersApi extends ApiManager {
user?: UserInfo;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/session`;
return this.get<{
success: boolean;
logged_in: boolean;
@@ -35,7 +35,7 @@ export class UsersApi extends ApiManager {
user?: UserInfo;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user/${username}/profile`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user/${username}/profile`;
return this.get<{
success: boolean;
user?: UserInfo;
@@ -62,7 +62,7 @@ export class UsersApi extends ApiManager {
usernameOrEmail: string;
password: string;
}): Promise<ApiResponse<{ signedSession?: string }>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/login`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/login`;
const body = {
username_or_email: usernameOrEmail,
password: password,
@@ -93,7 +93,7 @@ export class UsersApi extends ApiManager {
}
public Logout(): Promise<ApiResponse<null>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/logout`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/logout`;
return this.post<null, { success: boolean; error_message?: string }>({
endpoint: endpoint,
})
@@ -119,7 +119,7 @@ export class UsersApi extends ApiManager {
password: string;
passwordConfirmation: string;
}): Promise<ApiResponse<{ signedSession?: string }>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/create_account`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/create_account`;
const body = {
email_address: email,
password,
@@ -36,7 +36,7 @@ export class VideoApi extends ApiManager {
inference_job_token_type?: string;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/workflows/enqueue_studio`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/workflows/enqueue_studio`;
const body = {
...enqueueVideo,
@@ -26,7 +26,7 @@ export class VoiceConversionApi extends ApiManager {
public ConvertVoice(
params: VoiceConversionParams,
): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/voice_conversion/inference`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_conversion/inference`;
const body = this.parseBodyValues<
VoiceConversionParams,
@@ -21,7 +21,7 @@ export class VoiceDesignerApi extends ApiManager {
): Promise<
ApiResponse<{ inference_job_token?: string; voice_token?: string }>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/voice_designer/enqueue_tts`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_designer/enqueue_tts`;
const body = this.parseBodyValues<
VoiceDesignerParams,
@@ -60,7 +60,7 @@ export class VoiceDesignerApi extends ApiManager {
username?: string;
}): Promise<ApiResponse<ZsDataset[]>> {
const user = username ?? authentication.userInfo.value?.username;
const endpoint = `${this.ApiTargets.BaseApi}/v1/voice_designer/user/${user}/list`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_designer/user/${user}/list`;
return this.get<{
success: boolean;
@@ -96,7 +96,7 @@ export class WeightsApi extends ApiManager {
...params
}: ListWeightsByUserRequest): Promise<ApiResponse<Weight[], Pagination>> {
const user = username ?? authentication.userInfo.value?.username;
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/by_user/${user}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/by_user/${user}`;
const query = this.parseQueryValues(params);
@@ -118,7 +118,7 @@ export class WeightsApi extends ApiManager {
public ListWeights({
...params
}: ListWeightsRequest): Promise<ApiResponse<Weight[], PaginationInfinite>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/list`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list`;
const query = this.parseQueryValues(params);
@@ -142,7 +142,7 @@ export class WeightsApi extends ApiManager {
}: ListFeaturedWeightsRequest): Promise<
ApiResponse<Weight[], PaginationInfinite>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/list_featured`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list_featured`;
const query = this.parseQueryValues(params);
@@ -162,7 +162,7 @@ export class WeightsApi extends ApiManager {
}
public ListWeightsPinned(): Promise<ApiResponse<Weight[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/list_pinned`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list_pinned`;
return this.get<{
success: boolean;
@@ -180,7 +180,7 @@ export class WeightsApi extends ApiManager {
public SearchWeights(
params: SearchWeightParams,
): Promise<ApiResponse<Weight[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/search`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/search`;
const body = this.parseBodyValues<SearchWeightParams, SearchWeightRequest>(
params,
@@ -207,7 +207,7 @@ export class WeightsApi extends ApiManager {
}: {
weightToken: string;
}): Promise<ApiResponse<Weight>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/weight/${weightToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
return this.get<GetWeightByTokenResponse>({ endpoint })
.then(({ success, ...mediaFile }) => ({
@@ -223,7 +223,7 @@ export class WeightsApi extends ApiManager {
weightToken,
...params
}: UpdateWeightByTokenParams): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/weight/${weightToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
const body = this.parseBodyValues<
Omit<UpdateWeightByTokenParams, "weightToken">,
@@ -248,7 +248,7 @@ export class WeightsApi extends ApiManager {
}: {
weightToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/weight/${weightToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
const body = {
as_mod: true,
@@ -275,7 +275,7 @@ export class WeightsApi extends ApiManager {
weightToken: string;
coverImageMediaFileToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/${weightToken}/cover_image`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/${weightToken}/cover_image`;
const body = {
cover_image_media_file_token: coverImageMediaFileToken,
@@ -0,0 +1,70 @@
import { GetAppInfo } from "@storyteller/tauri-api";
import { StorytellerApiHostStore } from "@storyteller/api";
import { forceGetUserInfoAndSubcriptions } from "~/signals";
// Time before we should call Tauri again.
const SYNC_THRESHOLD = 10 * 1000;
/**
* Keep track of if we can call Tauri again.
*/
class Cache {
private static instance: Cache;
private lastFetchSuccess?: number;
public static getInstance(): Cache {
if (Cache.instance !== undefined) {
return Cache.instance;
}
const instance = new Cache();
Cache.instance = instance;
return instance;
}
public canCall() : boolean {
if (this.lastFetchSuccess === undefined) {
return true;
}
return Date.now() - this.lastFetchSuccess > SYNC_THRESHOLD;
}
public setCallSuccess() {
this.lastFetchSuccess = Date.now();
}
}
/**
* Syncs our view of the Storyteller API configs with Tauri.
* Runs any necessary user session functions if things change.
*/
export const SyncStorytellerApiConfig = async () => {
console.log("SyncStorytellerApiConfig()")
const cache = Cache.getInstance();
const oldValue = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
if (!cache.canCall()) {
return;
}
GetAppInfo().then(async (appInfo) => {
console.log("SyncStorytellerApiConfig() - appInfo", appInfo);
const schemeAndHost = appInfo.payload.storyteller_host;
if (!schemeAndHost) {
return ;
}
console.log(`Updating hostname to ${schemeAndHost}`);
StorytellerApiHostStore.getInstance().setApiSchemeAndHost(schemeAndHost);
cache.setCallSuccess();
if (oldValue !== schemeAndHost) {
console.log("SyncStorytellerApiConfig() - force session refresh")
// NB: This is a hack that might prevent the login screen from being shown
// if the user is working in development.
await forceGetUserInfoAndSubcriptions();
}
});
}
@@ -1,10 +0,0 @@
export const apiHost = "https://api.storyteller.ai";
// Upload File
export const uploadMedia = `${apiHost}/v1/media_files/upload`;
// Scenes
export const uploadNewScene = `${apiHost}/v1/media_files/upload/new_scene`;
export const uploadThumbnail = `${apiHost}/v1/media_files/cover_image/`;
export const updateExistingScene = (sceneToken: string) =>
`${apiHost}/v1/media_files/upload/saved_scene/${sceneToken}`;
@@ -13,8 +13,8 @@ export const AuthButtons = ({
const { status, userInfo } = authentication;
console.log("Current State:");
console.log(status.value);
console.log("Current State:", status.value);
if (status.value === AUTH_STATUS.LOGGED_IN) {
console.log("SHOWING DROPDOWN");
return null;
+6 -2
View File
@@ -10,14 +10,13 @@ import "@fortawesome/fontawesome-svg-core/styles.css";
import { config } from "@fortawesome/fontawesome-svg-core";
import EnvironmentVariables from "~/Classes/EnvironmentVariables";
import { pageHeight, pageWidth, persistLogin } from "~/signals";
import { SyncStorytellerApiConfig } from "./api/SyncStorytellerApiConfig";
import { posthog } from "posthog-js";
config.autoAddCss = false; /* eslint-disable import/first */
// TODO(bt,2025-04-19): Make these configurable
const ENV = {
BASE_API: "https://api.storyteller.ai",
GOOGLE_API: "https://studio.storyteller.ai",
FUNNEL_API: "https://studio.storyteller.ai",
CDN_API: "https://cdn-2.fakeyou.com",
@@ -26,7 +25,12 @@ const ENV = {
};
const GlobalSettingsManager = ({ env }: { env: Record<string, string> }) => {
console.log("GlobalSettingsManager()");
SyncStorytellerApiConfig();
useSignals();
useSignalEffect(() => {
persistLogin();
});
-1
View File
@@ -30,7 +30,6 @@ config.autoAddCss = false; /* eslint-disable import/first */
// TODO(bt,2025-04-19): Make these configurable
const ENV = {
BASE_API: "https://api.storyteller.ai",
GOOGLE_API: "https://studio.storyteller.ai",
FUNNEL_API: "https://studio.storyteller.ai",
CDN_API: "https://cdn-2.fakeyou.com",
@@ -1,12 +1,11 @@
import { v4 as uuidv4 } from "uuid";
import {
uploadNewScene as uploadNewSceneEndpoint,
updateExistingScene as updateExistingSceneEndpoint,
} from "~/api";
import { FetchProxy as fetch } from "@storyteller/tauri-utils";
import { StorytellerApiHostStore } from "@storyteller/api";
export const uploadNewScene = async (file: File, sceneTitle: string) => {
const endpoint = uploadNewSceneEndpoint;
const apiSchemeAndHost = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
const endpoint = `${apiSchemeAndHost}/v1/media_files/upload/new_scene`;
const formData = new FormData();
formData.append("uuid_idempotency_token", uuidv4());
formData.append("file", file);
@@ -36,7 +35,8 @@ export const uploadNewScene = async (file: File, sceneTitle: string) => {
};
export const updateExistingScene = async (file: File, sceneToken: string) => {
const endpoint = updateExistingSceneEndpoint(sceneToken);
const apiSchemeAndHost = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
const endpoint = `${apiSchemeAndHost}/v1/media_files/upload/saved_scene/${sceneToken}`;
const formData = new FormData();
formData.append("uuid_idempotency_token", uuidv4());
@@ -3,9 +3,9 @@ import * as THREE from "three";
import { GLTFExporter } from "three/addons/exporters/GLTFExporter.js";
import { signalScene, startPollingActiveJobs } from "~/signals";
import { updateExistingScene, uploadNewScene } from "./api_fetchers";
import { uploadThumbnail } from "~/api";
import environmentVariables from "~/Classes/EnvironmentVariables";
import { GetCdnOrigin } from "~/api/GetCdnOrigin";
import { StorytellerApiHostStore } from "@storyteller/api";
interface StylizeVideoParams {
media_token: string;
@@ -111,10 +111,14 @@ class APIManagerResponseError extends Error {
}
export class APIManager {
baseUrl: string;
constructor() {
this.baseUrl = environmentVariables.values.BASE_API as string;
// NB(bt,2025-07-06): Cleaning this up. The code was duplicated a half dozen times.
// I think all of the code in this file is legacy, but to be safe I'm continuing to update it.
}
protected getApiSchemeAndHost() {
return StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
}
/**
@@ -159,7 +163,9 @@ export class APIManager {
if (image_resp["media_file_token"]) {
const image_token = image_resp["media_file_token"];
await fetch(uploadThumbnail + uploadSceneResponse["media_file_token"], {
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/cover_image/${uploadSceneResponse["media_file_token"]}`;
await fetch(endpoint, {
method: "POST",
credentials: "include",
headers: {
@@ -178,8 +184,7 @@ export class APIManager {
public async loadSceneState(
scene_media_file_token: string | null,
): Promise<any> {
const api_base_url = environmentVariables.values.BASE_API;
const url = `${api_base_url}/v1/media_files/file/${scene_media_file_token}`;
const url = `${this.getApiSchemeAndHost()}/v1/media_files/file/${scene_media_file_token}`;
const response = await fetch(url);
if (response.status > 200) {
throw new APIManagerResponseError("Failed to load scene");
@@ -225,7 +230,7 @@ export class APIManager {
* @returns
*/
public async getMediaFile(media_file_token: string): Promise<string> {
const url = `${this.baseUrl}/v1/media_files/file/${media_file_token}`;
const url = `${this.getApiSchemeAndHost()}/v1/media_files/file/${media_file_token}`;
const response = await fetch(url);
const json = await JSON.parse(await response.text());
const bucketPath = json["media_file"]["public_bucket_path"];
@@ -250,7 +255,7 @@ export class APIManager {
}
public async uploadMediaSceneThumbnail(blob: Blob | File, fileName: string) {
const url = `${this.baseUrl}/v1/media_files/upload/image`;
const url = `${this.getApiSchemeAndHost()}/v1/media_files/upload/image`;
const uuid = uuidv4();
const formData = new FormData();
@@ -294,7 +299,7 @@ export class APIManager {
}) {
// Promise<APIManagerResponseSuccess>
//TODO: UPDATE ENDPOINT!!!!
const url = `${this.baseUrl}/v1/media_files/upload/new_video`;
const url = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_video`;
const uuid = uuidv4();
const formData = new FormData();
@@ -369,7 +374,7 @@ export class APIManager {
public async getMediaBatch(media_tokens: string[]): Promise<MediaFile[]> {
const tokens = media_tokens;
const url = new URL(`${this.baseUrl}/v1/media_files/batch`);
const url = new URL(`${this.getApiSchemeAndHost()}/v1/media_files/batch`);
tokens.forEach((token) => url.searchParams.append("tokens", token));
const result = await fetch(url)
.then((response) => response.json())
@@ -429,7 +434,7 @@ export class APIManager {
const json_data = JSON.stringify(data);
const response = await fetch(
`${this.baseUrl}/v1/workflows/enqueue_studio`,
`${this.getApiSchemeAndHost()}/v1/workflows/enqueue_studio`,
{
method: "POST",
credentials: "include",
@@ -8,9 +8,9 @@ import {
import { MMDLoader } from "three/addons/loaders/MMDLoader.js";
import { MoveAIResult, Retarget } from "../Editor/retargeting";
import environmentVariables from "~/Classes/EnvironmentVariables";
import IAnimationClip from "./ClipInterfaces/IAnimationClip";
import { GetCdnOrigin } from "~/api/GetCdnOrigin";
import { StorytellerApiHostStore } from "@storyteller/api";
export class AnimationClip implements IAnimationClip {
version: number;
@@ -76,8 +76,8 @@ export class AnimationClip implements IAnimationClip {
async get_media_url() {
//This is for prod when we have the proper info on the url.
const api_base_url = environmentVariables.values.BASE_API;
const url = `${api_base_url}/v1/media_files/file/${this.media_id}`;
const apiSchemeAndHost = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
const url = `${apiSchemeAndHost}/v1/media_files/file/${this.media_id}`;
const response = await fetch(url);
const json = await JSON.parse(await response.text());
@@ -1,6 +1,6 @@
import { GetCdnOrigin } from "~/api/GetCdnOrigin";
import environmentVariables from "~/Classes/EnvironmentVariables";
import Ijson from "~/interfaces/Ijson";
import { StorytellerApiHostStore } from "@storyteller/api";
interface AudioDataInterface {
audioContext: AudioContext;
@@ -37,8 +37,8 @@ export class AudioClip implements Ijson {
async get_media_url() {
//This is for prod when we have the proper info on the url.
const api_base_url = environmentVariables.values.BASE_API;
const url = `${api_base_url}/v1/media_files/file/${this.media_id}`;
const apiSchemeAndHost = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
const url = `${apiSchemeAndHost}/v1/media_files/file/${this.media_id}`;
const response = await fetch(url);
const json = await JSON.parse(await response.text());
@@ -1,8 +1,8 @@
import * as THREE from "three";
import { GetCdnOrigin } from "~/api/GetCdnOrigin";
import environmentVariables from "~/Classes/EnvironmentVariables";
import Ijson from "~/interfaces/Ijson";
import { StorytellerApiHostStore } from "@storyteller/api";
interface CsvJson {
[key: string]: string[];
}
@@ -26,8 +26,8 @@ export class EmotionClip implements Ijson {
async get_media_url() {
//This is for prod when we have the proper info on the url.
const api_base_url = environmentVariables.values.BASE_API;
const url = `${api_base_url}/v1/media_files/file/${this.media_id}`;
const apiSchemeAndHost = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
const url = `${apiSchemeAndHost}/v1/media_files/file/${this.media_id}`;
const response = await fetch(url);
const json = await JSON.parse(await response.text());
@@ -1,8 +1,8 @@
import { LipSync } from "../Editor/lipsync";
import * as THREE from "three";
import { GetCdnOrigin } from "~/api/GetCdnOrigin";
import environmentVariables from "~/Classes/EnvironmentVariables";
import Ijson from "~/interfaces/Ijson";
import { StorytellerApiHostStore } from "@storyteller/api";
interface AudioDataInterface {
audioContext: AudioContext;
@@ -58,10 +58,10 @@ export class LipSyncClip implements Ijson {
// lip sync will be generated through TTS
async get_media_url() {
//This is for prod when we have the proper info on the url.
const api_base_url = environmentVariables.values.BASE_API;
const url = `${api_base_url}/v1/media_files/file/${this.media_id}`;
const apiSchemeAndHost = StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
const url = `${apiSchemeAndHost}/v1/media_files/file/${this.media_id}`;
console.log(`API BASE URL? ${api_base_url}`);
console.log(`API BASE URL? ${apiSchemeAndHost}`);
console.log(`CALLED URL? ${url}`);
const response = await fetch(url);
@@ -1,113 +0,0 @@
https://api.fakeyou.com/v1/media_files/batch?tokens=m_jh74zz1nfj2jxrkw7n00yamt32zrhb&tokens=m_0rqwx4kbnn2gz5s37apzftkw25vkzb&tokens=m_je04hbk7bqjdq9cnegp1j10mf4dzdb
{
"success": true,
"media_files": [
{
"token": "m_0rqwx4kbnn2gz5s37apzftkw25vkzb",
"media_type": "video",
"media_class": "unknown",
"maybe_media_subtype": null,
"maybe_engine_extension": null,
"maybe_batch_token": null,
"public_bucket_path": "/media/c/0/n/g/p/c0ngp9c570w66q3vhs0ygmwpasf2sfk1/videoc0ngp9c570w66q3vhs0ygmwpasf2sfk1mp4",
"maybe_model_weight_info": null,
"maybe_creator_user": {
"user_token": "U:937C1VN0S5G8H",
"username": "echelon",
"display_name": "echelon",
"gravatar_hash": "37e7e18f19d8f654a1ace405c846a9de",
"default_avatar": {
"image_index": 10,
"color_index": 3
}
},
"creator_set_visibility": "private",
"maybe_text_transcript": null,
"maybe_prompt_token": "prompt_3sf5p1n7g3sna6pc44nqgpvyd",
"maybe_original_filename": null,
"is_emulated_media_file": false,
"stats": {
"positive_rating_count": 0,
"bookmark_count": 0
},
"created_at": "2024-03-25T02:25:18Z",
"updated_at": "2024-03-25T02:25:18Z"
},
{
"token": "m_je04hbk7bqjdq9cnegp1j10mf4dzdb",
"media_type": "video",
"media_class": "unknown",
"maybe_media_subtype": null,
"maybe_engine_extension": null,
"maybe_batch_token": null,
"public_bucket_path": "/media/d/a/3/b/6/da3b640rh3zjj1easv96vc4d7v4jq8c1/da3b640rh3zjj1easv96vc4d7v4jq8c1.mp4",
"maybe_model_weight_info": null,
"maybe_creator_user": {
"user_token": "U:937C1VN0S5G8H",
"username": "echelon",
"display_name": "echelon",
"gravatar_hash": "37e7e18f19d8f654a1ace405c846a9de",
"default_avatar": {
"image_index": 10,
"color_index": 3
}
},
"creator_set_visibility": "public",
"maybe_text_transcript": null,
"maybe_prompt_token": null,
"maybe_original_filename": null,
"is_emulated_media_file": false,
"stats": {
"positive_rating_count": 0,
"bookmark_count": 0
},
"created_at": "2024-03-25T02:04:22Z",
"updated_at": "2024-03-25T02:04:22Z"
},
{
"token": "m_jh74zz1nfj2jxrkw7n00yamt32zrhb",
"media_type": "video",
"media_class": "unknown",
"maybe_media_subtype": null,
"maybe_engine_extension": null,
"maybe_batch_token": null,
"public_bucket_path": "/media/a/c/s/z/e/acszeddd464edypg9hcp5cga0482sjfv/videoacszeddd464edypg9hcp5cga0482sjfvmp4",
"maybe_model_weight_info": null,
"maybe_creator_user": {
"user_token": "U:937C1VN0S5G8H",
"username": "echelon",
"display_name": "echelon",
"gravatar_hash": "37e7e18f19d8f654a1ace405c846a9de",
"default_avatar": {
"image_index": 10,
"color_index": 3
}
},
"creator_set_visibility": "private",
"maybe_text_transcript": null,
"maybe_prompt_token": "prompt_dc8x82w2gqsvbpmp5ksxypssj",
"maybe_original_filename": null,
"is_emulated_media_file": false,
"stats": {
"positive_rating_count": 0,
"bookmark_count": 0
},
"created_at": "2024-03-25T02:12:46Z",
"updated_at": "2024-03-25T02:12:46Z"
}
]
}
// lip sync will be generated through TTS
async get_media_url() {
//This is for prod when we have the proper info on the url.
let api_base_url = environmentVariables.value.BASE_API;
let url = ${api_base_url}/v1/media_files/file/${this.media_id}
let responce = await fetch(url);
let json = await JSON.parse(await responce.text());
let bucketPath = json["media_file"]["public_bucket_path"];
let media_base_url = "https://storage.googleapis.com/vocodes-public"
let media_url = ${media_base_url}${bucketPath}
return media_url;
}
https://storage.googleapis.com/vocodes-public
@@ -1,2 +0,0 @@
mkdir /User/ChromeData
open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/User/ChromeData" --disable-web-security
@@ -5,24 +5,29 @@ import { AUTH_STATUS, LoyaltyProgram, USER_FEATURE_FLAGS } from "~/enums";
const status = signal<AUTH_STATUS>(AUTH_STATUS.INIT);
const userInfo = signal<UserInfo | undefined>(undefined);
const activeSubs = signal<ActiveSubscriptions | undefined>(undefined);
// Return all true for these inorder to remove the login.
const canUpload3D = computed(() => {
if (!userInfo.value || !userInfo.value.maybe_feature_flags) {
return undefined;
}
return userInfo.value.maybe_feature_flags.includes(
USER_FEATURE_FLAGS.UPLOAD_3D,
);
// NB(bt,2025-07-06): This is legacy code. Everyone should be able to upload 3D
// if (!userInfo.value || !userInfo.value.maybe_feature_flags) {
// return undefined;
// }
// return userInfo.value.maybe_feature_flags.includes(
// USER_FEATURE_FLAGS.UPLOAD_3D,
// );
return true;
});
const hasAccess = computed(() => {
if (
userInfo.value === undefined ||
userInfo.value.can_access_studio === undefined
) {
return undefined;
}
return userInfo.value.can_access_studio;
// NB(bt,2025-07-06): This is legacy code. Everyone should have access to the software.
// if (
// userInfo.value === undefined ||
// userInfo.value.can_access_studio === undefined
// ) {
// return undefined;
// }
// return userInfo.value.can_access_studio;
return true;
});
const hasPremium = computed(() => {
@@ -91,7 +91,13 @@ export const persistLogin = async () => {
getUserInfoAndSubcriptions();
};
// NB: Only for SyncStorytellerApiConfig.
export const forceGetUserInfoAndSubcriptions = async () => {
getUserInfoAndSubcriptions();
};
async function getUserInfoAndSubcriptions() {
console.log('getUserInfoAndSubcriptions()')
updateAuthStatus(AUTH_STATUS.GET_USER_INFO);
const usersApi = new UsersApi();
const sessionResponse = await usersApi.GetSession();
@@ -3,6 +3,7 @@ import { UserInfo, ActiveSubscriptions } from "~/models";
import { authentication, flushAllBackgroundLoadedMedia } from "~/signals";
export const updateAuthStatus = (newStatus: AUTH_STATUS) => {
console.log('updateAuthStatus()', newStatus)
authentication.status.value = newStatus;
};
@@ -10,6 +11,7 @@ export const updateUserInfo = (
newInfo: UserInfo | undefined,
flush?: boolean,
) => {
console.log('updateUserInfo()', newInfo)
if (newInfo && !flush) {
//case of updating UserInfo partly
authentication.userInfo.value = {
@@ -23,7 +23,6 @@ const regEx =
// TODO(bt,2025-04-19): Make these configurable
const ENV = {
BASE_API: "https://api.storyteller.ai",
GOOGLE_API: "https://studio.storyteller.ai",
FUNNEL_API: "https://studio.storyteller.ai",
CDN_API: "https://cdn-2.fakeyou.com",
+1
View File
@@ -16,3 +16,4 @@ 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"
+1 -1
View File
@@ -8,7 +8,7 @@ export class AnalyticsApi extends ApiManager {
maybeLastAction: string;
maybeLogToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/analytics/log_session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/analytics/log_session`;
const body = {
maybe_last_action: maybeLastAction,
-17
View File
@@ -1,17 +0,0 @@
// import { GetCdnOrigin } from "~/api/GetCdnOrigin";
// import environmentVariables from "./EnvironmentVariables";
// export async function get_media_url(mediaId: string) {
// //This is for prod when we have the proper info on the url.
// const api_base_url = environmentVariables.values.BASE_API;
// const url = `${api_base_url}/v1/media_files/file/${mediaId}`;
// const response = await fetch(url);
// const json = await JSON.parse(await response.text());
// const bucketPath = json["media_file"]["public_bucket_path"];
// const media_api_base_url = GetCdnOrigin();
// const media_url = `${media_api_base_url}${bucketPath}`;
// return media_url;
// }
+5 -1
View File
@@ -1,4 +1,5 @@
// 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";
@@ -17,7 +18,6 @@ export class ApiManager {
constructor() {
this.ApiTargets = {
BaseApi: API_TARGETS.BASE_API,
GoggleApi: API_TARGETS.GOOGLE_API,
FunnelApi: API_TARGETS.FUNNEL_API,
CdnApi: API_TARGETS.CDN_API,
@@ -25,6 +25,10 @@ export class ApiManager {
};
}
protected getApiSchemeAndHost(): string {
return StorytellerApiHostStore.getInstance().getApiSchemeAndHost();
}
public async fetch<B, T>(
endpoint: string,
{
+1 -1
View File
@@ -9,7 +9,7 @@ export class BillingApi extends ApiManager {
maybe_loyalty_program?: LoyaltyProgram;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/billing/active_subscriptions`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/billing/active_subscriptions`;
return await this.get<{
success: boolean;
active_subscriptions?: Subscription[];
-91
View File
@@ -1,91 +0,0 @@
// import { ApiManager, ApiResponse } from "../apis/ApiManager";
// export class CommentsApi extends ApiManager {
// public CreateComment({
// commentMarkdown,
// entityToken,
// entityType,
// uuidIdempotencyToken,
// }: {
// commentMarkdown: string;
// entityToken: string;
// entityType: string;
// uuidIdempotencyToken: string;
// }): Promise<ApiResponse<string>> {
// const endpoint = `${this.ApiTargets.BaseApi}/v1/comments/new`;
// const body = {
// comment_markdown: commentMarkdown,
// entity_token: entityToken,
// entity_type: entityType,
// uuid_idempotency_token: uuidIdempotencyToken,
// };
// return this.post<
// {
// comment_markdown: string;
// entity_token: string;
// entity_type: string;
// uuid_idempotency_token: string;
// },
// {
// success?: boolean;
// comment_token?: string;
// BadInput?: string;
// }
// >({ endpoint, body })
// .then((response) => ({
// success: response.success ?? false,
// data: response.comment_token,
// errorMessage: response.BadInput,
// }))
// .catch((err) => {
// return { success: false, errorMessage: err.message };
// });
// }
// public DeleteComment({
// commentToken,
// }: {
// commentToken: string;
// }): Promise<ApiResponse<undefined>> {
// const endpoint = `${this.ApiTargets.BaseApi}/v1/comments/delete/${commentToken}`;
// return this.post<
// { 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 ListCommentsByEntity({
// entityType,
// entityToken,
// }: {
// entityType: string;
// entityToken: string;
// }): Promise<ApiResponse<string[]>> {
// const endpoint = `${this.ApiTargets.BaseApi}/v1/comments/list/${entityType}/${entityToken}`;
// return this.get<{
// success: boolean;
// comments: string[];
// }>({ endpoint })
// .then((response) => ({
// success: true,
// data: response.comments,
// }))
// .catch((err) => {
// return { success: false, errorMessage: err.message };
// });
// }
// }
+5 -5
View File
@@ -8,7 +8,7 @@ export class EngineApi extends ApiManager {
mediaFileToken: string;
uuidIdempotencyToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/conversion/enqueue_fbx_to_gltf`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/conversion/enqueue_fbx_to_gltf`;
const body = {
media_file_token: mediaFileToken,
@@ -44,7 +44,7 @@ export class EngineApi extends ApiManager {
screenshot: File; // base64 encoded PNG
sceneMediaToken?: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/scene_snapshot`;
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) {
@@ -97,7 +97,7 @@ export class EngineApi extends ApiManager {
snapshotMediaToken: string;
additionalImages?: string[];
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/prompt`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/prompt`;
const uuidIdempotencyToken = crypto.randomUUID(); // Generate a new UUID
const body = {
@@ -144,7 +144,7 @@ export class EngineApi extends ApiManager {
};
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/session/${jobToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/session/${jobToken}`;
const response = await this.get<{
success?: boolean;
@@ -182,7 +182,7 @@ export class EngineApi extends ApiManager {
};
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/session_jobs/${jobToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/session_jobs/${jobToken}`;
const response = await this.get<{
success?: boolean;
@@ -1,96 +0,0 @@
// import { ApiManager, ApiResponse } from "../apis/ApiManager";
// export class FeaturedItemsApi extends ApiManager {
// public CreateFeaturedItem({
// entityToken,
// entityType,
// }: {
// entityToken: string;
// entityType: string;
// }): Promise<ApiResponse<undefined>> {
// const endpoint = `${this.ApiTargets.BaseApi}/v1/featured_item/create`;
// const body = {
// entity_token: entityToken,
// entity_type: entityType,
// };
// return this.post<
// {
// entity_token: string;
// entity_type: 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 DeleteFeaturedItem({
// entityToken,
// entityType,
// }: {
// entityToken: string;
// entityType: string;
// }): Promise<ApiResponse<undefined>> {
// const endpoint = `${this.ApiTargets.BaseApi}/v1/featured_item/delete`;
// const body = {
// entity_token: entityToken,
// entity_type: entityType,
// };
// return this.delete<
// {
// entity_token: string;
// entity_type: 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 CheckFeaturedItem({
// entityType,
// entityToken,
// }: {
// entityType: string;
// entityToken: string;
// }): Promise<ApiResponse<boolean>> {
// const endpoint = `${this.ApiTargets.BaseApi}/v1/featured_item/is_featured/${entityType}/${entityToken}`;
// return this.post<
// undefined,
// {
// success?: boolean;
// is_featured?: boolean;
// BadInput?: string;
// }
// >({ endpoint })
// .then((response) => ({
// success: response.success ?? false,
// data: response.is_featured,
// errorMessage: response.BadInput,
// }))
// .catch((err) => {
// return { success: false, errorMessage: err.message };
// });
// }
// }
+5 -5
View File
@@ -9,7 +9,7 @@ export class JobsApi extends ApiManager {
}: {
token: string;
}): Promise<ApiResponse<JobPreview>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/workflows/preview_status/${token}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/workflows/preview_status/${token}`;
return this.get<ApiResponse<JobPreview>>({ endpoint })
.then((response) => ({
@@ -26,7 +26,7 @@ export class JobsApi extends ApiManager {
}: {
token: string;
}): Promise<ApiResponse<JobState>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/job/${token}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/job/${token}`;
return this.get<{
success: boolean;
@@ -42,7 +42,7 @@ export class JobsApi extends ApiManager {
}
public ListJobs(): Promise<ApiResponse<JobState[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/batch`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/batch`;
return this.get<{
success: boolean;
@@ -58,7 +58,7 @@ export class JobsApi extends ApiManager {
}
public ListRecentJobs(): Promise<ApiResponse<Job[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/session`;
return this.get<{
success: boolean;
@@ -75,7 +75,7 @@ export class JobsApi extends ApiManager {
}
public DeleteJobByToken(jobToken: string): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/job/${jobToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/job/${jobToken}`;
return this.delete<
undefined,
+11 -11
View File
@@ -48,7 +48,7 @@ export class MediaFilesApi extends ApiManager {
asMod?: boolean;
setDelete?: boolean;
}): Promise<ApiResponse<MediaFile>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/file/${mediaFileToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/file/${mediaFileToken}`;
const body = { as_mod: asMod, set_delete: setDelete };
return await this.delete<
@@ -78,7 +78,7 @@ export class MediaFilesApi extends ApiManager {
}: {
mediaTokens: string[];
}): Promise<ApiResponse<MediaFile[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/batch`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/batch`;
return await this.get<{
success: boolean;
@@ -99,7 +99,7 @@ export class MediaFilesApi extends ApiManager {
}: {
mediaFileToken: string;
}): Promise<ApiResponse<MediaFile>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/file/${mediaFileToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/file/${mediaFileToken}`;
return await this.get<{
success: boolean;
media_file: MediaFile;
@@ -119,7 +119,7 @@ export class MediaFilesApi extends ApiManager {
public async ListMediaFiles(
query: ListMediaQuery
): Promise<ApiResponse<MediaFile[], PaginationInfinite>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/list`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list`;
const queryWithStrings = {
...query,
filter_media_classes: query.filter_media_classes
@@ -153,7 +153,7 @@ export class MediaFilesApi extends ApiManager {
public async ListFeaturedMediaFiles(
query: ListMediaQuery
): Promise<ApiResponse<MediaFile[], PaginationInfinite>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/list_featured`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list_featured`;
const queryWithStrings = {
...query,
filter_media_classes: query.filter_media_classes
@@ -188,7 +188,7 @@ export class MediaFilesApi extends ApiManager {
query: ListUserMediaQuery
): Promise<ApiResponse<MediaFile[], Pagination>> {
const userName = query.username;
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/list/user/${userName}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/list/user/${userName}`;
const queryWithStrings = {
...query,
include_user_uploads: query.include_user_uploads,
@@ -229,7 +229,7 @@ export class MediaFilesApi extends ApiManager {
public async SearchFeaturedMediaFiles(
query: SearchFeaturedMediaQuery
): Promise<ApiResponse<MediaFile[], Pagination>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/search_featured`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/search_featured`;
const queryWithStrings = {
search_term: query.search_term,
filter_media_classes: query.filter_media_classes
@@ -261,7 +261,7 @@ export class MediaFilesApi extends ApiManager {
public async SearchUserMediaFiles(
query: SearchFeaturedMediaQuery
): Promise<ApiResponse<MediaFile[], Pagination>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/search_session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/search_session`;
const queryWithStrings = {
search_term: query.search_term,
filter_media_classes: query.filter_media_classes
@@ -297,7 +297,7 @@ export class MediaFilesApi extends ApiManager {
mediaToken: string;
name: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/rename/${mediaToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/rename/${mediaToken}`;
const body = { name };
return await this.post<
@@ -323,7 +323,7 @@ export class MediaFilesApi extends ApiManager {
mediaFileToken: string;
imageToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/cover_image/${mediaFileToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/cover_image/${mediaFileToken}`;
return await this.post<
{ cover_image_media_file_token: string },
{
@@ -350,7 +350,7 @@ export class MediaFilesApi extends ApiManager {
mediaFileToken: string;
visibility: Visibility;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/visibility/${mediaFileToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/visibility/${mediaFileToken}`;
return await this.post<
{ creator_set_visibility: string },
{
+9 -9
View File
@@ -6,7 +6,7 @@ export class MediaUploadApi extends ApiManager {
private sessionToken = "";
private async getSessionTokenForUploadStudioShot() {
const endpoint = `${this.ApiTargets.BaseApi}/v1/session_token`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/session_token`;
return await this.get<{
maybe_signed_session: string;
}>({ endpoint })
@@ -156,7 +156,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title?: string | undefined;
maybe_visibility?: Visibility | undefined;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/audio`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/audio`;
const options: Record<string, string | number | undefined> = {
maybe_title,
maybe_visibility: maybe_visibility?.toString(),
@@ -179,7 +179,7 @@ export class MediaUploadApi extends ApiManager {
maybe_visibility?: Visibility | undefined;
is_intermediate_system_file?: EIntermediateFile;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/image`;
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,
@@ -207,7 +207,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title?: string;
maybe_visibility?: Visibility;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/new_engine_asset`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_engine_asset`;
const options: Record<string, string | number | undefined> = {
engine_category,
maybe_title,
@@ -231,7 +231,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title?: string;
maybe_visibility?: Visibility;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/new_scene`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_scene`;
const options: Record<string, string | number | undefined> = {
maybe_title,
maybe_visibility: maybe_visibility?.toString(),
@@ -256,7 +256,7 @@ export class MediaUploadApi extends ApiManager {
maybe_style_name?: string;
maybe_scene_source_media_file_token?: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/new_video`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/new_video`;
const options: Record<string, string | number | undefined> = {
is_intermediate_system_file: "true",
maybe_title,
@@ -286,7 +286,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title?: string;
maybe_visibility?: Visibility;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/pmx`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/pmx`;
const options: Record<string, string | number | undefined> = {
is_intermediate_system_file: "true",
engine_category,
@@ -309,7 +309,7 @@ export class MediaUploadApi extends ApiManager {
uuid: string;
mediaToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/saved_scene/${mediaToken}`;
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 });
}
@@ -326,7 +326,7 @@ export class MediaUploadApi extends ApiManager {
maybe_title: string;
maybe_scene_source_media_file_token: string | undefined;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/media_files/upload/scene_snapshot`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/upload/scene_snapshot`;
const options: Record<string, string | number | undefined> = {
maybe_title: maybe_title,
+1 -1
View File
@@ -3,7 +3,7 @@ import { StatusAlert } from "./models/StatusAlert.js";
export class MiscApi extends ApiManager {
public GetStatusAlertCheck(): Promise<ApiResponse<StatusAlert>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/session`;
return this.get<{
success: boolean;
maybe_alert?: Omit<StatusAlert, "refresh_interval_millis">;
@@ -1,43 +0,0 @@
// import { ApiManager, ApiResponse } from "../apis/ApiManager";
// export class ModerationApi extends ApiManager {
// public async UpdateFeatureFlagsByToken({
// usernameOrToken,
// flags,
// }: {
// usernameOrToken: string;
// flags: string[];
// }): Promise<
// ApiResponse<{
// inference_job_token?: string;
// inference_job_token_type?: string;
// }>
// > {
// const endpoint = `${this.ApiTargets.BaseApi}/v1/moderation/user_feature_flags/${usernameOrToken}`;
// const body = {
// action: {
// AddFlags: {
// flags,
// },
// },
// };
// return this.post<
// { action: { AddFlags: { flags: string[] } } },
// { success?: boolean; BadInput?: string }
// >({
// endpoint,
// body: body,
// })
// .then((response) => ({
// success: response.success ?? false,
// errorMessage: response.BadInput,
// }))
// .catch((err) => ({
// success: false,
// errorMessage: err.message,
// }));
// }
// }
+5 -5
View File
@@ -15,7 +15,7 @@ export class PromptsApi extends ApiManager {
snapshotMediaToken: string;
additionalImages?: string[];
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/prompt`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/prompt`;
const uuidIdempotencyToken = crypto.randomUUID(); // Generate a new UUID
const body = {
@@ -77,7 +77,7 @@ export class PromptsApi extends ApiManager {
};
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/jobs/job/${jobToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/jobs/job/${jobToken}`;
const response = await this.get<any>({
endpoint,
@@ -141,7 +141,7 @@ export class PromptsApi extends ApiManager {
};
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/session_jobs/${jobToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/image_studio/session_jobs/${jobToken}`;
const response = await this.get<{
success?: boolean;
@@ -175,7 +175,7 @@ export class PromptsApi extends ApiManager {
}: {
token: string;
}): Promise<ApiResponse<Prompts>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/prompts/${token}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/prompts/${token}`;
return this.get<{
success: boolean;
@@ -198,7 +198,7 @@ export class PromptsApi extends ApiManager {
screenshot: File; // base64 encoded PNG
sceneMediaToken?: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/image_studio/scene_snapshot`;
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) {
+1 -1
View File
@@ -24,7 +24,7 @@ export class TtsApi extends ApiManager {
inference_job_token_type?: string;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/tts/inference`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/tts/inference`;
const body = {
...request,
@@ -61,7 +61,7 @@ export class UserBookmarksApi extends ApiManager {
user_bookmark_token?: string;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/create`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/create`;
const body = {
entity_token: entityToken,
entity_type: entityType,
@@ -97,7 +97,7 @@ export class UserBookmarksApi extends ApiManager {
}: {
entityToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/delete/${entityToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/delete/${entityToken}`;
return this.delete<
{ as_mod: boolean },
@@ -116,7 +116,7 @@ export class UserBookmarksApi extends ApiManager {
}
public ListUserBookmarks(): Promise<ApiResponse<UserBookmarkBatch[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/batch`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/batch`;
return this.get<{
success?: boolean;
@@ -145,7 +145,7 @@ export class UserBookmarksApi extends ApiManager {
ApiResponse<UserBookmarkByUser[], Pagination>
> {
const user = username;
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/list/${user}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/list/${user}`;
const query = {
sort_ascending,
@@ -184,7 +184,7 @@ export class UserBookmarksApi extends ApiManager {
entityType: string;
entityToken: string;
}): Promise<ApiResponse<UserBookmarkByEntity[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_bookmarks/list/${entityType}/${entityToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_bookmarks/list/${entityType}/${entityToken}`;
return this.get<{
success: boolean;
+3 -3
View File
@@ -8,7 +8,7 @@ export interface UserRating {
export class UserRatingApi extends ApiManager {
public ListUserRatings(): Promise<ApiResponse<UserRating[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_rating/batch`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/batch`;
return this.get<{
success?: boolean;
@@ -34,7 +34,7 @@ export class UserRatingApi extends ApiManager {
entityType: string;
ratingValue: string;
}): Promise<ApiResponse<number>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_rating/rate`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/rate`;
const body = {
entity_token: entityToken,
@@ -71,7 +71,7 @@ export class UserRatingApi extends ApiManager {
entityType: string;
entityToken: string;
}): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user_rating/view/${entityType}/${entityToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user_rating/view/${entityType}/${entityToken}`;
return this.get<{
success?: boolean;
+5 -5
View File
@@ -35,7 +35,7 @@ export class UsersApi extends ApiManager {
user?: UserInfo;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/session`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/session`;
return this.get<{
success: boolean;
logged_in: boolean;
@@ -62,7 +62,7 @@ export class UsersApi extends ApiManager {
user?: UserInfo;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/user/${username}/profile`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/user/${username}/profile`;
console.log("endpoint", endpoint);
return this.get<{
success: boolean;
@@ -91,7 +91,7 @@ export class UsersApi extends ApiManager {
password: string;
}): Promise<ApiResponse<{ signedSession?: string }>> {
console.log("Logging in with usernameOrEmail:", usernameOrEmail);
const endpoint = `${this.ApiTargets.BaseApi}/v1/login`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/login`;
const body = {
username_or_email: usernameOrEmail,
password: password,
@@ -129,7 +129,7 @@ export class UsersApi extends ApiManager {
}
public Logout(): Promise<ApiResponse<null>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/logout`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/logout`;
return this.post<null, { success: boolean; error_message?: string }>({
endpoint: endpoint,
})
@@ -155,7 +155,7 @@ export class UsersApi extends ApiManager {
password: string;
passwordConfirmation: string;
}): Promise<ApiResponse<{ signedSession?: string }>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/create_account`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/create_account`;
const body = {
email_address: email,
password,
+1 -1
View File
@@ -36,7 +36,7 @@ export class VideoApi extends ApiManager {
inference_job_token_type?: string;
}>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/workflows/enqueue_studio`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/workflows/enqueue_studio`;
const body = {
...enqueueVideo,
@@ -26,7 +26,7 @@ export class VoiceConversionApi extends ApiManager {
public ConvertVoice(
params: VoiceConversionParams,
): Promise<ApiResponse<string>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/voice_conversion/inference`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_conversion/inference`;
const body = this.parseBodyValues<
VoiceConversionParams,
@@ -20,7 +20,7 @@ export class VoiceDesignerApi extends ApiManager {
): Promise<
ApiResponse<{ inference_job_token?: string; voice_token?: string }>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/voice_designer/enqueue_tts`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_designer/enqueue_tts`;
const body = this.parseBodyValues<
VoiceDesignerParams,
@@ -59,7 +59,7 @@ export class VoiceDesignerApi extends ApiManager {
username: string;
}): Promise<ApiResponse<ZsDataset[]>> {
const user = username;
const endpoint = `${this.ApiTargets.BaseApi}/v1/voice_designer/user/${user}/list`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/voice_designer/user/${user}/list`;
return this.get<{
success: boolean;
+9 -9
View File
@@ -95,7 +95,7 @@ export class WeightsApi extends ApiManager {
...params
}: ListWeightsByUserRequest): Promise<ApiResponse<Weight[], Pagination>> {
const user = username;
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/by_user/${user}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/by_user/${user}`;
const query = this.parseQueryValues(params);
@@ -117,7 +117,7 @@ export class WeightsApi extends ApiManager {
public ListWeights({
...params
}: ListWeightsRequest): Promise<ApiResponse<Weight[], PaginationInfinite>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/list`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list`;
const query = this.parseQueryValues(params);
@@ -141,7 +141,7 @@ export class WeightsApi extends ApiManager {
}: ListFeaturedWeightsRequest): Promise<
ApiResponse<Weight[], PaginationInfinite>
> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/list_featured`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list_featured`;
const query = this.parseQueryValues(params);
@@ -161,7 +161,7 @@ export class WeightsApi extends ApiManager {
}
public ListWeightsPinned(): Promise<ApiResponse<Weight[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/list_pinned`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/list_pinned`;
return this.get<{
success: boolean;
@@ -179,7 +179,7 @@ export class WeightsApi extends ApiManager {
public SearchWeights(
params: SearchWeightParams,
): Promise<ApiResponse<Weight[]>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/search`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/search`;
const body = this.parseBodyValues<SearchWeightParams, SearchWeightRequest>(
params,
@@ -206,7 +206,7 @@ export class WeightsApi extends ApiManager {
}: {
weightToken: string;
}): Promise<ApiResponse<Weight>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/weight/${weightToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
return this.get<GetWeightByTokenResponse>({ endpoint })
.then(({ success, ...mediaFile }) => ({
@@ -222,7 +222,7 @@ export class WeightsApi extends ApiManager {
weightToken,
...params
}: UpdateWeightByTokenParams): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/weight/${weightToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
const body = this.parseBodyValues<
Omit<UpdateWeightByTokenParams, "weightToken">,
@@ -247,7 +247,7 @@ export class WeightsApi extends ApiManager {
}: {
weightToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/weight/${weightToken}`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/weight/${weightToken}`;
const body = {
as_mod: true,
@@ -274,7 +274,7 @@ export class WeightsApi extends ApiManager {
weightToken: string;
coverImageMediaFileToken: string;
}): Promise<ApiResponse<undefined>> {
const endpoint = `${this.ApiTargets.BaseApi}/v1/weights/${weightToken}/cover_image`;
const endpoint = `${this.getApiSchemeAndHost()}/v1/weights/${weightToken}/cover_image`;
const body = {
cover_image_media_file_token: coverImageMediaFileToken,
@@ -0,0 +1,47 @@
// Artcraft / Storyteller API backend
const DEFAULT_API_HOST = "https://api.storyteller.ai";
export class StorytellerApiHostStore {
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;
public static getInstance(): StorytellerApiHostStore {
if (StorytellerApiHostStore.instance !== undefined) {
return StorytellerApiHostStore.instance;
}
const instance = new StorytellerApiHostStore(DEFAULT_API_HOST);
StorytellerApiHostStore.instance = instance;
return instance;
}
/** Get the API scheme and host. */
public getApiSchemeAndHost(): string {
return this.apiSchemeAndHost;
}
/**
* Externally update the API host.
* This is used to sync with Tauri for enabling easier development.
*/
public setApiSchemeAndHost(apiSchemeAndHost: string) {
// 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;
}
}
-3
View File
@@ -1,7 +1,4 @@
export enum API_TARGETS {
// NB: Comment this out for quick testing in development
BASE_API = "http://localhost:12345",
//BASE_API = "https://api.storyteller.ai",
GOOGLE_API = "https://storage.googleapis.com",
FUNNEL_API = "https://style.storyteller.ai",
CDN_API = "https://cdn.storyteller.ai",