sidechat.js 2.6.5 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/classes/SidechatAPIClient.d.ts +166 -11
  2. package/dist/classes/SidechatAPIClient.d.ts.map +1 -1
  3. package/dist/index.cjs +925 -365
  4. package/dist/index.mjs +925 -365
  5. package/dist/types/SidechatTypes.d.ts +260 -9
  6. package/dist/types/SidechatTypes.d.ts.map +1 -1
  7. package/docs/sidechat.js/2.6.6/SidechatAPIClient.html +3 -0
  8. package/docs/sidechat.js/2.6.6/SidechatAPIError.html +3 -0
  9. package/docs/sidechat.js/2.6.6/SidechatColorList.html +3 -0
  10. package/docs/sidechat.js/2.6.6/classes_SidechatAPIClient.js.html +1447 -0
  11. package/docs/sidechat.js/2.6.6/classes_SidechatAPIError.js.html +16 -0
  12. package/docs/sidechat.js/2.6.6/classes_SidechatColorList.js.html +79 -0
  13. package/docs/sidechat.js/2.6.6/data/search.json +1 -0
  14. package/docs/sidechat.js/2.6.6/fonts/Inconsolata-Regular.ttf +0 -0
  15. package/docs/sidechat.js/2.6.6/fonts/OpenSans-Regular.ttf +0 -0
  16. package/docs/sidechat.js/2.6.6/fonts/WorkSans-Bold.ttf +0 -0
  17. package/docs/sidechat.js/2.6.6/global.html +3 -0
  18. package/docs/sidechat.js/2.6.6/index.html +4 -0
  19. package/docs/sidechat.js/2.6.6/scripts/core.js +726 -0
  20. package/docs/sidechat.js/2.6.6/scripts/core.min.js +23 -0
  21. package/docs/sidechat.js/2.6.6/scripts/resize.js +90 -0
  22. package/docs/sidechat.js/2.6.6/scripts/search.js +265 -0
  23. package/docs/sidechat.js/2.6.6/scripts/search.min.js +6 -0
  24. package/docs/sidechat.js/2.6.6/scripts/third-party/Apache-License-2.0.txt +202 -0
  25. package/docs/sidechat.js/2.6.6/scripts/third-party/fuse.js +9 -0
  26. package/docs/sidechat.js/2.6.6/scripts/third-party/hljs-line-num-original.js +369 -0
  27. package/docs/sidechat.js/2.6.6/scripts/third-party/hljs-line-num.js +1 -0
  28. package/docs/sidechat.js/2.6.6/scripts/third-party/hljs-original.js +5171 -0
  29. package/docs/sidechat.js/2.6.6/scripts/third-party/hljs.js +1 -0
  30. package/docs/sidechat.js/2.6.6/scripts/third-party/popper.js +5 -0
  31. package/docs/sidechat.js/2.6.6/scripts/third-party/tippy.js +1 -0
  32. package/docs/sidechat.js/2.6.6/scripts/third-party/tocbot.js +672 -0
  33. package/docs/sidechat.js/2.6.6/scripts/third-party/tocbot.min.js +1 -0
  34. package/docs/sidechat.js/2.6.6/styles/clean-jsdoc-theme-base.css +1159 -0
  35. package/docs/sidechat.js/2.6.6/styles/clean-jsdoc-theme-dark.css +412 -0
  36. package/docs/sidechat.js/2.6.6/styles/clean-jsdoc-theme-light.css +482 -0
  37. package/docs/sidechat.js/2.6.6/styles/clean-jsdoc-theme-scrollbar.css +30 -0
  38. package/docs/sidechat.js/2.6.6/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
  39. package/docs/sidechat.js/2.6.6/styles/clean-jsdoc-theme.min.css +1 -0
  40. package/docs/sidechat.js/2.6.6/tutorial-Authentication.html +14 -0
  41. package/docs/sidechat.js/2.6.6/tutorial-Email Registration.html +6 -0
  42. package/docs/sidechat.js/2.6.6/types_SidechatTypes.js.html +204 -0
  43. package/docs/sidechat.js/2.7.0/SidechatAPIClient.html +3 -0
  44. package/docs/sidechat.js/2.7.0/SidechatAPIError.html +3 -0
  45. package/docs/sidechat.js/2.7.0/SidechatColorList.html +3 -0
  46. package/docs/sidechat.js/2.7.0/classes_SidechatAPIClient.js.html +1897 -0
  47. package/docs/sidechat.js/2.7.0/classes_SidechatAPIError.js.html +16 -0
  48. package/docs/sidechat.js/2.7.0/classes_SidechatColorList.js.html +79 -0
  49. package/docs/sidechat.js/2.7.0/data/search.json +1 -0
  50. package/docs/sidechat.js/2.7.0/fonts/Inconsolata-Regular.ttf +0 -0
  51. package/docs/sidechat.js/2.7.0/fonts/OpenSans-Regular.ttf +0 -0
  52. package/docs/sidechat.js/2.7.0/fonts/WorkSans-Bold.ttf +0 -0
  53. package/docs/sidechat.js/2.7.0/global.html +3 -0
  54. package/docs/sidechat.js/2.7.0/index.html +4 -0
  55. package/docs/sidechat.js/2.7.0/scripts/core.js +726 -0
  56. package/docs/sidechat.js/2.7.0/scripts/core.min.js +23 -0
  57. package/docs/sidechat.js/2.7.0/scripts/resize.js +90 -0
  58. package/docs/sidechat.js/2.7.0/scripts/search.js +265 -0
  59. package/docs/sidechat.js/2.7.0/scripts/search.min.js +6 -0
  60. package/docs/sidechat.js/2.7.0/scripts/third-party/Apache-License-2.0.txt +202 -0
  61. package/docs/sidechat.js/2.7.0/scripts/third-party/fuse.js +9 -0
  62. package/docs/sidechat.js/2.7.0/scripts/third-party/hljs-line-num-original.js +369 -0
  63. package/docs/sidechat.js/2.7.0/scripts/third-party/hljs-line-num.js +1 -0
  64. package/docs/sidechat.js/2.7.0/scripts/third-party/hljs-original.js +5171 -0
  65. package/docs/sidechat.js/2.7.0/scripts/third-party/hljs.js +1 -0
  66. package/docs/sidechat.js/2.7.0/scripts/third-party/popper.js +5 -0
  67. package/docs/sidechat.js/2.7.0/scripts/third-party/tippy.js +1 -0
  68. package/docs/sidechat.js/2.7.0/scripts/third-party/tocbot.js +672 -0
  69. package/docs/sidechat.js/2.7.0/scripts/third-party/tocbot.min.js +1 -0
  70. package/docs/sidechat.js/2.7.0/styles/clean-jsdoc-theme-base.css +1159 -0
  71. package/docs/sidechat.js/2.7.0/styles/clean-jsdoc-theme-dark.css +412 -0
  72. package/docs/sidechat.js/2.7.0/styles/clean-jsdoc-theme-light.css +482 -0
  73. package/docs/sidechat.js/2.7.0/styles/clean-jsdoc-theme-scrollbar.css +30 -0
  74. package/docs/sidechat.js/2.7.0/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
  75. package/docs/sidechat.js/2.7.0/styles/clean-jsdoc-theme.min.css +1 -0
  76. package/docs/sidechat.js/2.7.0/tutorial-Authentication.html +16 -0
  77. package/docs/sidechat.js/2.7.0/tutorial-Email Registration.html +6 -0
  78. package/docs/sidechat.js/2.7.0/tutorial-Feeds and Pagination.html +10 -0
  79. package/docs/sidechat.js/2.7.0/tutorial-Posting and Media.html +19 -0
  80. package/docs/sidechat.js/2.7.0/types_SidechatTypes.js.html +297 -0
  81. package/docs/tutorials/Authentication.md +63 -52
  82. package/docs/tutorials/Email Registration.md +19 -16
  83. package/docs/tutorials/Feeds and Pagination.md +45 -0
  84. package/docs/tutorials/Posting and Media.md +63 -0
  85. package/package.json +55 -55
  86. package/src/classes/SidechatAPIClient.js +549 -81
  87. package/src/types/SidechatTypes.js +294 -202
package/dist/index.cjs CHANGED
@@ -2,219 +2,311 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- /**
6
- * A user-created post or comment, depending on the "type" prop
7
- * @typedef {Object} SidechatPostOrComment
8
- * @prop {"post"|"comment"} type - whether this object represents a post or a comment on a post
9
- * @prop {String} id - alphanumeric ID of post or comment
10
- * @prop {Boolean} authored_by_user - whether or not the post or comment was created by the current user
11
- * @prop {String} alias - post creator's name in-app
12
- * @prop {String} group_id - alphanumeric ID of group
13
- * @prop {SidechatGroup} group - group in which post or comment was created
14
- * @prop {String} text - text content of post or comment
15
- * @prop {String} created_at - date string of post or comment creation time
16
- * @prop {Number} vote_total - sum of upvotes and downvotes
17
- * @prop {SidechatVoteString} vote_status - current user's vote on post or comment
18
- * @prop {SidechatSimpleAsset[]} assets - array of simple assets attached to post or comment
19
- * @prop {Array} attachments - undocumented
20
- * @prop {Boolean} dms_disabled - whether or not you can send a DM to creator of post
21
- * @prop {String[]} tags - undocumented
22
- * @prop {SidechatIdentity} identity - creator's identity information
23
- * @prop {Boolean} pinned - undocumented
24
- * @prop {Boolean} is_saved - whether or not the current user has saved the post
25
- * @prop {"following"|"not_following"} follow_status - whether or not the current user should recieve activity notifications for the post
26
- * @prop {"group"} [destination] - undocumented
27
- * @prop {Number} [comment_count] - number of comments on post (only if type=post)
28
- * @prop {Boolean} [comments_disabled] - whether or not you can comment on post (only if type=post)
29
- * @prop {SidechatPoll} [poll] - poll attached to post (only if the post has a poll)
30
- * @prop {String} [parent_post_id] - alphanumeric ID of parent post (only if type=comment)
31
- * @prop {String} [reply_post_id] - alphanumeric ID of comment being replied to, falls back to parent_post_id (only if type=comment)
32
- * @prop {String} [context] - text content of comment being replied to, falls back to text (only if type=comment)
33
- */
34
-
35
- /**
36
- * A group object, containing metadata about a group as well as its join conditions and states. Some properties vary based on the endpoint the object came from.
37
- * @typedef {Object} SidechatGroup
38
- * @prop {String} id - alphanumeric ID of group
39
- * @prop {String} name - human-readable name of group
40
- * @prop {String} analytics_name - name to file group under
41
- * @prop {"non_member"|"member"} membership_type - whether or not current user is a member of group
42
- * @prop {String} color - group's theme color as hex code (e.g., #FFFFFF)
43
- * @prop {"open"|"closed"|"email_domain"} group_join_type - basis on which group accepts new members
44
- * @prop {"private"|"public_to_all"|"public_to_schools"} group_visibility - group's visibility setting
45
- * @prop {"show"|"hide"} asset_library_visibility - whether or not group's asset library is visible
46
- * @prop {Array} [roles] - undocumented
47
- * @prop {String} [description] - description of group
48
- * @prop {SidechatPrivateAssetURL} [icon_url] - image URL for group icon
49
- * @prop {Number} [member_count] - number of users in group
50
- * @prop {Boolean} [should_show_leaderboard] - undocumented
51
- */
52
-
53
- /**
54
- * An asset object, containing information about an image within a post or comment
55
- * @typedef {Object} SidechatSimpleAsset
56
- * @prop {String} id - alphanumeric ID of asset
57
- * @prop {"image"} type - undocumented
58
- * @prop {"jpeg"|"png"|"gif"} content_type - file type of asset
59
- * @prop {Number} width - width of asset
60
- * @prop {Number} height - height of asset
61
- * @prop {SidechatPrivateAssetURL} [url] - URL string of asset's location
62
- */
63
-
64
- /**
65
- * An asset object, containing information about an image from the asset library
66
- * @typedef {Object} SidechatLibraryAsset
67
- * @prop {String} id - alphanumeric ID of asset
68
- * @prop {String} created_at - date string of asset creation time
69
- * @prop {SidechatAssetMetadata} metadata - metadata associated with asset
70
- * @prop {SidechatPrivateAssetURL} url - URL string of asset's location
71
- */
72
-
73
- /**
74
- * An asset object, containing information about an image from the asset library
75
- * @typedef {Object} SidechatAssetMetadata
76
- * @prop {Number} width - width of asset
77
- * @prop {Number} height - height of asset
78
- * @prop {"image"} type - undocumented
79
- * @prop {"jpeg"|"png"|"gif"} content_type - file type of asset
80
- */
81
-
82
- /**
83
- * A user's anonymous identity information
84
- * @typedef {Object} SidechatIdentity
85
- * @prop {String} name - representation of user's name (varies across app)
86
- * @prop {Boolean} posted_with_username - undocumented
87
- */
88
-
89
- /**
90
- * A conversation icon associated with a user
91
- * @typedef {Object} SidechatIcon
92
- * @prop {String} emoji - unicode emoji character
93
- * @prop {String} color - primary hex color code
94
- * @prop {String} secondary_color - secondary hex color code
95
- */
96
-
97
- /**
98
- * The current user's information
99
- * @typedef {Object} SidechatCurrentUser
100
- * @prop {String} id - alphanumeric ID of current user
101
- * @prop {String} hashedVerifiedEmail - verified email of current user in an unreadable hashed form
102
- * @prop {Boolean} isGlobalModerator - whether or not user is a moderator
103
- * @prop {Boolean} isGlobalAdmin - whether or not user is an admin
104
- * @prop {SidechatMembership[]} memberships
105
- * @prop {Array} roles - undocumented
106
- * @prop {String} emailDomain - domain of verified email address on account
107
- * @prop {String} wildcardEmailDomain - domain of verified email address on account, preceeded by *. to support subdomains
108
- */
109
-
110
- /**
111
- * A user's public profile
112
- * @typedef {Object} SidechatProfile
113
- * @prop {String} id - alphanumeric ID of user
114
- * @prop {String} name - public-facing username
115
- * @prop {SidechatIcon} conversation_icon - icon associated with user
116
- * @prop {Boolean} description - the user bio
117
- * @prop {String} index_name - undocumented
118
- * @prop {String} analytics_name - undocumented
119
- * @prop {String} color - undocumented
120
- * @prop {String} share_color_start - undocumented
121
- * @prop {String} share_color_end - undocumented
122
- * @prop {"account"} group_join_type - undocumented
123
- * @prop {"public_to_all"} group_visibility - the profile visibility status
124
- */
125
-
126
- /**
127
- * Representation of a group membership
128
- * @typedef {Object} SidechatMembership
129
- * @prop {String} groupId - alphanumeric ID of group
130
- * @prop {String} type - role of current user in group
131
- */
132
-
133
- /**
134
- * An asset URL that can only be accessed by making a request with a user's bearer token attached in the Authorization header
135
- * @typedef {String} SidechatPrivateAssetURL
136
- */
137
-
138
- /**
139
- * A cursor for paginating through post lists
140
- * @typedef {String} SidechatCursorString
141
- */
142
-
143
- /**
144
- * A vote on a comment or post
145
- * @typedef {"upvote"|"downvote"|"none"} SidechatVoteString
146
- */
147
-
148
- /**
149
- * A user's bearer authentication token needed for most requests
150
- * @typedef {String} SidechatAuthToken
151
- */
152
-
153
- /**
154
- * A list of posts and the associated cursor
155
- * @typedef {Object} SidechatPostsAndCursor
156
- * @prop {SidechatPostOrComment[]} posts
157
- * @prop {SidechatCursorString} cursor
158
- */
159
-
160
-
161
- /**
162
- * A direct message thread
163
- * @typedef {Object} SidechatDirectThread
164
- * @prop {String} id - alphanumeric ID of thread
165
- * @prop {String} group_id - alphanumeric ID of group in which the thread exists
166
- * @prop {String} updated_at - date string of when the last message in the chat was sent
167
- * @prop {String} post_id - post or comment from which the thread was originally sent
168
- * @prop {String} post_context - the context of the DM thread (only "feed" is known at the moment)
169
- * @prop {"accepted"} accept_status - whether or not the other user has accepted this DM
170
- * @prop {"post"|"comment"} type - the type of the content from which the DM was originally sent
171
- * @prop {SidechatDirectMessage[]} messages - array of direct message objects
172
- */
173
-
174
- /**
175
- * A single direct message
176
- * @typedef {Object} SidechatDirectMessage
177
- * @prop {String} created_at - time at which the message was sent
178
- * @prop {String} client_id - alphanumeric ID of the device the message was sent on
179
- * @prop {String} obfuscatedUserId - obfuscated version of the sender's alphanumeric ID
180
- * @prop {String} text - body text of the message
181
- * @prop {String} id - alphanumeric ID of the message
182
- * @prop {String} chat_id - alphanumeric ID of the thread in which the message resides
183
- * @prop {Boolean} authored_by_user - whether or not the current user sent the message
184
- * @prop {"message"} type - undocumented
185
- */
186
-
187
- /**
188
- * Represents a poll with choices
189
- * @typedef {Object} SidechatPoll
190
- * @prop {String} id - alphanumeric ID of poll
191
- * @prop {String} post_id - alphanumeric ID of post to which poll is attached
192
- * @prop {SidechatPollChoice[]} choices - array of poll choices
193
- * @prop {Boolean} allows_view_results - whether or not poll results are publicly visible
194
- * @prop {Number} view_results_count - number of users who have viewed poll results
195
- * @prop {Boolean} participated - whether or not current user has voted in poll
196
- */
197
-
198
- /**
199
- * Represents a poll choice
200
- * @typedef {Object} SidechatPollChoice
201
- * @prop {Number} count - number of votes for choice
202
- * @prop {String} text - user-visible text of choice
203
- * @prop {Boolean} selected - whether or not current user has voted for choice
204
- */
205
-
5
+ /**
6
+ * A user-created post or comment, depending on the "type" prop
7
+ * @typedef {Object} SidechatPostOrComment
8
+ * @prop {"post"|"comment"} type - whether this object represents a post or a comment on a post
9
+ * @prop {String} id - alphanumeric ID of post or comment
10
+ * @prop {Boolean} authored_by_user - whether or not the post or comment was created by the current user
11
+ * @prop {String} alias - post creator's name in-app
12
+ * @prop {String} group_id - alphanumeric ID of group
13
+ * @prop {SidechatGroup} group - group in which post or comment was created
14
+ * @prop {String} text - text content of post or comment
15
+ * @prop {String} created_at - date string of post or comment creation time
16
+ * @prop {Number} vote_total - sum of upvotes and downvotes
17
+ * @prop {SidechatVoteString} vote_status - current user's vote on post or comment
18
+ * @prop {SidechatSimpleAsset[]} assets - array of simple assets attached to post or comment
19
+ * @prop {SidechatAttachment[]} attachments - link attachments on the post
20
+ * @prop {Boolean} dms_disabled - whether or not you can send a DM to creator of post
21
+ * @prop {String[]} tags - undocumented
22
+ * @prop {SidechatIdentity} identity - creator's identity information
23
+ * @prop {Boolean} pinned - undocumented
24
+ * @prop {Boolean} is_saved - whether or not the current user has saved the post
25
+ * @prop {"following"|"following_commented"|"not_following"} follow_status - whether or not the current user should recieve activity notifications for the post
26
+ * @prop {"group"|"account"} [destination] - whether the post was made in a group or on the author's profile
27
+ * @prop {Boolean} [is_deleted] - whether or not the post or comment has been deleted
28
+ * @prop {{post: SidechatPostOrComment, is_unavailable: Boolean}} [quote_post] - the post being quoted, if this is a repost
29
+ * @prop {Number} [comment_count] - number of comments on post (only if type=post)
30
+ * @prop {Boolean} [comments_disabled] - whether or not you can comment on post (only if type=post)
31
+ * @prop {SidechatPoll} [poll] - poll attached to post (only if the post has a poll)
32
+ * @prop {String} [parent_post_id] - alphanumeric ID of parent post (only if type=comment)
33
+ * @prop {String} [reply_post_id] - alphanumeric ID of comment being replied to, falls back to parent_post_id (only if type=comment)
34
+ * @prop {String} [context] - text content of comment being replied to, falls back to text (only if type=comment)
35
+ */
36
+
37
+ /**
38
+ * A group object, containing metadata about a group as well as its join conditions and states. Some properties vary based on the endpoint the object came from.
39
+ * @typedef {Object} SidechatGroup
40
+ * @prop {String} id - alphanumeric ID of group
41
+ * @prop {String} name - human-readable name of group
42
+ * @prop {String} analytics_name - name to file group under
43
+ * @prop {"non_member"|"member"} membership_type - whether or not current user is a member of group
44
+ * @prop {String} color - group's theme color as hex code (e.g., #FFFFFF)
45
+ * @prop {"open"|"closed"|"email_domain"} group_join_type - basis on which group accepts new members
46
+ * @prop {"private"|"public_to_all"|"public_to_schools"} group_visibility - group's visibility setting
47
+ * @prop {"show"|"hide"} asset_library_visibility - whether or not group's asset library is visible
48
+ * @prop {Array} [roles] - undocumented
49
+ * @prop {String} [description] - description of group
50
+ * @prop {SidechatPrivateAssetURL} [icon_url] - image URL for group icon
51
+ * @prop {Number} [member_count] - number of users in group
52
+ * @prop {Boolean} [should_show_leaderboard] - undocumented
53
+ */
54
+
55
+ /**
56
+ * An asset object, containing information about an image within a post or comment
57
+ * @typedef {Object} SidechatSimpleAsset
58
+ * @prop {String} id - alphanumeric ID of asset
59
+ * @prop {"image"|"video"} type - whether the asset is an image or a video
60
+ * @prop {"jpeg"|"png"|"gif"|"webp"|"mp4"|"mov"} content_type - file type of asset
61
+ * @prop {Number} width - width of asset
62
+ * @prop {Number} height - height of asset
63
+ * @prop {SidechatPrivateAssetURL} [url] - URL string of asset's location (an HLS .m3u8 stream for processed videos)
64
+ * @prop {SidechatSimpleAsset} [thumbnail_asset] - preview image (only if type=video)
65
+ * @prop {"not_started"|"ingest"|"complete"|"error"} [vod_status] - processing status (only if type=video)
66
+ */
67
+
68
+ /**
69
+ * An asset object, containing information about an image from the asset library
70
+ * @typedef {Object} SidechatLibraryAsset
71
+ * @prop {String} id - alphanumeric ID of asset
72
+ * @prop {String} created_at - date string of asset creation time
73
+ * @prop {SidechatAssetMetadata} metadata - metadata associated with asset
74
+ * @prop {SidechatPrivateAssetURL} url - URL string of asset's location
75
+ */
76
+
77
+ /**
78
+ * An asset object, containing information about an image from the asset library
79
+ * @typedef {Object} SidechatAssetMetadata
80
+ * @prop {Number} width - width of asset
81
+ * @prop {Number} height - height of asset
82
+ * @prop {"image"} type - undocumented
83
+ * @prop {"jpeg"|"png"|"gif"} content_type - file type of asset
84
+ */
85
+
86
+ /**
87
+ * A user's anonymous identity information
88
+ * @typedef {Object} SidechatIdentity
89
+ * @prop {String} name - representation of user's name (varies across app)
90
+ * @prop {Boolean} posted_with_username - undocumented
91
+ */
92
+
93
+ /**
94
+ * A conversation icon associated with a user
95
+ * @typedef {Object} SidechatIcon
96
+ * @prop {String} emoji - unicode emoji character
97
+ * @prop {String} color - primary hex color code
98
+ * @prop {String} secondary_color - secondary hex color code
99
+ */
100
+
101
+ /**
102
+ * The current user's information
103
+ * @typedef {Object} SidechatCurrentUser
104
+ * @prop {String} id - alphanumeric ID of current user
105
+ * @prop {String} hashedVerifiedEmail - verified email of current user in an unreadable hashed form
106
+ * @prop {Boolean} isGlobalModerator - whether or not user is a moderator
107
+ * @prop {Boolean} isGlobalAdmin - whether or not user is an admin
108
+ * @prop {SidechatMembership[]} memberships
109
+ * @prop {Array} roles - undocumented
110
+ * @prop {String} emailDomain - domain of verified email address on account
111
+ * @prop {String} wildcardEmailDomain - domain of verified email address on account, preceeded by *. to support subdomains
112
+ */
113
+
114
+ /**
115
+ * A user's public profile
116
+ * @typedef {Object} SidechatProfile
117
+ * @prop {String} id - alphanumeric ID of user
118
+ * @prop {String} name - public-facing username
119
+ * @prop {SidechatIcon} conversation_icon - icon associated with user
120
+ * @prop {Boolean} description - the user bio
121
+ * @prop {String} index_name - undocumented
122
+ * @prop {String} analytics_name - undocumented
123
+ * @prop {String} color - undocumented
124
+ * @prop {String} share_color_start - undocumented
125
+ * @prop {String} share_color_end - undocumented
126
+ * @prop {"account"} group_join_type - undocumented
127
+ * @prop {"public_to_all"} group_visibility - the profile visibility status
128
+ */
129
+
130
+ /**
131
+ * Representation of a group membership
132
+ * @typedef {Object} SidechatMembership
133
+ * @prop {String} groupId - alphanumeric ID of group
134
+ * @prop {String} type - role of current user in group
135
+ */
136
+
137
+ /**
138
+ * An asset URL that can only be accessed by making a request with a user's bearer token attached in the Authorization header
139
+ * @typedef {String} SidechatPrivateAssetURL
140
+ */
141
+
142
+ /**
143
+ * A cursor for paginating through post lists
144
+ * @typedef {String} SidechatCursorString
145
+ */
146
+
147
+ /**
148
+ * A vote on a comment or post
149
+ * @typedef {"upvote"|"downvote"|"none"} SidechatVoteString
150
+ */
151
+
152
+ /**
153
+ * A user's bearer authentication token needed for most requests
154
+ * @typedef {String} SidechatAuthToken
155
+ */
156
+
157
+ /**
158
+ * A list of posts and the associated cursor
159
+ * @typedef {Object} SidechatPostsAndCursor
160
+ * @prop {SidechatPostOrComment[]} posts
161
+ * @prop {SidechatCursorString} cursor
162
+ */
163
+
164
+ /**
165
+ * A direct message thread
166
+ * @typedef {Object} SidechatDirectThread
167
+ * @prop {String} id - alphanumeric ID of thread
168
+ * @prop {String} group_id - alphanumeric ID of group in which the thread exists
169
+ * @prop {String} updated_at - date string of when the last message in the chat was sent
170
+ * @prop {String} post_id - post or comment from which the thread was originally sent
171
+ * @prop {String} post_context - the context of the DM thread (only "feed" is known at the moment)
172
+ * @prop {"accepted"} accept_status - whether or not the other user has accepted this DM
173
+ * @prop {"post"|"comment"} type - the type of the content from which the DM was originally sent
174
+ * @prop {SidechatDirectMessage[]} messages - array of direct message objects
175
+ */
176
+
177
+ /**
178
+ * A single direct message
179
+ * @typedef {Object} SidechatDirectMessage
180
+ * @prop {String} created_at - time at which the message was sent
181
+ * @prop {String} client_id - alphanumeric ID of the device the message was sent on
182
+ * @prop {String} obfuscatedUserId - obfuscated version of the sender's alphanumeric ID
183
+ * @prop {String} text - body text of the message
184
+ * @prop {String} id - alphanumeric ID of the message
185
+ * @prop {String} chat_id - alphanumeric ID of the thread in which the message resides
186
+ * @prop {Boolean} authored_by_user - whether or not the current user sent the message
187
+ * @prop {"message"} type - undocumented
188
+ */
189
+
190
+ /**
191
+ * Represents a poll with choices
192
+ * @typedef {Object} SidechatPoll
193
+ * @prop {String} id - alphanumeric ID of poll
194
+ * @prop {String} post_id - alphanumeric ID of post to which poll is attached
195
+ * @prop {SidechatPollChoice[]} choices - array of poll choices
196
+ * @prop {Boolean} allows_view_results - whether or not poll results are publicly visible
197
+ * @prop {Number} view_results_count - number of users who have viewed poll results
198
+ * @prop {Boolean} participated - whether or not current user has voted in poll
199
+ */
200
+
201
+ /**
202
+ * Represents a poll choice
203
+ * @typedef {Object} SidechatPollChoice
204
+ * @prop {Number} count - number of votes for choice
205
+ * @prop {String} text - user-visible text of choice
206
+ * @prop {Boolean} selected - whether or not current user has voted for choice
207
+ */
208
+
209
+ /**
210
+ * A link attachment on a post
211
+ * @typedef {Object} SidechatAttachment
212
+ * @prop {String} id - alphanumeric ID of attachment
213
+ * @prop {"link"|"youtube"} type - whether the link is a regular link or a YouTube video
214
+ * @prop {String} link_url - URL the attachment points to
215
+ * @prop {String} [display_url] - shortened URL for display
216
+ * @prop {String} [title] - title of the linked page
217
+ * @prop {{id: String, url: String, width: Number, height: Number, content_type: "png"|"gif"}} [asset] - preview image of the linked page
218
+ */
219
+
220
+ /**
221
+ * A page of the home feed
222
+ * @typedef {Object} SidechatFeed
223
+ * @prop {SidechatFeedItem[]} feed_items - items in the feed
224
+ * @prop {SidechatCursorString} cursor
225
+ */
226
+
227
+ /**
228
+ * A single item in the home feed
229
+ * @typedef {Object} SidechatFeedItem
230
+ * @prop {String} item_type - type of item (posts have a type of "post")
231
+ * @prop {SidechatPostOrComment} [post] - the post, if this item is a post
232
+ */
233
+
234
+ /**
235
+ * A page of the user's activity
236
+ * @typedef {Object} SidechatActivityList
237
+ * @prop {SidechatActivityItem[]} items - activity items
238
+ * @prop {SidechatCursorString} cursor
239
+ */
240
+
241
+ /**
242
+ * A single activity item (in-app notification)
243
+ * @typedef {Object} SidechatActivityItem
244
+ * @prop {String} id - alphanumeric ID of activity item
245
+ * @prop {String} type - kind of activity (e.g. "comment", "comment_reply", "votes", "new_follower", "quote", "trending_post")
246
+ * @prop {String} text - user-facing description of the activity
247
+ * @prop {String} timestamp - date string of when the activity happened
248
+ * @prop {Boolean} is_seen - whether or not the user has seen the activity
249
+ * @prop {String} [post_id] - alphanumeric ID of related post
250
+ * @prop {String} [comment_id] - alphanumeric ID of related comment
251
+ * @prop {String} [group_id] - alphanumeric ID of related group
252
+ * @prop {Number} [yakarma] - yakarma gained
253
+ * @prop {String} [username] - username of the other user involved, if any
254
+ */
255
+
256
+ /**
257
+ * A group leaderboard and the current user's place in it
258
+ * @typedef {Object} SidechatLeaderboard
259
+ * @prop {Array<{value: Number}>} leaderboard - all-time leaderboard entries
260
+ * @prop {Array<{value: Number}>} season_leaderboard - leaderboard entries for the current season
261
+ * @prop {{year: Number, season: String, remaining_days: Number}} season - the current season
262
+ * @prop {SidechatKarma} karma - current user's all-time karma in the group
263
+ * @prop {SidechatKarma} season_karma - current user's karma this season
264
+ */
265
+
266
+ /**
267
+ * A user's karma within a group
268
+ * @typedef {Object} SidechatKarma
269
+ * @prop {String} group_id - alphanumeric ID of group
270
+ * @prop {Number} post - karma from posts
271
+ * @prop {Number} comment - karma from comments
272
+ * @prop {Number} yakarma - total karma
273
+ */
274
+
275
+ /**
276
+ * Which push notifications a user receives
277
+ * @typedef {Object} SidechatNotificationPreferences
278
+ * @prop {Boolean} [chats] - direct messages
279
+ * @prop {Boolean} [followed_posts_activity] - new comments on followed posts
280
+ * @prop {Boolean} [new_followers] - new followers
281
+ * @prop {Boolean} [post_activity] - comments and votes on the user's own posts
282
+ * @prop {Boolean} [trending] - trending posts
283
+ * @prop {Boolean} [community_activity] - undocumented
284
+ * @prop {Boolean} [leaderboards] - leaderboard updates
285
+ * @prop {Boolean} [rewards] - undocumented
286
+ * @prop {Boolean} [feature_updates] - announcements about new features
287
+ * @prop {Boolean} [yak_ball_updates] - undocumented
288
+ * @prop {Boolean} [game_reminders] - undocumented
289
+ * @prop {Boolean} [daily_game_reminders] - undocumented
290
+ * @prop {Boolean} [game_invitations] - undocumented
291
+ * @prop {Boolean} [game_match_updates] - undocumented
292
+ */
293
+ /**
294
+ * A reason for reporting a post, comment, or direct message thread
295
+ * @typedef {"username"|"spam"|"offTopic"|"pii"|"selfHarmDangerousActs"|"illegalActivities"|"offensiveHateSpeech"|"harassmentBullying"|"minorSafety"|"sexualContent"|"violentGraphicContent"|"misinformation"|"other"} SidechatReportReason
296
+ */
297
+
206
298
  var SidechatTypes = {};
207
299
 
208
- /**
209
- * Throwable error caused by the Sidechat API
210
- * @class
211
- * @extends Error
212
- */
213
- class SidechatAPIError extends Error {
214
- constructor(message) {
215
- super(message);
216
- this.name = "SidechatAPIError";
217
- }
300
+ /**
301
+ * Throwable error caused by the Sidechat API
302
+ * @class
303
+ * @extends Error
304
+ */
305
+ class SidechatAPIError extends Error {
306
+ constructor(message) {
307
+ super(message);
308
+ this.name = "SidechatAPIError";
309
+ }
218
310
  }
219
311
 
220
312
  /** @import * as types from "../types/SidechatTypes.js" */
@@ -284,6 +376,16 @@ class SidechatAPIClient {
284
376
  this.apiRoot = url;
285
377
  };
286
378
 
379
+ /**
380
+ * Set an identifier for this device, which will be sent with every request in the `X-Device-ID` header. Should be stable across sessions on the same device.
381
+ * @method
382
+ * @param {String} deviceIdentifier - stable identifier for this device
383
+ * @since 2.7.0
384
+ */
385
+ setDeviceIdentifier = (deviceIdentifier) => {
386
+ this.defaultHeaders["X-Device-ID"] = deviceIdentifier;
387
+ };
388
+
287
389
  /**
288
390
  * Run an arbitrary API request using the current client's authentication
289
391
  * @method
@@ -299,7 +401,7 @@ class SidechatAPIClient {
299
401
  method = "GET",
300
402
  body = undefined,
301
403
  headers = {},
302
- stripHeaders = false
404
+ stripHeaders = false,
303
405
  ) => {
304
406
  let requestHeaders = this.defaultHeaders;
305
407
  if (stripHeaders) {
@@ -314,19 +416,32 @@ class SidechatAPIClient {
314
416
  };
315
417
 
316
418
  /**
317
- * Initiate the login process with a phone number. Should be followed up with verifySMSCode().
419
+ * Initiate the login process with a phone number. Should be followed up with verifySMSCode(). If the response has an `error_code` of `"captcha_required"`, the server wants a captcha solved before it will send a code, and the request should be repeated with a captcha response. I haven't been able to recreate this yet, so I honestly don't know what captcha provider they want.
318
420
  * @method
319
421
  * @since 1.0.0
320
422
  * @param {Number} phoneNumber - US phone number (WITHOUT +1) to send verification code to
423
+ * @param {Boolean} [useFallback] - send the code through the backup SMS route, which the official app offers when a code doesn't arrive
424
+ * @param {String} [captchaMethod] - type of captcha being answered
425
+ * @param {String} [captchaResponse] - solved captcha token
321
426
  */
322
- loginViaSMS = async (phoneNumber) => {
427
+ loginViaSMS = async (
428
+ phoneNumber,
429
+ useFallback = false,
430
+ captchaMethod = undefined,
431
+ captchaResponse = undefined,
432
+ ) => {
323
433
  try {
324
- const res = await fetch(`${this.apiRoot}/v1/login_register`, {
434
+ const endpoint = useFallback
435
+ ? "/v1/login_register_sms_fallback"
436
+ : "/v1/login_register";
437
+ const res = await fetch(`${this.apiRoot}${endpoint}`, {
325
438
  method: "POST",
326
439
  headers: this.defaultHeaders,
327
440
  body: JSON.stringify({
328
441
  phone_number: `+1${phoneNumber}`,
329
442
  version: 3,
443
+ captcha_method: captchaMethod,
444
+ captcha_response: captchaResponse,
330
445
  }),
331
446
  });
332
447
  const json = await res.json();
@@ -371,8 +486,15 @@ class SidechatAPIClient {
371
486
  * @since 1.0.0
372
487
  * @param {Number} age - user's age in years
373
488
  * @param {String} registrationID - the registration ID generated by verifySMSCode()
489
+ * @param {String} [timeZone] - time zone of the user (e.g. "America/Chicago"). Falls back to the system time zone.
490
+ * @param {String} [inviteLinkURL] - group invite link that the user signed up through
374
491
  */
375
- setAge = async (age, registrationID) => {
492
+ setAge = async (
493
+ age,
494
+ registrationID,
495
+ timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone,
496
+ inviteLinkURL = undefined,
497
+ ) => {
376
498
  if (age < 13) {
377
499
  throw new SidechatAPIError("You're too young to use Offsides.");
378
500
  }
@@ -383,6 +505,9 @@ class SidechatAPIClient {
383
505
  body: JSON.stringify({
384
506
  age: Number(age),
385
507
  registration_id: registrationID,
508
+ time_zone: timeZone,
509
+ invite_link_url: inviteLinkURL,
510
+ device_id: this.defaultHeaders["X-Device-ID"],
386
511
  }),
387
512
  });
388
513
  const json = await res.json();
@@ -465,8 +590,9 @@ class SidechatAPIClient {
465
590
  * @method
466
591
  * @since 1.0.0
467
592
  * @param {String} deviceId - the device ID to set
593
+ * @param {"com.flowerave.sidechat"|"com.flowerave.yikyak"} [bundleID] - bundle ID of the app the push token belongs to
468
594
  */
469
- setDeviceID = async (deviceID) => {
595
+ setDeviceID = async (deviceID, bundleID = "com.flowerave.sidechat") => {
470
596
  if (!this.userToken) {
471
597
  throw new SidechatAPIError("User is not authenticated.");
472
598
  }
@@ -479,7 +605,7 @@ class SidechatAPIClient {
479
605
  },
480
606
  body: JSON.stringify({
481
607
  build_type: "release",
482
- bundle_id: "com.flowerave.sidechat",
608
+ bundle_id: bundleID,
483
609
  device_token: deviceID,
484
610
  }),
485
611
  });
@@ -522,7 +648,7 @@ class SidechatAPIClient {
522
648
  ...this.defaultHeaders,
523
649
  Authorization: `Bearer ${this.userToken}`,
524
650
  },
525
- }
651
+ },
526
652
  );
527
653
  const json = await res.json();
528
654
  return json;
@@ -539,23 +665,27 @@ class SidechatAPIClient {
539
665
  * @param {String} groupID - group ID
540
666
  * @param {"hot"|"recent"|"top"} category - category to filter posts
541
667
  * @param {types.SidechatCursorString} [cursor] - cursor string
668
+ * @param {"day"|"week"|"month"|"year"|"all_time"} [period] - time period to pull top posts from (only if category is "top")
542
669
  * @returns {Promise<types.SidechatPostsAndCursor>} List of posts and cursor
543
670
  */
544
- getGroupPosts = async (groupID, category = "hot", cursor) => {
671
+ getGroupPosts = async (groupID, category = "hot", cursor, period) => {
545
672
  if (!this.userToken) {
546
673
  throw new SidechatAPIError("User is not authenticated.");
547
674
  }
548
675
  try {
549
676
  const res = await fetch(
550
- `${this.apiRoot}/v1/posts?${cursor ? "cursor=" + encodeURIComponent(cursor) + "&" : ""
551
- }group_id=${groupID}&type=${category}`,
677
+ `${this.apiRoot}/v1/posts?${
678
+ cursor ? "cursor=" + encodeURIComponent(cursor) + "&" : ""
679
+ }${
680
+ period ? "period=" + period + "&" : ""
681
+ }group_id=${groupID}&type=${category}&cacheBust=${Date.now()}`,
552
682
  {
553
683
  method: "GET",
554
684
  headers: {
555
685
  ...this.defaultHeaders,
556
686
  Authorization: `Bearer ${this.userToken}`,
557
687
  },
558
- }
688
+ },
559
689
  );
560
690
  const json = await res.json();
561
691
  return json;
@@ -610,14 +740,14 @@ class SidechatAPIClient {
610
740
  }
611
741
  try {
612
742
  const res = await fetch(
613
- `${this.apiRoot}/v1/posts/get?include_deleted=${includeDeleted}&post_id=${postID}`,
743
+ `${this.apiRoot}/v1/posts/get?include_deleted=${includeDeleted}&post_id=${postID}&cacheBust=${Date.now()}`,
614
744
  {
615
745
  method: "GET",
616
746
  headers: {
617
747
  ...this.defaultHeaders,
618
748
  Authorization: `Bearer ${this.userToken}`,
619
749
  },
620
- }
750
+ },
621
751
  );
622
752
  const json = await res.json();
623
753
  return json.post;
@@ -644,7 +774,7 @@ class SidechatAPIClient {
644
774
  contentType = "my_comments";
645
775
  }
646
776
  try {
647
- const res = await fetch(`${this.apiRoot}/v1/posts&type=${contentType}`, {
777
+ const res = await fetch(`${this.apiRoot}/v1/posts?type=${contentType}`, {
648
778
  method: "GET",
649
779
  headers: {
650
780
  ...this.defaultHeaders,
@@ -672,14 +802,14 @@ class SidechatAPIClient {
672
802
  }
673
803
  try {
674
804
  const res = await fetch(
675
- `${this.apiRoot}/v1/posts/comments/?post_id=${postID}`,
805
+ `${this.apiRoot}/v1/posts/comments/?post_id=${postID}&cacheBust=${Date.now()}`,
676
806
  {
677
807
  method: "GET",
678
808
  headers: {
679
809
  ...this.defaultHeaders,
680
810
  Authorization: `Bearer ${this.userToken}`,
681
811
  },
682
- }
812
+ },
683
813
  );
684
814
  const json = await res.json();
685
815
  // Function to preprocess the comments and organize them into a nested structure
@@ -775,13 +905,16 @@ class SidechatAPIClient {
775
905
  throw new SidechatAPIError("User is not authenticated.");
776
906
  }
777
907
  try {
778
- const res = await fetch(`${this.apiRoot}/v1/groups/explore/search?term=${encodeURIComponent(query)}`, {
779
- method: "GET",
780
- headers: {
781
- ...this.defaultHeaders,
782
- Authorization: `Bearer ${this.userToken}`,
908
+ const res = await fetch(
909
+ `${this.apiRoot}/v1/groups/explore/search?term=${encodeURIComponent(query)}`,
910
+ {
911
+ method: "GET",
912
+ headers: {
913
+ ...this.defaultHeaders,
914
+ Authorization: `Bearer ${this.userToken}`,
915
+ },
783
916
  },
784
- });
917
+ );
785
918
  const json = await res.json();
786
919
  return await json.results;
787
920
  } catch (err) {
@@ -881,8 +1014,9 @@ class SidechatAPIClient {
881
1014
  throw new SidechatAPIError("User is not authenticated.");
882
1015
  }
883
1016
  try {
1017
+ // Joining moved to the v2 endpoint, which takes a list of IDs. Leave still sends group_id by itself, no list.
884
1018
  const res = await fetch(
885
- `${this.apiRoot}/v1/groups/${isMember ? "join" : "leave"}`,
1019
+ `${this.apiRoot}${isMember ? "/v2/groups/join" : "/v1/groups/leave"}`,
886
1020
  {
887
1021
  method: "POST",
888
1022
  headers: {
@@ -890,9 +1024,10 @@ class SidechatAPIClient {
890
1024
  Authorization: `Bearer ${this.userToken}`,
891
1025
  },
892
1026
  body: JSON.stringify({
893
- group_id: groupID,
1027
+ group_id: isMember ? undefined : groupID,
1028
+ group_ids: [groupID],
894
1029
  }),
895
- }
1030
+ },
896
1031
  );
897
1032
  const json = await res.json();
898
1033
  return await json;
@@ -924,7 +1059,7 @@ class SidechatAPIClient {
924
1059
  topLevelReplyID,
925
1060
  assetList = [],
926
1061
  disableDMs = false,
927
- anonymous = false
1062
+ anonymous = false,
928
1063
  ) => {
929
1064
  if (!this.userToken) {
930
1065
  throw new SidechatAPIError("User is not authenticated.");
@@ -949,15 +1084,17 @@ class SidechatAPIClient {
949
1084
  }),
950
1085
  });
951
1086
  const json = await res.json();
1087
+ if (!res.ok) throw new SidechatAPIError(json.message);
952
1088
  return await json.comment;
953
1089
  } catch (err) {
954
1090
  console.error(err);
1091
+ if (err instanceof SidechatAPIError && err.message) throw err;
955
1092
  throw new SidechatAPIError(`Failed to post comment.`);
956
1093
  }
957
1094
  };
958
1095
 
959
1096
  /**
960
- * Creates a new post in the specified group
1097
+ * Creates a new post in the specified group. Users can only make two posts a minute; if a post is rejected, the thrown error contains the reason from the server.
961
1098
  * @method
962
1099
  * @since 2.2.0
963
1100
  * @param {String} text - text content of comment
@@ -967,6 +1104,7 @@ class SidechatAPIClient {
967
1104
  * @param {Boolean} [disableComments] - whether or not comments should be disabled on post
968
1105
  * @param {Boolean} [anonymous] - whether or not to hide user's name and icon on post
969
1106
  * @param {Array<String>} [pollOptions] - List of poll options. If provided, a poll will be created with these options.
1107
+ * @param {Array<String>} [attachmentIDs] - IDs of link attachments created with createLinkAttachment()
970
1108
  * @returns {Promise<types.SidechatPostOrComment>} the created post
971
1109
  */
972
1110
  createPost = async (
@@ -977,7 +1115,8 @@ class SidechatAPIClient {
977
1115
  disableComments = false,
978
1116
  anonymous = false,
979
1117
  repostId = undefined,
980
- pollOptions = undefined
1118
+ pollOptions = undefined,
1119
+ attachmentIDs = [],
981
1120
  ) => {
982
1121
  if (!this.userToken) {
983
1122
  throw new SidechatAPIError("User is not authenticated.");
@@ -989,17 +1128,17 @@ class SidechatAPIClient {
989
1128
  assets: assetList,
990
1129
  group_ids: [groupID],
991
1130
  text: text,
992
- attachments: [],
1131
+ attachments: attachmentIDs,
993
1132
  dms_disabled: disableDMs,
994
1133
  comments_disabled: disableComments,
995
1134
  using_identity: !anonymous,
996
- quote_post_id: repostId
1135
+ quote_post_id: repostId,
997
1136
  };
998
1137
  // If pollOptions is provided and is a non-empty array, add poll_request
999
1138
  if (Array.isArray(pollOptions) && pollOptions.length > 0) {
1000
1139
  body.poll_request = {
1001
1140
  allows_view_results: true,
1002
- choices: pollOptions
1141
+ choices: pollOptions,
1003
1142
  };
1004
1143
  }
1005
1144
  const res = await fetch(`${this.apiRoot}/v1/posts`, {
@@ -1011,9 +1150,11 @@ class SidechatAPIClient {
1011
1150
  body: JSON.stringify(body),
1012
1151
  });
1013
1152
  const json = await res.json();
1153
+ if (!res.ok) throw new SidechatAPIError(json.message);
1014
1154
  return await json.posts[0];
1015
1155
  } catch (err) {
1016
1156
  console.error(err);
1157
+ if (err instanceof SidechatAPIError && err.message) throw err;
1017
1158
  throw new SidechatAPIError(`Failed to make post.`);
1018
1159
  }
1019
1160
  };
@@ -1089,16 +1230,19 @@ class SidechatAPIClient {
1089
1230
  throw new SidechatAPIError("User is not authenticated.");
1090
1231
  }
1091
1232
  try {
1092
- const res = await fetch(`${this.apiRoot}/v1/polls/view_results`, {
1093
- method: "POST",
1094
- headers: {
1095
- ...this.defaultHeaders,
1096
- Authorization: `Bearer ${this.userToken}`,
1233
+ const res = await fetch(
1234
+ `${this.apiRoot}/v1/polls/view_results?cacheBust=${Date.now()}`,
1235
+ {
1236
+ method: "POST",
1237
+ headers: {
1238
+ ...this.defaultHeaders,
1239
+ Authorization: `Bearer ${this.userToken}`,
1240
+ },
1241
+ body: JSON.stringify({
1242
+ poll_id: pollId,
1243
+ }),
1097
1244
  },
1098
- body: JSON.stringify({
1099
- poll_id: pollId,
1100
- }),
1101
- });
1245
+ );
1102
1246
  const json = await res.json();
1103
1247
  return await json;
1104
1248
  } catch (err) {
@@ -1108,22 +1252,27 @@ class SidechatAPIClient {
1108
1252
  };
1109
1253
 
1110
1254
  /**
1111
- * Uploads an asset to AWS S3 for use in posts and comments. Currently photos only
1255
+ * Uploads an asset to AWS S3 for use in posts and comments. Supports images and videos (videos must be under 50MB and are processed after upload)
1112
1256
  * @method
1113
1257
  * @param {String} uri - URI of the asset to upload
1114
- * @param {String} mimeType - mimetype of the asset (e.g. "image/png")
1258
+ * @param {String} mimeType - mimetype of the asset (e.g. "image/png" or "video/mp4")
1115
1259
  * @param {String} [name] - filename of the asset
1260
+ * @param {"post"|"post_vod_source"|"chat"|"chat_icon"|"group_icon"|"profile_picture_icon"} [context] - where the asset will be used. Videos default to "post_vod_source", which is required for them to be processed into a playable stream.
1116
1261
  * @returns {Promise<String>} URL of the uploaded asset
1117
1262
  * @since 2.5.1
1118
1263
  */
1119
- uploadAsset = async (uri, mimeType, name = "") => {
1264
+ uploadAsset = async (uri, mimeType, name = "", context = undefined) => {
1120
1265
  if (!this.userToken) {
1121
1266
  throw new SidechatAPIError("User is not authenticated.");
1122
1267
  }
1123
1268
 
1124
1269
  let imageType = mimeType.split("/")[1];
1125
- if (!["png", "jpeg", "gif"].includes(imageType)) {
1126
- throw new SidechatAPIError("Unsupported image format.");
1270
+ if (imageType == "quicktime") imageType = "mov";
1271
+ if (!["png", "jpeg", "gif", "webp", "mp4", "mov"].includes(imageType)) {
1272
+ throw new SidechatAPIError("Unsupported file format.");
1273
+ }
1274
+ if (!context && ["mp4", "mov"].includes(imageType)) {
1275
+ context = "post_vod_source";
1127
1276
  }
1128
1277
 
1129
1278
  const data = new FormData();
@@ -1133,7 +1282,11 @@ class SidechatAPIClient {
1133
1282
  uri: uri,
1134
1283
  });
1135
1284
 
1136
- const urlReq = await this.sendRequest(`/v1/assets/upload_url?content_type=${imageType}`);
1285
+ const urlReq = await this.sendRequest(
1286
+ `/v1/assets/upload_url?content_type=${imageType}${
1287
+ context ? "&context=" + context : ""
1288
+ }`,
1289
+ );
1137
1290
  const urlJson = await urlReq.json();
1138
1291
 
1139
1292
  try {
@@ -1148,7 +1301,7 @@ class SidechatAPIClient {
1148
1301
  return `${this.apiRoot}/v1/assets/library/${urlJson.asset_id}`;
1149
1302
  } else {
1150
1303
  throw new SidechatAPIError(
1151
- `Couldn't upload image - error ${uploadReq.status}`
1304
+ `Couldn't upload image - error ${uploadReq.status}`,
1152
1305
  );
1153
1306
  }
1154
1307
  } catch (e) {
@@ -1214,7 +1367,7 @@ class SidechatAPIClient {
1214
1367
  Authorization: `Bearer ${this.userToken}`,
1215
1368
  },
1216
1369
  body: JSON.stringify({
1217
- bio: bio
1370
+ bio: bio,
1218
1371
  }),
1219
1372
  });
1220
1373
  const json = await res.json();
@@ -1245,7 +1398,7 @@ class SidechatAPIClient {
1245
1398
  ...this.defaultHeaders,
1246
1399
  Authorization: `Bearer ${this.userToken}`,
1247
1400
  },
1248
- }
1401
+ },
1249
1402
  );
1250
1403
  if (res?.status == 200 || res?.status == 204) {
1251
1404
  return true;
@@ -1300,13 +1453,16 @@ class SidechatAPIClient {
1300
1453
  throw new SidechatAPIError("User is not authenticated.");
1301
1454
  }
1302
1455
  try {
1303
- const res = await fetch(`${this.apiRoot}/v1/groups/username?username=${username}`, {
1304
- method: "GET",
1305
- headers: {
1306
- ...this.defaultHeaders,
1307
- Authorization: `Bearer ${this.userToken}`,
1308
- }
1309
- });
1456
+ const res = await fetch(
1457
+ `${this.apiRoot}/v1/groups/username?username=${username}&cacheBust=${Date.now()}`,
1458
+ {
1459
+ method: "GET",
1460
+ headers: {
1461
+ ...this.defaultHeaders,
1462
+ Authorization: `Bearer ${this.userToken}`,
1463
+ },
1464
+ },
1465
+ );
1310
1466
  const json = await res.json();
1311
1467
  return await json.group;
1312
1468
  } catch (err) {
@@ -1327,13 +1483,16 @@ class SidechatAPIClient {
1327
1483
  throw new SidechatAPIError("User is not authenticated.");
1328
1484
  }
1329
1485
  try {
1330
- const res = await fetch(`${this.apiRoot}/v1/users/posts?username=${username}`, {
1331
- method: "GET",
1332
- headers: {
1333
- ...this.defaultHeaders,
1334
- Authorization: `Bearer ${this.userToken}`,
1335
- }
1336
- });
1486
+ const res = await fetch(
1487
+ `${this.apiRoot}/v1/users/posts?username=${username}`,
1488
+ {
1489
+ method: "GET",
1490
+ headers: {
1491
+ ...this.defaultHeaders,
1492
+ Authorization: `Bearer ${this.userToken}`,
1493
+ },
1494
+ },
1495
+ );
1337
1496
  const json = await res.json();
1338
1497
  return await json.posts;
1339
1498
  } catch (err) {
@@ -1381,13 +1540,16 @@ class SidechatAPIClient {
1381
1540
  throw new SidechatAPIError("User is not authenticated.");
1382
1541
  }
1383
1542
  try {
1384
- const res = await fetch(`${this.apiRoot}/v1/chats/explore`, {
1385
- method: "GET",
1386
- headers: {
1387
- ...this.defaultHeaders,
1388
- Authorization: `Bearer ${this.userToken}`,
1543
+ const res = await fetch(
1544
+ `${this.apiRoot}/v1/chats/explore?cacheBust=${Date.now()}`,
1545
+ {
1546
+ method: "GET",
1547
+ headers: {
1548
+ ...this.defaultHeaders,
1549
+ Authorization: `Bearer ${this.userToken}`,
1550
+ },
1389
1551
  },
1390
- });
1552
+ );
1391
1553
  const json = await res.json();
1392
1554
  return await json.chats;
1393
1555
  } catch (err) {
@@ -1411,7 +1573,7 @@ class SidechatAPIClient {
1411
1573
  displayName,
1412
1574
  emoji,
1413
1575
  primaryColor,
1414
- secondaryColor
1576
+ secondaryColor,
1415
1577
  ) => {
1416
1578
  if (!this.userToken) {
1417
1579
  throw new SidechatAPIError("User is not authenticated.");
@@ -1444,21 +1606,27 @@ class SidechatAPIClient {
1444
1606
  /**
1445
1607
  * Gets a list of the user's direct messages
1446
1608
  * @method
1609
+ * @param {types.SidechatCursorString} [cursor] - cursor string
1447
1610
  * @returns {Promise<types.SidechatDirectThread[]>}
1448
1611
  * @since 2.4.4
1449
1612
  */
1450
- getDMs = async () => {
1613
+ getDMs = async (cursor) => {
1451
1614
  if (!this.userToken) {
1452
1615
  throw new SidechatAPIError("User is not authenticated.");
1453
1616
  }
1454
1617
  try {
1455
- const res = await fetch(`${this.apiRoot}/v1/chats`, {
1456
- method: "GET",
1457
- headers: {
1458
- ...this.defaultHeaders,
1459
- Authorization: `Bearer ${this.userToken}`,
1618
+ const res = await fetch(
1619
+ `${this.apiRoot}/v1/chats${
1620
+ cursor ? "?cursor=" + encodeURIComponent(cursor) : ""
1621
+ }`,
1622
+ {
1623
+ method: "GET",
1624
+ headers: {
1625
+ ...this.defaultHeaders,
1626
+ Authorization: `Bearer ${this.userToken}`,
1627
+ },
1460
1628
  },
1461
- });
1629
+ );
1462
1630
  const json = await res.json();
1463
1631
  const list = await json.chats;
1464
1632
  let r = [];
@@ -1492,7 +1660,7 @@ class SidechatAPIClient {
1492
1660
  ...this.defaultHeaders,
1493
1661
  Authorization: `Bearer ${this.userToken}`,
1494
1662
  },
1495
- }
1663
+ },
1496
1664
  );
1497
1665
  const json = await res.json();
1498
1666
  return await json.chat;
@@ -1554,7 +1722,7 @@ class SidechatAPIClient {
1554
1722
  clientID,
1555
1723
  postID,
1556
1724
  anonymous = false,
1557
- postContext = "feed"
1725
+ postContext = "feed",
1558
1726
  ) => {
1559
1727
  if (!this.userToken) {
1560
1728
  throw new SidechatAPIError("User is not authenticated.");
@@ -1587,6 +1755,7 @@ class SidechatAPIClient {
1587
1755
  * @method
1588
1756
  * @param {String} postID - alphanumeric ID of post to hide
1589
1757
  * @since 2.6.2
1758
+ * @deprecated since 2.7.0. Please use `blockUser` instead!
1590
1759
  */
1591
1760
  hidePostsFromUser = async (postID) => {
1592
1761
  if (!this.userToken) {
@@ -1602,7 +1771,7 @@ class SidechatAPIClient {
1602
1771
  body: JSON.stringify({
1603
1772
  post_id: postID,
1604
1773
  post_context: "feed",
1605
- report: false
1774
+ report: false,
1606
1775
  }),
1607
1776
  });
1608
1777
  const json = await res.json();
@@ -1617,6 +1786,7 @@ class SidechatAPIClient {
1617
1786
  * Unhides all posts from all users
1618
1787
  * @method
1619
1788
  * @since 2.6.2
1789
+ * @deprecated since 2.7.0. No longer used by the official app and may stop working.
1620
1790
  */
1621
1791
  unhidePostsFromAllUsers = async () => {
1622
1792
  if (!this.userToken) {
@@ -1638,81 +1808,471 @@ class SidechatAPIClient {
1638
1808
  throw new SidechatAPIError(`Failed to unhide post.`);
1639
1809
  }
1640
1810
  };
1811
+
1812
+ /**
1813
+ * Fetches the home feed, which mixes posts from all of the user's groups
1814
+ * @method
1815
+ * @param {"for_you"|"hot"|"recent"} [type] - how the feed should be sorted
1816
+ * @param {String} [schoolGroupID] - alphanumeric ID of the user's school group
1817
+ * @param {types.SidechatCursorString} [cursor] - cursor string
1818
+ * @returns {Promise<types.SidechatFeed>} feed items and cursor
1819
+ * @since 2.7.0
1820
+ */
1821
+ getHomeFeed = async (type = "for_you", schoolGroupID, cursor) => {
1822
+ if (!this.userToken) {
1823
+ throw new SidechatAPIError("User is not authenticated.");
1824
+ }
1825
+ try {
1826
+ const params = new URLSearchParams({ type: type });
1827
+ if (schoolGroupID) params.set("school_group_id", schoolGroupID);
1828
+ if (cursor) params.set("cursor", cursor);
1829
+ const res = await this.sendRequest(`/v1/posts/home?${params}`);
1830
+ return await res.json();
1831
+ } catch (err) {
1832
+ console.error(err);
1833
+ throw new SidechatAPIError(`Failed to get home feed.`);
1834
+ }
1835
+ };
1836
+
1837
+ /**
1838
+ * Follows or unfollows a post. Followed posts send activity notifications when they get new comments.
1839
+ * @method
1840
+ * @param {String} postID - alphanumeric ID of post
1841
+ * @param {Boolean} following - whether or not the user should follow the post
1842
+ * @returns {Promise<{post: types.SidechatPostOrComment}>} the updated post
1843
+ * @since 2.7.0
1844
+ */
1845
+ setPostFollowing = async (postID, following) => {
1846
+ if (!this.userToken) {
1847
+ throw new SidechatAPIError("User is not authenticated.");
1848
+ }
1849
+ try {
1850
+ const res = await this.sendRequest(
1851
+ `/v1/posts/${following ? "follow" : "unfollow"}`,
1852
+ "POST",
1853
+ JSON.stringify({ post_id: postID }),
1854
+ );
1855
+ return await res.json();
1856
+ } catch (err) {
1857
+ console.error(err);
1858
+ throw new SidechatAPIError(`Failed to change post follow status.`);
1859
+ }
1860
+ };
1861
+
1862
+ /**
1863
+ * Reports a post or comment to the group's moderators
1864
+ * @method
1865
+ * @param {String} postID - alphanumeric ID of post or comment to report
1866
+ * @param {types.SidechatReportReason} reason - why the content is being reported
1867
+ * @param {String} [note] - explanation to send along with the report
1868
+ * @since 2.7.0
1869
+ */
1870
+ flagPost = async (postID, reason, note = undefined) => {
1871
+ if (!this.userToken) {
1872
+ throw new SidechatAPIError("User is not authenticated.");
1873
+ }
1874
+ try {
1875
+ const res = await this.sendRequest(
1876
+ "/v1/posts/flag",
1877
+ "POST",
1878
+ JSON.stringify({ post_id: postID, reason: reason, note: note }),
1879
+ );
1880
+ return await res.json();
1881
+ } catch (err) {
1882
+ console.error(err);
1883
+ throw new SidechatAPIError(`Failed to report post.`);
1884
+ }
1885
+ };
1886
+
1887
+ /**
1888
+ * Blocks the author of a post or comment, hiding all of their content from the user. Replaces `hidePostsFromUser`.
1889
+ * @method
1890
+ * @param {String} postID - alphanumeric ID of a post or comment by the user to block
1891
+ * @param {Boolean} [report] - whether or not to also report the content
1892
+ * @param {"feed"|"chat"} [postContext] - where the content was seen
1893
+ * @since 2.7.0
1894
+ */
1895
+ blockUser = async (postID, report = false, postContext = "feed") => {
1896
+ if (!this.userToken) {
1897
+ throw new SidechatAPIError("User is not authenticated.");
1898
+ }
1899
+ try {
1900
+ const res = await this.sendRequest(
1901
+ "/v1/posts/block_user",
1902
+ "POST",
1903
+ JSON.stringify({
1904
+ post_id: postID,
1905
+ post_context: postContext,
1906
+ report: report,
1907
+ }),
1908
+ );
1909
+ return await res.json();
1910
+ } catch (err) {
1911
+ console.error(err);
1912
+ throw new SidechatAPIError(`Failed to block user.`);
1913
+ }
1914
+ };
1915
+
1916
+ /**
1917
+ * Creates a link attachment that can be added to a post with createPost(). YouTube links are recognized and shown as embedded videos.
1918
+ * @method
1919
+ * @param {String} url - URL to attach
1920
+ * @returns {Promise<types.SidechatAttachment>} the created attachment
1921
+ * @since 2.7.0
1922
+ */
1923
+ createLinkAttachment = async (url) => {
1924
+ if (!this.userToken) {
1925
+ throw new SidechatAPIError("User is not authenticated.");
1926
+ }
1927
+ try {
1928
+ const res = await this.sendRequest(
1929
+ "/v1/attachments/upload_link",
1930
+ "POST",
1931
+ JSON.stringify({ link_url: url }),
1932
+ );
1933
+ return await res.json();
1934
+ } catch (err) {
1935
+ console.error(err);
1936
+ throw new SidechatAPIError(`Failed to create link attachment.`);
1937
+ }
1938
+ };
1939
+
1940
+ /**
1941
+ * Gets the user's activity feed (notifications for comments, votes, followers, etc.)
1942
+ * @method
1943
+ * @param {types.SidechatCursorString} [cursor] - cursor string
1944
+ * @returns {Promise<types.SidechatActivityList>} activity items and cursor
1945
+ * @since 2.7.0
1946
+ */
1947
+ getActivity = async (cursor) => {
1948
+ if (!this.userToken) {
1949
+ throw new SidechatAPIError("User is not authenticated.");
1950
+ }
1951
+ try {
1952
+ const res = await this.sendRequest(
1953
+ `/v1/activity${cursor ? "?cursor=" + encodeURIComponent(cursor) : ""}`,
1954
+ );
1955
+ return await res.json();
1956
+ } catch (err) {
1957
+ console.error(err);
1958
+ throw new SidechatAPIError(`Failed to get activity.`);
1959
+ }
1960
+ };
1961
+
1962
+ /**
1963
+ * Gets the groups the user is a member of
1964
+ * @method
1965
+ * @returns {Promise<types.SidechatGroup[]>}
1966
+ * @since 2.7.0
1967
+ */
1968
+ getGroups = async () => {
1969
+ if (!this.userToken) {
1970
+ throw new SidechatAPIError("User is not authenticated.");
1971
+ }
1972
+ try {
1973
+ const res = await this.sendRequest("/v1/groups");
1974
+ const json = await res.json();
1975
+ return json.groups;
1976
+ } catch (err) {
1977
+ console.error(err);
1978
+ throw new SidechatAPIError(`Failed to get groups.`);
1979
+ }
1980
+ };
1981
+
1982
+ /**
1983
+ * Gets groups suggested for the user to join
1984
+ * @method
1985
+ * @param {Number} [limit] - maximum number of groups to return
1986
+ * @returns {Promise<types.SidechatGroup[]>}
1987
+ * @since 2.7.0
1988
+ */
1989
+ getSuggestedGroups = async (limit = 10) => {
1990
+ if (!this.userToken) {
1991
+ throw new SidechatAPIError("User is not authenticated.");
1992
+ }
1993
+ try {
1994
+ const res = await this.sendRequest(
1995
+ `/v1/groups/suggestions?limit=${limit}`,
1996
+ );
1997
+ const json = await res.json();
1998
+ return json.groups;
1999
+ } catch (err) {
2000
+ console.error(err);
2001
+ throw new SidechatAPIError(`Failed to get suggested groups.`);
2002
+ }
2003
+ };
2004
+
2005
+ /**
2006
+ * Gets a shareable invite link for a group. School groups don't have invite links and will throw an error.
2007
+ * @method
2008
+ * @param {String} groupID - alphanumeric ID of group
2009
+ * @returns {Promise<String>} invite link URL
2010
+ * @since 2.7.0
2011
+ */
2012
+ getGroupInviteLink = async (groupID) => {
2013
+ if (!this.userToken) {
2014
+ throw new SidechatAPIError("User is not authenticated.");
2015
+ }
2016
+ try {
2017
+ const res = await this.sendRequest(
2018
+ `/v1/groups/invite_link?group_id=${groupID}`,
2019
+ );
2020
+ const json = await res.json();
2021
+ return json.link;
2022
+ } catch (err) {
2023
+ console.error(err);
2024
+ throw new SidechatAPIError(`Failed to get invite link.`);
2025
+ }
2026
+ };
2027
+
2028
+ /**
2029
+ * Gets the yakarma leaderboard for a group, along with the user's own karma
2030
+ * @method
2031
+ * @param {String} groupID - alphanumeric ID of group
2032
+ * @returns {Promise<types.SidechatLeaderboard>}
2033
+ * @since 2.7.0
2034
+ */
2035
+ getLeaderboard = async (groupID) => {
2036
+ if (!this.userToken) {
2037
+ throw new SidechatAPIError("User is not authenticated.");
2038
+ }
2039
+ try {
2040
+ const res = await this.sendRequest(`/v1/leaderboard?group_id=${groupID}`);
2041
+ return await res.json();
2042
+ } catch (err) {
2043
+ console.error(err);
2044
+ throw new SidechatAPIError(`Failed to get leaderboard.`);
2045
+ }
2046
+ };
2047
+
2048
+ /**
2049
+ * Gets the existing direct message thread for a post or comment. Returns undefined if the user hasn't started one.
2050
+ * @method
2051
+ * @param {String} postID - alphanumeric ID of post or comment
2052
+ * @returns {Promise<types.SidechatDirectThread>}
2053
+ * @since 2.7.0
2054
+ */
2055
+ getDMForPost = async (postID) => {
2056
+ if (!this.userToken) {
2057
+ throw new SidechatAPIError("User is not authenticated.");
2058
+ }
2059
+ try {
2060
+ const res = await this.sendRequest(`/v1/chats/by_post?post_id=${postID}`);
2061
+ const json = await res.json();
2062
+ return json.chat;
2063
+ } catch (err) {
2064
+ console.error(err);
2065
+ throw new SidechatAPIError(`Failed to get DM thread for post.`);
2066
+ }
2067
+ };
2068
+
2069
+ /**
2070
+ * Reports a direct message thread
2071
+ * @method
2072
+ * @param {String} chatID - alphanumeric ID of the thread to report
2073
+ * @param {types.SidechatReportReason} reason - why the thread is being reported
2074
+ * @since 2.7.0
2075
+ */
2076
+ reportDM = async (chatID, reason) => {
2077
+ if (!this.userToken) {
2078
+ throw new SidechatAPIError("User is not authenticated.");
2079
+ }
2080
+ try {
2081
+ const res = await this.sendRequest(
2082
+ "/v1/chats/report",
2083
+ "POST",
2084
+ JSON.stringify({ chat_id: chatID, reason: reason }),
2085
+ );
2086
+ return await res.json();
2087
+ } catch (err) {
2088
+ console.error(err);
2089
+ throw new SidechatAPIError(`Failed to report DM.`);
2090
+ }
2091
+ };
2092
+
2093
+ /**
2094
+ * Sets which push notifications the user receives
2095
+ * @method
2096
+ * @param {types.SidechatNotificationPreferences} preferences - notification types to enable or disable
2097
+ * @since 2.7.0
2098
+ */
2099
+ setNotificationPreferences = async (preferences) => {
2100
+ if (!this.userToken) {
2101
+ throw new SidechatAPIError("User is not authenticated.");
2102
+ }
2103
+ try {
2104
+ const res = await this.sendRequest(
2105
+ "/v1/users/set_notification_preferences",
2106
+ "POST",
2107
+ JSON.stringify({ notification_preferences: preferences }),
2108
+ );
2109
+ return await res.json();
2110
+ } catch (err) {
2111
+ console.error(err);
2112
+ throw new SidechatAPIError(`Failed to set notification preferences.`);
2113
+ }
2114
+ };
2115
+
2116
+ /**
2117
+ * Verifies the user's school email by signing in with Google or Microsoft instead of clicking an emailed link. Returns the same object as checkEmailVerification(). This was discovered from me decompiling the new Android app, I haven't tested this but based on the implementation it should work fine and might resolve the problem that a lot of people have with their accounts not being associated with their school automatically.
2118
+ * @method
2119
+ * @param {String} authToken - token from the Google or Microsoft sign-in
2120
+ * @param {"google"|"microsoft"} authType - provider the token came from
2121
+ * @param {Boolean} [isIncomingFreshman] - whether or not the user is an incoming freshman
2122
+ * @since 2.7.0
2123
+ * @tutorial Email Registration
2124
+ */
2125
+ verifyEmailWithThirdParty = async (
2126
+ authToken,
2127
+ authType,
2128
+ isIncomingFreshman = false,
2129
+ ) => {
2130
+ if (!this.userToken) {
2131
+ throw new SidechatAPIError("User is not authenticated.");
2132
+ }
2133
+ try {
2134
+ const res = await this.sendRequest(
2135
+ "/v1/users/third_party_email_verified",
2136
+ "POST",
2137
+ JSON.stringify({
2138
+ auth: authToken,
2139
+ auth_type: authType,
2140
+ is_incoming_freshman: isIncomingFreshman,
2141
+ }),
2142
+ );
2143
+ const json = await res.json();
2144
+ if (json.verified_email_updates_response) {
2145
+ return json.verified_email_updates_response;
2146
+ } else {
2147
+ throw new SidechatAPIError(json?.message || "Email is not verified.");
2148
+ }
2149
+ } catch (err) {
2150
+ console.error(err);
2151
+ throw new SidechatAPIError("Failed to verify email.");
2152
+ }
2153
+ };
2154
+
2155
+ /**
2156
+ * Authorizes a realtime (Pusher) connection to subscribe to a private channel, such as `private-chat-<chatID>` for live direct messages. Pass the result to your Pusher client's channel authorizer. This hasn't been tested, and is mostly theoretical.
2157
+ * @method
2158
+ * @param {String} socketID - socket ID assigned by Pusher
2159
+ * @param {String} channelName - name of the private channel to subscribe to
2160
+ * @returns {Promise<{auth: String}>} signed channel authorization
2161
+ * @since 2.7.0
2162
+ */
2163
+ authorizeRealtimeChannel = async (socketID, channelName) => {
2164
+ if (!this.userToken) {
2165
+ throw new SidechatAPIError("User is not authenticated.");
2166
+ }
2167
+ try {
2168
+ const res = await this.sendRequest(
2169
+ "/pusher/auth",
2170
+ "POST",
2171
+ JSON.stringify({ socket_id: socketID, channel_name: channelName }),
2172
+ );
2173
+ return await res.json();
2174
+ } catch (err) {
2175
+ console.error(err);
2176
+ throw new SidechatAPIError(`Failed to authorize realtime channel.`);
2177
+ }
2178
+ };
2179
+
2180
+ /**
2181
+ * Permanently deletes the current user's account. This cannot be undone!
2182
+ * @method
2183
+ * @since 2.7.0
2184
+ */
2185
+ deleteAccount = async () => {
2186
+ if (!this.userToken) {
2187
+ throw new SidechatAPIError("User is not authenticated.");
2188
+ }
2189
+ try {
2190
+ const res = await this.sendRequest(
2191
+ "/v1/users/delete",
2192
+ "POST",
2193
+ JSON.stringify({}),
2194
+ );
2195
+ return await res.json();
2196
+ } catch (err) {
2197
+ console.error(err);
2198
+ throw new SidechatAPIError(`Failed to delete account.`);
2199
+ }
2200
+ };
1641
2201
  }
1642
2202
 
1643
- /**
1644
- * @typedef SidechatColor
1645
- * @prop {String} primary - hex code of primary color
1646
- * @prop {String} secondary - hex code of secondary color
1647
- */
1648
-
1649
- /**
1650
- * List of colors compatible with user conversation icons
1651
- * @prop {SidechatColor[]} colors - list of color themes for user icons
1652
- */
1653
- class SidechatColorList {
1654
- colors = [
1655
- {
1656
- primary: "#74DEEE",
1657
- secondary: "#239EAB",
1658
- },
1659
- {
1660
- primary: "#15FF46",
1661
- secondary: "#3FC0FF",
1662
- },
1663
- {
1664
- primary: "#D9FB8A",
1665
- secondary: "#B1FD00",
1666
- },
1667
- {
1668
- primary: "#FC40FF",
1669
- secondary: "#0DD5B2",
1670
- },
1671
- {
1672
- primary: "#3E973C",
1673
- secondary: "#0F430E",
1674
- },
1675
- {
1676
- primary: "#FFD305",
1677
- secondary: "#F4B320",
1678
- },
1679
- {
1680
- primary: "#8483FF",
1681
- secondary: "#5857FF",
1682
- },
1683
- {
1684
- primary: "#FA81FF",
1685
- secondary: "#722DFF",
1686
- },
1687
- {
1688
- primary: "#00CBFE",
1689
- secondary: "#0D13D5",
1690
- },
1691
- {
1692
- primary: "#FF7B51",
1693
- secondary: "#B2431F",
1694
- },
1695
- {
1696
- primary: "#FF47CC",
1697
- secondary: "#69004C",
1698
- },
1699
- {
1700
- primary: "#00EE6E",
1701
- secondary: "#0C75E6",
1702
- },
1703
- {
1704
- primary: "#FF1885",
1705
- secondary: "#FA81FF",
1706
- },
1707
- {
1708
- primary: "#D8DC44",
1709
- secondary: "#228B3F",
1710
- },
1711
- {
1712
- primary: "#0968E5",
1713
- secondary: "#091970",
1714
- },
1715
- ];
2203
+ /**
2204
+ * @typedef SidechatColor
2205
+ * @prop {String} primary - hex code of primary color
2206
+ * @prop {String} secondary - hex code of secondary color
2207
+ */
2208
+
2209
+ /**
2210
+ * List of colors compatible with user conversation icons
2211
+ * @prop {SidechatColor[]} colors - list of color themes for user icons
2212
+ */
2213
+ class SidechatColorList {
2214
+ colors = [
2215
+ {
2216
+ primary: "#74DEEE",
2217
+ secondary: "#239EAB",
2218
+ },
2219
+ {
2220
+ primary: "#15FF46",
2221
+ secondary: "#3FC0FF",
2222
+ },
2223
+ {
2224
+ primary: "#D9FB8A",
2225
+ secondary: "#B1FD00",
2226
+ },
2227
+ {
2228
+ primary: "#FC40FF",
2229
+ secondary: "#0DD5B2",
2230
+ },
2231
+ {
2232
+ primary: "#3E973C",
2233
+ secondary: "#0F430E",
2234
+ },
2235
+ {
2236
+ primary: "#FFD305",
2237
+ secondary: "#F4B320",
2238
+ },
2239
+ {
2240
+ primary: "#8483FF",
2241
+ secondary: "#5857FF",
2242
+ },
2243
+ {
2244
+ primary: "#FA81FF",
2245
+ secondary: "#722DFF",
2246
+ },
2247
+ {
2248
+ primary: "#00CBFE",
2249
+ secondary: "#0D13D5",
2250
+ },
2251
+ {
2252
+ primary: "#FF7B51",
2253
+ secondary: "#B2431F",
2254
+ },
2255
+ {
2256
+ primary: "#FF47CC",
2257
+ secondary: "#69004C",
2258
+ },
2259
+ {
2260
+ primary: "#00EE6E",
2261
+ secondary: "#0C75E6",
2262
+ },
2263
+ {
2264
+ primary: "#FF1885",
2265
+ secondary: "#FA81FF",
2266
+ },
2267
+ {
2268
+ primary: "#D8DC44",
2269
+ secondary: "#228B3F",
2270
+ },
2271
+ {
2272
+ primary: "#0968E5",
2273
+ secondary: "#091970",
2274
+ },
2275
+ ];
1716
2276
  }
1717
2277
 
1718
2278
  exports.SidechatAPIClient = SidechatAPIClient;