github.com/0chain/gosdk@v1.17.11/zboxcore/sdk/playlist.go (about)

     1  package sdk
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"net/http"
     7  	"net/url"
     8  	"strings"
     9  
    10  	"github.com/0chain/gosdk/core/encryption"
    11  	"github.com/0chain/gosdk/core/resty"
    12  	"github.com/0chain/gosdk/core/sys"
    13  	"github.com/0chain/gosdk/zboxcore/client"
    14  	"github.com/0chain/gosdk/zboxcore/fileref"
    15  	"github.com/0chain/gosdk/zboxcore/logger"
    16  	"github.com/0chain/gosdk/zboxcore/zboxutil"
    17  )
    18  
    19  type PlaylistFile struct {
    20  	LookupHash     string `gorm:"column:lookup_hash" json:"lookup_hash"`
    21  	Name           string `gorm:"column:name" json:"name"`
    22  	Path           string `gorm:"column:path" json:"path"`
    23  	NumBlocks      int64  `gorm:"column:num_of_blocks" json:"num_of_blocks"`
    24  	ParentPath     string `gorm:"column:parent_path" json:"parent_path"`
    25  	Size           int64  `gorm:"column:size;" json:"size"`
    26  	ActualFileSize int64
    27  	MimeType       string `gorm:"column:mimetype" json:"mimetype"`
    28  	Type           string `gorm:"column:type" json:"type"`
    29  }
    30  
    31  func GetPlaylist(ctx context.Context, alloc *Allocation, path, since string) ([]PlaylistFile, error) {
    32  
    33  	q := &url.Values{}
    34  	q.Add("path", path)
    35  	q.Add("since", since)
    36  
    37  	return getPlaylistFromBlobbers(ctx, alloc, q.Encode())
    38  }
    39  
    40  func GetPlaylistByAuthTicket(ctx context.Context, alloc *Allocation, authTicket, lookupHash, since string) ([]PlaylistFile, error) {
    41  
    42  	q := &url.Values{}
    43  	q.Add("auth_token", authTicket)
    44  	q.Add("lookup_hash", lookupHash)
    45  	q.Add("since", since)
    46  
    47  	return getPlaylistFromBlobbers(ctx, alloc, q.Encode())
    48  }
    49  
    50  func getPlaylistFromBlobbers(ctx context.Context, alloc *Allocation, query string) ([]PlaylistFile, error) {
    51  
    52  	urls := make([]string, len(alloc.Blobbers))
    53  	for i, b := range alloc.Blobbers {
    54  		sb := &strings.Builder{}
    55  		sb.WriteString(strings.TrimRight(b.Baseurl, "/"))
    56  		sb.WriteString(zboxutil.PLAYLIST_LATEST_ENDPOINT)
    57  		sb.WriteString(alloc.ID)
    58  		sb.WriteString("?")
    59  		sb.WriteString(query)
    60  
    61  		urls[i] = sb.String()
    62  	}
    63  
    64  	opts := make([]resty.Option, 0, 3)
    65  
    66  	opts = append(opts, resty.WithRetry(resty.DefaultRetry))
    67  	opts = append(opts, resty.WithRequestInterceptor(func(req *http.Request) error {
    68  		req.Header.Set("X-App-Client-ID", client.GetClientID())
    69  		req.Header.Set("X-App-Client-Key", client.GetClientPublicKey())
    70  
    71  		hash := encryption.Hash(alloc.ID)
    72  		sign, err := sys.Sign(hash, client.GetClient().SignatureScheme, client.GetClientSysKeys())
    73  		if err != nil {
    74  			return err
    75  		}
    76  
    77  		// ClientSignatureHeader represents http request header contains signature.
    78  		req.Header.Set("X-App-Client-Signature", sign)
    79  
    80  		return nil
    81  	}))
    82  
    83  	c := createPlaylistConsensus(alloc.getConsensuses())
    84  
    85  	r := resty.New(opts...).
    86  		Then(func(req *http.Request, resp *http.Response, respBody []byte, cf context.CancelFunc, err error) error {
    87  			if err != nil {
    88  				logger.Logger.Error("playlist: ", err)
    89  				return err
    90  			}
    91  
    92  			if resp != nil {
    93  				if resp.StatusCode == http.StatusOK {
    94  					if e := c.AddFiles(respBody); e != nil {
    95  						logger.Logger.Error("playlist: ", e, resp.Request.URL)
    96  					}
    97  
    98  					return nil
    99  				}
   100  
   101  				logger.Logger.Error("playlist: ", resp.Status, resp.Request.URL)
   102  				return nil
   103  
   104  			}
   105  
   106  			return nil
   107  		})
   108  
   109  	r.DoGet(ctx, urls...)
   110  
   111  	r.Wait()
   112  
   113  	return c.GetConsensusResult(), nil
   114  }
   115  
   116  func GetPlaylistFile(ctx context.Context, alloc *Allocation, path string) (*PlaylistFile, error) {
   117  	q := &url.Values{}
   118  	q.Add("lookup_hash", fileref.GetReferenceLookup(alloc.ID, path))
   119  
   120  	return getPlaylistFileFromBlobbers(ctx, alloc, q.Encode())
   121  }
   122  
   123  func GetPlaylistFileByAuthTicket(ctx context.Context, alloc *Allocation, authTicket, lookupHash string) (*PlaylistFile, error) {
   124  	q := &url.Values{}
   125  	q.Add("auth_token", authTicket)
   126  	q.Add("lookup_hash", lookupHash)
   127  
   128  	return getPlaylistFileFromBlobbers(ctx, alloc, q.Encode())
   129  }
   130  
   131  func getPlaylistFileFromBlobbers(ctx context.Context, alloc *Allocation, query string) (*PlaylistFile, error) {
   132  
   133  	urls := make([]string, len(alloc.Blobbers))
   134  	for i, b := range alloc.Blobbers {
   135  		sb := &strings.Builder{}
   136  		sb.WriteString(strings.TrimRight(b.Baseurl, "/"))
   137  		sb.WriteString(zboxutil.PLAYLIST_FILE_ENDPOINT)
   138  		sb.WriteString(alloc.ID)
   139  		sb.WriteString("?")
   140  		sb.WriteString(query)
   141  
   142  		urls[i] = sb.String()
   143  	}
   144  
   145  	opts := make([]resty.Option, 0, 3)
   146  
   147  	opts = append(opts, resty.WithRetry(resty.DefaultRetry))
   148  	opts = append(opts, resty.WithRequestInterceptor(func(req *http.Request) error {
   149  		req.Header.Set("X-App-Client-ID", client.GetClientID())
   150  		req.Header.Set("X-App-Client-Key", client.GetClientPublicKey())
   151  
   152  		hash := encryption.Hash(alloc.ID)
   153  		sign, err := sys.Sign(hash, client.GetClient().SignatureScheme, client.GetClientSysKeys())
   154  		if err != nil {
   155  			return err
   156  		}
   157  
   158  		// ClientSignatureHeader represents http request header contains signature.
   159  		req.Header.Set("X-App-Client-Signature", sign)
   160  
   161  		return nil
   162  	}))
   163  
   164  	c := createPlaylistConsensus(alloc.getConsensuses())
   165  
   166  	r := resty.New(opts...).
   167  		Then(func(req *http.Request, resp *http.Response, respBody []byte, cf context.CancelFunc, err error) error {
   168  			if err != nil {
   169  				logger.Logger.Error("playlist: ", err)
   170  				return err
   171  			}
   172  
   173  			if resp != nil {
   174  				if resp.StatusCode == http.StatusOK {
   175  					if e := c.AddFile(respBody); e != nil {
   176  						logger.Logger.Error("playlist: ", e, resp.Request.URL)
   177  					}
   178  
   179  					return nil
   180  				}
   181  
   182  				logger.Logger.Error("playlist: ", resp.Status, resp.Request.URL)
   183  				return nil
   184  
   185  			}
   186  
   187  			return nil
   188  		})
   189  
   190  	r.DoGet(ctx, urls...)
   191  
   192  	r.Wait()
   193  
   194  	files := c.GetConsensusResult()
   195  
   196  	if len(files) > 0 {
   197  		return &files[0], nil
   198  	}
   199  
   200  	return nil, errors.New("playlist: playlist file not found")
   201  }