musora-content-services 1.3.14 → 1.3.16

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.3.16](https://github.com/railroadmedia/musora-content-services/compare/v1.3.15...v1.3.16) (2025-03-14)
6
+
7
+ ### [1.3.15](https://github.com/railroadmedia/musora-content-services/compare/v1.3.14...v1.3.15) (2025-03-10)
8
+
5
9
  ### [1.3.14](https://github.com/railroadmedia/musora-content-services/compare/v1.3.13...v1.3.14) (2025-03-06)
6
10
 
7
11
  ### [1.3.13](https://github.com/railroadmedia/musora-content-services/compare/v1.3.12...v1.3.13) (2025-03-06)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "1.3.14",
3
+ "version": "1.3.16",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
File without changes
package/src/index.d.ts CHANGED
@@ -38,18 +38,25 @@ import {
38
38
 
39
39
  import {
40
40
  addItemToPlaylist,
41
+ assignModeratorToComment,
42
+ closeComment,
41
43
  countAssignmentsAndLessons,
44
+ createComment,
42
45
  createPlaylist,
46
+ deleteComment,
43
47
  deletePlaylist,
44
48
  deletePlaylistItem,
45
49
  deletePlaylistLike,
46
50
  duplicatePlaylist,
51
+ editComment,
47
52
  fetchAllCompletedStates,
48
53
  fetchCarouselCardData,
49
54
  fetchChallengeIndexMetadata,
50
55
  fetchChallengeLessonData,
51
56
  fetchChallengeMetadata,
52
57
  fetchChallengeUserActiveChallenges,
58
+ fetchCommentRelies,
59
+ fetchComments,
53
60
  fetchCompletedChallenges,
54
61
  fetchCompletedContent,
55
62
  fetchCompletedState,
@@ -64,13 +71,16 @@ import {
64
71
  fetchPlaylistItem,
65
72
  fetchPlaylistItems,
66
73
  fetchSongsInProgress,
74
+ fetchTopComment,
67
75
  fetchUserAward,
68
76
  fetchUserBadges,
69
77
  fetchUserChallengeProgress,
70
78
  fetchUserLikes,
71
79
  fetchUserPermissionsData,
72
80
  fetchUserPlaylists,
81
+ likeComment,
73
82
  likePlaylist,
83
+ openComment,
74
84
  pinPlaylist,
75
85
  playback,
76
86
  postChallengesCommunityNotification,
@@ -87,13 +97,22 @@ import {
87
97
  postContentReset,
88
98
  postContentUnliked,
89
99
  postRecordWatchSession,
100
+ replyToComment,
90
101
  reportPlaylist,
91
102
  setStudentViewForUser,
103
+ unassignModeratorToComment,
104
+ unlikeComment,
92
105
  unpinPlaylist,
93
106
  updatePlaylist,
94
107
  updatePlaylistItem
95
108
  } from './services/railcontent.js';
96
109
 
110
+ import {
111
+ rankCategories,
112
+ rankItems,
113
+ similarItems
114
+ } from './services/recommendations.js';
115
+
97
116
  import {
98
117
  fetchAll,
99
118
  fetchAllFilterOptions,
@@ -146,16 +165,21 @@ import {
146
165
  declare module 'musora-content-services' {
147
166
  export {
148
167
  addItemToPlaylist,
168
+ assignModeratorToComment,
149
169
  assignmentStatusCompleted,
150
170
  assignmentStatusReset,
171
+ closeComment,
151
172
  contentStatusCompleted,
152
173
  contentStatusReset,
153
174
  countAssignmentsAndLessons,
175
+ createComment,
154
176
  createPlaylist,
177
+ deleteComment,
155
178
  deletePlaylist,
156
179
  deletePlaylistItem,
157
180
  deletePlaylistLike,
158
181
  duplicatePlaylist,
182
+ editComment,
159
183
  fetchAll,
160
184
  fetchAllCompletedStates,
161
185
  fetchAllFilterOptions,
@@ -174,6 +198,8 @@ declare module 'musora-content-services' {
174
198
  fetchCoachLessons,
175
199
  fetchComingSoon,
176
200
  fetchCommentModContentData,
201
+ fetchCommentRelies,
202
+ fetchComments,
177
203
  fetchCompletedChallenges,
178
204
  fetchCompletedContent,
179
205
  fetchCompletedState,
@@ -213,6 +239,7 @@ declare module 'musora-content-services' {
213
239
  fetchSongArtistCount,
214
240
  fetchSongById,
215
241
  fetchSongsInProgress,
242
+ fetchTopComment,
216
243
  fetchTopLevelParentId,
217
244
  fetchUpcomingEvents,
218
245
  fetchUserAward,
@@ -235,8 +262,10 @@ declare module 'musora-content-services' {
235
262
  initializeService,
236
263
  isContentLiked,
237
264
  jumpToContinueContent,
265
+ likeComment,
238
266
  likeContent,
239
267
  likePlaylist,
268
+ openComment,
240
269
  pinPlaylist,
241
270
  playback,
242
271
  postChallengesCommunityNotification,
@@ -253,11 +282,17 @@ declare module 'musora-content-services' {
253
282
  postContentReset,
254
283
  postContentUnliked,
255
284
  postRecordWatchSession,
285
+ rankCategories,
286
+ rankItems,
256
287
  recordWatchSession,
288
+ replyToComment,
257
289
  reportPlaylist,
258
290
  reset,
259
291
  setLastUpdatedTime,
260
292
  setStudentViewForUser,
293
+ similarItems,
294
+ unassignModeratorToComment,
295
+ unlikeComment,
261
296
  unlikeContent,
262
297
  unpinPlaylist,
263
298
  updatePlaylist,
package/src/index.js CHANGED
@@ -38,18 +38,25 @@ import {
38
38
 
39
39
  import {
40
40
  addItemToPlaylist,
41
+ assignModeratorToComment,
42
+ closeComment,
41
43
  countAssignmentsAndLessons,
44
+ createComment,
42
45
  createPlaylist,
46
+ deleteComment,
43
47
  deletePlaylist,
44
48
  deletePlaylistItem,
45
49
  deletePlaylistLike,
46
50
  duplicatePlaylist,
51
+ editComment,
47
52
  fetchAllCompletedStates,
48
53
  fetchCarouselCardData,
49
54
  fetchChallengeIndexMetadata,
50
55
  fetchChallengeLessonData,
51
56
  fetchChallengeMetadata,
52
57
  fetchChallengeUserActiveChallenges,
58
+ fetchCommentRelies,
59
+ fetchComments,
53
60
  fetchCompletedChallenges,
54
61
  fetchCompletedContent,
55
62
  fetchCompletedState,
@@ -64,13 +71,16 @@ import {
64
71
  fetchPlaylistItem,
65
72
  fetchPlaylistItems,
66
73
  fetchSongsInProgress,
74
+ fetchTopComment,
67
75
  fetchUserAward,
68
76
  fetchUserBadges,
69
77
  fetchUserChallengeProgress,
70
78
  fetchUserLikes,
71
79
  fetchUserPermissionsData,
72
80
  fetchUserPlaylists,
81
+ likeComment,
73
82
  likePlaylist,
83
+ openComment,
74
84
  pinPlaylist,
75
85
  playback,
76
86
  postChallengesCommunityNotification,
@@ -87,13 +97,22 @@ import {
87
97
  postContentReset,
88
98
  postContentUnliked,
89
99
  postRecordWatchSession,
100
+ replyToComment,
90
101
  reportPlaylist,
91
102
  setStudentViewForUser,
103
+ unassignModeratorToComment,
104
+ unlikeComment,
92
105
  unpinPlaylist,
93
106
  updatePlaylist,
94
107
  updatePlaylistItem
95
108
  } from './services/railcontent.js';
96
109
 
110
+ import {
111
+ rankCategories,
112
+ rankItems,
113
+ similarItems
114
+ } from './services/recommendations.js';
115
+
97
116
  import {
98
117
  fetchAll,
99
118
  fetchAllFilterOptions,
@@ -145,16 +164,21 @@ import {
145
164
 
146
165
  export {
147
166
  addItemToPlaylist,
167
+ assignModeratorToComment,
148
168
  assignmentStatusCompleted,
149
169
  assignmentStatusReset,
170
+ closeComment,
150
171
  contentStatusCompleted,
151
172
  contentStatusReset,
152
173
  countAssignmentsAndLessons,
174
+ createComment,
153
175
  createPlaylist,
176
+ deleteComment,
154
177
  deletePlaylist,
155
178
  deletePlaylistItem,
156
179
  deletePlaylistLike,
157
180
  duplicatePlaylist,
181
+ editComment,
158
182
  fetchAll,
159
183
  fetchAllCompletedStates,
160
184
  fetchAllFilterOptions,
@@ -173,6 +197,8 @@ export {
173
197
  fetchCoachLessons,
174
198
  fetchComingSoon,
175
199
  fetchCommentModContentData,
200
+ fetchCommentRelies,
201
+ fetchComments,
176
202
  fetchCompletedChallenges,
177
203
  fetchCompletedContent,
178
204
  fetchCompletedState,
@@ -212,6 +238,7 @@ export {
212
238
  fetchSongArtistCount,
213
239
  fetchSongById,
214
240
  fetchSongsInProgress,
241
+ fetchTopComment,
215
242
  fetchTopLevelParentId,
216
243
  fetchUpcomingEvents,
217
244
  fetchUserAward,
@@ -234,8 +261,10 @@ export {
234
261
  initializeService,
235
262
  isContentLiked,
236
263
  jumpToContinueContent,
264
+ likeComment,
237
265
  likeContent,
238
266
  likePlaylist,
267
+ openComment,
239
268
  pinPlaylist,
240
269
  playback,
241
270
  postChallengesCommunityNotification,
@@ -252,11 +281,17 @@ export {
252
281
  postContentReset,
253
282
  postContentUnliked,
254
283
  postRecordWatchSession,
284
+ rankCategories,
285
+ rankItems,
255
286
  recordWatchSession,
287
+ replyToComment,
256
288
  reportPlaylist,
257
289
  reset,
258
290
  setLastUpdatedTime,
259
291
  setStudentViewForUser,
292
+ similarItems,
293
+ unassignModeratorToComment,
294
+ unlikeComment,
260
295
  unlikeContent,
261
296
  unpinPlaylist,
262
297
  updatePlaylist,
@@ -5,6 +5,7 @@
5
5
  export let globalConfig = {
6
6
  sanityConfig: {},
7
7
  railcontentConfig: {},
8
+ recommendationsConfig: {},
8
9
  localStorage: null,
9
10
  isMA: false,
10
11
  localTimezoneString: null, // In format: America/Vancouver
@@ -35,6 +36,8 @@ const excludeFromGeneratedIndex = []
35
36
  * @param {string} config.railcontentConfig.userId - The user ID for fetching user-specific data.
36
37
  * @param {string} config.railcontentConfig.baseUrl - The url for the environment.
37
38
  * @param {string} config.railcontentConfig.authToken - The bearer authorization token.
39
+ * @param {string} config.recommendationsConfig.token - The token for authenticating recommendation requests.
40
+ * @param {string} config.recommendationsConfig.baseUrl - The url for the recommendation server.
38
41
  * @param {Object} config.localStorage - Cache to use for localStorage
39
42
  * @param {boolean} config.isMA - Variable that tells if the library is used by MA or FEW
40
43
  * @param {string} config.localTimezoneString - The local timezone string in format: America/Vancouver
@@ -49,15 +52,20 @@ const excludeFromGeneratedIndex = []
49
52
  * dataset: 'your-dataset-name',
50
53
  * version: '2021-06-07',
51
54
  * debug: true,
52
- * useCachedAPI: false
55
+ * useCachedAPI: false,
53
56
  * },
54
57
  * railcontentConfig: {
55
58
  * token: 'your-user-api-token',
56
59
  * userId: 'current-user-id',
57
- * baseUrl: 'https://web-staging-one.musora.com'
60
+ * baseUrl: 'https://web-staging-one.musora.com',
61
+ * authToken 'your-auth-token',
62
+ * },
63
+ * recommendationsConfig: {
64
+ * token: 'your-user-api-token',
65
+ * baseUrl: 'https://MusoraProductDepartment-PWGenerator.hf.space',
58
66
  * },
59
67
  * localStorage: localStorage,
60
- * isMA: false
68
+ * isMA: false,
61
69
  * });
62
70
  */
63
71
  export function initializeService(config) {
@@ -66,4 +74,5 @@ export function initializeService(config) {
66
74
  globalConfig.localStorage = config.localStorage
67
75
  globalConfig.isMA = config.isMA || false
68
76
  globalConfig.localTimezoneString = config.localTimezoneString || null
77
+ globalConfig.recommendationsConfig = config.recommendationsConfig
69
78
  }
File without changes
@@ -290,6 +290,10 @@ async function patchDataHandler(url, data) {
290
290
  return fetchHandler(url, 'patch', null, data)
291
291
  }
292
292
 
293
+ async function deleteDataHandler(url, data) {
294
+ return fetchHandler(url, 'delete')
295
+ }
296
+
293
297
  export async function fetchHandler(url, method = 'get', dataVersion = null, body = null) {
294
298
  let headers = {
295
299
  'Content-Type': 'application/json',
@@ -1206,28 +1210,28 @@ export async function setStudentViewForUser(userId, enable) {
1206
1210
  * @returns {Promise<Object|null>} - A promise that resolves to an comment object
1207
1211
  */
1208
1212
  export async function fetchTopComment(railcontentId) {
1209
- const url = `/api/content/v1/comments/${railcontentId}/top`
1213
+ const url = `/api/content/v1/comments/content/${railcontentId}/top`
1210
1214
  return await fetchHandler(url)
1211
1215
  }
1212
1216
 
1213
1217
 
1214
1218
  /**
1215
1219
  *
1216
- * @param railcontentId
1217
- * @param page
1218
- * @param limit
1220
+ * @param {int} railcontentId
1221
+ * @param {int} page
1222
+ * @param {int} limit
1219
1223
  * @returns {Promise<*|null>}
1220
1224
  */
1221
1225
  export async function fetchComments(railcontentId, page = 1, limit = 20) {
1222
- const url = `/api/content/v1/comments/${railcontentId}/all?page=${page}&limit=${limit}`
1226
+ const url = `/api/content/v1/comments/content/${railcontentId}/all?page=${page}&limit=${limit}`
1223
1227
  return await fetchHandler(url)
1224
1228
  }
1225
1229
 
1226
1230
  /**
1227
1231
  *
1228
- * @param commentId
1229
- * @param page
1230
- * @param limit
1232
+ * @param {int} commentId
1233
+ * @param {int} page
1234
+ * @param {int} limit
1231
1235
  * @returns {Promise<*|null>}
1232
1236
  */
1233
1237
  export async function fetchCommentRelies(commentId, page = 1, limit = 20) {
@@ -1235,6 +1239,115 @@ export async function fetchCommentRelies(commentId, page = 1, limit = 20) {
1235
1239
  return await fetchHandler(url)
1236
1240
  }
1237
1241
 
1242
+ /**
1243
+ * @param {int} commentId
1244
+ * @returns {Promise<*|null>}
1245
+ */
1246
+ export async function deleteComment(commentId) {
1247
+ const url = `/api/content/v1/comments/${commentId}`
1248
+ return await fetchHandler(url, "DELETE")
1249
+ }
1250
+
1251
+ /**
1252
+ * @param {int} commentId
1253
+ * @param {string} comment
1254
+ * @returns {Promise<*|null>}
1255
+ */
1256
+ export async function replyToComment(commentId, comment) {
1257
+ const data = {'comment' : comment}
1258
+ const url = `/api/content/v1/comments/${commentId}/reply`
1259
+ return await postDataHandler(url, data)
1260
+ }
1261
+
1262
+ /**
1263
+ * @param {int} railcontentId
1264
+ * @param {string} comment
1265
+ * @returns {Promise<*|null>}
1266
+ */
1267
+ export async function createComment(railcontentId, comment) {
1268
+ const data = {
1269
+ 'comment' : comment,
1270
+ 'content_id' : railcontentId
1271
+ }
1272
+ const url = `/api/content/v1/comments/store`
1273
+ return await postDataHandler(url, data)
1274
+ }
1275
+
1276
+ /**
1277
+ * @param {int} commentId
1278
+ * @returns {Promise<*|null>}
1279
+ */
1280
+ export async function assignModeratorToComment(commentId) {
1281
+ const url = `/api/content/v1/comments/${commentId}/assign_moderator`
1282
+ return await postDataHandler(url)
1283
+ }
1284
+
1285
+ /**
1286
+ * @param {int} commentId
1287
+ * @returns {Promise<*|null>}
1288
+ */
1289
+ export async function unassignModeratorToComment(commentId) {
1290
+ const url = `/api/content/v1/comments/${commentId}/unassign_moderator`
1291
+ return await postDataHandler(url)
1292
+ }
1293
+
1294
+ /**
1295
+ * @param {int} commentId
1296
+ * @returns {Promise<*|null>}
1297
+ */
1298
+ export async function likeComment(commentId) {
1299
+ const url = `/api/content/v1/comments/${commentId}/like`
1300
+ return await postDataHandler(url)
1301
+ }
1302
+
1303
+ /**
1304
+ * @param {int} commentId
1305
+ * @returns {Promise<*|null>}
1306
+ */
1307
+ export async function unlikeComment(commentId) {
1308
+ const url = `/api/content/v1/comments/${commentId}/like`
1309
+ return await deleteDataHandler(url)
1310
+ }
1311
+
1312
+ /**
1313
+ * @param {int} commentId
1314
+ * @returns {Promise<*|null>}
1315
+ */
1316
+ export async function closeComment(commentId) {
1317
+ const url = `/api/content/v1/comments/${commentId}`
1318
+ const data = {
1319
+ 'conversation_status' : 'closed'
1320
+ }
1321
+ return await patchDataHandler(url, data)
1322
+ }
1323
+
1324
+ /**
1325
+ * @param {int} commentId
1326
+ * @returns {Promise<*|null>}
1327
+ */
1328
+ export async function openComment(commentId) {
1329
+ const url = `/api/content/v1/comments/${commentId}`
1330
+ const data = {
1331
+ 'conversation_status' : 'open'
1332
+ }
1333
+ return await patchDataHandler(url, data)
1334
+ }
1335
+
1336
+ /**
1337
+ * @param {int} commentId
1338
+ * @param {string} comment
1339
+ * @returns {Promise<*|null>}
1340
+ */
1341
+ export async function editComment(commentId, comment) {
1342
+ const url = `/api/content/v1/comments/${commentId}`
1343
+ const data = {
1344
+ 'comment' : comment
1345
+ }
1346
+ return await patchDataHandler(url, data)
1347
+ }
1348
+
1349
+
1350
+
1238
1351
  function fetchAbsolute(url, params) {
1239
1352
  if (globalConfig.railcontentConfig.authToken) {
1240
1353
  params.headers['Authorization'] = `Bearer ${globalConfig.railcontentConfig.authToken}`
@@ -0,0 +1,153 @@
1
+ /**
2
+ * @module Railcontent-Services
3
+ */
4
+
5
+ import { globalConfig } from './config.js'
6
+
7
+ /**
8
+ * Exported functions that are excluded from index generation.
9
+ *
10
+ * @type {string[]}
11
+ */
12
+ const excludeFromGeneratedIndex = []
13
+
14
+ /**
15
+ * Fetches similar content to the provided content id
16
+ *
17
+ * @param {brand} brand - brand of the content to filter
18
+ * @param {integer} content_id - The ID of the content to find similar items for
19
+ * @param {integer} count - number of items to return
20
+ * @returns {Promise<Object|null>} - Returns the content_ids sorted by rank (most significant first)
21
+ * @example
22
+ * rankItems('drumeo', 1113)
23
+ * .then(status => console.log(status))
24
+ * .catch(error => console.error(error));
25
+ */
26
+ export async function similarItems(brand, content_id, count = 10) {
27
+ if (!content_id) {
28
+ return []
29
+ }
30
+
31
+ let data = {
32
+ 'brand': brand,
33
+ 'content_ids': content_id,
34
+ 'num_similar': count,
35
+ }
36
+ const url = `/similar_items/`
37
+ try {
38
+ const response = await fetchHandler(url, 'POST', data)
39
+ return response['similar_items']
40
+ } catch (error) {
41
+ console.error('Fetch error:', error)
42
+ return null
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Sorts the provided categories based on the user's match
48
+ *
49
+ * @param {brand} brand - brand of the content to filter
50
+ * @param {Object} categories - Keyed arrays of content ids
51
+ * @returns {Promise<Object|null>} - Returns the content_ids sorted by rank (most significant first), elements in each category are also ranked
52
+ * @example
53
+ * rankCategories('drumeo', {
54
+ * 1: [111222, 23120, 402199],
55
+ * 2: [2222, 33333, 44444]
56
+ * }
57
+ * )
58
+ * .then(status => console.log(status))
59
+ * .catch(error => console.error(error));
60
+ */
61
+ export async function rankCategories(brand, categories) {
62
+ if (categories.length === 0) {
63
+ return []
64
+ }
65
+ let data = {
66
+ 'brand': brand,
67
+ 'user_id': globalConfig.railcontentConfig.userId,
68
+ 'playlists': categories,
69
+ }
70
+ const url = `/rank_each_list/`
71
+ try {
72
+ const response = await fetchHandler(url, 'POST', data)
73
+ let rankedCategories = {}
74
+ response['ranked_playlists'].forEach((category) => rankedCategories[category['playlist_id']] = categories[category['playlist_id']])
75
+ return rankedCategories
76
+ } catch (error) {
77
+ console.error('Fetch error:', error)
78
+ return null
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Fetches the completion status of a specific lesson for the current user.
84
+ *
85
+ * @param {brand} brand - brand of the content to filter
86
+ * @param {Array<string>} content_ids - The IDs of the content to rank
87
+ * @returns {Promise<Object|null>} - Returns the content_ids sorted by rank (most significant first)
88
+ * @example
89
+ * rankItems('drumeo', ([111222, 23120, 402199])
90
+ * .then(status => console.log(status))
91
+ * .catch(error => console.error(error));
92
+ */
93
+ export async function rankItems(brand, content_ids) {
94
+ if (content_ids.length === 0) {
95
+ return []
96
+ }
97
+ let data = {
98
+ 'brand': brand,
99
+ 'user_id': globalConfig.railcontentConfig.userId,
100
+ 'content_ids': content_ids,
101
+ }
102
+ const url = `/rank_items/`
103
+ try {
104
+ const response = await fetchHandler(url, 'POST', data)
105
+ return response['ranked_content_ids']
106
+ } catch (error) {
107
+ console.error('Fetch error:', error)
108
+ return null
109
+ }
110
+ }
111
+
112
+ async function fetchHandler(url, method = 'get', body = null) {
113
+
114
+ let headers = {
115
+ 'Content-Type': 'application/json',
116
+ Accept: 'application/json',
117
+ 'X-CSRF-TOKEN': globalConfig.recommendationsConfig.token,
118
+ }
119
+
120
+ const options = {
121
+ method,
122
+ headers,
123
+ }
124
+
125
+ if (body) {
126
+ options.body = JSON.stringify(body)
127
+ }
128
+ try {
129
+ const response = await fetchAbsolute(url, options)
130
+ if (response.ok) {
131
+ return await response.json()
132
+ } else {
133
+ console.error(`Fetch error: ${method} ${url} ${response.status} ${response.statusText}`)
134
+ console.log(response)
135
+ }
136
+ } catch (error) {
137
+ console.error('Fetch error:', error)
138
+ }
139
+ return null
140
+ }
141
+
142
+
143
+ function fetchAbsolute(url, params) {
144
+ if (globalConfig.recommendationsConfig.token) {
145
+ params.headers['Authorization'] = `Bearer ${globalConfig.recommendationsConfig.token}`
146
+ }
147
+ if (globalConfig.recommendationsConfig.baseUrl) {
148
+ if (url.startsWith('/')) {
149
+ return fetch(globalConfig.recommendationsConfig.baseUrl + url, params)
150
+ }
151
+ }
152
+ return fetch(url, params)
153
+ }