mirror of
https://github.com/RipMeApp/ripme.git
synced 2025-08-11 16:34:04 +02:00
Support coomer.party
This commit is contained in:
@@ -0,0 +1,152 @@
|
|||||||
|
package com.rarchives.ripme.ripper.rippers;
|
||||||
|
|
||||||
|
import com.rarchives.ripme.ripper.AbstractJSONRipper;
|
||||||
|
import com.rarchives.ripme.utils.Http;
|
||||||
|
import com.rarchives.ripme.utils.Utils;
|
||||||
|
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <a href="https://coomer.su/api/schema">See this link for the API schema</a>.
|
||||||
|
*/
|
||||||
|
public class CoomerPartyRipper extends AbstractJSONRipper {
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(CoomerPartyRipper.class);
|
||||||
|
private static final String IMG_URL_BASE = "https://c3.coomer.su/data";
|
||||||
|
private static final String VID_URL_BASE = "https://c1.coomer.su/data";
|
||||||
|
private static final Pattern IMG_PATTERN = Pattern.compile("^.*\\.(jpg|jpeg|png|gif|apng|webp|tif|tiff)$", Pattern.CASE_INSENSITIVE);
|
||||||
|
private static final Pattern VID_PATTERN = Pattern.compile("^.*\\.(webm|mp4|m4v)$", Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
|
// just so we can return a JSONObject from getFirstPage
|
||||||
|
private static final String KEY_WRAPPER_JSON_ARRAY = "array";
|
||||||
|
|
||||||
|
private static final String KEY_FILE = "file";
|
||||||
|
private static final String KEY_PATH = "path";
|
||||||
|
private static final String KEY_ATTACHMENTS = "attachments";
|
||||||
|
|
||||||
|
private final String service;
|
||||||
|
private final String user;
|
||||||
|
|
||||||
|
public CoomerPartyRipper(URL url) throws IOException {
|
||||||
|
super(url);
|
||||||
|
List<String> pathElements = Arrays.stream(url.getPath().split("/"))
|
||||||
|
.filter(element -> !element.isBlank())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
service = pathElements.get(0);
|
||||||
|
user = pathElements.get(2);
|
||||||
|
|
||||||
|
if (service == null || user == null || service.isBlank() || user.isBlank()) {
|
||||||
|
LOGGER.warn("service=" + service + ", user=" + user);
|
||||||
|
throw new MalformedURLException("Invalid coomer.party URL: " + url);
|
||||||
|
}
|
||||||
|
LOGGER.debug("Parsed service=" + service + " and user=" + user + " from " + url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getDomain() {
|
||||||
|
return "coomer.party";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHost() {
|
||||||
|
return "coomer.party";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canRip(URL url) {
|
||||||
|
String host = url.getHost();
|
||||||
|
return host.endsWith("coomer.party") || host.endsWith("coomer.su");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getGID(URL url) {
|
||||||
|
return Utils.filesystemSafe(String.format("%s_%s", service, user));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JSONObject getFirstPage() throws IOException {
|
||||||
|
String apiUrl = String.format("https://coomer.su/api/v1/%s/user/%s", service, user);
|
||||||
|
String jsonArrayString = Http.url(apiUrl)
|
||||||
|
.ignoreContentType()
|
||||||
|
.response()
|
||||||
|
.body();
|
||||||
|
JSONArray jsonArray = new JSONArray(jsonArrayString);
|
||||||
|
|
||||||
|
// Ideally we'd just return the JSONArray from here, but we have to wrap it in a JSONObject
|
||||||
|
JSONObject wrapperObject = new JSONObject();
|
||||||
|
wrapperObject.put(KEY_WRAPPER_JSON_ARRAY, jsonArray);
|
||||||
|
return wrapperObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> getURLsFromJSON(JSONObject json) {
|
||||||
|
// extract the array from our wrapper JSONObject
|
||||||
|
JSONArray posts = json.getJSONArray(KEY_WRAPPER_JSON_ARRAY);
|
||||||
|
ArrayList<String> urls = new ArrayList<>();
|
||||||
|
for (int i = 0; i < posts.length(); i++) {
|
||||||
|
JSONObject post = posts.getJSONObject(i);
|
||||||
|
pullFileUrl(post, urls);
|
||||||
|
pullAttachmentUrls(post, urls);
|
||||||
|
}
|
||||||
|
LOGGER.debug("Pulled " + urls.size() + " URLs from " + posts.length() + " posts");
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void downloadURL(URL url, int index) {
|
||||||
|
addURLToDownload(url, getPrefix(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pullFileUrl(JSONObject post, ArrayList<String> results) {
|
||||||
|
try {
|
||||||
|
JSONObject file = post.getJSONObject(KEY_FILE);
|
||||||
|
String path = file.getString(KEY_PATH);
|
||||||
|
if (isImage(path)) {
|
||||||
|
String url = IMG_URL_BASE + path;
|
||||||
|
results.add(url);
|
||||||
|
} else if (isVideo(path)) {
|
||||||
|
String url = VID_URL_BASE + path;
|
||||||
|
results.add(url);
|
||||||
|
} else {
|
||||||
|
LOGGER.error("Unknown extension for coomer.su path: " + path);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pullAttachmentUrls(JSONObject post, ArrayList<String> results) {
|
||||||
|
try {
|
||||||
|
JSONArray attachments = post.getJSONArray(KEY_ATTACHMENTS);
|
||||||
|
for (int i = 0; i < attachments.length(); i++) {
|
||||||
|
JSONObject attachment = attachments.getJSONObject(0);
|
||||||
|
pullFileUrl(attachment, results);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
/* No-op */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isImage(String path) {
|
||||||
|
Matcher matcher = IMG_PATTERN.matcher(path);
|
||||||
|
return matcher.matches();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVideo(String path) {
|
||||||
|
Matcher matcher = VID_PATTERN.matcher(path);
|
||||||
|
return matcher.matches();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
package com.rarchives.ripme.tst.ripper.rippers;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import com.rarchives.ripme.ripper.rippers.CoomerPartyRipper;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class CoomerPartyRipperTest extends RippersTest {
|
||||||
|
@Test
|
||||||
|
public void testRip() throws IOException {
|
||||||
|
URL url = new URL("https://coomer.su/onlyfans/user/soogsx");
|
||||||
|
CoomerPartyRipper ripper = new CoomerPartyRipper(url);
|
||||||
|
testRipper(ripper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUrlParsing() throws IOException {
|
||||||
|
String expectedGid = "onlyfans_soogsx";
|
||||||
|
String[] urls = new String[]{
|
||||||
|
"https://coomer.su/onlyfans/user/soogsx", // normal url
|
||||||
|
"http://coomer.su/onlyfans/user/soogsx", // http, not https
|
||||||
|
"https://coomer.su/onlyfans/user/soogsx/", // with slash at the end
|
||||||
|
"https://coomer.su/onlyfans/user/soogsx?whatever=abc", // with url params
|
||||||
|
"https://coomer.party/onlyfans/user/soogsx", // alternate domain
|
||||||
|
};
|
||||||
|
for (String stringUrl : urls) {
|
||||||
|
URL url = new URL(stringUrl);
|
||||||
|
CoomerPartyRipper ripper = new CoomerPartyRipper(url);
|
||||||
|
assertTrue(ripper.canRip(url));
|
||||||
|
assertEquals(expectedGid, ripper.getGID(url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user