@saooti/octopus-sdk 41.1.6 → 41.1.7

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,12 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 41.1.7 (10/12/2025)
4
+
5
+ **Misc**
6
+
7
+ - Ajout API podcast
8
+ - Utilisation search V2 pour les podcasts
9
+
3
10
  ## 41.1.6 (10/12/2025)
4
11
 
5
12
  **Fixes**
@@ -12,6 +19,7 @@
12
19
  **Misc**
13
20
 
14
21
  - Ajout API playlist, emission, et organisation
22
+ - Utilisation content V2 pour la récupération du contenu des playlist
15
23
 
16
24
  ## 41.1.4 (04/12/2025)
17
25
 
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.7",
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,12 +60,13 @@ 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
+ import { podcastApi, PodcastMonetisation, PodcastSearchOptions, PodcastSort } from "../../../api/podcastApi";
69
70
 
70
71
 
71
72
  //Props
@@ -77,7 +78,7 @@ const props = defineProps({
77
78
  iabId: { default: undefined, type: Number },
78
79
  participantId: { default: undefined, type: Number },
79
80
  query: { default: undefined, type: String },
80
- monetisable: { default: undefined, type: String },
81
+ monetisable: { default: undefined, type: String as () => PodcastMonetisation },
81
82
  popularSort: { default: false, type: Boolean },
82
83
  reload: { default: false, type: Boolean },
83
84
  before: { default: undefined, type: String },
@@ -85,7 +86,7 @@ const props = defineProps({
85
86
  includeHidden: { default: false, type: Boolean },
86
87
  showCount: { default: false, type: Boolean },
87
88
  displaySortText: { default: true, type: Boolean },
88
- sortCriteria: { default: undefined, type: String },
89
+ sortCriteria: { default: undefined, type: String as () => PodcastSort },
89
90
  validity: { default: 'true', type: String },
90
91
  rubriqueId: { default: () => [], type: Array as () => Array<number> },
91
92
  rubriquageId: { default: () => [], type: Array as () => Array<number> },
@@ -137,7 +138,7 @@ const organisation = computed(() => {
137
138
  }
138
139
  return filterStore.filterOrgaId ? [filterStore.filterOrgaId] : [];
139
140
  });
140
- const sort = computed(() => props.popularSort ? "POPULARITY" : (props.sortCriteria ?? "DATE"));
141
+ const sort = computed(() => props.popularSort ? PodcastSort.POPULARITY : (props.sortCriteria ?? PodcastSort.DATE));
141
142
  const sortText = computed(() => {
142
143
  if (!props.displaySortText) {
143
144
  return "";
@@ -176,9 +177,15 @@ onBeforeMount(()=>fetchContent(false))
176
177
  //Methods
177
178
  async function fetchContent(reset: boolean): Promise<void> {
178
179
  loading.value = true;
179
- const param: FetchParam = {
180
+
181
+ let validity: undefined|boolean = undefined;
182
+ if (props.validity !== undefined) {
183
+ validity = props.validity !== 'true';
184
+ }
185
+
186
+ const param: PodcastSearchOptions = {
180
187
  first: reset ? 0 : dfirst.value,
181
- size: dsize.value,
188
+ pageSize: dsize.value,
182
189
  organisationId: organisation.value,
183
190
  emissionId: props.emissionId,
184
191
  iabId: props.iabId,
@@ -186,31 +193,26 @@ async function fetchContent(reset: boolean): Promise<void> {
186
193
  query: props.query,
187
194
  monetisable: props.monetisable,
188
195
  sort: sort.value,
189
- before: props.before,
190
- after: props.after,
196
+ pubDateBefore: props.before,
197
+ pubDateAfter: props.after,
191
198
  noRubriquageId: props.noRubriquageId.length
192
199
  ? props.noRubriquageId
193
200
  : undefined,
194
201
  rubriqueId: props.rubriqueId.length ? props.rubriqueId : undefined,
195
202
  rubriquageId: props.rubriquageId.length ? props.rubriquageId : undefined,
196
203
  includeHidden: props.includeHidden,
197
- validity: props.validity,
204
+ validity,
198
205
  /* publisherId:
199
206
  !this.onlyValid && !authStore.isRoleProduction
200
207
  ? authStore.authProfile?.userId
201
208
  : undefined, */
202
- includeStatus: ["READY", "PROCESSING"],
209
+ processingStatus: [PodcastProcessingStatus.Ready, PodcastProcessingStatus.Processing],
203
210
  withVideo: props.withVideo,
204
- includeTag: props.includeTag.length ? props.includeTag : undefined,
205
- beneficiary: props.beneficiaries ?? undefined
211
+ tags: props.includeTag.length ? props.includeTag : undefined,
212
+ beneficiaries: props.beneficiaries ?? undefined
206
213
  };
207
214
  try {
208
- const data = await classicApi.fetchData<ListClassicReturn<Podcast>>({
209
- api: 0,
210
- path: "podcast/search",
211
- parameters: param,
212
- specialTreatement: true,
213
- });
215
+ const data = await podcastApi.searchFull(param, true);
214
216
  afterFetching(reset, data);
215
217
  } catch (error) {
216
218
  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 */