musora-content-services 1.3.14 → 1.3.15

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,8 @@
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.15](https://github.com/railroadmedia/musora-content-services/compare/v1.3.14...v1.3.15) (2025-03-10)
6
+
5
7
  ### [1.3.14](https://github.com/railroadmedia/musora-content-services/compare/v1.3.13...v1.3.14) (2025-03-06)
6
8
 
7
9
  ### [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.15",
4
4
  "description": "A package for Musoras content services ",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/index.d.ts CHANGED
@@ -50,6 +50,8 @@ import {
50
50
  fetchChallengeLessonData,
51
51
  fetchChallengeMetadata,
52
52
  fetchChallengeUserActiveChallenges,
53
+ fetchCommentRelies,
54
+ fetchComments,
53
55
  fetchCompletedChallenges,
54
56
  fetchCompletedContent,
55
57
  fetchCompletedState,
@@ -64,6 +66,7 @@ import {
64
66
  fetchPlaylistItem,
65
67
  fetchPlaylistItems,
66
68
  fetchSongsInProgress,
69
+ fetchTopComment,
67
70
  fetchUserAward,
68
71
  fetchUserBadges,
69
72
  fetchUserChallengeProgress,
@@ -94,6 +97,12 @@ import {
94
97
  updatePlaylistItem
95
98
  } from './services/railcontent.js';
96
99
 
100
+ import {
101
+ rankCategories,
102
+ rankItems,
103
+ similarItems
104
+ } from './services/recommendations.js';
105
+
97
106
  import {
98
107
  fetchAll,
99
108
  fetchAllFilterOptions,
@@ -174,6 +183,8 @@ declare module 'musora-content-services' {
174
183
  fetchCoachLessons,
175
184
  fetchComingSoon,
176
185
  fetchCommentModContentData,
186
+ fetchCommentRelies,
187
+ fetchComments,
177
188
  fetchCompletedChallenges,
178
189
  fetchCompletedContent,
179
190
  fetchCompletedState,
@@ -213,6 +224,7 @@ declare module 'musora-content-services' {
213
224
  fetchSongArtistCount,
214
225
  fetchSongById,
215
226
  fetchSongsInProgress,
227
+ fetchTopComment,
216
228
  fetchTopLevelParentId,
217
229
  fetchUpcomingEvents,
218
230
  fetchUserAward,
@@ -253,11 +265,14 @@ declare module 'musora-content-services' {
253
265
  postContentReset,
254
266
  postContentUnliked,
255
267
  postRecordWatchSession,
268
+ rankCategories,
269
+ rankItems,
256
270
  recordWatchSession,
257
271
  reportPlaylist,
258
272
  reset,
259
273
  setLastUpdatedTime,
260
274
  setStudentViewForUser,
275
+ similarItems,
261
276
  unlikeContent,
262
277
  unpinPlaylist,
263
278
  updatePlaylist,
package/src/index.js CHANGED
@@ -50,6 +50,8 @@ import {
50
50
  fetchChallengeLessonData,
51
51
  fetchChallengeMetadata,
52
52
  fetchChallengeUserActiveChallenges,
53
+ fetchCommentRelies,
54
+ fetchComments,
53
55
  fetchCompletedChallenges,
54
56
  fetchCompletedContent,
55
57
  fetchCompletedState,
@@ -64,6 +66,7 @@ import {
64
66
  fetchPlaylistItem,
65
67
  fetchPlaylistItems,
66
68
  fetchSongsInProgress,
69
+ fetchTopComment,
67
70
  fetchUserAward,
68
71
  fetchUserBadges,
69
72
  fetchUserChallengeProgress,
@@ -94,6 +97,12 @@ import {
94
97
  updatePlaylistItem
95
98
  } from './services/railcontent.js';
96
99
 
100
+ import {
101
+ rankCategories,
102
+ rankItems,
103
+ similarItems
104
+ } from './services/recommendations.js';
105
+
97
106
  import {
98
107
  fetchAll,
99
108
  fetchAllFilterOptions,
@@ -173,6 +182,8 @@ export {
173
182
  fetchCoachLessons,
174
183
  fetchComingSoon,
175
184
  fetchCommentModContentData,
185
+ fetchCommentRelies,
186
+ fetchComments,
176
187
  fetchCompletedChallenges,
177
188
  fetchCompletedContent,
178
189
  fetchCompletedState,
@@ -212,6 +223,7 @@ export {
212
223
  fetchSongArtistCount,
213
224
  fetchSongById,
214
225
  fetchSongsInProgress,
226
+ fetchTopComment,
215
227
  fetchTopLevelParentId,
216
228
  fetchUpcomingEvents,
217
229
  fetchUserAward,
@@ -252,11 +264,14 @@ export {
252
264
  postContentReset,
253
265
  postContentUnliked,
254
266
  postRecordWatchSession,
267
+ rankCategories,
268
+ rankItems,
255
269
  recordWatchSession,
256
270
  reportPlaylist,
257
271
  reset,
258
272
  setLastUpdatedTime,
259
273
  setStudentViewForUser,
274
+ similarItems,
260
275
  unlikeContent,
261
276
  unpinPlaylist,
262
277
  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
  }
@@ -0,0 +1,155 @@
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
+ * @param {boolean} rankEachCategory - flag to sort each category by user's match
52
+ * @returns {Promise<Object|null>} - Returns the content_ids sorted by rank (most significant first)
53
+ * @example
54
+ * rankCategories('drumeo', {
55
+ * 1: [111222, 23120, 402199],
56
+ * 2: [2222, 33333, 44444]
57
+ * }
58
+ * )
59
+ * .then(status => console.log(status))
60
+ * .catch(error => console.error(error));
61
+ */
62
+ export async function rankCategories(brand, categories, rankEachCategory = true) {
63
+ if (categories.length === 0) {
64
+ return []
65
+ }
66
+ let data = {
67
+ 'brand': brand,
68
+ 'user_id': globalConfig.railcontentConfig.userId,
69
+ 'playlists': categories,
70
+ 'rank_each_list': Boolean(rankEachCategory),
71
+ }
72
+ const url = `/rank_playlists/`
73
+ try {
74
+ const response = await fetchHandler(url, 'POST', data)
75
+ let rankedCategories = {}
76
+ response['ranked_playlists'].forEach((category) => rankedCategories[category['playlist_id']] = categories[category['playlist_id']])
77
+ return rankedCategories
78
+ } catch (error) {
79
+ console.error('Fetch error:', error)
80
+ return null
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Fetches the completion status of a specific lesson for the current user.
86
+ *
87
+ * @param {brand} brand - brand of the content to filter
88
+ * @param {Array<string>} content_ids - The IDs of the content to rank
89
+ * @returns {Promise<Object|null>} - Returns the content_ids sorted by rank (most significant first)
90
+ * @example
91
+ * rankItems('drumeo', ([111222, 23120, 402199])
92
+ * .then(status => console.log(status))
93
+ * .catch(error => console.error(error));
94
+ */
95
+ export async function rankItems(brand, content_ids) {
96
+ if (content_ids.length === 0) {
97
+ return []
98
+ }
99
+ let data = {
100
+ 'brand': brand,
101
+ 'user_id': globalConfig.railcontentConfig.userId,
102
+ 'content_ids': content_ids,
103
+ }
104
+ const url = `/rank_items/`
105
+ try {
106
+ const response = await fetchHandler(url, 'POST', data)
107
+ return response['ranked_content_ids']
108
+ } catch (error) {
109
+ console.error('Fetch error:', error)
110
+ return null
111
+ }
112
+ }
113
+
114
+ async function fetchHandler(url, method = 'get', body = null) {
115
+
116
+ let headers = {
117
+ 'Content-Type': 'application/json',
118
+ Accept: 'application/json',
119
+ 'X-CSRF-TOKEN': globalConfig.recommendationsConfig.token,
120
+ }
121
+
122
+ const options = {
123
+ method,
124
+ headers,
125
+ }
126
+
127
+ if (body) {
128
+ options.body = JSON.stringify(body)
129
+ }
130
+ try {
131
+ const response = await fetchAbsolute(url, options)
132
+ if (response.ok) {
133
+ return await response.json()
134
+ } else {
135
+ console.error(`Fetch error: ${method} ${url} ${response.status} ${response.statusText}`)
136
+ console.log(response)
137
+ }
138
+ } catch (error) {
139
+ console.error('Fetch error:', error)
140
+ }
141
+ return null
142
+ }
143
+
144
+
145
+ function fetchAbsolute(url, params) {
146
+ if (globalConfig.recommendationsConfig.token) {
147
+ params.headers['Authorization'] = `Bearer ${globalConfig.recommendationsConfig.token}`
148
+ }
149
+ if (globalConfig.recommendationsConfig.baseUrl) {
150
+ if (url.startsWith('/')) {
151
+ return fetch(globalConfig.recommendationsConfig.baseUrl + url, params)
152
+ }
153
+ }
154
+ return fetch(url, params)
155
+ }