diff --git a/ks.server/pom.xml b/ks.server/pom.xml index c107d4a..33f68f2 100644 --- a/ks.server/pom.xml +++ b/ks.server/pom.xml @@ -76,6 +76,23 @@ ${jetty.version} + + + commons-io + commons-io + 2.5 + + + org.apache.httpcomponents + httpclient + 4.5.2 + + + org.jsoup + jsoup + 1.8.3 + + org.projectlombok diff --git a/ks.server/src/main/java/ks/server/SpringConfigMVC.java b/ks.server/src/main/java/ks/server/SpringConfigMVC.java index d137829..97459c2 100644 --- a/ks.server/src/main/java/ks/server/SpringConfigMVC.java +++ b/ks.server/src/main/java/ks/server/SpringConfigMVC.java @@ -4,17 +4,23 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.GsonHttpMessageConverter; +import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration -@ComponentScan({ "ks.server.controllers" }) +@ComponentScan({ "ks.server.controllers", "ks.server.browser" }) @EnableWebMvc public class SpringConfigMVC implements WebMvcConfigurer { @Override public void configureMessageConverters(List> converters) { converters.add(new GsonHttpMessageConverter()); } + + @Override + public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { + configurer.favorPathExtension(false); + } } diff --git a/ks.server/src/main/java/ks/server/WebApplication.java b/ks.server/src/main/java/ks/server/WebApplication.java index 6ea0404..2e8ed50 100644 --- a/ks.server/src/main/java/ks/server/WebApplication.java +++ b/ks.server/src/main/java/ks/server/WebApplication.java @@ -1,7 +1,5 @@ package ks.server; -import ks.server.controllers.ErrorPageController; -import ks.server.controllers.WebController; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.eclipse.jetty.server.ConnectionFactory; diff --git a/ks.server/src/main/java/ks/server/browser/ApacheBrowser.java b/ks.server/src/main/java/ks/server/browser/ApacheBrowser.java new file mode 100644 index 0000000..bae8620 --- /dev/null +++ b/ks.server/src/main/java/ks/server/browser/ApacheBrowser.java @@ -0,0 +1,47 @@ +package ks.server.browser; + +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClients; +import org.springframework.context.annotation.Scope; +import org.springframework.context.annotation.ScopedProxyMode; +import org.springframework.stereotype.Component; +import org.springframework.web.context.WebApplicationContext; + +import java.io.IOException; + +@Slf4j +@Component +@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) +public class ApacheBrowser implements Browser { + @Setter + private String encoding = "UTF-8"; + + private void setupHeaders(HttpGet request) { + request.addHeader("Connection", "close"); + request.addHeader("Accept-Encoding", "deflate"); + request.addHeader("User-Agent", "Mozilla/5.0 (Linux; Android 7.0; SM-G892A Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/67.0.3396.87 Mobile Safari/537.36"); + } + + @Override + public String get(String url) { + HttpClient client = HttpClients.createDefault(); + HttpGet request = new HttpGet(url); + setupHeaders(request); + + String result = ""; + try { + HttpResponse response = client.execute(request); + result = IOUtils.toString(response.getEntity().getContent(), encoding); + } catch (IOException e) { + log.warn("Error i/o from GET url \"{}\": {}", url, e.getMessage()); + log.debug("", e); + } + + return result; + } +} diff --git a/ks.server/src/main/java/ks/server/browser/Browser.java b/ks.server/src/main/java/ks/server/browser/Browser.java new file mode 100644 index 0000000..8be7a39 --- /dev/null +++ b/ks.server/src/main/java/ks/server/browser/Browser.java @@ -0,0 +1,6 @@ +package ks.server.browser; + +public interface Browser { + void setEncoding(String encoding); + String get(String url); +} diff --git a/ks.server/src/main/java/ks/server/controllers/WebController.java b/ks.server/src/main/java/ks/server/controllers/WebController.java index 747e6fb..3346ad6 100644 --- a/ks.server/src/main/java/ks/server/controllers/WebController.java +++ b/ks.server/src/main/java/ks/server/controllers/WebController.java @@ -1,21 +1,101 @@ package ks.server.controllers; +import ks.server.browser.Browser; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import javax.servlet.http.HttpServletRequest; import java.util.Collections; +import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; -@Controller -@RequestMapping(path = "/", produces = MediaType.APPLICATION_JSON_UTF8_VALUE) -@ResponseBody +@RestController +@RequestMapping( + path = "/", + method = RequestMethod.GET, + produces = MediaType.APPLICATION_JSON_UTF8_VALUE) public class WebController { + @Autowired + private Browser browser; - @RequestMapping(method = RequestMethod.GET) + private String subpath(String requestUri, String marker) { + return requestUri.substring(requestUri.indexOf(marker) + marker.length()); + } + + @RequestMapping public Map index() { return Collections.singletonMap("message", "hello?"); } + + @RequestMapping(path = "/c/animevost/info/**") + public Map animevostInfo(HttpServletRequest request) { + final String domainUri = "http://animevost.org/"; + final String path = subpath(request.getRequestURI(), "/info/"); + final String cinemaRequestUri = domainUri + path; + + final Map resultMap = new HashMap<>(); + resultMap.put("_uri", cinemaRequestUri); + + Document htmlDocument = Jsoup.parse(browser.get(cinemaRequestUri)); + + // /html/body/section/div/div[1]/div[2]/div[2] + // .infoContent + Element infoContent = htmlDocument.select(".infoContent").first(); + + // /html/body/section/div/div[1]/div[2]/div[2]/div[1]/h3 + // .infoContent > h3:nth-child(1) + resultMap.put("title", + infoContent.select("h3:nth-child(1)").first().text()); + + // /html/body/section/div/div[1]/div[2]/div[2]/div[1]/div[1]/img + // .infoContent > div:nth-child(2) > img:nth-child(1) + resultMap.put("poster", domainUri + + infoContent.select("div:nth-child(2) > img:nth-child(1)").first().attr("src")); + + // /html/body/section/div/div[1]/div[2]/div[2]/div[1]/p[1] + // .infoContent > p:nth-child(3) + resultMap.put("year", + Integer.parseInt(infoContent.select("p:nth-child(3)").first().childNode(1).toString().trim())); + + // /html/body/section/div/div[1]/div[2]/div[2]/div[1]/p[2] + // .infoContent > p:nth-child(4) + resultMap.put("genre", Stream.of( + infoContent.select("p:nth-child(4)").first().childNode(1).toString().trim() + .split(",")) + .map(String::trim).collect(Collectors.toList())); + + // /html/body/section/div/div[1]/div[2]/div[2]/div[1]/p[3] + // .infoContent > p:nth-child(5) + resultMap.put("type", + infoContent.select("p:nth-child(5)").first().childNode(1).toString().trim()); + + // /html/body/section/div/div[1]/div[2]/div[2]/div[1]/p[4] + // .infoContent > p:nth-child(6) + resultMap.put("countSeries", + infoContent.select("p:nth-child(6)").first().childNode(1).toString().trim()); + + // /html/body/section/div/div[1]/div[2]/div[2]/div[1]/p[5]/a + // .infoContent > p:nth-child(7) > a:nth-child(2) + resultMap.put("director", + infoContent.select("p:nth-child(7) > a:nth-child(2)").first().text()); + + // /html/body/section/div/div[1]/div[2]/div[2]/div[1]/p[6] + // .infoContent > p:nth-child(8) + resultMap.put("description", + infoContent.select("p:nth-child(8)").first().childNodes().stream() + .skip(1) + .map(node -> node.toString().trim()) + .filter(text -> !text.isEmpty() && !text.equalsIgnoreCase("
")) + .collect(Collectors.joining(" "))); + + return resultMap; + } }