sidechat.js 1.0.0 → 2.0.0-alpha.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 (50) hide show
  1. package/.github/workflows/static.yml +51 -0
  2. package/README.md +15 -1
  3. package/dist/sidechat.cjs +1 -1
  4. package/dist/sidechat.cjs.map +1 -1
  5. package/dist/sidechat.modern.js +1 -1
  6. package/dist/sidechat.modern.js.map +1 -1
  7. package/dist/sidechat.module.js +1 -1
  8. package/dist/sidechat.module.js.map +1 -1
  9. package/dist/sidechat.umd.js +1 -1
  10. package/dist/sidechat.umd.js.map +1 -1
  11. package/docs/sidechat.js/1.0.0/global.html +1 -1
  12. package/docs/sidechat.js/1.0.0/index.html +2 -1
  13. package/docs/sidechat.js/1.0.0/index.js.html +1 -3
  14. package/docs/sidechat.js/1.0.0/types_SidechatTypes.js.html +1 -1
  15. package/docs/sidechat.js/2.0.0-alpha.0/SidechatAPIClient.html +3 -0
  16. package/docs/sidechat.js/2.0.0-alpha.0/classes_SidechatAPIClient.js.html +374 -0
  17. package/docs/sidechat.js/2.0.0-alpha.0/data/search.json +1 -0
  18. package/docs/sidechat.js/2.0.0-alpha.0/fonts/Inconsolata-Regular.ttf +0 -0
  19. package/docs/sidechat.js/2.0.0-alpha.0/fonts/OpenSans-Regular.ttf +0 -0
  20. package/docs/sidechat.js/2.0.0-alpha.0/fonts/WorkSans-Bold.ttf +0 -0
  21. package/docs/sidechat.js/2.0.0-alpha.0/global.html +3 -0
  22. package/docs/sidechat.js/2.0.0-alpha.0/index.html +4 -0
  23. package/docs/sidechat.js/2.0.0-alpha.0/scripts/core.js +702 -0
  24. package/docs/sidechat.js/2.0.0-alpha.0/scripts/core.min.js +23 -0
  25. package/docs/sidechat.js/2.0.0-alpha.0/scripts/resize.js +90 -0
  26. package/docs/sidechat.js/2.0.0-alpha.0/scripts/search.js +265 -0
  27. package/docs/sidechat.js/2.0.0-alpha.0/scripts/search.min.js +6 -0
  28. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/Apache-License-2.0.txt +202 -0
  29. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/fuse.js +9 -0
  30. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/hljs-line-num-original.js +369 -0
  31. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/hljs-line-num.js +1 -0
  32. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/hljs-original.js +5171 -0
  33. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/hljs.js +1 -0
  34. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/popper.js +5 -0
  35. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/tippy.js +1 -0
  36. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/tocbot.js +672 -0
  37. package/docs/sidechat.js/2.0.0-alpha.0/scripts/third-party/tocbot.min.js +1 -0
  38. package/docs/sidechat.js/2.0.0-alpha.0/styles/clean-jsdoc-theme-base.css +975 -0
  39. package/docs/sidechat.js/2.0.0-alpha.0/styles/clean-jsdoc-theme-dark.css +407 -0
  40. package/docs/sidechat.js/2.0.0-alpha.0/styles/clean-jsdoc-theme-light.css +388 -0
  41. package/docs/sidechat.js/2.0.0-alpha.0/styles/clean-jsdoc-theme.min.css +1 -0
  42. package/docs/sidechat.js/2.0.0-alpha.0/types_SidechatTypes.js.html +82 -0
  43. package/jsdoc.json +7 -4
  44. package/package.json +3 -3
  45. package/src/classes/SidechatAPIClient.js +371 -0
  46. package/src/index.js +4 -0
  47. package/index.js +0 -362
  48. /package/{classes → src/classes}/SidechatAPIError.js +0 -0
  49. /package/{tests → src/tests}/basicTest.js +0 -0
  50. /package/{types → src/types}/SidechatTypes.js +0 -0
@@ -0,0 +1,371 @@
1
+ import "../types/SidechatTypes.js";
2
+ import SidechatAPIError from "../classes/SidechatAPIError.js";
3
+
4
+ /**
5
+ * API client class for making requests to Sidechat's private API. As of now all methods are static.
6
+ * @class
7
+ * @since 2.0.0-alpha.0
8
+ * @todo Add functionality for constructing a client with or without a token and having it keep track of requests/caching, etc
9
+ */
10
+ class SidechatAPIClient {
11
+ static defaultHeaders = {
12
+ Accept: "application/json",
13
+ "Content-Type": "application/json",
14
+ };
15
+
16
+ /**
17
+ * Initiate the login process with a phone number. Should be followed up with verifySMSCode().
18
+ * @method
19
+ * @param {Number} phoneNumber - US phone number (WITHOUT +1) to send verification code to
20
+ */
21
+ static loginViaSMS = async (phoneNumber) => {
22
+ try {
23
+ const res = await fetch(`https://api.sidechat.lol/v1/login_register`, {
24
+ method: "POST",
25
+ headers: defaultHeaders,
26
+ body: JSON.stringify({
27
+ phone_number: `+1${phoneNumber}`,
28
+ version: 3,
29
+ }),
30
+ });
31
+ const json = await res.json();
32
+ return json;
33
+ } catch (err) {
34
+ console.error(error);
35
+ throw new SidechatAPIError("Failed to request SMS verification.");
36
+ }
37
+ };
38
+
39
+ /**
40
+ * Verify the code sent via SMS with loginViaSMS().
41
+ * @method
42
+ * @param {Number} phoneNumber - US phone number (WITHOUT +1) that verification code was sent to
43
+ * @param {String} code - the verification code
44
+ */
45
+ static verifySMSCode = async (phoneNumber, code) => {
46
+ try {
47
+ const res = await fetch(
48
+ `https://api.sidechat.lol/v1/verify_phone_number`,
49
+ {
50
+ method: "POST",
51
+ headers: defaultHeaders,
52
+ body: JSON.stringify({
53
+ phone_number: `+1${phoneNumber}`,
54
+ code: code.toUpperCase(),
55
+ }),
56
+ }
57
+ );
58
+ const json = await res.json();
59
+ return json;
60
+ } catch (err) {
61
+ console.error(err);
62
+ throw new SidechatAPIError("Failed verify this code.");
63
+ }
64
+ };
65
+
66
+ /**
67
+ * Set the user's age
68
+ * @method
69
+ * @param {Number} age - user's age in years
70
+ * @param {String} registrationID - the registration ID generated by verifySMSCode()
71
+ */
72
+ static setAge = async (age, registrationID) => {
73
+ if (age < 13) {
74
+ throw new SidechatAPIError("You're too young to use Offsides.");
75
+ }
76
+ try {
77
+ const res = await fetch(
78
+ `https://api.sidechat.lol/v1/complete_registration`,
79
+ {
80
+ method: "POST",
81
+ headers: defaultHeaders,
82
+ body: JSON.stringify({
83
+ age: Number(age),
84
+ registration_id: registrationID,
85
+ }),
86
+ }
87
+ );
88
+ const json = await res.json();
89
+ return json;
90
+ } catch (err) {
91
+ console.error(err);
92
+ throw new SidechatAPIError("Failed verify this code.");
93
+ }
94
+ };
95
+
96
+ /**
97
+ * Initiate the email setup process. Should be followed up with checkEmailVerification().
98
+ * @method
99
+ * @param {String} email - school email address to send verification code to
100
+ * @param {String} token - user bearer token
101
+ */
102
+ static registerEmail = async (email, token) => {
103
+ try {
104
+ const res = await fetch(
105
+ `https://api.sidechat.lol/v2/users/register_email`,
106
+ {
107
+ method: "POST",
108
+ headers: {
109
+ ...defaultHeaders,
110
+ Authorization: `Bearer ${token}`,
111
+ },
112
+ body: JSON.stringify({
113
+ email: email,
114
+ }),
115
+ }
116
+ );
117
+ const json = await res.json();
118
+ if (json.message) {
119
+ throw new SidechatAPIError(json.message);
120
+ }
121
+ return json;
122
+ } catch (err) {
123
+ console.error(error);
124
+ throw new SidechatAPIError("Failed to request email verification.");
125
+ }
126
+ };
127
+
128
+ /**
129
+ * Check is the user's email is verified.
130
+ * @method
131
+ * @param {String} token - user bearer token
132
+ */
133
+ static checkEmailVerification = async (token) => {
134
+ try {
135
+ const res = await fetch(
136
+ `https://api.sidechat.lol/v1/users/check_email_verified`,
137
+ {
138
+ method: "GET",
139
+ headers: {
140
+ ...defaultHeaders,
141
+ Authorization: `Bearer ${token}`,
142
+ },
143
+ }
144
+ );
145
+ const json = await res.json();
146
+ if (json.verified_email_updates_response) {
147
+ return json.verified_email_updates_response;
148
+ } else {
149
+ throw new SidechatAPIError(json?.message || "Email is not verified.");
150
+ }
151
+ } catch (err) {
152
+ console.error(error);
153
+ throw new SidechatAPIError("Email is not verified.");
154
+ }
155
+ };
156
+
157
+ /**
158
+ * Set the device ID of the current user
159
+ * @method
160
+ * @param {String} deviceId - the device ID to set
161
+ * @param {String} token - the user bearer token
162
+ */
163
+ static setDeviceID = async (deviceID, token) => {
164
+ try {
165
+ const res = await fetch(
166
+ `https://api.sidechat.lol/v1/register_device_token`,
167
+ {
168
+ method: "POST",
169
+ headers: {
170
+ ...defaultHeaders,
171
+ Authorization: `Bearer ${token}`,
172
+ },
173
+ body: JSON.stringify({
174
+ build_type: "release",
175
+ bundle_id: "com.flowerave.sidechat",
176
+ device_token: deviceID,
177
+ }),
178
+ }
179
+ );
180
+ const json = await res.json();
181
+ await AsyncStorage.setItem("deviceID", deviceID);
182
+ return json;
183
+ } catch (err) {
184
+ console.error(err);
185
+ throw new SidechatAPIError("Failed verify this code.");
186
+ }
187
+ };
188
+
189
+ /**
190
+ * Get updated status for user and group
191
+ * @method
192
+ * @param {String} token - user bearer token
193
+ * @param {String} [groupID] - ID of a specific group to retrieve info from
194
+ */
195
+ static getUserAndGroup = async (token, groupID = "") => {
196
+ try {
197
+ const res = await fetch(
198
+ `https://api.sidechat.lol/v1/updates?group_id=${groupID}`,
199
+ {
200
+ method: "GET",
201
+ headers: {
202
+ ...defaultHeaders,
203
+ Authorization: `Bearer ${token}`,
204
+ },
205
+ }
206
+ );
207
+ const json = await res.json();
208
+ return json;
209
+ } catch (err) {
210
+ console.error(err);
211
+ throw new SidechatAPIError(`Failed to get posts from group.`);
212
+ }
213
+ };
214
+
215
+ /**
216
+ * Fetches posts from the specified category in a group
217
+ * @method
218
+ * @param {String} groupID - group ID
219
+ * @param {String} token - user bearer token
220
+ * @param {"hot"|"recent"|"top"} category - category to filter posts
221
+ * @param {SidechatCursorString} [cursor] - cursor string
222
+ * @returns {{posts: SidechatPostOrComment[], cursor: SidechatCursorString}} List of posts and cursor
223
+ */
224
+ static getGroupPosts = async (groupID, token, category = "hot", cursor) => {
225
+ try {
226
+ const res = await fetch(
227
+ `https://api.sidechat.lol/v1/posts?group_id=${groupID}&type=${category}${
228
+ cursor ? "&cursor=" + cursor : ""
229
+ }`,
230
+ {
231
+ method: "GET",
232
+ headers: {
233
+ ...defaultHeaders,
234
+ Authorization: `Bearer ${token}`,
235
+ },
236
+ }
237
+ );
238
+ const json = await res.json();
239
+ return json;
240
+ } catch (err) {
241
+ console.error(err);
242
+ throw new SidechatAPIError(`Failed to get posts from group.`);
243
+ }
244
+ };
245
+
246
+ /**
247
+ * Upvote or downvote, or unvote a post
248
+ * @method
249
+ * @param {String} postID - post ID to vote on
250
+ * @param {String} token - user bearer token
251
+ * @param {SidechatVoteString} action - whether to upvote, downvote, or reset vote
252
+ */
253
+ static setVote = async (postID, token, action) => {
254
+ try {
255
+ const res = await fetch(`https://api.sidechat.lol/v1/posts/set_vote`, {
256
+ method: "POST",
257
+ headers: {
258
+ ...defaultHeaders,
259
+ Authorization: `Bearer ${token}`,
260
+ },
261
+ body: JSON.stringify({
262
+ post_id: postID,
263
+ vote_status: action,
264
+ }),
265
+ });
266
+ const json = await res.json();
267
+ return json;
268
+ } catch (err) {
269
+ console.error(err);
270
+ throw new SidechatAPIError(`Failed to change the vote on post.`);
271
+ }
272
+ };
273
+
274
+ /**
275
+ * Get all the commments on a post
276
+ * @method
277
+ * @param {String} postID - post ID to get comments for
278
+ * @param {String} token - user bearer token
279
+ * @returns {SidechatPostOrComment[]} list of comments
280
+ */
281
+ static getPostComments = async (postID, token) => {
282
+ try {
283
+ const res = await fetch(
284
+ `https://api.sidechat.lol/v1/posts/comments/?post_id=${postID}`,
285
+ {
286
+ method: "GET",
287
+ headers: {
288
+ ...defaultHeaders,
289
+ Authorization: `Bearer ${token}`,
290
+ },
291
+ }
292
+ );
293
+ const json = await res.json();
294
+ // Function to preprocess the comments and organize them into a nested structure
295
+ function preprocessComments(apiComments) {
296
+ // Map to store comments by their IDs for efficient lookup
297
+ const commentMap = new Map();
298
+ // List to store top-level comments
299
+ const topLevelComments = [];
300
+
301
+ // Iterate through the API comments
302
+ apiComments.forEach((comment) => {
303
+ // Store the comment in the map with its ID as the key
304
+ commentMap.set(comment.id, comment);
305
+ // Get the parent comment using the reply_post_id
306
+ const parentComment = commentMap.get(comment.reply_post_id);
307
+ // Check if the comment is a top-level comment
308
+ if (
309
+ !parentComment ||
310
+ comment.reply_post_id === comment.parent_post_id
311
+ ) {
312
+ // If it's a top-level comment, push it to the topLevelComments array
313
+ topLevelComments.push(comment);
314
+ } else {
315
+ // If it's a reply, add it to the parent comment's replies array
316
+ if (!parentComment.replies) parentComment.replies = [];
317
+ parentComment.replies.push(comment);
318
+ }
319
+ });
320
+
321
+ // Flatten the nested structure and return a single list of comments
322
+ return flattenComments(topLevelComments);
323
+ }
324
+
325
+ // Function to flatten nested comments into a single list
326
+ function flattenComments(comments) {
327
+ // Use reduce to flatten the nested comments array into a single list
328
+ return comments.reduce((flatComments, comment) => {
329
+ // Push the current comment to the flatComments array
330
+ flatComments.push(comment);
331
+ // If the current comment has replies, recursively flatten them and push to the flatComments array
332
+ if (comment.replies)
333
+ flatComments.push(...flattenComments(comment.replies));
334
+ // Return the flatComments array
335
+ return flatComments;
336
+ }, []);
337
+ }
338
+
339
+ const sortedComments = preprocessComments(json.posts);
340
+ return sortedComments;
341
+ } catch (err) {
342
+ console.error(err);
343
+ throw new SidechatAPIError(`Failed to get comments on post.`);
344
+ }
345
+ };
346
+
347
+ /**
348
+ * Gets groups to be displayed on the "Explore Groups" page
349
+ * @method
350
+ * @param {String} token - user bearer token
351
+ * @returns {SidechatGroup}
352
+ */
353
+ static getAvailableGroups = async (token) => {
354
+ try {
355
+ const res = await fetch(`https://api.sidechat.lol/v1/groups/explore`, {
356
+ method: "GET",
357
+ headers: {
358
+ ...defaultHeaders,
359
+ Authorization: `Bearer ${token}`,
360
+ },
361
+ });
362
+ const json = await res.json();
363
+ return json.groups;
364
+ } catch (err) {
365
+ console.error(err);
366
+ throw new SidechatAPIError(`Failed to get groups from explore.`);
367
+ }
368
+ };
369
+ }
370
+
371
+ export default SidechatAPIClient;
package/src/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import SidechatAPIClient from "./classes/SidechatAPIClient";
2
+ import SidechatAPIError from "./classes/SidechatAPIError";
3
+
4
+ export { SidechatAPIClient, SidechatAPIError };