init
This commit is contained in:
commit
7be58a8f12
16
LICENSE
Normal file
16
LICENSE
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
Copyright 2024 matu6968
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||||
|
associated documentation files (the “Software”), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||||
|
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or
|
||||||
|
substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||||
|
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||||
|
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
85
README.md
Normal file
85
README.md
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
# WebDesk 3rd party App Market client API for Go
|
||||||
|
|
||||||
|
This allows you to make custom (known as 3rd party) App Market server clients for your intended purpose.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
- Listing currently uploaded apps
|
||||||
|
- Uploading new apps
|
||||||
|
- Editing app info
|
||||||
|
- Delete apps
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Go (1.23.1 or later, older will work with go.mod changes to the version)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Import in your Go code:
|
||||||
|
```
|
||||||
|
import (
|
||||||
|
"git.fluffy.pw/matu6968/webdesk-appmarket-golang"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
In the .env file this is the only thing you can set
|
||||||
|
|
||||||
|
```
|
||||||
|
AUTH_TOKEN=bearer-token-here # Put your token generated from the server .env file
|
||||||
|
```
|
||||||
|
# API usage
|
||||||
|
|
||||||
|
1. List uploaded apps:
|
||||||
|
|
||||||
|
```
|
||||||
|
// Create new client
|
||||||
|
c := client.NewClient("http://localhost:8080", os.Getenv("AUTH_TOKEN"))
|
||||||
|
|
||||||
|
// List all apps
|
||||||
|
apps, err := c.GetApps()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to get apps:", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Found %d apps\n", len(apps))
|
||||||
|
```
|
||||||
|
2. Upload an app:
|
||||||
|
|
||||||
|
```
|
||||||
|
// Upload new app
|
||||||
|
metadata := client.AppMetadata{
|
||||||
|
Name: "Camera",
|
||||||
|
Ver: "6",
|
||||||
|
Info: "This is a camera app",
|
||||||
|
Pub: "matu6968",
|
||||||
|
}
|
||||||
|
newApp, err := c.UploadApp(metadata, "./index.js")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to upload app:", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Uploaded app with ID: %s\n", newApp.AppID)
|
||||||
|
```
|
||||||
|
3. Edit an app:
|
||||||
|
|
||||||
|
```
|
||||||
|
// Edit app
|
||||||
|
metadata.Ver = "7" // only specify what you want to edit
|
||||||
|
metadata.Name = "Camera" // only specify what you want to edit
|
||||||
|
metadata.Info = "This is a newer camera app" // only specify what you want to edit
|
||||||
|
metadata.Pub = "matu6968" // only specify what you want to edit
|
||||||
|
err = c.EditApp(newApp.AppID, metadata, "./index.js") // replace newApp.AppID with the app id you want to delete
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to edit app:", err)
|
||||||
|
}
|
||||||
|
fmt.Println("App updated successfully")
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Delete an app:
|
||||||
|
```
|
||||||
|
// Delete app
|
||||||
|
err = c.DeleteApp(newApp.AppID) // replace newApp.AppID with the app id you want to delete
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to delete app:", err)
|
||||||
|
}
|
||||||
|
fmt.Println("App deleted successfully")
|
||||||
|
```
|
||||||
|
|
222
webdesk-appmarket-golang.go
Normal file
222
webdesk-appmarket-golang.go
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AppStoreClient struct {
|
||||||
|
BaseURL string
|
||||||
|
AuthToken string
|
||||||
|
HttpClient *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Ver string `json:"ver"`
|
||||||
|
AppID string `json:"appid"`
|
||||||
|
Info string `json:"info"`
|
||||||
|
Pub string `json:"pub"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AppMetadata struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Ver string `json:"ver"`
|
||||||
|
Info string `json:"info"`
|
||||||
|
Pub string `json:"pub"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient creates a new AppStore client
|
||||||
|
func NewClient(baseURL, authToken string) *AppStoreClient {
|
||||||
|
return &AppStoreClient{
|
||||||
|
BaseURL: baseURL,
|
||||||
|
AuthToken: authToken,
|
||||||
|
HttpClient: &http.Client{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetApps retrieves all apps from the store
|
||||||
|
func (c *AppStoreClient) GetApps() ([]App, error) {
|
||||||
|
resp, err := c.HttpClient.Get(c.BaseURL + "/apps")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var apps []App
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&apps); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return apps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadApp uploads a new app to the store
|
||||||
|
func (c *AppStoreClient) UploadApp(metadata AppMetadata, filePath string) (*App, error) {
|
||||||
|
// Create multipart form
|
||||||
|
body := &bytes.Buffer{}
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
|
||||||
|
// Add metadata
|
||||||
|
metadataBytes, err := json.Marshal(metadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := writer.WriteField("metadata", string(metadataBytes)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add file
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
part, err := writer.CreateFormFile("file", filepath.Base(filePath))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(part, file); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := writer.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create request
|
||||||
|
req, err := http.NewRequest("POST", c.BaseURL+"/uploadapp", body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
|
req.Header.Set("Authorization", "Bearer "+c.AuthToken)
|
||||||
|
|
||||||
|
// Send request
|
||||||
|
resp, err := c.HttpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var newApp App
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&newApp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &newApp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditApp updates an existing app
|
||||||
|
func (c *AppStoreClient) EditApp(appID string, metadata AppMetadata, filePath string) error {
|
||||||
|
body := &bytes.Buffer{}
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
|
||||||
|
// Add metadata
|
||||||
|
updateData := struct {
|
||||||
|
AppID string `json:"appid"`
|
||||||
|
App AppMetadata `json:"app"`
|
||||||
|
}{
|
||||||
|
AppID: appID,
|
||||||
|
App: metadata,
|
||||||
|
}
|
||||||
|
metadataBytes, err := json.Marshal(updateData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := writer.WriteField("metadata", string(metadataBytes)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add file if provided
|
||||||
|
if filePath != "" {
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
part, err := writer.CreateFormFile("file", filepath.Base(filePath))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(part, file); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := writer.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("PUT", c.BaseURL+"/editapp", body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
|
req.Header.Set("Authorization", "Bearer "+c.AuthToken)
|
||||||
|
|
||||||
|
resp, err := c.HttpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteApp removes an app from the store
|
||||||
|
func (c *AppStoreClient) DeleteApp(appID string) error {
|
||||||
|
data := struct {
|
||||||
|
AppID string `json:"appid"`
|
||||||
|
}{
|
||||||
|
AppID: appID,
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("DELETE", c.BaseURL+"/deleteapp", bytes.NewBuffer(jsonData))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("Authorization", "Bearer "+c.AuthToken)
|
||||||
|
|
||||||
|
resp, err := c.HttpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user