@@ -746,10 +746,52 @@ defmodule Algora.Accounts do
746746 Repo . all ( from m in UserMedia , where: m . user_id == ^ user . id )
747747 end
748748
749+ defp youtube_url? ( url ) do
750+ String . contains? ( url , "youtube.com" ) or String . contains? ( url , "youtu.be" )
751+ end
752+
749753 def create_user_media ( % User { } = user , attrs ) do
750- % UserMedia { }
751- |> UserMedia . changeset ( Map . put ( attrs , "user_id" , user . id ) )
752- |> Repo . insert ( )
754+ if youtube_url? ( attrs [ "url" ] ) do
755+ % UserMedia { }
756+ |> UserMedia . changeset ( Map . put ( attrs , "user_id" , user . id ) )
757+ |> Repo . insert ( )
758+ else
759+ with { :ok , % { body: body , headers: headers } } <- fetch_media ( attrs [ "url" ] ) ,
760+ object_path = media_object_path ( user . id , body ) ,
761+ { :ok , _ } <-
762+ Algora.S3 . upload ( body , object_path ,
763+ content_type: extract_content_type ( headers ) ,
764+ cache_control: "public, max-age=31536000, immutable"
765+ ) do
766+ s3_url = Path . join ( Algora.S3 . bucket_url ( ) , object_path )
767+
768+ % UserMedia { }
769+ |> UserMedia . changeset ( attrs |> Map . put ( "user_id" , user . id ) |> Map . put ( "url" , s3_url ) )
770+ |> Repo . insert ( )
771+ else
772+ error ->
773+ Logger . error ( "Failed to process media: #{ inspect ( error ) } " )
774+ { :error , :media_processing_failed }
775+ end
776+ end
777+ end
778+
779+ defp media_object_path ( user_id , body ) do
780+ hash = :md5 |> :crypto . hash ( body ) |> Base . encode16 ( case: :lower )
781+ Path . join ( [ "media" , to_string ( user_id ) , hash ] )
782+ end
783+
784+ defp fetch_media ( url ) do
785+ :get
786+ |> Finch . build ( url )
787+ |> Finch . request ( Algora.Finch )
788+ end
789+
790+ defp extract_content_type ( headers ) do
791+ case List . keyfind ( headers , "content-type" , 0 ) do
792+ { _ , content_type } -> content_type
793+ nil -> "application/octet-stream"
794+ end
753795 end
754796
755797 def delete_user_media ( % UserMedia { } = media ) do
0 commit comments