@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 +14 -0
- package/index.ts +1 -0
- package/package.json +1 -1
- package/src/api/playlistApi.ts +1 -4
- package/src/api/podcastApi.ts +174 -0
- package/src/components/display/podcasts/PodcastList.vue +60 -48
- package/src/components/display/podcasts/PodcastPlayButton.vue +1 -1
- package/src/helper/arrayHelper.ts +3 -0
- package/src/stores/class/general/podcast.ts +3 -3
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
package/src/api/playlistApi.ts
CHANGED
|
@@ -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 "
|
|
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 "
|
|
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
|
|
74
|
-
size
|
|
75
|
-
organisationId
|
|
76
|
-
emissionId
|
|
77
|
-
iabId
|
|
78
|
-
participantId
|
|
79
|
-
query
|
|
80
|
-
monetisable
|
|
81
|
-
popularSort
|
|
82
|
-
reload
|
|
83
|
-
before
|
|
84
|
-
after
|
|
85
|
-
includeHidden
|
|
86
|
-
showCount
|
|
87
|
-
displaySortText
|
|
88
|
-
sortCriteria
|
|
89
|
-
validity
|
|
90
|
-
rubriqueId
|
|
91
|
-
rubriquageId
|
|
92
|
-
noRubriquageId
|
|
93
|
-
justSizeChosen
|
|
94
|
-
withVideo
|
|
95
|
-
includeTag
|
|
96
|
-
forceUpdateParameters
|
|
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
|
|
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 ?
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
noRubriquageId: props.noRubriquageId
|
|
206
|
+
pubDateBefore: props.before,
|
|
207
|
+
pubDateAfter: props.after,
|
|
208
|
+
noRubriquageId: props.noRubriquageId?.length
|
|
192
209
|
? props.noRubriquageId
|
|
193
210
|
: undefined,
|
|
194
|
-
rubriqueId: props.rubriqueId
|
|
195
|
-
rubriquageId: props.rubriquageId
|
|
211
|
+
rubriqueId: props.rubriqueId?.length ? props.rubriqueId : undefined,
|
|
212
|
+
rubriquageId: props.rubriquageId?.length ? props.rubriquageId : undefined,
|
|
196
213
|
includeHidden: props.includeHidden,
|
|
197
|
-
validity
|
|
214
|
+
validity,
|
|
198
215
|
/* publisherId:
|
|
199
216
|
!this.onlyValid && !authStore.isRoleProduction
|
|
200
217
|
? authStore.authProfile?.userId
|
|
201
218
|
: undefined, */
|
|
202
|
-
|
|
219
|
+
processingStatus: [PodcastProcessingStatus.Ready, PodcastProcessingStatus.Processing],
|
|
203
220
|
withVideo: props.withVideo,
|
|
204
|
-
|
|
205
|
-
|
|
221
|
+
tags: props.includeTag?.length ? props.includeTag : undefined,
|
|
222
|
+
beneficiaries: props.beneficiaries ?? undefined
|
|
206
223
|
};
|
|
207
224
|
try {
|
|
208
|
-
const data = await
|
|
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";
|
|
@@ -7,7 +7,7 @@ import { Video } from "./video";
|
|
|
7
7
|
/**
|
|
8
8
|
* State of processing of the audio file
|
|
9
9
|
*/
|
|
10
|
-
export enum
|
|
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
|
|
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?:
|
|
52
|
+
processingStatus?: PodcastProcessingStatus;
|
|
53
53
|
/** An optional list of tags */
|
|
54
54
|
tags?: Array<string>;
|
|
55
55
|
/** An optional list of tags for OuestFrance */
|