-
-
Notifications
You must be signed in to change notification settings - Fork 674
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement /_matrix/client/v1/rooms/{roomId}/threads
(I am being lazy so can someone finish off this for me?)
#3404
base: main
Are you sure you want to change the base?
Changes from all commits
faeb0b4
9934f95
8e9dd3f
8b0c65c
a6f5918
8422ef6
0f80b26
06fa53c
133c77d
1f44a77
bf6a960
8e34a07
1b4fc37
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,107 @@ | ||||||
package routing | ||||||
|
||||||
import ( | ||||||
rstypes "github.com/matrix-org/dendrite/roomserver/types" | ||||||
"net/http" | ||||||
"strconv" | ||||||
|
||||||
"github.com/matrix-org/dendrite/internal/sqlutil" | ||||||
"github.com/matrix-org/dendrite/roomserver/api" | ||||||
"github.com/matrix-org/dendrite/syncapi/storage" | ||||||
"github.com/matrix-org/dendrite/syncapi/synctypes" | ||||||
"github.com/matrix-org/dendrite/syncapi/types" | ||||||
userapi "github.com/matrix-org/dendrite/userapi/api" | ||||||
"github.com/matrix-org/gomatrixserverlib/spec" | ||||||
"github.com/matrix-org/util" | ||||||
"github.com/sirupsen/logrus" | ||||||
) | ||||||
|
||||||
type ThreadsResponse struct { | ||||||
Chunk []synctypes.ClientEvent `json:"chunk"` | ||||||
NextBatch string `json:"next_batch,omitempty"` | ||||||
} | ||||||
|
||||||
func Threads( | ||||||
req *http.Request, | ||||||
device *userapi.Device, | ||||||
syncDB storage.Database, | ||||||
rsAPI api.SyncRoomserverAPI, | ||||||
rawRoomID string) util.JSONResponse { | ||||||
var err error | ||||||
roomID, err := spec.NewRoomID(rawRoomID) | ||||||
if err != nil { | ||||||
return util.JSONResponse{ | ||||||
Code: http.StatusBadRequest, | ||||||
JSON: spec.InvalidParam("invalid room ID"), | ||||||
} | ||||||
} | ||||||
|
||||||
limit, err := strconv.ParseUint(req.URL.Query().Get("limit"), 10, 64) | ||||||
if err != nil { | ||||||
limit = 50 | ||||||
} | ||||||
if limit > 100 { | ||||||
limit = 100 | ||||||
} | ||||||
|
||||||
var from types.StreamPosition | ||||||
if f := req.URL.Query().Get("from"); f != "" { | ||||||
if from, err = types.NewStreamPositionFromString(f); err != nil { | ||||||
return util.ErrorResponse(err) | ||||||
} | ||||||
} | ||||||
|
||||||
include := req.URL.Query().Get("include") | ||||||
|
||||||
snapshot, err := syncDB.NewDatabaseSnapshot(req.Context()) | ||||||
if err != nil { | ||||||
logrus.WithError(err).Error("Failed to get snapshot for relations") | ||||||
return util.JSONResponse{ | ||||||
Code: http.StatusInternalServerError, | ||||||
JSON: spec.InternalServerError{}, | ||||||
} | ||||||
} | ||||||
var succeeded bool | ||||||
defer sqlutil.EndTransactionWithCheck(snapshot, &succeeded, &err) | ||||||
|
||||||
res := &ThreadsResponse{ | ||||||
Chunk: []synctypes.ClientEvent{}, | ||||||
} | ||||||
|
||||||
var userID string | ||||||
if include == "participated" { | ||||||
_, err := spec.NewUserID(device.UserID, true) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
if err != nil { | ||||||
util.GetLogger(req.Context()).WithError(err).Error("device.UserID invalid") | ||||||
return util.JSONResponse{ | ||||||
Code: http.StatusInternalServerError, | ||||||
JSON: spec.Unknown("internal server error"), | ||||||
} | ||||||
} | ||||||
userID = device.UserID | ||||||
} else { | ||||||
userID = "" | ||||||
} | ||||||
var headeredEvents []*rstypes.HeaderedEvent | ||||||
headeredEvents, _, res.NextBatch, err = snapshot.ThreadsFor( | ||||||
req.Context(), roomID.String(), userID, from, limit, | ||||||
) | ||||||
if err != nil { | ||||||
return util.ErrorResponse(err) | ||||||
} | ||||||
|
||||||
for _, event := range headeredEvents { | ||||||
ce, err := synctypes.ToClientEvent(event, synctypes.FormatAll, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the roomID is not needed, as we're already requesting for a specific room?
Suggested change
|
||||||
return rsAPI.QueryUserIDForSender(req.Context(), roomID, senderID) | ||||||
}) | ||||||
if err != nil { | ||||||
return util.ErrorResponse(err) | ||||||
} | ||||||
res.Chunk = append(res.Chunk, *ce) | ||||||
} | ||||||
|
||||||
return util.JSONResponse{ | ||||||
Code: http.StatusOK, | ||||||
JSON: res, | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -811,3 +811,39 @@ func (d *DatabaseTransaction) RelationsFor(ctx context.Context, roomID, eventID, | |
|
||
return events, prevBatch, nextBatch, nil | ||
} | ||
|
||
func (d *DatabaseTransaction) ThreadsFor(ctx context.Context, roomID, userID string, from types.StreamPosition, limit uint64) ( | ||
events []*rstypes.HeaderedEvent, prevBatch, nextBatch string, err error, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
) { | ||
r := types.Range{ | ||
From: from, | ||
} | ||
|
||
if r.From == 0 { | ||
// If we're working backwards (dir=b) and there's no ?from= specified then | ||
// we will automatically want to work backwards from the current position, | ||
// so find out what that is. | ||
if r.From, err = d.MaxStreamPositionForRelations(ctx); err != nil { | ||
return nil, "", "", fmt.Errorf("d.MaxStreamPositionForRelations: %w", err) | ||
} | ||
// The result normally isn't inclusive of the event *at* the ?from= | ||
// position, so add 1 here so that we include the most recent relation. | ||
r.From++ | ||
} | ||
|
||
// First look up any threads from the database. We add one to the limit here | ||
// so that we can tell if we're overflowing, as we will only set the "next_batch" | ||
// in the response if we are. | ||
eventIDs, pos, err := d.Relations.SelectThreads(ctx, d.txn, roomID, userID, from, limit+1) | ||
|
||
if err != nil { | ||
return nil, "", "", fmt.Errorf("d.Relations.SelectRelationsInRange: %w", err) | ||
} | ||
|
||
events, err = d.Events(ctx, eventIDs) | ||
if err != nil { | ||
return nil, "", "", fmt.Errorf("d.OutputEvents.SelectEvents: %w", err) | ||
} | ||
|
||
return events, prevBatch, fmt.Sprintf("%d", pos), nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file needs to be formatted.