summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/client/ui/core/chat/chat.go110
-rw-r--r--internal/data/messages.sql.go23
-rw-r--r--internal/data/models.go1
-rw-r--r--internal/packet/models.go7
-rw-r--r--internal/packet/types.go1
-rw-r--r--internal/server/api/api.go30
-rw-r--r--internal/server/api/migrations/20250127154005_ping.sql8
7 files changed, 157 insertions, 23 deletions
diff --git a/internal/client/ui/core/chat/chat.go b/internal/client/ui/core/chat/chat.go
index c796050..3cad1b5 100644
--- a/internal/client/ui/core/chat/chat.go
+++ b/internal/client/ui/core/chat/chat.go
@@ -76,6 +76,11 @@ var (
MutedSymbol = lipgloss.NewStyle().
Foreground(colors.Red).Render(" 󱡣")
+
+ PingPrefix = "@ping:"
+
+ PingedBorderStyle = lipgloss.NewStyle().
+ Border(lipgloss.Border{Left: "┃"}, false, false, false, true)
)
const (
@@ -561,19 +566,13 @@ func (m Model) Locked() bool {
func (m *Model) sendMessage() tea.Cmd {
message := m.vi.String()
- if len(message) > MaxCharCount {
- return nil
- }
- if len(strings.TrimSpace(message)) == 0 {
- return nil
- }
- m.vi.Reset()
- m.base = SnapToBottom
+ var ping *snowflake.ID
var receiverId *snowflake.ID = nil
if m.receiverIndex != -1 {
receiverId = &state.Data.Peers[m.receiverIndex]
+ ping = nil
}
var frequencyId *snowflake.ID = nil
@@ -581,12 +580,50 @@ func (m *Model) sendMessage() tea.Cmd {
if m.frequencyIndex != -1 && networkId != nil {
frequencies := state.State.Frequencies[*networkId]
frequencyId = &frequencies[m.frequencyIndex].ID
+
+ // Parse ping
+ if strings.HasPrefix(message, PingPrefix) {
+ index := strings.Index(message, "\n")
+ if index != -1 {
+ value := message[len(PingPrefix):index]
+ switch value {
+ case "everyone":
+ pingValue := packet.PingEveryone
+ ping = &pingValue
+ message = message[index+1:]
+ case "admins":
+ pingValue := packet.PingAdmins
+ ping = &pingValue
+ message = message[index+1:]
+ default:
+ num, err := strconv.ParseInt(value, 10, 64)
+ if err != nil {
+ return nil
+ }
+ ping = (*snowflake.ID)(&num)
+ message = message[index+1:]
+ }
+ }
+ } else {
+ ping = nil
+ }
}
+ if len(message) > MaxCharCount {
+ return nil
+ }
+ if len(strings.TrimSpace(message)) == 0 {
+ return nil
+ }
+
+ m.vi.Reset()
+ m.base = SnapToBottom
+
return gateway.Send(&packet.SendMessage{
ReceiverID: receiverId,
FrequencyID: frequencyId,
Content: message,
+ Ping: ping,
})
}
@@ -903,8 +940,27 @@ func (m *Model) renderMessageGroup(group []data.Message, remaining *int, height
// Render all messages content
messageStyle := lipgloss.NewStyle().Width(m.width).
- PaddingLeft(PaddingCount + 2).PaddingRight(PaddingCount)
+ MarginLeft(PaddingCount + 2).PaddingRight(PaddingCount)
+
for i := len(group) - 1; i >= 0; i-- {
+ messageStyle := messageStyle
+ if m.frequencyIndex != -1 && group[i].Ping != nil {
+ members := state.State.Members[*state.NetworkId(m.networkIndex)]
+ if *group[i].Ping == *state.UserID {
+ messageStyle = messageStyle.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Gold)
+ } else if *group[i].Ping == packet.PingEveryone {
+ messageStyle = messageStyle.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Purple)
+ } else if *group[i].Ping == packet.PingAdmins && members[*state.UserID].IsAdmin {
+ messageStyle = messageStyle.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Red)
+ }
+ }
+
rawContent := group[i].Content
content := messageStyle.Render(rawContent)
heights[i] = lipgloss.Height(content)
@@ -953,6 +1009,23 @@ func (m *Model) renderMessageGroup(group []data.Message, remaining *int, height
}
style := messageStyle.Background(colors.BackgroundDim)
+ if m.frequencyIndex != -1 && group[selectedIndex].Ping != nil {
+ members := state.State.Members[*state.NetworkId(m.networkIndex)]
+ if *group[selectedIndex].Ping == *state.UserID {
+ style = style.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Gold)
+ } else if *group[selectedIndex].Ping == packet.PingEveryone {
+ style = style.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Purple)
+ } else if *group[selectedIndex].Ping == packet.PingAdmins && members[*state.UserID].IsAdmin {
+ style = style.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Red)
+ }
+ }
+
rawContent := group[selectedIndex].Content
content := style.Render(rawContent)
if group[selectedIndex].Edited {
@@ -963,12 +1036,31 @@ func (m *Model) renderMessageGroup(group []data.Message, remaining *int, height
content = style.Render(rawContent + SelectedEditedIndicatorNL)
}
}
+ content = lipgloss.NewStyle().Background(colors.BackgroundDim).Render(content)
buf = append(buf, content...)
buf = append(buf, '\n')
// Redraw rest
for i := selectedIndex - 1; i >= 0; i-- {
+ messageStyle := messageStyle
+ if m.frequencyIndex != -1 && group[i].Ping != nil {
+ members := state.State.Members[*state.NetworkId(m.networkIndex)]
+ if *group[i].Ping == *state.UserID {
+ messageStyle = messageStyle.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Gold)
+ } else if *group[i].Ping == packet.PingEveryone {
+ messageStyle = messageStyle.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Purple)
+ } else if *group[i].Ping == packet.PingAdmins && members[*state.UserID].IsAdmin {
+ messageStyle = messageStyle.
+ MarginLeft(PaddingCount).PaddingLeft(1).
+ Inherit(PingedBorderStyle).BorderForeground(colors.Red)
+ }
+ }
+
rawContent := group[i].Content
content := messageStyle.Render(rawContent)
heights[i] = lipgloss.Height(content)
diff --git a/internal/data/messages.sql.go b/internal/data/messages.sql.go
index a3d8257..82909e3 100644
--- a/internal/data/messages.sql.go
+++ b/internal/data/messages.sql.go
@@ -13,11 +13,11 @@ import (
const createMessage = `-- name: CreateMessage :one
INSERT INTO messages (
- id, content, sender_id, frequency_id, receiver_id
+ id, content, sender_id, frequency_id, receiver_id, ping
) VALUES (
- ?, ?, ?, ?, ?
+ ?, ?, ?, ?, ?, ?
)
-RETURNING id, sender_id, content, edited, frequency_id, receiver_id
+RETURNING id, sender_id, content, edited, frequency_id, receiver_id, ping
`
type CreateMessageParams struct {
@@ -26,6 +26,7 @@ type CreateMessageParams struct {
SenderID snowflake.ID
FrequencyID *snowflake.ID
ReceiverID *snowflake.ID
+ Ping *snowflake.ID
}
func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) (Message, error) {
@@ -35,6 +36,7 @@ func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) (M
arg.SenderID,
arg.FrequencyID,
arg.ReceiverID,
+ arg.Ping,
)
var i Message
err := row.Scan(
@@ -44,6 +46,7 @@ func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) (M
&i.Edited,
&i.FrequencyID,
&i.ReceiverID,
+ &i.Ping,
)
return i, err
}
@@ -63,7 +66,7 @@ UPDATE messages SET
edited = true,
content = ?
WHERE id = ?
-RETURNING id, sender_id, content, edited, frequency_id, receiver_id
+RETURNING id, sender_id, content, edited, frequency_id, receiver_id, ping
`
type EditMessageParams struct {
@@ -81,14 +84,15 @@ func (q *Queries) EditMessage(ctx context.Context, arg EditMessageParams) (Messa
&i.Edited,
&i.FrequencyID,
&i.ReceiverID,
+ &i.Ping,
)
return i, err
}
const getDirectMessages = `-- name: GetDirectMessages :many
-SELECT id, sender_id, content, edited, frequency_id, receiver_id FROM messages
+SELECT id, sender_id, content, edited, frequency_id, receiver_id, ping FROM messages
WHERE
- (sender_id = ?1 AND receiver_id = ?2) OR
+ (sender_id = ?1 AND receiver_id = ?2) OR
(sender_id = ?2 AND receiver_id = ?1)
ORDER BY id
`
@@ -114,6 +118,7 @@ func (q *Queries) GetDirectMessages(ctx context.Context, arg GetDirectMessagesPa
&i.Edited,
&i.FrequencyID,
&i.ReceiverID,
+ &i.Ping,
); err != nil {
return nil, err
}
@@ -129,7 +134,7 @@ func (q *Queries) GetDirectMessages(ctx context.Context, arg GetDirectMessagesPa
}
const getFrequencyMessages = `-- name: GetFrequencyMessages :many
-SELECT id, sender_id, content, edited, frequency_id, receiver_id FROM messages
+SELECT id, sender_id, content, edited, frequency_id, receiver_id, ping FROM messages
WHERE frequency_id = ?
ORDER BY id
`
@@ -150,6 +155,7 @@ func (q *Queries) GetFrequencyMessages(ctx context.Context, frequencyID *snowfla
&i.Edited,
&i.FrequencyID,
&i.ReceiverID,
+ &i.Ping,
); err != nil {
return nil, err
}
@@ -165,7 +171,7 @@ func (q *Queries) GetFrequencyMessages(ctx context.Context, frequencyID *snowfla
}
const getMessageById = `-- name: GetMessageById :one
-SELECT id, sender_id, content, edited, frequency_id, receiver_id FROM messages
+SELECT id, sender_id, content, edited, frequency_id, receiver_id, ping FROM messages
WHERE id = ?
`
@@ -179,6 +185,7 @@ func (q *Queries) GetMessageById(ctx context.Context, id snowflake.ID) (Message,
&i.Edited,
&i.FrequencyID,
&i.ReceiverID,
+ &i.Ping,
)
return i, err
}
diff --git a/internal/data/models.go b/internal/data/models.go
index 9bc2961..8470e2a 100644
--- a/internal/data/models.go
+++ b/internal/data/models.go
@@ -41,6 +41,7 @@ type Message struct {
Edited bool
FrequencyID *snowflake.ID
ReceiverID *snowflake.ID
+ Ping *snowflake.ID
}
type Network struct {
diff --git a/internal/packet/models.go b/internal/packet/models.go
index a61c61d..c26d93a 100644
--- a/internal/packet/models.go
+++ b/internal/packet/models.go
@@ -1,5 +1,7 @@
package packet
+import "github.com/kyren223/eko/pkg/snowflake"
+
const (
MaxNetworkNameBytes = 32
MaxIconBytes = 16
@@ -19,3 +21,8 @@ const (
PermReadWrite
PermMax
)
+
+const (
+ PingEveryone = snowflake.ID(0)
+ PingAdmins = snowflake.ID(1)
+)
diff --git a/internal/packet/types.go b/internal/packet/types.go
index f8e164c..6d0b1dd 100644
--- a/internal/packet/types.go
+++ b/internal/packet/types.go
@@ -139,6 +139,7 @@ type SendMessage struct {
ReceiverID *snowflake.ID
FrequencyID *snowflake.ID
Content string
+ Ping *snowflake.ID
}
func (m *SendMessage) Type() PacketType {
diff --git a/internal/server/api/api.go b/internal/server/api/api.go
index d7a0ef5..3fff656 100644
--- a/internal/server/api/api.go
+++ b/internal/server/api/api.go
@@ -71,19 +71,36 @@ func SendMessage(ctx context.Context, sess *session.Session, request *packet.Sen
}
if frequency.Perms != packet.PermReadWrite && !member.IsAdmin {
- log.Println("No perms")
return &ErrPermissionDenied
}
+ if request.Ping != nil {
+ if *request.Ping == packet.PingEveryone {
+ if !member.IsAdmin {
+ return &ErrPermissionDenied
+ }
+ } else if *request.Ping != packet.PingAdmins {
+ _, err := queries.GetUserById(ctx, *request.Ping)
+ if err == sql.ErrNoRows {
+ return &packet.Error{Error: "pinged user doesn't exist"}
+ }
+ if err != nil {
+ log.Println("database error 2:", err)
+ return &ErrInternalError
+ }
+ }
+ }
+
message, err := queries.CreateMessage(ctx, data.CreateMessageParams{
ID: sess.Manager().Node().Generate(),
SenderID: sess.ID(),
Content: content,
FrequencyID: request.FrequencyID,
ReceiverID: nil,
+ Ping: request.Ping,
})
if err != nil {
- log.Println(sess.Addr(), "database error 2:", err)
+ log.Println("database error 3:", err)
return &ErrInternalError
}
@@ -105,7 +122,7 @@ func SendMessage(ctx context.Context, sess *session.Session, request *packet.Sen
return &packet.Error{Error: "user doesn't exist"}
}
if err != nil {
- log.Println(sess.Addr(), "database error 3:", err)
+ log.Println("database error 4:", err)
return &ErrInternalError
}
if !user.IsPublicDM {
@@ -117,7 +134,7 @@ func SendMessage(ctx context.Context, sess *session.Session, request *packet.Sen
return &ErrPermissionDenied
}
if err != nil {
- log.Println(sess.Addr(), "database error 4:", err)
+ log.Println("database error 5:", err)
return &ErrInternalError
}
if !bytes.Equal(sess.PubKey, pubKey) {
@@ -127,13 +144,14 @@ func SendMessage(ctx context.Context, sess *session.Session, request *packet.Sen
message, err := queries.CreateMessage(ctx, data.CreateMessageParams{
ID: sess.Manager().Node().Generate(),
- SenderID: sess.ID(),
Content: content,
+ SenderID: sess.ID(),
FrequencyID: nil,
ReceiverID: request.ReceiverID,
+ Ping: nil,
})
if err != nil {
- log.Println(sess.Addr(), "database error 5:", err)
+ log.Println("database error 6:", err)
return &ErrInternalError
}
diff --git a/internal/server/api/migrations/20250127154005_ping.sql b/internal/server/api/migrations/20250127154005_ping.sql
new file mode 100644
index 0000000..54f207a
--- /dev/null
+++ b/internal/server/api/migrations/20250127154005_ping.sql
@@ -0,0 +1,8 @@
+-- +goose Up
+ALTER TABLE messages ADD ping INTEGER DEFAULT NULL;
+-- Must be null if freuqencyId is null
+-- 0 - @ping:everyone, 1 - @ping:admins, otherwise references userId
+
+
+-- +goose Down
+ALTER TABLE messages DROP ping;