|
4 | 4 | "bytes" |
5 | 5 | "encoding/json" |
6 | 6 | "fmt" |
| 7 | + "maps" |
7 | 8 | "reflect" |
8 | 9 | "strconv" |
9 | 10 | "strings" |
@@ -155,8 +156,44 @@ type RespUserDisplayName struct { |
155 | 156 | } |
156 | 157 |
|
157 | 158 | type RespUserProfile struct { |
158 | | - DisplayName string `json:"displayname"` |
159 | | - AvatarURL id.ContentURI `json:"avatar_url"` |
| 159 | + DisplayName string `json:"displayname,omitempty"` |
| 160 | + AvatarURL id.ContentURI `json:"avatar_url,omitempty"` |
| 161 | + Extra map[string]any `json:"-"` |
| 162 | +} |
| 163 | + |
| 164 | +type marshalableUserProfile RespUserProfile |
| 165 | + |
| 166 | +func (r *RespUserProfile) UnmarshalJSON(data []byte) error { |
| 167 | + err := json.Unmarshal(data, &r.Extra) |
| 168 | + if err != nil { |
| 169 | + return err |
| 170 | + } |
| 171 | + r.DisplayName, _ = r.Extra["displayname"].(string) |
| 172 | + avatarURL, _ := r.Extra["avatar_url"].(string) |
| 173 | + if avatarURL != "" { |
| 174 | + r.AvatarURL, _ = id.ParseContentURI(avatarURL) |
| 175 | + } |
| 176 | + delete(r.Extra, "displayname") |
| 177 | + delete(r.Extra, "avatar_url") |
| 178 | + return nil |
| 179 | +} |
| 180 | + |
| 181 | +func (r *RespUserProfile) MarshalJSON() ([]byte, error) { |
| 182 | + if len(r.Extra) == 0 { |
| 183 | + return json.Marshal((*marshalableUserProfile)(r)) |
| 184 | + } |
| 185 | + marshalMap := maps.Clone(r.Extra) |
| 186 | + if r.DisplayName != "" { |
| 187 | + marshalMap["displayname"] = r.DisplayName |
| 188 | + } else { |
| 189 | + delete(marshalMap, "displayname") |
| 190 | + } |
| 191 | + if !r.AvatarURL.IsEmpty() { |
| 192 | + marshalMap["avatar_url"] = r.AvatarURL.String() |
| 193 | + } else { |
| 194 | + delete(marshalMap, "avatar_url") |
| 195 | + } |
| 196 | + return json.Marshal(r.Extra) |
160 | 197 | } |
161 | 198 |
|
162 | 199 | type RespMutualRooms struct { |
|
0 commit comments