Skip to content

Commit e230651

Browse files
committed
ARTE: handle Collections in CategoryFilmList
2 parents 6fafc76 + ee0a47f commit e230651

File tree

5 files changed

+116
-35
lines changed

5 files changed

+116
-35
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ sourceCompatibility = 1.8
1717
targetCompatibility = 1.8
1818
group = 'de.mediathekview'
1919
archivesBaseName = "MServer"
20-
version = '3.1.196'
20+
version = '3.1.197'
2121

2222
def jarName = 'MServer.jar'
2323
def mainClass = 'mServer.Main'

src/main/java/mServer/crawler/sender/arte/ArteCategoryFilmListDeserializer.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import com.google.gson.JsonElement;
66
import com.google.gson.JsonObject;
77
import com.google.gson.JsonParseException;
8+
import de.mediathekview.mlib.tool.Log;
9+
810
import java.lang.reflect.Type;
911

1012
/**
@@ -25,7 +27,17 @@ public ArteCategoryFilmsDTO deserialize(JsonElement aJsonElement, Type aType, Js
2527
for (JsonElement jsonElement : aJsonElement.getAsJsonObject().get(JSON_ELEMENT_DATA).getAsJsonArray()) {
2628
String programId = jsonElement.getAsJsonObject().get(JSON_ELEMENT_PROGRAMID).getAsString();
2729
if (programId != null) {
28-
dto.addProgramId(programId);
30+
if (programId.startsWith("RC-")) {
31+
// add 1 to collection id to get list of episodes
32+
try {
33+
long collectionId = Long.parseLong(programId.replace("RC-", "")) + 1;
34+
dto.addCollection(String.format("RC-%06d", collectionId));
35+
} catch (NumberFormatException e) {
36+
Log.errorLog(12834939, "Invalid collection id: " + programId);
37+
}
38+
} else {
39+
dto.addProgramId(programId);
40+
}
2941
}
3042
}
3143

src/main/java/mServer/crawler/sender/arte/ArteCategoryFilmsDTO.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,23 @@
55
public class ArteCategoryFilmsDTO {
66

77
private final ArrayList<String> programIds = new ArrayList<>();
8+
private final ArrayList<String> collectionIds = new ArrayList<>();
9+
810
private boolean hasNextPage;
911

1012
public void addProgramId(String aProgramId) {
1113
programIds.add(aProgramId);
1214
}
15+
public void addCollection(String aCollectionId) {
16+
collectionIds.add(aCollectionId);
17+
}
1318

1419
public ArrayList<String> getProgramIds() {
1520
return programIds;
1621
}
22+
public ArrayList<String> getCollectionIds() {
23+
return collectionIds;
24+
}
1725

1826
public boolean hasNextPage() {
1927
return hasNextPage;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package mServer.crawler.sender.arte;
2+
3+
import com.google.gson.*;
4+
import mServer.crawler.sender.base.JsonUtils;
5+
6+
import java.lang.reflect.Type;
7+
8+
public class ArteCollectionDeserializer implements JsonDeserializer<ArteCategoryFilmsDTO> {
9+
private static final String ATTRIBUTE_PROGRAM_ID = "programId";
10+
private static final String ELEMENT_PROGRAMS = "programs";
11+
private static final String ELEMENT_VIDEOS = "videos";
12+
13+
public ArteCategoryFilmsDTO deserialize(
14+
final JsonElement aJsonElement,
15+
final Type aType,
16+
final JsonDeserializationContext aJsonDeserializationContext)
17+
throws JsonParseException {
18+
final ArteCategoryFilmsDTO result = new ArteCategoryFilmsDTO();
19+
if (aJsonElement.isJsonObject()) {
20+
final JsonObject mainObj = aJsonElement.getAsJsonObject();
21+
22+
if (JsonUtils.checkTreePath(mainObj, ELEMENT_PROGRAMS)) {
23+
final JsonArray programs = mainObj.get(ELEMENT_PROGRAMS).getAsJsonArray();
24+
programs.forEach(
25+
program -> {
26+
final JsonObject programObject = program.getAsJsonObject();
27+
if (JsonUtils.checkTreePath(programObject, ELEMENT_VIDEOS)) {
28+
programObject
29+
.get(ELEMENT_VIDEOS)
30+
.getAsJsonArray()
31+
.forEach(
32+
filmElement ->
33+
JsonUtils.getAttributeAsString(filmElement.getAsJsonObject(), ATTRIBUTE_PROGRAM_ID)
34+
.ifPresent(result::addProgramId));
35+
}
36+
});
37+
}
38+
}
39+
return result;
40+
}
41+
42+
}

src/main/java/mServer/crawler/sender/arte/MediathekArte.java

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,40 @@
77
import de.mediathekview.mlib.daten.DatenFilm;
88
import de.mediathekview.mlib.daten.ListeFilme;
99
import de.mediathekview.mlib.tool.Log;
10-
import java.time.LocalDate;
11-
import java.time.format.DateTimeFormatter;
12-
import java.util.ArrayList;
13-
import java.util.Collection;
14-
import java.util.HashMap;
15-
import java.util.List;
16-
import java.util.Map;
17-
import java.util.Objects;
18-
import java.util.Set;
19-
import java.util.stream.Collectors;
20-
2110
import mServer.crawler.CrawlerTool;
2211
import mServer.crawler.FilmeSuchen;
2312
import mServer.crawler.sender.MediathekReader;
2413
import org.apache.logging.log4j.LogManager;
2514
import org.apache.logging.log4j.Logger;
2615

16+
import java.time.LocalDate;
17+
import java.time.format.DateTimeFormatter;
18+
import java.util.*;
19+
import java.util.stream.Collectors;
20+
2721
public class MediathekArte extends MediathekReader {
2822

2923
/*
30-
* Informationen zu den ARTE-URLs:
31-
* {} sind nur Makierungen, dass es Platzhalter sind, sie gehören nicht zur URL.
32-
*
33-
* Allgemeine URL eines Films: (050169-002-A = ID des Films); (die-spur-der-steine = Titel)
34-
* http://www.arte.tv/de/videos/{050169-002-A}/{die-spur-der-steine}
35-
*
36-
* Alle Sendungen: (Deutsch = DE; Französisch = FR)
37-
* https://api.arte.tv/api/opa/v3/videos?channel={DE}
38-
*
39-
* Informationen zum Film: (050169-002-A = ID des Films); (de für deutsch / fr für französisch)
40-
* https://api.arte.tv/api/player/v1/config/{de}/{050169-002-A}?platform=ARTE_NEXT
41-
*
42-
* Zweite Quelle für Informationen zum Film: (050169-002-A = ID des Films); (de für deutsch / fr für französisch)
43-
* https://api.arte.tv/api/opa/v3/programs/{de}/{050169-002-A}
44-
*
45-
* Hintergrundinfos zum Laden der Filme nach Kategorien im langen Lauf:
46-
* 1. statische Informationen über verfügbare Kategorien laden: URL_STATIC_CONTENT
47-
* 2. für jede Kategorie die Unterkategorien ermitteln: URL_CATEGORY
48-
* 3. für jede Unterkategorie die enthaltenen ProgramId ermitteln: URL_SUBCATEGORY
49-
* 4. für alle ProgramIds die Videoinformationen laden (wie kurze Variante)
24+
* Informationen zu den ARTE-URLs:
25+
* {} sind nur Makierungen, dass es Platzhalter sind, sie gehören nicht zur URL.
26+
*
27+
* Allgemeine URL eines Films: (050169-002-A = ID des Films); (die-spur-der-steine = Titel)
28+
* http://www.arte.tv/de/videos/{050169-002-A}/{die-spur-der-steine}
29+
*
30+
* Alle Sendungen: (Deutsch = DE; Französisch = FR)
31+
* https://api.arte.tv/api/opa/v3/videos?channel={DE}
32+
*
33+
* Informationen zum Film: (050169-002-A = ID des Films); (de für deutsch / fr für französisch)
34+
* https://api.arte.tv/api/player/v1/config/{de}/{050169-002-A}?platform=ARTE_NEXT
35+
*
36+
* Zweite Quelle für Informationen zum Film: (050169-002-A = ID des Films); (de für deutsch / fr für französisch)
37+
* https://api.arte.tv/api/opa/v3/programs/{de}/{050169-002-A}
38+
*
39+
* Hintergrundinfos zum Laden der Filme nach Kategorien im langen Lauf:
40+
* 1. statische Informationen über verfügbare Kategorien laden: URL_STATIC_CONTENT
41+
* 2. für jede Kategorie die Unterkategorien ermitteln: URL_CATEGORY
42+
* 3. für jede Unterkategorie die enthaltenen ProgramId ermitteln: URL_SUBCATEGORY
43+
* 4. für alle ProgramIds die Videoinformationen laden (wie kurze Variante)
5044
*/
5145
private static final Logger LOG = LogManager.getLogger(MediathekArte.class);
5246
private static final String ARTE_API_TAG_URL_PATTERN = "https://api.arte.tv/api/opa/v3/videos?channel=%s&arteSchedulingDay=%s";
@@ -66,6 +60,8 @@ public class MediathekArte extends MediathekReader {
6660
"CIV", "LGP", "XXE"
6761
};
6862

63+
private static final String COLLECTION_URL = "https://api.arte.tv/api/opa/v3/programs/%s/%s";
64+
6965
private static final DateTimeFormatter ARTE_API_DATEFORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
7066
private static final boolean PARSE_SUBCATEGORY_SUB_PAGES = false; // Flag, ob Unterseiten der Unterkategorien verarbeitet werden soll
7167

@@ -152,7 +148,7 @@ private void addCategories() {
152148
senderLanguages.forEach((sender, langCode) -> {
153149
for (String subCategory : SUBCATEGORIES) {
154150
String subCategoryUrl = String.format(URL_SUBCATEGORY, langCode.toLowerCase(), subCategory, 1);
155-
listeThemen.add(new String[]{sender, langCode, subCategory, subCategoryUrl});
151+
listeThemen.add(new String[]{sender, langCode, subCategory, subCategoryUrl});
156152
}
157153
});
158154
}
@@ -209,6 +205,7 @@ private void addFilmeForTag(String sender, String aUrl) {
209205
*/
210206
class CategoryLoader extends Thread {
211207

208+
212209
@Override
213210
public void run() {
214211
try {
@@ -225,19 +222,27 @@ public void run() {
225222
}
226223

227224
private void loadSubCategory(String sender, String langCode, String aCategory, String aUrl) {
228-
Gson gson = new GsonBuilder().registerTypeAdapter(ArteCategoryFilmsDTO.class, new ArteCategoryFilmListDeserializer()).create();
225+
Gson gson = new GsonBuilder()
226+
.registerTypeAdapter(ArteCategoryFilmsDTO.class, new ArteCategoryFilmListDeserializer())
227+
.create();
228+
Gson gsonCollection = new GsonBuilder()
229+
.registerTypeAdapter(ArteCategoryFilmsDTO.class, new ArteCollectionDeserializer())
230+
.create();
229231

230232
// erste Seite laden
231233
int i = 2;
232234
ArteCategoryFilmsDTO dto = loadSubCategoryPage(gson, sender, aUrl);
233235
if (dto != null) {
236+
loadCollections(sender, langCode, gsonCollection, dto);
237+
234238
ArteCategoryFilmsDTO nextDto = dto;
235239
while (PARSE_SUBCATEGORY_SUB_PAGES && nextDto != null && nextDto.hasNextPage()) {
236240

237241
// weitere Seiten laden und zu programId-liste des ersten DTO hinzufügen
238242
String url = String.format(URL_SUBCATEGORY, langCode.toLowerCase(), aCategory, i);
239243
nextDto = loadSubCategoryPage(gson, sender, url);
240244
if (nextDto != null) {
245+
loadCollections(sender, langCode, gsonCollection, nextDto);
241246
nextDto.getProgramIds().forEach(programId -> dto.addProgramId(programId));
242247
}
243248

@@ -251,6 +256,20 @@ private void loadSubCategory(String sender, String langCode, String aCategory, S
251256
}
252257
}
253258

259+
private void loadCollections(String sender, String langCode, Gson gson, ArteCategoryFilmsDTO dto) {
260+
dto.getCollectionIds().forEach(collectionId -> {
261+
final String url = String.format(COLLECTION_URL, langCode, collectionId);
262+
try {
263+
final ArteCategoryFilmsDTO collectionDto = ArteHttpClient.executeRequest(sender, LOG, gson, url, ArteCategoryFilmsDTO.class);
264+
if (collectionDto != null) {
265+
collectionDto.getProgramIds().forEach(dto::addProgramId);
266+
}
267+
} catch (Exception e) {
268+
Log.errorLog(894330855, e, url);
269+
}
270+
});
271+
}
272+
254273
private ListeFilme loadPrograms(String sender, String langCode, ArteCategoryFilmsDTO dto) {
255274
ListeFilme listeFilme = new ListeFilme();
256275

0 commit comments

Comments
 (0)