This commit is contained in:
matu6968 2024-11-21 00:45:22 +01:00
commit 7be58a8f12
3 changed files with 323 additions and 0 deletions

16
LICENSE Normal file
View 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
View 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
View 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
}