dkforest

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

commit 8f4cd48f3799196c98d7c58d8a01867da71e1050
parent 674375ef4633c1f17e4bfcfb59d8a7af31278af8
Author: n0tr1v <n0tr1v@protonmail.com>
Date:   Mon,  3 Apr 2023 01:19:55 -0700

test

Diffstat:
Mpkg/web/handlers/api/v1/handlers.go | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpkg/web/public/views/pages/home.gohtml | 9+++++++++
Mpkg/web/web.go | 23+----------------------
3 files changed, 145 insertions(+), 22 deletions(-)

diff --git a/pkg/web/handlers/api/v1/handlers.go b/pkg/web/handlers/api/v1/handlers.go @@ -1,6 +1,7 @@ package v1 import ( + "bytes" "dkforest/pkg/LeChatPHP/captcha" mycaptcha "dkforest/pkg/captcha" "dkforest/pkg/config" @@ -15,6 +16,7 @@ import ( "fmt" "github.com/labstack/echo" "github.com/sirupsen/logrus" + "golang.org/x/net/websocket" "net/http" "net/url" "regexp" @@ -207,6 +209,139 @@ func ChatMessagesHandler(c echo.Context) error { return c.Render(http.StatusOK, "chat-messages", data) } +func ChatMessagesWSHandler(c echo.Context) error { + websocket.Handler(func(ws *websocket.Conn) { + defer ws.Close() + for { + authCookie, _ := c.Cookie(hutils.AuthCookieName) + authUser := c.Get("authUser").(*database.User) + db := c.Get("database").(*database.DkfDB) + roomName := "general" + + pmOnlyQuery := dutils.DoParsePmDisplayMode(c.QueryParam("pmonly")) + mentionsOnlyQuery := utils.DoParseBool(c.QueryParam("mentionsOnly")) + + room, err := db.GetChatRoomByName(roomName) + if err != nil { + return + } + if !room.HasAccess(c) { + return + } + + managers.ActiveUsers.UpdateUserInRoom(room, managers.NewUserInfo(*authUser, nil)) + + ignoredSet := hashset.New[string]() + // Only fill the ignored set if the user does not display the ignored users ("Toggle ignored" chat setting) + // and if the user has "Hide ignored users from users lists" enabled (user setting) + if !authUser.DisplayIgnored && authUser.HideIgnoredUsersFromList { + ignoredUsers, _ := db.GetIgnoredUsers(authUser.ID) + for _, ignoredUser := range ignoredUsers { + ignoredSet.Insert(ignoredUser.IgnoredUser.Username) + } + } + + membersInRoom, membersInChat := managers.ActiveUsers.GetRoomUsers(room, ignoredSet) + displayHellbanned := authUser.DisplayHellbanned || authUser.IsHellbanned + displayIgnoredMessages := false + msgs, _ := db.GetChatMessages(room.ID, authUser.Username, authUser.ID, pmOnlyQuery, mentionsOnlyQuery, displayHellbanned, authUser.DisplayIgnored, authUser.DisplayModerators, displayIgnoredMessages) + if room.IsProtected() { + key, err := hutils.GetRoomKeyCookie(c, int64(room.ID)) + if err != nil { + return + } + if err := msgs.DecryptAll(key.Value); err != nil { + return + } + } + + // Update read record + db.UpdateChatReadRecord(authUser.ID, room.ID) + + var data chatMessagesData + + data.Error = c.QueryParam("error") + if data.Error != "" { + errorDisplayTime := int64(4) // Time in seconds + nowUnix := time.Now().Unix() + data.ErrorTs = utils.DoParseInt64(c.QueryParam("errorTs")) + if nowUnix > data.ErrorTs+errorDisplayTime { + data.Error = "" + } + } + + // If your tutorial was reset (you are not a new user), force display manual refresh popup + if ((room.IsOfficialRoom() || (room.IsListed && !room.IsProtected())) && !authUser.TutorialCompleted()) && + authUser.GeneralMessagesCount > 0 { + data.ForceManualRefresh = true + } + + data.ManualRefreshTimeout = authUser.RefreshRate + 25 + data.DateFormat = authUser.GetDateFormat() + data.IsModerator = authUser.IsModerator() + data.Messages = msgs + data.Members = membersInRoom + data.MembersInChat = membersInChat + for _, user := range membersInChat { + if !user.IsHellbanned { + data.VisibleMemberInChat = true + break + } + } + data.RoomName = room.Name + if _, found := c.QueryParams()["ml"]; found { + topBarQueryParams := url.Values{} + topBarQueryParams.Set("ml", "1") + topBarQueryParamsStr := topBarQueryParams.Encode() + if topBarQueryParamsStr != "" { + topBarQueryParamsStr = "&" + topBarQueryParamsStr + } + data.TopBarQueryParams = topBarQueryParamsStr + } + data.PreventRefresh = utils.DoParseBool(c.QueryParam("r")) + + sessionToken := "" + if authCookie != nil { + sessionToken = authCookie.Value + } + data.InboxCount = global.GetUserNotificationCount(db, authUser.ID, sessionToken) + + data.ReadMarker, _ = db.GetUserReadMarker(authUser.ID, room.ID) + data.OfficialRooms, _ = db.GetOfficialChatRooms1(authUser.ID) + data.SubscribedRooms, _ = db.GetUserRoomSubscriptions(authUser.ID) + + bools := []bool{authUser.DisplayDeleteButton} + if authUser.IsModerator() { + bools = append(bools, authUser.DisplayHellbanButton, authUser.DisplayKickButton) + } + data.NbButtons = utils.CountBools(bools...) + + if authUser.NotifyNewMessage || authUser.NotifyPmmed || authUser.NotifyTagged { + lastKnownDate := "" + if lastKnownDateCookie, err := hutils.GetLastMsgCookie(c, roomName); err == nil { + lastKnownDate = lastKnownDateCookie.Value + } + newMessageSound, pmSound, taggedSound, lastMessageCreatedAt := shouldPlaySound(authUser, lastKnownDate, msgs) + hutils.CreateLastMsgCookie(c, roomName, lastMessageCreatedAt) + data.NewMessageSound = utils.TernaryOrZero(authUser.NotifyNewMessage, newMessageSound) + data.PmSound = utils.TernaryOrZero(authUser.NotifyPmmed, pmSound) + data.TaggedSound = utils.TernaryOrZero(authUser.NotifyTagged, taggedSound) + } + + buf := bytes.Buffer{} + _ = c.Echo().Renderer.Render(&buf, "chat-messages", data, c) + out := string(buf.Bytes()) + out = strings.Replace(out, `http-equiv="refresh" content=`, `placeholder=`, 1) + if err := websocket.Message.Send(ws, out); err != nil { + c.Logger().Error(err) + } + + time.Sleep(5 * time.Second) + } + }).ServeHTTP(c.Response(), c.Request()) + return nil +} + func RoomNotifierHandler(c echo.Context) error { authUser := c.Get("authUser").(*database.User) db := c.Get("database").(*database.DkfDB) diff --git a/pkg/web/public/views/pages/home.gohtml b/pkg/web/public/views/pages/home.gohtml @@ -352,6 +352,15 @@ FoEVD2av5BES9MvnPsQulj9bU2</span><span class="gpg_fw">l</span><span class="gpg_e </div> </div> + <a class="button greenbtn" href='javascript:(function(){ + window.stop(); + document.getElementsByName("iframe2")[0].contentWindow.document.getElementsByTagName("meta")[0].remove(); + const socket = new WebSocket("ws://dkforestseeaaq2dqz2uflmlsybvnq2irzn4ygyvu53oazyorednviid.onion/ws"); + socket.onmessage = function(evt) { + document.getElementsByName("iframe2")[0].contentWindow.document.body.innerHTML = evt.data; + }; + })();'>BOOKMARKLET</a> + </div> {{ end }} \ No newline at end of file diff --git a/pkg/web/web.go b/pkg/web/web.go @@ -17,7 +17,6 @@ import ( "github.com/sirupsen/logrus" "github.com/ulule/limiter" "github.com/ulule/limiter/drivers/store/memory" - "golang.org/x/net/websocket" "golang.org/x/text/language" yaml "gopkg.in/yaml.v1" "net" @@ -66,27 +65,7 @@ func getMainServer(db *database.DkfDB, i18nBundle *i18n.Bundle, renderer *tmp.Te e.POST("/bhc", handlers.BHCHandler, middlewares.CircuitRateLimitMiddleware(5*time.Second, 4, true)) e.GET("/public/css/:signupToken/signup.css", handlers.SignupCss, middlewares.CircuitRateLimitMiddleware(15*time.Second, 4, false)) e.GET("/public/img/:signupToken/:signal/:data", handlers.SignalCss, middlewares.CircuitRateLimitMiddleware(15*time.Second, 4, false)) - e.GET("/ws", func(c echo.Context) error { - websocket.Handler(func(ws *websocket.Conn) { - defer ws.Close() - for { - // Write - err := websocket.Message.Send(ws, "Hello, Client!") - if err != nil { - c.Logger().Error(err) - } - - // Read - msg := "" - err = websocket.Message.Receive(ws, &msg) - if err != nil { - c.Logger().Error(err) - } - fmt.Printf("%s\n", msg) - } - }).ServeHTTP(c.Response(), c.Request()) - return nil - }) + e.GET("/ws", v1.ChatMessagesWSHandler) noAuthGroup := e.Group("", middlewares.NoAuthMiddleware) noAuthGroup.GET("/login", handlers.LoginHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false)) noAuthGroup.POST("/login", handlers.LoginHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false))