musora-content-services 2.87.0 → 2.88.1

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,22 @@
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
+ ### [2.88.1](https://github.com/railroadmedia/musora-content-services/compare/v2.88.0...v2.88.1) (2025-11-26)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * add queries in get daily session and get active path ([#593](https://github.com/railroadmedia/musora-content-services/issues/593)) ([91f3974](https://github.com/railroadmedia/musora-content-services/commit/91f3974c530ca695fa87f5bfe14066e5a473db79))
11
+
12
+ ## [2.88.0](https://github.com/railroadmedia/musora-content-services/compare/v2.86.1...v2.88.0) (2025-11-26)
13
+
14
+
15
+ ### Features
16
+
17
+ * **BEH-1418:** refactor learning path endpoints ([#589](https://github.com/railroadmedia/musora-content-services/issues/589)) ([e3637f6](https://github.com/railroadmedia/musora-content-services/commit/e3637f6359ddf8f4295eead890de6457b942b4ea))
18
+ * Implement unified user reporting system ([7aa42ab](https://github.com/railroadmedia/musora-content-services/commit/7aa42ab8dcee09ce3f293d9fbb1a203dcbe94414))
19
+ * **MU2-1250:** Implement unified user reporting system ([3303282](https://github.com/railroadmedia/musora-content-services/commit/33032829b729efa9f9b1e40f31179127c8c74f9d))
20
+
5
21
  ## [2.87.0](https://github.com/railroadmedia/musora-content-services/compare/v2.86.1...v2.87.0) (2025-11-26)
6
22
 
7
23
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "musora-content-services",
3
- "version": "2.87.0",
3
+ "version": "2.88.1",
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
@@ -242,6 +242,11 @@ import {
242
242
  recommendations
243
243
  } from './services/recommendations.js';
244
244
 
245
+ import {
246
+ getReportIssueOptions,
247
+ report
248
+ } from './services/reporting/reporting.ts';
249
+
245
250
  import {
246
251
  buildEntityAndTotalQuery,
247
252
  fetchAll,
@@ -597,6 +602,7 @@ declare module 'musora-content-services' {
597
602
  getRecent,
598
603
  getRecentActivity,
599
604
  getRecommendedForYou,
605
+ getReportIssueOptions,
600
606
  getResumeTimeSeconds,
601
607
  getResumeTimeSecondsByIds,
602
608
  getSanityDate,
@@ -662,6 +668,7 @@ declare module 'musora-content-services' {
662
668
  removeContentAsNotInterested,
663
669
  removeUserPractice,
664
670
  replyToComment,
671
+ report,
665
672
  reportComment,
666
673
  reportPlaylist,
667
674
  requestEmailChange,
package/src/index.js CHANGED
@@ -242,6 +242,11 @@ import {
242
242
  recommendations
243
243
  } from './services/recommendations.js';
244
244
 
245
+ import {
246
+ getReportIssueOptions,
247
+ report
248
+ } from './services/reporting/reporting.ts';
249
+
245
250
  import {
246
251
  buildEntityAndTotalQuery,
247
252
  fetchAll,
@@ -596,6 +601,7 @@ export {
596
601
  getRecent,
597
602
  getRecentActivity,
598
603
  getRecommendedForYou,
604
+ getReportIssueOptions,
599
605
  getResumeTimeSeconds,
600
606
  getResumeTimeSecondsByIds,
601
607
  getSanityDate,
@@ -661,6 +667,7 @@ export {
661
667
  removeContentAsNotInterested,
662
668
  removeUserPractice,
663
669
  replyToComment,
670
+ report,
664
671
  reportComment,
665
672
  reportPlaylist,
666
673
  requestEmailChange,
@@ -3,13 +3,12 @@
3
3
  */
4
4
 
5
5
  import { fetchHandler } from '../railcontent.js'
6
- import { fetchByRailContentId, fetchByRailContentIds, fetchMethodV2Structure } from '../sanity.js'
6
+ import { fetchByRailContentId, fetchMethodV2Structure } from '../sanity.js'
7
7
  import { addContextToContent } from '../contentAggregator.js'
8
8
  import {
9
9
  contentStatusCompleted,
10
10
  contentStatusReset,
11
11
  getProgressState,
12
- getProgressStateByIds
13
12
  } from '../contentProgress.js'
14
13
 
15
14
  const BASE_PATH: string = `/api/content-org`
@@ -21,10 +20,6 @@ interface ActiveLearningPathResponse {
21
20
  active_learning_path_id: number,
22
21
  }
23
22
 
24
-
25
-
26
-
27
-
28
23
  /**
29
24
  * Gets today's daily session for the user.
30
25
  * @param brand
@@ -32,9 +27,8 @@ interface ActiveLearningPathResponse {
32
27
  */
33
28
  export async function getDailySession(brand: string, userDate: Date) {
34
29
  const stringDate = userDate.toISOString().split('T')[0]
35
- const url: string = `${LEARNING_PATHS_PATH}/daily-session/get`
36
- const body = { brand: brand, userDate: stringDate }
37
- return await fetchHandler(url, 'GET', null, body)
30
+ const url: string = `${LEARNING_PATHS_PATH}/daily-session/get?brand=${brand}&userDate=${userDate}`
31
+ return await fetchHandler(url, 'GET', null, null)
38
32
  }
39
33
 
40
34
  /**
@@ -59,9 +53,8 @@ export async function updateDailySession(
59
53
  * @param brand
60
54
  */
61
55
  export async function getActivePath(brand: string) {
62
- const url: string = `${LEARNING_PATHS_PATH}/active-path/get`
63
- const body = { brand: brand }
64
- return await fetchHandler(url, 'GET', null, body)
56
+ const url: string = `${LEARNING_PATHS_PATH}/active-path/get?brand=${brand}`
57
+ return await fetchHandler(url, 'GET', null, null)
65
58
  }
66
59
 
67
60
  /**
@@ -0,0 +1,316 @@
1
+ # Reporting Service
2
+
3
+ Service for submitting user reports about content, comments, forum posts, and playlists.
4
+
5
+ ## Overview
6
+
7
+ This service provides two main functions for reporting content:
8
+
9
+ 1. **`report()`** - Unified method to submit reports for any type of content (content, comments, forum posts, playlists)
10
+ 2. **`getReportIssueOptions()`** - Helper function to get valid issue options for each reportable type, with support for platform-specific options (web vs mobile app)
11
+
12
+ Reports are sent to the appropriate team (support or mentors) based on the content type. Both functions are designed to be used by the web platform (MPF) and mobile app (MA) to ensure consistent reporting options and behavior.
13
+
14
+ ## Features
15
+
16
+ - ✅ Unified `report()` method for all reportable types
17
+ - ✅ Type-safe issue selection with TypeScript generics
18
+ - ✅ Platform-specific options (web vs mobile app)
19
+ - ✅ Helper function to get valid issue options by type
20
+ - ✅ Rate limiting (10 requests per minute per user)
21
+ - ✅ Emails sent to appropriate teams (support or mentors)
22
+ - ✅ Full TypeScript support with mapped types
23
+
24
+ ## Installation
25
+
26
+ The reporting service is included in `musora-content-services`. Simply import the functions you need:
27
+
28
+ ```typescript
29
+ import { report, getReportIssueOptions } from 'musora-content-services'
30
+ ```
31
+
32
+ Both functions are exported from `services/reporting/reporting.ts`.
33
+
34
+ ## API Reference
35
+
36
+ ### `report<T>(params)`
37
+
38
+ Unified method to submit a report for any type. Uses TypeScript generics for type-safe issue selection.
39
+
40
+ **Type Parameter:**
41
+ - `T extends ReportableType` - The type of content being reported
42
+
43
+ **Parameters:**
44
+ ```typescript
45
+ type ReportParams<T extends ReportableType> = {
46
+ type: T // 'content' | 'comment' | 'forum_post' | 'playlist'
47
+ id: number // ID of the entity being reported
48
+ issue: IssueTypeMap[T] // Type-safe issue (varies by type)
49
+ details?: string // Required when issue is 'other', not sent otherwise
50
+ brand: string // Required: 'drumeo', 'pianote', 'guitareo', 'singeo', 'playbass'
51
+ }
52
+ ```
53
+
54
+ **Returns:** `Promise<ReportResponse>`
55
+ ```typescript
56
+ interface ReportResponse {
57
+ report_id: number // The ID of the submitted report
58
+ message: string // Success message
59
+ }
60
+ ```
61
+
62
+ **Example - Report Content:**
63
+ ```typescript
64
+ import { report } from 'musora-content-services'
65
+
66
+ const response = await report({
67
+ type: 'content',
68
+ id: 12345,
69
+ issue: 'video_issue',
70
+ brand: 'drumeo'
71
+ })
72
+
73
+ console.log(`Report submitted with ID: ${response.report_id}`)
74
+ console.log(response.message) // "Report submitted successfully"
75
+ ```
76
+
77
+ **Example - Report Comment:**
78
+ ```typescript
79
+ await report({
80
+ type: 'comment',
81
+ id: 67890,
82
+ issue: 'offensive_language',
83
+ brand: 'pianote'
84
+ })
85
+ ```
86
+
87
+ **Example - Report Forum Post:**
88
+ ```typescript
89
+ await report({
90
+ type: 'forum_post',
91
+ id: 45678,
92
+ issue: 'abusive',
93
+ brand: 'guitareo'
94
+ })
95
+ ```
96
+
97
+ **Example - Report Playlist:**
98
+ ```typescript
99
+ await report({
100
+ type: 'playlist',
101
+ id: 99999,
102
+ issue: 'incorrect_metadata',
103
+ brand: 'singeo'
104
+ })
105
+ ```
106
+
107
+ **Example - Report with 'other' issue (details required):**
108
+ ```typescript
109
+ await report({
110
+ type: 'content',
111
+ id: 12345,
112
+ issue: 'other',
113
+ details: 'The instructor audio is out of sync with the video',
114
+ brand: 'drumeo'
115
+ })
116
+ ```
117
+
118
+ ---
119
+
120
+ ### `getReportIssueOptions(type, isMobileApp?)`
121
+
122
+ Helper function to get valid issue options for a specific reportable type. Returns both the value and user-friendly label for each option.
123
+
124
+ **Parameters:**
125
+ ```typescript
126
+ type: ReportableType // 'content' | 'comment' | 'forum_post' | 'playlist'
127
+ isMobileApp?: boolean // Default: false. Set to true for mobile app options
128
+ ```
129
+
130
+ **Returns:** `ReportIssueOption[]`
131
+ ```typescript
132
+ interface ReportIssueOption {
133
+ value: string // Issue value to send to API
134
+ label: string // User-friendly label for display
135
+ }
136
+ ```
137
+
138
+ **Example - Web Platform:**
139
+ ```typescript
140
+ import { getReportIssueOptions } from 'musora-content-services'
141
+
142
+ // Get content issue options for web
143
+ const options = getReportIssueOptions('content')
144
+ // Returns:
145
+ // [
146
+ // { value: 'incorrect_metadata', label: 'The lesson image, title or description is incorrect' },
147
+ // { value: 'video_issue', label: 'Video issue' },
148
+ // { value: 'assignment_issue', label: 'An issue with lesson assignment' },
149
+ // { value: 'other', label: 'Other' }
150
+ // ]
151
+ options.map(opt => ({
152
+ ...opt,
153
+ label: t(`report.${opt.value}`)
154
+ }))
155
+ ```
156
+
157
+ **Example - Mobile App:**
158
+ ```typescript
159
+ // Get content issue options for mobile app (includes download option)
160
+ const options = getReportIssueOptions('content', true)
161
+ // Returns:
162
+ // [
163
+ // { value: 'incorrect_metadata', label: 'The lesson image, title or description is incorrect' },
164
+ // { value: 'video_issue', label: 'Video issue' },
165
+ // { value: 'download_unavailable', label: 'Download is not available' },
166
+ // { value: 'assignment_issue', label: 'An issue with lesson assignment' },
167
+ // { value: 'other', label: 'Other' }
168
+ // ]
169
+ options.map(opt => ({
170
+ ...opt,
171
+ label: t(`report.${opt.value}`)
172
+ }))
173
+ ```
174
+
175
+ **Example - Comment Issues:**
176
+ ```typescript
177
+ const commentOptions = getReportIssueOptions('comment')
178
+ // Returns:
179
+ // [
180
+ // { value: 'offensive_language', label: 'It contains offensive language or content' },
181
+ // { value: 'abusive', label: "It's abusive or harmful" },
182
+ // { value: 'personal_information', label: 'It contains personal information' },
183
+ // { value: 'misleading', label: "It's misleading or a false claim" },
184
+ // { value: 'other', label: 'Other reasons' }
185
+ // ]
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Report Issues by Type
191
+
192
+ ### Content & Playlists:
193
+ - `incorrect_metadata` - The lesson image, title or description is incorrect
194
+ - `video_issue` - Video issue
195
+ - `download_unavailable` - Download is not available (mobile app only)
196
+ - `assignment_issue` - An issue with lesson assignment
197
+ - `other` - Other
198
+
199
+ ### Comments & Forum Posts:
200
+ - `offensive_language` - It contains offensive language or content
201
+ - `abusive` - It's abusive or harmful
202
+ - `personal_information` - It contains personal information
203
+ - `misleading` - It's misleading or a false claim
204
+ - `other` - Other reasons
205
+
206
+ **Important:** The `details` field is **required** when `issue` is `'other'` and should **not be sent** for other issue types.
207
+
208
+ ---
209
+
210
+ ## Rate Limiting
211
+
212
+ API requests are rate-limited to **10 requests per minute per user**. If you exceed this limit, you'll receive a `429 Too Many Requests` error.
213
+
214
+ ---
215
+
216
+ ## Email Recipients
217
+
218
+ Reports are automatically routed to the appropriate team:
219
+
220
+ | Report Type | Email Recipient |
221
+ |-------------|----------------|
222
+ | Forum Posts | mentors@musora.com |
223
+ | Comments | mentors@musora.com |
224
+ | Content | support@musora.com |
225
+ | Playlists | support@musora.com |
226
+
227
+ ---
228
+
229
+ ## Platform-Specific Options
230
+
231
+ The `getReportIssueOptions()` function supports platform-specific options via the `isMobileApp` parameter:
232
+
233
+ **Web Platform (default):**
234
+ - Does NOT include "Download is not available" option
235
+ - Use: `getReportIssueOptions('content')`
236
+
237
+ **Mobile App:**
238
+ - INCLUDES "Download is not available" option for content and playlists
239
+ - Use: `getReportIssueOptions('content', true)`
240
+
241
+
242
+ ---
243
+
244
+ ## Error Handling
245
+
246
+ ```typescript
247
+ import { report } from 'musora-content-services'
248
+
249
+ try {
250
+ const response = await report({
251
+ type: 'content',
252
+ id: 123,
253
+ issue: 'video_issue',
254
+ brand: 'drumeo'
255
+ })
256
+
257
+ // Handle success
258
+ showToast('Report submitted successfully')
259
+ } catch (error) {
260
+ if (error.status === 429) {
261
+ // Rate limit exceeded
262
+ showToast('Too many reports. Please try again later.')
263
+ } else if (error.status === 422) {
264
+ // Validation error
265
+ showToast(error.message || 'Invalid report data')
266
+ } else if (error.status === 401) {
267
+ // Not authenticated
268
+ showToast('Please log in to submit a report')
269
+ } else {
270
+ // Other errors
271
+ showToast('Failed to submit report')
272
+ }
273
+ }
274
+ ```
275
+
276
+ ---
277
+
278
+ ## Type Safety
279
+
280
+ The reporting service uses TypeScript generics to ensure type-safe issue selection:
281
+
282
+ ```typescript
283
+ // ✅ Type-safe: 'video_issue' is valid for content
284
+ await report({
285
+ type: 'content',
286
+ id: 123,
287
+ issue: 'video_issue', // TypeScript knows this is valid
288
+ brand: 'drumeo'
289
+ })
290
+
291
+ // ❌ Type error: 'offensive_language' is not valid for content
292
+ await report({
293
+ type: 'content',
294
+ id: 123,
295
+ issue: 'offensive_language', // TypeScript error!
296
+ brand: 'drumeo'
297
+ })
298
+
299
+ // ✅ Type-safe: 'offensive_language' is valid for comments
300
+ await report({
301
+ type: 'comment',
302
+ id: 456,
303
+ issue: 'offensive_language', // TypeScript knows this is valid
304
+ brand: 'drumeo'
305
+ })
306
+ ```
307
+
308
+ The `IssueTypeMap` maps each reportable type to its valid issues:
309
+ ```typescript
310
+ type IssueTypeMap = {
311
+ forum_post: ForumIssueType
312
+ comment: CommentIssueType
313
+ content: ContentIssueType
314
+ playlist: PlaylistIssueType
315
+ }
316
+ ```
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @module Reporting
3
+ * @description Service for submitting user reports about content, comments, forum posts, and playlists.
4
+ *
5
+ * This service provides a unified method to report any type of content when users encounter
6
+ * inappropriate behavior, technical issues, or other problems.
7
+ *
8
+ */
9
+
10
+ import { HttpClient } from '../../infrastructure/http/HttpClient'
11
+ import { globalConfig } from '../config.js'
12
+ import {
13
+ ReportResponse,
14
+ ReportableType,
15
+ IssueTypeMap,
16
+ ReportIssueOption,
17
+ } from './types'
18
+ import {Brand} from "../../lib/brands";
19
+
20
+ /**
21
+ * Parameters for submitting a report with type-safe issue values
22
+ */
23
+ export type ReportParams<T extends ReportableType = ReportableType> = {
24
+ /** Type of content being reported */
25
+ type: T
26
+ /** ID of the content being reported */
27
+ id: number
28
+ /** Issue category - type-safe based on reportable type */
29
+ issue: IssueTypeMap[T]
30
+ /** Details about the issue - required when issue is 'other', not sent otherwise */
31
+ details?: string
32
+ /** Brand context (required: drumeo, pianote, guitareo, singeo, playbass) */
33
+ brand: Brand
34
+ }
35
+
36
+ /**
37
+ * Submit a report for any type of content.
38
+ *
39
+ * This is a unified method that handles all report types (content, comment, forum_post, playlist).
40
+ * The issue parameter is type-safe based on the reportable type.
41
+ *
42
+ * @param {ReportParams} params - The report parameters
43
+ * @returns {Promise<ReportResponse>} The report submission response
44
+ * @throws {HttpError} Throws HttpError if the request fails
45
+ *
46
+ * @example
47
+ * // Report content with technical issue - no details needed
48
+ * const response = await report({
49
+ * type: 'content',
50
+ * id: 123,
51
+ * issue: 'video_issue',
52
+ * brand: 'drumeo'
53
+ * })
54
+ *
55
+ * console.log(`Report submitted with ID: ${response.report_id}`)
56
+ *
57
+ * @example
58
+ * // Report with 'other' issue - details required
59
+ * await report({
60
+ * type: 'content',
61
+ * id: 456,
62
+ * issue: 'other',
63
+ * details: 'The instructor audio is out of sync with the video',
64
+ * brand: 'drumeo'
65
+ * })
66
+ *
67
+ * @example
68
+ * // Report forum post
69
+ * await report({
70
+ * type: 'forum_post',
71
+ * id: 789,
72
+ * issue: 'abusive',
73
+ * brand: 'drumeo'
74
+ * })
75
+ */
76
+ export async function report<T extends ReportableType>(params: ReportParams<T>): Promise<ReportResponse> {
77
+ const httpClient = new HttpClient(globalConfig.baseUrl)
78
+
79
+ // Build request body
80
+ const requestBody: any = {
81
+ reportable_type: params.type,
82
+ reportable_id: params.id,
83
+ issue: params.issue,
84
+ brand: params.brand,
85
+ }
86
+
87
+ // Add details only when provided (required for 'other' issue)
88
+ if (params.details) {
89
+ requestBody.details = params.details
90
+ }
91
+
92
+ const response = await httpClient.post<ReportResponse>(
93
+ '/api/user-reports/v1/reports',
94
+ requestBody
95
+ )
96
+
97
+ return response
98
+ }
99
+
100
+ /**
101
+ * Get valid report issue options for a specific reportable type
102
+ *
103
+ * @param {ReportableType} type - The type of content being reported
104
+ * @param {boolean} isMobileApp - Whether this is for mobile app (includes download option)
105
+ * @returns {ReportIssueOption[]} Array of valid issue options with their labels
106
+ *
107
+ * @example
108
+ * // Web options (default)
109
+ * const contentOptions = getReportIssueOptions('content')
110
+ * // Returns: [
111
+ * // { value: 'incorrect_metadata', label: 'The lesson image, title or description is incorrect' },
112
+ * // { value: 'video_issue', label: 'Video issue' },
113
+ * // { value: 'assignment_issue', label: 'An issue with lesson assignment' },
114
+ * // { value: 'other', label: 'Other' }
115
+ * // ]
116
+ *
117
+ * @example
118
+ * // Mobile app options (includes download)
119
+ * const contentOptions = getReportIssueOptions('content', true)
120
+ * // Returns: [
121
+ * // { value: 'incorrect_metadata', label: 'The lesson image, title or description is incorrect' },
122
+ * // { value: 'video_issue', label: 'Video issue' },
123
+ * // { value: 'download_unavailable', label: 'Download is not available' },
124
+ * // { value: 'assignment_issue', label: 'An issue with lesson assignment' },
125
+ * // { value: 'other', label: 'Other' }
126
+ * // ]
127
+ */
128
+ export function getReportIssueOptions(type: ReportableType, isMobileApp: boolean = false): ReportIssueOption[] {
129
+ switch (type) {
130
+ case 'forum_post':
131
+ return [
132
+ { value: 'offensive_language', label: 'It contains offensive language or content' },
133
+ { value: 'abusive', label: "It's abusive or harmful" },
134
+ { value: 'personal_information', label: 'It contains personal information' },
135
+ { value: 'misleading', label: "It's misleading or a false claim" },
136
+ { value: 'other', label: 'Other reasons' },
137
+ ]
138
+
139
+ case 'comment':
140
+ return [
141
+ { value: 'offensive_language', label: 'It contains offensive language or content' },
142
+ { value: 'abusive', label: "It's abusive or harmful" },
143
+ { value: 'personal_information', label: 'It contains personal information' },
144
+ { value: 'misleading', label: "It's misleading or a false claim" },
145
+ { value: 'other', label: 'Other reasons' },
146
+ ]
147
+
148
+ case 'content':
149
+ const contentOptions = [
150
+ { value: 'incorrect_metadata', label: 'The lesson image, title or description is incorrect' },
151
+ { value: 'video_issue', label: 'Video issue' },
152
+ ]
153
+
154
+ // Add download option only for mobile app
155
+ if (isMobileApp) {
156
+ contentOptions.push({ value: 'download_unavailable', label: 'Download is not available' })
157
+ }
158
+
159
+ contentOptions.push(
160
+ { value: 'assignment_issue', label: 'An issue with lesson assignment' },
161
+ { value: 'other', label: 'Other' }
162
+ )
163
+
164
+ return contentOptions
165
+
166
+ case 'playlist':
167
+ const playlistOptions = [
168
+ { value: 'incorrect_metadata', label: 'The lesson image, title or description is incorrect' },
169
+ { value: 'video_issue', label: 'Video issue' },
170
+ ]
171
+
172
+ // Add download option only for mobile app
173
+ if (isMobileApp) {
174
+ playlistOptions.push({ value: 'download_unavailable', label: 'Download is not available' })
175
+ }
176
+
177
+ playlistOptions.push(
178
+ { value: 'assignment_issue', label: 'An issue with lesson assignment' },
179
+ { value: 'other', label: 'Other' }
180
+ )
181
+
182
+ return playlistOptions
183
+
184
+ default:
185
+ return [
186
+ { value: 'other', label: 'Other' },
187
+ ]
188
+ }
189
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @module Reporting Types
3
+ */
4
+
5
+ /**
6
+ * Type of entity being reported
7
+ */
8
+ export type ReportableType = 'content' | 'comment' | 'forum_post' | 'playlist'
9
+
10
+ /**
11
+ * Valid issue types for forum posts
12
+ */
13
+ export type ForumIssueType = 'spam' | 'harassment' | 'inappropriate' | 'other'
14
+
15
+ /**
16
+ * Valid issue types for comments
17
+ */
18
+ export type CommentIssueType = 'offensive_language' | 'abusive' | 'personal_information' | 'misleading' | 'other'
19
+
20
+ /**
21
+ * Valid issue types for content
22
+ */
23
+ export type ContentIssueType = 'incorrect_metadata' | 'video_issue' | 'download_unavailable' | 'assignment_issue' | 'other'
24
+
25
+ /**
26
+ * Valid issue types for playlists
27
+ */
28
+ export type PlaylistIssueType = 'incorrect_metadata' | 'video_issue' | 'download_unavailable' | 'assignment_issue' | 'other'
29
+
30
+ /**
31
+ * Map reportable type to its valid issue types
32
+ */
33
+ export type IssueTypeMap = {
34
+ forum_post: ForumIssueType
35
+ comment: CommentIssueType
36
+ content: ContentIssueType
37
+ playlist: PlaylistIssueType
38
+ }
39
+
40
+ /**
41
+ * Response from submitting a report
42
+ */
43
+ export interface ReportResponse {
44
+ /** The ID of the submitted report */
45
+ report_id: number
46
+ /** Success message */
47
+ message: string
48
+ }
49
+
50
+ /**
51
+ * Report issue option
52
+ */
53
+ export interface ReportIssueOption {
54
+ value: string
55
+ label: string
56
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(rg:*)"
5
- ],
6
- "deny": []
7
- }
8
- }