@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 +8 -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 +21 -19
- 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,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
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,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 "
|
|
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
|
+
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 ?
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
190
|
-
|
|
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
|
|
204
|
+
validity,
|
|
198
205
|
/* publisherId:
|
|
199
206
|
!this.onlyValid && !authStore.isRoleProduction
|
|
200
207
|
? authStore.authProfile?.userId
|
|
201
208
|
: undefined, */
|
|
202
|
-
|
|
209
|
+
processingStatus: [PodcastProcessingStatus.Ready, PodcastProcessingStatus.Processing],
|
|
203
210
|
withVideo: props.withVideo,
|
|
204
|
-
|
|
205
|
-
|
|
211
|
+
tags: props.includeTag.length ? props.includeTag : undefined,
|
|
212
|
+
beneficiaries: props.beneficiaries ?? undefined
|
|
206
213
|
};
|
|
207
214
|
try {
|
|
208
|
-
const data = await
|
|
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";
|
|
@@ -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 */
|