pls pull #1
					 10 changed files with 250 additions and 19 deletions
				
			
		
							
								
								
									
										56
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										56
									
								
								README.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1 +1,55 @@
 | 
			
		|||
# go-tsviewer
 | 
			
		||||
# go-tsviewer **[WIP]**
 | 
			
		||||
## **WARNING** This API is not usable ATM
 | 
			
		||||
 | 
			
		||||
A REST API made for TS3 Viewer.
 | 
			
		||||
 | 
			
		||||
# Features
 | 
			
		||||
## Config
 | 
			
		||||
The config file is generated automatically on first startup.
 | 
			
		||||
```json
 | 
			
		||||
{
 | 
			
		||||
    "ip": "127.0.0.1",              // Server IP
 | 
			
		||||
    "port": 10011,                  // Dataquery Port
 | 
			
		||||
    "user": {
 | 
			
		||||
        "name": "serveradmin",      // Username
 | 
			
		||||
        "password": ""              // Password
 | 
			
		||||
    },
 | 
			
		||||
    "server": {
 | 
			
		||||
        "port": 9987                // Port of the target server
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
## URL-Parameter
 | 
			
		||||
| Name       | Type     | Description              |
 | 
			
		||||
| ---------- | -------- | ------------------------ |
 | 
			
		||||
| `pretty`   | `bool`   | pretty-prints JSON       |
 | 
			
		||||
| `envelope` | `bool`   | wraps JSON in data array |
 | 
			
		||||
## Channels
 | 
			
		||||
- **`GET`** `/v1/channels/:id`
 | 
			
		||||
- **`GET`** `/v1/channels`
 | 
			
		||||
```json
 | 
			
		||||
A channel object in JSON
 | 
			
		||||
{
 | 
			
		||||
    "id": 1,
 | 
			
		||||
    "databaseId": 1,
 | 
			
		||||
    "nickname": "serveradmin from 127.0.0.1:58359",
 | 
			
		||||
    "type": 1,
 | 
			
		||||
    "away": false,
 | 
			
		||||
    "awayMessage": ""
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
## Clients
 | 
			
		||||
- **`GET`** `/v1/clients/:id`
 | 
			
		||||
- **`GET`** `/v1/clients/`
 | 
			
		||||
```json
 | 
			
		||||
A client object in JSON
 | 
			
		||||
{
 | 
			
		||||
    "id": 1,
 | 
			
		||||
    "subchannels": [
 | 
			
		||||
        ... (contains all subchannel)
 | 
			
		||||
    ],
 | 
			
		||||
    "name": "main1",
 | 
			
		||||
    "totalClients": 0,
 | 
			
		||||
    "neededSubscribePower": 0
 | 
			
		||||
},
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,9 +8,10 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
type Config struct {
 | 
			
		||||
	IP   string `json:"ip"`
 | 
			
		||||
	Port uint16 `json:"port"`
 | 
			
		||||
	User User   `json:"user"`
 | 
			
		||||
	IP     string `json:"ip"`
 | 
			
		||||
	Port   uint16 `json:"port"`
 | 
			
		||||
	User   User   `json:"user"`
 | 
			
		||||
	Server Server `json:"server"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type User struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +19,10 @@ type User struct {
 | 
			
		|||
	Password string `json:"password"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Server struct {
 | 
			
		||||
	Port uint16 `json:"port"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const FileName = "config.json"
 | 
			
		||||
 | 
			
		||||
func New() (*Config, error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -25,9 +30,7 @@ func New() (*Config, error) {
 | 
			
		|||
 | 
			
		||||
	configFile, err := os.Open(FileName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Println("Made it")
 | 
			
		||||
		if err := config.createFile(); err != nil {
 | 
			
		||||
			log.Println("WUT?")
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -59,5 +62,8 @@ func defaults() Config {
 | 
			
		|||
			Name:     "serveradmin",
 | 
			
		||||
			Password: "",
 | 
			
		||||
		},
 | 
			
		||||
		Server: Server{
 | 
			
		||||
			Port: 9987,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@ type Service interface {
 | 
			
		|||
 | 
			
		||||
type Channel struct {
 | 
			
		||||
	ID                   int       `json:"id"`
 | 
			
		||||
	Subchannels          []Channel `json:"subchannel"`
 | 
			
		||||
	Subchannels          []Channel `json:"subchannels,omitempty"`
 | 
			
		||||
	Name                 string    `json:"name"`
 | 
			
		||||
	TotalClients         int       `json:"totalClients"`
 | 
			
		||||
	NeededSubscribePower int       `json:"neededSubscribePower"`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										15
									
								
								features/client/client.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								features/client/client.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
package client
 | 
			
		||||
 | 
			
		||||
type Service interface {
 | 
			
		||||
	Client(id int) (*Client, error)
 | 
			
		||||
	Clients() ([]*Client, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Client struct {
 | 
			
		||||
	ID          int    `json:"id"`
 | 
			
		||||
	DatabaseID  int    `json:"databaseId"`
 | 
			
		||||
	Nickname    string `json:"nickname"`
 | 
			
		||||
	Type        int    `json:"type"`
 | 
			
		||||
	Away        bool   `json:"away"`
 | 
			
		||||
	AwayMessage string `json:"awayMessage"`
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								features/client/handler.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								features/client/handler.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"git.cliffbreak.de/haveachin/go-tsviewer/response"
 | 
			
		||||
	"github.com/go-chi/chi"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ClientHandler(s Service) http.HandlerFunc {
 | 
			
		||||
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		response.Handler(w, response.HandlerFunc(func() (int, error) {
 | 
			
		||||
			id, err := strconv.ParseUint(chi.URLParam(r, "id"), 10, 64)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return http.StatusBadRequest, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			c, err := s.Client(int(id))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return http.StatusNotFound, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return response.New(c, r).Send(w, http.StatusOK)
 | 
			
		||||
		}))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ClientsHandler(s Service) http.HandlerFunc {
 | 
			
		||||
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		response.Handler(w, response.HandlerFunc(func() (int, error) {
 | 
			
		||||
			cc, err := s.Clients()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return http.StatusBadRequest, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return response.New(cc, r).Send(w, http.StatusOK)
 | 
			
		||||
		}))
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								features/client/routes.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								features/client/routes.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
package client
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/go-chi/chi"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Routes(s Service) *chi.Mux {
 | 
			
		||||
	router := chi.NewRouter()
 | 
			
		||||
 | 
			
		||||
	router.Get("/{id}", ClientHandler(s))
 | 
			
		||||
	router.Get("/", ClientsHandler(s))
 | 
			
		||||
 | 
			
		||||
	return router
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								main.go
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"git.cliffbreak.de/haveachin/go-tsviewer/config"
 | 
			
		||||
	"git.cliffbreak.de/haveachin/go-tsviewer/features/channel"
 | 
			
		||||
	"git.cliffbreak.de/haveachin/go-tsviewer/features/client"
 | 
			
		||||
	"git.cliffbreak.de/haveachin/go-tsviewer/service"
 | 
			
		||||
	"github.com/go-chi/chi"
 | 
			
		||||
	"github.com/go-chi/chi/middleware"
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +25,7 @@ func Routes(s service.Service) *chi.Mux {
 | 
			
		|||
 | 
			
		||||
	router.Route("/v1", func(r chi.Router) {
 | 
			
		||||
		r.Mount("/channels", channel.Routes(s))
 | 
			
		||||
		r.Mount("/clients", client.Routes(s))
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return router
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +41,7 @@ func main() {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer service.Client.Close()
 | 
			
		||||
	defer service.TSClient.Close()
 | 
			
		||||
 | 
			
		||||
	router := Routes(*service)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,24 +1,64 @@
 | 
			
		|||
package service
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"git.cliffbreak.de/haveachin/go-tsviewer/features/channel"
 | 
			
		||||
	"github.com/multiplay/go-ts3"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (s Service) Channel(id int) (*channel.Channel, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s Service) Channels() ([]*channel.Channel, error) {
 | 
			
		||||
	cc, err := s.Client.Server.ClientList()
 | 
			
		||||
	channels, err := s.TSClient.Server.ChannelList()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, c := range cc {
 | 
			
		||||
		log.Println(*c)
 | 
			
		||||
	var c *channel.Channel
 | 
			
		||||
 | 
			
		||||
	for _, channel := range channels {
 | 
			
		||||
		if channel.ID == id {
 | 
			
		||||
			c = convertChannel(channel)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, nil
 | 
			
		||||
	if c == nil {
 | 
			
		||||
		return nil, errors.New("channel does not exist")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s Service) Channels() ([]*channel.Channel, error) {
 | 
			
		||||
	channels, err := s.TSClient.Server.ChannelList()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var cc []*channel.Channel
 | 
			
		||||
 | 
			
		||||
	for _, channel := range channels {
 | 
			
		||||
		if channel.ParentID == 0 {
 | 
			
		||||
			cc = append(cc, convertChannel(channel))
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, c := range cc {
 | 
			
		||||
			if c.ID == channel.ParentID {
 | 
			
		||||
				c.Subchannels = append(c.Subchannels, *convertChannel(channel))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cc, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertChannel(c *ts3.Channel) *channel.Channel {
 | 
			
		||||
	return &channel.Channel{
 | 
			
		||||
		ID:                   c.ID,
 | 
			
		||||
		Subchannels:          []channel.Channel{},
 | 
			
		||||
		Name:                 c.ChannelName,
 | 
			
		||||
		TotalClients:         c.TotalClients,
 | 
			
		||||
		NeededSubscribePower: c.NeededSubscribePower,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										56
									
								
								service/client.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								service/client.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
package service
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
 | 
			
		||||
	"git.cliffbreak.de/haveachin/go-tsviewer/features/client"
 | 
			
		||||
	"github.com/multiplay/go-ts3"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (s Service) Client(id int) (*client.Client, error) {
 | 
			
		||||
	clients, err := s.TSClient.Server.ClientList()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var c *client.Client
 | 
			
		||||
 | 
			
		||||
	for _, client := range clients {
 | 
			
		||||
		if client.ID == id {
 | 
			
		||||
			c = convertClient(client)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c == nil {
 | 
			
		||||
		return nil, errors.New("client does not exist")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s Service) Clients() ([]*client.Client, error) {
 | 
			
		||||
	clients, err := s.TSClient.Server.ClientList()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var cc []*client.Client
 | 
			
		||||
 | 
			
		||||
	for _, client := range clients {
 | 
			
		||||
		cc = append(cc, convertClient(client))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cc, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertClient(c *ts3.OnlineClient) *client.Client {
 | 
			
		||||
	return &client.Client{
 | 
			
		||||
		ID:          c.ID,
 | 
			
		||||
		DatabaseID:  c.DatabaseID,
 | 
			
		||||
		Nickname:    c.Nickname,
 | 
			
		||||
		Type:        c.Type,
 | 
			
		||||
		Away:        c.Away,
 | 
			
		||||
		AwayMessage: c.AwayMessage,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
type Service struct {
 | 
			
		||||
	Client *ts3.Client
 | 
			
		||||
	TSClient *ts3.Client
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func New(config config.Config) (*Service, error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +27,11 @@ func New(config config.Config) (*Service, error) {
 | 
			
		|||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := client.UsePort(int(config.Server.Port)); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &Service{
 | 
			
		||||
		Client: client,
 | 
			
		||||
		TSClient: client,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue