mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-23 18:19:30 -04:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e7ad25e9d8 | ||
|
|
bfe19076d6 | ||
|
|
d21fda4b9d | ||
|
|
8bde78d8c1 | ||
|
|
08127a4f4a |
+18
-18
@@ -124,7 +124,7 @@ mod tests {
|
||||
let links = MediaLinksBuilder::from_rooted_path_and_env(MediaDomain::FakeYou, ServerEnvironment::Production, "/foo/bar.wav");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn-2.fakeyou.com/foo/bar.wav");
|
||||
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;let links = MediaLinksBuilder::from_rooted_path_and_env(MediaDomain::Storyteller, ServerEnvironment::Development, "/foo/bar.wav");
|
||||
let links = MediaLinksBuilder::from_rooted_path_and_env(MediaDomain::Storyteller, ServerEnvironment::Development, "/foo/bar.wav");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://pub-c8a4a5bdbdb048f286b77bdf9f786ff2.r2.dev/foo/bar.wav");
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ use crate::http_server::common_responses::media::media_links_builder::MediaLinks
|
||||
#[test]
|
||||
fn wav_file() {
|
||||
let links = MediaLinksBuilder::from_rooted_path_and_env(DOMAIN, ServerEnvironment::Production, "/foo/bar.wav");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn.storyteller.ai/foo/bar.wav");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn-2.fakeyou.com/foo/bar.wav");
|
||||
assert_eq!(links.maybe_thumbnail_template, None);
|
||||
assert_eq!(links.maybe_video_previews, None);
|
||||
}
|
||||
@@ -227,7 +227,7 @@ use crate::http_server::common_responses::media::media_links_builder::MediaLinks
|
||||
#[test]
|
||||
fn glb_file() {
|
||||
let links = MediaLinksBuilder::from_rooted_path_and_env(DOMAIN, ServerEnvironment::Production, "/foo/bar.glb");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn.storyteller.ai/foo/bar.glb");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn-2.fakeyou.com/foo/bar.glb");
|
||||
assert_eq!(links.maybe_thumbnail_template, None);
|
||||
assert_eq!(links.maybe_video_previews, None);
|
||||
}
|
||||
@@ -235,21 +235,21 @@ use crate::http_server::common_responses::media::media_links_builder::MediaLinks
|
||||
#[test]
|
||||
fn jpg_image() {
|
||||
let links = MediaLinksBuilder::from_rooted_path_and_env(DOMAIN, ServerEnvironment::Production, "/foo/bar.jpg");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn.storyteller.ai/foo/bar.jpg");
|
||||
assert_eq!(links.maybe_thumbnail_template, Some("https://cdn.storyteller.ai/cdn-cgi/image/width={WIDTH},quality=95/foo/bar.jpg".to_string()));
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn-2.fakeyou.com/foo/bar.jpg");
|
||||
assert_eq!(links.maybe_thumbnail_template, Some("https://cdn-2.fakeyou.com/cdn-cgi/image/width={WIDTH},quality=95/foo/bar.jpg".to_string()));
|
||||
assert_eq!(links.maybe_video_previews, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mp4_video() {
|
||||
let links = MediaLinksBuilder::from_rooted_path_and_env(DOMAIN, ServerEnvironment::Production, "/foo/bar.mp4");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn.storyteller.ai/foo/bar.mp4");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn-2.fakeyou.com/foo/bar.mp4");
|
||||
assert_eq!(links.maybe_thumbnail_template, None);
|
||||
let video_previews = links.maybe_video_previews.expect("should have previews");
|
||||
assert_eq!(video_previews.animated.as_str(), "https://cdn.storyteller.ai/foo/bar.mp4-thumb.gif");
|
||||
assert_eq!(video_previews.still.as_str(), "https://cdn.storyteller.ai/foo/bar.mp4-thumb.jpg");
|
||||
assert_eq!(video_previews.animated_thumbnail_template, "https://cdn.storyteller.ai/cdn-cgi/image/width={WIDTH},quality=95/foo/bar.mp4-thumb.gif");
|
||||
assert_eq!(video_previews.still_thumbnail_template, "https://cdn.storyteller.ai/cdn-cgi/image/width={WIDTH},quality=95/foo/bar.mp4-thumb.jpg");
|
||||
assert_eq!(video_previews.animated.as_str(), "https://cdn-2.fakeyou.com/foo/bar.mp4-thumb.gif");
|
||||
assert_eq!(video_previews.still.as_str(), "https://cdn-2.fakeyou.com/foo/bar.mp4-thumb.jpg");
|
||||
assert_eq!(video_previews.animated_thumbnail_template, "https://cdn-2.fakeyou.com/cdn-cgi/image/width={WIDTH},quality=95/foo/bar.mp4-thumb.gif");
|
||||
assert_eq!(video_previews.still_thumbnail_template, "https://cdn-2.fakeyou.com/cdn-cgi/image/width={WIDTH},quality=95/foo/bar.mp4-thumb.jpg");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ use crate::http_server::common_responses::media::media_links_builder::MediaLinks
|
||||
// https://storage.googleapis.com/vocodes-public/media/9/4/a/2/7/94a27nmbd0bqmd10tg0pp3hz45zytf67/fakeyou_94a27nmbd0bqmd10tg0pp3hz45zytf67.wav
|
||||
let media_path = MediaFileBucketPath::from_object_hash("94a27nmbd0bqmd10tg0pp3hz45zytf67", Some("fakeyou_"), Some(".wav"));
|
||||
let links = MediaLinksBuilder::from_media_path_and_env(DOMAIN, ServerEnvironment::Production, &media_path);
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn.storyteller.ai/media/9/4/a/2/7/94a27nmbd0bqmd10tg0pp3hz45zytf67/fakeyou_94a27nmbd0bqmd10tg0pp3hz45zytf67.wav");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn-2.fakeyou.com/media/9/4/a/2/7/94a27nmbd0bqmd10tg0pp3hz45zytf67/fakeyou_94a27nmbd0bqmd10tg0pp3hz45zytf67.wav");
|
||||
assert_eq!(links.maybe_thumbnail_template, None);
|
||||
assert_eq!(links.maybe_video_previews, None);
|
||||
}
|
||||
@@ -272,8 +272,8 @@ use crate::http_server::common_responses::media::media_links_builder::MediaLinks
|
||||
/// https://storage.googleapis.com/vocodes-public/media/3/7/m/b/3/37mb3gh8fmj85y21thvbv08bzv24atjt/upload_37mb3gh8fmj85y21thvbv08bzv24atjt.png
|
||||
let media_path = MediaFileBucketPath::from_object_hash("37mb3gh8fmj85y21thvbv08bzv24atjt", Some("upload_"), Some(".png"));
|
||||
let links = MediaLinksBuilder::from_media_path_and_env(DOMAIN, ServerEnvironment::Production, &media_path);
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn.storyteller.ai/media/3/7/m/b/3/37mb3gh8fmj85y21thvbv08bzv24atjt/upload_37mb3gh8fmj85y21thvbv08bzv24atjt.png");
|
||||
assert_eq!(links.maybe_thumbnail_template, Some("https://cdn.storyteller.ai/cdn-cgi/image/width={WIDTH},quality=95/media/3/7/m/b/3/37mb3gh8fmj85y21thvbv08bzv24atjt/upload_37mb3gh8fmj85y21thvbv08bzv24atjt.png".to_string()));
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn-2.fakeyou.com/media/3/7/m/b/3/37mb3gh8fmj85y21thvbv08bzv24atjt/upload_37mb3gh8fmj85y21thvbv08bzv24atjt.png");
|
||||
assert_eq!(links.maybe_thumbnail_template, Some("https://cdn-2.fakeyou.com/cdn-cgi/image/width={WIDTH},quality=95/media/3/7/m/b/3/37mb3gh8fmj85y21thvbv08bzv24atjt/upload_37mb3gh8fmj85y21thvbv08bzv24atjt.png".to_string()));
|
||||
assert_eq!(links.maybe_video_previews, None);
|
||||
}
|
||||
|
||||
@@ -282,13 +282,13 @@ use crate::http_server::common_responses::media::media_links_builder::MediaLinks
|
||||
// https://storage.googleapis.com/vocodes-public/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4
|
||||
let media_path = MediaFileBucketPath::from_object_hash("t6cnyw4g3e8k7carkk2bvrt6nd3fycjv", Some("storyteller_"), Some(".mp4"));
|
||||
let links = MediaLinksBuilder::from_media_path_and_env(DOMAIN, ServerEnvironment::Production, &media_path);
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn.storyteller.ai/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4");
|
||||
assert_eq!(links.cdn_url.as_str(), "https://cdn-2.fakeyou.com/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4");
|
||||
assert_eq!(links.maybe_thumbnail_template, None);
|
||||
let video_previews = links.maybe_video_previews.expect("should have previews");
|
||||
assert_eq!(video_previews.animated.as_str(), "https://cdn.storyteller.ai/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4-thumb.gif");
|
||||
assert_eq!(video_previews.still.as_str(), "https://cdn.storyteller.ai/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4-thumb.jpg");
|
||||
assert_eq!(video_previews.animated_thumbnail_template, "https://cdn.storyteller.ai/cdn-cgi/image/width={WIDTH},quality=95/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4-thumb.gif");
|
||||
assert_eq!(video_previews.still_thumbnail_template, "https://cdn.storyteller.ai/cdn-cgi/image/width={WIDTH},quality=95/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4-thumb.jpg");
|
||||
assert_eq!(video_previews.animated.as_str(), "https://cdn-2.fakeyou.com/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4-thumb.gif");
|
||||
assert_eq!(video_previews.still.as_str(), "https://cdn-2.fakeyou.com/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4-thumb.jpg");
|
||||
assert_eq!(video_previews.animated_thumbnail_template, "https://cdn-2.fakeyou.com/cdn-cgi/image/width={WIDTH},quality=95/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4-thumb.gif");
|
||||
assert_eq!(video_previews.still_thumbnail_template, "https://cdn-2.fakeyou.com/cdn-cgi/image/width={WIDTH},quality=95/media/t/6/c/n/y/t6cnyw4g3e8k7carkk2bvrt6nd3fycjv/storyteller_t6cnyw4g3e8k7carkk2bvrt6nd3fycjv.mp4-thumb.jpg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-6
@@ -8,7 +8,7 @@ use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::endpoints::media_files::common_responses::live_portrait::MediaFileLivePortraitDetails;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_media_domain::get_media_domain;
|
||||
use crate::http_server::web_utils::bucket_urls::bucket_url_from_media_path::bucket_url_from_media_path;
|
||||
use crate::http_server::web_utils::bucket_urls::bucket_url_from_media_path_updated::bucket_url_from_media_path_updated;
|
||||
use crate::http_server::web_utils::bucket_urls::bucket_url_from_str_path::bucket_url_from_str_path;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -366,11 +366,7 @@ async fn modern_media_file_lookup(
|
||||
maybe_batch_token: result.maybe_batch_token,
|
||||
maybe_scene_source_media_file_token: result.maybe_scene_source_media_file_token,
|
||||
media_links: MediaLinksBuilder::from_media_path_and_env(media_domain, server_state.server_environment, &public_bucket_path),
|
||||
public_bucket_url: bucket_url_from_media_path(&public_bucket_path)
|
||||
.map_err(|err| {
|
||||
warn!("error creating URL: {:?}", err);
|
||||
GetMediaFileError::ServerError
|
||||
})?,
|
||||
public_bucket_url: bucket_url_from_media_path_updated(media_domain, server_state.server_environment, &public_bucket_path),
|
||||
public_bucket_path: public_bucket_path
|
||||
.get_full_object_path_str()
|
||||
.to_string(),
|
||||
|
||||
+2
@@ -115,6 +115,8 @@ pub async fn fal_webhook_handler(
|
||||
) -> Result<Json<SimpleGenericJsonSuccess>, FalWebhookError> {
|
||||
|
||||
info!("Received FAL webhook body: {:?}", request);
|
||||
|
||||
println!("--------------------\nFal Result: {:?}\n--------------------", request);
|
||||
|
||||
let request_id = request.request_id
|
||||
.as_deref()
|
||||
|
||||
+36
-45
@@ -13,7 +13,6 @@ use mimetypes::mimetype_info::mimetype_info::MimetypeInfo;
|
||||
use mysql_queries::queries::generic_inference::fal::get_inference_job_by_fal_id::FalJobDetails;
|
||||
use mysql_queries::queries::media_files::create::insert_builder::media_file_insert_builder::MediaFileInsertBuilder;
|
||||
use serde_json::{Map, Value};
|
||||
use mysql_queries::queries::media_files::edit::set_media_file_cover_image::{set_media_file_cover_image, UpdateArgs};
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
const PREFIX : Option<&str> = Some("artcraft_");
|
||||
@@ -68,31 +67,37 @@ pub async fn handle_model_glb_payload(
|
||||
job: &FalJobDetails,
|
||||
server_state: &ServerState,
|
||||
) -> AnyhowResult<MediaFileToken> {
|
||||
|
||||
|
||||
// Step 1: Try to upload thumbnail first (fail open)
|
||||
let maybe_cover_token = match try_to_upload_thumbnail(payload, job, server_state).await {
|
||||
Ok(maybe_token) => maybe_token,
|
||||
Err(err) => {
|
||||
warn!("Could not upload thumbnail as cover image: {:?}. Continuing without cover.", err);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
// Step 2: Upload the GLB mesh, attaching the cover image if available
|
||||
let model_glb_value = payload.get("model_glb")
|
||||
.ok_or_else(|| anyhow!("no `model_mesh` key in payload"))?;
|
||||
.ok_or_else(|| anyhow!("no `model_glb` key in payload"))?;
|
||||
|
||||
info!("Fal Model Glb Payload: {:?}", model_glb_value);
|
||||
|
||||
|
||||
let mesh: FalMediaPayload = serde_json::from_value(model_glb_value.clone())?;
|
||||
|
||||
let mesh_url = mesh.url
|
||||
.as_deref()
|
||||
.ok_or_else(|| anyhow!("no `url` in image payload"))?;
|
||||
|
||||
//let mime_type = mesh.content_type
|
||||
// .as_deref()
|
||||
// .ok_or_else(|| anyhow!("no `content_type` in mesh payload"))?;
|
||||
.ok_or_else(|| anyhow!("no `url` in model_glb payload"))?;
|
||||
|
||||
let file_bytes = http_download_url_to_bytes(mesh_url)
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to download mesh: {:?}", e))?;
|
||||
|
||||
|
||||
let mimetype_info = MimetypeInfo::get_for_bytes(&file_bytes)
|
||||
.ok_or_else(|| anyhow!("Failed to get mimetype info"))?;
|
||||
|
||||
|
||||
let mime_type = mimetype_info.mime_type();
|
||||
|
||||
|
||||
info!("Mime type of mesh: {}", mime_type);
|
||||
|
||||
let media_file_type = MediaFileType::try_from_mime_type(mime_type)
|
||||
@@ -124,59 +129,51 @@ pub async fn handle_model_glb_payload(
|
||||
.media_file_type(media_file_type)
|
||||
.media_file_origin_category(MediaFileOriginCategory::Inference)
|
||||
.maybe_engine_category(Some(MediaFileEngineCategory::Object))
|
||||
//.media_file_origin_product_category(MediaFileOriginProductCategory::Unknown)
|
||||
.mime_type(mime_type)
|
||||
.file_size_bytes(file_size_bytes as u64)
|
||||
.maybe_prompt_token(job.maybe_prompt_token.as_ref())
|
||||
.maybe_cover_image_media_file_token(maybe_cover_token.as_ref())
|
||||
.checksum_sha2(&file_hash)
|
||||
.insert_pool(&server_state.mysql_pool)
|
||||
.await?;
|
||||
|
||||
|
||||
info!("Glb media file uploaded with token: {}", media_token);
|
||||
|
||||
let result = try_to_attach_thumbnail(
|
||||
payload,
|
||||
job,
|
||||
server_state,
|
||||
&media_token,
|
||||
).await;
|
||||
|
||||
// NB: Fail open
|
||||
if let Err(err) = result {
|
||||
warn!("Could not attach thumbnail as cover image to media file: {:?}", err);
|
||||
}
|
||||
|
||||
Ok(media_token)
|
||||
}
|
||||
|
||||
async fn try_to_attach_thumbnail(
|
||||
async fn try_to_upload_thumbnail(
|
||||
payload: &Map<String, Value>,
|
||||
job: &FalJobDetails,
|
||||
server_state: &ServerState,
|
||||
glb_media_token: &MediaFileToken,
|
||||
) -> AnyhowResult<()> {
|
||||
) -> AnyhowResult<Option<MediaFileToken>> {
|
||||
|
||||
let thumbnail_value = payload.get("thumbnail")
|
||||
.ok_or_else(|| anyhow!("no `thumbnail` key in payload"))?;
|
||||
let thumbnail_value = match payload.get("thumbnail") {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
info!("No thumbnail in payload, skipping cover image.");
|
||||
return Ok(None);
|
||||
}
|
||||
};
|
||||
|
||||
info!("Fal Thumbnail Payload: {:?}", thumbnail_value);
|
||||
|
||||
let thumbnail : FalMediaPayload = serde_json::from_value(thumbnail_value.clone())?;
|
||||
let thumbnail: FalMediaPayload = serde_json::from_value(thumbnail_value.clone())?;
|
||||
|
||||
let mesh_url = thumbnail.url
|
||||
let thumbnail_url = thumbnail.url
|
||||
.as_deref()
|
||||
.ok_or_else(|| anyhow!("no `url` in image payload"))?;
|
||||
.ok_or_else(|| anyhow!("no `url` in thumbnail payload"))?;
|
||||
|
||||
let file_bytes = http_download_url_to_bytes(mesh_url)
|
||||
let file_bytes = http_download_url_to_bytes(thumbnail_url)
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to download image: {:?}", e))?;
|
||||
.map_err(|e| anyhow!("Failed to download thumbnail: {:?}", e))?;
|
||||
|
||||
let mimetype_info = MimetypeInfo::get_for_bytes(&file_bytes)
|
||||
.ok_or_else(|| anyhow!("Failed to get mimetype info"))?;
|
||||
|
||||
let mime_type = mimetype_info.mime_type();
|
||||
|
||||
info!("Mime type of image: {}", mime_type);
|
||||
info!("Mime type of thumbnail: {}", mime_type);
|
||||
|
||||
let media_file_type = MediaFileType::try_from_mime_type(mime_type)
|
||||
.ok_or_else(|| anyhow!("Unsupported media file type: {}", mime_type))?;
|
||||
@@ -206,8 +203,6 @@ async fn try_to_attach_thumbnail(
|
||||
.media_file_class(MediaFileClass::Image)
|
||||
.media_file_type(media_file_type)
|
||||
.media_file_origin_category(MediaFileOriginCategory::Processed)
|
||||
//.maybe_engine_category(Some(MediaFileEngineCategory::Object))
|
||||
//.media_file_origin_product_category(MediaFileOriginProductCategory::Unknown)
|
||||
.mime_type(mime_type)
|
||||
.file_size_bytes(file_size_bytes as u64)
|
||||
.maybe_prompt_token(job.maybe_prompt_token.as_ref())
|
||||
@@ -216,11 +211,7 @@ async fn try_to_attach_thumbnail(
|
||||
.insert_pool(&server_state.mysql_pool)
|
||||
.await?;
|
||||
|
||||
let query_result = set_media_file_cover_image(UpdateArgs {
|
||||
media_file_token: glb_media_token,
|
||||
maybe_cover_image_media_file_token: Some(&thumbnail_media_token),
|
||||
mysql_pool: &server_state.mysql_pool,
|
||||
}).await;
|
||||
info!("Thumbnail uploaded with token: {}", thumbnail_media_token);
|
||||
|
||||
Ok(())
|
||||
Ok(Some(thumbnail_media_token))
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
use url::Url;
|
||||
|
||||
use bucket_paths::legacy::typified_paths::public::media_files::bucket_file_path::MediaFileBucketPath;
|
||||
use server_environment::ServerEnvironment;
|
||||
|
||||
use crate::http_server::common_responses::media::media_domain::MediaDomain;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
|
||||
#[deprecated(note="this is better than bucket_url_from_media_path, but still refrain from using it")]
|
||||
pub fn bucket_url_from_media_path_updated(
|
||||
media_domain: MediaDomain,
|
||||
server_environment: ServerEnvironment,
|
||||
bucket_path: &MediaFileBucketPath,
|
||||
) -> Url {
|
||||
let media_links = MediaLinksBuilder::from_media_path_and_env(media_domain, server_environment, bucket_path);
|
||||
media_links.cdn_url
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod bucket_url_from_media_path;
|
||||
pub mod bucket_url_from_media_path_updated;
|
||||
pub mod bucket_url_from_str_path;
|
||||
pub mod bucket_url_string_from_media_path;
|
||||
Reference in New Issue
Block a user