diff --git a/pkg/mod/waifu_bucket.go b/pkg/mod/waifu_bucket.go new file mode 100644 index 0000000..55313ce --- /dev/null +++ b/pkg/mod/waifu_bucket.go @@ -0,0 +1,9 @@ +package mod + +type WaifuBucket struct { + // the token of the bucket + Token string `json:"token"` + + // The files contained in this bucket + Files []WaifuResponse[int] `json:"files"` +} diff --git a/pkg/mod/waifu_vault.go b/pkg/mod/waifu_vault.go index 2b787a4..3692b71 100644 --- a/pkg/mod/waifu_vault.go +++ b/pkg/mod/waifu_vault.go @@ -20,4 +20,13 @@ type Waifuvalt interface { // ModifyFile - modify an entry ModifyFile(ctx context.Context, token string, options ModifyEntryPayload) (*WaifuResponse[int], error) + + // CreateBucket - create a new bucket, buckets are bound to your IP, so you may only have one bucket per IP + CreateBucket(ctx context.Context) (*WaifuBucket, error) + + // GetBucket - Get a bucket and all the files it contains + GetBucket(ctx context.Context, token string) (*WaifuBucket, error) + + // DeleteBucket - Delete a bucket and all files it contains + DeleteBucket(ctx context.Context, token string) (bool, error) } diff --git a/pkg/mod/waifu_vault_put_opts.go b/pkg/mod/waifu_vault_put_opts.go index 2ef7cc0..672c304 100644 --- a/pkg/mod/waifu_vault_put_opts.go +++ b/pkg/mod/waifu_vault_put_opts.go @@ -29,4 +29,7 @@ type WaifuvaultPutOpts struct { // If this is true, then the file will be deleted as soon as it is accessed OneTimeDownload bool `json:"oneTimeDownload"` + + // If supplied, this file will be associated to that bucket + BucketToken string } diff --git a/pkg/waifu_vault_api.go b/pkg/waifu_vault_api.go index 450f280..40ff495 100644 --- a/pkg/waifu_vault_api.go +++ b/pkg/waifu_vault_api.go @@ -90,7 +90,7 @@ func (re *api) UploadFile(ctx context.Context, options mod.WaifuvaultPutOpts) (* "expires": options.Expires, "hide_filename": options.HideFilename, "one_time_download": options.OneTimeDownload, - }, "") + }, options.BucketToken) r, err := re.createRequest(ctx, http.MethodPut, uploadUrl, &body, writer) if err != nil { @@ -158,9 +158,6 @@ func (re *api) DeleteFile(ctx context.Context, token string) (bool, error) { if err != nil { return false, err } - if err != nil { - return false, err - } bodyBytes, err := io.ReadAll(resp.Body) bodyString := string(bodyBytes) @@ -229,6 +226,54 @@ func (re *api) ModifyFile(ctx context.Context, token string, options mod.ModifyE return getResponse[int](resp) } +func (re *api) CreateBucket(ctx context.Context) (*mod.WaifuBucket, error) { + restUrl := baseUrl + "/rest/bucket/createBucket" + r, err := re.createRequest(ctx, http.MethodGet, restUrl, nil, nil) + if err != nil { + return nil, err + } + resp, err := re.client.Do(r) + if err != nil { + return nil, err + } + return getBucketResponse(resp) +} + +func (re *api) GetBucket(ctx context.Context, token string) (*mod.WaifuBucket, error) { + restUrl := baseUrl + "/rest/bucket" + type payload struct { + BucketToken string `json:"bucket_token"` + } + jsonData, err := json.Marshal(&payload{token}) + r, err := re.createRequest(ctx, http.MethodPost, restUrl, bytes.NewBuffer(jsonData), nil) + if err != nil { + return nil, err + } + resp, err := re.client.Do(r) + if err != nil { + return nil, err + } + return getBucketResponse(resp) +} + +func (re *api) DeleteBucket(ctx context.Context, token string) (bool, error) { + deleteUrl := baseUrl + "/rest/bucket/" + token + r, err := re.createRequest(ctx, http.MethodDelete, deleteUrl, nil, nil) + if err != nil { + return false, err + } + resp, err := re.client.Do(r) + defer resp.Body.Close() + err = checkError(resp) + if err != nil { + return false, err + } + bodyBytes, err := io.ReadAll(resp.Body) + bodyString := string(bodyBytes) + + return bodyString == "true", nil +} + func getUrl(obj map[string]any, path string) string { baseRestUrl := fmt.Sprintf("%s/rest", baseUrl) if path != "" { @@ -253,19 +298,29 @@ func getUrl(obj map[string]any, path string) string { return baseRestUrl } +func getBucketResponse(response *http.Response) (*mod.WaifuBucket, error) { + return readResponse(response, mod.WaifuBucket{}) +} + func getResponse[T string | int](response *http.Response) (*mod.WaifuResponse[T], error) { + return readResponse(response, mod.WaifuResponse[T]{}) +} + +func readResponse[T any](response *http.Response, target T) (*T, error) { defer response.Body.Close() err := checkError(response) if err != nil { return nil, err } - bodyBytes, _ := io.ReadAll(response.Body) - var target = &mod.WaifuResponse[T]{} - err = json.Unmarshal(bodyBytes, target) + bodyBytes, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + err = json.Unmarshal(bodyBytes, &target) if err != nil { return nil, err } - return target, nil + return &target, nil } func checkError(response *http.Response) error { diff --git a/readme.md b/readme.md index fbfac39..7329a66 100644 --- a/readme.md +++ b/readme.md @@ -18,6 +18,9 @@ This API contains 4 interactions: 3. [Delete File](#delete-file) 4. [Get File](#get-file) 5. [Modify Entry](#modify-entry) +6. [Create Bucket](#create-bucket) +7. [Get Bucket](#get-bucket) +8. [Delete Bucket](#delete-bucket) The package is namespaced to `waifuVault`, so to import it, simply: @@ -470,3 +473,112 @@ func ToPtr[T any](x T) *T { return &x } ``` + +### Create bucket + +Buckets are virtual collections that are linked to your IP and a token. When you create a bucket, you will receive a +bucket token that you can use in [Get Bucket](#get-bucket) to get all the files in that bucket + +To create a bucket, use the `CreateBucket` function. This function does not take any arguments. + +```go +package main + +import ( + "context" + "fmt" + waifuVault "github.com/waifuvault/waifuVault-go-api/pkg" + "net/http" +) + +func main() { + cx := context.Background() + api := waifuVault.NewWaifuvaltApi(http.Client{}) + resp, err := api.CreateBucket(cx) + if err != nil { + fmt.Print(err) + } + fmt.Print(resp.Token) // the bucket token +} +``` + +### Get Bucket + +To get a bucket, you must use the `GetBucket` function and supply the token. +This function takes the following options as parameters: + +| Parameter | Type | Description | Required | Extra info | +|-----------|----------|-------------------------|----------|------------| +| `token` | `string` | The token of the bucket | true | | + +This will respond with the bucket and all the files the bucket contains. + +```go +package main + +import ( + "context" + "fmt" + waifuVault "github.com/waifuvault/waifuVault-go-api/pkg" + "net/http" +) + +func main() { + cx := context.Background() + api := waifuVault.NewWaifuvaltApi(http.Client{}) + + // create the bucket + resp, err := api.CreateBucket(cx) + if err != nil { + fmt.Print(err) + } + + // get the bucket + bucket, err := api.GetBucket(cx, resp.Token) + if err != nil { + fmt.Print(err) + } + fmt.Print(bucket.Files) // all the files in the bucket +} +``` + +### Delete Bucket + +Deleting a bucket will delete the bucket and all the files it contains. + +To delete a bucket, you must call the `DeleteBucket` function with the following options as parameters: + +| Parameter | Type | Description | Required | Extra info | +|-----------|----------|-----------------------------------|----------|------------| +| `token` | `string` | The token of the bucket to delete | true | | + +> **NOTE:** `DeleteBucket` will only ever either return `true` or throw an exception if the token is invalid + +```go +package main + +import ( + "context" + "fmt" + waifuVault "github.com/waifuvault/waifuVault-go-api/pkg" + "net/http" +) + +func main() { + cx := context.Background() + api := waifuVault.NewWaifuvaltApi(http.Client{}) + + // create the bucket + resp, err := api.CreateBucket(cx) + if err != nil { + fmt.Print(err) + } + + // delete the bucket + delResp, err := api.DeleteBucket(cx, resp.Token) + if err != nil { + fmt.Print(err) + } + fmt.Print(delResp) // true +} +```