diff --git a/src/main/java/com/rarchives/ripme/ripper/rippers/NsfwXxxRipper.java b/src/main/java/com/rarchives/ripme/ripper/rippers/NsfwXxxRipper.java new file mode 100644 index 00000000..d25f453b --- /dev/null +++ b/src/main/java/com/rarchives/ripme/ripper/rippers/NsfwXxxRipper.java @@ -0,0 +1,124 @@ +package com.rarchives.ripme.ripper.rippers; + +import com.rarchives.ripme.ripper.AbstractJSONRipper; +import com.rarchives.ripme.utils.Http; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class NsfwXxxRipper extends AbstractJSONRipper { + + public NsfwXxxRipper(URL url) throws IOException { + super(url); + } + + @Override + protected String getDomain() { + return "nsfw.xxx"; + } + + @Override + public String getHost() { + return "nsfw_xxx"; + } + + + @Override + public URL sanitizeURL(URL url) throws MalformedURLException { + String u = url.toExternalForm(); + // https://nsfw.xxx/user/kelly-kat/foo -> https://nsfw.xxx/user/kelly-kat + // https://nsfw.xxx/user/kelly-kat -> https://nsfw.xxx/user/kelly-kat + // keep up to and including the username + u = u.replaceAll("https?://nsfw.xxx/user/([^/]+)/?.*", "https://nsfw.xxx/user/$1"); + if (!u.contains("nsfw.xxx/user")) { + throw new MalformedURLException("Invalid URL: " + url); + } + + return new URL(u); + } + + String getUser() throws MalformedURLException { + return getGID(url); + } + + URL getPage(int page) throws MalformedURLException { + return new URL("https://nsfw.xxx/slide-page/" + page + "?nsfw%5B%5D=0&types%5B%5D=image&types%5B%5D=video&types%5B%5D=gallery&slider=1&jsload=1&user=" + getUser()); + } + + + @Override + public String getGID(URL url) throws MalformedURLException { + Pattern p = Pattern.compile("https://nsfw.xxx/user/([^/]+)/?$"); + Matcher m = p.matcher(url.toExternalForm()); + if (m.matches()) { + return m.group(1); + } + throw new MalformedURLException("Expected URL format: " + + "nsfw.xxx/user/USER - got " + url + " instead"); + } + + + int currentPage = 1; + + @Override + protected JSONObject getFirstPage() throws IOException { + return Http.url(getPage(1)).getJSON(); + } + + List descriptions = new ArrayList<>(); + + @Override + protected JSONObject getNextPage(JSONObject doc) throws IOException { + currentPage++; + JSONObject nextPage = Http.url(getPage(doc.getInt("page") + 1)).getJSON(); + JSONArray items = nextPage.getJSONArray("items"); + if (items.length() == 0) { + throw new IOException("No more pages"); + } + return nextPage; + } + + class ApiEntry { + String srcUrl; + String author; + String title; + + public ApiEntry(String srcUrl, String author, String title) { + this.srcUrl = srcUrl; + this.author = author; + this.title = title; + } + } + + @Override + protected List getURLsFromJSON(JSONObject json) { + JSONArray items = json.getJSONArray("items"); + List data = IntStream + .range(0, items.length()) + .mapToObj(items::getJSONObject) + .map(o -> new ApiEntry(o.getString("src"), o.getString("author"), o.getString("title"))) + .collect(Collectors.toList()); + + data.forEach(e -> descriptions.add(e.title)); + return data.stream().map(e -> e.srcUrl).collect(Collectors.toList()); + } + + @Override + protected void downloadURL(URL url, int index) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + addURLToDownload(url, getPrefix(index) + descriptions.get(index - 1) + "_" , "", "", null); + } +}