dkforest

A forum and chat platform (onion)
git clone https://git.dasho.dev/n0tr1v/dkforest.git
Log | Files | Refs | LICENSE

commit 498b2af94a7c26af859b53d8cec1af5a545a7256
parent 915c193a6a2da77805d75c6eed7fe41011294ef3
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Mon, 12 Jun 2023 01:14:32 -0700

prototype players status icon

Diffstat:
Mpkg/web/handlers/handlers.go | 85++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Mpkg/web/handlers/interceptors/chess.go | 2++
2 files changed, 73 insertions(+), 14 deletions(-)

diff --git a/pkg/web/handlers/handlers.go b/pkg/web/handlers/handlers.go @@ -4981,7 +4981,7 @@ func ChessGameFormHandler(c echo.Context) error { } func ChessGameHandler(c echo.Context) error { - debugChess := false + debugChess := true authUser := c.Get("authUser").(*database.User) key := c.Param("key") @@ -5045,10 +5045,10 @@ func ChessGameHandler(c echo.Context) error { quit := closeSignalChan(c) - if err := usersStreamsManager.Add(authUser.ID); err != nil { + if err := usersStreamsManager.Add(authUser.ID, key); err != nil { return nil } - defer usersStreamsManager.Remove(authUser.ID) + defer usersStreamsManager.Remove(authUser.ID, key) c.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTMLCharsetUTF8) c.Response().WriteHeader(http.StatusOK) @@ -5081,6 +5081,35 @@ func ChessGameHandler(c echo.Context) error { blackQueenSideRookID = "img_56" ) + go func(c echo.Context) { + p1Online := false + p2Online := false + for { + select { + case <-time.After(5 * time.Second): + case <-quit: + return + } + p1Count := usersStreamsManager.GetUserStreamsCountFor(g.Player1.ID, key) + p2Count := usersStreamsManager.GetUserStreamsCountFor(g.Player2.ID, key) + if p1Online && p1Count == 0 { + p1Online = false + send(`<style>#p1Status { background-color: darkred !important; }</style>`) + } else if !p1Online && p1Count > 0 { + p1Online = true + send(`<style>#p1Status { background-color: green !important; }</style>`) + } + if p2Online && p2Count == 0 { + p2Online = false + send(`<style>#p2Status { background-color: darkred !important; }</style>`) + } else if !p2Online && p2Count > 0 { + p2Online = true + send(`<style>#p2Status { background-color: green !important; }</style>`) + } + c.Response().Flush() + } + }(c) + i := 0 Loop: for { @@ -5211,40 +5240,68 @@ const userMaxStream = 15 var ErrTooManyStreams = errors.New("too many streams") +type UserStreamsMap map[string]int64 + +func (m *UserStreamsMap) Count() (out int64) { + for _, v := range *m { + out += v + } + return +} + // UsersStreamsManager ensure that a user doesn't have more than userMaxStream // http long polling streams open at the same time. // If the limit is reached, the pages will then refuse to load. // This is to prevent a malicious user from opening unlimited amount of streams and wasting the server resources. type UsersStreamsManager struct { sync.Mutex - m map[database.UserID]int64 + m map[database.UserID]UserStreamsMap } func NewUsersStreamsManager() *UsersStreamsManager { - return &UsersStreamsManager{m: make(map[database.UserID]int64)} + return &UsersStreamsManager{m: make(map[database.UserID]UserStreamsMap)} } -func (m *UsersStreamsManager) Add(userID database.UserID) error { +func (m *UsersStreamsManager) Add(userID database.UserID, chessKey string) error { m.Lock() defer m.Unlock() - if m.m[userID] >= userMaxStream { + tmp, found := m.m[userID] + if !found { + tmp = make(UserStreamsMap) + } + if tmp.Count() >= userMaxStream { return ErrTooManyStreams } - m.m[userID]++ + tmp[chessKey]++ + m.m[userID] = tmp return nil } -func (m *UsersStreamsManager) Remove(userID database.UserID) { +func (m *UsersStreamsManager) Remove(userID database.UserID, chessKey string) { + m.Lock() + defer m.Unlock() + if tmp, found := m.m[userID]; found { + tmp[chessKey]-- + m.m[userID] = tmp + } +} + +func (m *UsersStreamsManager) GetUserStreamsCountFor(userID database.UserID, key string) (out int64) { m.Lock() defer m.Unlock() - m.m[userID]-- + if userMap, found := m.m[userID]; found { + if nbStreams, found1 := userMap[key]; found1 { + return nbStreams + } + } + return } func (m *UsersStreamsManager) GetUsers() (out []database.UserID) { m.Lock() defer m.Unlock() - for userID, count := range m.m { - if count > 0 { + for userID, userMap := range m.m { + if userMap.Count() > 0 { out = append(out, userID) } } @@ -5360,10 +5417,10 @@ func ChatStreamMessagesHandler(c echo.Context) error { quit := closeSignalChan(c) // Keep track of users streams, so we can limit how many are open at one time per user - if err := usersStreamsManager.Add(authUser.ID); err != nil { + if err := usersStreamsManager.Add(authUser.ID, ""); err != nil { return nil } - defer usersStreamsManager.Remove(authUser.ID) + defer usersStreamsManager.Remove(authUser.ID, "") // Keep track of how many bytes we sent on the http request, so we can auto-refresh when passing a threshold bytesSent := 0 diff --git a/pkg/web/handlers/interceptors/chess.go b/pkg/web/handlers/interceptors/chess.go @@ -314,8 +314,10 @@ func (g *ChessGame) drawPlayerCard(key string, isBlack, isSpectator, isYourTurn <tr> <td style="padding: 10px 0;"> <div style="color: #eee;"> + <div id="p1Status" style="width: 18px; height: 18px; border-radius: 9px; background-color: darkred; display: inline-block;"></div> <span {{ .White.UserStyle | attr }}>@{{ .White.Username }}</span> (white) VS <span {{ .Black.UserStyle | attr }}>@{{ .Black.Username }}</span> (black) + <div id="p2Status" style="width: 18px; height: 18px; border-radius: 9px; background-color: darkred; display: inline-block;"></div> </div> </td> </tr>