added CKeller parser
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -1,4 +1,114 @@
|
||||
/* © SRSoftware 2024 */
|
||||
package de.srsoftware.cal.importer.weimar;
|
||||
|
||||
public class CKeller {
|
||||
import static de.srsoftware.tools.Error.error;
|
||||
import static de.srsoftware.tools.Optionals.nullable;
|
||||
import static de.srsoftware.tools.Result.transform;
|
||||
import static de.srsoftware.tools.Tag.*;
|
||||
import static de.srsoftware.tools.TagFilter.*;
|
||||
import static java.util.Optional.empty;
|
||||
|
||||
import de.srsoftware.cal.BaseAppointment;
|
||||
import de.srsoftware.cal.Util;
|
||||
import de.srsoftware.cal.api.Appointment;
|
||||
import de.srsoftware.cal.api.Attachment;
|
||||
import de.srsoftware.cal.api.Importer;
|
||||
import de.srsoftware.cal.api.Link;
|
||||
import de.srsoftware.tools.Payload;
|
||||
import de.srsoftware.tools.Result;
|
||||
import de.srsoftware.tools.Tag;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class CKeller implements Importer {
|
||||
private static final String BASE_URL = "http://c-keller.de";
|
||||
private static final Pattern YEAR_PATTERN = Pattern.compile("^(\\d{4}):?$");
|
||||
private static final Pattern EVENT_PATTERN = Pattern.compile("\\D*(\\d\\d?).(\\d\\d?). *([^&]+)&[^;]+;(.*)");
|
||||
private static final String LOCATION = "C-Keller, Markt 21, 99423 Weimar";
|
||||
private static final LocalTime START_TIME = LocalTime.of(19,0);
|
||||
private final Link link;
|
||||
|
||||
public CKeller() throws MalformedURLException {
|
||||
link = new Link(URI.create(BASE_URL).toURL(),"Homepage");
|
||||
}
|
||||
@Override
|
||||
public String description() {
|
||||
return "Importer für Events des C-Keller in Weimar";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Appointment> fetch() throws IOException {
|
||||
return Payload.of(BASE_URL)
|
||||
.map(Util::url)
|
||||
.map(Util::open)
|
||||
.map(Util::preload)
|
||||
.map(Util::parseXML)
|
||||
.map(this::extract)
|
||||
.optional()
|
||||
.orElseGet(List::of)
|
||||
.stream();
|
||||
}
|
||||
|
||||
private Result<List<Appointment>> extract(Result<Tag> tagResult) {
|
||||
var list = new ArrayList<Appointment>();
|
||||
if (tagResult.optional().isEmpty()) return transform(tagResult);
|
||||
Util.dump(tagResult.optional().get());
|
||||
var divs = tagResult.optional().get()
|
||||
.find(attributeEquals(ID,"col2_content")).stream()
|
||||
.flatMap(tag -> tag.children().stream())
|
||||
.toList();
|
||||
Tag last = null;
|
||||
var now = LocalDate.now();
|
||||
for (var div : divs){
|
||||
if ("textumschluss".equals(div.get(ID))){
|
||||
createEvent(last,div,now).ifPresent(list::add);
|
||||
}
|
||||
last = div;
|
||||
}
|
||||
return Payload.of(list);
|
||||
}
|
||||
|
||||
private Optional<Appointment> createEvent(Tag cal, Tag text, LocalDate now) {
|
||||
var day = cal.find(attributeEquals(CLASS, "calday")).stream()
|
||||
.map(Tag::strip).map(Util::parseInt).findAny().orElseGet(() -> error("No date")).optional();
|
||||
if (day.isEmpty()) return empty();
|
||||
|
||||
Stream<Result<Integer>> stream = cal.find(attributeEquals(CLASS, "calmonth")).stream().map(Tag::strip).flatMap(s -> Util.toNumericMonth(s).stream());
|
||||
Optional<Integer> mon = stream.findAny().orElse(error("Error")).optional();
|
||||
if (mon.isEmpty()) return empty();
|
||||
var title = text.find(attributeEquals(CLASS,"fett")).stream().map(Tag::strip).findAny();
|
||||
if (title.isEmpty()) return empty();
|
||||
var desc = text.find(attributeEquals(CLASS,"kalenderi")).stream().map(Tag::strip).findAny();
|
||||
|
||||
var date = LocalDate.of(now.getYear(),mon.get(),day.get());
|
||||
if (date.isBefore(now)) date = date.withYear(now.getYear()+1);
|
||||
var start = LocalDateTime.of(date,START_TIME);
|
||||
var app = new BaseAppointment(0,title.get(),desc.orElse(title.get()),start,null,LOCATION);
|
||||
|
||||
text.find(IS_IMAGE).stream().map(tag -> imageToAttachment(tag))
|
||||
.map(Result::optional).flatMap(Optional::stream)
|
||||
.forEach(app::add);
|
||||
app.addLinks(link);
|
||||
app.tags("C-Keller","Weimar");
|
||||
return Optional.of(app);
|
||||
}
|
||||
|
||||
private Result<Attachment> imageToAttachment(Tag img) {
|
||||
var parent = img.parent();
|
||||
String url = parent.map(tag -> tag.get(HREF)).orElseGet(() -> img.get("src"));
|
||||
if (url == null) return error("No link found");
|
||||
if (url.startsWith("./")) url = url.substring(2);
|
||||
if (!url.contains("://")) url = BASE_URL + "/" + url;
|
||||
return Payload.of(url).map(Util::url).map(Util::toAttachment);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user