Skip to content
This repository was archived by the owner on Apr 27, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 1 addition & 11 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,7 @@ repositories {
}

dependencies {
compile 'io.javaslang:javaslang:2.0.2'
compile group: 'io.javaslang', name: 'javaslang', version: '2.0.5'
compile 'org.jsoup:jsoup:1.10.2'

compile 'org.slf4j:slf4j-api:1.6.4'
compile 'ch.qos.logback:logback-classic:1.0.1'
compile 'ch.qos.logback:logback-core:1.0.1'

compileOnly "org.projectlombok:lombok:1.16.10"

testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
testCompile 'org.codehaus.groovy:groovy:2.4.7'
testCompile 'cglib:cglib:3.2.2'

}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.softwaremill.java_fp_example.contest.wkromolicki;

import static com.softwaremill.java_fp_example.DefaultImage.DEFAULT_IMAGE;
import static com.softwaremill.java_fp_example.contest.wkromolicki.ParserFunctions.*;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

import org.jsoup.nodes.Element;

import javaslang.control.Try;

public class FacebookImage {

private final static Predicate<Element> FACEBOOK_IMAGE_TAG_FILTER = el -> "og:image".equals(el.attr("property"));

public static String extractImage(String pageUrl) {
return findImage.apply(FACEBOOK_IMAGE_TAG_FILTER)
.apply(pageUrl)
.onFailure(handleExceptionFor(pageUrl))
.getOrElse(DEFAULT_IMAGE);
}

private static Function<Predicate<Element>, Function<String, Try<String>>> findImage =
filter -> fetchUrl.andThen(lift(parseUrl)).andThen(lift(findMetaTag.apply(filter))).andThen(lift(extractContent));


private static Consumer<Throwable> handleExceptionFor(String pageUrl) {
return e -> log(String.format("Unable to extract og:image from url %s. Problem: %s", pageUrl, e.getMessage()));
}

private static void log(String message) {
System.out.println(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.softwaremill.java_fp_example.contest.wkromolicki;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

public class FacebookImageVersion {

public static final String DEFAULT_IMAGE = "https://softwaremill.com/images/logo-vertical.023d8496.png";
private static final Pattern FACEBOOK_IMAGE_PATTERN = Pattern.compile("<head>.*?(<meta\\s+[^>]*?property=\"og:image\".*?\\/?>).*?<\\/head>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE);
private static final Pattern TAG_CONTENT_PATTERN = Pattern.compile("content=\"(.+?)\"", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE);
private static final int TEN_SECONDS = 10_000;
private static final Logger log = Logger.getLogger(FacebookImageVersion.class.getName());

public static String extractImageAddressFrom(String pageUrl) {
HttpURLConnection c = null;
try {
c = (HttpURLConnection) new URL(pageUrl).openConnection();
} catch (IOException e) {
log.severe("Cannot open connection to " + pageUrl + " - reason: " + e.toString());
return DEFAULT_IMAGE;
}
c.setConnectTimeout(TEN_SECONDS);
c.setReadTimeout(TEN_SECONDS);
String contentEncoding = c.getHeaderField("Content-Encoding");
String html = null;
try (InputStream is = contentEncoding != null && contentEncoding.contains("gzip") ? new GZIPInputStream(c.getInputStream()) : c.getInputStream();
Scanner s = new Scanner(is, StandardCharsets.UTF_8.name())) {
html = s.useDelimiter("\\A").next();
} catch (IOException e) {
log.severe("Cannot read from " + pageUrl + " - reason: " + e.toString());
return DEFAULT_IMAGE;
}
try {
Matcher tagMatch = FACEBOOK_IMAGE_PATTERN.matcher(html);
tagMatch.find();
Matcher contentMatch = TAG_CONTENT_PATTERN.matcher(tagMatch.group(1));
contentMatch.find();
return contentMatch.group(1);
} catch (Exception e) {
log.warning("No og:image found for blog post " + pageUrl);
return DEFAULT_IMAGE;
}
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017 <twój login na GitHubie>
Copyright (c) 2017 wkromolicki

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.softwaremill.java_fp_example.contest.wkromolicki;

import java.net.URL;
import java.util.function.Function;
import java.util.function.Predicate;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import javaslang.collection.List;
import javaslang.control.Try;

public class ParserFunctions {
public final static int TIMEOUT = 10_000;

public static Function<Predicate<Element>, Function<Document, Try<Element>>> findMetaTag =
tagFilter -> document -> List.ofAll(document.head().getElementsByTag("meta")).filter(tagFilter).headOption().toTry();


public static Function<Element, Try<String>> extractContent = safe(el -> el.attr("content"));

public static Function<String, Try<URL>> fetchUrl = safe(URL::new);

public static Function<URL, Try<Document>> parseUrl = safe(url -> Jsoup.parse(url, TIMEOUT));


//below are helper methods which do not belong to parser domain and should be in some library
public static <A,B> Function<Try<A>, Try<B>> lift(Function<A, Try<B>> func) {
return in -> in.flatMap(func::apply);
}

public static <A, B> Function<A, Try<B>> safe(Try.CheckedFunction<A, B> func) {
return a -> Try.of(() -> func.apply(a));
}


}
Loading