@@ -27,10 +27,17 @@ type MediaUploader struct {
2727 authType string
2828 username string
2929 headers []string
30+ trace bool
31+ }
32+
33+ type InitRequest struct {
34+ TotalBytes int64 `json:"total_bytes"`
35+ MediaType string `json:"media_type"`
36+ MediaCategory string `json:"media_category"`
3037}
3138
3239// NewMediaUploader creates a new MediaUploader
33- func NewMediaUploader (client Client , filePath string , verbose bool , authType string , username string , headers []string ) (* MediaUploader , error ) {
40+ func NewMediaUploader (client Client , filePath string , verbose , trace bool , authType string , username string , headers []string ) (* MediaUploader , error ) {
3441 fileInfo , err := os .Stat (filePath )
3542 if err != nil {
3643 return nil , fmt .Errorf ("error accessing file: %v" , err )
@@ -49,16 +56,18 @@ func NewMediaUploader(client Client, filePath string, verbose bool, authType str
4956 authType : authType ,
5057 username : username ,
5158 headers : headers ,
59+ trace : trace ,
5260 }, nil
5361}
5462
55- func NewMediaUploaderWithoutFile (client Client , verbose bool , authType string , username string , headers []string ) * MediaUploader {
63+ func NewMediaUploaderWithoutFile (client Client , verbose , trace bool , authType string , username string , headers []string ) * MediaUploader {
5664 return & MediaUploader {
5765 client : client ,
5866 verbose : verbose ,
5967 authType : authType ,
6068 username : username ,
6169 headers : headers ,
70+ trace : trace ,
6271 }
6372}
6473
@@ -69,19 +78,27 @@ func (m *MediaUploader) Init(mediaType string, mediaCategory string) error {
6978 }
7079
7180 finalUrl := MediaEndpoint +
72- "?command=INIT" +
73- "&total_bytes=" + strconv .FormatInt (m .fileSize , 10 ) +
74- "&media_type=" + mediaType +
75- "&media_category=" + mediaCategory
81+ "/initialize"
82+
83+ body := InitRequest {
84+ TotalBytes : m .fileSize ,
85+ MediaType : mediaType ,
86+ MediaCategory : mediaCategory ,
87+ }
88+ jsonData , err := json .Marshal (body )
89+ if err != nil {
90+ return fmt .Errorf ("error marshalling body: %v" , err )
91+ }
7692
7793 requestOptions := RequestOptions {
7894 Method : "POST" ,
7995 Endpoint : finalUrl ,
8096 Headers : m .headers ,
81- Data : "" ,
97+ Data : string ( jsonData ) ,
8298 AuthType : m .authType ,
8399 Username : m .username ,
84100 Verbose : m .verbose ,
101+ Trace : m .trace ,
85102 }
86103
87104 response , clientErr := m .client .SendRequest (requestOptions )
@@ -142,27 +159,27 @@ func (m *MediaUploader) Append() error {
142159 return fmt .Errorf ("error reading file: %v" , err )
143160 }
144161
162+ finalUrl := MediaEndpoint + fmt .Sprintf ("/%s/append" , m .mediaID )
163+
145164 // Prepare form fields
146165 formFields := map [string ]string {
147- "command" : "APPEND" ,
148- "media_id" : m .mediaID ,
149166 "segment_index" : strconv .Itoa (segmentIndex ),
150167 }
151168
152169 requestOptions := RequestOptions {
153170 Method : "POST" ,
154- Endpoint : MediaEndpoint ,
171+ Endpoint : finalUrl ,
155172 Headers : m .headers ,
156173 Data : "" ,
157174 AuthType : m .authType ,
158175 Username : m .username ,
159176 Verbose : m .verbose ,
177+ Trace : m .trace ,
160178 }
161179 multipartOptions := MultipartOptions {
162180 RequestOptions : requestOptions ,
163181 FormFields : formFields ,
164182 FileField : "media" ,
165- FilePath : m .filePath ,
166183 FileName : filepath .Base (m .filePath ),
167184 FileData : buffer [:bytesRead ],
168185 }
@@ -199,7 +216,7 @@ func (m *MediaUploader) Finalize() (json.RawMessage, error) {
199216 fmt .Printf ("\033 [32mFinalizing media upload...\033 [0m\n " )
200217 }
201218
202- finalUrl := MediaEndpoint + "?command=FINALIZE&media_id=" + m .mediaID
219+ finalUrl := MediaEndpoint + fmt . Sprintf ( "/%s/finalize" , m .mediaID )
203220 requestOptions := RequestOptions {
204221 Method : "POST" ,
205222 Endpoint : finalUrl ,
@@ -208,6 +225,7 @@ func (m *MediaUploader) Finalize() (json.RawMessage, error) {
208225 AuthType : m .authType ,
209226 Username : m .username ,
210227 Verbose : m .verbose ,
228+ Trace : m .trace ,
211229 }
212230 response , clientErr := m .client .SendRequest (requestOptions )
213231 if clientErr != nil {
@@ -237,6 +255,7 @@ func (m *MediaUploader) CheckStatus() (json.RawMessage, error) {
237255 AuthType : m .authType ,
238256 Username : m .username ,
239257 Verbose : m .verbose ,
258+ Trace : m .trace ,
240259 }
241260 response , clientErr := m .client .SendRequest (requestOptions )
242261 if clientErr != nil {
@@ -316,8 +335,8 @@ func (m *MediaUploader) SetMediaID(mediaID string) {
316335}
317336
318337// ExecuteMediaUpload handles the media upload command execution
319- func ExecuteMediaUpload (filePath , mediaType , mediaCategory , authType , username string , verbose , waitForProcessing bool , headers []string , client Client ) error {
320- uploader , err := NewMediaUploader (client , filePath , verbose , authType , username , headers )
338+ func ExecuteMediaUpload (filePath , mediaType , mediaCategory , authType , username string , verbose , waitForProcessing , trace bool , headers []string , client Client ) error {
339+ uploader , err := NewMediaUploader (client , filePath , verbose , trace , authType , username , headers )
321340 if err != nil {
322341 return fmt .Errorf ("error: %v" , err )
323342 }
@@ -352,8 +371,8 @@ func ExecuteMediaUpload(filePath, mediaType, mediaCategory, authType, username s
352371}
353372
354373// ExecuteMediaStatus handles the media status command execution
355- func ExecuteMediaStatus (mediaID , authType , username string , verbose , wait bool , headers []string , client Client ) error {
356- uploader := NewMediaUploaderWithoutFile (client , verbose , authType , username , headers )
374+ func ExecuteMediaStatus (mediaID , authType , username string , verbose , wait , trace bool , headers []string , client Client ) error {
375+ uploader := NewMediaUploaderWithoutFile (client , verbose , trace , authType , username , headers )
357376
358377 uploader .SetMediaID (mediaID )
359378
@@ -386,19 +405,25 @@ func ExecuteMediaStatus(mediaID, authType, username string, verbose, wait bool,
386405
387406// HandleMediaAppendRequest handles a media append request with a file
388407func HandleMediaAppendRequest (options RequestOptions , mediaFile string , client Client ) (json.RawMessage , error ) {
389- mediaID := ExtractMediaID (options .Endpoint , options .Data )
408+ // TODO: This function is in a weird state since append accepts either a multipart request or a json request
409+ // Right now, this function takes in segment_index from the json request and sends a multipart request
410+ // We should refactor this to handle both cases (by adding curl-like multipart request support)
411+ // example usage:
412+ // xurl -X POST "/2/media/upload/{id}/append" \
413+ // -H "Content-Type: multipart/form-data" \
414+ // -F "media=@/path/to/your/file.mp4" \
415+ // -F "segment_index=0"
416+ mediaID := ExtractMediaID (options .Endpoint )
390417 if mediaID == "" {
391- return nil , fmt .Errorf ("media_id is required for APPEND command " )
418+ return nil , fmt .Errorf ("media_id is required for append endpoint " )
392419 }
393420
394- segmentIndex := ExtractSegmentIndex (options .Endpoint , options . Data )
421+ segmentIndex := ExtractSegmentIndex (options .Data )
395422 if segmentIndex == "" {
396423 segmentIndex = "0"
397424 }
398425
399426 formFields := map [string ]string {
400- "command" : "APPEND" ,
401- "media_id" : mediaID ,
402427 "segment_index" : segmentIndex ,
403428 }
404429
@@ -421,62 +446,83 @@ func HandleMediaAppendRequest(options RequestOptions, mediaFile string, client C
421446}
422447
423448// ExtractMediaID extracts media_id from URL or data
424- func ExtractMediaID (url string , data string ) string {
425- if strings .Contains (url , "media_id=" ) {
426- parts := strings .Split (url , "media_id=" )
449+ func ExtractMediaID (url string ) string {
450+ if url == "" {
451+ return ""
452+ }
453+
454+ if ! strings .Contains (url , "/2/media/upload" ) {
455+ return ""
456+ }
457+
458+ if strings .HasSuffix (url , "/2/media/upload/initialize" ) {
459+ return ""
460+ }
461+
462+ // Extract media ID from path for append/finalize endpoints
463+ if strings .Contains (url , "/2/media/upload/" ) {
464+ parts := strings .Split (url , "/2/media/upload/" )
427465 if len (parts ) > 1 {
428- mediaID := parts [1 ]
429- if idx := strings .Index (mediaID , "&" ); idx != - 1 {
430- mediaID = mediaID [:idx ]
466+ path := parts [1 ]
467+ for _ , suffix := range []string {"/append" , "/finalize" } {
468+ if idx := strings .Index (path , suffix ); idx != - 1 {
469+ return path [:idx ]
470+ }
431471 }
432- return mediaID
433472 }
434473 }
435474
436- if strings .Contains (data , "media_id=" ) {
437- parts := strings .Split (data , "media_id=" )
438- if len (parts ) > 1 {
439- mediaID := parts [1 ]
440- if idx := strings .Index (mediaID , "&" ); idx != - 1 {
441- mediaID = mediaID [:idx ]
475+ if strings .Contains (url , "?" ) {
476+ queryParams := strings .Split (url , "?" )
477+ if len (queryParams ) > 1 {
478+ params := strings .Split (queryParams [1 ], "&" )
479+ for _ , param := range params {
480+ if strings .HasPrefix (param , "media_id=" ) {
481+ return strings .Split (param , "=" )[1 ]
482+ }
442483 }
443- return mediaID
444484 }
445485 }
446486
447487 return ""
448488}
449489
450- // ExtractSegmentIndex extracts segment_index from URL or data
451- func ExtractSegmentIndex (url string , data string ) string {
452- if strings .Contains (url , "segment_index= " ) {
453- parts := strings .Split (url , "segment_index= " )
490+ // extracts command from URL
491+ func ExtractCommand (url string ) string {
492+ if strings .Contains (url , "/2/media/upload/ " ) {
493+ parts := strings .Split (url , "/2/media/upload/ " )
454494 if len (parts ) > 1 {
455- segmentIndex := parts [1 ]
456- if idx := strings .Index (segmentIndex , "&" ); idx != - 1 {
457- segmentIndex = segmentIndex [:idx ]
495+ path := parts [1 ]
496+ if strings .Contains (path , "/append" ) {
497+ return "append"
498+ }
499+ if strings .Contains (path , "/finalize" ) {
500+ return "finalize"
501+ }
502+ if path == "initialize" {
503+ return "initialize"
458504 }
459- return segmentIndex
460505 }
506+ return "status"
461507 }
462508
463- if strings .Contains (data , "segment_index=" ) {
464- parts := strings .Split (data , "segment_index=" )
465- if len (parts ) > 1 {
466- segmentIndex := parts [1 ]
467- if idx := strings .Index (segmentIndex , "&" ); idx != - 1 {
468- segmentIndex = segmentIndex [:idx ]
469- }
509+ return ""
510+ }
511+
512+ // ExtractSegmentIndex extracts segment_index from URL or data
513+ func ExtractSegmentIndex (data string ) string {
514+ var jsonData map [string ]string
515+ if err := json .Unmarshal ([]byte (data ), & jsonData ); err == nil {
516+ if segmentIndex , ok := jsonData ["segment_index" ]; ok {
470517 return segmentIndex
471518 }
472519 }
473-
474520 return ""
475521}
476522
477523// IsMediaAppendRequest checks if the request is a media append request
478524func IsMediaAppendRequest (url string , mediaFile string ) bool {
479525 return strings .Contains (url , "/2/media/upload" ) &&
480- strings .Contains (url , "command=APPEND " ) &&
526+ strings .Contains (url , "append " ) &&
481527 mediaFile != ""
482528}
0 commit comments