Skip to content

Commit 0ff62fc

Browse files
author
updating-bot
committed
mirroring bot - 2025/10/14
1 parent 3dd7748 commit 0ff62fc

36 files changed

+1880
-478
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package jd.plugins.decrypter;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import java.util.regex.Pattern;
6+
7+
import org.jdownloader.plugins.controller.LazyPlugin;
8+
9+
import jd.PluginWrapper;
10+
import jd.http.Browser;
11+
import jd.plugins.DecrypterPlugin;
12+
import jd.plugins.hoster.BurningCamelCom;
13+
14+
@DecrypterPlugin(revision = "$Revision: 51660 $", interfaceVersion = 2, names = {}, urls = {})
15+
public class BurningCamelComCrawler extends PornEmbedParser {
16+
public BurningCamelComCrawler(PluginWrapper wrapper) {
17+
super(wrapper);
18+
}
19+
20+
@Override
21+
public LazyPlugin.FEATURE[] getFeatures() {
22+
return new LazyPlugin.FEATURE[] { LazyPlugin.FEATURE.XXX };
23+
}
24+
25+
public static List<String[]> getPluginDomains() {
26+
final List<String[]> ret = new ArrayList<String[]>();
27+
// each entry in List<String[]> will result in one PluginForDecrypt, Plugin.getHost() will return String[0]->main domain
28+
ret.add(new String[] { "burningcamel.com", "camelstyle.net" });
29+
return ret;
30+
}
31+
32+
@Override
33+
protected ArrayList<String> getDeadDomains() {
34+
final ArrayList<String> deadDomains = new ArrayList<String>();
35+
deadDomains.add("camelstyle.net");
36+
return deadDomains;
37+
}
38+
39+
public static String[] getAnnotationNames() {
40+
return buildAnnotationNames(getPluginDomains());
41+
}
42+
43+
@Override
44+
public String[] siteSupportedNames() {
45+
return buildSupportedNames(getPluginDomains());
46+
}
47+
48+
public static String[] getAnnotationUrls() {
49+
return buildAnnotationUrls(getPluginDomains());
50+
}
51+
52+
private static final Pattern TYPE_OLD = Pattern.compile("/video/([a-z0-9-]+(/\\d+)?)", Pattern.CASE_INSENSITIVE);
53+
/* 2025-10-13: New */
54+
private static final Pattern TYPE_NEW = Pattern.compile("/\\d{4}/\\d{2}/\\d{2}/([\\w-]+)/?", Pattern.CASE_INSENSITIVE);
55+
56+
public static String[] buildAnnotationUrls(final List<String[]> pluginDomains) {
57+
final List<String> ret = new ArrayList<String>();
58+
for (final String[] domains : pluginDomains) {
59+
ret.add("https?://(?:www\\.)?" + buildHostsPatternPart(domains) + "(" + TYPE_OLD.pattern() + "|" + TYPE_NEW.pattern() + ")");
60+
}
61+
return ret.toArray(new String[0]);
62+
}
63+
64+
protected boolean isOffline(final Browser br) {
65+
if (br.getHttpConnection().getResponseCode() == 404) {
66+
return true;
67+
} else if (!this.canHandle(br.getURL())) {
68+
return true;
69+
} else {
70+
return false;
71+
}
72+
}
73+
74+
@Override
75+
protected boolean isSelfhosted(final Browser br) {
76+
if (BurningCamelCom.findDirectUrl(br) != null) {
77+
return true;
78+
} else {
79+
return false;
80+
}
81+
}
82+
83+
public static final String getContentURL(final String fid) {
84+
return "https://" + getPluginDomains().get(0)[0] + "/video/" + fid;
85+
}
86+
}

svn_trunk/src/jd/plugins/decrypter/CivitaiComCrawler.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
import jd.plugins.hoster.CivitaiCom;
4848
import jd.plugins.hoster.DirectHTTP;
4949

50-
@DecrypterPlugin(revision = "$Revision: 50475 $", interfaceVersion = 3, names = {}, urls = {})
50+
@DecrypterPlugin(revision = "$Revision: 51657 $", interfaceVersion = 3, names = {}, urls = {})
5151
@PluginDependencies(dependencies = { CivitaiCom.class })
5252
public class CivitaiComCrawler extends PluginForDecrypt {
5353
public CivitaiComCrawler(PluginWrapper wrapper) {
@@ -103,6 +103,13 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
103103
*/
104104
final String apiBase = "https://civitai.com/api/v1";
105105
final List<Map<String, Object>> modelVersions = new ArrayList<Map<String, Object>>();
106+
/**
107+
* 2024-07-18: About the "nsfw" parameter: According to their docs, without nsfw parameter, all items will be returned but that is
108+
* wrong --> Wrong API docs or bug in API. </br>
109+
* Only with the nsfw parameter set to "X", all items will be returned. <br>
110+
* 2024-07-18: Issue has been reported to civitai: https://github.com/civitai/civitai/issues/1277
111+
*/
112+
final String special_api_params = "&nsfw=X";
106113
String modelName = null;
107114
if (itemType.equals("models")) {
108115
/* Crawl all versions of a model */
@@ -125,9 +132,11 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
125132
}
126133
}
127134
} else if (itemType.equals("posts")) {
128-
/* Handles such links: https://civitai.com/posts/1234567 */
129-
/* https://github.com/civitai/civitai/wiki/REST-API-Reference#get-apiv1images */
130-
br.getPage(apiBase + "/images?postId=" + itemID);
135+
/**
136+
* Handles such links: https://civitai.com/posts/1234567 <br>
137+
* https://github.com/civitai/civitai/wiki/REST-API-Reference#get-apiv1images
138+
*/
139+
br.getPage(apiBase + "/images?postId=" + itemID + special_api_params);
131140
if (br.getHttpConnection().getResponseCode() == 404) {
132141
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
133142
}
@@ -162,14 +171,9 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
162171
/* Handles such links: https://civitai.com/user/test */
163172
/* https://github.com/civitai/civitai/wiki/REST-API-Reference#get-apiv1images */
164173
/* 2024-07-17: use small limit/pagination size to avoid timeout issues */
165-
/**
166-
* 2024-07-18: About the "nsfw" parameter: According to their docs, without nsfw parameter, all items will be rerturned but that
167-
* is wrong --> Wrong API docs or bug in API. </br>
168-
* Only with the nsfw parameter set to "X", all items will be returned.
169-
*/
170174
final int maxItemsPerPage = cfg.getProfileCrawlerMaxPaginationItems();
171175
final int paginationSleepMillis = cfg.getProfileCrawlerPaginationSleepMillis();
172-
String nextpage = apiBase + "/images?username=" + itemID + "&limit=" + maxItemsPerPage + "&nsfw=X";
176+
String nextpage = apiBase + "/images?username=" + itemID + "&limit=" + maxItemsPerPage + special_api_params;
173177
if (modelVersionId != null) {
174178
nextpage += "&modelVersionId=" + modelVersionId;
175179
}

svn_trunk/src/jd/plugins/decrypter/FilefactoryComFolder.java

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package jd.plugins.decrypter;
1717

1818
import java.util.ArrayList;
19+
import java.util.Arrays;
1920
import java.util.HashSet;
2021
import java.util.List;
2122
import java.util.Map;
@@ -45,7 +46,7 @@
4546
import jd.plugins.PluginForDecrypt;
4647
import jd.plugins.hoster.FileFactory;
4748

48-
@DecrypterPlugin(revision = "$Revision: 51653 $", interfaceVersion = 2, names = {}, urls = {})
49+
@DecrypterPlugin(revision = "$Revision: 51663 $", interfaceVersion = 2, names = {}, urls = {})
4950
@PluginDependencies(dependencies = { FileFactory.class })
5051
public class FilefactoryComFolder extends PluginForDecrypt {
5152
public FilefactoryComFolder(PluginWrapper wrapper) {
@@ -121,18 +122,73 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
121122
/* Empty folder */
122123
throw new DecrypterRetryException(RetryReason.EMPTY_FOLDER);
123124
}
124-
String folder_url_without_params = URLHelper.getUrlWithoutParams(br.getURL());
125-
if (!folder_url_without_params.endsWith("/")) {
126-
folder_url_without_params += "/";
127-
}
128-
final String folderTitle = br.getRegex("<h1>Files in\\s*<span>([^<]+)</span>").getMatch(0);
125+
/* Folder title is not available in CSV file thus to get it, we need to look into the html code of the older URL. */
126+
String folderTitle = br.getRegex("<h1>Files in\\s*<span>([^<]+)</span>").getMatch(0);
129127
final FilePackage fp = FilePackage.getInstance();
130128
if (!StringUtils.isEmpty(folderTitle)) {
131-
fp.setName(Encoding.htmlDecode(folderTitle).trim());
129+
folderTitle = Encoding.htmlDecode(folderTitle).trim();
130+
fp.setName(folderTitle);
132131
} else {
133132
logger.warning("Failed to find folder title");
134133
fp.setName(folder_id);
135134
}
135+
fp.setPackageKey(this.getHost() + "://folder/" + folder_id);
136+
parse_folder_csv_export: {
137+
/* Try to extract folder information from CSV since this is the better source of data. */
138+
final String folderExportLink = br.getRegex("(/folder/" + folder_id + "/\\?export=1)").getMatch(0);
139+
if (folderExportLink == null) {
140+
logger.warning("CSV crawler: Cannot parse folder CSV export because: Failed to find folder export link");
141+
break parse_folder_csv_export;
142+
}
143+
try {
144+
final Browser brc = br.cloneBrowser();
145+
/* Allow unlimited size of CSV files. */
146+
brc.setLoadLimit(Integer.MAX_VALUE);
147+
brc.getPage(folderExportLink);
148+
final String exportName = getFileNameFromConnection(brc.getHttpConnection());
149+
if (!StringUtils.endsWithCaseInsensitive(exportName, ".csv") || brc.getHttpConnection().getResponseCode() != 200) {
150+
logger.warning("CSV crawler: csv export failed");
151+
break parse_folder_csv_export;
152+
}
153+
final String csvContent = brc.getRequest().getHtmlCode();
154+
// Split by line breaks
155+
final String[] lines = csvContent.split("\\r?\\n");
156+
/* Validate CSV integrity by checking for the expected CSV headers. */
157+
final List<String> header = Arrays.asList(parseCsvLine(lines[0]));
158+
final int filenameIndex = header.indexOf("filename");
159+
final int sizeIndex = header.indexOf("size");
160+
final int urlIndex = header.indexOf("url");
161+
if (filenameIndex == -1 || sizeIndex == -1 || urlIndex == -1) {
162+
logger.warning("CSV crawler: cannot find all required columns in csv");
163+
break parse_folder_csv_export;
164+
}
165+
for (int i = 1; i < lines.length; i++) { // Start at 1 to skip CSV header
166+
final String line = lines[i];
167+
final String[] data = parseCsvLine(line);
168+
final String filename = data[filenameIndex];
169+
final String sizeBytesStr = data[sizeIndex];
170+
// final String createdDate = data[2];
171+
final String url = data[urlIndex];
172+
final DownloadLink link = this.createDownloadlink(url);
173+
link.setFinalFileName(filename);
174+
link.setVerifiedFileSize(Long.parseLong(sizeBytesStr));
175+
link._setFilePackage(fp);
176+
link.setAvailable(true);
177+
ret.add(link);
178+
}
179+
logger.info("CSV crawler: Success!");
180+
return ret;
181+
} catch (Exception e) {
182+
logger.log(e);
183+
logger.info("CSV crawler: Failed!");
184+
break parse_folder_csv_export;
185+
}
186+
}
187+
/* Base URL needed for pagination. */
188+
String folder_url_without_params = URLHelper.getUrlWithoutParams(br.getURL());
189+
if (!folder_url_without_params.endsWith("/")) {
190+
folder_url_without_params += "/";
191+
}
136192
int pageMax = 1;
137193
final HashSet<String> dupes = new HashSet<String>();
138194
pagination: for (int page = 1; page <= pageMax; page++) {
@@ -298,6 +354,44 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
298354
return ret;
299355
}
300356

357+
/**
358+
* Parses a CSV line correctly - handles quotes, commas, and escaped quotes within quoted values Java 1.6 compatible version
359+
*
360+
* CSV escape rules: - Fields with commas or quotes are wrapped in quotes: "value" - Quotes inside quoted fields are escaped by doubling
361+
* them: ""
362+
*
363+
* Example: "File with ""quotes"" in name.zip" represents: File with "quotes" in name.zip
364+
*/
365+
private static String[] parseCsvLine(String line) {
366+
List<String> result = new ArrayList<String>();
367+
StringBuilder current = new StringBuilder();
368+
boolean inQuotes = false;
369+
for (int i = 0; i < line.length(); i++) {
370+
char c = line.charAt(i);
371+
if (c == '"') {
372+
// Check if this is an escaped quote ("")
373+
if (inQuotes && i + 1 < line.length() && line.charAt(i + 1) == '"') {
374+
// Escaped quote: add one quote to output and skip the next one
375+
current.append('"');
376+
i++; // Skip next quote
377+
} else {
378+
// Toggle quote mode (start or end of quoted field)
379+
inQuotes = !inQuotes;
380+
}
381+
} else if (c == ',' && !inQuotes) {
382+
// Comma outside quotes = new field
383+
result.add(current.toString());
384+
current = new StringBuilder();
385+
} else {
386+
// Regular character
387+
current.append(c);
388+
}
389+
}
390+
// Add last field
391+
result.add(current.toString());
392+
return result.toArray(new String[result.size()]);
393+
}
394+
301395
private String generateSingleFileLink(final String file_id, final String filename) {
302396
String url = "https://www." + this.getHost() + "/file/" + file_id;
303397
if (filename != null) {

svn_trunk/src/jd/plugins/decrypter/JulesjordanComDecrypter.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
import jd.plugins.hoster.JulesjordanCom;
4848
import jd.plugins.hoster.JulesjordanCom.JulesjordanComConfigInterface;
4949

50-
@DecrypterPlugin(revision = "$Revision: 50564 $", interfaceVersion = 3, names = {}, urls = {})
50+
@DecrypterPlugin(revision = "$Revision: 51661 $", interfaceVersion = 3, names = {}, urls = {})
5151
public class JulesjordanComDecrypter extends PluginForDecrypt {
5252
public JulesjordanComDecrypter(PluginWrapper wrapper) {
5353
super(wrapper);
@@ -61,6 +61,7 @@ public static List<String[]> getPluginDomains() {
6161
ret.add(new String[] { "theassfactory.com" });
6262
ret.add(new String[] { "spermswallowers.com" });
6363
ret.add(new String[] { "girlgirl.com" });
64+
ret.add(new String[] { "auntjudysxxx.com" });
6465
return ret;
6566
}
6667

@@ -150,7 +151,7 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
150151
account.saveCookies(br.getCookies(br.getHost()), "");
151152
}
152153
} else {
153-
// refresh stored cookies
154+
// login successful -> refresh stored cookies
154155
account.saveCookies(br.getCookies(br.getHost()), "");
155156
}
156157
}
@@ -199,7 +200,7 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
199200
}
200201

201202
public static boolean isNewDeviceProtectionActive(final Browser br) {
202-
if (br.containsHTML("(?i)>\\s*New Device or Location Detected")) {
203+
if (br.containsHTML(">\\s*New Device or Location Detected")) {
203204
return true;
204205
} else {
205206
return false;
@@ -222,7 +223,9 @@ public static HashMap<String, String> findAllQualities(final Browser br) throws
222223
final String[] jsons = br.getRegex("(\\{ path:.*?\\});").getColumn(0);
223224
for (final String json : jsons) {
224225
final Map<String, Object> entries = JavaScriptEngineFactory.jsonToJavaMap(json);
225-
final String url = (String) entries.get("path");
226+
String url = entries.get("path").toString();
227+
/* Ensure we got an absolute URL, not a relative URL. */
228+
url = br.getURL(url).toString();
226229
final String name = (String) entries.get("name");
227230
allQualities.put(name, url);
228231
}

svn_trunk/src/jd/plugins/decrypter/SolarMovieCr.java

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import jd.plugins.PluginException;
3131
import jd.plugins.PluginForDecrypt;
3232

33-
@DecrypterPlugin(revision = "$Revision: 48482 $", interfaceVersion = 2, names = {}, urls = {})
33+
@DecrypterPlugin(revision = "$Revision: 51660 $", interfaceVersion = 2, names = {}, urls = {})
3434
public class SolarMovieCr extends PluginForDecrypt {
3535
public SolarMovieCr(PluginWrapper wrapper) {
3636
super(wrapper);
@@ -46,7 +46,7 @@ public Browser createNewBrowserInstance() {
4646
public static List<String[]> getPluginDomains() {
4747
final List<String[]> ret = new ArrayList<String[]>();
4848
// each entry in List<String[]> will result in one PluginForDecrypt, Plugin.getHost() will return String[0]->main domain
49-
ret.add(new String[] { "solarmovie.cr", "solarmovie.one" });
49+
ret.add(new String[] { "solarmovie.cx", "solarmovie.cr", "solarmovie.one" });
5050
return ret;
5151
}
5252

@@ -66,7 +66,7 @@ public static String[] getAnnotationUrls() {
6666
public static String[] buildAnnotationUrls(final List<String[]> pluginDomains) {
6767
final List<String> ret = new ArrayList<String>();
6868
for (final String[] domains : pluginDomains) {
69-
ret.add("https?://(?:\\w+\\.)?" + buildHostsPatternPart(domains) + "/movie/[\\w-]+-\\d+/?");
69+
ret.add("https?://(?:\\w+\\.)?" + buildHostsPatternPart(domains) + "/movie/[\\w-]+-\\d+");
7070
}
7171
return ret.toArray(new String[0]);
7272
}
@@ -75,17 +75,27 @@ public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressContro
7575
final ArrayList<DownloadLink> ret = new ArrayList<DownloadLink>();
7676
final String contenturl = param.getCryptedUrl() + "/watching";
7777
br.getPage(contenturl);
78-
String fpName = br.getRegex("<meta name=\"description\" content=[\"']Watch ([^\"]*) Online For Free").getMatch(0);
78+
if (br.getHttpConnection().getResponseCode() == 404) {
79+
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
80+
}
81+
String title = br.getRegex("<meta name=\"description\" content=[\"']Watch ([^\"]*) Online\\s*(For)?\\s*Free").getMatch(0);
7982
final String[] links = br.getRegex("<a[^>]+data-file=\"([^\"]+)\"[^>]+>").getColumn(0);
80-
if (links == null || links.length == 0) {
81-
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
83+
if (links != null) {
84+
for (String link : links) {
85+
ret.add(createDownloadlink(Encoding.htmlDecode(link)));
86+
}
8287
}
83-
for (String link : links) {
84-
ret.add(createDownloadlink(Encoding.htmlDecode(link)));
88+
final String embed = br.getRegex("id\\s*=\\s*\"iframe-embed\"\\s*src\\s*=\\s*\"(.*?)\"").getMatch(0);
89+
if (embed != null) {
90+
ret.add(createDownloadlink(Encoding.htmlDecode(embed)));
91+
}
92+
if (ret.isEmpty()) {
93+
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
8594
}
8695
final FilePackage fp = FilePackage.getInstance();
87-
if (fpName != null) {
88-
fp.setName(Encoding.htmlDecode(fpName).trim());
96+
if (title != null) {
97+
title = Encoding.htmlDecode(title).trim();
98+
fp.setName(title);
8999
} else {
90100
/* Fallback */
91101
fp.setName(br._getURL().getPath());

0 commit comments

Comments
 (0)