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;
|
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