From 5bbae9f4f738b1f4eb5fe6e6b8c315d11ab302ff Mon Sep 17 00:00:00 2001 From: Hendrik Schlehlein Date: Tue, 15 Jan 2019 01:46:39 +0100 Subject: [PATCH] added features --- README.md | 56 ++++++++++++++++++++++++++++++++++- config/config.go | 16 ++++++---- features/channel/channel.go | 2 +- features/client/client.go | 15 ++++++++++ features/client/handler.go | 40 +++++++++++++++++++++++++ features/client/routes.go | 14 +++++++++ main.go | 4 ++- service/channel.go | 58 +++++++++++++++++++++++++++++++------ service/client.go | 56 +++++++++++++++++++++++++++++++++++ service/service.go | 8 +++-- 10 files changed, 250 insertions(+), 19 deletions(-) create mode 100644 features/client/client.go create mode 100644 features/client/handler.go create mode 100644 features/client/routes.go create mode 100644 service/client.go diff --git a/README.md b/README.md index a2ddf14..8d75b70 100644 --- a/README.md +++ b/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 +}, +``` diff --git a/config/config.go b/config/config.go index 93e22b7..ea0acb5 100644 --- a/config/config.go +++ b/config/config.go @@ -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, + }, } } diff --git a/features/channel/channel.go b/features/channel/channel.go index daea83c..cad648b 100644 --- a/features/channel/channel.go +++ b/features/channel/channel.go @@ -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"` diff --git a/features/client/client.go b/features/client/client.go new file mode 100644 index 0000000..14f557a --- /dev/null +++ b/features/client/client.go @@ -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"` +} diff --git a/features/client/handler.go b/features/client/handler.go new file mode 100644 index 0000000..3578061 --- /dev/null +++ b/features/client/handler.go @@ -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) + })) + }) +} diff --git a/features/client/routes.go b/features/client/routes.go new file mode 100644 index 0000000..a34c596 --- /dev/null +++ b/features/client/routes.go @@ -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 +} diff --git a/main.go b/main.go index 538a51a..836267f 100644 --- a/main.go +++ b/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) diff --git a/service/channel.go b/service/channel.go index 2bc4e7a..51cf321 100644 --- a/service/channel.go +++ b/service/channel.go @@ -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, + } } diff --git a/service/client.go b/service/client.go new file mode 100644 index 0000000..79de5b9 --- /dev/null +++ b/service/client.go @@ -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, + } +} diff --git a/service/service.go b/service/service.go index 8c34632..86d4187 100644 --- a/service/service.go +++ b/service/service.go @@ -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 }