Invitations into hosted rooms: the dialog's details, and joining as a public room
CI / build (push) Successful in 34s
CI / build (push) Successful in 34s
The invitation carries the room as the dialog shows it (name, owner, image, occupancy, description) and the inviter's picture, age and gender from IMVU's public profile. Accepting names the room (room_instance_id), so the client joins it as a public room with the invite rather than opening a private chat, and getParticipants before joining asks the hub, so the client sees its inviter there. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
210bc064e9
commit
2df46da3ad
3 files changed
+116
-9
No files matched your search
@@ -112,23 +112,72 @@ func (r *Rooms) deliverInvite(n int64, hubID string, from int64) {
|
||||
if err != nil || r.UserDeliver == nil {
|
||||
return
|
||||
}
|
||||
name := ""
|
||||
inviter := r.profile(ctx, from)
|
||||
for _, p := range r.people(ctx, n) {
|
||||
if p.ImvuID == from {
|
||||
name = p.Name
|
||||
if p.ImvuID == from && p.Name != "" {
|
||||
inviter["name"] = plain(p.Name)
|
||||
}
|
||||
}
|
||||
r.mu.Lock()
|
||||
local := r.newInviteLocked(&invite{room: n, hub: hubID, from: from})
|
||||
r.mu.Unlock()
|
||||
rating := 0
|
||||
if rm.Rating == "adult" {
|
||||
rating = 1
|
||||
}
|
||||
instance := instanceID(rm.OwnerImvuID, n)
|
||||
// location is what the invitation dialog shows of the room.
|
||||
location := map[string]any{"name": plain(rm.Name), "private": rm.Privacy == "private", "imageUrl": rm.Image,
|
||||
"ownerName": plain(rm.OwnerName), "language": "", "currentOccupancy": rm.Occupancy, "maxOccupancy": rm.MaxUsers,
|
||||
"description": plain(rm.Description), "rating": rating, "room_instance_id": instance}
|
||||
b, _ := json.Marshal(map[string]any{"chatId": Base + n, "inviteId": local, "partnerId": from,
|
||||
"location": instanceID(rm.OwnerImvuID, n),
|
||||
"inviter": map[string]any{"name": plain(name), "age": "", "gender": "", "imageUrl": "", "relationship": ""}})
|
||||
"location": location, "inviter": inviter})
|
||||
if err := r.UserDeliver("web_msg", append([]byte("chatInvite "), b...)); err != nil {
|
||||
r.logf("hosted: giving the client an invitation: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// profile is what the invitation dialog shows of the inviter, from IMVU's public profile.
|
||||
func (r *Rooms) profile(ctx context.Context, id int64) map[string]any {
|
||||
out := map[string]any{"name": "", "age": "", "gender": "", "imageUrl": "", "relationship": ""}
|
||||
u := fmt.Sprintf("https://api.imvu.com/user/user-%d", id)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
|
||||
if err != nil {
|
||||
return out
|
||||
}
|
||||
resp, err := r.client().Do(req)
|
||||
if err != nil {
|
||||
return out
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var body struct {
|
||||
Denormalized map[string]struct {
|
||||
Data struct {
|
||||
Username string `json:"username"`
|
||||
Age any `json:"age"`
|
||||
Gender string `json:"gender"`
|
||||
ThumbnailURL string `json:"thumbnail_url"`
|
||||
} `json:"data"`
|
||||
} `json:"denormalized"`
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK || json.NewDecoder(resp.Body).Decode(&body) != nil {
|
||||
return out
|
||||
}
|
||||
d := body.Denormalized[u].Data
|
||||
out["name"], out["gender"], out["imageUrl"] = plain(d.Username), d.Gender, d.ThumbnailURL
|
||||
if d.Age != nil {
|
||||
out["age"] = fmt.Sprint(d.Age)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (r *Rooms) client() *http.Client {
|
||||
if r.HTTPClient != nil {
|
||||
return r.HTTPClient
|
||||
}
|
||||
return http.DefaultClient
|
||||
}
|
||||
|
||||
type person struct {
|
||||
ImvuID int64 `json:"imvu_id"`
|
||||
Seat int `json:"seat"`
|
||||
@@ -184,7 +233,17 @@ func (r *Rooms) interceptPhase2(ctx context.Context, x *proxy.Exchange, method s
|
||||
x.Response = xmlrpcAnswer(true)
|
||||
return true
|
||||
}
|
||||
x.Response = r.joinChat(ctx, in.room, in.hub)
|
||||
// The client joins the room itself when the answer names it (as a public room, not a private chat); that
|
||||
// join carries the invite.
|
||||
r.mu.Lock()
|
||||
if r.accepted == nil {
|
||||
r.accepted = map[int64]string{}
|
||||
}
|
||||
r.accepted[in.room] = in.hub
|
||||
instance := r.instanceOfLocked(in.room) // known: the room was looked up for the invitation
|
||||
r.mu.Unlock()
|
||||
x.Response = xmlrpcAnswer(xmlrpc.Struct{{Name: "chatId", Value: Base + in.room}, {Name: "partnerId", Value: in.from},
|
||||
{Name: "room_instance_id", Value: instance}})
|
||||
return true
|
||||
case "chat.bootOutOfChat":
|
||||
// The "*boot" chat line already told the hub (Send); the client only wants an answer.
|
||||
|
||||
Reference in new issue
Block a user