*General*

- PluginForHost: enoughTrafficFor: added IDE only code for special multihost traffic calculation
- ZeveraCore: setVerifiedFilesize
- AccountTooltip: getDomainInfos early return and set domains with subdomain
- DomainInfo: added ability to allow/set domain with subdomain for e.g. drive.google.com and mh.takefile.link (at this moment such domains would just be displayed twice in list of supported multihosts which is just wrong)
- NewRuleAction: refactored to early return, allow subdomains refs #90321

*Plugins: Fixes/Changes/Maintenance*
- BooruOrgCrawler: added safebooruorg and updated pattern RE forum 90201
- BitchuteComChannel: fixed and added GEO-blocked errorhandling RE forum 88455
- MixCloudComCrawler: set estimated filesize
- MixCloudCom: minor changes

git-svn-id: svn://svn.jdownloader.org/jdownloader/trunk@49846 ebf7c1c2-ba36-0410-9fe8-c592906822b4

Former-commit-id: efa796b87da86d868314e7eeb861b5c7ee3c6feb
This commit is contained in:
psp 2024-09-24 10:27:48 +00:00
parent eca4d1b14f
commit 509baa63a4
13 changed files with 276 additions and 231 deletions

View File

@ -56,7 +56,7 @@ public class AccountCache implements Iterable<CachedAccount> {
}
this.plugin = plugin;
this.host = host;
pluginDomainInfo = plugin != null ? DomainInfo.getInstance(plugin.getHost()) : null;
pluginDomainInfo = plugin != null ? DomainInfo.getInstance(plugin.getHost(), true) : null;
}
public final Account getAccount() {

View File

@ -138,26 +138,29 @@ public class AccountTooltip extends PanelToolTip {
return super.getPreferredSize();
}
private List<DomainInfo> getDomainInfos(AccountServiceCollection accountCollection) {
HashSet<DomainInfo> domains = new HashSet<DomainInfo>();
for (Account acc : accountCollection) {
AccountInfo ai = acc.getAccountInfo();
if (ai != null) {
final List<String> supported = ai.getMultiHostSupport();
if (supported != null) {
/*
* synchronized on list because plugins can change the list in runtime
*/
for (String sup : supported) {
LazyHostPlugin plg = HostPluginController.getInstance().get(sup);
if (plg != null) {
domains.add(DomainInfo.getInstance(plg.getHost()));
}
}
private List<DomainInfo> getDomainInfos(final AccountServiceCollection accountCollection) {
final HashSet<DomainInfo> domains = new HashSet<DomainInfo>();
for (final Account acc : accountCollection) {
final AccountInfo ai = acc.getAccountInfo();
if (ai == null) {
continue;
}
final List<String> supported = ai.getMultiHostSupport();
if (supported == null) {
continue;
}
/*
* synchronized on list because plugins can change the list in runtime
*/
for (final String sup : supported) {
final LazyHostPlugin plg = HostPluginController.getInstance().get(sup);
if (plg == null) {
continue;
}
domains.add(DomainInfo.getInstance(plg.getHost(), true));
}
}
ArrayList<DomainInfo> ret = new ArrayList<DomainInfo>(domains);
final ArrayList<DomainInfo> ret = new ArrayList<DomainInfo>(domains);
Collections.sort(ret, new Comparator<DomainInfo>() {
@Override
public int compare(DomainInfo o1, DomainInfo o2) {

View File

@ -13,7 +13,6 @@
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package jd.gui.swing.jdgui.components.premiumbar;
import java.awt.HeadlessException;
@ -34,19 +33,6 @@ import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import jd.SecondLevelLaunch;
import jd.controlling.AccountController;
import jd.controlling.AccountControllerEvent;
import jd.controlling.AccountControllerListener;
import jd.gui.swing.dialog.AddAccountDialog;
import jd.gui.swing.jdgui.JDGui;
import jd.gui.swing.jdgui.views.settings.ConfigurationView;
import jd.gui.swing.jdgui.views.settings.panels.accountmanager.AccountManagerSettings;
import jd.plugins.Account;
import jd.plugins.AccountInfo;
import jd.plugins.PluginForHost;
import net.miginfocom.swing.MigLayout;
import org.appwork.scheduler.DelayedRunnable;
import org.appwork.storage.config.JsonConfig;
import org.appwork.storage.config.ValidationException;
@ -69,12 +55,22 @@ import org.jdownloader.settings.GraphicalUserInterfaceSettings;
import org.jdownloader.settings.GraphicalUserInterfaceSettings.PremiumStatusBarDisplay;
import org.jdownloader.settings.staticreferences.CFG_GUI;
import jd.SecondLevelLaunch;
import jd.controlling.AccountController;
import jd.controlling.AccountControllerEvent;
import jd.controlling.AccountControllerListener;
import jd.gui.swing.dialog.AddAccountDialog;
import jd.gui.swing.jdgui.JDGui;
import jd.gui.swing.jdgui.views.settings.ConfigurationView;
import jd.gui.swing.jdgui.views.settings.panels.accountmanager.AccountManagerSettings;
import jd.plugins.Account;
import jd.plugins.AccountInfo;
import jd.plugins.PluginForHost;
import net.miginfocom.swing.MigLayout;
public class ServicePanel extends JPanel implements MouseListener, AccountTooltipOwner {
private static final long serialVersionUID = 7290466989514173719L;
private DelayedRunnable redrawTimer;
private final CopyOnWriteArrayList<ServicePanelExtender> extender;
private static ServicePanel INSTANCE = new ServicePanel();
static {
@ -82,7 +78,7 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
throw new HeadlessException();
}
}
private AtomicBoolean redrawing = new AtomicBoolean(false);
private AtomicBoolean redrawing = new AtomicBoolean(false);
public static ServicePanel getInstance() {
return INSTANCE;
@ -110,13 +106,10 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
private ServicePanel() {
super(new MigLayout("ins 0 2 0", "0[]0[]0[]0[]0", "0[]0"));
extender = new CopyOnWriteArrayList<ServicePanelExtender>();
this.setOpaque(false);
final ScheduledExecutorService scheduler = DelayedRunnable.getNewScheduledExecutorService();
redrawTimer = new DelayedRunnable(scheduler, 1000, 5000) {
@Override
public String getID() {
return "PremiumStatusRedraw";
@ -124,15 +117,11 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
@Override
public void delayedrun() {
redraw();
}
};
redraw();
CFG_GUI.PREMIUM_STATUS_BAR_DISPLAY.getEventSender().addListener(new GenericConfigEventListener<Enum>() {
@Override
public void onConfigValidatorError(KeyHandler<Enum> keyHandler, Enum invalidValue, ValidationException validateException) {
}
@ -143,7 +132,6 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
}
});
org.jdownloader.settings.staticreferences.CFG_GENERAL.USE_AVAILABLE_ACCOUNTS.getEventSender().addListener(new GenericConfigEventListener<Boolean>() {
public void onConfigValueModified(KeyHandler<Boolean> keyHandler, Boolean newValue) {
redraw();
}
@ -152,15 +140,12 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
}
});
SecondLevelLaunch.ACCOUNTLIST_LOADED.executeWhenReached(new Runnable() {
public void run() {
new Thread() {
@Override
public void run() {
redrawTimer.run();
AccountController.getInstance().getEventSender().addListener(new AccountControllerListener() {
public void onAccountControllerEvent(AccountControllerEvent event) {
if (org.jdownloader.settings.staticreferences.CFG_GENERAL.USE_AVAILABLE_ACCOUNTS.isEnabled()) {
redrawTimer.run();
@ -198,18 +183,15 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
break;
}
}
if (!hasValidAccount) {
sb.append("[]0");
}
setLayout(new MigLayout("ins 0 2 0 0", sb.toString(), "[22!]"));
for (ServiceCollection<?> s : services) {
final JComponent c = s.createIconComponent(ServicePanel.this);
if (c != null) {
add(c, "gapleft 0,gapright 0");
}
}
if (!hasValidAccount && CFG_GUI.CFG.isStatusBarAddPremiumButtonVisible()) {
ExtButton addPremium = new ExtButton(new AppAction() {
@ -223,13 +205,11 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
JDGui.getInstance().setContent(ConfigurationView.getInstance(), true);
ConfigurationView.getInstance().setSelectedSubPanel(AccountManagerSettings.class);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
AddAccountDialog.showDialog(null, null);
}
});
}
});
addPremium.setRolloverEffectEnabled(true);
@ -237,7 +217,6 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
addPremium.setIcon(new AbstractIcon(IconKey.ICON_ADD, 18));
// addPremium.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
add(addPremium, "height 20!,gapright 10!");
}
revalidate();
repaint();
@ -272,7 +251,6 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
public int compare(Account o1, Account o2) {
return compare(o1.isMultiHost(), o2.isMultiHost());
}
});
} catch (final Throwable e) {
LogController.CL(true).log(e);
@ -298,10 +276,9 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
if (acc.getLastValidTimestamp() == -1 || (!acc.isEnabled() && timeSinceValidLogin > expireTimeMS)) {
continue;
}
final PluginForHost plugin = acc.getPlugin();
if (plugin != null) {
final DomainInfo domainInfo = DomainInfo.getInstance(plugin.getHost());
final DomainInfo domainInfo = DomainInfo.getInstance(plugin.getHost(), true);
final String domainTld = domainInfo.getTld();
domainInfo.getFavIcon();
switch (premiumStatusBarDisplay) {
@ -361,7 +338,6 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
break;
}
}
}
if (PremiumStatusBarDisplay.GROUP_BY_SUPPORTED_ACCOUNTS.equals(premiumStatusBarDisplay)) {
for (ServiceCollection<?> serviceCollection : services) {
@ -391,5 +367,4 @@ public class ServicePanel extends JPanel implements MouseListener, AccountToolti
public void mouseReleased(MouseEvent e) {
}
}

View File

@ -38,8 +38,8 @@ public class NewRuleAction extends AbstractAddAction {
final ArrayList<DomainInfo> list = getAvailableDomainInfoList();
/* Allow only one rule per hoster -> Remove items from list which a rule already exists for. */
final HosterRuleController hrc = HosterRuleController.getInstance();
for (AccountUsageRule aur : hrc.list()) {
list.remove(DomainInfo.getInstance(aur.getHoster()));
for (final AccountUsageRule aur : hrc.list()) {
list.remove(DomainInfo.getInstance(aur.getHoster(), true));
}
final ChooseHosterDialog d = new ChooseHosterDialog(_GUI.T.NewRuleAction_actionPerformed_choose_hoster_message(), list.toArray(new DomainInfo[] {}));
try {
@ -64,27 +64,30 @@ public class NewRuleAction extends AbstractAddAction {
final HashSet<String> multihosterDomains = new HashSet<String>();
/* Collect domains of all multihoster accounts which the user currently has. */
for (final Account acc : AccountController.getInstance().list()) {
if (acc.getPlugin().hasFeature(FEATURE.MULTIHOST)) {
final String thisMultihosterDomain = acc.getHoster();
multihosterDomains.add(thisMultihosterDomain);
final AccountInfo ai = acc.getAccountInfo();
if (ai != null) {
final List<String> supportedHosts = ai.getMultiHostSupport();
if (supportedHosts != null) {
for (final String supportedHost : supportedHosts) {
if (multihosterDomains.contains(supportedHost)) {
/*
* Multihoster supports its own domain or domains of other multihosters -> Exclude those domains from usage
* rule selection
*/
continue;
}
final LazyHostPlugin plg = HostPluginController.getInstance().get(supportedHost);
if (plg != null) {
domains.add(DomainInfo.getInstance(plg.getHost()));
}
}
}
if (!acc.getPlugin().hasFeature(FEATURE.MULTIHOST)) {
continue;
}
final String thisMultihosterDomain = acc.getHoster();
multihosterDomains.add(thisMultihosterDomain);
final AccountInfo ai = acc.getAccountInfo();
if (ai == null) {
continue;
}
final List<String> supportedHosts = ai.getMultiHostSupport();
if (supportedHosts == null) {
continue;
}
for (final String supportedHost : supportedHosts) {
if (multihosterDomains.contains(supportedHost)) {
/*
* Multihoster supports its own domain or domains of other multihosters -> Exclude those domains from usage rule
* selection
*/
continue;
}
final LazyHostPlugin plg = HostPluginController.getInstance().get(supportedHost);
if (plg != null) {
domains.add(DomainInfo.getInstance(plg.getHost(), true));
}
}
}
@ -92,7 +95,7 @@ public class NewRuleAction extends AbstractAddAction {
/* Collect all domains which the user is allowed to create usage rules for. */
for (final LazyHostPlugin plugin : plugins) {
if (allowAccountUsageRuleCreation(plugin)) {
domains.add(DomainInfo.getInstance(plugin.getHost()));
domains.add(DomainInfo.getInstance(plugin.getHost(), true));
}
}
/* Sort results. */

View File

@ -625,7 +625,7 @@ public class AccountInfo extends Property implements AccountTrafficView {
return mhosts;
}
/** Returns information about host if it is supported. */
/** Returns information about specific host if it is supported. */
public MultiHostHost getMultihostSupportedHost(final String domain) {
final List<MultiHostHost> mhosts = getMultiHostSupport2();
if (mhosts == null || mhosts.size() == 0) {

View File

@ -46,51 +46,6 @@ import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.SwingConstants;
import jd.PluginWrapper;
import jd.captcha.JACMethod;
import jd.config.SubConfiguration;
import jd.controlling.accountchecker.AccountChecker.AccountCheckJob;
import jd.controlling.accountchecker.AccountCheckerThread;
import jd.controlling.captcha.CaptchaSettings;
import jd.controlling.captcha.SkipException;
import jd.controlling.captcha.SkipRequest;
import jd.controlling.downloadcontroller.AccountCache.ACCOUNTTYPE;
import jd.controlling.downloadcontroller.DiskSpaceManager.DISKSPACERESERVATIONRESULT;
import jd.controlling.downloadcontroller.DiskSpaceReservation;
import jd.controlling.downloadcontroller.DownloadSession;
import jd.controlling.downloadcontroller.DownloadWatchDog;
import jd.controlling.downloadcontroller.DownloadWatchDogJob;
import jd.controlling.downloadcontroller.ExceptionRunnable;
import jd.controlling.downloadcontroller.SingleDownloadController;
import jd.controlling.downloadcontroller.SingleDownloadController.WaitingQueueItem;
import jd.controlling.linkchecker.LinkChecker;
import jd.controlling.linkcollector.LinkCollector;
import jd.controlling.linkcrawler.CheckableLink;
import jd.controlling.linkcrawler.CrawledLink;
import jd.controlling.linkcrawler.LinkCrawler;
import jd.controlling.linkcrawler.LinkCrawlerThread;
import jd.controlling.packagecontroller.AbstractNode;
import jd.controlling.proxy.AbstractProxySelectorImpl;
import jd.controlling.reconnect.ipcheck.BalancedWebIPCheck;
import jd.controlling.reconnect.ipcheck.IPCheckException;
import jd.controlling.reconnect.ipcheck.OfflineException;
import jd.gui.swing.jdgui.views.settings.panels.pluginsettings.PluginConfigPanel;
import jd.http.Browser;
import jd.http.Browser.BrowserException;
import jd.http.NoGateWayException;
import jd.http.ProxySelectorInterface;
import jd.http.Request;
import jd.http.StaticProxySelector;
import jd.http.URLConnectionAdapter;
import jd.nutils.Formatter;
import jd.nutils.JDHash;
import jd.plugins.Account.AccountError;
import jd.plugins.DownloadLink.AvailableStatus;
import jd.plugins.download.DownloadInterface;
import jd.plugins.download.DownloadInterfaceFactory;
import jd.plugins.download.DownloadLinkDownloadable;
import jd.plugins.download.Downloadable;
import org.appwork.exceptions.WTFException;
import org.appwork.net.protocol.http.HTTPConstants;
import org.appwork.storage.JSonStorage;
@ -104,6 +59,7 @@ import org.appwork.uio.ConfirmDialogInterface;
import org.appwork.uio.InputDialogInterface;
import org.appwork.uio.UIOManager;
import org.appwork.utils.Application;
import org.appwork.utils.DebugMode;
import org.appwork.utils.Exceptions;
import org.appwork.utils.Files;
import org.appwork.utils.Hash;
@ -190,6 +146,51 @@ import org.jdownloader.translate._JDT;
import org.jdownloader.updatev2.UpdateController;
import org.jdownloader.updatev2.UpdateHandler;
import jd.PluginWrapper;
import jd.captcha.JACMethod;
import jd.config.SubConfiguration;
import jd.controlling.accountchecker.AccountChecker.AccountCheckJob;
import jd.controlling.accountchecker.AccountCheckerThread;
import jd.controlling.captcha.CaptchaSettings;
import jd.controlling.captcha.SkipException;
import jd.controlling.captcha.SkipRequest;
import jd.controlling.downloadcontroller.AccountCache.ACCOUNTTYPE;
import jd.controlling.downloadcontroller.DiskSpaceManager.DISKSPACERESERVATIONRESULT;
import jd.controlling.downloadcontroller.DiskSpaceReservation;
import jd.controlling.downloadcontroller.DownloadSession;
import jd.controlling.downloadcontroller.DownloadWatchDog;
import jd.controlling.downloadcontroller.DownloadWatchDogJob;
import jd.controlling.downloadcontroller.ExceptionRunnable;
import jd.controlling.downloadcontroller.SingleDownloadController;
import jd.controlling.downloadcontroller.SingleDownloadController.WaitingQueueItem;
import jd.controlling.linkchecker.LinkChecker;
import jd.controlling.linkcollector.LinkCollector;
import jd.controlling.linkcrawler.CheckableLink;
import jd.controlling.linkcrawler.CrawledLink;
import jd.controlling.linkcrawler.LinkCrawler;
import jd.controlling.linkcrawler.LinkCrawlerThread;
import jd.controlling.packagecontroller.AbstractNode;
import jd.controlling.proxy.AbstractProxySelectorImpl;
import jd.controlling.reconnect.ipcheck.BalancedWebIPCheck;
import jd.controlling.reconnect.ipcheck.IPCheckException;
import jd.controlling.reconnect.ipcheck.OfflineException;
import jd.gui.swing.jdgui.views.settings.panels.pluginsettings.PluginConfigPanel;
import jd.http.Browser;
import jd.http.Browser.BrowserException;
import jd.http.NoGateWayException;
import jd.http.ProxySelectorInterface;
import jd.http.Request;
import jd.http.StaticProxySelector;
import jd.http.URLConnectionAdapter;
import jd.nutils.Formatter;
import jd.nutils.JDHash;
import jd.plugins.Account.AccountError;
import jd.plugins.DownloadLink.AvailableStatus;
import jd.plugins.download.DownloadInterface;
import jd.plugins.download.DownloadInterfaceFactory;
import jd.plugins.download.DownloadLinkDownloadable;
import jd.plugins.download.Downloadable;
/**
* Dies ist die Oberklasse fuer alle Plugins, die von einem Anbieter Dateien herunterladen koennen
*
@ -198,11 +199,10 @@ import org.jdownloader.updatev2.UpdateHandler;
public abstract class PluginForHost extends Plugin {
private static final String COPY_MOVE_FILE = "CopyMoveFile";
private static final Pattern[] PATTERNS = new Pattern[] {
/**
* these patterns should split filename and fileextension (extension must include the
* point)
*/
// multipart rar archives
/**
* these patterns should split filename and fileextension (extension must include the point)
*/
// multipart rar archives
Pattern.compile("(.*)(\\.pa?r?t?\\.?[0-9]+.*?\\.rar$)", Pattern.CASE_INSENSITIVE),
// normal files with extension
Pattern.compile("(.*)(\\..*?$)", Pattern.CASE_INSENSITIVE) };
@ -1136,14 +1136,41 @@ public abstract class PluginForHost extends Plugin {
if (accountTrafficView == null) {
return true;
}
final long trafficLeft = accountTrafficView.getTrafficLeft();
final long minimum = 1024;
final long downloadSize = link.getView().getBytesTotalEstimated();
if (DebugMode.TRUE_IN_IDE_ELSE_FALSE && ACCOUNTTYPE.MULTI.equals(account.getType()) && downloadSize != -1) {
final AccountInfo ai = account.getAccountInfo();
if (ai == null) {
/* Multihoster account without accountInfo -> That should never happen */
return false;
}
/* Verify again because plugins can modify list on runtime */
/* Check for domain specific limits of multihost items. */
final MultiHostHost hostinfo = ai.getMultihostSupportedHost(link.getHost());
if (hostinfo == null) {
/* Not supported */
return false;
}
final long trafficCalcFactor = hostinfo.getTrafficCalculationFactorPercent();
long neededTraffic = downloadSize;
if (trafficCalcFactor != 100) {
neededTraffic = (downloadSize * trafficCalcFactor) / 100;
if (neededTraffic > trafficLeft) {
return false;
}
}
/* Account itself has enough traffic but does it have enough traffic for the host we are trying to download from? */
if (!hostinfo.isUnlimitedTraffic() && neededTraffic > hostinfo.getTrafficLeft()) {
/* Not enough traffic to download this file */
return false;
}
}
if (accountTrafficView.isUnlimitedTraffic() || accountTrafficView.isSpecialTraffic()) {
return true;
}
final long trafficLeft = accountTrafficView.getTrafficLeft();
final long minimum = 1024;
if (trafficLeft == 0) {
if (accountTrafficView.isTrafficRefill()) {
final long downloadSize = link.getView().getBytesTotalEstimated();
final long downloadLeft;
if (downloadSize >= 0) {
downloadLeft = Math.max(minimum, downloadSize - link.getView().getBytesLoaded());
@ -1155,7 +1182,6 @@ public abstract class PluginForHost extends Plugin {
return false;
}
} else {
final long downloadSize = link.getView().getBytesTotalEstimated();
if (downloadSize <= 0) {
/* File size is unknown */
return true;
@ -1292,12 +1318,9 @@ public abstract class PluginForHost extends Plugin {
protected void handleException(final DownloadLink downloadLink, final ACCOUNTTYPE accountType, final Account account, final Exception e) throws Exception {
if (ACCOUNTTYPE.MULTI.equals(accountType) && e instanceof PluginException) {
if (((PluginException) e).getLinkStatus() == LinkStatus.ERROR_FILE_NOT_FOUND && AvailableStatus.TRUE.equals(link.getAvailableStatus())) {
/* File is online according to original filehoster -> Do not trust offline status from multihoster. */
throw new PluginException(LinkStatus.ERROR_TEMPORARILY_UNAVAILABLE, "Multihoster " + getHost() + " claims that this file is offline", e);
}
}
}
@ -1367,16 +1390,16 @@ public abstract class PluginForHost extends Plugin {
public void handleMultiHost(DownloadLink downloadLink, Account account) throws Exception {
/*
* fetchAccountInfo must fill ai.setMultiHostSupport to signal all supported multiHosts
*
*
* please synchronized on accountinfo and the ArrayList<String> when you change something in the handleMultiHost function
*
*
* in fetchAccountInfo we don't have to synchronize because we create a new instance of AccountInfo and fill it
*
*
* if you need customizable maxDownloads, please use getMaxSimultanDownload to handle this you are in multihost when account host
* does not equal link host!
*
*
*
*
*
*
* will update this doc about error handling
*/
logger.severe("invalid call to handleMultiHost: " + downloadLink.getName() + ":" + downloadLink.getHost() + " to " + getHost() + ":" + this.getVersion() + " with " + account);

View File

@ -16,16 +16,18 @@
package jd.plugins.decrypter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.appwork.storage.TypeRef;
import org.appwork.utils.StringUtils;
import org.jdownloader.controlling.filter.CompiledFiletypeFilter;
import org.jdownloader.plugins.controller.LazyPlugin;
import jd.PluginWrapper;
import jd.controlling.ProgressController;
import jd.http.Cookies;
import jd.nutils.encoding.Encoding;
import jd.parser.Regex;
import jd.plugins.CryptedLink;
@ -63,54 +65,68 @@ public class BitchuteComChannel extends PluginForDecrypt {
} else if (br.containsHTML("(?i)>\\s*This channel is blocked under the following Community Guideline")) {
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
}
final String csrftoken = this.br.getCookie(br.getHost(), "csrftoken", Cookies.NOTDELETEDPATTERN);
final String channelUID = br.getRegex("channelRefreshCounts\\('([A-Za-z0-9]+)'").getMatch(0);
if (StringUtils.isEmpty(csrftoken) || channelUID == null) {
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
final String channelID = new Regex(parameter, this.getSupportedLinks()).getMatch(0);
/*
* Prefer to use channelname from html - channelname inside URL is always lowercase and sometimes a cryptic string while html
* contains the "nicer" channelname.
*/
String channelname = br.getRegex("id=\"channel-title\"[^>]*>([^>]+)<").getMatch(0);
String channelname = br.getRegex("itemprop=\"name\" content=\"([^\"]+)").getMatch(0);
if (StringUtils.isEmpty(channelname)) {
/* Fallback */
channelname = new Regex(parameter, this.getSupportedLinks()).getMatch(0);
channelname = channelID;
}
final FilePackage fp = FilePackage.getInstance();
fp.setName(Encoding.htmlDecode(channelname.trim()));
int index = 0;
fp.setPackageKey("bitchute://channel/" + channelID);
int offset = 0;
int page = 0;
final int itemsPerRequest = 25;
br.getHeaders().put("x-requested-with", "XMLHttpRequest");
final int itemsPerRequest = 10;
br.getHeaders().put("Accept", "application/json, text/plain, */*");
br.getHeaders().put("X-Requested-With", "XMLHttpRequest");
br.getHeaders().put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
do {
logger.info("Crawling page: " + page);
br.postPage("https://www.bitchute.com/channel/" + channelUID + "/extend/", "csrfmiddlewaretoken=" + Encoding.urlEncode(csrftoken) + "&name=&offset=" + index);
final String[] videoIDs = br.getRegex("/video/([A-Za-z0-9]+)/").getColumn(0);
int addedItems = 0;
for (final String videoID : videoIDs) {
if (isAbort()) {
break;
} else if (dupes.add(videoID)) {
dupes.add(videoID);
final DownloadLink dl = createDownloadlink("https://www." + this.getHost() + "/video/" + videoID);
dl.setMimeHint(CompiledFiletypeFilter.VideoExtensions.MP4);
dl.setAvailable(true);
/* Property for packagizer */
dl.setProperty("username", channelname);
dl._setFilePackage(fp);
ret.add(dl);
distribute(dl);
addedItems++;
final Map<String, Object> postdata = new HashMap<String, Object>();
postdata.put("channel_id", channelID);
postdata.put("limit", itemsPerRequest);
pagination: do {
postdata.put("offset", offset);
br.getPage(br.createJSonPostRequest("https://api.bitchute.com/api/beta/channel/videos", postdata));
if (br.getHttpConnection().getResponseCode() == 403) {
/**
* E.g. GEO-blocked: <br>
* {"errors":[{"context":"AUTH","message":"Forbidden - Cannot perform this action"},{"context":"reason","message":"Content
* access is restricted based on the users location"}]}
*/
throw new DecrypterRetryException(RetryReason.GEO);
} else if (br.getHttpConnection().getResponseCode() == 404) {
throw new PluginException(LinkStatus.ERROR_FILE_NOT_FOUND);
}
final Map<String, Object> entries = restoreFromString(br.getRequest().getHtmlCode(), TypeRef.MAP);
final List<Map<String, Object>> videos = (List<Map<String, Object>>) entries.get("videos");
int numberofNewItemsThisPage = 0;
for (final Map<String, Object> videomap : videos) {
final String videoID = videomap.get("video_id").toString();
if (!dupes.add(videoID)) {
continue;
}
final DownloadLink dl = createDownloadlink("https://www." + this.getHost() + "/video/" + videoID);
dl.setName(videomap.get("video_name") + ".mp4");
dl.setAvailable(true);
/* Property for Packagizer */
dl.setProperty("username", channelname);
dl._setFilePackage(fp);
ret.add(dl);
distribute(dl);
numberofNewItemsThisPage++;
}
logger.info("Crawling page: " + page + " | Found items so far: " + index);
if (addedItems < itemsPerRequest) {
logger.info("Crawled page: " + page + " | offset: " + offset + " | Found items so far: " + ret.size());
if (this.isAbort()) {
break pagination;
} else if (numberofNewItemsThisPage < itemsPerRequest) {
logger.info("Stopping because number of items found doesn't match number of items per request");
break;
break pagination;
}
index += itemsPerRequest;
/* Continue to next page */
offset += itemsPerRequest;
page += 1;
} while (!this.isAbort());
return ret;

View File

@ -16,12 +16,15 @@
package jd.plugins.decrypter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.appwork.utils.parser.UrlQuery;
import jd.PluginWrapper;
import jd.controlling.ProgressController;
import jd.nutils.encoding.Encoding;
import jd.parser.Regex;
import jd.plugins.CryptedLink;
import jd.plugins.DecrypterPlugin;
import jd.plugins.DownloadLink;
@ -40,7 +43,9 @@ public class BooruOrgCrawler extends PluginForDecrypt {
public static List<String[]> getPluginDomains() {
final List<String[]> ret = new ArrayList<String[]>();
// each entry in List<String[]> will result in one PluginForHost, Plugin.getHost() will return String[0]->main domain
ret.add(new String[] { "tbib.org", "booru.org" });
ret.add(new String[] { "tbib.org" });
ret.add(new String[] { "booru.org" });
ret.add(new String[] { "safebooru.org" });
return ret;
}
@ -56,7 +61,7 @@ public class BooruOrgCrawler extends PluginForDecrypt {
public static String[] getAnnotationUrls() {
final List<String> ret = new ArrayList<String>();
for (final String[] domains : getPluginDomains()) {
ret.add("https?://(?:\\w+\\.)?" + buildHostsPatternPart(domains) + "/index\\.php\\?page=post\\&s=list\\&tags=[A-Za-z0-9_\\-]+");
ret.add("https?://(?:\\w+\\.)?" + buildHostsPatternPart(domains) + "/.*?index\\.php\\?page=post\\&s=list\\&tags=[A-Za-z0-9_\\-]+");
}
return ret.toArray(new String[0]);
}
@ -68,8 +73,8 @@ public class BooruOrgCrawler extends PluginForDecrypt {
if (br.getHttpConnection().getResponseCode() == 404) {
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
final String full_host = new Regex(contenturl, "https?://([^/]+)/").getMatch(0);
final String fpName = new Regex(contenturl, "tags=(.+)").getMatch(0);
final UrlQuery query = UrlQuery.parse(contenturl);
final String fpName = query.get("tags");
final FilePackage fp = FilePackage.getInstance();
fp.setName(Encoding.htmlDecode(fpName).trim());
final String url_part = contenturl;
@ -77,11 +82,8 @@ public class BooruOrgCrawler extends PluginForDecrypt {
int offset = 0;
final int max_entries_per_page = 20;
int entries_per_page_current = 0;
do {
if (this.isAbort()) {
logger.info("Decryption aborted by user");
return ret;
}
final Set<String> dupes = new HashSet<String>();
pagination: do {
if (page_counter > 1) {
this.br.getPage(url_part + "&pid=" + offset);
if (this.br.containsHTML("You are viewing an advertisement")) {
@ -95,8 +97,12 @@ public class BooruOrgCrawler extends PluginForDecrypt {
break;
}
entries_per_page_current = linkids.length;
int numberofNewItemsThisPage = 0;
for (final String linkid : linkids) {
final String link = "http://" + full_host + "/index.php?page=post&s=view&id=" + linkid;
if (!dupes.add(linkid)) {
continue;
}
final String link = br.getURL("index.php?page=post&s=view&id=" + linkid).toExternalForm();
final DownloadLink dl = createDownloadlink(link);
dl.setLinkID(linkid);
dl.setAvailable(true);
@ -105,9 +111,22 @@ public class BooruOrgCrawler extends PluginForDecrypt {
ret.add(dl);
distribute(dl);
offset++;
numberofNewItemsThisPage++;
}
if (this.isAbort()) {
logger.info("Decryption aborted by user");
break pagination;
} else if (numberofNewItemsThisPage == 0) {
logger.info("Stopping because: Failed to find any new items on current page");
break pagination;
} else {
/* Continue to next page */
page_counter++;
}
page_counter++;
} while (entries_per_page_current >= max_entries_per_page);
if (ret.isEmpty()) {
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
return ret;
}

View File

@ -22,6 +22,13 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.appwork.storage.TypeRef;
import org.appwork.utils.StringUtils;
import org.appwork.utils.parser.UrlQuery;
import org.jdownloader.plugins.components.antiDDoSForDecrypt;
import org.jdownloader.plugins.controller.LazyPlugin;
import org.jdownloader.scripting.JavaScriptEngineFactory;
import jd.PluginWrapper;
import jd.controlling.AccountController;
import jd.controlling.ProgressController;
@ -42,13 +49,6 @@ import jd.plugins.PluginException;
import jd.plugins.PluginForHost;
import jd.utils.JDHexUtils;
import org.appwork.storage.TypeRef;
import org.appwork.utils.StringUtils;
import org.appwork.utils.parser.UrlQuery;
import org.jdownloader.plugins.components.antiDDoSForDecrypt;
import org.jdownloader.plugins.controller.LazyPlugin;
import org.jdownloader.scripting.JavaScriptEngineFactory;
@DecrypterPlugin(revision = "$Revision$", interfaceVersion = 3, names = { "mixcloud.com" }, urls = { "https?://(?:www\\.)?mixcloud\\.com/(widget/iframe/\\?.+|[^/]+/?([^/]+/)?)" })
public class MixCloudComCrawler extends antiDDoSForDecrypt {
public MixCloudComCrawler(final PluginWrapper wrapper) {
@ -126,11 +126,9 @@ public class MixCloudComCrawler extends antiDDoSForDecrypt {
if (csrftoken == null) {
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
PostRequest request = br
.createJSonPostRequest(
"https://app.mixcloud.com/graphql",
"{\"query\":\"query UserProfileHeaderQuery( $lookup: UserLookup!) { user: userLookup(lookup: $lookup) { id displayName username isBranded isStaff isFollowing isViewer followers { totalCount } hasCoverPicture hasPremiumFeatures hasProFeatures picture { primaryColor ...UGCImage_picture } coverPicture { urlRoot } ...UserBadge_user ...ProfileNavigation_user ...ShareUserButton_user ...ProfileRegisterUpsellComponent_user ...FollowButton_user ...SelectUpsellButton_user } viewer { ...ProfileRegisterUpsellComponent_viewer ...FollowButton_viewer id }}fragment FollowButton_user on User { id isFollowed isFollowing isViewer followers { totalCount } username displayName}fragment FollowButton_viewer on Viewer { me { id }}fragment ProfileNavigation_user on User { id username stream { totalCount } favorites { totalCount } listeningHistory { totalCount } uploads { totalCount } posts { totalCount } profileNavigation { menuItems { __typename ... on NavigationItemInterface { __isNavigationItemInterface: __typename inDropdown } ... on HideableNavigationItemInterface { __isHideableNavigationItemInterface: __typename hidden } ... on PlaylistNavigationItem { count playlist { id name slug } } } }}fragment ProfileRegisterUpsellComponent_user on User { id displayName followers { totalCount }}fragment ProfileRegisterUpsellComponent_viewer on Viewer { me { id }}fragment SelectUpsellButton_user on User { username isSelect isSubscribedTo selectUpsell { planInfo { displayAmount } }}fragment ShareUserButton_user on User { biog username displayName id isUploader picture { urlRoot }}fragment UGCImage_picture on Picture { urlRoot primaryColor}fragment UserBadge_user on User { username hasProFeatures hasPremiumFeatures isStaff isSelect}\",\"variables\":{\"lookup\":{\"username\":\""
+ username + "\"}}}");
PostRequest request = br.createJSonPostRequest("https://app.mixcloud.com/graphql",
"{\"query\":\"query UserProfileHeaderQuery( $lookup: UserLookup!) { user: userLookup(lookup: $lookup) { id displayName username isBranded isStaff isFollowing isViewer followers { totalCount } hasCoverPicture hasPremiumFeatures hasProFeatures picture { primaryColor ...UGCImage_picture } coverPicture { urlRoot } ...UserBadge_user ...ProfileNavigation_user ...ShareUserButton_user ...ProfileRegisterUpsellComponent_user ...FollowButton_user ...SelectUpsellButton_user } viewer { ...ProfileRegisterUpsellComponent_viewer ...FollowButton_viewer id }}fragment FollowButton_user on User { id isFollowed isFollowing isViewer followers { totalCount } username displayName}fragment FollowButton_viewer on Viewer { me { id }}fragment ProfileNavigation_user on User { id username stream { totalCount } favorites { totalCount } listeningHistory { totalCount } uploads { totalCount } posts { totalCount } profileNavigation { menuItems { __typename ... on NavigationItemInterface { __isNavigationItemInterface: __typename inDropdown } ... on HideableNavigationItemInterface { __isHideableNavigationItemInterface: __typename hidden } ... on PlaylistNavigationItem { count playlist { id name slug } } } }}fragment ProfileRegisterUpsellComponent_user on User { id displayName followers { totalCount }}fragment ProfileRegisterUpsellComponent_viewer on Viewer { me { id }}fragment SelectUpsellButton_user on User { username isSelect isSubscribedTo selectUpsell { planInfo { displayAmount } }}fragment ShareUserButton_user on User { biog username displayName id isUploader picture { urlRoot }}fragment UGCImage_picture on Picture { urlRoot primaryColor}fragment UserBadge_user on User { username hasProFeatures hasPremiumFeatures isStaff isSelect}\",\"variables\":{\"lookup\":{\"username\":\""
+ username + "\"}}}");
br.getPage(request);
Map<String, Object> entries = restoreFromString(br.toString(), TypeRef.MAP);
entries = (Map<String, Object>) JavaScriptEngineFactory.walkJson(entries, "data/user");
@ -213,13 +211,9 @@ public class MixCloudComCrawler extends antiDDoSForDecrypt {
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
br.setFollowRedirects(true);
final PostRequest request = br
.createJSonPostRequest(
"https://app.mixcloud.com/graphql",
String.format(
"{\"id\":\"q13\",\"query\":\"query HeaderQuery($lookup_0:CloudcastLookup!,$lighten_1:Int!,$alpha_2:Float!) {cloudcastLookup(lookup:$lookup_0) {id,...Fn}} fragment F0 on Cloudcast {picture {urlRoot,primaryColor},id} fragment F1 on Cloudcast {id,name,slug,owner {username,id}} fragment F2 on Cloudcast {owner {id,displayName,followers {totalCount}},id} fragment F3 on Cloudcast {restrictedReason,owner {displayName,country,username,isSubscribedTo,isViewer,id},slug,id,isAwaitingAudio,isDraft,isPlayable,streamInfo {hlsUrl,dashUrl,url,uuid},audioLength,currentPosition,proportionListened,repeatPlayAmount,hasPlayCompleted,seekRestriction,previewUrl,isExclusivePreviewOnly,isExclusive,picture {primaryColor,isLight,_primaryColor2pfPSM:primaryColor(lighten:$lighten_1),_primaryColor3Yfcks:primaryColor(alpha:$alpha_2)}} fragment F4 on Node {id,__typename} fragment F5 on Cloudcast {id,isFavorited,isPublic,hiddenStats,favorites {totalCount},slug,owner {id,isFollowing,username,isSelect,displayName,isViewer}} fragment F6 on Cloudcast {id,isUnlisted,isPublic} fragment F7 on Cloudcast {id,isReposted,isPublic,hiddenStats,reposts {totalCount},owner {isViewer,id}} fragment F8 on Cloudcast {id,isUnlisted,isPublic,slug,description,picture {urlRoot},owner {displayName,isViewer,username,id}} fragment F9 on Cloudcast {id,slug,isSpam,owner {username,isViewer,id}} fragment Fa on Cloudcast {owner {isViewer,isSubscribedTo,username,hasProFeatures,isBranded,id},sections {__typename,...F4},id,slug,isExclusive,isUnlisted,isShortLength,...F5,...F6,...F7,...F8,...F9} fragment Fb on Cloudcast {qualityScore,listenerMinutes,id} fragment Fc on Cloudcast {slug,plays,publishDate,hiddenStats,owner {username,id},id,...Fb} fragment Fd on User {id} fragment Fe on User {username,hasProFeatures,hasPremiumFeatures,isStaff,isSelect,id} fragment Ff on User {id,isFollowed,isFollowing,isViewer,followers {totalCount},username,displayName} fragment Fg on Cloudcast {isExclusive,isExclusivePreviewOnly,slug,id,owner {username,id}} fragment Fh on Cloudcast {isExclusive,owner {id,username,displayName,...Fd,...Fe,...Ff},id,...Fg} fragment Fi on Cloudcast {id,streamInfo {uuid,url,hlsUrl,dashUrl},audioLength,seekRestriction,currentPosition} fragment Fj on Cloudcast {owner {displayName,isSelect,username,id},seekRestriction,id} fragment Fk on Cloudcast {id,waveformUrl,previewUrl,audioLength,isPlayable,streamInfo {hlsUrl,dashUrl,url,uuid},restrictedReason,seekRestriction,currentPosition,...Fj} fragment Fl on Cloudcast {__typename,isExclusivePreviewOnly,isExclusive,owner {isSelect,isSubscribedTo,username,displayName,isViewer,id},id} fragment Fm on Cloudcast {owner {username,displayName,isSelect,id},id} fragment Fn on Cloudcast {id,name,picture {isLight,primaryColor,urlRoot,primaryColor},owner {displayName,isViewer,isBranded,selectUpsell {text},id},repeatPlayAmount,restrictedReason,seekRestriction,...F0,...F1,...F2,...F3,...Fa,...Fc,...Fh,...Fi,...Fk,...Fl,...Fm}\",\"variables\":{\"lookup_0\":{\"username\":\"%s\",\"slug\":\"%s\"},\"lighten_1\":15,\"alpha_2\":0.3}}",
username, slug));
final PostRequest request = br.createJSonPostRequest("https://app.mixcloud.com/graphql", String.format(
"{\"id\":\"q13\",\"query\":\"query HeaderQuery($lookup_0:CloudcastLookup!,$lighten_1:Int!,$alpha_2:Float!) {cloudcastLookup(lookup:$lookup_0) {id,...Fn}} fragment F0 on Cloudcast {picture {urlRoot,primaryColor},id} fragment F1 on Cloudcast {id,name,slug,owner {username,id}} fragment F2 on Cloudcast {owner {id,displayName,followers {totalCount}},id} fragment F3 on Cloudcast {restrictedReason,owner {displayName,country,username,isSubscribedTo,isViewer,id},slug,id,isAwaitingAudio,isDraft,isPlayable,streamInfo {hlsUrl,dashUrl,url,uuid},audioLength,currentPosition,proportionListened,repeatPlayAmount,hasPlayCompleted,seekRestriction,previewUrl,isExclusivePreviewOnly,isExclusive,picture {primaryColor,isLight,_primaryColor2pfPSM:primaryColor(lighten:$lighten_1),_primaryColor3Yfcks:primaryColor(alpha:$alpha_2)}} fragment F4 on Node {id,__typename} fragment F5 on Cloudcast {id,isFavorited,isPublic,hiddenStats,favorites {totalCount},slug,owner {id,isFollowing,username,isSelect,displayName,isViewer}} fragment F6 on Cloudcast {id,isUnlisted,isPublic} fragment F7 on Cloudcast {id,isReposted,isPublic,hiddenStats,reposts {totalCount},owner {isViewer,id}} fragment F8 on Cloudcast {id,isUnlisted,isPublic,slug,description,picture {urlRoot},owner {displayName,isViewer,username,id}} fragment F9 on Cloudcast {id,slug,isSpam,owner {username,isViewer,id}} fragment Fa on Cloudcast {owner {isViewer,isSubscribedTo,username,hasProFeatures,isBranded,id},sections {__typename,...F4},id,slug,isExclusive,isUnlisted,isShortLength,...F5,...F6,...F7,...F8,...F9} fragment Fb on Cloudcast {qualityScore,listenerMinutes,id} fragment Fc on Cloudcast {slug,plays,publishDate,hiddenStats,owner {username,id},id,...Fb} fragment Fd on User {id} fragment Fe on User {username,hasProFeatures,hasPremiumFeatures,isStaff,isSelect,id} fragment Ff on User {id,isFollowed,isFollowing,isViewer,followers {totalCount},username,displayName} fragment Fg on Cloudcast {isExclusive,isExclusivePreviewOnly,slug,id,owner {username,id}} fragment Fh on Cloudcast {isExclusive,owner {id,username,displayName,...Fd,...Fe,...Ff},id,...Fg} fragment Fi on Cloudcast {id,streamInfo {uuid,url,hlsUrl,dashUrl},audioLength,seekRestriction,currentPosition} fragment Fj on Cloudcast {owner {displayName,isSelect,username,id},seekRestriction,id} fragment Fk on Cloudcast {id,waveformUrl,previewUrl,audioLength,isPlayable,streamInfo {hlsUrl,dashUrl,url,uuid},restrictedReason,seekRestriction,currentPosition,...Fj} fragment Fl on Cloudcast {__typename,isExclusivePreviewOnly,isExclusive,owner {isSelect,isSubscribedTo,username,displayName,isViewer,id},id} fragment Fm on Cloudcast {owner {username,displayName,isSelect,id},id} fragment Fn on Cloudcast {id,name,picture {isLight,primaryColor,urlRoot,primaryColor},owner {displayName,isViewer,isBranded,selectUpsell {text},id},repeatPlayAmount,restrictedReason,seekRestriction,...F0,...F1,...F2,...F3,...Fa,...Fc,...Fh,...Fi,...Fk,...Fl,...Fm}\",\"variables\":{\"lookup_0\":{\"username\":\"%s\",\"slug\":\"%s\"},\"lighten_1\":15,\"alpha_2\":0.3}}",
username, slug));
this.sendRequest(request);
int page = 0;
boolean hasMore = false;
@ -420,7 +414,7 @@ public class MixCloudComCrawler extends antiDDoSForDecrypt {
logger.info("Skip dupe object: " + id);
continue;
}
final Object cloudcastStreamInfo = entries.get("streamInfo");
final Map<String, Object> cloudcastStreamInfo = (Map<String, Object>) entries.get("streamInfo");
if (cloudcastStreamInfo == null && StringUtils.isEmpty(url_preview)) {
/* Skip invalid objects */
continue;
@ -431,11 +425,10 @@ public class MixCloudComCrawler extends antiDDoSForDecrypt {
if (cloudcastStreamInfo != null) {
/* We should have found the correct object here! */
// final String url_mp3_preview = (String) entries.get("previewUrl");
entries = (Map<String, Object>) cloudcastStreamInfo;
/*
* 2017-11-15: We can chose between dash, http or hls
* 2017-11-15: We can chose between dash, progressive or hls
*/
downloadurl = (String) entries.get("url");
downloadurl = (String) cloudcastStreamInfo.get("url");
}
if (StringUtils.isEmpty(url_preview) && StringUtils.isEmpty(downloadurl)) {
/* Skip objects without streams */
@ -466,6 +459,12 @@ public class MixCloudComCrawler extends antiDDoSForDecrypt {
dlink.setComment(description);
}
dlink.setAvailable(true);
final Number lengthSeconds = (Number) entries.get("audioLength");
if (lengthSeconds != null) {
/* Set estimated filesize based on a bitrate of 64KB/s */
final long trackEstimatedFilesize = (lengthSeconds.intValue() * 64 * 1024) / 8;
dlink.setDownloadSize(trackEstimatedFilesize);
}
dlink._setFilePackage(fp);
distribute(dlink);
decryptedLinks.add(dlink);

View File

@ -64,7 +64,7 @@ public class BooruOrg extends PluginForHost {
public static String[] getAnnotationUrls() {
final List<String> ret = new ArrayList<String>();
for (final String[] domains : getPluginDomains()) {
ret.add("https?://(?:\\w+\\.)?" + buildHostsPatternPart(domains) + "/index\\.php\\?page=post\\&s=view\\&id=(\\d+)");
ret.add("https?://(?:\\w+\\.)?" + buildHostsPatternPart(domains) + "/.*?index\\.php\\?page=post\\&s=view\\&id=(\\d+)");
}
return ret.toArray(new String[0]);
}
@ -88,7 +88,7 @@ public class BooruOrg extends PluginForHost {
@Override
public String getAGBLink() {
return "https://booru.org/tos.php";
return "https://" + getHost() + "/tos.php";
}
@Override

View File

@ -15,11 +15,16 @@
//along with this program. If not, see <http://www.gnu.org/licenses/>.
package jd.plugins.hoster;
import java.net.URL;
import org.appwork.net.protocol.http.HTTPConstants;
import org.appwork.utils.StringUtils;
import org.jdownloader.plugins.controller.LazyPlugin;
import jd.PluginWrapper;
import jd.http.Cookies;
import jd.http.requests.PostRequest;
import jd.nutils.encoding.Encoding;
import jd.parser.Regex;
import jd.plugins.Account;
import jd.plugins.Account.AccountType;
import jd.plugins.AccountInfo;
@ -28,20 +33,17 @@ import jd.plugins.DownloadLink;
import jd.plugins.DownloadLink.AvailableStatus;
import jd.plugins.HostPlugin;
import jd.plugins.LinkStatus;
import jd.plugins.Plugin;
import jd.plugins.PluginException;
import jd.plugins.PluginForHost;
import jd.plugins.components.PluginJSonUtils;
import jd.plugins.decrypter.MixCloudComCrawler;
import org.appwork.net.protocol.http.HTTPConstants;
import org.appwork.utils.StringUtils;
import org.jdownloader.plugins.controller.LazyPlugin;
@HostPlugin(revision = "$Revision$", interfaceVersion = 3, names = { "mixcloud.com" }, urls = { "https?://stream\\d+\\.mixcloud\\.com/.+|https://thumbnailer\\.mixcloud\\.com/unsafe/.+" })
public class MixCloudCom extends PluginForHost {
public MixCloudCom(PluginWrapper wrapper) {
super(wrapper);
this.enablePremium("https://www.mixcloud.com/select/");
this.enablePremium("https://www." + getHost() + "/select/");
}
@Override
@ -87,12 +89,12 @@ public class MixCloudCom extends PluginForHost {
private AvailableStatus requestFileInformation(final DownloadLink link, final boolean isDownload) throws Exception {
dllink = null;
br.setFollowRedirects(true);
final String url_filename = new Regex(link.getDownloadURL(), "mixcloud\\.com/(.+)").getMatch(0);
final String url_filename = Plugin.getFileNameFromURL(new URL(link.getPluginPatternMatcher()));
String filename = link.getFinalFileName();
if (filename == null) {
filename = url_filename;
}
dllink = link.getDownloadURL();
dllink = link.getPluginPatternMatcher();
if (filename == null) {
throw new PluginException(LinkStatus.ERROR_PLUGIN_DEFECT);
}
@ -156,7 +158,7 @@ public class MixCloudCom extends PluginForHost {
if (!StringUtils.isEmpty(username)) {
logger.info("Cookie login successful");
/* Refresh cookie timestamp */
account.saveCookies(this.br.getCookies(br.getHost()), "");
account.saveCookies(br.getCookies(br.getHost()), "");
return true;
} else {
logger.info("Cookie login failed");

View File

@ -213,7 +213,7 @@ abstract public class ZeveraCore extends UseNet {
link.setFinalFileName(filename);
}
if (filesize != null) {
link.setDownloadSize(filesize.longValue());
link.setVerifiedFileSize(filesize.longValue());
}
return details;
}

View File

@ -136,7 +136,7 @@ public class DomainInfo implements FavIconRequestor, Comparable<DomainInfo>, Ico
private static final HashMap<String, WeakReference<DomainInfo>> CACHE = new HashMap<String, WeakReference<DomainInfo>>();
private static String getCacheID(String domain) {
private static String getCacheID(final String domain) {
String ret = domain.toLowerCase(Locale.ENGLISH);
int index = ret.indexOf(" ");
if (index > 0) {
@ -151,16 +151,21 @@ public class DomainInfo implements FavIconRequestor, Comparable<DomainInfo>, Ico
return ret;
}
/** Returns DomainInfo without subdomain */
public static DomainInfo getInstance(final String domain) {
return getInstance(domain, false);
}
public static DomainInfo getInstance(final String domain, final boolean includeSubdomain) {
if (domain == null) {
return null;
}
final String lcaseTld = getCacheID(domain);
synchronized (CACHE) {
DomainInfo ret = null;
WeakReference<DomainInfo> domainInfo = CACHE.get(lcaseTld);
final WeakReference<DomainInfo> domainInfo = CACHE.get(lcaseTld);
if (domainInfo == null || (ret = domainInfo.get()) == null) {
ret = new DomainInfo(Browser.getHost(lcaseTld), lcaseTld);
ret = new DomainInfo(Browser.getHost(lcaseTld, includeSubdomain), lcaseTld);
CACHE.put(lcaseTld, new WeakReference<DomainInfo>(ret));
}
return ret;