mirror of
https://github.com/mirror/jdownloader.git
synced 2024-11-23 12:09:43 +00:00
*Plugins: Fixes/Changes/Maintenance*
- FaceBookComGallery: improved detection of actually desired item DiskYandexNet: - added support for password protected folders RE ticket #LQFA3817-MCAK-6226FQNK - added better detection- and errorhandling for "read only" files (= files where uploader has disabled official download button) - added errorhandling for non-video 'read-only' files - login in crawler if account is available to avoid running into anti bot blocks too often - set last modified timestamp so that it will be set correctly even when non-original file is downloaded (e.g. stream download of non officially downloadable file) - moved unneeded function into YandexAlbum - refactored errorhandling - added support to download read-only .txt files - do not set FilePackage with name "unknown" on single file items so that Various package handling can do its job - improved parsing of docviewer URLs - set full relative path as package name in website- and API handling (removed inconsistency) - match same items (internal link_id) via 'hash' as the previous set value was different depending on source (website/API) - better error message for non downloadable read-only files git-svn-id: svn://svn.jdownloader.org/jdownloader/trunk@49595 ebf7c1c2-ba36-0410-9fe8-c592906822b4 Former-commit-id: c2f3a89b3eb4fc5cb4c9851fa774e8e01815d7e0
This commit is contained in:
parent
9db3f26a2e
commit
12599b3a8c
@ -19,17 +19,28 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.appwork.storage.TypeRef;
|
||||
import org.appwork.utils.StringUtils;
|
||||
import org.appwork.utils.encoding.URLEncode;
|
||||
import org.appwork.utils.parser.UrlQuery;
|
||||
import org.jdownloader.scripting.JavaScriptEngineFactory;
|
||||
|
||||
import jd.PluginWrapper;
|
||||
import jd.controlling.AccountController;
|
||||
import jd.controlling.ProgressController;
|
||||
import jd.http.Browser;
|
||||
import jd.http.requests.PostRequest;
|
||||
import jd.nutils.encoding.Encoding;
|
||||
import jd.parser.Regex;
|
||||
import jd.plugins.Account;
|
||||
import jd.plugins.CryptedLink;
|
||||
import jd.plugins.DecrypterException;
|
||||
import jd.plugins.DecrypterPlugin;
|
||||
import jd.plugins.DecrypterRetryException;
|
||||
import jd.plugins.DecrypterRetryException.RetryReason;
|
||||
@ -42,12 +53,6 @@ import jd.plugins.PluginForDecrypt;
|
||||
import jd.plugins.components.PluginJSonUtils;
|
||||
import jd.plugins.hoster.DiskYandexNet;
|
||||
|
||||
import org.appwork.storage.TypeRef;
|
||||
import org.appwork.utils.StringUtils;
|
||||
import org.appwork.utils.encoding.URLEncode;
|
||||
import org.appwork.utils.parser.UrlQuery;
|
||||
import org.jdownloader.scripting.JavaScriptEngineFactory;
|
||||
|
||||
@DecrypterPlugin(revision = "$Revision$", interfaceVersion = 3, names = {}, urls = {})
|
||||
public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
public DiskYandexNetFolder(PluginWrapper wrapper) {
|
||||
@ -96,82 +101,166 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
}
|
||||
|
||||
/** Usually docviewer.yandex.xy but we're supporting so many domains and subdomains that a generic RegEx works better. */
|
||||
private static final String type_docviewer = "(?i)https?://[^/]+/\\?url=ya\\-disk\\-public%3A%2F%2F([^/\"\\&]+).*?";
|
||||
private final String type_primaryURLs = "(?i).+?public/?(\\?hash=.+|#.+)";
|
||||
private final String type_shortURLs_d = "(?i)https?://[^/]+/d/[A-Za-z0-9\\-_]+((/[^/]+){0,})";
|
||||
private final String type_shortURLs_i = "(?i)https?://[^/]+/i/[A-Za-z0-9\\-_]+";
|
||||
private final String type_yadi_sk_mail = "(?i)https?://[^/]+/mail/\\?hash=.+";
|
||||
private static final String JSON_TYPE_DIR = "dir";
|
||||
private static final Pattern type_docviewer = Pattern.compile("https?://[^/]+/\\?url=ya\\-disk\\-public%3A%2F%2F([^/\"\\&]+).*?", Pattern.CASE_INSENSITIVE);
|
||||
private final String type_primaryURLs = "(?i).+?public/?(\\?hash=.+|#.+)";
|
||||
private final String type_shortURLs_d = "(?i)https?://[^/]+/d/[A-Za-z0-9\\-_]+((/[^/]+){0,})";
|
||||
private final String type_shortURLs_i = "(?i)https?://[^/]+/i/[A-Za-z0-9\\-_]+";
|
||||
private final String type_yadi_sk_mail = "(?i)https?://[^/]+/mail/\\?hash=.+";
|
||||
private static final String JSON_TYPE_DIR = "dir";
|
||||
private DiskYandexNet hosterplugin = null;
|
||||
|
||||
/** Using API: https://tech.yandex.ru/disk/api/reference/public-docpage/ */
|
||||
@SuppressWarnings({ "deprecation" })
|
||||
public ArrayList<DownloadLink> decryptIt(CryptedLink param, ProgressController progress) throws Exception {
|
||||
public ArrayList<DownloadLink> decryptIt(final CryptedLink param, ProgressController progress) throws Exception {
|
||||
final Account account = AccountController.getInstance().getValidAccount(this.getHost());
|
||||
return decryptIt(param, account, true);
|
||||
}
|
||||
|
||||
public ArrayList<DownloadLink> decryptIt(final CryptedLink param, final Account account, final boolean allowPagination) throws Exception {
|
||||
br.setFollowRedirects(true);
|
||||
/* Load hosterplugin to use same browser headers/settings. */
|
||||
this.getNewPluginForHostInstance(this.getHost());
|
||||
String contenturl = param.getCryptedUrl();
|
||||
/* Do some URL corrections */
|
||||
if (param.getCryptedUrl().matches(type_docviewer)) {
|
||||
/* Documents in web view mode --> File-URLs! */
|
||||
/* First lets fix broken URLs by removing unneeded parameters ... */
|
||||
String tmp = param.getCryptedUrl();
|
||||
final String remove = new Regex(tmp, "(\\&[a-z0-9]+=.+)").getMatch(0);
|
||||
if (remove != null) {
|
||||
tmp = tmp.replace(remove, "");
|
||||
}
|
||||
String hash = new Regex(tmp, type_docviewer).getMatch(0);
|
||||
if (StringUtils.isEmpty(hash)) {
|
||||
hash = new Regex(tmp, "url=ya\\-disk\\-public%3A%2F%2F(.+)").getMatch(0);
|
||||
if (StringUtils.isEmpty(hash)) {
|
||||
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
|
||||
}
|
||||
}
|
||||
final Regex docviewer = new Regex(contenturl, type_docviewer);
|
||||
if (docviewer.patternFind()) {
|
||||
/* Documents in web view mode --> Change them to normal file-URLs! */
|
||||
final UrlQuery query = UrlQuery.parse(contenturl);
|
||||
final String param_url = query.get("url");
|
||||
final String hash = param_url.replace("ya-disk-public%3A%2F%2F", "");
|
||||
final String hashRoot = URLDecoder.decode(hash, "UTF-8");
|
||||
contenturl = generateContentURL(hashRoot);
|
||||
}
|
||||
/* Load hosterplugin to use same browser headers/settings. */
|
||||
hosterplugin = (DiskYandexNet) this.getNewPluginForHostInstance(this.getHost());
|
||||
/* Login whenever possible. Helps us get around anti bot captchas. */
|
||||
if (account != null) {
|
||||
hosterplugin.login(account, false);
|
||||
}
|
||||
/**
|
||||
* 2021-02-09: New: Prefer website if we do now know whether we got a file or a folder! API will fail in case it is a single file &&
|
||||
* 2021-02-09: New: Prefer website if we don't know whether we got a file or a folder! API will fail in case it is a single file &&
|
||||
* is currently quota-limited!
|
||||
*/
|
||||
if (StringUtils.isEmpty(this.getAdoptedCloudFolderStructure()) || StringUtils.isEmpty(getHashFromURL(contenturl))) {
|
||||
/*
|
||||
* Set password from previous CryptedLink e.g. password has been obtained when root folder was added so now we know it for all
|
||||
* subfolders.
|
||||
*/
|
||||
String passToken = null;
|
||||
final DownloadLink parent = param.getDownloadLink();
|
||||
if (parent != null) {
|
||||
/*
|
||||
* 2024-08-13: psp: Password protected links cannot be processed via API in JDownloader [yet]. Reason: I was unable to find out
|
||||
* which parameter the password needs to be sent as.
|
||||
*/
|
||||
passToken = parent.getStringProperty(DiskYandexNet.PROPERTY_PASSWORD_TOKEN);
|
||||
}
|
||||
if (StringUtils.isEmpty(this.getAdoptedCloudFolderStructure()) || StringUtils.isEmpty(getHashFromURL(contenturl)) || passToken != null) {
|
||||
logger.info("Using website crawler because we cannot know whether we got a single file- or a folder");
|
||||
return this.crawlFilesFoldersWebsite(param, contenturl);
|
||||
return this.crawlFilesFoldersWebsite(param, contenturl, allowPagination);
|
||||
} else {
|
||||
logger.info("Using API crawler");
|
||||
return this.crawlFilesFoldersAPI(param, contenturl);
|
||||
return this.crawlFilesFoldersAPI(param, contenturl, allowPagination);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<DownloadLink> crawlFilesFoldersWebsite(final CryptedLink param, final String contenturl) throws Exception {
|
||||
private ArrayList<DownloadLink> crawlFilesFoldersWebsite(final CryptedLink param, final String contenturl, final boolean allowPagination) throws Exception {
|
||||
final ArrayList<DownloadLink> ret = new ArrayList<DownloadLink>();
|
||||
String relativeDownloadPath = this.getAdoptedCloudFolderStructure();
|
||||
if (relativeDownloadPath == null) {
|
||||
relativeDownloadPath = "";
|
||||
}
|
||||
/*
|
||||
* Set password from previous CryptedLink e.g. password has been obtained when root folder was added so now we know it for all
|
||||
* subfolders.
|
||||
*/
|
||||
String passCode = null;
|
||||
String passToken = null;
|
||||
final DownloadLink parent = param.getDownloadLink();
|
||||
if (parent != null) {
|
||||
passToken = parent.getStringProperty(DiskYandexNet.PROPERTY_PASSWORD_TOKEN);
|
||||
passCode = parent.getDownloadPassword();
|
||||
if (passToken != null) {
|
||||
/*
|
||||
* If that token is still valid, it will grant us access to password protected folders without the need to send the password
|
||||
* again for each subfolder crawl process.
|
||||
*/
|
||||
setFolderPasswordTokenCookie(br, Browser.getHost(contenturl), passToken);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 2021-02-12: If a user adds an URL leading to only one file but this file is part of a folder, this crawler will crawl everything
|
||||
* from the root folder on. This is because the fiule could e.g. be at the end of a paginated folder -> Browser will do pagination
|
||||
* from the root folder on. This is because the file could e.g. be at the end of a paginated folder -> Browser will do pagination
|
||||
* until file is found but this takes too much time and effort for us so we'll just add everything. The user can then sort/find that
|
||||
* file in the LinkGrabber.
|
||||
*/
|
||||
br.getPage(contenturl);
|
||||
if (isOfflineWebsite(this.br)) {
|
||||
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
this.checkErrors(br);
|
||||
final String sk = DiskYandexNet.getSK(this.br);
|
||||
final String json = br.getRegex("<script type=\"application/json\"[^>]*id=\"store-prefetch\"[^>]*>(.*?)</script>").getMatch(0);
|
||||
Map<String, Object> map = restoreFromString(json, TypeRef.MAP);
|
||||
Map<String, Object> json_root = null;
|
||||
Map<String, Object> resources_map = null;
|
||||
String sk = null;
|
||||
boolean passwordSuccess = false;
|
||||
folderPasswordVerificationLoop: do {
|
||||
br.getPage(contenturl);
|
||||
if (isOfflineWebsite(this.br)) {
|
||||
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
this.hosterplugin.checkErrorsWebsite(br, parent, null);
|
||||
sk = DiskYandexNet.getSK(this.br);
|
||||
final String json = br.getRegex("<script type=\"application/json\"[^>]*id=\"store-prefetch\"[^>]*>(.*?)</script>").getMatch(0);
|
||||
if (json == null) {
|
||||
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
|
||||
}
|
||||
json_root = restoreFromString(json, TypeRef.MAP);
|
||||
resources_map = (Map<String, Object>) json_root.get("resources");
|
||||
final Map<String, Object> password_protected_map = (Map<String, Object>) resources_map.get("password-protected");
|
||||
if (password_protected_map == null) {
|
||||
/* No password needed or password has already been entered. */
|
||||
break folderPasswordVerificationLoop;
|
||||
} else if (passwordSuccess) {
|
||||
/* Correct password has already been entered but is needed again here -> Something went really wrong */
|
||||
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
|
||||
}
|
||||
/* Password protected folder */
|
||||
Map<String, Object> pwresp = null;
|
||||
pwloop: for (int i = 0; i <= 5; i++) {
|
||||
if (StringUtils.isEmpty(passCode) || i > 0) {
|
||||
/* Ask user for password */
|
||||
passCode = getUserInput("Password?", param);
|
||||
}
|
||||
final Map<String, Object> postData = new HashMap<String, Object>();
|
||||
postData.put("hash", password_protected_map.get("hash"));
|
||||
postData.put("password", passCode);
|
||||
postData.put("sk", sk);
|
||||
final PostRequest request = br.createJSonPostRequest("/public/api/check-password", postData);
|
||||
prepareJsonRequest(request, br);
|
||||
br.getPage(request);
|
||||
pwresp = hosterplugin.checkErrorsWebAPI(br, parent, null);
|
||||
final Object errorO = pwresp.get("error");
|
||||
if (errorO == null || Boolean.FALSE.equals(errorO)) {
|
||||
logger.info("Pwloop: " + i + " | Correct password: " + passCode);
|
||||
passwordSuccess = true;
|
||||
break pwloop;
|
||||
} else {
|
||||
/* {"error":true,"statusCode":403,"code":"HTTP_403","data":{"code":309,"title":"Symlink invalid password"}} */
|
||||
logger.info("Pwloop: " + i + " | Incorrect password: " + passCode);
|
||||
continue pwloop;
|
||||
}
|
||||
}
|
||||
if (!passwordSuccess) {
|
||||
throw new DecrypterException(DecrypterException.PASSWORD);
|
||||
}
|
||||
passToken = pwresp.get("token").toString();
|
||||
setFolderPasswordTokenCookie(br, br.getHost(), passToken);
|
||||
/* Continue so page gets reloaded so we can get the "json without folder-password-prompt". */
|
||||
logger.info("Performing page reload after successful password handling");
|
||||
continue;
|
||||
} while (true);
|
||||
final String authSk = PluginJSonUtils.getJson(this.br, "authSk");
|
||||
// final String rootResourceId = (String) map.get("rootResourceId");
|
||||
final String currentResourceId = (String) map.get("currentResourceId");
|
||||
Map<String, Object> entries = (Map<String, Object>) map.get("resources");
|
||||
final String currentResourceId = (String) json_root.get("currentResourceId");
|
||||
/*
|
||||
* First find the base folder name: If there are multiple items as part of a folder, the first item is kind of a dummy item
|
||||
* containing the name of the root folder.
|
||||
*/
|
||||
String hashMain = null;
|
||||
for (final String key : entries.keySet()) {
|
||||
final Map<String, Object> ressource = (Map<String, Object>) entries.get(key);
|
||||
for (final String key : resources_map.keySet()) {
|
||||
final Map<String, Object> ressource = (Map<String, Object>) resources_map.get(key);
|
||||
final String type = (String) ressource.get("type");
|
||||
if ("dir".equals(type) && ressource.get("parent") == null) {
|
||||
hashMain = (String) ressource.get("hash");
|
||||
@ -179,8 +268,8 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
}
|
||||
}
|
||||
String baseFolderName = null;
|
||||
for (final String key : entries.keySet()) {
|
||||
final Map<String, Object> ressource = (Map<String, Object>) entries.get(key);
|
||||
for (final String key : resources_map.keySet()) {
|
||||
final Map<String, Object> ressource = (Map<String, Object>) resources_map.get(key);
|
||||
final String type = (String) ressource.get("type");
|
||||
final String id = (String) ressource.get("id");
|
||||
if ("dir".equals(type) && StringUtils.equals(id, currentResourceId)) {
|
||||
@ -188,49 +277,48 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(baseFolderName)) {
|
||||
/* Fallback */
|
||||
baseFolderName = "unknown";
|
||||
}
|
||||
if (StringUtils.isEmpty(relativeDownloadPath)) {
|
||||
if (StringUtils.isEmpty(relativeDownloadPath) && baseFolderName != null) {
|
||||
/* First time crawl of a possible folder structure -> Define root dir name */
|
||||
relativeDownloadPath = baseFolderName;
|
||||
}
|
||||
final FilePackage fp = FilePackage.getInstance();
|
||||
fp.setName(baseFolderName);
|
||||
List<Object> ressources = new ArrayList<Object>();
|
||||
/* First collect map items in list because API will return list later! */
|
||||
for (final String key : entries.keySet()) {
|
||||
ressources.add(entries.get(key));
|
||||
FilePackage fp = null;
|
||||
if (relativeDownloadPath != null) {
|
||||
fp = FilePackage.getInstance();
|
||||
fp.setName(relativeDownloadPath);
|
||||
}
|
||||
List<Object> ressources_list = new ArrayList<Object>();
|
||||
/* First collect map items in list because API will return list later. */
|
||||
for (final String key : resources_map.keySet()) {
|
||||
ressources_list.add(resources_map.get(key));
|
||||
}
|
||||
final int maxItemsPerPage = 40;
|
||||
int page = 0;
|
||||
int page = 1;
|
||||
int offset = 0;
|
||||
do {
|
||||
logger.info("Crawling page: " + (page + 1));
|
||||
pagination: do {
|
||||
logger.info("Crawling page: " + page);
|
||||
boolean completed = false;
|
||||
for (final Object ressourceO : ressources) {
|
||||
for (final Object ressourceO : ressources_list) {
|
||||
final Map<String, Object> ressource = (Map<String, Object>) ressourceO;
|
||||
final String type = (String) ressource.get("type");
|
||||
final String name = (String) ressource.get("name");
|
||||
String hash = (String) ressource.get("hash");
|
||||
final String path = (String) ressource.get("path");
|
||||
final DownloadLink link;
|
||||
if (type.equalsIgnoreCase("dir")) {
|
||||
/* Folder */
|
||||
final List<Object> children = (List<Object>) ressource.get("children");
|
||||
if ((children != null && !children.isEmpty()) || path == null || StringUtils.equals(path, hashMain + ":")) {
|
||||
/* Skip dummy entries - also do not increase out offset value! */
|
||||
/* Skip dummy entries - also do not increase our offset value! */
|
||||
continue;
|
||||
}
|
||||
offset += 1;
|
||||
/* Subfolders go back into our decrypter! Path contains "<hash_long_decoded>:/path" */
|
||||
/* Subfolders go back into our crawler! Path contains "<hash_long_decoded>:/path" */
|
||||
final String folderlink = this.generateContentURL(path);
|
||||
final DownloadLink dl = createDownloadlink(folderlink);
|
||||
dl.setRelativeDownloadFolderPath(relativeDownloadPath + "/" + name);
|
||||
ret.add(dl);
|
||||
distribute(dl);
|
||||
link = createDownloadlink(folderlink);
|
||||
if (relativeDownloadPath != null) {
|
||||
link.setRelativeDownloadFolderPath(relativeDownloadPath + "/" + name);
|
||||
}
|
||||
} else {
|
||||
offset += 1;
|
||||
// final Map<String, Object> ressourceMeta = (Map<String, Object>) ressource.get("meta");
|
||||
/* File */
|
||||
// final boolean antiFileSharing = ((Boolean) ressourceMeta.get("antiFileSharing")).booleanValue();
|
||||
final String resource_id = (String) ressource.get("id");
|
||||
if (StringUtils.isEmpty(hash) && !StringUtils.isEmpty(path) && path.contains(":/")) {
|
||||
@ -240,8 +328,8 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
if (StringUtils.isEmpty(name) || StringUtils.isEmpty(hash) || StringUtils.isEmpty(resource_id)) {
|
||||
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
|
||||
}
|
||||
final DownloadLink dl = createDownloadlink("http://yandexdecrypted.net/" + System.currentTimeMillis() + new Random().nextInt(10000000));
|
||||
parseFilePropertiesWebsite(dl, ressource);
|
||||
link = createDownloadlink("http://yandexdecrypted.net/" + System.currentTimeMillis() + new Random().nextInt(10000000));
|
||||
parseFilePropertiesWebsite(link, ressource);
|
||||
/*
|
||||
* We want the user to have an URL which he can open via browser and it does not only open up the root of the folder but
|
||||
* the exact file he wants to have!
|
||||
@ -253,75 +341,91 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
} else {
|
||||
urlContent = "https://disk.yandex.com/public?hash=" + URLEncode.encodeURIComponent(hash);
|
||||
}
|
||||
if (!StringUtils.isEmpty(path)) {
|
||||
/* Path contains hash + path */
|
||||
dl.setProperty(DiskYandexNet.PROPERTY_HASH, path);
|
||||
} else {
|
||||
/* Hash only */
|
||||
dl.setProperty(DiskYandexNet.PROPERTY_HASH, hash);
|
||||
link.setProperty("mainlink", urlContent);
|
||||
link.setContentUrl(urlContent);
|
||||
if (fp != null) {
|
||||
link._setFilePackage(fp);
|
||||
}
|
||||
dl.setProperty("mainlink", urlContent);
|
||||
dl.setContentUrl(urlContent);
|
||||
dl.setProperty(DiskYandexNet.PROPERTY_INTERNAL_FUID, resource_id);
|
||||
if (ressources.size() > 1) {
|
||||
if (StringUtils.isNotEmpty(relativeDownloadPath)) {
|
||||
dl.setRelativeDownloadFolderPath(relativeDownloadPath);
|
||||
}
|
||||
dl._setFilePackage(fp);
|
||||
if (relativeDownloadPath != null) {
|
||||
link.setRelativeDownloadFolderPath(relativeDownloadPath);
|
||||
}
|
||||
ret.add(dl);
|
||||
distribute(dl);
|
||||
}
|
||||
if (!StringUtils.isEmpty(path)) {
|
||||
/* Path contains hash + path */
|
||||
link.setProperty(DiskYandexNet.PROPERTY_HASH, path);
|
||||
} else {
|
||||
/* Hash only */
|
||||
link.setProperty(DiskYandexNet.PROPERTY_HASH, hash);
|
||||
}
|
||||
if (passCode != null && passToken != null) {
|
||||
link.setPasswordProtected(true);
|
||||
link.setDownloadPassword(passCode);
|
||||
link.setProperty(DiskYandexNet.PROPERTY_PASSWORD_TOKEN, passToken);
|
||||
}
|
||||
if (authSk != null) {
|
||||
link.setProperty(DiskYandexNet.PROPERTY_LAST_AUTH_SK, authSk);
|
||||
}
|
||||
ret.add(link);
|
||||
distribute(link);
|
||||
offset += 1;
|
||||
}
|
||||
if (page > 0) {
|
||||
completed = Boolean.TRUE.equals(entries.get("completed"));
|
||||
if (page > 1) {
|
||||
completed = Boolean.TRUE.equals(resources_map.get("completed"));
|
||||
} else {
|
||||
if (!completed) {
|
||||
completed = ressources.size() < maxItemsPerPage;
|
||||
completed = ressources_list.size() < maxItemsPerPage;
|
||||
}
|
||||
}
|
||||
logger.info("Crawled page: " + page + " | Found items so far: " + ret.size());
|
||||
if (completed) {
|
||||
logger.info("Stopping because: Reached last page");
|
||||
break;
|
||||
break pagination;
|
||||
} else if (StringUtils.isEmpty(sk)) {
|
||||
/* This should never happen */
|
||||
logger.warning("Pagination failure: sk missing");
|
||||
break;
|
||||
break pagination;
|
||||
} else if (StringUtils.isEmpty(hashMain)) {
|
||||
/* This should never happen */
|
||||
logger.warning("Pagination failure: hashMain missing");
|
||||
break;
|
||||
break pagination;
|
||||
} else if (!allowPagination) {
|
||||
logger.info("Stopping because: Pagination is not allowed");
|
||||
break pagination;
|
||||
} else if (this.isAbort()) {
|
||||
logger.info("Stopping because: Aborted by user");
|
||||
break pagination;
|
||||
}
|
||||
// final Map<String, Object> paginationMap = new HashMap<String, Object>();
|
||||
// final Map<String, Object> paginationOptions = new HashMap<String, Object>();
|
||||
// paginationOptions.put("hasExperimentVideoWithoutPreview", true);
|
||||
// paginationMap.put("hash", hash_long_decoded);
|
||||
// paginationMap.put("offset", offset);
|
||||
// paginationMap.put("withSizes", true);
|
||||
// paginationMap.put("sk", sk);
|
||||
// paginationMap.put("options", paginationOptions);
|
||||
PostRequest request = br.createPostRequest("/public/api/fetch-list", (UrlQuery) null, null);
|
||||
request.getHeaders().put("X-Requested-With", "XMLHttpRequest");
|
||||
// request.getHeaders().put("X-Retpath-Y", param.getCryptedUrl());
|
||||
request.getHeaders().put("Accept", "*/*");
|
||||
request.getHeaders().put("Origin", "https://" + br._getURL().getHost());
|
||||
request.setContentType("text/plain");
|
||||
/* Continue to next page */
|
||||
final PostRequest request = br.createPostRequest("/public/api/fetch-list", (UrlQuery) null, null);
|
||||
prepareJsonRequest(request, br);
|
||||
request.setPostDataString("%7B%22hash%22%3A%22" + Encoding.urlEncode(hashMain) + "%3A%22%2C%22offset%22%3A" + offset + "%2C%22withSizes%22%3Atrue%2C%22sk%22%3A%22" + sk + "%22%2C%22options%22%3A%7B%22hasExperimentVideoWithoutPreview%22%3Atrue%7D%7D");
|
||||
br.getPage(request);
|
||||
this.checkErrors(br);
|
||||
entries = restoreFromString(br.getRequest().getHtmlCode(), TypeRef.MAP);
|
||||
ressources = (List<Object>) entries.get("resources");
|
||||
if (ressources == null) {
|
||||
resources_map = hosterplugin.checkErrorsWebAPI(br, parent, null);
|
||||
ressources_list = (List<Object>) resources_map.get("resources");
|
||||
if (ressources_list == null) {
|
||||
/* This should never happen */
|
||||
logger.warning("Pagination failure: ressources missing");
|
||||
break;
|
||||
break pagination;
|
||||
}
|
||||
page += 1;
|
||||
continue pagination;
|
||||
} while (!this.isAbort());
|
||||
return ret;
|
||||
}
|
||||
|
||||
private ArrayList<DownloadLink> crawlFilesFoldersAPI(final CryptedLink param2, final String contenturl) throws Exception {
|
||||
public static void setFolderPasswordTokenCookie(final Browser br, final String domain, final String token) {
|
||||
br.setCookie(domain, "passToken", token);
|
||||
}
|
||||
|
||||
private void prepareJsonRequest(final PostRequest request, final Browser originbr) {
|
||||
request.getHeaders().put("X-Requested-With", "XMLHttpRequest");
|
||||
// request.getHeaders().put("X-Retpath-Y", param.getCryptedUrl());
|
||||
request.getHeaders().put("Accept", "*/*");
|
||||
request.getHeaders().put("Origin", "https://" + originbr._getURL().getHost());
|
||||
request.setContentType("text/plain");
|
||||
}
|
||||
|
||||
private ArrayList<DownloadLink> crawlFilesFoldersAPI(final CryptedLink param, final String contenturl, final boolean allowPagination) throws Exception {
|
||||
final ArrayList<DownloadLink> ret = new ArrayList<DownloadLink>();
|
||||
String relativeDownloadPath = this.getAdoptedCloudFolderStructure();
|
||||
if (relativeDownloadPath == null) {
|
||||
@ -332,7 +436,7 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
hashWithPath = getHashFromURL(contenturl);
|
||||
} else if (contenturl.matches(type_shortURLs_d) || contenturl.matches(type_shortURLs_i)) {
|
||||
br.getPage(contenturl);
|
||||
this.checkErrors(br);
|
||||
this.hosterplugin.checkErrorsWebsite(br, null, null);
|
||||
if (isOfflineWebsite(this.br)) {
|
||||
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
@ -368,14 +472,18 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
}
|
||||
this.br.getHeaders().put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||
this.br.getHeaders().put("X-Requested-With", "XMLHttpRequest");
|
||||
short offset = 0;
|
||||
int offset = 0;
|
||||
final short entries_per_request = 200;
|
||||
int totalNumberofEntries = 0;
|
||||
final FilePackage fp = FilePackage.getInstance();
|
||||
do {
|
||||
br.getPage(DiskYandexNet.APIV1_BASE + "/disk/public/resources?limit=" + entries_per_request + "&offset=" + offset + "&public_key=" + URLEncode.encodeURIComponent(hashWithoutPath) + "&path=" + URLEncode.encodeURIComponent(internalPath));
|
||||
this.checkErrors(br);
|
||||
Map<String, Object> entries = restoreFromString(br.getRequest().getHtmlCode(), TypeRef.MAP);
|
||||
final UrlQuery query = new UrlQuery();
|
||||
query.add("limit", Integer.toString(entries_per_request));
|
||||
query.add("public_key", URLEncode.encodeURIComponent(hashWithoutPath));
|
||||
query.add("path", URLEncode.encodeURIComponent(internalPath));
|
||||
pagination: do {
|
||||
query.addAndReplace("offset", Integer.toString(offset));
|
||||
br.getPage(DiskYandexNet.APIV1_BASE + "/disk/public/resources?" + query.toString());
|
||||
Map<String, Object> entries = this.hosterplugin.checkErrorsWebAPI(br, null, null);
|
||||
/*
|
||||
* 2021-01-19:
|
||||
* {"message":"Не удалось найти запрошенный ресурс.","description":"Resource not found.","error":"DiskNotFoundError"}
|
||||
@ -386,16 +494,16 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
final String type_main = (String) entries.get("type");
|
||||
if (!type_main.equals(JSON_TYPE_DIR)) {
|
||||
/* We only have a single file --> Add to downloadliste / host plugin */
|
||||
final DownloadLink dl = parseSingleFileAPI(entries);
|
||||
final DownloadLink link = parseSingleFileAPI(entries);
|
||||
if (StringUtils.isNotEmpty(relativeDownloadPath)) {
|
||||
dl.setRelativeDownloadFolderPath(relativeDownloadPath);
|
||||
link.setRelativeDownloadFolderPath(relativeDownloadPath);
|
||||
}
|
||||
dl._setFilePackage(fp);
|
||||
ret.add(dl);
|
||||
link._setFilePackage(fp);
|
||||
ret.add(link);
|
||||
return ret;
|
||||
}
|
||||
final String walk_string = "_embedded/items";
|
||||
final List<Object> resource_data_list = (List) JavaScriptEngineFactory.walkJson(entries, walk_string);
|
||||
final List<Map<String, Object>> resource_data_list = (List<Map<String, Object>>) JavaScriptEngineFactory.walkJson(entries, walk_string);
|
||||
if (offset == 0) {
|
||||
/* Set total number of entries on first loop. */
|
||||
final Map<String, Object> itemInfo = (Map<String, Object>) entries.get("_embedded");
|
||||
@ -405,11 +513,11 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
baseFolderName = hashWithPath;
|
||||
}
|
||||
totalNumberofEntries = ((Number) itemInfo.get("total")).intValue();
|
||||
fp.setName(baseFolderName);
|
||||
if (StringUtils.isEmpty(relativeDownloadPath)) {
|
||||
/* First time crawl of a possible folder structure -> Define root dir name */
|
||||
relativeDownloadPath = baseFolderName;
|
||||
}
|
||||
fp.setName(relativeDownloadPath);
|
||||
if (totalNumberofEntries == 0) {
|
||||
if (!StringUtils.isEmpty(relativeDownloadPath)) {
|
||||
throw new DecrypterRetryException(RetryReason.EMPTY_FOLDER, hashWithoutPath + "_" + relativeDownloadPath);
|
||||
@ -418,62 +526,58 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (final Object list_object : resource_data_list) {
|
||||
entries = (Map<String, Object>) list_object;
|
||||
final String type = (String) entries.get("type");
|
||||
final String hash = (String) entries.get("public_key");
|
||||
final String path = (String) entries.get("path");
|
||||
final String name = (String) entries.get("name");
|
||||
for (final Map<String, Object> resource_data : resource_data_list) {
|
||||
final String type = (String) resource_data.get("type");
|
||||
final String hash = (String) resource_data.get("public_key");
|
||||
final String path = (String) resource_data.get("path");
|
||||
final String name = (String) resource_data.get("name");
|
||||
if (StringUtils.isEmpty(type_main) || StringUtils.isEmpty(path) || StringUtils.isEmpty(name)) {
|
||||
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
|
||||
}
|
||||
final DownloadLink link;
|
||||
if (type.equals(JSON_TYPE_DIR)) {
|
||||
/* Subfolders go back into our decrypter! */
|
||||
/* Folder */
|
||||
final String folderlink = "https://disk.yandex.com/public?hash=" + URLEncode.encodeURIComponent(hash + ":" + path);
|
||||
final DownloadLink dl = createDownloadlink(folderlink);
|
||||
dl.setRelativeDownloadFolderPath(relativeDownloadPath + "/" + name);
|
||||
ret.add(dl);
|
||||
} else {
|
||||
final DownloadLink dl = parseSingleFileAPI(entries);
|
||||
if (StringUtils.isNotEmpty(relativeDownloadPath)) {
|
||||
dl.setRelativeDownloadFolderPath(relativeDownloadPath);
|
||||
link = createDownloadlink(folderlink);
|
||||
if (!StringUtils.isEmpty(relativeDownloadPath)) {
|
||||
link.setRelativeDownloadFolderPath(relativeDownloadPath + "/" + name);
|
||||
}
|
||||
dl._setFilePackage(fp);
|
||||
ret.add(dl);
|
||||
distribute(dl);
|
||||
} else {
|
||||
/* File */
|
||||
link = parseSingleFileAPI(resource_data);
|
||||
if (!StringUtils.isEmpty(relativeDownloadPath)) {
|
||||
link.setRelativeDownloadFolderPath(relativeDownloadPath);
|
||||
}
|
||||
link._setFilePackage(fp);
|
||||
}
|
||||
ret.add(link);
|
||||
distribute(link);
|
||||
offset++;
|
||||
}
|
||||
if (resource_data_list.size() < entries_per_request) {
|
||||
/* Fail safe */
|
||||
logger.info("Stopping because current page contains less items than max. items allowed --> Should be the last page");
|
||||
break;
|
||||
logger.info("Stopping because current page contains less items than max items per page --> Should be the last page");
|
||||
break pagination;
|
||||
} else if (offset >= totalNumberofEntries) {
|
||||
logger.info("Stopping because: Reached end");
|
||||
break;
|
||||
break pagination;
|
||||
} else if (!allowPagination) {
|
||||
logger.info("Stopping because: Pagination is not allowed");
|
||||
break pagination;
|
||||
}
|
||||
} while (!this.isAbort());
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void checkErrors(final Browser br) throws PluginException, DecrypterRetryException {
|
||||
if (br.getHttpConnection().getResponseCode() == 404) {
|
||||
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
|
||||
} else if (br.getURL().contains("/showcaptcha")) {
|
||||
throw new DecrypterRetryException(RetryReason.HOST_RATE_LIMIT);
|
||||
}
|
||||
}
|
||||
|
||||
private DownloadLink parseSingleFileAPI(final Map<String, Object> entries) throws Exception {
|
||||
final String hash = (String) entries.get("public_key");
|
||||
final String path = (String) entries.get("path");
|
||||
final String name = (String) entries.get("name");
|
||||
final String resource_id = (String) entries.get("resource_id");
|
||||
if (StringUtils.isEmpty(name) || StringUtils.isEmpty(path) || StringUtils.isEmpty(hash) || StringUtils.isEmpty(resource_id)) {
|
||||
if (StringUtils.isEmpty(name) || StringUtils.isEmpty(path) || StringUtils.isEmpty(hash)) {
|
||||
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
|
||||
}
|
||||
final DownloadLink dl = createDownloadlink("http://yandexdecrypted.net/" + System.currentTimeMillis() + new Random().nextInt(10000000));
|
||||
parseFilePropertiesAPI(dl, entries);
|
||||
final DownloadLink link = createDownloadlink("http://yandexdecrypted.net/" + System.currentTimeMillis() + new Random().nextInt(10000000));
|
||||
parseFilePropertiesAPI(link, entries);
|
||||
final String hashFull = hash + ":" + path;
|
||||
final String urlContent = generateContentURL(hashFull);
|
||||
/**
|
||||
@ -492,14 +596,13 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
// */
|
||||
// urlUser = urlContent;
|
||||
// }
|
||||
dl.setProperty("mainlink", generateContentURL(hashFull));
|
||||
dl.setContentUrl(urlContent);
|
||||
dl.setProperty(DiskYandexNet.PROPERTY_INTERNAL_FUID, resource_id);
|
||||
return dl;
|
||||
link.setProperty("mainlink", generateContentURL(hashFull));
|
||||
link.setContentUrl(urlContent);
|
||||
return link;
|
||||
}
|
||||
|
||||
private String generateContentURL(final String hash) {
|
||||
return "https://disk.yandex.com/public/?hash=" + URLEncode.encodeURIComponent(hash);
|
||||
private String generateContentURL(final String hashWithPath) {
|
||||
return "https://disk.yandex.com/public/?hash=" + URLEncode.encodeURIComponent(hashWithPath);
|
||||
}
|
||||
|
||||
public static String getPathFromHash(final String hash) {
|
||||
@ -527,25 +630,16 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
return br;
|
||||
}
|
||||
|
||||
public static Map<String, Object> findModel(final List<Object> modelObjects, final String targetModelName) {
|
||||
Map<String, Object> entries = null;
|
||||
boolean foundResourceModel = false;
|
||||
for (final Object modelo : modelObjects) {
|
||||
entries = (Map<String, Object>) modelo;
|
||||
final String model = (String) entries.get("model");
|
||||
if (targetModelName.equalsIgnoreCase(model)) {
|
||||
foundResourceModel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundResourceModel) {
|
||||
return null;
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
public static boolean isOfflineWebsite(final Browser br) {
|
||||
return br.containsHTML("class=\"not\\-found\\-public__caption\"|class=\"error__icon error__icon_blocked\"|_file\\-blocked\"|A complaint was received regarding this file|>File blocked<") || br.getHttpConnection().getResponseCode() == 404 || br.getHttpConnection().getResponseCode() == 500;
|
||||
if (br.containsHTML("class=\"not\\-found\\-public__caption\"|class=\"error__icon error__icon_blocked\"|_file\\-blocked\"|A complaint was received regarding this file|>\\s*File blocked\\s*<")) {
|
||||
return true;
|
||||
} else if (br.getHttpConnection().getResponseCode() == 404) {
|
||||
return true;
|
||||
} else if (br.getHttpConnection().getResponseCode() == 500) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private String getHashFromURL(final String url) throws UnsupportedEncodingException, MalformedURLException {
|
||||
@ -557,13 +651,13 @@ public class DiskYandexNetFolder extends PluginForDecrypt {
|
||||
}
|
||||
}
|
||||
|
||||
private void parseFilePropertiesAPI(final DownloadLink dl, final Map<String, Object> entries) throws Exception {
|
||||
final AvailableStatus status = DiskYandexNet.parseInformationAPIAvailablecheckFiles(this, dl, null, entries);
|
||||
dl.setAvailableStatus(status);
|
||||
private void parseFilePropertiesAPI(final DownloadLink link, final Map<String, Object> entries) throws Exception {
|
||||
final AvailableStatus status = DiskYandexNet.parseInformationAPIAvailablecheckFiles(this, link, null, entries);
|
||||
link.setAvailableStatus(status);
|
||||
}
|
||||
|
||||
private void parseFilePropertiesWebsite(final DownloadLink dl, final Map<String, Object> entries) throws Exception {
|
||||
final AvailableStatus status = DiskYandexNet.parseInformationWebsiteAvailablecheckFiles(this, dl, entries);
|
||||
dl.setAvailableStatus(status);
|
||||
private void parseFilePropertiesWebsite(final DownloadLink link, final Map<String, Object> entries) throws Exception {
|
||||
final AvailableStatus status = DiskYandexNet.parseInformationWebsiteAvailablecheckFiles(this, link, entries);
|
||||
link.setAvailableStatus(status);
|
||||
}
|
||||
}
|
||||
|
@ -197,18 +197,18 @@ public class FaceBookComGallery extends PluginForDecrypt {
|
||||
}
|
||||
/* Do some minor corrections of added link. */
|
||||
/* Remove m.facebook.com as our crawler can't cope with those (old?) facebook website versions for mobile devices. */
|
||||
String url = param.getCryptedUrl().replaceFirst("(?i)http://", "https://").replace("https://m.", "https://www.");
|
||||
final String videoIDFRomEmbedURL = new Regex(url, "(?i)https?://[^/]+/video/embed\\?video_id=(\\d+)").getMatch(0);
|
||||
String addedurl = param.getCryptedUrl().replaceFirst("(?i)http://", "https://").replace("https://m.", "https://www.");
|
||||
final String videoIDFRomEmbedURL = new Regex(addedurl, "(?i)https?://[^/]+/video/embed\\?video_id=(\\d+)").getMatch(0);
|
||||
// final String mobileSubdomain = new Regex(url, "(?i)https?:/(m\\.[^/]+)/.+").getMatch(0);
|
||||
if (videoIDFRomEmbedURL != null) {
|
||||
/* Small workaround for embedded videourls */
|
||||
url = "https://www." + this.getHost() + "/watch/?v=" + videoIDFRomEmbedURL;
|
||||
addedurl = "https://www." + this.getHost() + "/watch/?v=" + videoIDFRomEmbedURL;
|
||||
}
|
||||
// if (mobileSubdomain != null) {
|
||||
// /* Remove mobile sobdomain */
|
||||
// url = url.replaceFirst(Pattern.quote(mobileSubdomain), this.getHost());
|
||||
// }
|
||||
br.getPage(url);
|
||||
br.getPage(addedurl);
|
||||
if (br.getHttpConnection().getResponseCode() == 404) {
|
||||
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
@ -291,11 +291,11 @@ public class FaceBookComGallery extends PluginForDecrypt {
|
||||
}
|
||||
if (FaceBookComVideos.isVideo(result)) {
|
||||
videoPackages.put(contentID, contentIDPackages.get(contentID));
|
||||
if (url.contains(contentID)) {
|
||||
if (addedurl.contains(contentID) || br.getURL().contains(contentID)) {
|
||||
contentIDOfSingleDesiredVideo = contentID;
|
||||
}
|
||||
} else if (FaceBookComVideos.isPhoto(result)) {
|
||||
if (url.contains(contentID)) {
|
||||
if (addedurl.contains(contentID) || br.getURL().contains(contentID)) {
|
||||
contentIDOfSingleDesiredPhoto = contentID;
|
||||
singleDesiredPhoto = result;
|
||||
}
|
||||
@ -362,6 +362,7 @@ public class FaceBookComGallery extends PluginForDecrypt {
|
||||
}
|
||||
ret.clear();
|
||||
ret.addAll(resultsForOneDesiredVideo);
|
||||
/* Do not return here since filenames will be set down below! */
|
||||
}
|
||||
if (singleDesiredPhoto != null) {
|
||||
/* User wants single photo -> Try to find more metadata e.g. name of the uploader */
|
||||
@ -393,30 +394,32 @@ public class FaceBookComGallery extends PluginForDecrypt {
|
||||
for (final DownloadLink result : ret) {
|
||||
FaceBookComVideos.setFilename(result);
|
||||
final String videoID = result.getStringProperty(FaceBookComVideos.PROPERTY_CONTENT_ID);
|
||||
if (videoID != null) {
|
||||
final String description = result.getStringProperty(FaceBookComVideos.PROPERTY_DESCRIPTION);
|
||||
FilePackage fp = packages.get(videoID);
|
||||
if (fp == null) {
|
||||
fp = FilePackage.getInstance();
|
||||
final String title = result.getStringProperty(FaceBookComVideos.PROPERTY_TITLE);
|
||||
final String uploaderNameForPackage = FaceBookComVideos.getUploaderNameAny(result);
|
||||
if (uploaderNameForPackage != null && title != null) {
|
||||
fp.setName(uploaderNameForPackage + " - " + title + " - " + videoID);
|
||||
} else if (uploaderNameForPackage != null) {
|
||||
fp.setName(uploaderNameForPackage + " - " + videoID);
|
||||
} else if (title != null) {
|
||||
fp.setName(title + " - " + videoID);
|
||||
} else {
|
||||
fp.setName(videoID);
|
||||
}
|
||||
if (!StringUtils.isEmpty(description)) {
|
||||
fp.setComment(description);
|
||||
}
|
||||
packages.put(videoID, fp);
|
||||
}
|
||||
result._setFilePackage(fp);
|
||||
result.setContainerUrl(br.getURL());
|
||||
if (videoID == null) {
|
||||
/* Other/external item */
|
||||
continue;
|
||||
}
|
||||
final String description = result.getStringProperty(FaceBookComVideos.PROPERTY_DESCRIPTION);
|
||||
FilePackage fp = packages.get(videoID);
|
||||
if (fp == null) {
|
||||
fp = FilePackage.getInstance();
|
||||
final String title = result.getStringProperty(FaceBookComVideos.PROPERTY_TITLE);
|
||||
final String uploaderNameForPackage = FaceBookComVideos.getUploaderNameAny(result);
|
||||
if (uploaderNameForPackage != null && title != null) {
|
||||
fp.setName(uploaderNameForPackage + " - " + title + " - " + videoID);
|
||||
} else if (uploaderNameForPackage != null) {
|
||||
fp.setName(uploaderNameForPackage + " - " + videoID);
|
||||
} else if (title != null) {
|
||||
fp.setName(title + " - " + videoID);
|
||||
} else {
|
||||
fp.setName(videoID);
|
||||
}
|
||||
if (!StringUtils.isEmpty(description)) {
|
||||
fp.setComment(description);
|
||||
}
|
||||
packages.put(videoID, fp);
|
||||
}
|
||||
result._setFilePackage(fp);
|
||||
result.setContainerUrl(br.getURL());
|
||||
}
|
||||
if (ret.isEmpty()) {
|
||||
/*
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -84,7 +84,7 @@ public class YandexAlbum extends PluginForHost {
|
||||
}
|
||||
/* Find json object for current link ... */
|
||||
final List<Object> modelObjects = (List<Object>) JavaScriptEngineFactory.jsonToJavaObject(jd.plugins.decrypter.DiskYandexNetFolder.regExJSON(this.br));
|
||||
Map<String, Object> entries = jd.plugins.decrypter.DiskYandexNetFolder.findModel(modelObjects, "resources");
|
||||
Map<String, Object> entries = findModel(modelObjects, "resources");
|
||||
if (entries == null) {
|
||||
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
|
||||
}
|
||||
@ -108,6 +108,23 @@ public class YandexAlbum extends PluginForHost {
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, Object> findModel(final List<Object> modelObjects, final String targetModelName) {
|
||||
Map<String, Object> entries = null;
|
||||
boolean foundResourceModel = false;
|
||||
for (final Object modelo : modelObjects) {
|
||||
entries = (Map<String, Object>) modelo;
|
||||
final String model = (String) entries.get("model");
|
||||
if (targetModelName.equalsIgnoreCase(model)) {
|
||||
foundResourceModel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundResourceModel) {
|
||||
return null;
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
/** Parses file info for photo/video (ALBUM) urls e.g. /album/blabla:5fffffce1939c0c46ffffffe */
|
||||
public static AvailableStatus parseInformationAPIAvailablecheckAlbum(final Plugin plugin, final DownloadLink dl, final Map<String, Object> entries) throws Exception {
|
||||
Map<String, Object> entriesMeta = (Map<String, Object>) entries.get("meta");
|
||||
|
Loading…
Reference in New Issue
Block a user