user_info_stub.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package handlers
  2. import (
  3. "log/slog"
  4. "net/http"
  5. )
  6. type UserInfoStubHandler struct {
  7. Logger *slog.Logger
  8. }
  9. // UserDetailsData reports which third-party services the account is linked to.
  10. type UserDetailsData struct {
  11. UserDetails UserDetails `json:"userDetails" xml:"userDetails"`
  12. }
  13. // UserDetails lists the linked services.
  14. type UserDetails struct {
  15. Services []UserService `json:"services" xml:"services>service"`
  16. }
  17. // UserService names one linked service.
  18. type UserService struct {
  19. Service string `json:"service" xml:"service"`
  20. }
  21. // NotificationsData is the social-notification feed, which this server does not
  22. // keep.
  23. type NotificationsData struct {
  24. // Activities is always sent, empty included: the client maps over it
  25. // unconditionally on a 200.
  26. Activities []string `json:"activities" xml:"activities>activity"`
  27. }
  28. // ServicesData lists the IM services the account can sign on to.
  29. type ServicesData struct {
  30. // Services is always sent, empty included: the client iterates it
  31. // unconditionally on a 200.
  32. Services []Service `json:"services" xml:"services>service"`
  33. }
  34. // Service describes one signed-on or linkable IM service. Every field is sent
  35. // even when false or empty, because the client reads each one unconditionally
  36. // rather than testing for its presence.
  37. type Service struct {
  38. Name string `json:"name" xml:"name"`
  39. Service string `json:"service" xml:"service"`
  40. Associated bool `json:"associated" xml:"associated"`
  41. Online bool `json:"online" xml:"online"`
  42. // Roster is a third-party friend list available to import, not the buddy
  43. // list; this server federates with nothing, so there is never one.
  44. Roster bool `json:"roster" xml:"roster"`
  45. HaveRoster bool `json:"haveRoster" xml:"haveRoster"`
  46. AutoLogin bool `json:"autoLogin" xml:"autoLogin"`
  47. SignupURL string `json:"signupURL" xml:"signupURL"`
  48. }
  49. // GetServices advertises AIM as the only service, already signed on. The client
  50. // asks at sign-on to build its service list and to decide whether to offer a
  51. // link-account prompt for the others.
  52. func (h *UserInfoStubHandler) GetServices(w http.ResponseWriter, r *http.Request) {
  53. resp := BaseResponse{}
  54. resp.Response.StatusCode = 200
  55. resp.Response.StatusText = "OK"
  56. resp.Response.Data = &ServicesData{
  57. Services: []Service{
  58. {
  59. Name: "aim",
  60. Service: "aim",
  61. Associated: true,
  62. Online: true,
  63. },
  64. },
  65. }
  66. SendResponse(w, r, resp, h.Logger)
  67. }
  68. func (h *UserInfoStubHandler) GetUserDetails(w http.ResponseWriter, r *http.Request) {
  69. resp := BaseResponse{}
  70. resp.Response.StatusCode = 200
  71. resp.Response.StatusText = "OK"
  72. resp.Response.Data = &UserDetailsData{
  73. UserDetails: UserDetails{Services: []UserService{{Service: "aim"}}},
  74. }
  75. SendResponse(w, r, resp, h.Logger)
  76. }
  77. // HeyGetNotifications returns an empty social-notification feed.
  78. //
  79. // The activities array must be present even when empty: the client maps over
  80. // response.data.activities unconditionally on a 200, so omitting it raises
  81. // "Array.prototype.map called on null or undefined" and aborts the rest of the
  82. // notification setup.
  83. func (h *UserInfoStubHandler) HeyGetNotifications(w http.ResponseWriter, r *http.Request) {
  84. resp := BaseResponse{}
  85. resp.Response.StatusCode = 200
  86. resp.Response.StatusText = "OK"
  87. resp.Response.Data = &NotificationsData{Activities: []string{}}
  88. SendResponse(w, r, resp, h.Logger)
  89. }
  90. func (h *UserInfoStubHandler) EmptyOK(w http.ResponseWriter, r *http.Request) {
  91. h.emptyOK(w, r)
  92. }
  93. func (h *UserInfoStubHandler) emptyOK(w http.ResponseWriter, r *http.Request) {
  94. resp := BaseResponse{}
  95. resp.Response.StatusCode = 200
  96. resp.Response.StatusText = "OK"
  97. SendResponse(w, r, resp, h.Logger)
  98. }