diff --git a/backend/.idea/.gitignore b/backend/.idea/.gitignore
deleted file mode 100644
index 13566b8..0000000
--- a/backend/.idea/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-# Default ignored files
-/shelf/
-/workspace.xml
-# Editor-based HTTP Client requests
-/httpRequests/
-# Datasource local storage ignored files
-/dataSources/
-/dataSources.local.xml
diff --git a/backend/.idea/discord.xml b/backend/.idea/discord.xml
new file mode 100644
index 0000000..d8e9561
--- /dev/null
+++ b/backend/.idea/discord.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/backend/.idea/workspace.xml b/backend/.idea/workspace.xml
new file mode 100644
index 0000000..9eb829d
--- /dev/null
+++ b/backend/.idea/workspace.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
\ No newline at end of file
diff --git a/backend/Dockerfile b/backend/Dockerfile
deleted file mode 100644
index e69de29..0000000
diff --git a/backend/cmd/watchtogether/main.go b/backend/cmd/watchtogether/main.go
index 42a71ce..cf31321 100644
--- a/backend/cmd/watchtogether/main.go
+++ b/backend/cmd/watchtogether/main.go
@@ -1,72 +1,41 @@
package main
import (
- "flag"
- "fmt"
- "github.com/peterbourgon/ff/v3"
- "github.com/qpixel/watchtogether/internal/logger"
- "github.com/qpixel/watchtogether/internal/server"
- "github.com/ubergeek77/tinylog"
- "os"
- "runtime"
+ "encoding/json"
+ "github.com/gorilla/mux"
+ "github.com/qpixel/watchtogether/internal/ws"
+ tlog "github.com/ubergeek77/tinylog"
+ "net/http"
)
-type flags struct {
- loglvl int
- port int
-}
-
-func newFlags(args []string) (flgs flags, err error) {
- fs := flag.NewFlagSet(args[0], flag.ContinueOnError)
-
- var (
- loglvl = fs.Int("loglvl", tinylog.TraceLevel, "sets the log level (also via LOG_LEVEL)")
- port = fs.Int("port", 4000, "sets the port to use (also via PORT)")
- )
- // Parse the command line flags from above
- err = ff.Parse(fs, args[1:], ff.WithEnvVarNoPrefix())
- if err != nil {
- return flgs, err
- }
- return flags{
- loglvl: *loglvl,
- port: *port,
- }, nil
-}
+var log = tlog.NewTaggedLogger("Logger", tlog.NewColor("38;5;111"))
func main() {
- if err := run(os.Args); err != nil {
- tinylog.DefaultLogger().Errorf("error from main.run(): %s\n", err)
- os.Exit(1)
- }
+ r := mux.NewRouter()
+ r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "application/json")
+ resp := make(map[string]string)
+ resp["status"] = "ok"
+ jsonResp, err := json.Marshal(resp)
+ if err != nil {
+ log.Fatalf("error in unmarshalling json. err: %s", err.Error())
+ }
+ _, err = w.Write(jsonResp)
+ if err != nil {
+ return
+ }
+ return
+ })
+ hub := ws.NewHub()
+ go hub.Run()
-}
+ r.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
+ ws.ServeWs(hub, w, r)
+ })
-func run(args []string) error {
-
- flgs, err := newFlags(args)
+ err := http.ListenAndServe(":8080", r)
if err != nil {
- return err
+ log.Errorf("%s", err.Error())
+ log.Fatalf("unable to serve on port 8080")
}
- // setup logger with defaults
- lgr := logger.NewLogger(flgs.loglvl, "WatchTogether")
-
- lgr.Infof("go runtime ver: %s", runtime.Version())
- lgr.Infof("Logging level has been set to %d", lgr.LogLevel)
-
- mr := server.NewMuxRouter()
-
- serverDriver := server.NewDriver()
-
- params := server.NewServerParams(lgr, serverDriver)
-
- s, err := server.NewServer(mr, params)
- if err != nil {
- lgr.Errorf("err: %s", err)
- lgr.Fatal("error in server.NewServer")
- }
-
- s.Addr = fmt.Sprintf(":%d", flgs.port)
-
- return s.ListenAndServe()
}
diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml
deleted file mode 100644
index e69de29..0000000
diff --git a/backend/go.mod b/backend/go.mod
index f9ea6d0..52d2683 100644
--- a/backend/go.mod
+++ b/backend/go.mod
@@ -2,16 +2,8 @@ module github.com/qpixel/watchtogether
go 1.17
-replace (
- github.com/qpixel/tloghttp => ../../tloghttp
- github.com/qpixel/tlogbuilder => ../../tlogbuilder
-)
-
require (
- github.com/gorilla/mux v1.8.0
- github.com/justinas/alice v1.2.0
- github.com/peterbourgon/ff/v3 v3.1.2
- github.com/qpixel/tloghttp v0.0.0-20211222065322-cd8d1a945a36
- github.com/qpixel/tlogbuilder v0.0.0
- github.com/ubergeek77/tinylog v1.0.0
+ github.com/gorilla/mux v1.8.0 // indirect
+ github.com/gorilla/websocket v1.4.2 // indirect
+ github.com/ubergeek77/tinylog v1.0.0 // indirect
)
diff --git a/backend/go.sum b/backend/go.sum
index bed6aa5..7ad59fc 100644
--- a/backend/go.sum
+++ b/backend/go.sum
@@ -1,13 +1,6 @@
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
-github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo=
-github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA=
-github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
-github.com/peterbourgon/ff/v3 v3.1.2 h1:0GNhbRhO9yHA4CC27ymskOsuRpmX0YQxwxM9UPiP6JM=
-github.com/peterbourgon/ff/v3 v3.1.2/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE=
+github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/ubergeek77/tinylog v1.0.0 h1:gsq98mbig3LDWhsizOe2tid12wHUz/mrkDlmgJ0MZG4=
github.com/ubergeek77/tinylog v1.0.0/go.mod h1:NzUi4PkRG2hACL4cGgmW7db6EaKjAeqrqlVQnJdw78Q=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/backend/internal/driver/driver.go b/backend/internal/driver/driver.go
deleted file mode 100644
index bb7e36e..0000000
--- a/backend/internal/driver/driver.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2018 The Go Cloud Development Kit Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// @gilcrest - removed TLSServer interface
-
-// Package driver defines an interface for custom HTTP listeners.
-// Application code should use package server.
-
-package driver
-
-import (
- "context"
- "net/http"
-)
-
-// Server dispatches requests to an http.Handler.
-type Server interface {
- // ListenAndServe listens on the TCP network address addr and then
- // calls Serve with handler to handle requests on incoming connections.
- // The addr argument will be a non-empty string specifying "host:port".
- // The http.Handler will always be non-nil.
- // Drivers must block until serving is done (or
- // return an error if serving can't occur for some reason), serve
- // requests to the given http.Handler, and be interruptable by Shutdown.
- // Drivers should use the given address if they serve using TCP directly.
- ListenAndServe(addr string, h http.Handler) error
-
- // Shutdown gracefully shuts down the server without interrupting
- // any active connections. If the provided context expires before
- // the shutdown is complete, Shutdown returns the context's error,
- // otherwise it returns any error returned from closing the Server's
- // underlying Listener(s).
- Shutdown(ctx context.Context) error
-}
diff --git a/backend/internal/logger/logger.go b/backend/internal/logger/logger.go
deleted file mode 100644
index b871a11..0000000
--- a/backend/internal/logger/logger.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package logger
-
-import (
- "github.com/ubergeek77/tinylog"
-)
-
-func NewLogger(lvl int, tag string) *tinylog.Logger {
- // cfg contains our custom config for tinylog
- cfg := tinylog.NewConfig()
- cfg.LogLevel = lvl
- cfg.LogPrefix = tinylog.GenerateTag(tag, tinylog.NewColor("38;5;133"), cfg)
-
- //initialize the instance of tinylog
- lgr := tinylog.NewLogger(cfg)
-
- return lgr
-}
diff --git a/backend/internal/server/middleware.go b/backend/internal/server/middleware.go
deleted file mode 100644
index 8ab4360..0000000
--- a/backend/internal/server/middleware.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package server
-
-import (
- "github.com/justinas/alice"
- "github.com/qpixel/tlogbuilder"
- "github.com/qpixel/tloghttp"
- "net/http"
- "time"
-)
-
-// MIT License
-//
-//Copyright (c) 2017 Dan Gillis
-//
-//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.
-
-// LoggerChain returns a middleware chain (via alice.Chain)
-// initialized with all the standard middleware handlers for logging. The logger
-// will be added to the request context for subsequent use with pre-populated
-// fields, including the request method, url, status, size, duration, remote IP,
-// user agent, referer. A unique Request ID is also added to the logger, context
-// and response headers.
-func (s *Server) loggerChain() alice.Chain {
- ac := alice.New(tloghttp.NewHandler(s.logger),
- tloghttp.AccessHandler(func(r *http.Request, status, size int, duration time.Duration) {
- tlogbuilder.CreateBuilder(tloghttp.FromRequest(r)).
- Info().
- Str("method", r.Method).
- Stringer("url", r.URL).
- Int("status", status).
- Int("size", size).
- Dur("duration", duration).
- Msg("request logged").
- Build()
- }),
- tloghttp.RemoteAddrHandler("remote_ip"),
- tloghttp.UserAgentHandler("user_agent"),
- tloghttp.RefererHandler("referer"),
- //tloghttp.RequestIDHandler("request_id", "Request-Id"),
- )
-
- return ac
-}
diff --git a/backend/internal/server/routes.go b/backend/internal/server/routes.go
deleted file mode 100644
index a7064d9..0000000
--- a/backend/internal/server/routes.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package server
-
-import "net/http"
-
-const (
- contentTypeHeaderKey string = "Content-Type"
- appJSONContentTypeHeaderVal string = "application/json",
-)
-
-func (s *Server) routes() {
- s.router.Handle("/", func(http.ResponseWriter, *http.Response) {
-
- })
-}
diff --git a/backend/internal/server/server.go b/backend/internal/server/server.go
deleted file mode 100644
index cb53caf..0000000
--- a/backend/internal/server/server.go
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2018 The Go Cloud Development Kit Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-// @QPixel edits - I have made a copy of the go-api-basic server code and made
-// the following changes:
-//
-// - removed zerolog dependency
-
-package server
-
-import (
- "context"
- "errors"
- "github.com/gorilla/mux"
- "github.com/qpixel/watchtogether/internal/driver"
- "github.com/ubergeek77/tinylog"
- "io"
- "net/http"
- "time"
-)
-
-const pathPrefix = "/api"
-
-// Server represents an HTTP server
-type Server struct {
- router *mux.Router
- driver driver.Server
-
- logger *tinylog.Logger
-
- Addr string
-
- // Authorization
-
- // Services
-}
-
-//type LoggerService interface {
-// Read() logger.LoggerResponse
-//
-//}
-
-// SvrParams is the set of configuration parameters for a Server
-type SvrParams struct {
- // Logger is used for the server logging
- Logger *tinylog.Logger
-
- // Driver serves HTTP requests
- Driver driver.Server
-}
-
-// NewServerParams is an initializer for ServerParams
-func NewServerParams(lgr *tinylog.Logger, d driver.Server) *SvrParams {
- options := &SvrParams{
- Logger: lgr,
- Driver: d,
- }
- return options
-}
-
-// NewServer initializes a new Server and registers
-// routes to the router mux
-// todo add error checking
-func NewServer(r *mux.Router, params *SvrParams) (*Server, error) {
- s := &Server{router: r}
- s.logger = params.Logger
- s.driver = params.Driver
-
- return s, nil
-}
-
-func (s *Server) ListenAndServe() error {
- if s.Addr == "" {
- return errors.New("server Addr is empty")
- }
- if s.router == nil {
- return errors.New("server router is nil")
- }
- if s.driver == nil {
- return errors.New("server driver is nil")
- }
- s.logger.Infof("server is listening on %s", s.Addr)
- return s.driver.ListenAndServe(s.Addr, s.router)
-}
-
-// Shutdown will gracefully shut down the server without interrupting any active connections
-func (s *Server) Shutdown(ctx context.Context) error {
- if s.driver == nil {
- return nil
- }
- return s.driver.Shutdown(ctx)
-}
-
-// Driver implements the driver.Server interface. The zero value is a valid http.Server
-type Driver struct {
- Server http.Server
-}
-
-// NewDriver intializes a Driver with http.Server using default timeouts
-func NewDriver() *Driver {
- return &Driver{
- Server: http.Server{
- ReadTimeout: 30 * time.Second,
- WriteTimeout: 30 * time.Second,
- IdleTimeout: 120 * time.Second,
- },
- }
-}
-
-// ListenAndServe sets the address and handler on Driver's http.Server
-func (d *Driver) ListenAndServe(addr string, h http.Handler) error {
- d.Server.Addr = addr
- d.Server.Handler = h
- return d.Server.ListenAndServe()
-}
-
-// Shutdown gracefully shuts down the server without interrupting any active connections,
-// by calling Shutdown on Driver's http.Server
-func (d *Driver) Shutdown(ctx context.Context) error {
- return d.Server.Shutdown(ctx)
-}
-
-// NewMuxRouter initializes a gorilla/mux router and
-// adds the /api subroute to it
-func NewMuxRouter() *mux.Router {
- // initializer gorilla/mux router
- r := mux.NewRouter()
-
- // send Router through PathPrefix method to validate any standard
- // subroutes you may want for your APIs. e.g. I always want to be
- // sure that every request has "/api" as part of its path prefix
- // without having to put it into every handle path in my various
- // routing functions
- s := r.PathPrefix(pathPrefix).Subrouter()
-
- return s
-}
-
-func decoderErr(err error) error {
- switch {
- case err == io.EOF:
- return errors.New("request body cannot be empty")
- case err == io.ErrUnexpectedEOF:
- return errors.New("malformed json")
- case err != nil:
- return err
- }
- return nil
-}
diff --git a/backend/internal/ws/client.go b/backend/internal/ws/client.go
new file mode 100644
index 0000000..c874fd0
--- /dev/null
+++ b/backend/internal/ws/client.go
@@ -0,0 +1,129 @@
+package ws
+
+import (
+ "bytes"
+ "github.com/gorilla/websocket"
+ "net/http"
+ "time"
+)
+
+const (
+ // time allowed to write a message to the peer.
+ writeWait = 10 * time.Second
+
+ pongWait = 60 * time.Second
+
+ pingPeriod = (pongWait * 9) / 10
+
+ maxMessageSize = 512
+)
+
+var (
+ newline = []byte{'\n'}
+ space = []byte{' '}
+)
+
+var upgrader = websocket.Upgrader{
+ ReadBufferSize: 1024,
+ WriteBufferSize: 1024,
+}
+
+type Client struct {
+ hub *Hub
+ conn *websocket.Conn
+ send chan []byte
+}
+
+// readPump pumps messages from the websocket connection to the hub.
+//
+// The application runs readPump in a per-connection goroutine. The application
+// ensures that there is at most one reader on a connection by executing all
+// reads from this goroutine.
+func (c *Client) readPump() {
+ defer func() {
+ c.hub.unregister <- c
+ c.conn.Close()
+ }()
+ c.conn.SetReadLimit(maxMessageSize)
+ c.conn.SetReadDeadline(time.Now().Add(pongWait))
+ c.conn.SetPongHandler(func(string) error { c.conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
+ for {
+ _, message, err := c.conn.ReadMessage()
+ if err != nil {
+ if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
+ log.Infof("error: %v", err)
+ }
+ break
+ }
+ message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
+ c.hub.broadcast <- RawMessage{
+ Client: c,
+ Data: message,
+ }
+ }
+}
+
+// writePump pumps messages from the hub to the websocket connection.
+//
+// A goroutine running writePump is started for each connection. The
+// application ensures that there is at most one writer to a connection by
+// executing all writes from this goroutine.
+func (c *Client) writePump() {
+ ticker := time.NewTicker(pingPeriod)
+ defer func() {
+ ticker.Stop()
+ c.conn.Close()
+ }()
+ for {
+ select {
+ case message, ok := <-c.send:
+ c.conn.SetWriteDeadline(time.Now().Add(writeWait))
+ if !ok {
+ // The hub closed the channel.
+ c.conn.WriteMessage(websocket.CloseMessage, []byte{})
+ return
+ }
+
+ w, err := c.conn.NextWriter(websocket.TextMessage)
+ if err != nil {
+ return
+ }
+ w.Write(message)
+
+ // Add queued chat messages to the current websocket message.
+ n := len(c.send)
+ for i := 0; i < n; i++ {
+ w.Write(newline)
+ w.Write(<-c.send)
+ }
+
+ if err := w.Close(); err != nil {
+ return
+ }
+ case <-ticker.C:
+ c.conn.SetWriteDeadline(time.Now().Add(writeWait))
+ if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
+ return
+ }
+ }
+ }
+}
+
+// ServeWs handles websocket requests from the peer.
+func ServeWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
+ upgrader.CheckOrigin = func(r *http.Request) bool {
+ return true
+ }
+ conn, err := upgrader.Upgrade(w, r, nil)
+ if err != nil {
+ log.Error(err.Error())
+ return
+ }
+ client := &Client{hub: hub, conn: conn, send: make(chan []byte, 256)}
+ client.hub.register <- client
+
+ // Allow collection of memory referenced by the caller by doing all work in
+ // new goroutines.
+ go client.writePump()
+ go client.readPump()
+}
diff --git a/backend/internal/ws/handlers.go b/backend/internal/ws/handlers.go
new file mode 100644
index 0000000..0446f8b
--- /dev/null
+++ b/backend/internal/ws/handlers.go
@@ -0,0 +1,21 @@
+package ws
+
+type IdentityData struct {
+ ClientID string `json:"client_id"`
+ User User `json:"user"`
+}
+
+func handleIdentifyEvent(message *Message) {
+
+}
+
+func handlePingEvent(message *Message) {
+ m := Message{
+ message.Client,
+ MessageData{
+ Type: Pong,
+ Data: nil,
+ },
+ }
+ message.send <- m.SerializeMessage().Data
+}
diff --git a/backend/internal/ws/hub.go b/backend/internal/ws/hub.go
new file mode 100644
index 0000000..a4340e4
--- /dev/null
+++ b/backend/internal/ws/hub.go
@@ -0,0 +1,59 @@
+package ws
+
+type Hub struct {
+ // Registered clients
+ clients map[*Client]bool
+
+ // Inbound messages from the clients
+ broadcast chan RawMessage
+
+ // Register requests from the clients
+ register chan *Client
+
+ // Unregister requests from clients
+ unregister chan *Client
+}
+
+func NewHub() *Hub {
+ return &Hub{
+ broadcast: make(chan RawMessage),
+ register: make(chan *Client),
+ unregister: make(chan *Client),
+ clients: make(map[*Client]bool),
+ }
+}
+
+func (h *Hub) handleMessage(rm RawMessage) {
+ m := rm.UnSerializeData()
+ switch m.Type {
+ case Identify:
+ handleIdentifyEvent(&m)
+ case Ping:
+ handlePingEvent(&m)
+ }
+ return
+}
+
+func (h *Hub) Run() {
+ for {
+ select {
+ case client := <-h.register:
+ h.clients[client] = true
+ case client := <-h.unregister:
+ if _, ok := h.clients[client]; ok {
+ delete(h.clients, client)
+ close(client.send)
+ }
+ case message := <-h.broadcast:
+ go h.handleMessage(message)
+ //for client := range h.clients {
+ // select {
+ // case client.send <- message:
+ // default:
+ // close(client.send)
+ // delete(h.clients, client)
+ // }
+ //}
+ }
+ }
+}
diff --git a/backend/internal/ws/message.go b/backend/internal/ws/message.go
new file mode 100644
index 0000000..631ada8
--- /dev/null
+++ b/backend/internal/ws/message.go
@@ -0,0 +1,72 @@
+package ws
+
+import (
+ "encoding/json"
+ tlog "github.com/ubergeek77/tinylog"
+ "strconv"
+)
+
+var log = tlog.NewTaggedLogger("WS", tlog.NewColor("38;5;111"))
+
+type MessageTypes float64
+
+// todo rewrite to use an event handler system
+const (
+ Ping MessageTypes = iota
+ Pong
+ Identify
+ Position
+ SetPosition
+)
+
+type MessageData struct {
+ Type MessageTypes `json:"type"`
+ RawData json.RawMessage `json:"data,omitempty"`
+ Data map[string]interface{} `json:"-"`
+}
+
+type Message struct {
+ *Client
+ MessageData
+}
+
+type RawMessage struct {
+ Client *Client
+ Data []byte
+}
+
+func (rm RawMessage) UnSerializeData() Message {
+ s, _ := strconv.Unquote(string(rm.Data))
+ var md MessageData
+ if err := json.Unmarshal([]byte(s), &md); err != nil {
+ log.Errorf("error unmarshalling message, %s", err.Error())
+ }
+ if md.RawData != nil && len(md.RawData) > 0 && md.RawData[0] == '"' {
+ var s string
+ if err := json.Unmarshal(md.RawData, &s); err != nil {
+ // handle error
+ log.Errorf("error unmarshalling message, %s", err.Error())
+ }
+ md.RawData = json.RawMessage(s)
+ if err := json.Unmarshal(md.RawData, &md.Data); err != nil {
+ // handle error
+ log.Errorf("error unmarshalling message, %s", err.Error())
+ }
+ }
+
+ m := Message{
+ Client: rm.Client,
+ MessageData: md,
+ }
+ return m
+}
+
+func (m Message) SerializeMessage() RawMessage {
+ data, err := json.Marshal(m)
+ if err != nil {
+ log.Errorf("unable to marshal message, %s", err.Error())
+ }
+ return RawMessage{
+ Data: data,
+ }
+}
diff --git a/backend/internal/ws/structs.go b/backend/internal/ws/structs.go
new file mode 100644
index 0000000..f0d528f
--- /dev/null
+++ b/backend/internal/ws/structs.go
@@ -0,0 +1,7 @@
+package ws
+
+type User struct {
+ Name string `json:"name"`
+ UserID string `json:"user_id"`
+ Admin bool `json:"admin"`
+}
diff --git a/backend/services/logger.go b/backend/services/logger.go
deleted file mode 100644
index 01d39b6..0000000
--- a/backend/services/logger.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package services
-
-import "github.com/ubergeek77/tinylog"
-
-// LoggerService reads and updates the logger state
-type LoggerService struct {
- Logger tinylog.Logger
-}
-
-// NewLoggerService creates a new instance of the logging service
-func NewLoggerService(logger tinylog.Logger) *LoggerService {
- return &LoggerService{Logger: logger}
-}
diff --git a/frontend/src/interfaces/IMessage.ts b/frontend/src/interfaces/IMessage.ts
new file mode 100644
index 0000000..fe313e2
--- /dev/null
+++ b/frontend/src/interfaces/IMessage.ts
@@ -0,0 +1,14 @@
+enum MessageTypes {
+ Ping,
+ Pong,
+ Identify,
+ Position,
+ SetPosition,
+}
+
+interface IMessage {
+ Type: MessageTypes;
+ Data?: Map;
+}
+
+export default IMessage;
diff --git a/frontend/src/interfaces/IUser.ts b/frontend/src/interfaces/IUser.ts
new file mode 100644
index 0000000..cb14d08
--- /dev/null
+++ b/frontend/src/interfaces/IUser.ts
@@ -0,0 +1,5 @@
+interface IUser {
+ name: string;
+ userID: string;
+ admin: boolean;
+}
diff --git a/frontend/src/interfaces/Identity.ts b/frontend/src/interfaces/Identity.ts
new file mode 100644
index 0000000..7872158
--- /dev/null
+++ b/frontend/src/interfaces/Identity.ts
@@ -0,0 +1,4 @@
+interface IdentityData {
+ clientID: string;
+ user: IUser;
+}
diff --git a/frontend/src/pages/admin/index.tsx b/frontend/src/pages/admin/index.tsx
index 987acc0..f73548a 100644
--- a/frontend/src/pages/admin/index.tsx
+++ b/frontend/src/pages/admin/index.tsx
@@ -19,7 +19,6 @@ const AdminPage: NextPage = ({
isAdmin,
session,
}) => {
- console.log(session);
return (
<>
diff --git a/yarn-error.log b/yarn-error.log
new file mode 100644
index 0000000..0d9d9c4
--- /dev/null
+++ b/yarn-error.log
@@ -0,0 +1,36 @@
+Arguments:
+ /home/pixel/.volta/tools/image/node/16.13.2/bin/node /home/pixel/.volta/tools/image/yarn/1.22.17/bin/yarn.js add -D @types/zib
+
+PATH:
+ /home/pixel/.volta/tools/image/yarn/1.22.17/bin:/home/pixel/.volta/tools/image/node/16.13.2/bin:/home/pixel/.volta/bin:/home/pixel/.volta/bin:/home/pixel/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl
+
+Yarn version:
+ 1.22.17
+
+Node version:
+ 16.13.2
+
+Platform:
+ linux x64
+
+Trace:
+ Error: https://registry.yarnpkg.com/@types%2fzib: Not found
+ at Request.params.callback [as _callback] (/home/pixel/.volta/tools/image/yarn/1.22.17/lib/cli.js:67029:18)
+ at Request.self.callback (/home/pixel/.volta/tools/image/yarn/1.22.17/lib/cli.js:140883:22)
+ at Request.emit (node:events:390:28)
+ at Request. (/home/pixel/.volta/tools/image/yarn/1.22.17/lib/cli.js:141855:10)
+ at Request.emit (node:events:390:28)
+ at IncomingMessage. (/home/pixel/.volta/tools/image/yarn/1.22.17/lib/cli.js:141777:12)
+ at Object.onceWrapper (node:events:509:28)
+ at IncomingMessage.emit (node:events:402:35)
+ at endReadableNT (node:internal/streams/readable:1343:12)
+ at processTicksAndRejections (node:internal/process/task_queues:83:21)
+
+npm manifest:
+ No manifest
+
+yarn manifest:
+ No manifest
+
+Lockfile:
+ No lockfile