7 changed files with 122 additions and 8 deletions
@ -0,0 +1,6 @@ |
|||||||
|
description = "OpenCloudCal : Application" |
||||||
|
|
||||||
|
dependencies { |
||||||
|
implementation(project(":de.srsoftware.cal.api")) |
||||||
|
implementation(project(":de.srsoftware.cal.importer")) |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
/* © SRSoftware 2024 */ |
||||||
|
package de.srsoftware.cal.app; |
||||||
|
|
||||||
|
import de.srsoftware.cal.importer.JenaRosenkeller; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class Application { |
||||||
|
public static void main(String[] args) throws IOException { |
||||||
|
var rosenkeller = new JenaRosenkeller(); |
||||||
|
rosenkeller.fetch(); |
||||||
|
} |
||||||
|
} |
@ -1,4 +0,0 @@ |
|||||||
description = "OpenCloudCal : Importers" |
|
||||||
|
|
||||||
dependencies { |
|
||||||
} |
|
@ -0,0 +1,8 @@ |
|||||||
|
description = "OpenCloudCal : Importers" |
||||||
|
|
||||||
|
dependencies { |
||||||
|
implementation(project(":de.srsoftware.cal.api")) |
||||||
|
implementation("de.srsoftware:tools.optionals:1.0.0") |
||||||
|
implementation("de.srsoftware:tools.util:1.1.0") |
||||||
|
implementation("de.srsoftware:tools.web:1.2.1") |
||||||
|
} |
@ -0,0 +1,91 @@ |
|||||||
|
/* © SRSoftware 2024 */ |
||||||
|
package de.srsoftware.cal.importer; |
||||||
|
|
||||||
|
import static de.srsoftware.tools.Optionals.nullable; |
||||||
|
import static java.util.Optional.empty; |
||||||
|
import static java.util.function.Predicate.not; |
||||||
|
|
||||||
|
import de.srsoftware.cal.api.Appointment; |
||||||
|
import de.srsoftware.cal.api.Importer; |
||||||
|
import de.srsoftware.tools.Payload; |
||||||
|
import de.srsoftware.tools.Tag; |
||||||
|
import de.srsoftware.tools.XMLParser; |
||||||
|
import java.io.IOException; |
||||||
|
import java.net.MalformedURLException; |
||||||
|
import java.net.URI; |
||||||
|
import java.net.URISyntaxException; |
||||||
|
import java.net.URL; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
import java.util.stream.Stream; |
||||||
|
|
||||||
|
public class JenaRosenkeller implements Importer { |
||||||
|
@Override |
||||||
|
public String description() { |
||||||
|
return "Events von der Seite rosenkeller.org importieren"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<Appointment> fetch() throws IOException { |
||||||
|
var url = "https://rosenkeller.org/de/programm"; |
||||||
|
var listUrl = url(url); |
||||||
|
if (listUrl.isEmpty()) throw new RuntimeException("Failed to fetch %s".formatted(url)); |
||||||
|
|
||||||
|
var input = listUrl.get().openConnection().getInputStream(); |
||||||
|
input = XMLParser.preload(input); |
||||||
|
var result = XMLParser.parse(input); |
||||||
|
input.close(); |
||||||
|
List<Appointment> appointments = nullable(result) //
|
||||||
|
.filter(o -> o instanceof Payload<Tag>) |
||||||
|
.map(o -> (Payload<Tag>)o) |
||||||
|
.map(Payload::get) |
||||||
|
.stream() |
||||||
|
.flatMap(JenaRosenkeller::findEventUrls) |
||||||
|
.map(JenaRosenkeller::url) |
||||||
|
.filter(Optional::isPresent) |
||||||
|
.map(Optional::get) |
||||||
|
.map(JenaRosenkeller::loadEvent) |
||||||
|
.filter(Optional::isPresent) |
||||||
|
.map(Optional::get) |
||||||
|
.toList(); |
||||||
|
|
||||||
|
System.out.println(appointments); |
||||||
|
return appointments; |
||||||
|
} |
||||||
|
|
||||||
|
private static Optional<Appointment> loadEvent(URL url) { |
||||||
|
try { |
||||||
|
var input = url.openConnection().getInputStream(); |
||||||
|
input = XMLParser.preload(input); |
||||||
|
var result = XMLParser.parse(input); |
||||||
|
input.close(); |
||||||
|
if (result instanceof Payload<Tag> payload) { |
||||||
|
var tag = payload.get(); |
||||||
|
tag.find("class", s -> s.endsWith("single-event-title")) //
|
||||||
|
.stream() |
||||||
|
.map(Tag::children) |
||||||
|
.filter(not(List::isEmpty)) |
||||||
|
.map(List::getFirst) |
||||||
|
.map(Tag::toString) |
||||||
|
.forEach(System.out::println); |
||||||
|
} |
||||||
|
return empty(); |
||||||
|
} catch (IOException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
return empty(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static Stream<String> findEventUrls(Tag tag) { |
||||||
|
return tag.find("id", val -> val.startsWith("event-")).stream().map(t -> t.find("class", "ect-event-url" ::equals)).flatMap(List::stream).map(t -> t.get("href")); |
||||||
|
} |
||||||
|
|
||||||
|
private static Optional<URL> url(String url) { |
||||||
|
try { |
||||||
|
return Optional.of(new URI(url).toURL()); |
||||||
|
} catch (MalformedURLException | URISyntaxException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
return empty(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue