@saooti/octopus-sdk 41.1.6 → 41.1.8

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
@@ -1,5 +1,18 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 41.1.8 (10/12/2025)
4
+
5
+ **Fixes**
6
+
7
+ - Correction recherche dans `PodcastList`
8
+
9
+ ## 41.1.7 (10/12/2025)
10
+
11
+ **Misc**
12
+
13
+ - Ajout API podcast
14
+ - Utilisation search V2 pour les podcasts
15
+
3
16
  ## 41.1.6 (10/12/2025)
4
17
 
5
18
  **Fixes**
@@ -12,6 +25,7 @@
12
25
  **Misc**
13
26
 
14
27
  - Ajout API playlist, emission, et organisation
28
+ - Utilisation content V2 pour la récupération du contenu des playlist
15
29
 
16
30
  ## 41.1.4 (04/12/2025)
17
31
 
package/index.ts CHANGED
@@ -140,6 +140,7 @@ import classicApi from "./src/api/classicApi.ts";
140
140
  export { emissionApi } from "./src/api/emissionApi.ts";
141
141
  export { organisationApi } from "./src/api/organisationApi.ts";
142
142
  export { playlistApi } from "./src/api/playlistApi.ts";
143
+ export { podcastApi, PodcastSort, type PodcastSearchOptions } from "./src/api/podcastApi.ts";
143
144
 
144
145
  //Icons
145
146
  export const getAmazonMusicIcon = () => import("./src/components/icons/AmazonMusicIcon.vue");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saooti/octopus-sdk",
3
- "version": "41.1.6",
3
+ "version": "41.1.8",
4
4
  "private": false,
5
5
  "description": "Javascript SDK for using octopus",
6
6
  "author": "Saooti",
@@ -4,6 +4,7 @@ import { Podcast, SimplifiedPodcast } from "../stores/class/general/podcast";
4
4
  import { Playlist } from "../stores/class/general/playlist";
5
5
  import { organisationApi } from "./organisationApi";
6
6
  import { emissionApi } from "./emissionApi";
7
+ import { unique } from '../helper/arrayHelper';
7
8
 
8
9
  /**
9
10
  * Retrieve playlist data
@@ -29,10 +30,6 @@ async function getContent(playlistId: number): Promise<Array<SimplifiedPodcast>>
29
30
  });
30
31
  }
31
32
 
32
- function unique<T>(value: T, index: number, array: Array<T>): boolean {
33
- return array.indexOf(value) === index;
34
- }
35
-
36
33
  /**
37
34
  * Retrieve the podcasts defined in the playlist, with all their data
38
35
  * This query is longer, because it also needs to retrieve organisations &
@@ -0,0 +1,174 @@
1
+ import { Podcast, PodcastProcessingStatus, SimplifiedPodcast } from '../stores/class/general/podcast';
2
+ import { ListClassicReturn } from '../stores/class/general/listReturn';
3
+ import { useAuthStore } from '../stores/AuthStore';
4
+ import classicApi from './classicApi';
5
+ import { ModuleApi } from './apiConnection';
6
+ import { unique } from '../helper/arrayHelper';
7
+ import { organisationApi } from './organisationApi';
8
+ import { emissionApi } from './emissionApi';
9
+
10
+ export enum PodcastSort {
11
+ DATE = 'DATE',
12
+ DATE_ASC = 'DATE_ASC',
13
+ NAME = 'NAME',
14
+ LAST_PODCAST_DESC = 'LAST_PODCAST_DESC',
15
+ POPULARITY = 'POPULARITY',
16
+ SCORE = 'SCORE',
17
+ UPDATE_ASC = 'UPDATE_ASC',
18
+ UPDATE_DESC = 'UPDATE_DESC'
19
+ }
20
+
21
+ export enum PodcastMonetisation {
22
+ YES = "YES",
23
+ NO = "NO",
24
+ UNDEFINED = "UNDEFINED"
25
+ }
26
+
27
+ interface Paginable<S> {
28
+ /** The start of pagination */
29
+ first?: number;
30
+ /** The number of elements to retrieve */
31
+ pageSize?: number;
32
+ /** Sorting */
33
+ sort?: S;
34
+ }
35
+
36
+ /**
37
+ * The options available to search for podcasts.
38
+ *
39
+ * ** /!\ This list is not exhaustive **
40
+ */
41
+ export interface PodcastSearchOptions extends Paginable<PodcastSort> {
42
+ /** Filter by emission ID */
43
+ emissionId?: number|number[];
44
+ /** Filter by organisation ID */
45
+ organisationId?: string[];
46
+ /** Filter by title containing */
47
+ query?: string;
48
+ /** Filter by IAB category */
49
+ iabId?: number;
50
+ /** Filter by participant */
51
+ participantId?: number;
52
+ /** Fitler by monetisation */
53
+ monetisable?: PodcastMonetisation;
54
+ /** Filter by pub date before */
55
+ pubDateBefore?: string;
56
+ /** Filter by pub date after */
57
+ pubDateAfter?: string;
58
+ /** Filter by rubriquage exclusion ? */
59
+ noRubriquageId?: Array<number>;
60
+ /** Filter by rubrique */
61
+ rubriqueId?: Array<number>;
62
+ /** Filter by rubriquage */
63
+ rubriquageId?: Array<number>;
64
+ /** Also show hidden podcasts */
65
+ includeHidden?: boolean;
66
+ /** Filter by validity */
67
+ validity?: boolean;
68
+ /** Filter by status */
69
+ processingStatus?: Array<PodcastProcessingStatus>;
70
+ /** Filter by podcast having a video */
71
+ withVideo?: boolean;
72
+ /** Filter by tags */
73
+ tags: Array<string>;
74
+ /** Filter by beneficiaries/rights holder reference */
75
+ beneficiaries?: Array<string>;
76
+ }
77
+
78
+ async function downloadRegister(podcastId: number, parameters?: Record<string,unknown>): Promise<{ location: string; downloadId: number }> {
79
+ const authStore = useAuthStore();
80
+
81
+ return classicApi.fetchData<{
82
+ location: string;
83
+ downloadId: number;
84
+ }>({
85
+ api: ModuleApi.DEFAULT,
86
+ path:"podcast/download/register/" + podcastId + ".mp3",
87
+ parameters: {
88
+ access_token: authStore.authParam.accessToken,
89
+ ...parameters
90
+ },
91
+ headers: {'X-Extra-UA':'Saooti Player'},
92
+ isNotAuth:true
93
+ });
94
+ }
95
+
96
+ /**
97
+ * Get a podcast by its ID
98
+ */
99
+ function get(podcastId: number): Promise<Podcast> {
100
+ return classicApi.fetchData<Podcast>({
101
+ api: ModuleApi.DEFAULT,
102
+ path: 'podcast/' + podcastId
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Search for podcasts. Retrieved podcasts are 'incomplete', some of their
108
+ * properties are only IDs.
109
+ * Use `searchFull` to get full podcasts, but more queries will be made
110
+ * @param options The search criterias
111
+ * @param adaptParameters If true, some adjustments will be made to the parameters
112
+ * @return A list of simplified podcasts
113
+ */
114
+ function search(options: PodcastSearchOptions, adaptParameters?: boolean): Promise<ListClassicReturn<SimplifiedPodcast>> {
115
+ return classicApi.fetchData<ListClassicReturn<SimplifiedPodcast>>({
116
+ api: ModuleApi.DEFAULT,
117
+ path: 'v2/podcast/search',
118
+ parameters: {
119
+ ...options,
120
+ beneficiary: options.beneficiaries,
121
+ includeStatus: options.processingStatus,
122
+ includeTags: options.tags,
123
+ before: options.pubDateBefore,
124
+ after: options.pubDateAfter,
125
+ size: options.pageSize ?? 50
126
+ },
127
+ specialTreatement: adaptParameters
128
+ });
129
+ }
130
+
131
+ /**
132
+ * Retrieve the podcasts matching the search criterias, with all their data.
133
+ * This query is longer, because it also needs to retrieve organisations &
134
+ * emissions.
135
+ * @param options The search criterias
136
+ * @param adaptParameters If true, some adjustments will be made to the parameters
137
+ * @return A list of podcasts
138
+ */
139
+ async function searchFull(options:PodcastSearchOptions, adaptParameters?: boolean): Promise<ListClassicReturn<Podcast>> {
140
+ const podcasts = await search(options, adaptParameters);
141
+ const full: ListClassicReturn<Podcast> = {
142
+ count: podcasts.count,
143
+ sort:podcasts.sort,
144
+ result: []
145
+ };
146
+
147
+ const organisationIds = podcasts.result.map((p: SimplifiedPodcast) => p.organisationId)
148
+ .filter(unique);
149
+ const emissionIds = podcasts.result.map((p: SimplifiedPodcast) => p.emissionId)
150
+ .filter(unique);
151
+
152
+ const organisations = await organisationApi.getAllById(organisationIds);
153
+ const emissions = await emissionApi.getAllById(emissionIds);
154
+
155
+ podcasts.result.forEach((s: SimplifiedPodcast) => {
156
+ const organisation = organisations[s.organisationId];
157
+ const emission = emissions[s.emissionId];
158
+
159
+ full.result.push({
160
+ ...s,
161
+ organisation,
162
+ emission
163
+ });
164
+ });
165
+
166
+ return full;
167
+ }
168
+
169
+ export const podcastApi = {
170
+ downloadRegister,
171
+ get,
172
+ search,
173
+ searchFull
174
+ }
@@ -60,43 +60,54 @@ import classicApi from "../../../api/classicApi";
60
60
  import PodcastItem from "./PodcastItem.vue";
61
61
  import ClassicLazy from "../../misc/ClassicLazy.vue";
62
62
  import { useFilterStore } from "../../../stores/FilterStore";
63
- import { Podcast, emptyPodcastData } from "@/stores/class/general/podcast";
63
+ import { Podcast, PodcastProcessingStatus, emptyPodcastData } from "../../../stores/class/general/podcast";
64
64
  import { computed, onBeforeMount, Ref, ref, watch } from "vue";
65
65
  import { FetchParam } from "@/stores/class/general/fetchParam";
66
66
  import { AxiosError } from "axios";
67
- import { ListClassicReturn } from "@/stores/class/general/listReturn";
67
+ import { ListClassicReturn } from "../../../stores/class/general/listReturn";
68
68
  import { useI18n } from "vue-i18n";
69
-
69
+ import { podcastApi, PodcastMonetisation, PodcastSearchOptions, PodcastSort } from "../../../api/podcastApi";
70
70
 
71
71
  //Props
72
- const props = defineProps({
73
- first: { default: 0, type: Number },
74
- size: { default: 30, type: Number },
75
- organisationId: { default: () => [], type: Array as () => Array<string> },
76
- emissionId: { default: undefined, type: Number },
77
- iabId: { default: undefined, type: Number },
78
- participantId: { default: undefined, type: Number },
79
- query: { default: undefined, type: String },
80
- monetisable: { default: undefined, type: String },
81
- popularSort: { default: false, type: Boolean },
82
- reload: { default: false, type: Boolean },
83
- before: { default: undefined, type: String },
84
- after: { default: undefined, type: String },
85
- includeHidden: { default: false, type: Boolean },
86
- showCount: { default: false, type: Boolean },
87
- displaySortText: { default: true, type: Boolean },
88
- sortCriteria: { default: undefined, type: String },
89
- validity: { default: 'true', type: String },
90
- rubriqueId: { default: () => [], type: Array as () => Array<number> },
91
- rubriquageId: { default: () => [], type: Array as () => Array<number> },
92
- noRubriquageId: { default: () => [], type: Array as () => Array<number> },
93
- justSizeChosen: { default: false, type: Boolean },
94
- withVideo: { default: undefined, type: Boolean },
95
- includeTag:{ default: () => [], type: Array as () => Array<string> },
96
- forceUpdateParameters: { default: false, type: Boolean },
72
+ const props = withDefaults(defineProps<{
73
+ first?: number;
74
+ size?: number;
75
+ organisationId?: Array<string>;
76
+ emissionId?: number;
77
+ iabId?: number;
78
+ participantId?: number;
79
+ query?: string;
80
+ monetisable?: PodcastMonetisation;
81
+ popularSort?: boolean;
82
+ reload?: boolean;
83
+ before?: string;
84
+ after?: string;
85
+ includeHidden?: boolean;
86
+ showCount?: boolean;
87
+ displaySortText?: boolean;
88
+ sortCriteria?: PodcastSort;
89
+ validity?: 'true'|'false'|boolean;
90
+ rubriqueId?: Array<number>;
91
+ rubriquageId?: Array<number>;
92
+ noRubriquageId?: Array<number>;
93
+ justSizeChosen?: boolean;
94
+ withVideo?: boolean;
95
+ includeTag?: Array<string>;
96
+ forceUpdateParameters?: boolean;
97
97
  /** The beneficiaries to filter on */
98
- beneficiaries: { default: null, type: Array as () => Array<string> }
99
- })
98
+ beneficiaries?: Array<string>;
99
+ }>(), {
100
+ first: 0,
101
+ size: 30,
102
+ popularSort: false,
103
+ reload: false,
104
+ includeHidden: false,
105
+ showCount: false,
106
+ displaySortText: true,
107
+ validity: true,
108
+ justSizeChosen: false,
109
+ forceUpdateParameters: false
110
+ });
100
111
 
101
112
  //Emits
102
113
  const emit = defineEmits(["fetch", "emptyList"]);
@@ -137,7 +148,7 @@ const organisation = computed(() => {
137
148
  }
138
149
  return filterStore.filterOrgaId ? [filterStore.filterOrgaId] : [];
139
150
  });
140
- const sort = computed(() => props.popularSort ? "POPULARITY" : (props.sortCriteria ?? "DATE"));
151
+ const sort = computed(() => props.popularSort ? PodcastSort.POPULARITY : (props.sortCriteria ?? PodcastSort.DATE));
141
152
  const sortText = computed(() => {
142
153
  if (!props.displaySortText) {
143
154
  return "";
@@ -176,9 +187,15 @@ onBeforeMount(()=>fetchContent(false))
176
187
  //Methods
177
188
  async function fetchContent(reset: boolean): Promise<void> {
178
189
  loading.value = true;
179
- const param: FetchParam = {
190
+
191
+ let validity: undefined|boolean = undefined;
192
+ if (props.validity !== undefined) {
193
+ validity = props.validity === 'true' || props.validity === true;
194
+ }
195
+
196
+ const param: PodcastSearchOptions = {
180
197
  first: reset ? 0 : dfirst.value,
181
- size: dsize.value,
198
+ pageSize: dsize.value,
182
199
  organisationId: organisation.value,
183
200
  emissionId: props.emissionId,
184
201
  iabId: props.iabId,
@@ -186,31 +203,26 @@ async function fetchContent(reset: boolean): Promise<void> {
186
203
  query: props.query,
187
204
  monetisable: props.monetisable,
188
205
  sort: sort.value,
189
- before: props.before,
190
- after: props.after,
191
- noRubriquageId: props.noRubriquageId.length
206
+ pubDateBefore: props.before,
207
+ pubDateAfter: props.after,
208
+ noRubriquageId: props.noRubriquageId?.length
192
209
  ? props.noRubriquageId
193
210
  : undefined,
194
- rubriqueId: props.rubriqueId.length ? props.rubriqueId : undefined,
195
- rubriquageId: props.rubriquageId.length ? props.rubriquageId : undefined,
211
+ rubriqueId: props.rubriqueId?.length ? props.rubriqueId : undefined,
212
+ rubriquageId: props.rubriquageId?.length ? props.rubriquageId : undefined,
196
213
  includeHidden: props.includeHidden,
197
- validity: props.validity,
214
+ validity,
198
215
  /* publisherId:
199
216
  !this.onlyValid && !authStore.isRoleProduction
200
217
  ? authStore.authProfile?.userId
201
218
  : undefined, */
202
- includeStatus: ["READY", "PROCESSING"],
219
+ processingStatus: [PodcastProcessingStatus.Ready, PodcastProcessingStatus.Processing],
203
220
  withVideo: props.withVideo,
204
- includeTag: props.includeTag.length ? props.includeTag : undefined,
205
- beneficiary: props.beneficiaries ?? undefined
221
+ tags: props.includeTag?.length ? props.includeTag : undefined,
222
+ beneficiaries: props.beneficiaries ?? undefined
206
223
  };
207
224
  try {
208
- const data = await classicApi.fetchData<ListClassicReturn<Podcast>>({
209
- api: 0,
210
- path: "podcast/search",
211
- parameters: param,
212
- specialTreatement: true,
213
- });
225
+ const data = await podcastApi.searchFull(param, true);
214
226
  afterFetching(reset, data);
215
227
  } catch (error) {
216
228
  handle403(error as AxiosError);
@@ -91,7 +91,7 @@ import CancelIcon from "vue-material-design-icons/Cancel.vue";
91
91
  import AlertIcon from "vue-material-design-icons/Alert.vue";
92
92
  import DurationHelper from "../../../helper/durationHelper";
93
93
  import { state } from "../../../stores/ParamSdkStore";
94
- import { Podcast, ProcessingStatus } from "../../../stores/class/general/podcast";
94
+ import { Podcast, PodcastProcessingStatus as ProcessingStatus } from "../../../stores/class/general/podcast";
95
95
  import { Conference } from "@/stores/class/conference/conference";
96
96
  import { usePlayerStore } from "../../../stores/PlayerStore";
97
97
  import { computed, defineAsyncComponent, ref } from "vue";
@@ -0,0 +1,3 @@
1
+ export function unique<T>(value: T, index: number, array: Array<T>): boolean {
2
+ return array.indexOf(value) === index;
3
+ }
@@ -7,7 +7,7 @@ import { Video } from "./video";
7
7
  /**
8
8
  * State of processing of the audio file
9
9
  */
10
- export enum ProcessingStatus {
10
+ export enum PodcastProcessingStatus {
11
11
  Planned = "PLANNED",
12
12
  Processing = "PROCESSING",
13
13
  Ready = "READY",
@@ -27,7 +27,7 @@ export interface PodcastAvailability {
27
27
  /**
28
28
  * Data about a podcast/episode
29
29
  */
30
- export interface Podcast extends BasePodcast {
30
+ export interface Podcast {
31
31
  /** ID of the podcast */
32
32
  podcastId: number;
33
33
  /** Emission the podcast belongs to */
@@ -49,7 +49,7 @@ export interface Podcast extends BasePodcast {
49
49
  /** Publishing date */
50
50
  pubDate?: string;
51
51
  /** The status of the processing of the audio file */
52
- processingStatus?: ProcessingStatus;
52
+ processingStatus?: PodcastProcessingStatus;
53
53
  /** An optional list of tags */
54
54
  tags?: Array<string>;
55
55
  /** An optional list of tags for OuestFrance */