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