add messages persistancy, channels does not persist
This commit is contained in:
@@ -61,6 +61,7 @@ func main() {
|
|||||||
http.HandleFunc("POST /hub", withCORS(httpRequest.HandleHubCreate))
|
http.HandleFunc("POST /hub", withCORS(httpRequest.HandleHubCreate))
|
||||||
http.HandleFunc("GET /hub", withCORS(httpRequest.GetHubData))
|
http.HandleFunc("GET /hub", withCORS(httpRequest.GetHubData))
|
||||||
http.HandleFunc("POST /hub/channel/message", withCORS(httpRequest.HandleHubMessage))
|
http.HandleFunc("POST /hub/channel/message", withCORS(httpRequest.HandleHubMessage))
|
||||||
|
http.HandleFunc("GET /hub/channel/messages", withCORS(httpRequest.HandleHubChannelGetMessages))
|
||||||
http.HandleFunc("GET /hub/channel", withCORS(httpRequest.GetChannelData))
|
http.HandleFunc("GET /hub/channel", withCORS(httpRequest.GetChannelData))
|
||||||
http.HandleFunc("GET /hubs", withCORS(httpRequest.HandleGetHubs))
|
http.HandleFunc("GET /hubs", withCORS(httpRequest.HandleGetHubs))
|
||||||
http.HandleFunc("GET /hubs/channels", withCORS(httpRequest.HandleGetChannels))
|
http.HandleFunc("GET /hubs/channels", withCORS(httpRequest.HandleGetChannels))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package httpRequest
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"go-socket/packages/config"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -317,6 +318,81 @@ func HandleHubMessage(response http.ResponseWriter, request *http.Request) {
|
|||||||
response.WriteHeader(http.StatusCreated)
|
response.WriteHeader(http.StatusCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HandleHubChannelGetMessages(response http.ResponseWriter, request *http.Request) {
|
||||||
|
if !validCheckWithResponseOnFail(response, request, normal) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx := request.Context()
|
||||||
|
user, hubUser, hub, err := getHubUserIfValidWithResponseOnFail(ctx, response, request)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
channel, err := getHubChannelIfValidWithResponseOnFail(ctx, response, hub, hubUser, request.FormValue("channel_id"))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
channel.Mu.RLock()
|
||||||
|
canReadHistory := channel.UsersCachedPermissions[user.Id].CanReadHistory()
|
||||||
|
channel.Mu.RUnlock()
|
||||||
|
if !canReadHistory {
|
||||||
|
http.Error(response, "forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
before, err := convertions.StringToTimestamp(request.URL.Query().Get("before"))
|
||||||
|
if err != nil {
|
||||||
|
before = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
messagesCap, err := convertions.StringToUint32(request.URL.Query().Get("messages"))
|
||||||
|
if err != nil {
|
||||||
|
messagesCap = config.MaxDirectMsgCache
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer, bufferSize := channel.GetSortedMessagesBuff()
|
||||||
|
|
||||||
|
var validBufCount uint32
|
||||||
|
for validBufCount < bufferSize && buffer[validBufCount].CreatedAt.Before(before) {
|
||||||
|
validBufCount++
|
||||||
|
}
|
||||||
|
|
||||||
|
var messages []*types.Message
|
||||||
|
|
||||||
|
if validBufCount >= messagesCap {
|
||||||
|
start := validBufCount - messagesCap
|
||||||
|
messages = make([]*types.Message, messagesCap)
|
||||||
|
for i := uint32(0); i < messagesCap; i++ {
|
||||||
|
messages[i] = buffer[start+i]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
remaining := messagesCap - validBufCount
|
||||||
|
cutoff := before
|
||||||
|
if validBufCount > 0 {
|
||||||
|
cutoff = buffer[0].CreatedAt
|
||||||
|
}
|
||||||
|
dbMessages, err := postgresql.HubChannelGetMessagesBefore(ctx, cutoff, channel.Id, remaining)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
messages = make([]*types.Message, 0, uint32(len(dbMessages))+validBufCount)
|
||||||
|
messages = append(messages, dbMessages...)
|
||||||
|
for i := uint32(0); i < validBufCount; i++ {
|
||||||
|
messages = append(messages, buffer[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := json.Marshal(messages)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(response, "internal server error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.WriteHeader(http.StatusOK)
|
||||||
|
response.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
func HandleGetChannels(response http.ResponseWriter, request *http.Request) {
|
func HandleGetChannels(response http.ResponseWriter, request *http.Request) {
|
||||||
if !validCheckWithResponseOnFail(response, request, normal) {
|
if !validCheckWithResponseOnFail(response, request, normal) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -578,6 +578,35 @@ func HubChannelMessageGet(ctx context.Context, message *types.Message) error {
|
|||||||
`, message.Id).Scan(&message.Sender, &message.Receiver, &message.CreatedAt, &message.Content, &message.AttachedFile)
|
`, message.Id).Scan(&message.Sender, &message.Receiver, &message.CreatedAt, &message.Content, &message.AttachedFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HubChannelGetMessagesBefore(ctx context.Context, before time.Time, channelId uuid.UUID, cap uint32) ([]*types.Message, error) {
|
||||||
|
rows, err := dbConn.Query(ctx, `
|
||||||
|
SELECT id, sender_id, receiver_id, created_at, content, attached_file
|
||||||
|
FROM (
|
||||||
|
SELECT id, sender_id, receiver_id, created_at, content, attached_file
|
||||||
|
FROM hub_channel_messages
|
||||||
|
WHERE receiver_id = $1
|
||||||
|
AND created_at < $2
|
||||||
|
ORDER BY created_at DESC
|
||||||
|
LIMIT $3
|
||||||
|
) sub
|
||||||
|
ORDER BY created_at ASC
|
||||||
|
`, channelId, before, cap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
messages := make([]*types.Message, 0, cap)
|
||||||
|
for rows.Next() {
|
||||||
|
msg := &types.Message{}
|
||||||
|
if err = rows.Scan(&msg.Id, &msg.Sender, &msg.Receiver, &msg.CreatedAt, &msg.Content, &msg.AttachedFile); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
messages = append(messages, msg)
|
||||||
|
}
|
||||||
|
return messages, rows.Err()
|
||||||
|
}
|
||||||
|
|
||||||
func HubUpdate(ctx context.Context, hub *types.Hub, updateList *types.HubUpdate) error {
|
func HubUpdate(ctx context.Context, hub *types.Hub, updateList *types.HubUpdate) error {
|
||||||
setClauses := make([]string, 0, 6)
|
setClauses := make([]string, 0, 6)
|
||||||
args := make([]any, 0, 7)
|
args := make([]any, 0, 7)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
<button data-form="msg-user" onclick="showForm('msg-user')">POST /connection/message</button>
|
<button data-form="msg-user" onclick="showForm('msg-user')">POST /connection/message</button>
|
||||||
<button data-form="hub-create" onclick="showForm('hub-create')">POST /hub</button>
|
<button data-form="hub-create" onclick="showForm('hub-create')">POST /hub</button>
|
||||||
<button data-form="hub-message" onclick="showForm('hub-message')">POST /hub/channel/message</button>
|
<button data-form="hub-message" onclick="showForm('hub-message')">POST /hub/channel/message</button>
|
||||||
|
<button data-form="get-hub-channel-messages" onclick="showForm('get-hub-channel-messages')">GET /hub/channel/messages</button>
|
||||||
<button data-form="hub-join" onclick="showForm('hub-join')">PUT /hub/join</button>
|
<button data-form="hub-join" onclick="showForm('hub-join')">PUT /hub/join</button>
|
||||||
<button data-form="get-hubs" onclick="showForm('get-hubs')">GET /hubs</button>
|
<button data-form="get-hubs" onclick="showForm('get-hubs')">GET /hubs</button>
|
||||||
<button data-form="get-hub-data" onclick="showForm('get-hub-data')">GET /hub</button>
|
<button data-form="get-hub-data" onclick="showForm('get-hub-data')">GET /hub</button>
|
||||||
@@ -51,6 +52,7 @@
|
|||||||
<button data-form="get-hub-users" onclick="showForm('get-hub-users')">GET /hubs/users</button>
|
<button data-form="get-hub-users" onclick="showForm('get-hub-users')">GET /hubs/users</button>
|
||||||
<button data-form="get-hub-roles" onclick="showForm('get-hub-roles')">GET /hubs/roles</button>
|
<button data-form="get-hub-roles" onclick="showForm('get-hub-roles')">GET /hubs/roles</button>
|
||||||
<button data-form="get-users" onclick="showForm('get-users')">GET /users</button>
|
<button data-form="get-users" onclick="showForm('get-users')">GET /users</button>
|
||||||
|
<button data-form="hub-set-joinrole" onclick="showForm('hub-set-joinrole')">PATCH /hub/joinrole</button>
|
||||||
<button data-form="hub-set-name" onclick="showForm('hub-set-name')">PATCH /hub/name</button>
|
<button data-form="hub-set-name" onclick="showForm('hub-set-name')">PATCH /hub/name</button>
|
||||||
<button data-form="hub-set-color" onclick="showForm('hub-set-color')">PATCH /hub/color</button>
|
<button data-form="hub-set-color" onclick="showForm('hub-set-color')">PATCH /hub/color</button>
|
||||||
<button data-form="hub-set-icon" onclick="showForm('hub-set-icon')">PATCH /hub/icon</button>
|
<button data-form="hub-set-icon" onclick="showForm('hub-set-icon')">PATCH /hub/icon</button>
|
||||||
@@ -242,6 +244,16 @@
|
|||||||
<div class="form-actions"><button class="send" onclick="submit('hub-message')">Send</button></div>
|
<div class="form-actions"><button class="send" onclick="submit('hub-message')">Send</button></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- GET /hub/channel/messages -->
|
||||||
|
<div class="form-content" id="fc-get-hub-channel-messages">
|
||||||
|
<div class="field"><label>token</label><input id="ghcm-token" placeholder=""></div>
|
||||||
|
<div class="field"><label>hub_id</label><input id="ghcm-hubid" placeholder="UUID"><span class="hint">sent as header</span></div>
|
||||||
|
<div class="field"><label>channel_id</label><input id="ghcm-channelid" placeholder="UUID"></div>
|
||||||
|
<div class="field"><label>messages</label><input id="ghcm-messages" placeholder="count (optional)"></div>
|
||||||
|
<div class="field"><label>before</label><input id="ghcm-before" placeholder="RFC3339 (optional)"><span class="hint">e.g. 2025-01-01T00:00:00Z</span></div>
|
||||||
|
<div class="form-actions"><button class="send" onclick="submit('get-hub-channel-messages')">Send</button></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- PUT /hub/join -->
|
<!-- PUT /hub/join -->
|
||||||
<div class="form-content" id="fc-hub-join">
|
<div class="form-content" id="fc-hub-join">
|
||||||
<div class="field"><label>token</label><input id="hj-token" placeholder=""></div>
|
<div class="field"><label>token</label><input id="hj-token" placeholder=""></div>
|
||||||
@@ -276,6 +288,14 @@
|
|||||||
<div class="form-actions"><button class="send" onclick="submit('get-hub-users')">Send</button></div>
|
<div class="form-actions"><button class="send" onclick="submit('get-hub-users')">Send</button></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- PATCH /hub/joinrole -->
|
||||||
|
<div class="form-content" id="fc-hub-set-joinrole">
|
||||||
|
<div class="field"><label>token</label><input id="hsjr-token" placeholder=""></div>
|
||||||
|
<div class="field"><label>hub_id</label><input id="hsjr-hubid" placeholder="UUID"></div>
|
||||||
|
<div class="field"><label>new_role_id</label><input id="hsjr-roleid" placeholder="uint8"></div>
|
||||||
|
<div class="form-actions"><button class="send" onclick="submit('hub-set-joinrole')">Send</button></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- PATCH /hub/name -->
|
<!-- PATCH /hub/name -->
|
||||||
<div class="form-content" id="fc-hub-set-name">
|
<div class="form-content" id="fc-hub-set-name">
|
||||||
<div class="field"><label>token</label><input id="hsn-token" placeholder=""></div>
|
<div class="field"><label>token</label><input id="hsn-token" placeholder=""></div>
|
||||||
@@ -584,6 +604,7 @@
|
|||||||
'msg-user': { method:'POST', path:'/connection/message', title:'POST /connection/message — send direct message', fields:[{id:'mu-token',dest:'header',name:'token'},{id:'mu-connectionid',dest:'body',name:'connection_id'},{id:'mu-msgContent',dest:'body',name:'msg_content'},{id:'mu-attachedFile',dest:'body',name:'attached_file'}] },
|
'msg-user': { method:'POST', path:'/connection/message', title:'POST /connection/message — send direct message', fields:[{id:'mu-token',dest:'header',name:'token'},{id:'mu-connectionid',dest:'body',name:'connection_id'},{id:'mu-msgContent',dest:'body',name:'msg_content'},{id:'mu-attachedFile',dest:'body',name:'attached_file'}] },
|
||||||
'hub-create': { method:'POST', path:'/hub', title:'POST /hub — create a new hub', fields:[{id:'hc-token',dest:'header',name:'token'},{id:'hc-hubname',dest:'body',name:'hub_name'}] },
|
'hub-create': { method:'POST', path:'/hub', title:'POST /hub — create a new hub', fields:[{id:'hc-token',dest:'header',name:'token'},{id:'hc-hubname',dest:'body',name:'hub_name'}] },
|
||||||
'hub-message': { method:'POST', path:'/hub/channel/message', title:'POST /hub/channel/message — send hub channel message', fields:[{id:'hm-token',dest:'header',name:'token'},{id:'hm-hubid',dest:'header',name:'hub_id'},{id:'hm-channelid',dest:'header',name:'channel_id'},{id:'hm-msgContent',dest:'body',name:'msg_content'},{id:'hm-attachedFile',dest:'body',name:'attached_file'}] },
|
'hub-message': { method:'POST', path:'/hub/channel/message', title:'POST /hub/channel/message — send hub channel message', fields:[{id:'hm-token',dest:'header',name:'token'},{id:'hm-hubid',dest:'header',name:'hub_id'},{id:'hm-channelid',dest:'header',name:'channel_id'},{id:'hm-msgContent',dest:'body',name:'msg_content'},{id:'hm-attachedFile',dest:'body',name:'attached_file'}] },
|
||||||
|
'get-hub-channel-messages':{ method:'GET', path:'/hub/channel/messages', title:'GET /hub/channel/messages — channel message history', fields:[{id:'ghcm-token',dest:'header',name:'token'},{id:'ghcm-hubid',dest:'header',name:'hub_id'},{id:'ghcm-channelid',dest:'query',name:'channel_id'},{id:'ghcm-messages',dest:'query',name:'messages'},{id:'ghcm-before',dest:'query',name:'before'}] },
|
||||||
'hub-join': { method:'PUT', path:'/hub/join', title:'PUT /hub/join — join hub (hubid as header)', fields:[{id:'hj-token',dest:'header',name:'token'},{id:'hj-hubid',dest:'header',name:'hub_id'}] },
|
'hub-join': { method:'PUT', path:'/hub/join', title:'PUT /hub/join — join hub (hubid as header)', fields:[{id:'hj-token',dest:'header',name:'token'},{id:'hj-hubid',dest:'header',name:'hub_id'}] },
|
||||||
'get-hubs': { method:'GET', path:'/hubs', title:'GET /hubs — get own hubs', fields:[{id:'gh-token',dest:'header',name:'token'}] },
|
'get-hubs': { method:'GET', path:'/hubs', title:'GET /hubs — get own hubs', fields:[{id:'gh-token',dest:'header',name:'token'}] },
|
||||||
'get-hub-data': { method:'GET', path:'/hub', title:'GET /hub — get hub data', fields:[{id:'ghd-token',dest:'header',name:'token'},{id:'ghd-hubid',dest:'header',name:'hub_id'}] },
|
'get-hub-data': { method:'GET', path:'/hub', title:'GET /hub — get hub data', fields:[{id:'ghd-token',dest:'header',name:'token'},{id:'ghd-hubid',dest:'header',name:'hub_id'}] },
|
||||||
@@ -592,6 +613,7 @@
|
|||||||
'get-hub-users': { method:'GET', path:'/hubs/users', title:'GET /hubs/users — get hub users (excludes self)', fields:[{id:'ghu-token',dest:'header',name:'token'},{id:'ghu-hubid',dest:'header',name:'hub_id'}] },
|
'get-hub-users': { method:'GET', path:'/hubs/users', title:'GET /hubs/users — get hub users (excludes self)', fields:[{id:'ghu-token',dest:'header',name:'token'},{id:'ghu-hubid',dest:'header',name:'hub_id'}] },
|
||||||
'get-hub-roles': { method:'GET', path:'/hubs/roles', title:'GET /hubs/roles — get hub roles', fields:[{id:'ghr-token',dest:'header',name:'token'},{id:'ghr-hubid',dest:'header',name:'hub_id'}] },
|
'get-hub-roles': { method:'GET', path:'/hubs/roles', title:'GET /hubs/roles — get hub roles', fields:[{id:'ghr-token',dest:'header',name:'token'},{id:'ghr-hubid',dest:'header',name:'hub_id'}] },
|
||||||
'get-users': { method:'GET', path:'/users', title:'GET /users — get multiple users by IDs', fields:[{id:'gus-token',dest:'header',name:'token'},{id:'gus-targetids',dest:'query',name:'target_ids'}] },
|
'get-users': { method:'GET', path:'/users', title:'GET /users — get multiple users by IDs', fields:[{id:'gus-token',dest:'header',name:'token'},{id:'gus-targetids',dest:'query',name:'target_ids'}] },
|
||||||
|
'hub-set-joinrole': { method:'PATCH', path:'/hub/joinrole', title:'PATCH /hub/joinrole — set default join role', fields:[{id:'hsjr-token',dest:'header',name:'token'},{id:'hsjr-hubid',dest:'header',name:'hub_id'},{id:'hsjr-roleid',dest:'body',name:'new_role_id'}] },
|
||||||
'hub-set-name': { method:'PATCH', path:'/hub/name', title:'PATCH /hub/name — set hub name', fields:[{id:'hsn-token',dest:'header',name:'token'},{id:'hsn-hubid',dest:'header',name:'hub_id'},{id:'hsn-newname',dest:'body',name:'new_name'}] },
|
'hub-set-name': { method:'PATCH', path:'/hub/name', title:'PATCH /hub/name — set hub name', fields:[{id:'hsn-token',dest:'header',name:'token'},{id:'hsn-hubid',dest:'header',name:'hub_id'},{id:'hsn-newname',dest:'body',name:'new_name'}] },
|
||||||
'hub-set-color': { method:'PATCH', path:'/hub/color', title:'PATCH /hub/color — set hub color (R,G,B,A)', fields:[{id:'hsc-token',dest:'header',name:'token'},{id:'hsc-hubid',dest:'header',name:'hub_id'},{id:'hsc-newcolor',dest:'body',name:'new_color'}] },
|
'hub-set-color': { method:'PATCH', path:'/hub/color', title:'PATCH /hub/color — set hub color (R,G,B,A)', fields:[{id:'hsc-token',dest:'header',name:'token'},{id:'hsc-hubid',dest:'header',name:'hub_id'},{id:'hsc-newcolor',dest:'body',name:'new_color'}] },
|
||||||
'hub-set-icon': { title:'PATCH /hub/icon — set hub icon image' },
|
'hub-set-icon': { title:'PATCH /hub/icon — set hub icon image' },
|
||||||
|
|||||||
Reference in New Issue
Block a user