commit f31832af640dc0a28126a8e7b99c838eeeabb7c4
parent 7e53f66ebd895655618aa7c6e9fab8ee789978fc
Author: n0tr1v <n0tr1v@protonmail.com>
Date: Fri, 29 Dec 2023 17:20:50 -0500
proof of concept to have private conversation within same page as other chat
Diffstat:
9 files changed, 80 insertions(+), 18 deletions(-)
diff --git a/pkg/database/database.go b/pkg/database/database.go
@@ -100,7 +100,7 @@ type IDkfDB interface {
DoCreateSession(userID UserID, userAgent string, sessionDuration time.Duration) Session
GetActiveUserSessions(userID UserID) (out []Session)
GetCategories() (out []CategoriesResult, err error)
- GetChatMessages(roomID RoomID, roomKey string, username Username, userID UserID, displayPms PmDisplayMode, mentionsOnly, displayHellbanned, displayIgnored, displayModerators, displayIgnoredMessages bool, msgsLimit, minID1 int64) (out ChatMessages, err error)
+ GetChatMessages(roomID RoomID, roomKey string, username Username, userID UserID, pmUserID *UserID, displayPms PmDisplayMode, mentionsOnly, displayHellbanned, displayIgnored, displayModerators, displayIgnoredMessages bool, msgsLimit, minID1 int64) (out ChatMessages, err error)
GetChatRoomByID(roomID RoomID) (out ChatRoom, err error)
GetChatRoomByName(roomName string) (out ChatRoom, err error)
GetChessSubscribers() (out []User, err error)
diff --git a/pkg/database/tableChatMessages.go b/pkg/database/tableChatMessages.go
@@ -377,7 +377,7 @@ const (
)
func (d *DkfDB) GetChatMessages(roomID RoomID, roomKey string, username Username, userID UserID,
- displayPms PmDisplayMode, mentionsOnly, displayHellbanned, displayIgnored, displayModerators,
+ pmUserID *UserID, displayPms PmDisplayMode, mentionsOnly, displayHellbanned, displayIgnored, displayModerators,
displayIgnoredMessages bool, msgsLimit, minID1 int64) (out ChatMessages, err error) {
cmp := func(t, t2 ChatMessage) bool { return t.ID > t2.ID }
@@ -408,6 +408,9 @@ func (d *DkfDB) GetChatMessages(roomID RoomID, roomKey string, username Username
if mentionsOnly {
q = q.Where(`raw_message LIKE ?`, "%@"+username+"%")
}
+ if pmUserID != nil {
+ q = q.Where(`(to_user_id = ? AND user_id = ?) OR (user_id = ? AND to_user_id = ?)`, userID, pmUserID, userID, pmUserID)
+ }
switch displayPms {
case PmNoFilter: // Display all messages
q = q.Where(`to_user_id is null OR to_user_id = ? OR user_id = ?`, userID, userID)
@@ -681,6 +684,7 @@ const (
ForceRefresh
DeleteMsg
Wizz
+ Redirect
RefreshTopic string = "refresh"
)
@@ -690,6 +694,7 @@ type ChatMessageType struct {
Msg ChatMessage
IsMod bool
ToUserUsername *Username
+ NewURL string
}
var MsgPubSub = pubsub.NewPubSub[ChatMessageType]()
diff --git a/pkg/database/utils/utils.go b/pkg/database/utils/utils.go
@@ -67,6 +67,15 @@ func DoParseUsernamePtr(v string) *database.Username {
return &username
}
+func GetUserIDFromUsername(db *database.DkfDB, u string) *database.UserID {
+ username := DoParseUsernamePtr(u)
+ if username == nil {
+ return nil
+ }
+ userID, _ := db.GetUserIDByUsername(*username)
+ return &userID
+}
+
func DoParsePmDisplayMode(v string) database.PmDisplayMode {
p, err := utils.ParseInt64(v)
if err != nil {
diff --git a/pkg/web/handlers/api/v1/chat.go b/pkg/web/handlers/api/v1/chat.go
@@ -8,6 +8,7 @@ import (
"dkforest/pkg/managers"
"dkforest/pkg/pubsub"
"dkforest/pkg/utils"
+ "dkforest/pkg/web/handlers/interceptors/command"
"dkforest/pkg/web/handlers/poker"
"dkforest/pkg/web/handlers/streamModals"
"dkforest/pkg/web/handlers/utils/stream"
@@ -63,7 +64,15 @@ func manualPreload(db *database.DkfDB, msg *database.ChatMessage, room database.
// Return true if the message passes all the user's filter.
// false if the message does not and should be discarded.
func applyUserFilters(db *database.DkfDB, authUser *database.User, msg *database.ChatMessage,
- pmOnlyQuery database.PmDisplayMode, displayHellbanned, mentionsOnlyQuery bool) bool {
+ pmUserID *database.UserID, pmOnlyQuery database.PmDisplayMode, displayHellbanned, mentionsOnlyQuery bool) bool {
+ if pmUserID != nil {
+ if msg.ToUserID == nil {
+ return false
+ }
+ if *msg.ToUserID == *pmUserID || msg.UserID == *pmUserID {
+ return true
+ }
+ }
if (pmOnlyQuery == database.PmOnly && msg.ToUser == nil) ||
(pmOnlyQuery == database.PmNone && msg.ToUser != nil) ||
!authUser.DisplayModerators && msg.Moderators ||
@@ -176,9 +185,10 @@ func ChatStreamMessagesHandler(c echo.Context) error {
// Get initial messages for the user
pmOnlyQuery := dutils.DoParsePmDisplayMode(c.QueryParam("pmonly"))
mentionsOnlyQuery := utils.DoParseBool(c.QueryParam("mentionsOnly"))
+ pmUserID := dutils.GetUserIDFromUsername(db, c.QueryParam(command.RedirectPmUsernameQP))
displayHellbanned := authUser.DisplayHellbanned || authUser.IsHellbanned
displayIgnoredMessages := false
- msgs, err := db.GetChatMessages(room.ID, roomKey, authUser.Username, authUser.ID, pmOnlyQuery, mentionsOnlyQuery,
+ msgs, err := db.GetChatMessages(room.ID, roomKey, authUser.Username, authUser.ID, pmUserID, pmOnlyQuery, mentionsOnlyQuery,
displayHellbanned, authUser.DisplayIgnored, authUser.DisplayModerators, displayIgnoredMessages, 500, 0)
if err != nil {
return c.Redirect(http.StatusFound, "/")
@@ -305,6 +315,11 @@ Loop:
return nil
}
+ if topic == selfRefreshTopic && msgTyp.Typ == database.Redirect {
+ send(`<meta http-equiv="refresh" content="0; URL='` + msgTyp.NewURL + `'" />`)
+ return nil
+ }
+
if topic == selfRefreshTopic || msgTyp.Typ == database.ForceRefresh {
send(metaRefresh)
return nil
@@ -336,7 +351,7 @@ Loop:
if msgTyp.Typ == database.EditMsg {
// Get all messages for the user that were created after the edited one (included)
- msgs, err := db.GetChatMessages(room.ID, roomKey, authUser.Username, authUser.ID, pmOnlyQuery,
+ msgs, err := db.GetChatMessages(room.ID, roomKey, authUser.Username, authUser.ID, pmUserID, pmOnlyQuery,
mentionsOnlyQuery, displayHellbanned, authUser.DisplayIgnored, authUser.DisplayModerators,
displayIgnoredMessages, 150, msgTyp.Msg.ID)
if err != nil {
@@ -384,7 +399,7 @@ Loop:
}
if !VerifyMsgAuth(db, authUser, msg) ||
- !applyUserFilters(db, authUser, msg, pmOnlyQuery, displayHellbanned, mentionsOnlyQuery) {
+ !applyUserFilters(db, authUser, msg, pmUserID, pmOnlyQuery, displayHellbanned, mentionsOnlyQuery) {
continue
}
diff --git a/pkg/web/handlers/api/v1/handlers.go b/pkg/web/handlers/api/v1/handlers.go
@@ -66,6 +66,7 @@ func chatMessages(c echo.Context) (status int, data ChatMessagesData) {
pmOnlyQuery := dutils.DoParsePmDisplayMode(c.QueryParam("pmonly"))
mentionsOnlyQuery := utils.DoParseBool(c.QueryParam("mentionsOnly"))
+ pmUserID := dutils.GetUserIDFromUsername(db, c.QueryParam(command.RedirectPmUsernameQP))
room, roomKey, err := dutils.GetRoomAndKey(db, c, roomName)
if err != nil {
@@ -76,7 +77,7 @@ func chatMessages(c echo.Context) (status int, data ChatMessagesData) {
displayHellbanned := authUser.DisplayHellbanned || authUser.IsHellbanned
displayIgnoredMessages := false
- msgs, err := db.GetChatMessages(room.ID, roomKey, authUser.Username, authUser.ID, pmOnlyQuery, mentionsOnlyQuery,
+ msgs, err := db.GetChatMessages(room.ID, roomKey, authUser.Username, authUser.ID, pmUserID, pmOnlyQuery, mentionsOnlyQuery,
displayHellbanned, authUser.DisplayIgnored, authUser.DisplayModerators, displayIgnoredMessages, 150, 0)
if err != nil {
return http.StatusInternalServerError, data
@@ -180,7 +181,8 @@ func RoomNotifierHandler(c echo.Context) error {
displayHellbanned := authUser.DisplayHellbanned || authUser.IsHellbanned
mentionsOnly := false
displayIgnoredMessages := false
- msgs, err := db.GetChatMessages(room.ID, roomKey, authUser.Username, authUser.ID, database.PmNoFilter, mentionsOnly,
+ var pmUserID *database.UserID
+ msgs, err := db.GetChatMessages(room.ID, roomKey, authUser.Username, authUser.ID, pmUserID, database.PmNoFilter, mentionsOnly,
displayHellbanned, authUser.DisplayIgnored, authUser.DisplayModerators, displayIgnoredMessages, 150, 0)
if err != nil {
return c.NoContent(http.StatusInternalServerError)
diff --git a/pkg/web/handlers/api/v1/topBarHandler.go b/pkg/web/handlers/api/v1/topBarHandler.go
@@ -134,6 +134,7 @@ func ChatTopBarHandler(c echo.Context) error {
data.RoomName = c.Param("roomName")
queryParams := c.QueryParams()
+ pmUsername := c.QueryParam(command.RedirectPmUsernameQP)
origMl := utils.DoParseBool(c.QueryParam(command.RedirectMultilineQP))
data.QueryParams = queryParams.Encode()
queryParams.Set(command.RedirectMultilineQP, "1")
@@ -148,6 +149,9 @@ func ChatTopBarHandler(c echo.Context) error {
redirectQP.Set(command.RedirectMultilineQP, "1")
}
}
+ if pmUsername != "" {
+ redirectQP.Set(command.RedirectPmUsernameQP, pmUsername)
+ }
room, roomKey, err := dutils.GetRoomAndKey(db, c, data.RoomName)
if err != nil {
diff --git a/pkg/web/handlers/interceptors/command/command.go b/pkg/web/handlers/interceptors/command/command.go
@@ -25,16 +25,17 @@ func (e ErrSuccess) Error() string {
}
const (
- RedirectPmQP = "pm"
- RedirectEditQP = "e"
- RedirectGroupQP = "g"
- RedirectModQP = "m"
- RedirectHbmQP = "hbm"
- RedirectTagQP = "tag"
- RedirectHTagQP = "htag"
- RedirectMTagQP = "mtag"
- RedirectQuoteQP = "quote"
- RedirectMultilineQP = "ml"
+ RedirectPmQP = "pm"
+ RedirectEditQP = "e"
+ RedirectGroupQP = "g"
+ RedirectModQP = "m"
+ RedirectHbmQP = "hbm"
+ RedirectTagQP = "tag"
+ RedirectHTagQP = "htag"
+ RedirectMTagQP = "mtag"
+ RedirectQuoteQP = "quote"
+ RedirectMultilineQP = "ml"
+ RedirectPmUsernameQP = "pmusername"
)
type Command struct {
diff --git a/pkg/web/handlers/interceptors/msgInterceptor.go b/pkg/web/handlers/interceptors/msgInterceptor.go
@@ -116,6 +116,24 @@ func (i MsgInterceptor) InterceptMsg(cmd *command.Command) {
return
}
+ pmUsername := dutils.DoParseUsernamePtr(cmd.C.QueryParam(command.RedirectPmUsernameQP))
+ if pmUsername != nil {
+ toUser, err := cmd.DB.GetUserByUsername(*pmUsername)
+ if err != nil {
+ cmd.Err = command.ErrRedirect
+ return
+ }
+ cmd.SkipInboxes, cmd.Err = dutils.CanUserPmOther(cmd.DB, *cmd.AuthUser, toUser, cmd.Room.IsOwned())
+ if cmd.Err != nil {
+ return
+ }
+ cmd.ToUser = &toUser
+ cmd.HellbanMsg = false
+ cmd.ModMsg = false
+ cmd.SystemMsg = false
+ cmd.GroupID = nil
+ }
+
toUserID := database.UserPtrID(cmd.ToUser)
msgID, _ := cmd.DB.CreateOrEditMessage(cmd.EditMsg, html, cmd.OrigMessage, cmd.RoomKey, cmd.Room.ID, cmd.AuthUser.ID, toUserID, cmd.Upload, cmd.GroupID, cmd.HellbanMsg, cmd.ModMsg, cmd.SystemMsg)
diff --git a/pkg/web/handlers/interceptors/slashInterceptor.go b/pkg/web/handlers/interceptors/slashInterceptor.go
@@ -977,6 +977,14 @@ func handlePMCmd(c *command.Command) (handled bool) {
username := database.Username(m[1])
newMsg := m[2]
+ if strings.TrimSpace(newMsg) == "" {
+ newURL := fmt.Sprintf("/api/v1/chat/messages/%s/stream?pmusername=%s", c.Room.Name, username)
+ database.MsgPubSub.Pub("refresh_"+string(c.AuthUser.Username), database.ChatMessageType{Typ: database.Redirect, NewURL: newURL})
+ c.RedirectQP.Set(command.RedirectPmUsernameQP, username.String())
+ c.Err = command.ErrRedirect
+ return true
+ }
+
// Chat helpers
if username == config.NullUsername {
return handlePm0(c, newMsg)