├── java ├── settings.gradle.kts ├── src ├── main │ ├── resources │ │ ├── camera.wav │ │ ├── folder.png │ │ ├── gear.png │ │ ├── icon.ico │ │ ├── icon.png │ │ ├── list.png │ │ ├── stop.png │ │ ├── time.png │ │ ├── wrench.png │ │ ├── comment.png │ │ ├── LabelsBundle_en_US.properties │ │ ├── log4j.properties │ │ ├── log4j.file.properties │ │ ├── rip.properties │ │ ├── LabelsBundle_porrisavvo_FI.properties │ │ ├── LabelsBundle_in_ID.properties │ │ ├── LabelsBundle_fi_FI.properties │ │ ├── LabelsBundle_nl_NL.properties │ │ └── LabelsBundle_ru_RU.properties │ └── java │ │ └── com │ │ └── rarchives │ │ └── ripme │ │ ├── ui │ │ ├── RipStatusHandler.java │ │ ├── RipStatusComplete.java │ │ ├── RipStatusMessage.java │ │ └── HistoryEntry.java │ │ ├── ripper │ │ ├── rippers │ │ │ ├── BaraagRipper.java │ │ │ ├── ArtAlleyRipper.java │ │ │ ├── MastodonXyzRipper.java │ │ │ ├── PawooRipper.java │ │ │ ├── XlecxRipper.java │ │ │ ├── ArtstnRipper.java │ │ │ ├── ReadcomicRipper.java │ │ │ ├── RulePornRipper.java │ │ │ ├── ModelxRipper.java │ │ │ ├── tamindirmp3.java │ │ │ ├── GfycatporntubeRipper.java │ │ │ ├── CyberdropRipper.java │ │ │ ├── PornpicsRipper.java │ │ │ ├── KingcomixRipper.java │ │ │ ├── FemjoyhunterRipper.java │ │ │ ├── ShesFreakyRipper.java │ │ │ ├── MyreadingmangaRipper.java │ │ │ ├── ImgboxRipper.java │ │ │ ├── video │ │ │ │ ├── StickyXXXRipper.java │ │ │ │ ├── VidearnRipper.java │ │ │ │ ├── ViddmeRipper.java │ │ │ │ └── MotherlessVideoRipper.java │ │ │ ├── ripperhelpers │ │ │ │ └── ChanSite.java │ │ │ ├── MyhentaigalleryRipper.java │ │ │ ├── FitnakedgirlsRipper.java │ │ │ ├── XcartxRipper.java │ │ │ ├── YoupornRipper.java │ │ │ ├── ModelmayhemRipper.java │ │ │ ├── FolioRipper.java │ │ │ └── YuvutuRipper.java │ │ ├── RipperInterface.java │ │ ├── AbstractSingleFileRipper.java │ │ └── DownloadThreadPool.java │ │ └── utils │ │ └── UTF8Control.java ├── test │ └── java │ │ └── com │ │ └── rarchives │ │ └── ripme │ │ └── tst │ │ ├── ripper │ │ └── rippers │ │ │ ├── tamindirmp3Test.java │ │ │ ├── JabArchivesRipperTest.java │ │ │ ├── CfakeRipperTest.java │ │ │ ├── HentaifoxRipperTest.java │ │ │ ├── OglafRipperTest.java │ │ │ ├── PawooRipperTest.java │ │ │ ├── PorncomixRipperTest.java │ │ │ ├── BaraagRipperTest.java │ │ │ ├── HbrowseRipperTest.java │ │ │ ├── ArtAlleyRipperTest.java │ │ │ ├── MastodonRipperTest.java │ │ │ ├── MyreadingmangaRipperTest.java │ │ │ ├── ImagearnRipperTest.java │ │ │ ├── MastodonXyzRipperTest.java │ │ │ ├── PornpicsRipperTest.java │ │ │ ├── PahealRipperTest.java │ │ │ ├── HentaidudeRipperTest.java │ │ │ ├── GirlsOfDesireRipperTest.java │ │ │ ├── AllporncomicRipperTest.java │ │ │ ├── SpankBangRipperTest.java │ │ │ ├── XcartxRipperTest.java │ │ │ ├── DribbbleRipperTest.java │ │ │ ├── MotherlessRipperTest.java │ │ │ ├── Hentai2readRipperTest.java │ │ │ ├── ViewcomicRipperTest.java │ │ │ ├── XvideosRipperTest.java │ │ │ ├── ImagebamRipperTest.java │ │ │ ├── XlecxRipperTest.java │ │ │ ├── FemjoyhunterRipperTest.java │ │ │ ├── PorncomixinfoRipperTest.java │ │ │ ├── FooktubeRipperTest.java │ │ │ ├── DuckmoviesRipperTest.java │ │ │ ├── BcfakesRipperTest.java │ │ │ ├── FivehundredpxRipperTest.java │ │ │ ├── JagodibujaRipperTest.java │ │ │ ├── FlickrRipperTest.java │ │ │ ├── HentaiimageRipperTest.java │ │ │ ├── TwodgalleriesRipperTest.java │ │ │ ├── BlackbrickroadofozRipperTest.java │ │ │ ├── HitomiRipperTest.java │ │ │ ├── ArtstnRipperTest.java │ │ │ ├── MangadexRipperTest.java │ │ │ ├── CheveretoRipperTest.java │ │ │ ├── RulePornRipperTest.java │ │ │ ├── ImgboxRipperTest.java │ │ │ ├── YoupornRipperTest.java │ │ │ ├── StickyXXXRipperTest.java │ │ │ ├── VidbleRipperTest.java │ │ │ ├── SinfestRipperTest.java │ │ │ ├── BooruRipperTest.java │ │ │ ├── NewgroundsRipperTest.java │ │ │ ├── SmuttyRipperTest.java │ │ │ ├── Rule34RipperTest.java │ │ │ ├── PicstatioRipperTest.java │ │ │ ├── NudeGalsRipperTest.java │ │ │ ├── StaRipperTest.java │ │ │ ├── TwitterRipperTest.java │ │ │ ├── MeituriRipperTest.java │ │ │ ├── ModelxRipperTest.java │ │ │ ├── TapasticRipperTest.java │ │ │ ├── ErofusRipperTest.java │ │ │ ├── TeenplanetRipperTest.java │ │ │ ├── ListalRipperTest.java │ │ │ ├── MyhentaigalleryRipperTest.java │ │ │ ├── DynastyscansRipperTest.java │ │ │ ├── ComicextraRipperTest.java │ │ │ ├── FuskatorRipperTest.java │ │ │ ├── TheyiffgalleryRipperTest.java │ │ │ ├── PichunterRipperTest.java │ │ │ ├── HentaicafeRipperTest.java │ │ │ ├── ManganeloRipperTest.java │ │ │ ├── KingcomixRipperTest.java │ │ │ ├── GfycatporntubeRipperTest.java │ │ │ ├── FolioRipperTest.java │ │ │ ├── ModelmayhemRipperTest.java │ │ │ ├── ShesFreakyRipperTest.java │ │ │ ├── ImagevenueRipperTest.java │ │ │ ├── YuvutuRipperTest.java │ │ │ ├── ErotivRipperTest.java │ │ │ ├── HentaifoundryRipperTest.java │ │ │ ├── ZizkiRipperTest.java │ │ │ ├── WebtoonsRipperTest.java │ │ │ ├── BatoRipperTest.java │ │ │ ├── HypnohubRipperTest.java │ │ │ ├── NfsfwRipperTest.java │ │ │ ├── TumblrRipperTest.java │ │ │ ├── EhentaiRipperTest.java │ │ │ ├── AerisdiesRipperTest.java │ │ │ ├── ArtStationRipperTest.java │ │ │ ├── ImagefapRipperTest.java │ │ │ ├── VscoRipperTest.java │ │ │ ├── FuraffinityRipperTest.java │ │ │ ├── HentainexusRipperTest.java │ │ │ ├── NhentaiRipperTest.java │ │ │ ├── SankakuComplexRipperTest.java │ │ │ ├── EightmusesRipperTest.java │ │ │ ├── TsuminoRipperTest.java │ │ │ ├── EromeRipperTest.java │ │ │ ├── LusciousRipperTest.java │ │ │ ├── GfycatRipperTest.java │ │ │ ├── CyberdropRipperTest.java │ │ │ ├── MyhentaicomicsRipperTest.java │ │ │ ├── PornhubRipperTest.java │ │ │ └── RedgifsRipperTest.java │ │ ├── Base64Test.java │ │ ├── ui │ │ └── RipStatusMessageTest.java │ │ ├── AbstractRipperTest.java │ │ └── proxyTest.java └── LabelsBundle_zh_CN.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── deploy.bat ├── .vscode └── settings.json ├── .travis.yml ├── workspace.code-workspace ├── deploy.ps1 ├── .project ├── .github ├── workflows │ └── maven.yml ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── SECURITY.md ├── utils ├── stylefix.sh └── style.sh ├── LICENSE.txt └── .gitignore /java: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "ripme" 2 | -------------------------------------------------------------------------------- /src/main/resources/camera.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/camera.wav -------------------------------------------------------------------------------- /src/main/resources/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/folder.png -------------------------------------------------------------------------------- /src/main/resources/gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/gear.png -------------------------------------------------------------------------------- /src/main/resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/icon.ico -------------------------------------------------------------------------------- /src/main/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/icon.png -------------------------------------------------------------------------------- /src/main/resources/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/list.png -------------------------------------------------------------------------------- /src/main/resources/stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/stop.png -------------------------------------------------------------------------------- /src/main/resources/time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/time.png -------------------------------------------------------------------------------- /src/main/resources/wrench.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/wrench.png -------------------------------------------------------------------------------- /src/main/resources/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/src/main/resources/comment.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skyme5/ripme/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/LabelsBundle_en_US.properties: -------------------------------------------------------------------------------- 1 | # This need to be empty since EN is the default language in the bundles -------------------------------------------------------------------------------- /deploy.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -c ".\deploy.ps1 -source (Join-Path target (Get-Item -Path .\target\* -Filter *.jar)[0].Name) -dest ripme.jar" 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "target/**": true, 4 | "**/.git": true, 5 | "**/.DS_Store": true, 6 | "**/*.class": true, 7 | "**/rips/**": true 8 | }, 9 | "java.configuration.updateBuildConfiguration": "automatic" 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ui/RipStatusHandler.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ui; 2 | 3 | import com.rarchives.ripme.ripper.AbstractRipper; 4 | 5 | /** 6 | * @author Mads 7 | */ 8 | public interface RipStatusHandler { 9 | 10 | void update(AbstractRipper ripper, RipStatusMessage message); 11 | 12 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | matrix: 4 | include: 5 | - jdk: openjdk9 6 | before_install: 7 | - rm "${JAVA_HOME}/lib/security/cacerts" 8 | - ln -s /etc/ssl/certs/java/cacerts "${JAVA_HOME}/lib/security/cacerts" 9 | - jdk: openjdk8 10 | 11 | after_success: 12 | - mvn clean test jacoco:report coveralls:report 13 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/tamindirmp3Test.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.tamindirmp3; 7 | 8 | public class tamindirmp3Test extends RippersTest { 9 | // TODO add a test 10 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/JabArchivesRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.JabArchivesRipper; 7 | 8 | public class JabArchivesRipperTest extends RippersTest { 9 | // TODO add a test 10 | } -------------------------------------------------------------------------------- /workspace.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "E:\\Downloads\\_Isaaku\\dev" 5 | } 6 | ], 7 | "settings": { 8 | "files.exclude": { 9 | "**/.classpath": false, 10 | "**/.project": true, 11 | "**/.settings": true, 12 | "**/.factorypath": true 13 | }, 14 | "java.configuration.updateBuildConfiguration": "automatic" 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/Base64Test.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst; 2 | 3 | import com.rarchives.ripme.utils.Base64; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import static org.junit.jupiter.api.Assertions.assertEquals; 7 | 8 | public class Base64Test { 9 | 10 | @Test 11 | public void testDecode() { 12 | assertEquals("test", new String(Base64.decode("dGVzdA=="))); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | 2 | # define the console appender 3 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender 4 | log4j.appender.stdout.Target = System.out 5 | log4j.appender.stdout.Threshold = info 6 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 7 | log4j.appender.stdout.layout.ConversionPattern = %m%n 8 | 9 | # now map our console appender as a root logger, means all log messages will go to this appender 10 | log4j.rootLogger = debug, stdout -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/CfakeRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.CfakeRipper; 7 | 8 | public class CfakeRipperTest extends RippersTest { 9 | public void testRip() throws IOException { 10 | CfakeRipper ripper = new CfakeRipper(new URL("http://cfake.com/picture/Zooey_Deschanel/1264")); 11 | testRipper(ripper); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /deploy.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [Parameter(Mandatory=$True)] 3 | [string]$source, 4 | [Parameter(Mandatory=$True)] 5 | [string]$dest 6 | ) 7 | 8 | Copy-Item -Path $source -Destination $dest 9 | 10 | $sourceHash = (Get-FileHash $source -algorithm MD5).Hash 11 | $destHash = (Get-FileHash $dest -algorithm MD5).Hash 12 | if ($sourceHash -eq $destHash) { 13 | Write-Output 'Deployed successfully.' 14 | } else { 15 | Write-Output 'Hash Mismatch: did you close ripme before deploying?' 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HentaifoxRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.HentaifoxRipper; 7 | 8 | public class HentaifoxRipperTest extends RippersTest { 9 | public void testRip() throws IOException { 10 | HentaifoxRipper ripper = new HentaifoxRipper(new URL("https://hentaifox.com/gallery/38544/")); 11 | testRipper(ripper); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/BaraagRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | public class BaraagRipper extends MastodonRipper { 7 | public BaraagRipper(URL url) throws IOException { 8 | super(url); 9 | } 10 | 11 | @Override 12 | public String getHost() { 13 | return "baraag"; 14 | } 15 | 16 | @Override 17 | public String getDomain() { 18 | return "baraag.net"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/ArtAlleyRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | public class ArtAlleyRipper extends MastodonRipper { 7 | public ArtAlleyRipper(URL url) throws IOException { 8 | super(url); 9 | } 10 | 11 | @Override 12 | public String getHost() { 13 | return "artalley"; 14 | } 15 | 16 | @Override 17 | public String getDomain() { 18 | return "artalley.social"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/OglafRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.OglafRipper; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class OglafRipperTest extends RippersTest { 11 | @Test 12 | public void testRip() throws IOException { 13 | OglafRipper ripper = new OglafRipper(new URL("http://oglaf.com/plumes/")); 14 | testRipper(ripper); 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/PawooRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.PawooRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class PawooRipperTest extends RippersTest { 10 | @Test 11 | public void testRip() throws IOException { 12 | PawooRipper ripper = new PawooRipper(new URL("https://pawoo.net/@halki/media")); 13 | testRipper(ripper); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/PorncomixRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.PorncomixRipper; 7 | 8 | public class PorncomixRipperTest extends RippersTest { 9 | public void testPorncomixAlbum() throws IOException { 10 | PorncomixRipper ripper = new PorncomixRipper(new URL("http://www.porncomix.info/lust-unleashed-desire-to-submit/")); 11 | testRipper(ripper); 12 | } 13 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/MastodonXyzRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | public class MastodonXyzRipper extends MastodonRipper { 7 | public MastodonXyzRipper(URL url) throws IOException { 8 | super(url); 9 | } 10 | 11 | @Override 12 | public String getHost() { 13 | return "mastodonxyz"; 14 | } 15 | 16 | @Override 17 | public String getDomain() { 18 | return "mastodon.xyz"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/BaraagRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.BaraagRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class BaraagRipperTest extends RippersTest { 10 | @Test 11 | public void testRip() throws IOException { 12 | BaraagRipper ripper = new BaraagRipper(new URL("https://baraag.net/@darkshadow777/media")); 13 | testRipper(ripper); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HbrowseRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.HbrowseRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class HbrowseRipperTest extends RippersTest { 10 | @Test 11 | public void testPahealRipper() throws IOException { 12 | HbrowseRipper ripper = new HbrowseRipper(new URL("https://www.hbrowse.com/21013/c00001")); 13 | testRipper(ripper); 14 | } 15 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ArtAlleyRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ArtAlleyRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class ArtAlleyRipperTest extends RippersTest { 10 | @Test 11 | public void testRip() throws IOException { 12 | ArtAlleyRipper ripper = new ArtAlleyRipper(new URL("https://artalley.social/@curator/media")); 13 | testRipper(ripper); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/MastodonRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.MastodonRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class MastodonRipperTest extends RippersTest { 10 | @Test 11 | public void testRip() throws IOException { 12 | MastodonRipper ripper = new MastodonRipper(new URL("https://mastodon.social/@pythonhub/media")); 13 | testRipper(ripper); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/MyreadingmangaRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import com.rarchives.ripme.ripper.rippers.MyreadingmangaRipper; 6 | 7 | 8 | public class MyreadingmangaRipperTest extends RippersTest { 9 | public void testRip() throws IOException { 10 | MyreadingmangaRipper ripper = new MyreadingmangaRipper(new URL("https://myreadingmanga.info/zelo-lee-brave-lover-dj-slave-market-jp/")); 11 | testRipper(ripper); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ImagearnRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ImagearnRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class ImagearnRipperTest extends RippersTest { 10 | @Test 11 | public void testImagearnRip() throws IOException { 12 | ImagearnRipper ripper = new ImagearnRipper(new URL("http://imagearn.com//gallery.php?id=578682")); 13 | testRipper(ripper); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/MastodonXyzRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.MastodonXyzRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class MastodonXyzRipperTest extends RippersTest { 10 | @Test 11 | public void testRip() throws IOException { 12 | MastodonXyzRipper ripper = new MastodonXyzRipper(new URL("https://mastodon.xyz/@artwo/media")); 13 | testRipper(ripper); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/PornpicsRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.PornpicsRipper; 7 | 8 | public class PornpicsRipperTest extends RippersTest { 9 | public void testRip() throws IOException { 10 | PornpicsRipper ripper = new PornpicsRipper(new URL("https://www.pornpics.com/galleries/pornstar-dahlia-sky-takes-a-fat-cock-in-her-butthole-wearing-fishnet-stockings/")); 11 | testRipper(ripper); 12 | } 13 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/PahealRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.PahealRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class PahealRipperTest extends RippersTest { 10 | @Test 11 | public void testPahealRipper() throws IOException { 12 | // a photo set 13 | PahealRipper ripper = new PahealRipper(new URL("http://rule34.paheal.net/post/list/bimbo/1")); 14 | testRipper(ripper); 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HentaidudeRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.HentaidudeRipper; 4 | import com.rarchives.ripme.utils.Utils; 5 | 6 | import java.io.IOException; 7 | import java.net.URL; 8 | 9 | public class HentaidudeRipperTest extends RippersTest{ 10 | 11 | public void testRip() throws IOException { 12 | HentaidudeRipper ripper = new HentaidudeRipper(new URL("https://hentaidude.com/girlfriends-4ever-dlc-2/")); 13 | testRipper(ripper); 14 | 15 | } 16 | 17 | 18 | 19 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/GirlsOfDesireRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.GirlsOfDesireRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class GirlsOfDesireRipperTest extends RippersTest { 10 | @Test 11 | public void testGirlsofdesireAlbum() throws IOException { 12 | GirlsOfDesireRipper ripper = new GirlsOfDesireRipper(new URL("http://www.girlsofdesire.org/galleries/krillia/")); 13 | testRipper(ripper); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | ripme 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/AllporncomicRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.AllporncomicRipper; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | import java.net.URL; 8 | 9 | public class AllporncomicRipperTest extends RippersTest { 10 | @Test 11 | public void testAlbum() throws IOException { 12 | AllporncomicRipper ripper = new AllporncomicRipper(new URL("https://allporncomic.com/porncomic/dnd-pvp-dungeons-dragons-fred-perry/1-dnd-pvp")); 13 | testRipper(ripper); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Java CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | matrix: 11 | os: [ubuntu-latest, windows-latest, macOS-latest] 12 | java: [1.8] 13 | include: # test newest java on one os only 14 | - os: ubuntu-latest 15 | java: 1.15 16 | 17 | 18 | steps: 19 | - uses: actions/checkout@v1 20 | - name: Set up JDK 21 | uses: actions/setup-java@v1 22 | with: 23 | java-version: ${{ matrix.java }} 24 | - name: Build with Maven 25 | run: mvn package --file pom.xml 26 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/SpankBangRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.SpankbangRipper; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class SpankBangRipperTest extends RippersTest { 10 | @Test 11 | public void testSpankBangVideo() throws IOException { 12 | SpankbangRipper ripper = new SpankbangRipper(new URL("https://spankbang.com/2a7fh/video/mdb901")); //most popular video of all time on site; should stay up 13 | testRipper(ripper); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/XcartxRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.XcartxRipper; 4 | 5 | import org.junit.jupiter.api.Disabled; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.net.URL; 10 | 11 | public class XcartxRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("Broken ripper") 14 | public void testAlbum() throws IOException { 15 | XcartxRipper ripper = new XcartxRipper(new URL("http://xcartx.com/4937-tokimeki-nioi.html")); 16 | testRipper(ripper); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/DribbbleRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.DribbbleRipper; 7 | import org.junit.jupiter.api.Disabled; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class DribbbleRipperTest extends RippersTest { 11 | @Test 12 | @Disabled("test or ripper broken") 13 | public void testDribbbleRip() throws IOException { 14 | DribbbleRipper ripper = new DribbbleRipper(new URL("https://dribbble.com/typogriff")); 15 | testRipper(ripper); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/MotherlessRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.MotherlessRipper; 7 | 8 | import org.junit.jupiter.api.Tag; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class MotherlessRipperTest extends RippersTest { 12 | @Test 13 | @Tag("flaky") 14 | public void testMotherlessAlbumRip() throws IOException { 15 | MotherlessRipper ripper = new MotherlessRipper(new URL("https://motherless.com/G1168D90")); 16 | testRipper(ripper); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/PawooRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.utils.Http; 7 | 8 | import org.jsoup.nodes.Document; 9 | import org.jsoup.select.Elements; 10 | 11 | public class PawooRipper extends MastodonRipper { 12 | public PawooRipper(URL url) throws IOException { 13 | super(url); 14 | } 15 | 16 | @Override 17 | public String getHost() { 18 | return "pawoo"; 19 | } 20 | 21 | @Override 22 | public String getDomain() { 23 | return "pawoo.net"; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/Hentai2readRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.Hentai2readRipper; 7 | import org.junit.jupiter.api.Tag; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class Hentai2readRipperTest extends RippersTest { 11 | @Test 12 | @Tag("flaky") 13 | public void testHentai2readAlbum() throws IOException { 14 | Hentai2readRipper ripper = new Hentai2readRipper(new URL("https://hentai2read.com/sm_school_memorial/1/")); 15 | testRipper(ripper); 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ViewcomicRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ViewcomicRipper; 7 | import org.junit.jupiter.api.Disabled; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class ViewcomicRipperTest extends RippersTest { 11 | @Test @Disabled("Ripper broken") 12 | public void testViewcomicRipper() throws IOException { 13 | ViewcomicRipper ripper = new ViewcomicRipper(new URL("https://view-comic.com/batman-no-mans-land-vol-1/")); 14 | testRipper(ripper); 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/XvideosRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.XvideosRipper; 7 | import com.rarchives.ripme.tst.ripper.rippers.RippersTest; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class XvideosRipperTest extends RippersTest { 11 | @Test 12 | public void testXhamsterAlbum1() throws IOException { 13 | XvideosRipper ripper = new XvideosRipper(new URL("https://www.xvideos.com/video23515878/dee_s_pool_toys")); 14 | testRipper(ripper); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ImagebamRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ImagebamRipper; 7 | import org.junit.jupiter.api.Tag; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class ImagebamRipperTest extends RippersTest { 11 | @Test 12 | @Tag("flaky") 13 | public void testImagebamRip() throws IOException { 14 | ImagebamRipper ripper = new ImagebamRipper(new URL("http://www.imagebam.com/gallery/488cc796sllyf7o5srds8kpaz1t4m78i")); 15 | testRipper(ripper); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/XlecxRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.XlecxRipper; 7 | 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class XlecxRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("Broken ripper") 14 | public void testAlbum() throws IOException { 15 | XlecxRipper ripper = new XlecxRipper(new URL("http://xlecx.com/4274-black-canary-ravished-prey.html")); 16 | testRipper(ripper); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/FemjoyhunterRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.FemjoyhunterRipper; 7 | 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class FemjoyhunterRipperTest extends RippersTest { 11 | @Test 12 | public void testRip() throws IOException { 13 | FemjoyhunterRipper ripper = new FemjoyhunterRipper(new URL( 14 | "https://www.femjoyhunter.com/alisa-i-got-nice-big-breasts-and-fine-ass-so-she-seems-to-be-a-hottest-brunette-5936/")); 15 | testRipper(ripper); 16 | } 17 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/PorncomixinfoRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.PorncomixinfoRipper; 7 | import org.junit.Test; 8 | 9 | public class PorncomixinfoRipperTest extends RippersTest { 10 | @Test 11 | public void testRip() throws IOException { 12 | PorncomixinfoRipper ripper = new PorncomixinfoRipper(new URL("https://porncomixinfo.net/chapter/alx-come-to-naught-down-in-flames-up-in-smoke-tracy-scops/alx-come-to-naught-down-in-flames-up-in-smoke-tracy-scops/")); 13 | testRipper(ripper); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 1.7.x | :white_check_mark: | 11 | | < 1.7 | :x: | 12 | 13 | ## Reporting a Vulnerability 14 | 15 | A vulnerability may be reported either on [github](https://github.com/RipMeApp/ripme/issues) 16 | or by contacting a maintainer on reddit. 17 | 18 | Maintainers with reddit accounts: 19 | * [ineedmorealts](https://www.reddit.com/user/ineedmorealts/) 20 | * [metaprime](https://www.reddit.com/user/metaprime/) 21 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/FooktubeRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.FooktubeRipper; 7 | import org.junit.jupiter.api.Disabled; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class FooktubeRipperTest extends RippersTest { 11 | @Test 12 | @Disabled("test or ripper broken") 13 | public void testFooktubeVideo() throws IOException { 14 | FooktubeRipper ripper = new FooktubeRipper(new URL("https://fooktube.com/video/641/in-the-cinema")); //pick any video from the front page 15 | testRipper(ripper); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/DuckmoviesRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.DuckmoviesRipper; 4 | 5 | import org.junit.jupiter.api.Disabled; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.net.URL; 10 | 11 | public class DuckmoviesRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("Broken ripper") 14 | public void testRip() throws IOException { 15 | DuckmoviesRipper ripper = new DuckmoviesRipper( 16 | new URL("https://palapaja.com/spyfam-stepbro-gives-in-to-stepsis-asian-persuasion/")); 17 | testRipper(ripper); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/BcfakesRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.BcfakesRipper; 7 | 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class BcfakesRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("21/06/2018 This test was disbaled as the site has experienced notable downtime") 14 | public void testRip() throws IOException { 15 | BcfakesRipper ripper = new BcfakesRipper(new URL("http://www.bcfakes.com/celebritylist/olivia-wilde/")); 16 | testRipper(ripper); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/FivehundredpxRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.FivehundredpxRipper; 7 | import org.junit.jupiter.api.Disabled; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class FivehundredpxRipperTest extends RippersTest { 11 | @Test @Disabled("Ripper is broken. See https://github.com/RipMeApp/ripme/issues/438") 12 | public void test500pxAlbum() throws IOException { 13 | FivehundredpxRipper ripper = new FivehundredpxRipper(new URL("https://marketplace.500px.com/alexander_hurman")); 14 | testRipper(ripper); 15 | } 16 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/RipperInterface.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | 7 | /** 8 | * I have no idea why I made this interface. Everything is captured within the AbstractRipper. 9 | * Oh well, here's to encapsulation and abstraction! (raises glass) 10 | * 11 | * (cheers!) 12 | */ 13 | interface RipperInterface { 14 | void rip() throws IOException; 15 | boolean canRip(URL url); 16 | URL sanitizeURL(URL url) throws MalformedURLException; 17 | void setWorkingDir(URL url) throws IOException; 18 | String getHost(); 19 | String getGID(URL url) throws MalformedURLException; 20 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/JagodibujaRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.JagodibujaRipper; 7 | import org.junit.jupiter.api.Disabled; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class JagodibujaRipperTest extends RippersTest { 11 | @Test 12 | @Disabled("fails on github ubuntu automated PR check 2020-07-29") 13 | public void testJagodibujaRipper() throws IOException { 14 | // a photo set 15 | JagodibujaRipper ripper = new JagodibujaRipper(new URL("http://www.jagodibuja.com/comic-in-me/")); 16 | testRipper(ripper); 17 | } 18 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | * Ripme version: 2 | * Java version: 3 | * Operating system: 4 | 6 | * Exact URL you were trying to rip when the problem occurred: 7 | * Please include any additional information about how to reproduce the problem: 8 | 9 | ## Expected Behavior 10 | 11 | Detail the expected behavior here. 12 | 13 | ## Actual Behavior 14 | 15 | Detail the actual (incorrect) behavior here. You can post log snippets or attach log files to your issue report. 16 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/FlickrRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.FlickrRipper; 7 | 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class FlickrRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("https://github.com/RipMeApp/ripme/issues/243") 14 | public void testFlickrAlbum() throws IOException { 15 | FlickrRipper ripper = new FlickrRipper( 16 | new URL("https://www.flickr.com/photos/leavingallbehind/sets/72157621895942720/")); 17 | testRipper(ripper); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HentaiimageRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.HentaiimageRipper; 7 | import com.rarchives.ripme.utils.Utils; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class HentaiimageRipperTest extends RippersTest { 11 | @Test 12 | public void testHentaifoundryRip() throws IOException { 13 | if (Utils.getConfigBoolean("test.run_flaky_tests", false)) { 14 | HentaiimageRipper ripper = new HentaiimageRipper(new URL("https://hentai-image.com/image/afrobull-gerudo-ongoing-12/")); 15 | testRipper(ripper); 16 | } 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/TwodgalleriesRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.TwodgalleriesRipper; 7 | 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class TwodgalleriesRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("https://github.com/RipMeApp/ripme/issues/182") 14 | public void testTwodgalleriesRip() throws IOException { 15 | TwodgalleriesRipper ripper = new TwodgalleriesRipper( 16 | new URL("http://www.2dgalleries.com/artist/regis-loisel-6477")); 17 | testRipper(ripper); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ui/RipStatusComplete.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ui; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | public class RipStatusComplete { 7 | File dir = null; 8 | int count = 0; 9 | 10 | public RipStatusComplete(File dir) { 11 | this.dir = dir; 12 | this.count = 1; 13 | } 14 | 15 | public RipStatusComplete(File dir, int count) { 16 | this.dir = dir; 17 | this.count = count; 18 | } 19 | 20 | public String getDir() { 21 | String result; 22 | try { 23 | result = this.dir.getCanonicalPath(); 24 | } catch (IOException e) { 25 | result = this.dir.toString(); 26 | } 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/BlackbrickroadofozRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.BlackbrickroadofozRipper; 4 | 5 | import org.junit.jupiter.api.Disabled; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.net.URL; 10 | 11 | public class BlackbrickroadofozRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("Commented out on 02/04/2019 because the serve has been down for a while") 14 | public void testRip() throws IOException { 15 | BlackbrickroadofozRipper ripper = new BlackbrickroadofozRipper( 16 | new URL("http://www.blackbrickroadofoz.com/comic/beginning")); 17 | testRipper(ripper); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HitomiRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.HitomiRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class HitomiRipperTest extends RippersTest { 13 | @Test 14 | @Disabled("Broken ripper") 15 | public void testRip() throws IOException { 16 | HitomiRipper ripper = new HitomiRipper(new URL("https://hitomi.la/galleries/975973.html")); 17 | testRipper(ripper); 18 | Assertions.assertTrue(ripper.getGID(new URL("https://hitomi.la/galleries/975973.html")).equals("975973")); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ArtstnRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ArtstnRipper; 7 | 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class ArtstnRipperTest extends RippersTest { 12 | @Test 13 | public void testSingleProject() throws IOException { 14 | URL url = new URL("https://artstn.co/p/JlE15Z"); 15 | testRipper(new ArtstnRipper(url)); 16 | } 17 | 18 | @Test 19 | @Disabled("Failed with cloudflare protection") 20 | public void testUserPortfolio() throws IOException { 21 | URL url = new URL("https://artstn.co/m/rv37"); 22 | testRipper(new ArtstnRipper(url)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/MangadexRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | 4 | import com.rarchives.ripme.ripper.rippers.MangadexRipper; 5 | 6 | import java.io.IOException; 7 | import java.net.URL; 8 | 9 | public class MangadexRipperTest extends RippersTest{ 10 | public void testRip() throws IOException { 11 | MangadexRipper ripper = new MangadexRipper(new URL("https://mangadex.org/chapter/467904/")); 12 | testRipper(ripper); 13 | } 14 | public class testMangaRip extends RippersTest{ 15 | 16 | public void testRip() throws IOException { 17 | MangadexRipper ripper = new MangadexRipper(new URL("https://mangadex.org/title/44625/this-croc-will-die-in-100-days")); 18 | testRipper(ripper); 19 | } 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/CheveretoRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.CheveretoRipper; 7 | import org.junit.jupiter.api.Tag; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class CheveretoRipperTest extends RippersTest { 11 | @Test 12 | public void testTagFox() throws IOException { 13 | CheveretoRipper ripper = new CheveretoRipper(new URL("http://tag-fox.com/album/Thjb")); 14 | testRipper(ripper); 15 | } 16 | @Test 17 | @Tag("flaky") 18 | public void testSubdirAlbum() throws IOException { 19 | CheveretoRipper ripper = new CheveretoRipper(new URL("https://kenzato.uk/booru/album/TnEc")); 20 | testRipper(ripper); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ui/RipStatusMessageTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ui; 2 | 3 | import com.rarchives.ripme.ui.RipStatusMessage; 4 | 5 | import org.junit.jupiter.api.Assertions; 6 | 7 | public class RipStatusMessageTest { 8 | 9 | public void testConstructor() { 10 | RipStatusMessage.STATUS loadingResource = RipStatusMessage.STATUS.LOADING_RESOURCE; 11 | String path = "path/to/file"; 12 | String toStringValue = "Loading Resource: " + path; 13 | 14 | RipStatusMessage ripStatusMessage = new RipStatusMessage(loadingResource, path); 15 | 16 | Assertions.assertEquals(loadingResource, ripStatusMessage.getStatus()); 17 | Assertions.assertEquals(path, ripStatusMessage.getObject()); 18 | Assertions.assertEquals(toStringValue, ripStatusMessage.toString()); 19 | } 20 | 21 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/RulePornRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.RulePornRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class RulePornRipperTest extends RippersTest { 11 | @Test 12 | public void testRip() throws IOException { 13 | RulePornRipper ripper = new RulePornRipper(new URL("https://ruleporn.com/tosh/")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | URL url = new URL("https://ruleporn.com/tosh/"); 20 | RulePornRipper ripper = new RulePornRipper(url); 21 | Assertions.assertEquals("tosh", ripper.getGID(url)); 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ImgboxRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ImgboxRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class ImgboxRipperTest extends RippersTest { 11 | @Test 12 | public void testImgboxRip() throws IOException { 13 | ImgboxRipper ripper = new ImgboxRipper(new URL("https://imgbox.com/g/FJPF7t26FD")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | URL url = new URL("https://imgbox.com/g/FJPF7t26FD"); 20 | ImgboxRipper ripper = new ImgboxRipper(url); 21 | Assertions.assertEquals("FJPF7t26FD", ripper.getGID(url)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/YoupornRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.YoupornRipper; 4 | import org.junit.jupiter.api.Tag; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.io.IOException; 8 | import java.net.URL; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | public class YoupornRipperTest extends RippersTest { 13 | @Test 14 | @Tag("flaky") 15 | public void testYoupornRipper() throws IOException { 16 | List contentURLs = new ArrayList<>(); 17 | contentURLs.add(new URL("http://www.youporn.com/watch/7669155/mrs-li-amateur-69-orgasm/?from=categ")); 18 | for (URL url : contentURLs) { 19 | YoupornRipper ripper = new YoupornRipper(url); 20 | testRipper(ripper); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/resources/log4j.file.properties: -------------------------------------------------------------------------------- 1 | # define the file appender 2 | log4j.appender.FILE = org.apache.log4j.RollingFileAppender 3 | log4j.appender.FILE.File = ripme.log 4 | log4j.appender.FILE.ImmediateFlush = true 5 | log4j.appender.FILE.Threshold = warn 6 | log4j.appender.FILE.maxFileSize = 20MB 7 | log4j.appender.FILE.layout = org.apache.log4j.PatternLayout 8 | log4j.appender.FILE.layout.ConversionPattern = %d %-5p %c{2} %x.%M() %m%n 9 | 10 | # define the console appender 11 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender 12 | log4j.appender.stdout.Target = System.out 13 | log4j.appender.stdout.Threshold = info 14 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 15 | log4j.appender.stdout.layout.ConversionPattern = %m%n 16 | 17 | # now map our console appender as a root logger, means all log messages will go to this appender 18 | log4j.rootLogger = debug, stdout, FILE -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/StickyXXXRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.video.StickyXXXRipper; 7 | // import com.rarchives.ripme.tst.ripper.rippers.RippersTest; 8 | import com.rarchives.ripme.utils.Utils; 9 | 10 | public class StickyXXXRipperTest extends RippersTest { 11 | 12 | public void testStickyXXXVideo() throws IOException { 13 | // This test fails on the CI - possibly due to checking for a file before it's written - so we're skipping it 14 | if (Utils.getConfigBoolean("test.run_flaky_tests", false)) { 15 | StickyXXXRipper ripper = new StickyXXXRipper(new URL("http://www.stickyxxx.com/a-very-intense-farewell/")); 16 | testRipper(ripper); 17 | } 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/VidbleRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.VidbleRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class VidbleRipperTest extends RippersTest { 11 | @Test 12 | public void testVidbleRip() throws IOException { 13 | VidbleRipper ripper = new VidbleRipper(new URL("http://www.vidble.com/album/y1oyh3zd")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | URL url = new URL("http://www.vidble.com/album/y1oyh3zd"); 20 | VidbleRipper ripper = new VidbleRipper(url); 21 | Assertions.assertEquals("y1oyh3zd", ripper.getGID(url)); 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/SinfestRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.SinfestRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class SinfestRipperTest extends RippersTest { 11 | @Test 12 | public void testRip() throws IOException { 13 | SinfestRipper ripper = new SinfestRipper(new URL("http://sinfest.net/view.php?date=2000-01-17")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | URL url = new URL("http://sinfest.net/view.php?date=2000-01-17"); 20 | SinfestRipper ripper = new SinfestRipper(url); 21 | Assertions.assertEquals("2000-01-17", ripper.getGID(url)); 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/BooruRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.BooruRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class BooruRipperTest extends RippersTest { 11 | @Test 12 | public void testRip() throws IOException { 13 | BooruRipper ripper = new BooruRipper(new URL("http://xbooru.com/index.php?page=post&s=list&tags=furry")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | URL url = new URL("http://xbooru.com/index.php?page=post&s=list&tags=furry"); 20 | BooruRipper ripper = new BooruRipper(url); 21 | Assertions.assertEquals("furry", ripper.getGID(url)); 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/NewgroundsRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.NewgroundsRipper; 4 | import org.junit.jupiter.api.Assertions; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import java.io.IOException; 8 | import java.net.URL; 9 | 10 | public class NewgroundsRipperTest extends RippersTest { 11 | @Test 12 | public void testNewgroundsRip() throws IOException { 13 | NewgroundsRipper ripper = new NewgroundsRipper(new URL("https://zone-sama.newgrounds.com/art")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | URL url = new URL("https://zone-sama.newgrounds.com/art"); 20 | NewgroundsRipper ripper = new NewgroundsRipper(url); 21 | Assertions.assertEquals("zone-sama", ripper.getGID(url)); 22 | } 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/SmuttyRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.SmuttyRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Tag; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class SmuttyRipperTest extends RippersTest { 12 | @Test 13 | @Tag("flaky") 14 | public void testRip() throws IOException { 15 | SmuttyRipper ripper = new SmuttyRipper(new URL("https://smutty.com/user/QUIGON/")); 16 | testRipper(ripper); 17 | } 18 | 19 | @Test 20 | public void testGetGID() throws IOException { 21 | URL url = new URL("https://smutty.com/user/QUIGON/"); 22 | SmuttyRipper ripper = new SmuttyRipper(url); 23 | Assertions.assertEquals("QUIGON", ripper.getGID(url)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/Rule34RipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.Rule34Ripper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class Rule34RipperTest extends RippersTest { 11 | @Test 12 | public void testShesFreakyRip() throws IOException { 13 | Rule34Ripper ripper = new Rule34Ripper(new URL("https://rule34.xxx/index.php?page=post&s=list&tags=bimbo")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | URL url = new URL("https://rule34.xxx/index.php?page=post&s=list&tags=bimbo"); 20 | Rule34Ripper ripper = new Rule34Ripper(url); 21 | Assertions.assertEquals("bimbo", ripper.getGID(url)); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/PicstatioRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.PicstatioRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class PicstatioRipperTest extends RippersTest { 11 | 12 | public void testRip() throws IOException { 13 | PicstatioRipper ripper = new PicstatioRipper(new URL("https://www.picstatio.com/aerial-view-wallpapers")); 14 | testRipper(ripper); 15 | } 16 | @Test 17 | public void testGID() throws IOException { 18 | PicstatioRipper ripper = new PicstatioRipper(new URL("https://www.picstatio.com/aerial-view-wallpapers")); 19 | Assertions.assertEquals("aerial-view-wallpapers", ripper.getGID(new URL("https://www.picstatio.com/aerial-view-wallpapers"))); 20 | } 21 | } -------------------------------------------------------------------------------- /utils/stylefix.sh: -------------------------------------------------------------------------------- 1 | echo "" 2 | echo "=====================================================" 3 | echo "Tabs are not allowed (please manually fix tabs)" 4 | echo "-----------------------------------------------------" 5 | git grep -n -P "\t" -- :/*.java | sed -e "s/\t/\x1b[7m--->\x1b[m/g" 6 | echo "=====================================================" 7 | 8 | echo "Removing trailing whitespace..." 9 | git grep -l -P "[ \t]+$" -- :/*.java | xargs -I % sed -i -r -e "s/[ \t]+$//g" % 10 | 11 | echo "Replacing '){' with ') {'..." 12 | git grep -l -P "\)\{" -- :/*.java | xargs -I % sed -i -r -e "s/\)\{/) {/g" % 13 | 14 | echo "Adding space between keywords and punctuation..." 15 | git grep -l -P "(\b(if|for|while|catch)\b[(])" -- :/*.java | xargs -I % sed -i -r -e "s/(\b(if|for|while|catch)\b[(])/\2 (/g" % 16 | git grep -l -P "(\b(else|do|try|finally)\b[{])" -- :/*.java | xargs -I % sed -i -r -e "s/(\b(else|do|try|finally)\b[{])/\2 {/g" % 17 | 18 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/NudeGalsRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.NudeGalsRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class NudeGalsRipperTest extends RippersTest { 11 | @Test 12 | public void testRip() throws IOException { 13 | NudeGalsRipper ripper = new NudeGalsRipper(new URL("https://nude-gals.com/photoshoot.php?photoshoot_id=5541")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | NudeGalsRipper ripper = new NudeGalsRipper(new URL("https://nude-gals.com/photoshoot.php?photoshoot_id=5541")); 20 | Assertions.assertEquals("5541", ripper.getGID( new URL("https://nude-gals.com/photoshoot.php?photoshoot_id=5541"))); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/StaRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.StaRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class StaRipperTest extends RippersTest { 13 | @Test 14 | @Disabled("Ripper broken, Nullpointer exception") 15 | public void testRip() throws IOException { 16 | StaRipper ripper = new StaRipper(new URL("https://sta.sh/01umpyuxi4js")); 17 | testRipper(ripper); 18 | } 19 | 20 | @Test 21 | @Disabled 22 | public void testGetGID() throws IOException { 23 | URL url = new URL("https://sta.sh/01umpyuxi4js"); 24 | StaRipper ripper = new StaRipper(url); 25 | Assertions.assertEquals("01umpyuxi4js", ripper.getGID(url)); 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/TwitterRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.TwitterRipper; 7 | 8 | import org.junit.jupiter.api.Tag; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class TwitterRipperTest extends RippersTest { 12 | @Test 13 | @Tag("flaky") 14 | public void testTwitterUserRip() throws IOException { 15 | TwitterRipper ripper = new TwitterRipper(new URL("https://twitter.com/danngamber01/media")); 16 | testRipper(ripper); 17 | } 18 | 19 | @Test 20 | @Tag("flaky") 21 | public void testTwitterSearchRip() throws IOException { 22 | TwitterRipper ripper = new TwitterRipper( 23 | new URL("https://twitter.com/search?f=tweets&q=from%3Aalinalixxx%20filter%3Aimages&src=typd")); 24 | testRipper(ripper); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/MeituriRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.MeituriRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class MeituriRipperTest extends RippersTest { 13 | @Test 14 | @Disabled("Broken ripper") 15 | public void testMeituriRip() throws IOException { 16 | MeituriRipper ripper = new MeituriRipper(new URL("https://www.meituri.com/a/14449/")); 17 | testRipper(ripper); 18 | } 19 | 20 | @Test 21 | public void testGetGID() throws IOException { 22 | URL url = new URL("https://www.meituri.com/a/14449/"); 23 | MeituriRipper ripper = new MeituriRipper(url); 24 | Assertions.assertEquals("14449", ripper.getGID(url)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ModelxRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ModelxRipper; 7 | 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class ModelxRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("ModelxRipper domain has been changes. Commenting to avoid build failure.") 14 | public void testModelxAlbum() throws IOException { 15 | ModelxRipper ripper = new ModelxRipper(new URL( 16 | "http://www.modelx.org/graphis-collection-2002-2016/ai-yuzuki-%e6%9f%9a%e6%9c%88%e3%81%82%e3%81%84-yuzuiro/")); 17 | System.out.println(ripper.getGID(new URL( 18 | "http://www.modelx.org/graphis-collection-2002-2016/ai-yuzuki-%e6%9f%9a%e6%9c%88%e3%81%82%e3%81%84-yuzuiro/"))); 19 | testRipper(ripper); 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/TapasticRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.TapasticRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class TapasticRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("ripper broken") 14 | public void testTapasticRip() throws IOException { 15 | TapasticRipper ripper = new TapasticRipper(new URL("https://tapas.io/series/TPIAG")); 16 | testRipper(ripper); 17 | } 18 | 19 | @Test 20 | public void testGetGID() throws IOException { 21 | URL url = new URL("https://tapas.io/series/TPIAG"); 22 | TapasticRipper ripper = new TapasticRipper(url); 23 | Assertions.assertEquals("series_ TPIAG", ripper.getGID(url)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ErofusRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ErofusRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class ErofusRipperTest extends RippersTest { 11 | @Test 12 | public void testRip() throws IOException { 13 | ErofusRipper ripper = new ErofusRipper(new URL("https://www.erofus.com/comics/be-story-club-comics/a-kiss/issue-1")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | ErofusRipper ripper = new ErofusRipper(new URL("https://www.erofus.com/comics/be-story-club-comics/a-kiss/issue-1")); 20 | Assertions.assertEquals("be-story-club-comics", ripper.getGID(new URL("https://www.erofus.com/comics/be-story-club-comics/a-kiss/issue-1"))); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/TeenplanetRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.TeenplanetRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class TeenplanetRipperTest extends RippersTest { 11 | @Test 12 | public void testTeenplanetRip() throws IOException { 13 | TeenplanetRipper ripper = new TeenplanetRipper(new URL("http://teenplanet.org/galleries/the-perfect-side-of-me-6588.html")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | URL url = new URL("http://teenplanet.org/galleries/the-perfect-side-of-me-6588.html"); 20 | TeenplanetRipper ripper = new TeenplanetRipper(url); 21 | Assertions.assertEquals("the-perfect-side-of-me-6588", ripper.getGID(url)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ListalRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import com.rarchives.ripme.ripper.rippers.ListalRipper; 6 | 7 | public class ListalRipperTest extends RippersTest { 8 | 9 | /** 10 | * Test for list type url. 11 | * @throws IOException 12 | */ 13 | public void testRipListType() throws IOException { 14 | ListalRipper ripper = 15 | new ListalRipper(new URL("https://www.listal.com/list/evolution-emma-stone")); 16 | testRipper(ripper); 17 | } 18 | 19 | /** 20 | * Test for folder type url. 21 | * @throws IOException 22 | */ 23 | public void testRipFolderType() throws IOException { 24 | ListalRipper ripper = 25 | new ListalRipper(new URL("https://www.listal.com/chet-atkins/pictures")); 26 | testRipper(ripper); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/MyhentaigalleryRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.MyhentaigalleryRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class MyhentaigalleryRipperTest extends RippersTest { 11 | @Test 12 | public void testMyhentaigalleryAlbum() throws IOException { 13 | MyhentaigalleryRipper ripper = new MyhentaigalleryRipper( 14 | new URL("https://myhentaigallery.com/gallery/thumbnails/9201")); 15 | testRipper(ripper); 16 | } 17 | 18 | @Test 19 | public void testGetGID() throws IOException { 20 | URL url = new URL("https://myhentaigallery.com/gallery/thumbnails/9201"); 21 | MyhentaigalleryRipper ripper = new MyhentaigalleryRipper(url); 22 | Assertions.assertEquals("9201", ripper.getGID(url)); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/DynastyscansRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.DynastyscansRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class DynastyscansRipperTest extends RippersTest { 11 | @Test 12 | public void testRip() throws IOException { 13 | DynastyscansRipper ripper = new DynastyscansRipper(new URL("https://dynasty-scans.com/chapters/under_one_roof_ch01")); 14 | testRipper(ripper); 15 | } 16 | 17 | @Test 18 | public void testGetGID() throws IOException { 19 | DynastyscansRipper ripper = new DynastyscansRipper(new URL("https://dynasty-scans.com/chapters/under_one_roof_ch01")); 20 | Assertions.assertEquals("under_one_roof_ch01", ripper.getGID(new URL("https://dynasty-scans.com/chapters/under_one_roof_ch01"))); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ComicextraRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import com.rarchives.ripme.ripper.rippers.ComicextraRipper; 6 | import org.junit.jupiter.api.Disabled; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class ComicextraRipperTest extends RippersTest { 10 | @Test 11 | public void testComicUrl() throws IOException { 12 | URL url = new URL("https://www.comicextra.com/comic/karma-police"); 13 | ComicextraRipper ripper = new ComicextraRipper(url); 14 | testRipper(ripper); 15 | } 16 | @Test 17 | @Disabled("no images found error, broken ripper?") 18 | public void testChapterUrl() throws IOException { 19 | URL url = new URL("https://www.comicextra.com/v-for-vendetta/chapter-1"); 20 | ComicextraRipper ripper = new ComicextraRipper(url); 21 | testRipper(ripper); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/FuskatorRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.FuskatorRipper; 7 | import org.junit.jupiter.api.Disabled; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class FuskatorRipperTest extends RippersTest { 11 | @Test 12 | @Disabled("test or ripper broken") 13 | public void testFuskatorAlbum() throws IOException { 14 | FuskatorRipper ripper = new FuskatorRipper(new URL("https://fuskator.com/thumbs/hqt6pPXAf9z/Shaved-Blonde-Babe-Katerina-Ambre.html")); 15 | testRipper(ripper); 16 | } 17 | @Test 18 | @Disabled("test or ripper broken") 19 | public void testUrlsWithTiled() throws IOException { 20 | FuskatorRipper ripper = new FuskatorRipper(new URL("https://fuskator.com/thumbs/hsrzk~UIFmJ/Blonde-Babe-Destiny-Dixon-Playing-With-Black-Dildo.html")); 21 | testRipper(ripper); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/TheyiffgalleryRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.TheyiffgalleryRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Tag; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class TheyiffgalleryRipperTest extends RippersTest { 12 | @Test 13 | @Tag("flaky") 14 | public void testTheyiffgallery() throws IOException { 15 | TheyiffgalleryRipper ripper = new TheyiffgalleryRipper(new URL("https://theyiffgallery.com/index?/category/4303")); 16 | testRipper(ripper); 17 | } 18 | 19 | @Test 20 | public void testGetGID() throws IOException { 21 | URL url = new URL("https://theyiffgallery.com/index?/category/4303"); 22 | TheyiffgalleryRipper ripper = new TheyiffgalleryRipper(url); 23 | Assertions.assertEquals("4303", ripper.getGID(url)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/PichunterRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.PichunterRipper; 7 | 8 | import org.junit.jupiter.api.Tag; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class PichunterRipperTest extends RippersTest { 12 | @Test 13 | @Tag("flaky") 14 | public void testPichunterModelPageRip() throws IOException { 15 | // A non-photoset 16 | PichunterRipper ripper = new PichunterRipper(new URL("https://www.pichunter.com/models/Madison_Ivy")); 17 | testRipper(ripper); 18 | } 19 | 20 | @Test 21 | @Tag("flaky") 22 | public void testPichunterGalleryRip() throws IOException { 23 | // a photo set 24 | PichunterRipper ripper = new PichunterRipper( 25 | new URL("http://www.pichunter.com/gallery/3270642/Its_not_only_those_who")); 26 | testRipper(ripper); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HentaicafeRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.HentaiCafeRipper; 7 | import org.junit.jupiter.api.Tag; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class HentaicafeRipperTest extends RippersTest { 11 | @Test 12 | @Tag("flaky") 13 | public void testHentaiCafeAlbum() throws IOException { 14 | HentaiCafeRipper ripper = new HentaiCafeRipper(new URL("https://hentai.cafe/kikuta-the-oni-in-the-room/")); 15 | testRipper(ripper); 16 | } 17 | // This album has a line break (
) in the url. Test it to make sure ripme can handle these invalid urls 18 | @Test 19 | @Tag("flaky") 20 | public void testAlbumWithInvalidChars() throws IOException { 21 | HentaiCafeRipper ripper = new HentaiCafeRipper(new URL("https://hentai.cafe/chobipero-club/")); 22 | testRipper(ripper); 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ManganeloRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ManganeloRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class ManganeloRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("no images found, test or ripper broken") 14 | public void testRip() throws IOException { 15 | ManganeloRipper ripper = new ManganeloRipper(new URL("https://manganelo.com/manga/demonic_housekeeper")); 16 | testRipper(ripper); 17 | } 18 | 19 | @Test 20 | public void testGetGID() throws IOException { 21 | URL url = new URL("https://manganelo.com/manga/demonic_housekeeper"); 22 | ManganeloRipper ripper = new ManganeloRipper(url); 23 | Assertions.assertEquals("demonic_housekeeper", ripper.getGID(url)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/KingcomixRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.KingcomixRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class KingcomixRipperTest extends RippersTest { 13 | 14 | @Test 15 | @Disabled("test or ripper broken") 16 | public void testRip() throws IOException { 17 | KingcomixRipper ripper = new KingcomixRipper(new URL("https://kingcomix.com/aunt-cumming-tracy-scops/")); 18 | testRipper(ripper); 19 | } 20 | 21 | @Test 22 | public void testGetGID() throws IOException { 23 | URL url = new URL("https://kingcomix.com/aunt-cumming-tracy-scops/"); 24 | KingcomixRipper ripper = new KingcomixRipper(url); 25 | Assertions.assertEquals("aunt-cumming-tracy-scops", ripper.getGID(url)); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Category 2 | 3 | This change is exactly one of the following (please change `[ ]` to `[x]`) to indicate which: 4 | * [ ] a bug fix (Fix #...) 5 | * [ ] a new Ripper 6 | * [ ] a refactoring 7 | * [ ] a style change/fix 8 | * [ ] a new feature 9 | 10 | 11 | # Description 12 | 13 | Please add details about your change here. 14 | 15 | 16 | # Testing 17 | 18 | Required verification: 19 | * [ ] I've verified that there are no regressions in `mvn test` (there are no new failures or errors). 20 | * [ ] I've verified that this change works as intended. 21 | * [ ] Downloads all relevant content. 22 | * [ ] Downloads content from multiple pages (as necessary or appropriate). 23 | * [ ] Saves content at reasonable file names (e.g. page titles or content IDs) to help easily browse downloaded content. 24 | * [ ] I've verified that this change did not break existing functionality (especially in the Ripper I modified). 25 | 26 | Optional but recommended: 27 | * [ ] I've added a unit test to cover my change. 28 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/GfycatporntubeRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.GfycatporntubeRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Tag; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class GfycatporntubeRipperTest extends RippersTest { 12 | @Test 13 | @Tag("flaky") 14 | public void testRip() throws IOException { 15 | GfycatporntubeRipper ripper = new GfycatporntubeRipper(new URL("https://gfycatporntube.com/blowjob-bunny-puts-on-a-show/")); 16 | testRipper(ripper); 17 | } 18 | 19 | @Test 20 | public void testGetGID() throws IOException { 21 | URL url = new URL("https://gfycatporntube.com/blowjob-bunny-puts-on-a-show/"); 22 | GfycatporntubeRipper ripper = new GfycatporntubeRipper(url); 23 | Assertions.assertEquals("blowjob-bunny-puts-on-a-show", ripper.getGID(url)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/FolioRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import com.rarchives.ripme.ripper.rippers.FolioRipper; 6 | 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class FolioRipperTest extends RippersTest { 12 | /** 13 | * Test for folio.ink ripper 14 | * @throws IOException 15 | */ 16 | @Test 17 | @Disabled("test or ripper broken") 18 | public void testFolioRip() throws IOException { 19 | FolioRipper ripper = new FolioRipper(new URL("https://folio.ink/DmBe6i")); 20 | testRipper(ripper); 21 | } 22 | 23 | @Test 24 | public void testGetGID() throws IOException { 25 | URL url = new URL("https://folio.ink/DmBe6i"); 26 | FolioRipper ripper = new FolioRipper(url); 27 | Assertions.assertEquals("DmBe6i", ripper.getGID(url)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ModelmayhemRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ModelmayhemRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class ModelmayhemRipperTest extends RippersTest { 13 | 14 | @Test 15 | @Disabled("Broken ripper") 16 | public void testModelmayhemRip() throws IOException { 17 | ModelmayhemRipper ripper = new ModelmayhemRipper( 18 | new URL("https://www.modelmayhem.com/portfolio/520206/viewall")); 19 | testRipper(ripper); 20 | } 21 | 22 | @Test 23 | public void testGetGID() throws IOException { 24 | ModelmayhemRipper ripper = new ModelmayhemRipper( 25 | new URL("https://www.modelmayhem.com/portfolio/520206/viewall")); 26 | Assertions.assertEquals("520206", ripper.getGID(new URL("https://www.modelmayhem.com/portfolio/520206/viewall"))); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/XlecxRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | public class XlecxRipper extends XcartxRipper { 10 | 11 | private Pattern p = Pattern.compile("^https?://xlecx.org/([a-zA-Z0-9_\\-]+).html"); 12 | 13 | public XlecxRipper(URL url) throws IOException { 14 | super(url); 15 | } 16 | 17 | @Override 18 | public String getHost() { 19 | return "xlecx"; 20 | } 21 | 22 | @Override 23 | public String getDomain() { 24 | return "xlecx.org"; 25 | } 26 | 27 | @Override 28 | public String getGID(URL url) throws MalformedURLException { 29 | Matcher m = p.matcher(url.toExternalForm()); 30 | if (m.matches()) { 31 | return m.group(1); 32 | } 33 | throw new MalformedURLException("Expected URL format: http://xlecx.org/comic, got: " + url); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ShesFreakyRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ShesFreakyRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class ShesFreakyRipperTest extends RippersTest { 13 | @Test 14 | @Disabled("https://github.com/RipMeApp/ripme/issues/254") 15 | public void testShesFreakyRip() throws IOException { 16 | ShesFreakyRipper ripper = new ShesFreakyRipper( 17 | new URL("http://www.shesfreaky.com/gallery/nicee-snow-bunny-579NbPjUcYa.html")); 18 | testRipper(ripper); 19 | } 20 | 21 | @Test 22 | public void testGetGID() throws IOException { 23 | URL url = new URL("http://www.shesfreaky.com/gallery/nicee-snow-bunny-579NbPjUcYa.html"); 24 | ShesFreakyRipper ripper = new ShesFreakyRipper(url); 25 | Assertions.assertEquals("nicee-snow-bunny-579NbPjUcYa", ripper.getGID(url)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ImagevenueRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ImagevenueRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class ImagevenueRipperTest extends RippersTest { 13 | @Test 14 | @Disabled("See https://github.com/RipMeApp/ripme/issues/1202") 15 | public void testImagevenueRip() throws IOException { 16 | ImagevenueRipper ripper = new ImagevenueRipper( 17 | new URL("http://img120.imagevenue.com/galshow.php?gal=gallery_1373818527696_191lo")); 18 | testRipper(ripper); 19 | } 20 | 21 | @Test 22 | public void testGetGID() throws IOException { 23 | URL url = new URL("http://img120.imagevenue.com/galshow.php?gal=gallery_1373818527696_191lo"); 24 | ImagevenueRipper ripper = new ImagevenueRipper(url); 25 | Assertions.assertEquals("gallery_1373818527696_191lo", ripper.getGID(url)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 rarchives.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/YuvutuRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.YuvutuRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class YuvutuRipperTest extends RippersTest { 11 | @Test 12 | public void testYuvutuAlbum1() throws IOException { 13 | YuvutuRipper ripper = new YuvutuRipper(new URL("http://www.yuvutu.com/modules.php?name=YuGallery&action=view&set_id=127013")); 14 | testRipper(ripper); 15 | } 16 | @Test 17 | public void testYuvutuAlbum2() throws IOException { 18 | YuvutuRipper ripper = new YuvutuRipper(new URL("http://www.yuvutu.com/modules.php?name=YuGallery&action=view&set_id=420333")); 19 | testRipper(ripper); 20 | } 21 | 22 | public void testGetGID() throws IOException { 23 | URL url = new URL("http://www.yuvutu.com/modules.php?name=YuGallery&action=view&set_id=420333"); 24 | YuvutuRipper ripper = new YuvutuRipper(url); 25 | Assertions.assertEquals("420333", ripper.getGID(url)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ErotivRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ErotivRipper; 7 | import org.junit.jupiter.api.Disabled; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class ErotivRipperTest extends RippersTest { 11 | @Test 12 | public void testGetGID() throws IOException { 13 | URL url = new URL("https://erotiv.io/e/1568314255"); 14 | ErotivRipper ripper = new ErotivRipper(url); 15 | assert("1568314255".equals(ripper.getGID(url))); 16 | } 17 | 18 | public void testRip() throws IOException { 19 | URL url = new URL("https://erotiv.io/e/1568314255"); 20 | ErotivRipper ripper = new ErotivRipper(url); 21 | testRipper(ripper); 22 | } 23 | 24 | @Test 25 | @Disabled("test or ripper broken") 26 | public void testGetURLsFromPage() throws IOException { 27 | URL url = new URL("https://erotiv.io/e/1568314255"); 28 | ErotivRipper ripper = new ErotivRipper(url); 29 | assert(1 == ripper.getURLsFromPage(ripper.getFirstPage()).size()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HentaifoundryRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.HentaifoundryRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class HentaifoundryRipperTest extends RippersTest { 11 | @Test 12 | public void testHentaifoundryRip() throws IOException { 13 | HentaifoundryRipper ripper = new HentaifoundryRipper(new URL("https://www.hentai-foundry.com/pictures/user/personalami")); 14 | testRipper(ripper); 15 | } 16 | @Test 17 | public void testHentaifoundryGetGID() throws IOException { 18 | HentaifoundryRipper ripper = new HentaifoundryRipper(new URL("https://www.hentai-foundry.com/stories/user/Rakked")); 19 | testRipper(ripper); 20 | Assertions.assertEquals("Rakked", ripper.getGID(new URL("https://www.hentai-foundry.com/stories/user/Rakked"))); 21 | } 22 | @Test 23 | public void testHentaifoundryPdfRip() throws IOException { 24 | HentaifoundryRipper ripper = new HentaifoundryRipper(new URL("https://www.hentai-foundry.com/stories/user/Rakked")); 25 | testRipper(ripper); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ZizkiRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.ZizkiRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Tag; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class ZizkiRipperTest extends RippersTest { 12 | 13 | @Test 14 | @Tag("flaky") 15 | public void testRip() throws IOException { 16 | ZizkiRipper ripper = new ZizkiRipper(new URL("http://zizki.com/dee-chorde/we-got-spirit")); 17 | testRipper(ripper); 18 | } 19 | 20 | @Test 21 | public void testGetGID() throws IOException { 22 | URL url = new URL("http://zizki.com/dee-chorde/we-got-spirit"); 23 | ZizkiRipper ripper = new ZizkiRipper(url); 24 | Assertions.assertEquals("dee-chorde", ripper.getGID(url)); 25 | } 26 | 27 | @Test 28 | @Tag("flaky") 29 | public void testAlbumTitle() throws IOException { 30 | URL url = new URL("http://zizki.com/dee-chorde/we-got-spirit"); 31 | ZizkiRipper ripper = new ZizkiRipper(url); 32 | Assertions.assertEquals("zizki_Dee Chorde_We Got Spirit", ripper.getAlbumTitle(url)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/AbstractSingleFileRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper; 2 | 3 | import com.rarchives.ripme.utils.Utils; 4 | 5 | import java.io.IOException; 6 | import java.net.URL; 7 | 8 | 9 | /** 10 | * This is just an extension of AbstractHTMLRipper that auto overrides a few things 11 | * to help cut down on copy pasted code 12 | */ 13 | public abstract class AbstractSingleFileRipper extends AbstractHTMLRipper { 14 | private int bytesTotal = 1; 15 | private int bytesCompleted = 1; 16 | 17 | protected AbstractSingleFileRipper(URL url) throws IOException { 18 | super(url); 19 | } 20 | 21 | @Override 22 | public String getStatusText() { 23 | return Utils.getByteStatusText(getCompletionPercentage(), bytesCompleted, bytesTotal); 24 | } 25 | 26 | @Override 27 | public int getCompletionPercentage() { 28 | return (int) (100 * (bytesCompleted / (float) bytesTotal)); 29 | } 30 | 31 | @Override 32 | public void setBytesTotal(int bytes) { 33 | this.bytesTotal = bytes; 34 | } 35 | 36 | @Override 37 | public void setBytesCompleted(int bytes) { 38 | this.bytesCompleted = bytes; 39 | } 40 | 41 | @Override 42 | public boolean useByteProgessBar() {return true;} 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/AbstractRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst; 2 | 3 | import com.rarchives.ripme.ripper.AbstractRipper; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | import java.net.URL; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | 12 | public class AbstractRipperTest { 13 | 14 | @Test 15 | public void testGetFileName() throws IOException { 16 | String fileName = AbstractRipper.getFileName(new URL("http://www.tsumino.com/Image/Object?name=U1EieteEGwm6N1dGszqCpA%3D%3D"), "test", "test"); 17 | assertEquals("test.test", fileName); 18 | 19 | fileName = AbstractRipper.getFileName(new URL("http://www.tsumino.com/Image/Object?name=U1EieteEGwm6N1dGszqCpA%3D%3D"), "test", null); 20 | assertEquals("test", fileName); 21 | 22 | fileName = AbstractRipper.getFileName(new URL("http://www.tsumino.com/Image/Object?name=U1EieteEGwm6N1dGszqCpA%3D%3D"), null, null); 23 | assertEquals("Object", fileName); 24 | 25 | fileName = AbstractRipper.getFileName(new URL("http://www.test.com/file.png"), null, null); 26 | assertEquals("file.png", fileName); 27 | 28 | fileName = AbstractRipper.getFileName(new URL("http://www.test.com/file."), null, null); 29 | assertEquals("file.", fileName); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/WebtoonsRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.WebtoonsRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class WebtoonsRipperTest extends RippersTest { 12 | @Test 13 | public void testWebtoonsAlbum() throws IOException { 14 | WebtoonsRipper ripper = new WebtoonsRipper(new URL("https://www.webtoons.com/en/super-hero/unordinary/episode-103/viewer?title_no=679&episode_no=109")); 15 | testRipper(ripper); 16 | } 17 | @Test 18 | public void testWedramabtoonsType() throws IOException { 19 | WebtoonsRipper ripper = new WebtoonsRipper(new URL("http://www.webtoons.com/en/drama/lookism/ep-145/viewer?title_no=1049&episode_no=145")); 20 | testRipper(ripper); 21 | } 22 | @Test 23 | @Disabled("URL format different") 24 | public void testGetGID() throws IOException { 25 | URL url = new URL("https://www.webtoons.com/en/super-hero/unordinary/episode-103/viewer?title_no=679&episode_no=109"); 26 | WebtoonsRipper ripper = new WebtoonsRipper(url); 27 | Assertions.assertEquals("super-hero", ripper.getGID(url)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/BatoRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.BatoRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class BatoRipperTest extends RippersTest { 13 | 14 | @Test 15 | @Disabled("cloudlare? gets unavailable in test but works in browser") 16 | public void testRip() throws IOException { 17 | BatoRipper ripper = new BatoRipper(new URL("https://bato.to/chapter/1207152")); 18 | testRipper(ripper); 19 | } 20 | 21 | @Test 22 | public void testGetGID() throws IOException { 23 | URL url = new URL("https://bato.to/chapter/1207152"); 24 | BatoRipper ripper = new BatoRipper(url); 25 | Assertions.assertEquals("1207152", ripper.getGID(url)); 26 | } 27 | 28 | @Test 29 | @Disabled("cloudlare? gets unavailable in test but works in browser") 30 | public void testGetAlbumTitle() throws IOException { 31 | URL url = new URL("https://bato.to/chapter/1207152"); 32 | BatoRipper ripper = new BatoRipper(url); 33 | Assertions.assertEquals("bato_1207152_I_Messed_Up_by_Teaching_at_a_Black_Gyaru_School!_Ch.2", ripper.getAlbumTitle(url)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ui/RipStatusMessage.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ui; 2 | 3 | /** 4 | * Contains information about downloaded files and rips, and their states. 5 | */ 6 | public class RipStatusMessage { 7 | 8 | public enum STATUS { 9 | LOADING_RESOURCE("Loading Resource"), 10 | DOWNLOAD_STARTED("Download Started"), 11 | DOWNLOAD_COMPLETE("Download Complete"), 12 | DOWNLOAD_ERRORED("Download Errored"), 13 | DOWNLOAD_COMPLETE_HISTORY("Download Complete History"), 14 | RIP_COMPLETE("Rip Complete"), 15 | DOWNLOAD_WARN("Download problem"), 16 | TOTAL_BYTES("Total bytes"), 17 | COMPLETED_BYTES("Completed bytes"), 18 | RIP_ERRORED("Rip Errored"), 19 | NO_ALBUM_OR_USER("No album or user"); 20 | 21 | String value; 22 | STATUS(String value) { 23 | this.value = value; 24 | } 25 | } 26 | 27 | private STATUS status; 28 | private Object object; 29 | 30 | public RipStatusMessage(STATUS status, Object object) { 31 | this.status = status; 32 | this.object = object; 33 | } 34 | 35 | public STATUS getStatus() { 36 | return status; 37 | } 38 | 39 | public Object getObject() { 40 | return object; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return status.value + ": " + object.toString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/rip.properties: -------------------------------------------------------------------------------- 1 | 2 | # Download threads to use per ripper 3 | threads.size = 5 4 | 5 | # Overwrite existing files 6 | file.overwrite = false 7 | 8 | # Number of retries on failed downloads 9 | download.retries = 1 10 | 11 | # File download timeout (in milliseconds) 12 | download.timeout = 60000 13 | 14 | # Page download timeout (in milliseconds) 15 | page.timeout = 5000 16 | 17 | # Maximum size of downloaded files in bytes (required) 18 | download.max_size = 104857600 19 | 20 | # Don't retry on 404 errors 21 | error.skip404 = true 22 | 23 | # API creds 24 | twitter.auth = VW9Ybjdjb1pkd2J0U3kwTUh2VXVnOm9GTzVQVzNqM29LQU1xVGhnS3pFZzhKbGVqbXU0c2lHQ3JrUFNNZm8= 25 | tumblr.auth = JFNLu3CbINQjRdUvZibXW9VpSEVYYtiPJ86o8YmvgLZIoKyuNX 26 | gw.api = gonewild 27 | 28 | twitter.max_requests = 10 29 | twitter.rip_retweets = false 30 | 31 | clipboard.autorip = false 32 | 33 | download.save_order = true 34 | 35 | ## Reddit ripper configs 36 | # Determines whether or not to filter reddit ripping by upvote 37 | # Enables the reddit.min_upvotes and reddit.max_upvotes properties when true 38 | reddit.rip_by_upvote = false 39 | 40 | # Only rips file if the number of upvotes is equal to or greater than this value 41 | # Requires reddit.rip_by_upvote = true 42 | reddit.min_upvotes = 0 43 | 44 | # Only rips files if the number of upvotes is less than this value 45 | # Requires reddit.rip_by_upvote = true 46 | reddit.max_upvotes = 10000 47 | 48 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HypnohubRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.HypnohubRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class HypnohubRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("wants a hunman") 14 | public void testRip() throws IOException { 15 | URL poolURL = new URL("http://hypnohub.net/pool/show/2303"); 16 | URL postURL = new URL("http://hypnohub.net/post/show/63464/black_hair-bracelet-collar-corruption-female_only-"); 17 | HypnohubRipper ripper = new HypnohubRipper(poolURL); 18 | testRipper(ripper); 19 | ripper = new HypnohubRipper(postURL); 20 | testRipper(ripper); 21 | } 22 | @Test 23 | public void testGetGID() throws IOException { 24 | URL poolURL = new URL("http://hypnohub.net/pool/show/2303"); 25 | HypnohubRipper ripper = new HypnohubRipper(poolURL); 26 | Assertions.assertEquals("2303", ripper.getGID(poolURL)); 27 | 28 | URL postURL = new URL("http://hypnohub.net/post/show/63464/black_hair-bracelet-collar-corruption-female_only-"); 29 | Assertions.assertEquals("63464_black_hair-bracelet-collar-corruption-female_only-", ripper.getGID(postURL)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/NfsfwRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.NfsfwRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class NfsfwRipperTest extends RippersTest { 13 | 14 | @Test 15 | @Disabled("https://github.com/RipMeApp/ripme/issues/291 -- nfsfw 'account suspended' error; disabled flaky test in CI") 16 | public void testNfsfwRip() throws IOException { 17 | NfsfwRipper ripper = new NfsfwRipper(new URL("http://nfsfw.com/gallery/v/Kitten/")); 18 | testRipper(ripper); 19 | } 20 | 21 | @Test 22 | public void testGetGID() throws IOException { 23 | URL url = new URL("http://nfsfw.com/gallery/v/Kitten/"); 24 | NfsfwRipper ripper = new NfsfwRipper(url); 25 | Assertions.assertEquals("Kitten", ripper.getGID(url)); 26 | url = new URL("http://nfsfw.com/gallery/v/Kitten"); 27 | Assertions.assertEquals("Kitten", ripper.getGID(url)); 28 | url = new URL("http://nfsfw.com/gallery/v/Kitten/gif_001/"); 29 | Assertions.assertEquals("Kitten__gif_001", ripper.getGID(url)); 30 | url = new URL("http://nfsfw.com/gallery/v/Kitten/gif_001/"); 31 | Assertions.assertEquals("Kitten__gif_001", ripper.getGID(url)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/TumblrRipperTest.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rarchives.ripme.tst.ripper.rippers; 3 | 4 | import java.io.IOException; 5 | import java.net.URL; 6 | 7 | import com.rarchives.ripme.ripper.rippers.TumblrRipper; 8 | 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class TumblrRipperTest extends RippersTest { 13 | @Test 14 | @Disabled 15 | public void testTumblrFullRip() throws IOException { 16 | TumblrRipper ripper = new TumblrRipper(new URL("http://wrouinr.tumblr.com")); 17 | testRipper(ripper); 18 | } 19 | 20 | @Test 21 | @Disabled 22 | public void testTumblrTagRip() throws IOException { 23 | TumblrRipper ripper = new TumblrRipper(new URL("https://these-are-my-b-sides.tumblr.com/tagged/boobs")); 24 | testRipper(ripper); 25 | } 26 | 27 | @Test 28 | @Disabled 29 | public void testTumblrPostRip() throws IOException { 30 | TumblrRipper ripper = new TumblrRipper(new URL("http://sadbaffoon.tumblr.com/post/132045920789/what-a-hoe")); 31 | testRipper(ripper); 32 | } 33 | 34 | @Test 35 | @Disabled("Commented out because the test link is 404ing") 36 | public void testEmbeddedImage() throws IOException { 37 | TumblrRipper ripper = new TumblrRipper( 38 | new URL("https://these-are-my-b-sides.tumblr.com/post/178225921524/this-was-fun")); 39 | testRipper(ripper); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/EhentaiRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.util.List; 6 | 7 | import com.rarchives.ripme.ripper.rippers.EHentaiRipper; 8 | import com.rarchives.ripme.utils.RipUtils; 9 | import org.junit.jupiter.api.Assertions; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class EhentaiRipperTest extends RippersTest { 13 | @Test 14 | public void testEHentaiAlbum() throws IOException { 15 | EHentaiRipper ripper = new EHentaiRipper(new URL("https://e-hentai.org/g/1144492/e823bdf9a5/")); 16 | testRipper(ripper); 17 | } 18 | 19 | // Test the tag black listing 20 | @Test 21 | public void testTagBlackList() throws IOException { 22 | URL url = new URL("https://e-hentai.org/g/1228503/1a2f455f96/"); 23 | EHentaiRipper ripper = new EHentaiRipper(url); 24 | List tagsOnPage = ripper.getTags(ripper.getFirstPage()); 25 | // Test multiple blacklisted tags 26 | String[] tags = {"test", "one", "yuri"}; 27 | String blacklistedTag = RipUtils.checkTags(tags, tagsOnPage); 28 | Assertions.assertEquals("yuri", blacklistedTag); 29 | 30 | // test tags with spaces in them 31 | String[] tags2 = {"test", "one", "midnight on mars"}; 32 | blacklistedTag = RipUtils.checkTags(tags2, tagsOnPage); 33 | Assertions.assertEquals("midnight on mars", blacklistedTag); 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/AerisdiesRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.AerisdiesRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Tag; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class AerisdiesRipperTest extends RippersTest { 13 | @Test 14 | @Tag("flaky") 15 | public void testAlbum() throws IOException { 16 | AerisdiesRipper ripper = new AerisdiesRipper(new URL("http://www.aerisdies.com/html/lb/alb_1097_1.html")); 17 | testRipper(ripper); 18 | } 19 | 20 | @Test 21 | @Tag("flaky") 22 | public void testSubAlbum() throws IOException { 23 | AerisdiesRipper ripper = new AerisdiesRipper(new URL("http://www.aerisdies.com/html/lb/alb_3692_1.html")); 24 | testRipper(ripper); 25 | } 26 | 27 | @Test 28 | public void testDjAlbum() throws IOException { 29 | AerisdiesRipper ripper = new AerisdiesRipper(new URL("http://www.aerisdies.com/html/lb/douj_5230_1.html")); 30 | testRipper(ripper); 31 | } 32 | 33 | @Test 34 | public void testGetGID() throws IOException { 35 | URL url = new URL("http://www.aerisdies.com/html/lb/douj_5230_1.html"); 36 | AerisdiesRipper ripper = new AerisdiesRipper(url); 37 | Assertions.assertEquals("5230", ripper.getGID(url)); 38 | } 39 | 40 | // TODO: Add a test for an album with a title. 41 | } 42 | -------------------------------------------------------------------------------- /utils/style.sh: -------------------------------------------------------------------------------- 1 | echo "" 2 | echo "=====================================================" 3 | echo "Tabs are not allowed" 4 | echo "-----------------------------------------------------" 5 | git grep -n -P "\t" -- :/*.java | sed -e "s/\t/\x1b[7m--->\x1b[m/g" 6 | echo "=====================================================" 7 | 8 | echo "" 9 | echo "=====================================================" 10 | echo "Trailing whitespace is not allowed" 11 | echo "-----------------------------------------------------" 12 | git grep -n -P "[ \t]+$" -- :/*.java | sed -e "s/\t/\x1b[7m--->\x1b[m/g" | sed -e "s/ /\x1b[7m.\x1b[m/g" | sed -e "s/$/\x1b[7m$\x1b[m/g" 13 | echo "=====================================================" 14 | 15 | echo "" 16 | echo "=====================================================" 17 | echo "'){' is not allowed. Place a space between ')' and '{', i.e. 'if (a) {'" 18 | echo "-----------------------------------------------------" 19 | git grep -n -P "\)\{" -- :/*.java 20 | echo "=====================================================" 21 | 22 | echo "" 23 | echo "=====================================================" 24 | echo "A space is required after keywords (if|else|for|while|do|try|catch|finally)" 25 | echo "-----------------------------------------------------" 26 | git grep -n -P "(\b(if|for|while|catch)\b[(])|(\b(else|do|try|finally)\b[{])" -- :/*.java | sed -r -e "s/(\b(if|for|while|catch)\b[(])|(\b(else|do|try|finally)\b[{])/\x1b[7m\0\x1b[m/g" 27 | echo "=====================================================" 28 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ArtStationRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import com.rarchives.ripme.ripper.rippers.ArtStationRipper; 9 | 10 | import org.junit.jupiter.api.Tag; 11 | import org.junit.jupiter.api.Test; 12 | 13 | public class ArtStationRipperTest extends RippersTest { 14 | 15 | @Test 16 | @Tag("flaky") 17 | public void testArtStationProjects() throws IOException { 18 | List contentURLs = new ArrayList<>(); 19 | contentURLs.add(new URL("https://www.artstation.com/artwork/the-dwarf-mortar")); 20 | contentURLs.add(new URL("https://www.artstation.com/artwork/K36GR")); 21 | contentURLs.add(new URL("http://artstation.com/artwork/5JJQw")); 22 | for (URL url : contentURLs) { 23 | ArtStationRipper ripper = new ArtStationRipper(url); 24 | testRipper(ripper); 25 | } 26 | } 27 | 28 | @Test 29 | @Tag("flaky") 30 | public void testArtStationUserProfiles() throws IOException { 31 | List contentURLs = new ArrayList<>(); 32 | contentURLs.add(new URL("https://www.artstation.com/heitoramatsu")); 33 | contentURLs.add(new URL("https://artstation.com/kuvshinov_ilya")); 34 | contentURLs.add(new URL("http://artstation.com/givemeapiggy")); 35 | for (URL url : contentURLs) { 36 | ArtStationRipper ripper = new ArtStationRipper(url); 37 | testRipper(ripper); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/ImagefapRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import com.rarchives.ripme.ripper.rippers.ImagefapRipper; 9 | import org.junit.jupiter.api.Assertions; 10 | import org.junit.jupiter.api.Tag; 11 | import org.junit.jupiter.api.Test; 12 | 13 | public class ImagefapRipperTest extends RippersTest { 14 | @Test 15 | @Tag("flaky") 16 | public void testImagefapAlbums() throws IOException { 17 | Map testURLs = new HashMap<>(); 18 | 19 | // Album with specific title 20 | testURLs.put(new URL("http://www.imagefap.com/pictures/4649440/Frozen-%28Elsa-and-Anna%29?view=2"), 21 | "Frozen (Elsa and Anna)"); 22 | 23 | // New URL format 24 | testURLs.put(new URL("http://www.imagefap.com/gallery.php?pgid=fffd68f659befa5535cf78f014e348f1"), 25 | "imagefap_fffd68f659befa5535cf78f014e348f1"); 26 | 27 | for (URL url : testURLs.keySet()) { 28 | ImagefapRipper ripper = new ImagefapRipper(url); 29 | testRipper(ripper); 30 | } 31 | } 32 | @Test 33 | @Tag("flaky") 34 | public void testImagefapGetAlbumTitle() throws IOException { 35 | URL url = new URL("https://www.imagefap.com/gallery.php?gid=7789753"); 36 | ImagefapRipper ripper = new ImagefapRipper(url); 37 | Assertions.assertEquals("imagefap_Red.Heels.Lover.In.Love_7789753", ripper.getAlbumTitle(url)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/VscoRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.VscoRipper; 4 | 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.io.IOException; 9 | import java.net.URL; 10 | 11 | public class VscoRipperTest extends RippersTest { 12 | 13 | /** 14 | * Testing single image. 15 | * 16 | * @throws IOException 17 | */ 18 | @Test 19 | public void testSingleImageRip() throws IOException { 20 | VscoRipper ripper = new VscoRipper(new URL("https://vsco.co/jonathangodoy/media/5d1aec76bb669a128035e98a")); 21 | testRipper(ripper); 22 | } 23 | 24 | /** 25 | * Tests profile rip., Prevents Bug #679 from happening again. 26 | * https://github.com/RipMeApp/ripme/issues/679 27 | * 28 | * @throws IOException 29 | */ 30 | @Test 31 | public void testHyphenatedRip() throws IOException { 32 | VscoRipper ripper = new VscoRipper(new URL("https://vsco.co/jolly-roger/gallery")); 33 | testRipper(ripper); 34 | } 35 | 36 | /** 37 | * Make sure it names the folder something sensible. 38 | * 39 | * @throws IOException 40 | */ 41 | @Test 42 | public void testGetGID() throws IOException { 43 | URL url = new URL("https://vsco.co/jolly-roger/media/590359c4ade3041f2658f407"); 44 | 45 | VscoRipper ripper = new VscoRipper(url); 46 | 47 | Assertions.assertEquals("jolly-roger/59035", ripper.getGID(url), "Failed to get GID"); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/FuraffinityRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.FuraffinityRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Tag; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class FuraffinityRipperTest extends RippersTest { 12 | @Test 13 | @Tag("slow") 14 | public void testFuraffinityAlbum() throws IOException { 15 | FuraffinityRipper ripper = new FuraffinityRipper(new URL("https://www.furaffinity.net/gallery/spencerdragon/")); 16 | testRipper(ripper); 17 | } 18 | @Test 19 | @Tag("slow") 20 | public void testFuraffinityScrap() throws IOException { 21 | FuraffinityRipper ripper = new FuraffinityRipper(new URL("http://www.furaffinity.net/scraps/sssonic2/")); 22 | testRipper(ripper); 23 | } 24 | 25 | @Test 26 | public void testGetGID() throws IOException { 27 | URL url = new URL("https://www.furaffinity.net/gallery/mustardgas/"); 28 | FuraffinityRipper ripper = new FuraffinityRipper(url); 29 | Assertions.assertEquals("mustardgas", ripper.getGID(url)); 30 | } 31 | @Test 32 | public void testLogin() throws IOException { 33 | URL url = new URL("https://www.furaffinity.net/gallery/mustardgas/"); 34 | FuraffinityRipper ripper = new FuraffinityRipper(url); 35 | // Check if the first page contain the username of ripmes shared account 36 | boolean containsUsername = ripper.getFirstPage().html().contains("ripmethrowaway"); 37 | assert containsUsername; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/ArtstnRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | 7 | import org.jsoup.Connection.Response; 8 | 9 | import com.rarchives.ripme.utils.Http; 10 | 11 | /* 12 | * Ripper for ArtStation's short URL domain. 13 | * Example URL: https://artstn.co/p/JlE15Z 14 | */ 15 | 16 | public class ArtstnRipper extends ArtStationRipper { 17 | public URL artStationUrl = null; 18 | 19 | public ArtstnRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public boolean canRip(URL url) { 25 | return url.getHost().endsWith("artstn.co"); 26 | } 27 | 28 | @Override 29 | public String getGID(URL url) throws MalformedURLException { 30 | if (artStationUrl == null) { 31 | // Run only once. 32 | try { 33 | artStationUrl = getFinalUrl(url); 34 | if (artStationUrl == null) { 35 | throw new IOException("Null url received."); 36 | } 37 | } catch (IOException e) { 38 | LOGGER.error("Couldnt resolve URL.", e); 39 | } 40 | 41 | } 42 | return super.getGID(artStationUrl); 43 | } 44 | 45 | public URL getFinalUrl(URL url) throws IOException { 46 | if (url.getHost().endsWith("artstation.com")) { 47 | return url; 48 | } 49 | 50 | LOGGER.info("Checking url: " + url); 51 | Response response = Http.url(url).connection().followRedirects(false).execute(); 52 | if (response.statusCode() / 100 == 3 && response.hasHeader("location")) { 53 | return getFinalUrl(new URL(response.header("location"))); 54 | } else { 55 | return null; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/ReadcomicRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | 14 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 15 | import com.rarchives.ripme.utils.Http; 16 | 17 | public class ReadcomicRipper extends ViewcomicRipper { 18 | 19 | public ReadcomicRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return "read-comic"; 26 | } 27 | 28 | @Override 29 | public String getDomain() { 30 | return "read-comic.com"; 31 | } 32 | 33 | 34 | 35 | @Override 36 | public String getGID(URL url) throws MalformedURLException { 37 | Pattern p = Pattern.compile("https?://read-comic.com/([a-zA-Z1-9_-]*)/?$"); 38 | Matcher m = p.matcher(url.toExternalForm()); 39 | if (m.matches()) { 40 | return m.group(1); 41 | } 42 | throw new MalformedURLException("Expected view-comic URL format: " + 43 | "read-comic.com/COMIC_NAME - got " + url + " instead"); 44 | } 45 | 46 | @Override 47 | public List getURLsFromPage(Document doc) { 48 | List result = new ArrayList(); 49 | for (Element el : doc.select("div.pinbin-copy > a > img")) { 50 | result.add(el.attr("src")); 51 | } 52 | return result; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/HentainexusRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | import com.rarchives.ripme.ripper.rippers.HentaiNexusRipper; 9 | import org.json.JSONObject; 10 | import org.junit.Assert; 11 | import org.junit.jupiter.api.Tag; 12 | import org.junit.jupiter.api.Test; 13 | 14 | public class HentainexusRipperTest extends RippersTest { 15 | @Test 16 | @Tag("flaky") 17 | public void testHentaiNexusJson() throws IOException { 18 | List testURLs = new ArrayList<>(); 19 | testURLs.add(new URL("https://hentainexus.com/view/9202")); 20 | testURLs.add(new URL("https://hentainexus.com/read/9202")); 21 | testURLs.add(new URL("https://hentainexus.com/view/9202#001")); 22 | testURLs.add(new URL("https://hentainexus.com/read/9202#001")); 23 | 24 | for (URL url : testURLs) { 25 | 26 | HentaiNexusRipper ripper = new HentaiNexusRipper(url); 27 | 28 | boolean testOK = false; 29 | try { 30 | 31 | String jsonEncodedString = ripper.getJsonEncodedStringFromPage(); 32 | String jsonDecodedString = ripper.decodeJsonString(jsonEncodedString); 33 | JSONObject json = new JSONObject(jsonDecodedString); 34 | // Fail test if JSON empty 35 | testOK = !json.isEmpty(); 36 | 37 | } catch (Exception e) { 38 | // Fail test if JSON invalid, not present or other errors 39 | testOK = false; 40 | } 41 | 42 | Assert.assertEquals(true, testOK); 43 | } 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/NhentaiRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.util.List; 6 | 7 | import com.rarchives.ripme.ripper.rippers.NhentaiRipper; 8 | import com.rarchives.ripme.utils.RipUtils; 9 | import org.junit.jupiter.api.Assertions; 10 | import org.junit.jupiter.api.Tag; 11 | import org.junit.jupiter.api.Test; 12 | 13 | public class NhentaiRipperTest extends RippersTest { 14 | public void testRip() throws IOException { 15 | NhentaiRipper ripper = new NhentaiRipper(new URL("https://nhentai.net/g/233295/")); 16 | testRipper(ripper); 17 | } 18 | 19 | public void testGetGID() throws IOException { 20 | NhentaiRipper ripper = new NhentaiRipper(new URL("https://nhentai.net/g/233295/")); 21 | Assertions.assertEquals("233295", ripper.getGID(new URL("https://nhentai.net/g/233295/"))); 22 | } 23 | 24 | // Test the tag black listing 25 | @Test 26 | @Tag("flaky") 27 | public void testTagBlackList() throws IOException { 28 | URL url = new URL("https://nhentai.net/g/233295/"); 29 | NhentaiRipper ripper = new NhentaiRipper(url); 30 | List tagsOnPage = ripper.getTags(ripper.getFirstPage()); 31 | // Test multiple blacklisted tags 32 | String[] tags = {"test", "one", "blowjob"}; 33 | String blacklistedTag = RipUtils.checkTags(tags, tagsOnPage); 34 | Assertions.assertEquals("blowjob", blacklistedTag); 35 | 36 | // test tags with spaces in them 37 | String[] tags2 = {"test", "one", "sole-female"}; 38 | blacklistedTag = RipUtils.checkTags(tags2, tagsOnPage); 39 | Assertions.assertEquals("sole-female", blacklistedTag); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ui/HistoryEntry.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ui; 2 | 3 | import java.util.Date; 4 | 5 | import org.json.JSONObject; 6 | 7 | public class HistoryEntry { 8 | 9 | public String url = "", 10 | title = "", 11 | dir = ""; 12 | public int count = 0; 13 | public Date startDate = new Date(), 14 | modifiedDate = new Date(); 15 | public boolean selected = false; 16 | 17 | public HistoryEntry() { 18 | } 19 | 20 | public HistoryEntry fromJSON(JSONObject json) { 21 | this.url = json.getString("url"); 22 | this.startDate = new Date(json.getLong("startDate")); 23 | this.modifiedDate = new Date(json.getLong("modifiedDate")); 24 | if (json.has("title")) { 25 | this.title = json.getString("title"); 26 | } 27 | if (json.has("count")) { 28 | this.count = json.getInt("count"); 29 | } 30 | if (json.has("dir")) { 31 | this.dir = json.getString("dir"); 32 | } 33 | if (json.has("selected")) { 34 | this.selected = json.getBoolean("selected"); 35 | } 36 | return this; 37 | } 38 | 39 | public JSONObject toJSON() { 40 | JSONObject json = new JSONObject(); 41 | json.put("url", this.url); 42 | json.put("startDate", this.startDate.getTime()); 43 | json.put("modifiedDate", this.modifiedDate.getTime()); 44 | json.put("title", this.title); 45 | json.put("count", this.count); 46 | json.put("selected", this.selected); 47 | return json; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | return this.url; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/DownloadThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper; 2 | 3 | import java.util.concurrent.Executors; 4 | import java.util.concurrent.ThreadPoolExecutor; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import org.apache.log4j.Logger; 8 | 9 | import com.rarchives.ripme.utils.Utils; 10 | 11 | /** 12 | * Simple wrapper around a FixedThreadPool. 13 | */ 14 | public class DownloadThreadPool { 15 | 16 | private static final Logger logger = Logger.getLogger(DownloadThreadPool.class); 17 | private ThreadPoolExecutor threadPool = null; 18 | 19 | public DownloadThreadPool() { 20 | initialize("Main"); 21 | } 22 | 23 | public DownloadThreadPool(String threadPoolName) { 24 | initialize(threadPoolName); 25 | } 26 | 27 | /** 28 | * Initializes the threadpool. 29 | * @param threadPoolName Name of the threadpool. 30 | */ 31 | private void initialize(String threadPoolName) { 32 | int threads = Utils.getConfigInteger("threads.size", 10); 33 | logger.debug("Initializing " + threadPoolName + " thread pool with " + threads + " threads"); 34 | threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(threads); 35 | } 36 | /** 37 | * For adding threads to execution pool. 38 | * @param t 39 | * Thread to be added. 40 | */ 41 | public void addThread(Thread t) { 42 | threadPool.execute(t); 43 | } 44 | 45 | /** 46 | * Tries to shutdown threadpool. 47 | */ 48 | public void waitForThreads() { 49 | threadPool.shutdown(); 50 | try { 51 | threadPool.awaitTermination(3600, TimeUnit.SECONDS); 52 | } catch (InterruptedException e) { 53 | logger.error("[!] Interrupted while waiting for threads to finish: ", e); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/RulePornRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import com.rarchives.ripme.ripper.AbstractSingleFileRipper; 12 | import org.jsoup.nodes.Document; 13 | 14 | import com.rarchives.ripme.utils.Http; 15 | 16 | public class RulePornRipper extends AbstractSingleFileRipper { 17 | 18 | public RulePornRipper(URL url) throws IOException { 19 | super(url); 20 | } 21 | 22 | @Override 23 | public String getHost() { 24 | return "ruleporn"; 25 | } 26 | 27 | @Override 28 | public String getDomain() { 29 | return "ruleporn.com"; 30 | } 31 | 32 | @Override 33 | public String getGID(URL url) throws MalformedURLException { 34 | Pattern p = Pattern.compile("^https://.*ruleporn\\.com/(.*)/$"); 35 | Matcher m = p.matcher(url.toExternalForm()); 36 | if (m.matches()) { 37 | return m.group(1); 38 | } 39 | throw new MalformedURLException( 40 | "Expected ruleporn.com URL format: " + "ruleporn.com/NAME - got " + url + " instead"); 41 | } 42 | 43 | @Override 44 | public Document getFirstPage() throws IOException { 45 | return Http.url(url).get(); 46 | } 47 | 48 | @Override 49 | public List getURLsFromPage(Document doc) { 50 | List result = new ArrayList<>(); 51 | result.add(doc.select("source[type=video/mp4]").attr("src")); 52 | return result; 53 | } 54 | 55 | @Override 56 | public void downloadURL(URL url, int index) { 57 | addURLToDownload(url, getPrefix(index)); 58 | } 59 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/SankakuComplexRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.SankakuComplexRipper; 7 | 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Disabled; 10 | import org.junit.jupiter.api.Test; 11 | 12 | public class SankakuComplexRipperTest extends RippersTest { 13 | @Test 14 | @Disabled("https://github.com/RipMeApp/ripme/issues/257") 15 | public void testSankakuChanRip() throws IOException { 16 | SankakuComplexRipper ripper = new SankakuComplexRipper( 17 | new URL("https://chan.sankakucomplex.com/?tags=cleavage")); 18 | testRipper(ripper); 19 | } 20 | 21 | @Test 22 | @Disabled("https://github.com/RipMeApp/ripme/issues/257") 23 | public void testSankakuIdolRip() throws IOException { 24 | SankakuComplexRipper ripper = new SankakuComplexRipper( 25 | new URL("https://idol.sankakucomplex.com/?tags=meme_%28me%21me%21me%21%29_%28cosplay%29")); 26 | testRipper(ripper); 27 | } 28 | 29 | @Test 30 | public void testgetGID() throws IOException { 31 | URL url = new URL("https://idol.sankakucomplex.com/?tags=meme_%28me%21me%21me%21%29_%28cosplay%29"); 32 | SankakuComplexRipper ripper = new SankakuComplexRipper(url); 33 | Assertions.assertEquals("idol._meme_(me!me!me!)_(cosplay)", ripper.getGID(url)); 34 | } 35 | 36 | @Test 37 | public void testgetSubDomain() throws IOException { 38 | URL url = new URL("https://idol.sankakucomplex.com/?tags=meme_%28me%21me%21me%21%29_%28cosplay%29"); 39 | SankakuComplexRipper ripper = new SankakuComplexRipper(url); 40 | Assertions.assertEquals("idol.", ripper.getSubDomain(url)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/ModelxRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 4 | import com.rarchives.ripme.utils.Http; 5 | import org.jsoup.nodes.Document; 6 | import org.jsoup.nodes.Element; 7 | 8 | import java.io.IOException; 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | public class ModelxRipper extends AbstractHTMLRipper { 17 | 18 | public ModelxRipper(URL url) throws IOException { 19 | super(url); 20 | } 21 | 22 | @Override 23 | public String getHost() { 24 | return "modelx"; 25 | } 26 | 27 | @Override 28 | public String getDomain() { 29 | return "modelx.org"; 30 | } 31 | 32 | @Override 33 | public String getGID(URL url) throws MalformedURLException { 34 | Pattern p = Pattern.compile("^.*modelx.org/.*/(.+)$"); 35 | Matcher m = p.matcher(url.toExternalForm()); 36 | 37 | if (m.matches()) { 38 | return m.group(1); 39 | } 40 | 41 | throw new MalformedURLException("Expected URL format: http://www.modelx.org/[category (one or more)]/xxxxx got: " + url); 42 | } 43 | 44 | @Override 45 | public Document getFirstPage() throws IOException { 46 | return Http.url(url).get(); 47 | } 48 | 49 | @Override 50 | public List getURLsFromPage(Document page) { 51 | List result = new ArrayList<>(); 52 | 53 | for (Element el : page.select(".gallery-icon > a")) { 54 | result.add(el.attr("href")); 55 | } 56 | 57 | return result; 58 | } 59 | 60 | @Override 61 | public void downloadURL(URL url, int index) { 62 | addURLToDownload(url, getPrefix(index)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/EightmusesRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.EightmusesRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class EightmusesRipperTest extends RippersTest { 11 | @Test 12 | public void testEightmusesAlbum() throws IOException { 13 | // A simple image album 14 | EightmusesRipper ripper = new EightmusesRipper(new URL("https://www.8muses.com/comix/album/Affect3D-Comics/TheDude3DX/Lust-Unleashed-The-Urge-To-Explore")); 15 | testRipper(ripper); 16 | // Test the new url format 17 | ripper = new EightmusesRipper(new URL("https://www.8muses.com/comics/album/Affect3D-Comics/TheDude3DX/Lust-Unleashed-The-Urge-To-Explore")); 18 | testRipper(ripper); 19 | // Test pages with subalbums 20 | ripper = new EightmusesRipper(new URL("https://www.8muses.com/comix/album/Blacknwhitecomics_com-Comix/BlacknWhiteComics/The-Mayor")); 21 | testRipper(ripper); 22 | } 23 | @Test 24 | public void testGID() throws IOException { 25 | EightmusesRipper ripper = new EightmusesRipper(new URL("https://www.8muses.com/comix/album/Affect3D-Comics/TheDude3DX/Lust-Unleashed-The-Urge-To-Explore")); 26 | Assertions.assertEquals("Affect3D-Comics", ripper.getGID(new URL("https://www.8muses.com/comics/album/Affect3D-Comics/TheDude3DX/Lust-Unleashed-The-Urge-To-Explore"))); 27 | } 28 | @Test 29 | public void testGetSubdir() throws IOException { 30 | EightmusesRipper ripper = new EightmusesRipper(new URL("https://www.8muses.com/comix/album/Affect3D-Comics/TheDude3DX/Lust-Unleashed-The-Urge-To-Explore")); 31 | Assertions.assertEquals("After-Party-Issue-1", ripper.getSubdir("After Party - Issue 1")); 32 | } 33 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/TsuminoRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import java.util.List; 6 | 7 | import com.rarchives.ripme.ripper.rippers.TsuminoRipper; 8 | import com.rarchives.ripme.utils.RipUtils; 9 | import org.jsoup.nodes.Document; 10 | import org.junit.jupiter.api.Assertions; 11 | import org.junit.jupiter.api.Disabled; 12 | import org.junit.jupiter.api.Test; 13 | 14 | 15 | public class TsuminoRipperTest extends RippersTest { 16 | @Test 17 | @Disabled("Broken ripper") 18 | public void testTsuminoRipper() throws IOException { 19 | TsuminoRipper ripper = new TsuminoRipper(new URL("http://www.tsumino.com/Book/Info/43528/sore-wa-kurokute-suketeita-what-s-tight-and-black-and-sheer-all-over-")); 20 | testRipper(ripper); 21 | } 22 | @Test 23 | @Disabled("Broken ripper") 24 | public void testTagBlackList() throws IOException { 25 | TsuminoRipper ripper = new TsuminoRipper(new URL("http://www.tsumino.com/Book/Info/43528/sore-wa-kurokute-suketeita-what-s-tight-and-black-and-sheer-all-over-")); 26 | Document doc = ripper.getFirstPage(); 27 | List tagsOnPage = ripper.getTags(doc); 28 | String[] tags1 = {"test", "one", "Smell"}; 29 | String blacklistedTag = RipUtils.checkTags(tags1, tagsOnPage); 30 | Assertions.assertEquals("smell", blacklistedTag); 31 | 32 | // Test a tag with spaces 33 | String[] tags2 = {"test", "one", "Face sitting"}; 34 | blacklistedTag = RipUtils.checkTags(tags2, tagsOnPage); 35 | Assertions.assertEquals("face sitting", blacklistedTag); 36 | 37 | // Test a album with no blacklisted tags 38 | String[] tags3 = {"nothing", "one", "null"}; 39 | blacklistedTag = RipUtils.checkTags(tags3, tagsOnPage); 40 | Assertions.assertNull(blacklistedTag); 41 | 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/tamindirmp3.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | 14 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 15 | import com.rarchives.ripme.utils.Http; 16 | 17 | public class tamindirmp3 extends AbstractHTMLRipper { 18 | 19 | public tamindirmp3(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return "tamindir"; 26 | } 27 | @Override 28 | public String getDomain() { 29 | return "tamindir.com"; 30 | } 31 | 32 | @Override 33 | public String getGID(URL url) throws MalformedURLException { 34 | Pattern p = Pattern.compile("^https?://[server48.]*tamindir\\.com/files/([a-zA-Z0-9]+).*$"); 35 | Matcher m = p.matcher(url.toExternalForm()); 36 | if (m.matches()) { 37 | return m.group(1); 38 | } 39 | throw new MalformedURLException("Expected tamindir.com URL format: " + 40 | "tamindir.com/files/albumid - got " + url + "instead"); 41 | } 42 | 43 | @Override 44 | public Document getFirstPage() throws IOException { 45 | return Http.url(url).get(); 46 | 47 | } 48 | 49 | @Override 50 | public List getURLsFromPage(Document doc) { 51 | List music = new ArrayList<>(); 52 | for (Element el : doc.select("mp3")) { 53 | music.add(el.attr("src")); 54 | } 55 | return music; 56 | } 57 | @Override 58 | public void downloadURL(URL url, int index) { 59 | addURLToDownload(url, getPrefix(index)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/utils/UTF8Control.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.utils; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.io.InputStreamReader; 6 | import java.net.URL; 7 | import java.net.URLConnection; 8 | import java.util.Locale; 9 | import java.util.PropertyResourceBundle; 10 | import java.util.ResourceBundle; 11 | 12 | // Code taken from https://stackoverflow.com/questions/4659929/how-to-use-utf-8-in-resource-properties-with-resourcebundle/4660195#4660195 13 | 14 | public class UTF8Control extends ResourceBundle.Control { 15 | public ResourceBundle newBundle 16 | (String baseName, Locale locale, String format, ClassLoader loader, boolean reload) 17 | throws IllegalAccessException, InstantiationException, IOException 18 | { 19 | // The below is a copy of the default implementation. 20 | String bundleName = toBundleName(baseName, locale); 21 | String resourceName = toResourceName(bundleName, "properties"); 22 | ResourceBundle bundle = null; 23 | InputStream stream = null; 24 | if (reload) { 25 | URL url = loader.getResource(resourceName); 26 | if (url != null) { 27 | URLConnection connection = url.openConnection(); 28 | if (connection != null) { 29 | connection.setUseCaches(false); 30 | stream = connection.getInputStream(); 31 | } 32 | } 33 | } else { 34 | stream = loader.getResourceAsStream(resourceName); 35 | } 36 | if (stream != null) { 37 | try { 38 | // Only this line is changed to make it to read properties files as UTF-8. 39 | bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8")); 40 | } finally { 41 | stream.close(); 42 | } 43 | } 44 | return bundle; 45 | } 46 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/EromeRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | 7 | import com.rarchives.ripme.ripper.rippers.EromeRipper; 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class EromeRipperTest extends RippersTest { 12 | @Test 13 | public void testGetGIDProfilePage() throws IOException { 14 | URL url = new URL("https://www.erome.com/Jay-Jenna"); 15 | EromeRipper ripper = new EromeRipper(url); 16 | Assertions.assertEquals("Jay-Jenna", ripper.getGID(url)); 17 | } 18 | @Test 19 | public void testGetGIDAlbum() throws IOException { 20 | URL url = new URL("https://www.erome.com/a/KbDAM1XT"); 21 | EromeRipper ripper = new EromeRipper(url); 22 | Assertions.assertEquals("KbDAM1XT", ripper.getGID(url)); 23 | } 24 | @Test 25 | public void testGetAlbumsToQueue() throws IOException { 26 | URL url = new URL("https://www.erome.com/Jay-Jenna"); 27 | EromeRipper ripper = new EromeRipper(url); 28 | assert (2 >= ripper.getAlbumsToQueue(ripper.getFirstPage()).size()); 29 | } 30 | @Test 31 | public void testPageContainsAlbums() throws IOException { 32 | URL url = new URL("https://www.erome.com/Jay-Jenna"); 33 | EromeRipper ripper = new EromeRipper(url); 34 | assert (ripper.pageContainsAlbums(url)); 35 | assert (!ripper.pageContainsAlbums(new URL("https://www.erome.com/a/KbDAM1XT"))); 36 | } 37 | 38 | public void testRip() throws IOException { 39 | URL url = new URL("https://www.erome.com/a/vlefBdsg"); 40 | EromeRipper ripper = new EromeRipper(url); 41 | testRipper(ripper); 42 | } 43 | @Test 44 | public void testGetURLsFromPage() throws IOException { 45 | URL url = new URL("https://www.erome.com/a/Tak8F2h6"); 46 | EromeRipper ripper = new EromeRipper(url); 47 | assert (35 == ripper.getURLsFromPage(ripper.getFirstPage()).size()); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/GfycatporntubeRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import com.rarchives.ripme.ripper.AbstractSingleFileRipper; 12 | import org.jsoup.nodes.Document; 13 | 14 | import com.rarchives.ripme.utils.Http; 15 | 16 | public class GfycatporntubeRipper extends AbstractSingleFileRipper { 17 | 18 | public GfycatporntubeRipper(URL url) throws IOException { 19 | super(url); 20 | } 21 | 22 | @Override 23 | public String getHost() { 24 | return "gfycatporntube"; 25 | } 26 | 27 | @Override 28 | public String getDomain() { 29 | return "gfycatporntube.com"; 30 | } 31 | 32 | @Override 33 | public String getGID(URL url) throws MalformedURLException { 34 | Pattern p = Pattern.compile("https?://gfycatporntube.com/([a-zA-Z1-9_-]*)/?$"); 35 | Matcher m = p.matcher(url.toExternalForm()); 36 | if (m.matches()) { 37 | return m.group(1); 38 | } 39 | throw new MalformedURLException("Expected gfycatporntube URL format: " + 40 | "gfycatporntube.com/NAME - got " + url + " instead"); 41 | } 42 | 43 | @Override 44 | public Document getFirstPage() throws IOException { 45 | // "url" is an instance field of the superclass 46 | return Http.url(url).get(); 47 | } 48 | 49 | @Override 50 | public List getURLsFromPage(Document doc) { 51 | List result = new ArrayList<>(); 52 | result.add(doc.select("source[id=mp4Source]").attr("src")); 53 | return result; 54 | } 55 | 56 | @Override 57 | public void downloadURL(URL url, int index) { 58 | addURLToDownload(url, getPrefix(index)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/CyberdropRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.*; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 11 | import com.rarchives.ripme.utils.Http; 12 | import org.jsoup.nodes.Document; 13 | import org.jsoup.nodes.Element; 14 | 15 | public class CyberdropRipper extends AbstractHTMLRipper { 16 | 17 | public CyberdropRipper(URL url) throws IOException { 18 | super(url); 19 | } 20 | 21 | @Override 22 | public String getHost() { 23 | return "cyberdrop"; 24 | } 25 | 26 | @Override 27 | protected Document getFirstPage() throws IOException { 28 | return Http.url(url).get(); 29 | } 30 | 31 | @Override 32 | public String getDomain() { 33 | return "cyberdrop.me"; 34 | } 35 | 36 | @Override 37 | public String getGID(URL url) throws MalformedURLException { 38 | Pattern p = Pattern.compile("^https?://cyberdrop\\.me/a/([a-zA-Z0-9]+).*?$"); 39 | Matcher m = p.matcher(url.toExternalForm()); 40 | if (m.matches()) { 41 | return m.group(1); 42 | } 43 | throw new MalformedURLException("Expected cyberdrop.me URL format: " + 44 | "https://cyberdrop.me/a/xxxxxxxx - got " + url + "instead"); 45 | } 46 | 47 | @Override 48 | public void downloadURL(URL url, int index) { 49 | addURLToDownload(url, getPrefix(index)); 50 | } 51 | 52 | @Override 53 | protected List getURLsFromPage(Document page) { 54 | ArrayList urls = new ArrayList<>(); 55 | for (Element element: page.getElementsByClass("image")) { 56 | urls.add(element.attr("href")); 57 | } 58 | return urls; 59 | } 60 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/LusciousRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.LusciousRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Disabled; 9 | import org.junit.jupiter.api.Test; 10 | 11 | public class LusciousRipperTest extends RippersTest { 12 | @Test 13 | @Disabled("test or ripper broken") 14 | public void testPahealRipper() throws IOException { 15 | // a photo set 16 | LusciousRipper ripper = new LusciousRipper( 17 | new URL("https://luscious.net/albums/h-na-alice-wa-suki-desu-ka-do-you-like-alice-when_321609/")); 18 | testRipper(ripper); 19 | } 20 | 21 | @Test 22 | public void testGetGID() throws IOException { 23 | URL url = new URL("https://luscious.net/albums/h-na-alice-wa-suki-desu-ka-do-you-like-alice-when_321609/"); 24 | LusciousRipper ripper = new LusciousRipper(url); 25 | Assertions.assertEquals("h-na-alice-wa-suki-desu-ka-do-you-like-alice-when_321609", ripper.getGID(url)); 26 | } 27 | 28 | @Test 29 | @Disabled("test or ripper broken") 30 | public void testGetNextPage() throws IOException { 31 | URL multiPageAlbumUrl = new URL("https://luscious.net/albums/women-of-color_58/"); 32 | LusciousRipper multiPageRipper = new LusciousRipper(multiPageAlbumUrl); 33 | assert (multiPageRipper.getNextPage(multiPageRipper.getFirstPage()) != null); 34 | 35 | URL singlePageAlbumUrl = new URL("https://members.luscious.net/albums/bakaneko-navidarks_332097/"); 36 | LusciousRipper singlePageRipper = new LusciousRipper(singlePageAlbumUrl); 37 | try { 38 | singlePageRipper.getNextPage(singlePageRipper.getFirstPage()); 39 | } catch (IOException e) { 40 | Assertions.assertEquals("No next page found.", e.getMessage()); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/PornpicsRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 4 | import com.rarchives.ripme.utils.Http; 5 | import org.jsoup.nodes.Document; 6 | import org.jsoup.nodes.Element; 7 | 8 | import java.io.IOException; 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.regex.Matcher; 14 | import java.util.regex.Pattern; 15 | 16 | 17 | public class PornpicsRipper extends AbstractHTMLRipper { 18 | 19 | public PornpicsRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return "pornpics"; 26 | } 27 | 28 | @Override 29 | public String getDomain() { 30 | return "pornpics.com"; 31 | } 32 | 33 | @Override 34 | public String getGID(URL url) throws MalformedURLException { 35 | Pattern p = Pattern.compile("https?://www.pornpics.com/galleries/([a-zA-Z0-9_-]*)/?"); 36 | Matcher m = p.matcher(url.toExternalForm()); 37 | if (m.matches()) { 38 | return m.group(1); 39 | } 40 | throw new MalformedURLException("Expected pornpics URL format: " + 41 | "www.pornpics.com/galleries/ID - got " + url + " instead"); 42 | } 43 | 44 | @Override 45 | public Document getFirstPage() throws IOException { 46 | // "url" is an instance field of the superclass 47 | return Http.url(url).get(); 48 | } 49 | 50 | @Override 51 | public List getURLsFromPage(Document doc) { 52 | List result = new ArrayList<>(); 53 | for (Element el : doc.select("a.rel-link")) { 54 | result.add(el.attr("href")); 55 | } 56 | return result; 57 | } 58 | 59 | @Override 60 | public void downloadURL(URL url, int index) { 61 | addURLToDownload(url, getPrefix(index)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/KingcomixRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | 14 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 15 | import com.rarchives.ripme.utils.Http; 16 | 17 | public class KingcomixRipper extends AbstractHTMLRipper { 18 | 19 | public KingcomixRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return "kingcomix"; 26 | } 27 | 28 | @Override 29 | public String getDomain() { 30 | return "kingcomix.com"; 31 | } 32 | 33 | @Override 34 | public String getGID(URL url) throws MalformedURLException { 35 | Pattern p = Pattern.compile("https://kingcomix.com/([a-zA-Z1-9_-]*)/?$"); 36 | Matcher m = p.matcher(url.toExternalForm()); 37 | if (m.matches()) { 38 | return m.group(1); 39 | } 40 | throw new MalformedURLException("Expected kingcomix URL format: " + 41 | "kingcomix.com/COMIX - got " + url + " instead"); 42 | } 43 | 44 | @Override 45 | public Document getFirstPage() throws IOException { 46 | // "url" is an instance field of the superclass 47 | return Http.url(url).get(); 48 | } 49 | 50 | 51 | @Override 52 | public List getURLsFromPage(Document doc) { 53 | List result = new ArrayList<>(); 54 | for (Element el : doc.select("div.entry-content > p > img")) { 55 | result.add(el.attr("src")); 56 | } 57 | return result; 58 | } 59 | 60 | @Override 61 | public void downloadURL(URL url, int index) { 62 | addURLToDownload(url, getPrefix(index)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/GfycatRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.GfycatRipper; 4 | import org.junit.jupiter.api.Test; 5 | 6 | import java.io.IOException; 7 | import java.net.URL; 8 | 9 | 10 | public class GfycatRipperTest extends RippersTest { 11 | 12 | /** 13 | * Rips correctly formatted URL directly from Gfycat 14 | * @throws IOException 15 | */ 16 | @Test 17 | public void testGfycatGoodURL() throws IOException{ 18 | GfycatRipper ripper = new GfycatRipper(new URL("https://gfycat.com/TemptingExcellentIchthyosaurs")); 19 | testRipper(ripper); 20 | } 21 | /** 22 | * Rips badly formatted URL directly from Gfycat 23 | * @throws IOException 24 | */ 25 | public void testGfycatBadURL() throws IOException { 26 | GfycatRipper ripper = new GfycatRipper(new URL("https://gfycat.com/gifs/detail/limitedtestyamericancrow")); 27 | testRipper(ripper); 28 | } 29 | 30 | /** 31 | * Rips a Gfycat profile 32 | * @throws IOException 33 | */ 34 | public void testGfycatProfile() throws IOException { 35 | GfycatRipper ripper = new GfycatRipper(new URL("https://gfycat.com/@golbanstorage")); 36 | testRipper(ripper); 37 | } 38 | 39 | /** 40 | * Rips a Gfycat amp link 41 | * @throws IOException 42 | */ 43 | public void testGfycatAmp() throws IOException { 44 | GfycatRipper ripper = new GfycatRipper(new URL("https://gfycat.com/amp/TemptingExcellentIchthyosaurs")); 45 | testRipper(ripper); 46 | } 47 | 48 | /** 49 | * Rips a Gfycat profile with special characters in username 50 | * @throws IOException 51 | */ 52 | public void testGfycatSpecialChar() throws IOException { 53 | GfycatRipper ripper = new GfycatRipper(new URL("https://gfycat.com/@rsss.kr")); 54 | testRipper(ripper); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/CyberdropRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.CyberdropRipper; 4 | import com.rarchives.ripme.utils.Http; 5 | import org.jsoup.nodes.Document; 6 | import org.junit.jupiter.api.Assertions; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import java.io.IOException; 10 | import java.net.URL; 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | import java.util.List; 14 | import java.util.Map; 15 | 16 | public class CyberdropRipperTest extends RippersTest { 17 | @Test 18 | public void testScrolllerGID() throws IOException { 19 | Map testURLs = new HashMap<>(); 20 | 21 | testURLs.put(new URL("https://cyberdrop.me/a/n4umdBjw"), "n4umdBjw"); 22 | testURLs.put(new URL("https://cyberdrop.me/a/iLtp4BjW"), "iLtp4BjW"); 23 | for (URL url : testURLs.keySet()) { 24 | CyberdropRipper ripper = new CyberdropRipper(url); 25 | ripper.setup(); 26 | Assertions.assertEquals(testURLs.get(url), ripper.getGID(ripper.getURL())); 27 | deleteDir(ripper.getWorkingDir()); 28 | } 29 | } 30 | 31 | @Test 32 | public void testCyberdropNumberOfFiles() throws IOException { 33 | List testURLs = new ArrayList(); 34 | 35 | testURLs.add(new URL("https://cyberdrop.me/a/n4umdBjw")); 36 | testURLs.add(new URL("https://cyberdrop.me/a/iLtp4BjW")); 37 | for (URL url : testURLs) { 38 | Assertions.assertTrue(willDownloadAllFiles(url)); 39 | } 40 | } 41 | 42 | public boolean willDownloadAllFiles(URL url) throws IOException { 43 | Document doc = Http.url(url).get(); 44 | long numberOfLinks = doc.getElementsByClass("image").stream().count(); 45 | int numberOfFiles = Integer.parseInt(doc.getElementById("totalFilesAmount").text()); 46 | return numberOfLinks == numberOfFiles; 47 | } 48 | 49 | 50 | 51 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/FemjoyhunterRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | 14 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 15 | import com.rarchives.ripme.utils.Http; 16 | 17 | public class FemjoyhunterRipper extends AbstractHTMLRipper { 18 | 19 | public FemjoyhunterRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return "femjoyhunter"; 26 | } 27 | 28 | @Override 29 | public String getDomain() { 30 | return "femjoyhunter.com"; 31 | } 32 | 33 | @Override 34 | public String getGID(URL url) throws MalformedURLException { 35 | Pattern p = Pattern.compile("https?://www.femjoyhunter.com/([a-zA-Z0-9_-]+)/?"); 36 | Matcher m = p.matcher(url.toExternalForm()); 37 | if (m.matches()) { 38 | return m.group(1); 39 | } 40 | throw new MalformedURLException("Expected femjoyhunter URL format: " + 41 | "femjoyhunter.com/ID - got " + url + " instead"); 42 | } 43 | 44 | @Override 45 | public Document getFirstPage() throws IOException { 46 | // "url" is an instance field of the superclass 47 | return Http.url(url).get(); 48 | } 49 | 50 | @Override 51 | public List getURLsFromPage(Document doc) { 52 | List result = new ArrayList<>(); 53 | for (Element el : doc.select("img")) { 54 | result.add(el.attr("src")); 55 | } 56 | return result; 57 | } 58 | 59 | @Override 60 | public void downloadURL(URL url, int index) { 61 | 62 | addURLToDownload(url, getPrefix(index), "", "https://a2h6m3w6.ssl.hwcdn.net/", null); 63 | } 64 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/ShesFreakyRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | 14 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 15 | import com.rarchives.ripme.utils.Http; 16 | 17 | public class ShesFreakyRipper extends AbstractHTMLRipper { 18 | 19 | public ShesFreakyRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return "shesfreaky"; 26 | } 27 | 28 | @Override 29 | public String getDomain() { 30 | return "shesfreaky.com"; 31 | } 32 | 33 | @Override 34 | public String getGID(URL url) throws MalformedURLException { 35 | Pattern p = Pattern.compile("^https?://[wm.]*shesfreaky\\.com/gallery/([a-zA-Z0-9\\-_]+).*$"); 36 | Matcher m = p.matcher(url.toExternalForm()); 37 | if (m.matches()) { 38 | return m.group(1); 39 | } 40 | throw new MalformedURLException("Expected shesfreaky.com URL format: " 41 | + "shesfreaky.com/gallery/... - got " + url + "instead"); 42 | } 43 | 44 | @Override 45 | public Document getFirstPage() throws IOException { 46 | return Http.url(url).get(); 47 | } 48 | 49 | @Override 50 | public List getURLsFromPage(Document doc) { 51 | List imageURLs = new ArrayList<>(); 52 | for (Element thumb : doc.select("a[data-lightbox=\"gallery\"]")) { 53 | String image = thumb.attr("href"); 54 | imageURLs.add("https:" + image); 55 | } 56 | return imageURLs; 57 | } 58 | 59 | @Override 60 | public void downloadURL(URL url, int index) { 61 | addURLToDownload(url, getPrefix(index)); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/MyhentaicomicsRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.MyhentaicomicsRipper; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | 10 | public class MyhentaicomicsRipperTest extends RippersTest { 11 | @Test 12 | public void testMyhentaicomicsAlbum() throws IOException { 13 | MyhentaicomicsRipper ripper = new MyhentaicomicsRipper(new URL("http://myhentaicomics.com/index.php/Nienna-Lost-Tales")); 14 | testRipper(ripper); 15 | } 16 | 17 | public void testGetGID() throws IOException { 18 | URL url = new URL("http://myhentaicomics.com/index.php/Nienna-Lost-Tales"); 19 | MyhentaicomicsRipper ripper = new MyhentaicomicsRipper(url); 20 | // Test a comic 21 | Assertions.assertEquals("Nienna-Lost-Tales", ripper.getGID(url)); 22 | // Test a search 23 | Assertions.assertEquals("test", ripper.getGID(new URL("http://myhentaicomics.com/index.php/search?q=test"))); 24 | // Test a tag 25 | Assertions.assertEquals("2409", ripper.getGID(new URL("http://myhentaicomics.com/index.php/tag/2409/"))); 26 | } 27 | @Test 28 | public void testGetAlbumsToQueue() throws IOException { 29 | URL url = new URL("https://myhentaicomics.com/index.php/tag/3167/"); 30 | MyhentaicomicsRipper ripper = new MyhentaicomicsRipper(url); 31 | Assertions.assertEquals(15, ripper.getAlbumsToQueue(ripper.getFirstPage()).size()); 32 | } 33 | @Test 34 | public void testPageContainsAlbums() throws IOException { 35 | URL url = new URL("https://myhentaicomics.com/index.php/tag/3167/"); 36 | URL url2 = new URL("https://myhentaicomics.com/index.php/search?q=test"); 37 | MyhentaicomicsRipper ripper = new MyhentaicomicsRipper(url); 38 | Assertions.assertTrue(ripper.pageContainsAlbums(url)); 39 | Assertions.assertTrue(ripper.pageContainsAlbums(url2)); 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/PornhubRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | 6 | import com.rarchives.ripme.ripper.rippers.PornhubRipper; 7 | import com.rarchives.ripme.utils.Http; 8 | import com.rarchives.ripme.utils.Utils; 9 | import org.jsoup.nodes.Document; 10 | import org.junit.jupiter.api.Assertions; 11 | import org.junit.jupiter.api.Tag; 12 | import org.junit.jupiter.api.Test; 13 | 14 | public class PornhubRipperTest extends RippersTest { 15 | @Test 16 | public void testPornhubRip() throws IOException { 17 | if (Utils.getConfigBoolean("test.run_flaky_tests", false)) { 18 | PornhubRipper ripper = new PornhubRipper(new URL("https://www.pornhub.com/album/15680522")); 19 | testRipper(ripper); 20 | } 21 | } 22 | 23 | public void testGetGID() throws IOException { 24 | URL url = new URL("https://www.pornhub.com/album/15680522?page=2"); 25 | PornhubRipper ripper = new PornhubRipper(url); 26 | Assertions.assertEquals("15680522", ripper.getGID(url)); 27 | url = new URL("https://www.pornhub.com/album/15680522"); 28 | Assertions.assertEquals("15680522", ripper.getGID(url)); 29 | } 30 | 31 | @Test 32 | @Tag("flaky") 33 | public void testGetNextPage() throws IOException { 34 | String baseURL = "https://www.pornhub.com/album/30687901"; 35 | PornhubRipper ripper = new PornhubRipper(new URL(baseURL)); 36 | Document page = Http.url(baseURL).get(); 37 | int numPagesRemaining = 1; 38 | for (int idx = 0; idx < numPagesRemaining; idx++){ 39 | page = ripper.getNextPage(page); 40 | Assertions.assertEquals(baseURL + "?page=" + (idx + 2), page.location()); 41 | } 42 | try { 43 | page = ripper.getNextPage(page); 44 | Assertions.fail("Get next page did not throw an exception on the last page"); 45 | } catch(IOException e){ 46 | Assertions.assertEquals(e.getMessage(), "No more pages"); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/MyreadingmangaRipper.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rarchives.ripme.ripper.rippers; 3 | 4 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 5 | import com.rarchives.ripme.utils.Http; 6 | import java.io.IOException; 7 | import java.net.MalformedURLException; 8 | import java.net.URL; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | import org.jsoup.nodes.Document; 14 | import org.jsoup.nodes.Element; 15 | 16 | public class MyreadingmangaRipper extends AbstractHTMLRipper { 17 | 18 | public MyreadingmangaRipper(URL url) throws IOException { 19 | super(url); 20 | } 21 | 22 | @Override 23 | public String getHost() { 24 | return "myreadingmanga"; 25 | } 26 | 27 | @Override 28 | public String getDomain() { 29 | return "myreadingmanga.info"; 30 | } 31 | 32 | @Override 33 | public String getGID(URL url) throws MalformedURLException { 34 | Pattern p = Pattern.compile("https://myreadingmanga.info/([a-zA-Z_\\-0-9]+)/?$"); 35 | Matcher m = p.matcher(url.toExternalForm()); 36 | if (m.matches()) { 37 | return m.group(1); 38 | } 39 | 40 | throw new MalformedURLException("Expected myreadingmanga.info URL format: " 41 | + "myreadingmanga.info/title - got " + url + " instead"); 42 | } 43 | 44 | @Override 45 | public Document getFirstPage() throws IOException { 46 | // "url" is an instance field of the superclass 47 | return Http.url(url).get(); 48 | } 49 | 50 | @Override 51 | public List getURLsFromPage(Document doc) { 52 | List result = new ArrayList<>(); 53 | for (Element el : doc.select("div * img[data-lazy-src]")) { 54 | String imageSource = el.attr("data-lazy-src"); 55 | result.add(imageSource); 56 | } 57 | return result; 58 | } 59 | 60 | @Override 61 | public void downloadURL(URL url, int index) { 62 | addURLToDownload(url, getPrefix(index)); 63 | } 64 | 65 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/ImgboxRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | 14 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 15 | import com.rarchives.ripme.utils.Http; 16 | 17 | public class ImgboxRipper extends AbstractHTMLRipper { 18 | 19 | public ImgboxRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return "imgbox"; 26 | } 27 | @Override 28 | public String getDomain() { 29 | return "imgbox.com"; 30 | } 31 | 32 | @Override 33 | public String getGID(URL url) throws MalformedURLException { 34 | Pattern p = Pattern.compile("^https?://[wm.]*imgbox\\.com/g/([a-zA-Z0-9]+).*$"); 35 | Matcher m = p.matcher(url.toExternalForm()); 36 | if (m.matches()) { 37 | return m.group(1); 38 | } 39 | throw new MalformedURLException("Expected imgbox.com URL format: " + 40 | "imgbox.com/g/albumid - got " + url + "instead"); 41 | } 42 | 43 | @Override 44 | public Document getFirstPage() throws IOException { 45 | return Http.url(url).get(); 46 | } 47 | @Override 48 | public List getURLsFromPage(Document doc) { 49 | List imageURLs = new ArrayList<>(); 50 | for (Element thumb : doc.select("div.boxed-content > a > img")) { 51 | String image = thumb.attr("src").replaceAll("thumbs", "images"); 52 | image = image.replace("_b", "_o"); 53 | image = image.replaceAll("\\d-s", "i"); 54 | imageURLs.add(image); 55 | } 56 | return imageURLs; 57 | } 58 | @Override 59 | public void downloadURL(URL url, int index) { 60 | addURLToDownload(url, getPrefix(index)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/video/StickyXXXRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers.video; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | import org.jsoup.nodes.Document; 10 | import org.jsoup.select.Elements; 11 | 12 | import com.rarchives.ripme.ripper.VideoRipper; 13 | import com.rarchives.ripme.utils.Http; 14 | 15 | public class StickyXXXRipper extends VideoRipper { 16 | 17 | private static final String HOST = "stickyxxx"; 18 | 19 | public StickyXXXRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return HOST; 26 | } 27 | 28 | @Override 29 | public boolean canRip(URL url) { 30 | Pattern p = Pattern.compile("^https?://.*stickyxxx\\.com(/)(.*)/$"); 31 | Matcher m = p.matcher(url.toExternalForm()); 32 | return m.matches(); 33 | } 34 | 35 | @Override 36 | public URL sanitizeURL(URL url) throws MalformedURLException { 37 | return url; 38 | } 39 | 40 | @Override 41 | public String getGID(URL url) throws MalformedURLException { 42 | Pattern p = Pattern.compile("^https?://.*stickyxxx\\.com(/)(.*)/$"); 43 | Matcher m = p.matcher(url.toExternalForm()); 44 | if (m.matches()) { 45 | return m.group(2); 46 | } 47 | 48 | throw new MalformedURLException( 49 | "Expected stickyxxx format:" 50 | + "stickyxxx.com/####" 51 | + " Got: " + url); 52 | } 53 | 54 | @Override 55 | public void rip() throws IOException { 56 | LOGGER.info("Retrieving " + this.url); 57 | Document doc = Http.url(url).get(); 58 | Elements videos = doc.select(".wp-video > video > source"); 59 | if (videos.isEmpty()) { 60 | throw new IOException("Could not find Embed code at " + url); 61 | } 62 | String vidUrl = videos.attr("src"); 63 | addURLToDownload(new URL(vidUrl), HOST + "_" + getGID(this.url)); 64 | waitForThreads(); 65 | } 66 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/ripperhelpers/ChanSite.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers.ripperhelpers; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | 6 | public class ChanSite { 7 | // The domains where the threads are hosted. 8 | public List domains; 9 | // The domains where the images are hosted. 10 | public List cdnDomains; 11 | 12 | public ChanSite(List Domains, List CdnDomains) { 13 | if (Domains.isEmpty()) { 14 | throw new IllegalArgumentException("Domains"); 15 | } 16 | if (CdnDomains.isEmpty()) { 17 | throw new IllegalArgumentException("CdnDomains"); 18 | } 19 | domains = Domains; 20 | cdnDomains = CdnDomains; 21 | } 22 | 23 | public ChanSite(String Domain, List CdnDomains) { 24 | if (Domain.isEmpty()) { 25 | throw new IllegalArgumentException("Domains"); 26 | } 27 | if (CdnDomains.isEmpty()) { 28 | throw new IllegalArgumentException("CdnDomains"); 29 | } 30 | domains = Arrays.asList(Domain); 31 | cdnDomains = CdnDomains; 32 | } 33 | 34 | public ChanSite(String Domain, String CdnDomain) { 35 | if (Domain.isEmpty()) { 36 | throw new IllegalArgumentException("Domains"); 37 | } 38 | if (CdnDomain.isEmpty()) { 39 | throw new IllegalArgumentException("CdnDomains"); 40 | } 41 | domains = Arrays.asList(Domain); 42 | cdnDomains = Arrays.asList(CdnDomain); 43 | } 44 | 45 | public ChanSite(String Domain) { 46 | if (Domain.isEmpty()) { 47 | throw new IllegalArgumentException("Domains"); 48 | } 49 | domains = Arrays.asList(Domain); 50 | cdnDomains = Arrays.asList(Domain); 51 | } 52 | 53 | public ChanSite(List Domains) { 54 | if (Domains.isEmpty()) { 55 | throw new IllegalArgumentException("Domains"); 56 | } 57 | domains = Domains; 58 | cdnDomains = Domains; 59 | } 60 | public List getDomains() { 61 | return domains; 62 | } 63 | 64 | public List getCdns() { 65 | return cdnDomains; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/video/VidearnRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers.video; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | import org.jsoup.nodes.Document; 11 | 12 | import com.rarchives.ripme.ripper.VideoRipper; 13 | import com.rarchives.ripme.utils.Http; 14 | import com.rarchives.ripme.utils.Utils; 15 | 16 | public class VidearnRipper extends VideoRipper { 17 | 18 | private static final String HOST = "videarn"; 19 | 20 | public VidearnRipper(URL url) throws IOException { 21 | super(url); 22 | } 23 | 24 | @Override 25 | public String getHost() { 26 | return HOST; 27 | } 28 | 29 | @Override 30 | public boolean canRip(URL url) { 31 | Pattern p = Pattern.compile("^https?://[wm.]*videarn\\.com/[a-zA-Z0-9\\-]+/([0-9]+).*$"); 32 | Matcher m = p.matcher(url.toExternalForm()); 33 | return m.matches(); 34 | } 35 | 36 | @Override 37 | public URL sanitizeURL(URL url) throws MalformedURLException { 38 | return url; 39 | } 40 | 41 | @Override 42 | public String getGID(URL url) throws MalformedURLException { 43 | Pattern p = Pattern.compile("^https?://[wm.]*videarn\\.com/[a-zA-Z0-9\\-]+/([0-9]+).*$"); 44 | Matcher m = p.matcher(url.toExternalForm()); 45 | if (m.matches()) { 46 | return m.group(1); 47 | } 48 | 49 | throw new MalformedURLException( 50 | "Expected videarn format:" 51 | + "videarn.com/.../####-..." 52 | + " Got: " + url); 53 | } 54 | 55 | @Override 56 | public void rip() throws IOException { 57 | LOGGER.info("Retrieving " + this.url); 58 | Document doc = Http.url(url).get(); 59 | List mp4s = Utils.between(doc.html(), "file:\"", "\""); 60 | if (mp4s.isEmpty()) { 61 | throw new IOException("Could not find files at " + url); 62 | } 63 | String vidUrl = mp4s.get(0); 64 | addURLToDownload(new URL(vidUrl), HOST + "_" + getGID(this.url)); 65 | waitForThreads(); 66 | } 67 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/MyhentaigalleryRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 4 | import com.rarchives.ripme.utils.Http; 5 | import java.io.IOException; 6 | import java.net.MalformedURLException; 7 | import java.net.URL; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | import org.jsoup.nodes.Document; 13 | import org.jsoup.nodes.Element; 14 | 15 | public class MyhentaigalleryRipper extends AbstractHTMLRipper { 16 | 17 | public MyhentaigalleryRipper(URL url) throws IOException { 18 | super(url); 19 | } 20 | 21 | @Override 22 | public String getHost() { 23 | return "myhentaigallery"; 24 | } 25 | 26 | @Override 27 | public String getDomain() { 28 | return "myhentaigallery.com"; 29 | } 30 | 31 | @Override 32 | public String getGID(URL url) throws MalformedURLException { 33 | Pattern p = Pattern.compile("https://myhentaigallery.com/gallery/thumbnails/([0-9]+)/?$"); 34 | Matcher m = p.matcher(url.toExternalForm()); 35 | if (m.matches()) { 36 | return m.group(1); 37 | } 38 | 39 | throw new MalformedURLException("Expected myhentaicomics.com URL format: " 40 | + "myhentaigallery.com/gallery/thumbnails/ID - got " + url + " instead"); 41 | } 42 | 43 | @Override 44 | public Document getFirstPage() throws IOException { 45 | // "url" is an instance field of the superclass 46 | return Http.url(url).get(); 47 | } 48 | 49 | @Override 50 | public List getURLsFromPage(Document doc) { 51 | List result = new ArrayList<>(); 52 | for (Element el : doc.select(".comic-thumb > img")) { 53 | String imageSource = el.attr("src"); 54 | // We replace thumbs with resizes so we can the full sized images 55 | imageSource = imageSource.replace("thumbnail", "original"); 56 | result.add(imageSource); 57 | } 58 | return result; 59 | } 60 | 61 | @Override 62 | public void downloadURL(URL url, int index) { 63 | addURLToDownload(url, getPrefix(index)); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/main/resources/LabelsBundle_porrisavvo_FI.properties: -------------------------------------------------------------------------------- 1 | Log = Loki 2 | History = Historriijja 3 | created = luatu 4 | modified = muakat 5 | queue = Jono 6 | Configuration = Assetuksse 7 | 8 | # Keys for the Configuration menu 9 | 10 | current.version = Nykyne versijjo 11 | check.for.updates = Tarkist update 12 | auto.update = Automaatpäivvitys? 13 | max.download.threads = Yht'aikasse ripi 14 | timeout.mill = Timeout (millisekois): 15 | retry.download.count = Ripi retry count 16 | overwrite.existing.files = Korvvaa nykysse filu? 17 | sound.when.rip.completes = Valmistummis'ään 18 | preserve.order = Pir järestys 19 | save.logs = Tallen loki 20 | notification.when.rip.starts = Valmistummisilmotus 21 | save.urls.only = Tallen vaa ossottee 22 | save.album.titles = Tallen album'otsiko 23 | autorip.from.clipboard = Ot linki leikpöyrrält 24 | save.descriptions = Tallen kuvvauksse 25 | prefer.mp4.over.gif = Suasi MP4 GIF sijjaa 26 | restore.window.position = Palaut ikkunna sijaant 27 | remember.url.history = Muist osot'hissa 28 | loading.history.from = Larrataa hissaa lähteest 29 | 30 | # Misc UI keys 31 | 32 | loading.history.from.configuration = Larrataa hissaa asetusfilust 33 | interrupted.while.waiting.to.rip.next.album = Keskeytet venates seurraavvaa album 34 | inactive = Idle 35 | re-rip.checked = Re-rip merkatu 36 | remove = Poist 37 | clear = Tyhjen 38 | download.url.list = Download url list 39 | select.save.dir = Valkkaa savekansio 40 | 41 | # Keys for the logs generated by DownloadFileThread 42 | 43 | nonretriable.status.code = retry-kelvvoto statuskoori 44 | retriable.status.code = Retriable statuskoori 45 | server.doesnt.support.resuming.downloads = Servvu ei tue lataaste retryamist 46 | # A "magic number" can also be called a file signature 47 | was.unable.to.get.content.type.using.magic.number = Sissälttötyyppii ei pystyt selvittää taikanumerolla 48 | magic.number.was = Taikanumero o 49 | deleting.existing.file = Deletoirraa nykyne filu 50 | request.properties = Pyynt'omminassuurre 51 | download.interrupted = Lattaus keskeytet 52 | exceeded.maximum.retries = Max-retryet saavvutet 53 | http.status.exception = HTTP-statuspoikkeus 54 | exception.while.downloading.file = Poikkeus larattajjes filuu 55 | failed.to.download = Lattaamminne failas 56 | skipping = Skipataa 57 | file.already.exists = filu ojjo ollemmas -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/video/ViddmeRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers.video; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | import org.jsoup.nodes.Document; 10 | import org.jsoup.select.Elements; 11 | 12 | import com.rarchives.ripme.ripper.VideoRipper; 13 | import com.rarchives.ripme.utils.Http; 14 | 15 | public class ViddmeRipper extends VideoRipper { 16 | 17 | private static final String HOST = "vid"; 18 | 19 | public ViddmeRipper(URL url) throws IOException { 20 | super(url); 21 | } 22 | 23 | @Override 24 | public String getHost() { 25 | return HOST; 26 | } 27 | 28 | @Override 29 | public boolean canRip(URL url) { 30 | Pattern p = Pattern.compile("^https?://[wm.]*vid\\.me/[a-zA-Z0-9]+.*$"); 31 | Matcher m = p.matcher(url.toExternalForm()); 32 | return m.matches(); 33 | } 34 | 35 | @Override 36 | public URL sanitizeURL(URL url) throws MalformedURLException { 37 | return url; 38 | } 39 | 40 | @Override 41 | public String getGID(URL url) throws MalformedURLException { 42 | Pattern p = Pattern.compile("^https?://[wm.]*vid\\.me/([a-zA-Z0-9]+).*$"); 43 | Matcher m = p.matcher(url.toExternalForm()); 44 | if (m.matches()) { 45 | return m.group(1); 46 | } 47 | 48 | throw new MalformedURLException( 49 | "Expected vid.me format:" 50 | + "vid.me/id" 51 | + " Got: " + url); 52 | } 53 | 54 | @Override 55 | public void rip() throws IOException { 56 | LOGGER.info(" Retrieving " + this.url.toExternalForm()); 57 | Document doc = Http.url(this.url).get(); 58 | Elements videos = doc.select("meta[name=twitter:player:stream]"); 59 | if (videos.isEmpty()) { 60 | throw new IOException("Could not find twitter:player:stream at " + url); 61 | } 62 | String vidUrl = videos.first().attr("content"); 63 | vidUrl = vidUrl.replaceAll("&", "&"); 64 | addURLToDownload(new URL(vidUrl), HOST + "_" + getGID(this.url)); 65 | waitForThreads(); 66 | } 67 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/FitnakedgirlsRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | import org.jsoup.select.Elements; 14 | 15 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 16 | import com.rarchives.ripme.utils.Http; 17 | 18 | public class FitnakedgirlsRipper extends AbstractHTMLRipper { 19 | 20 | public FitnakedgirlsRipper(URL url) throws IOException { 21 | super(url); 22 | } 23 | 24 | @Override 25 | public String getHost() { 26 | return "fitnakedgirls"; 27 | } 28 | 29 | @Override 30 | public String getDomain() { 31 | return "fitnakedgirls.com"; 32 | } 33 | 34 | @Override 35 | public String getGID(URL url) throws MalformedURLException { 36 | Pattern p; 37 | Matcher m; 38 | 39 | p = Pattern.compile("^.*fitnakedgirls\\.com/gallery/(.+)$"); 40 | m = p.matcher(url.toExternalForm()); 41 | if (m.matches()) { 42 | return m.group(1); 43 | } 44 | 45 | throw new MalformedURLException( 46 | "Expected fitnakedgirls.com gallery format: " + "fitnakedgirls.com/gallery/####" + " Got: " + url); 47 | } 48 | 49 | @Override 50 | public Document getFirstPage() throws IOException { 51 | return Http.url(url).get(); 52 | } 53 | 54 | @Override 55 | public List getURLsFromPage(Document doc) { 56 | List imageURLs = new ArrayList<>(); 57 | 58 | Elements imgs = doc.select("div[class*=wp-tiles-tile-bg] > img"); 59 | for (Element img : imgs) { 60 | String imgSrc = img.attr("src"); 61 | imageURLs.add(imgSrc); 62 | } 63 | 64 | return imageURLs; 65 | } 66 | 67 | @Override 68 | public void downloadURL(URL url, int index) { 69 | // Send referrer when downloading images 70 | addURLToDownload(url, getPrefix(index), "", this.url.toExternalForm(), null); 71 | } 72 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/ripper/rippers/RedgifsRipperTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.rippers.RedgifsRipper; 4 | import org.jsoup.nodes.Document; 5 | import org.junit.jupiter.api.*; 6 | 7 | import java.io.IOException; 8 | import java.net.URL; 9 | 10 | public class RedgifsRipperTest extends RippersTest { 11 | 12 | /** 13 | * Rips correctly formatted URL directly from Redgifs 14 | * @throws IOException 15 | */ 16 | @Test 17 | @Disabled("test or ripper broken") 18 | public void testRedgifsGoodURL() throws IOException{ 19 | RedgifsRipper ripper = new RedgifsRipper(new URL("https://www.redgifs.com/watch/talkativewarpeddragon-petite")); 20 | testRipper(ripper); 21 | } 22 | 23 | /** 24 | * Rips gifdeliverynetwork URL's by redirecting them to proper redgifs url 25 | * @throws IOException 26 | */ 27 | @Test 28 | @Tag("flaky") 29 | public void testRedgifsBadRL() throws IOException{ 30 | RedgifsRipper ripper = new RedgifsRipper(new URL("https://www.gifdeliverynetwork.com/foolishelasticchimpanzee")); 31 | testRipper(ripper); 32 | } 33 | 34 | /** 35 | * Rips a Redifs profile 36 | * @throws IOException 37 | */ 38 | @Test 39 | @Tag("flaky") 40 | public void testRedgifsProfile() throws IOException { 41 | RedgifsRipper ripper = new RedgifsRipper(new URL("https://redgifs.com/users/margo_monty")); 42 | testRipper(ripper); 43 | } 44 | 45 | /** 46 | * Rips a Redifs category/search 47 | * @throws IOException 48 | */ 49 | @Test 50 | @Disabled("test or ripper broken") 51 | public void testRedgifsSearch() throws IOException { 52 | RedgifsRipper ripper = new RedgifsRipper(new URL("https://redgifs.com/gifs/browse/little-caprice")); 53 | Document doc = ripper.getFirstPage(); 54 | 55 | doc = ripper.getNextPage(doc); 56 | Assertions.assertTrue("https://napi.redgifs.com/v1/gfycats/search?search_text=little%20caprice&count=150&start=150".equalsIgnoreCase(doc.location())); 57 | doc = ripper.getNextPage(doc); 58 | Assertions.assertTrue("https://napi.redgifs.com/v1/gfycats/search?search_text=little%20caprice&count=150&start=300".equalsIgnoreCase(doc.location())); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/video/MotherlessVideoRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers.video; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | import com.rarchives.ripme.ripper.VideoRipper; 11 | import com.rarchives.ripme.utils.Http; 12 | import com.rarchives.ripme.utils.Utils; 13 | 14 | public class MotherlessVideoRipper extends VideoRipper { 15 | 16 | private static final String HOST = "motherless"; 17 | 18 | public MotherlessVideoRipper(URL url) throws IOException { 19 | super(url); 20 | } 21 | 22 | @Override 23 | public String getHost() { 24 | return HOST; 25 | } 26 | 27 | @Override 28 | public boolean canRip(URL url) { 29 | Pattern p = Pattern.compile("^https?://[wm.]*motherless\\.com/[A-Z0-9]+.*$"); 30 | Matcher m = p.matcher(url.toExternalForm()); 31 | return m.matches(); 32 | } 33 | 34 | @Override 35 | public URL sanitizeURL(URL url) throws MalformedURLException { 36 | return url; 37 | } 38 | 39 | @Override 40 | public String getGID(URL url) throws MalformedURLException { 41 | Pattern p = Pattern.compile("^https?://[wm.]*motherless\\.com/([A-Z0-9]+).*$"); 42 | Matcher m = p.matcher(url.toExternalForm()); 43 | if (m.matches()) { 44 | return m.group(1); 45 | } 46 | 47 | throw new MalformedURLException( 48 | "Expected motherless format:" 49 | + "motherless.com/####" 50 | + " Got: " + url); 51 | } 52 | 53 | @Override 54 | public void rip() throws IOException { 55 | LOGGER.info(" Retrieving " + this.url); 56 | String html = Http.url(this.url).get().toString(); 57 | if (html.contains("__fileurl = '")) { 58 | LOGGER.error("WTF"); 59 | } 60 | List vidUrls = Utils.between(html, "__fileurl = '", "';"); 61 | if (vidUrls.isEmpty()) { 62 | throw new IOException("Could not find video URL at " + url); 63 | } 64 | String vidUrl = vidUrls.get(0); 65 | addURLToDownload(new URL(vidUrl), HOST + "_" + getGID(this.url)); 66 | waitForThreads(); 67 | } 68 | } -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/XcartxRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 4 | import com.rarchives.ripme.utils.Http; 5 | import org.jsoup.nodes.Document; 6 | import org.jsoup.nodes.Element; 7 | import org.jsoup.select.Elements; 8 | 9 | import java.io.IOException; 10 | import java.net.MalformedURLException; 11 | import java.net.URL; 12 | import java.util.ArrayList; 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | import java.util.regex.Matcher; 17 | import java.util.regex.Pattern; 18 | 19 | public class XcartxRipper extends AbstractHTMLRipper { 20 | private Map cookies = new HashMap<>(); 21 | 22 | 23 | public XcartxRipper(URL url) throws IOException { 24 | super(url); 25 | } 26 | 27 | @Override 28 | public String getHost() { 29 | return "xcartx"; 30 | } 31 | @Override 32 | public String getDomain() { 33 | return "xcartx.com"; 34 | } 35 | 36 | @Override 37 | public String getGID(URL url) throws MalformedURLException { 38 | Pattern p = Pattern.compile("^https?://xcartx.com/([a-zA-Z0-9_\\-]+).html"); 39 | Matcher m = p.matcher(url.toExternalForm()); 40 | if (m.matches()) { 41 | return m.group(1); 42 | } 43 | throw new MalformedURLException("Expected URL format: http://xcartx.com/comic, got: " + url); 44 | 45 | } 46 | 47 | @Override 48 | public Document getFirstPage() throws IOException { 49 | return Http.url(url).get(); 50 | } 51 | 52 | @Override 53 | public List getURLsFromPage(Document page) { 54 | List imageURLs = new ArrayList<>(); 55 | Elements imageElements = page.select("div.f-desc img"); 56 | for (Element image : imageElements) { 57 | String imageUrl = image.attr("data-src"); 58 | 59 | imageURLs.add("https://" + getDomain() + imageUrl); 60 | } 61 | return imageURLs; 62 | } 63 | 64 | @Override 65 | public void downloadURL(URL url, int index) { 66 | addURLToDownload(url, getPrefix(index), "", this.url.toExternalForm(), cookies); 67 | } 68 | 69 | @Override 70 | public String getPrefix(int index) { 71 | return String.format("%03d_", index); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/YoupornRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import com.rarchives.ripme.ripper.AbstractSingleFileRipper; 12 | import org.jsoup.nodes.Document; 13 | import org.jsoup.nodes.Element; 14 | import org.jsoup.select.Elements; 15 | 16 | import com.rarchives.ripme.ripper.VideoRipper; 17 | import com.rarchives.ripme.utils.Http; 18 | 19 | public class YoupornRipper extends AbstractSingleFileRipper { 20 | 21 | 22 | public YoupornRipper(URL url) throws IOException { 23 | super(url); 24 | } 25 | 26 | @Override 27 | public String getHost() { 28 | return "youporn"; 29 | } 30 | 31 | @Override 32 | public String getDomain() { 33 | return "youporn.com"; 34 | } 35 | 36 | @Override 37 | public boolean canRip(URL url) { 38 | Pattern p = Pattern.compile("^https?://[wm.]*youporn\\.com/watch/[0-9]+.*$"); 39 | Matcher m = p.matcher(url.toExternalForm()); 40 | return m.matches(); 41 | } 42 | 43 | @Override 44 | public Document getFirstPage() throws IOException { 45 | return Http.url(this.url).get(); 46 | } 47 | 48 | @Override 49 | public List getURLsFromPage(Document doc) { 50 | List results = new ArrayList<>(); 51 | Elements videos = doc.select("video"); 52 | 53 | Element video = videos.get(0); 54 | results.add(video.attr("src")); 55 | return results; 56 | } 57 | 58 | 59 | @Override 60 | public String getGID(URL url) throws MalformedURLException { 61 | Pattern p = Pattern.compile("^https?://[wm.]*youporn\\.com/watch/([0-9]+).*$"); 62 | Matcher m = p.matcher(url.toExternalForm()); 63 | if (m.matches()) { 64 | return m.group(1); 65 | } 66 | 67 | throw new MalformedURLException( 68 | "Expected youporn format:" 69 | + "youporn.com/watch/####" 70 | + " Got: " + url); 71 | } 72 | 73 | @Override 74 | public void downloadURL(URL url, int index) { 75 | addURLToDownload(url, getPrefix(index)); 76 | } 77 | } -------------------------------------------------------------------------------- /src/test/java/com/rarchives/ripme/tst/proxyTest.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.tst; 2 | 3 | import java.io.IOException; 4 | import java.net.URL; 5 | import com.rarchives.ripme.utils.Proxy; 6 | import com.rarchives.ripme.utils.Utils; 7 | import com.rarchives.ripme.utils.Http; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertFalse; 11 | 12 | public class proxyTest { 13 | 14 | 15 | // This test will only run on machines where the user has added a entry for proxy.socks 16 | @Test 17 | public void testSocksProxy() throws IOException { 18 | // Unset proxy before testing 19 | System.setProperty("http.proxyHost", ""); 20 | System.setProperty("https.proxyHost", ""); 21 | System.setProperty("socksProxyHost", ""); 22 | URL url = new URL("https://icanhazip.com"); 23 | String proxyConfig = Utils.getConfigString("proxy.socks", ""); 24 | if (!proxyConfig.equals("")) { 25 | String ip1 = Http.url(url).ignoreContentType().get().text(); 26 | Proxy.setSocks(Utils.getConfigString("proxy.socks", "")); 27 | String ip2 = Http.url(url).ignoreContentType().get().text(); 28 | assertFalse(ip1.equals(ip2)); 29 | } else { 30 | System.out.println("Skipping testSocksProxy"); 31 | assert(true); 32 | } 33 | } 34 | 35 | // This test will only run on machines where the user has added a entry for proxy.http 36 | @Test 37 | public void testHTTPProxy() throws IOException { 38 | // Unset proxy before testing 39 | System.setProperty("http.proxyHost", ""); 40 | System.setProperty("https.proxyHost", ""); 41 | System.setProperty("socksProxyHost", ""); 42 | URL url = new URL("https://icanhazip.com"); 43 | String proxyConfig = Utils.getConfigString("proxy.http", ""); 44 | if (!proxyConfig.equals("")) { 45 | String ip1 = Http.url(url).ignoreContentType().get().text(); 46 | Proxy.setHTTPProxy(Utils.getConfigString("proxy.http", "")); 47 | String ip2 = Http.url(url).ignoreContentType().get().text(); 48 | assertFalse(ip1.equals(ip2)); 49 | } else { 50 | System.out.println("Skipping testHTTPProxy"); 51 | assert(true); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/resources/LabelsBundle_in_ID.properties: -------------------------------------------------------------------------------- 1 | Log = Log 2 | History = Riwayat 3 | created = dibuat pada 4 | modified = diubah pada 5 | queue = Antrian 6 | Configuration = Pengaturan 7 | 8 | # Keys for the Configuration menu 9 | 10 | current.version = Versi saat ini 11 | check.for.updates = Periksa update 12 | auto.update = Update otomatis? 13 | max.download.threads = Thread unduh maksimal 14 | timeout.mill = Batas waktu (dalam milidetik): 15 | retry.download.count = Jumlah percobaan unduh 16 | overwrite.existing.files = Timpa file yang ada? 17 | sound.when.rip.completes = Hidupkan suara saat rip selesai 18 | preserve.order = Pertahankan urutan 19 | save.logs = Simpan log 20 | notification.when.rip.starts = Pemberitahuan saat rip dimulai 21 | save.urls.only = Simpan URL saja 22 | save.album.titles = Simpan judul album 23 | autorip.from.clipboard = Rip otomatis dari clipboard 24 | save.descriptions = Simpan deskripsi 25 | prefer.mp4.over.gif = Utamakan MP4 dari GIF 26 | restore.window.position = Kembalikan ukuran Window 27 | remember.url.history = Ingat riwayat URL 28 | loading.history.from = Ambil riwayat dari 29 | 30 | # Misc UI keys 31 | 32 | loading.history.from.configuration = Ambil riwayat dari pengaturan 33 | interrupted.while.waiting.to.rip.next.album = Terputus saat menunggu rip album selanjutnya 34 | inactive = Tidak aktif 35 | re-rip.checked = Rip Ulang 36 | remove = Hapus 37 | clear = Hapus Semua 38 | download.url.list = Unduh daftar url 39 | select.save.dir = Pilih Tempat Penyimpanan 40 | 41 | # Keys for the logs generated by DownloadFileThread 42 | 43 | nonretriable.status.code = Kode status tidak dapat diulang 44 | retriable.status.code = Kode status dapat diulang 45 | server.doesnt.support.resuming.downloads = Server tidak punya fitur melanjutkan unduhan 46 | 47 | # A "magic number" can also be called a file signature 48 | 49 | was.unable.to.get.content.type.using.magic.number = Tidak dapat mengetahui tipe file menggunakan magic number 50 | magic.number.was = Magic number nya 51 | deleting.existing.file = Menghapus file yang sudah ada 52 | request.properties = Membutuhkan data properties 53 | download.interrupted = Unduhan terputus 54 | exceeded.maximum.retries = Mencapai percobaan maksimum 55 | http.status.exception = Pengecualian status HTTP 56 | exception.while.downloading.file = Pengecualian saat mengunduh file 57 | failed.to.download = Gagal mengunduh 58 | skipping = Melewatkan 59 | file.already.exists = file sudah ada -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/ModelmayhemRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | import org.jsoup.nodes.Document; 14 | import org.jsoup.nodes.Element; 15 | 16 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 17 | import com.rarchives.ripme.utils.Http; 18 | 19 | public class ModelmayhemRipper extends AbstractHTMLRipper { 20 | 21 | private Map cookies = new HashMap<>(); 22 | 23 | public ModelmayhemRipper(URL url) throws IOException { 24 | super(url); 25 | } 26 | 27 | @Override 28 | public String getHost() { 29 | return "modelmayhem"; 30 | } 31 | 32 | @Override 33 | public String getDomain() { 34 | return "modelmayhem.com"; 35 | } 36 | 37 | @Override 38 | public String getGID(URL url) throws MalformedURLException { 39 | Pattern p = Pattern.compile("https?://www\\.modelmayhem\\.com/portfolio/(\\d+)/viewall"); 40 | Matcher m = p.matcher(url.toExternalForm()); 41 | if (m.matches()) { 42 | return m.group(1); 43 | } 44 | throw new MalformedURLException("Expected modelmayhem URL format: " + 45 | "modelmayhem.com/portfolio/ID/viewall - got " + url + " instead"); 46 | } 47 | 48 | @Override 49 | public Document getFirstPage() throws IOException { 50 | // Bypass NSFW filter 51 | cookies.put("worksafe", "0"); 52 | // "url" is an instance field of the superclass 53 | return Http.url(url).cookies(cookies).get(); 54 | } 55 | 56 | @Override 57 | public List getURLsFromPage(Document doc) { 58 | List result = new ArrayList<>(); 59 | for (Element el : doc.select("tr.a_pics > td > div > a")) { 60 | String image_URL = el.select("img").attr("src").replaceAll("_m", ""); 61 | if (image_URL.contains("http")) { 62 | result.add(image_URL); 63 | } 64 | } 65 | return result; 66 | } 67 | 68 | @Override 69 | public void downloadURL(URL url, int index) { 70 | addURLToDownload(url, getPrefix(index)); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/resources/LabelsBundle_fi_FI.properties: -------------------------------------------------------------------------------- 1 | Log = Logi 2 | History = Historia 3 | created = luotu 4 | modified = muokattu 5 | queue = Jono 6 | Configuration = Asetukset 7 | 8 | # Keys for the Configuration menu 9 | 10 | current.version = Nykyinen versio 11 | check.for.updates = Tarkista päivitykset 12 | auto.update = Automaattipäivitys? 13 | max.download.threads = Yhtäaikaiset lataukset 14 | timeout.mill = Aikakatkaisu (millisekunneissa): 15 | retry.download.count = Latauksen uudelleenyritykset 16 | overwrite.existing.files = Korvaa nykyiset tiedostot? 17 | sound.when.rip.completes = Valmistumisääni 18 | preserve.order = Pidä järjestys 19 | save.logs = Tallenna logit 20 | notification.when.rip.starts = Valmistumisilmoitus 21 | save.urls.only = Tallenna vain osoitteet 22 | save.album.titles = Tallenna albumiotsikot 23 | autorip.from.clipboard = Ota linkit leikepöydältä 24 | save.descriptions = Tallenna kuvaukset 25 | prefer.mp4.over.gif = Suosi MP4:jää GIF:fin sijasta 26 | restore.window.position = Palauta ikkunan sijainti 27 | remember.url.history = Muista osoitehistoria 28 | loading.history.from = Ladataan historiaa kohteesta 29 | 30 | # Misc UI keys 31 | 32 | loading.history.from.configuration = Ladataan historiaa asetustiedostosta 33 | interrupted.while.waiting.to.rip.next.album = Keskeytetty odottaessa seuraavaa albumia 34 | inactive = Toimeton 35 | re-rip.checked = Uudelleenlataa merkatut 36 | remove = Poista 37 | clear = Tyhjennä 38 | download.url.list = Download url list 39 | select.save.dir = Valitse tallennuskansio 40 | 41 | # Keys for the logs generated by DownloadFileThread 42 | 43 | nonretriable.status.code = Uudelleenyrityskelvoton tilakoodi 44 | retriable.status.code = Uudelleenyritettävä tilakoodi 45 | server.doesnt.support.resuming.downloads = Serveri ei tue latausten uudelleen jatkamista 46 | # A "magic number" can also be called a file signature 47 | was.unable.to.get.content.type.using.magic.number = Sisältötyyppiä ei pystytty taikanumerolla selvittämään 48 | magic.number.was = Taikanumero on 49 | deleting.existing.file = Poistetaan nykyinen tiedosto 50 | request.properties = Pyyntöominaisuudet 51 | download.interrupted = Lataus keskeytetty 52 | exceeded.maximum.retries = Max-uudelleenyritykset saavutettu 53 | http.status.exception = HTTP-tilapoikkeus 54 | exception.while.downloading.file = Poikkeus ladattaessa tiedostoa 55 | failed.to.download = Lataaminen epäonnistui 56 | skipping = Ohitetaan 57 | file.already.exists = tiedosto on jo olemassa -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/FolioRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | 7 | import java.util.List; 8 | import java.util.ArrayList; 9 | import java.util.regex.Pattern; 10 | import java.util.regex.Matcher; 11 | 12 | import org.json.JSONObject; 13 | import org.json.JSONArray; 14 | 15 | import com.rarchives.ripme.ripper.AbstractJSONRipper; 16 | import com.rarchives.ripme.utils.Http; 17 | 18 | /** 19 | * @author owaiswiz 20 | * 21 | */ 22 | public class FolioRipper extends AbstractJSONRipper { 23 | public FolioRipper(URL url) throws IOException { 24 | super(url); 25 | } 26 | 27 | @Override 28 | public String getHost() { 29 | return "folio"; 30 | } 31 | 32 | @Override 33 | public String getDomain() { 34 | return "folio.ink"; 35 | } 36 | 37 | @Override 38 | public String getGID(URL url) throws MalformedURLException { 39 | Pattern p = Pattern.compile("^https?://(?:www.)?folio.ink/([a-zA-Z0-9]+).*$"); 40 | Matcher m = p.matcher(url.toExternalForm()); 41 | if (m.matches()) { 42 | return m.group(1); 43 | } 44 | throw new MalformedURLException("Expected folio.ink URL format: " + 45 | "folio.ink/albumid (e.g: folio.ink/DmBe6i) - got " + url + " instead"); 46 | } 47 | 48 | @Override 49 | public JSONObject getFirstPage() throws IOException { 50 | String jsonArrayString = Http.url("https://folio.ink/getimages/" + getGID(url)).ignoreContentType().response().body(); 51 | JSONArray imagesArray = new JSONArray(jsonArrayString); 52 | JSONObject imagesObject = new JSONObject(); 53 | imagesObject.put("images", imagesArray); 54 | 55 | return imagesObject; 56 | } 57 | 58 | @Override 59 | public List getURLsFromJSON(JSONObject json) { 60 | List result = new ArrayList(); 61 | JSONArray imagesArray = json.getJSONArray("images"); 62 | 63 | for (int i = 0; i < imagesArray.length(); i++) { 64 | JSONObject image = imagesArray.getJSONObject(i); 65 | result.add(image.getString("image_url")); 66 | } 67 | 68 | return result; 69 | } 70 | 71 | @Override 72 | public void downloadURL(URL url, int index) { 73 | addURLToDownload(url, getPrefix(index)); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/LabelsBundle_zh_CN.properties: -------------------------------------------------------------------------------- 1 | Log = 日志 2 | History = 历史 3 | created = 创建时间 4 | modified = 修改时间 5 | queue = 队列 6 | Configuration = 配置 7 | open = 打开 8 | 9 | # Keys for the Configuration menu 10 | current.version = 当前版本 11 | check.for.updates = 检查更新 12 | auto.update = 自动更新? 13 | max.download.threads = 最大下载线程数: 14 | timeout.mill = 超时(毫秒): 15 | retry.download.count = 重试下载次数 16 | overwrite.existing.files = 覆盖现有文件? 17 | sound.when.rip.completes = 抓取完成时播放声音 18 | preserve.order = 保持顺序 19 | save.logs = 保存日志 20 | notification.when.rip.starts = 通知抓取开始 21 | save.urls.only = 仅保存 URL 22 | save.album.titles = 保存专辑标题 23 | autorip.from.clipboard = 监视剪贴板上的 URL 24 | save.descriptions = 保存描述 25 | prefer.mp4.over.gif = 首选 MP4 而非 GIF 26 | restore.window.position = 恢复窗口位置 27 | remember.url.history = 记住 URL 历史 28 | loading.history.from = 加载历史从 29 | 30 | # Queue keys 31 | queue.remove.all = 移除全部 32 | queue.validation = 您确定要移除队列内的全部项目? 33 | queue.remove.selected = 移除所选项目 34 | 35 | # History 36 | re-rip.checked = 重新抓取选中的项目 37 | remove = 移除 38 | clear = 清除 39 | history.check.all = 选中全部 40 | history.check.none = 取消选中全部 41 | history.check.selected = 选中所选项目 42 | history.uncheck.selected = 取消选中所选项目 43 | history.load.failed.warning = RipMe 加载位于 historyFile.getAbsolutePath() 的历史文件失败\n\n错误:%s\n\n关闭 RipMe 会自动覆盖此文件的内容,\n请在关闭 RipMe 前备份它! 44 | history.load.none = 无可重新抓取的历史条目。请先抓取一些专辑 45 | history.load.none.checked = 未 '选中' 任何历史条目,请通过选中所需 URL 前面的复选框或URL 的右键菜单以选中所需条目 46 | 47 | # TrayIcon 48 | tray.show = 显示 49 | tray.hide = 隐藏 50 | tray.autorip = 监视剪贴板上的 URL 51 | tray.exit = 退出 52 | 53 | # Misc UI keys 54 | loading.history.from.configuration = 从配置加载历史 55 | interrupted.while.waiting.to.rip.next.album = 等候抓取下一专辑期间发生中断 56 | inactive = 非活动 57 | download.url.list = 下载 URL 列表 58 | select.save.dir = 选择保存目录 59 | 60 | # Keys for the logs generated by DownloadFileThread 61 | nonretriable.status.code = 非可重试状态代码 62 | retriable.status.code = 可重试状态代码 63 | server.doesnt.support.resuming.downloads = 服务器不支持继续下载(续传) 64 | # A "magic number" can also be called a file signature 65 | was.unable.to.get.content.type.using.magic.number = 不能使用幻数获取内容类型 66 | magic.number.was = 幻数为 67 | deleting.existing.file = 删除现有文件 68 | request.properties = 请求属性 69 | download.interrupted = 下载中断 70 | exceeded.maximum.retries = 超过最大重试次数 71 | http.status.exception = HTTP 状态意外 72 | exception.while.downloading.file = 下载文件时发生意外 73 | failed.to.download = 下载失败 74 | skipping = 跳过 75 | file.already.exists = 文件已存在 -------------------------------------------------------------------------------- /src/main/java/com/rarchives/ripme/ripper/rippers/YuvutuRipper.java: -------------------------------------------------------------------------------- 1 | package com.rarchives.ripme.ripper.rippers; 2 | 3 | import java.io.IOException; 4 | import java.net.MalformedURLException; 5 | import java.net.URL; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.jsoup.nodes.Document; 12 | import org.jsoup.nodes.Element; 13 | 14 | import com.rarchives.ripme.ripper.AbstractHTMLRipper; 15 | import com.rarchives.ripme.utils.Http; 16 | 17 | public class YuvutuRipper extends AbstractHTMLRipper { 18 | 19 | private static final String DOMAIN = "yuvutu.com", 20 | HOST = "yuvutu"; 21 | 22 | public YuvutuRipper(URL url) throws IOException { 23 | super(url); 24 | } 25 | 26 | @Override 27 | public String getHost() { 28 | return HOST; 29 | } 30 | @Override 31 | public String getDomain() { 32 | return DOMAIN; 33 | } 34 | 35 | @Override 36 | public boolean canRip(URL url) { 37 | Pattern p = Pattern.compile("^http://www\\.yuvutu\\.com/modules\\.php\\?name=YuGallery&action=view&set_id=([0-9]+)$"); 38 | Matcher m = p.matcher(url.toExternalForm()); 39 | return m.matches(); 40 | } 41 | 42 | @Override 43 | public String getGID(URL url) throws MalformedURLException { 44 | Pattern p = Pattern.compile("^http://www\\.yuvutu\\.com/modules\\.php\\?name=YuGallery&action=view&set_id=([0-9]+)$"); 45 | Matcher m = p.matcher(url.toExternalForm()); 46 | if (m.matches()) { 47 | return m.group(1); 48 | } 49 | throw new MalformedURLException("Expected yuvutu.com URL format: " + 50 | "yuvutu.com/modules.php?name=YuGallery&action=view&set_id=albumid - got " + url + "instead"); 51 | } 52 | 53 | @Override 54 | public Document getFirstPage() throws IOException { 55 | return Http.url(url).get(); 56 | } 57 | @Override 58 | public List getURLsFromPage(Document doc) { 59 | List imageURLs = new ArrayList<>(); 60 | for (Element thumb : doc.select("div#galleria > a > img")) { 61 | String image = thumb.attr("src"); 62 | imageURLs.add(image); 63 | } 64 | return imageURLs; 65 | } 66 | @Override 67 | public void downloadURL(URL url, int index) { 68 | addURLToDownload(url, getPrefix(index)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/resources/LabelsBundle_nl_NL.properties: -------------------------------------------------------------------------------- 1 | Log = Logboek 2 | History = Geschiedenis 3 | created = gemaakt 4 | modified = aangepast 5 | queue = Wachtrij 6 | Configuration = Configuratie 7 | 8 | # Keys for the Configuration menu 9 | 10 | current.version = Huidige versie 11 | check.for.updates = Controleer op updates 12 | auto.update = Auto-update? 13 | max.download.threads = Maximale downloadthreads 14 | timeout.mill = Timeout (in milliseconden): 15 | retry.download.count = Aantal keren opnieuw proberen te downloaden 16 | overwrite.existing.files = Bestaande bestanden overschrijven? 17 | sound.when.rip.completes = Geluid wanneer rip klaar is 18 | preserve.order = Volgorde behouden 19 | save.logs = Logbestanden opslaan 20 | notification.when.rip.starts = Notificatie wanneer rip start 21 | save.urls.only = Alleen URLs opslaan 22 | save.album.titles = Album titels opslaan 23 | autorip.from.clipboard = Rip automatisch van klembord 24 | save.descriptions = Beschrijvingen opslaan 25 | prefer.mp4.over.gif = Geef de voorkeur aan MP4 over GIF 26 | restore.window.position = Vensterpositie herstellen 27 | remember.url.history = URL geschiedenis onthouden 28 | loading.history.from = Geschiedenis laden van 29 | 30 | # Misc UI keys 31 | 32 | loading.history.from.configuration = Geschiedenis laden van configuratie 33 | interrupted.while.waiting.to.rip.next.album = Onderbroken tijdens het wachten om volgend album te rippen 34 | inactive = Inactief 35 | re-rip.checked = Re-rip Gecheckt 36 | remove = Verwijderen 37 | clear = Opruimen 38 | download.url.list = Download url list 39 | select.save.dir = Select Save Directory 40 | 41 | # Keys for the logs generated by DownloadFileThread 42 | 43 | nonretriable.status.code = Non-retriable status code 44 | retriable.status.code = Retriable status code 45 | server.doesnt.support.resuming.downloads = Server doesn't support resuming downloads 46 | # A "magic number" can also be called a file signature 47 | was.unable.to.get.content.type.using.magic.number = Was unable to get content type using magic number 48 | magic.number.was = Magic number was 49 | deleting.existing.file = Deleting existing file 50 | request.properties = Request properties 51 | download.interrupted = Download interrupted 52 | exceeded.maximum.retries = Exceeded maximum retries 53 | http.status.exception = HTTP status exception 54 | exception.while.downloading.file = Exception while downloading file 55 | failed.to.download = Failed to download 56 | skipping = Skipping 57 | file.already.exists = file already exists -------------------------------------------------------------------------------- /src/main/resources/LabelsBundle_ru_RU.properties: -------------------------------------------------------------------------------- 1 | Log = Лог 2 | History = История 3 | created = создано 4 | modified = изменено 5 | queue = Очередь 6 | Configuration = Настройки 7 | 8 | # Keys for the Configuration menu 9 | 10 | current.version = Текущая версия 11 | check.for.updates = Проверить обновления 12 | auto.update = Автообновление 13 | max.download.threads = Максимальное число потоков: 14 | timeout.mill = Задержка (в миллисекундах): 15 | retry.download.count = Число повторов 16 | overwrite.existing.files = Перезаписать существующие файлы? 17 | sound.when.rip.completes = Звук при завершении 18 | preserve.order = Сохранять порядок 19 | save.logs = Сохранять логи 20 | notification.when.rip.starts = Уведомление при запуске 21 | save.urls.only = Сохранять только ссылки 22 | save.album.titles = Сохранять названия альбомов 23 | autorip.from.clipboard = Автоскачивание из буфера 24 | save.descriptions = Сохранять описания 25 | prefer.mp4.over.gif = Предпочесть MP4 вместо GIF 26 | restore.window.position = Восстановить положение окна 27 | remember.url.history = Запоминать историю запросов 28 | loading.history.from = Загрузить историю из 29 | 30 | # Misc UI keys 31 | 32 | loading.history.from.configuration = Загрузить историю из настроек 33 | interrupted.while.waiting.to.rip.next.album = Прервано во время ожидания скачивания следующего альбома 34 | inactive = Неактивно 35 | re-rip.checked = Перекачать выбранное 36 | remove = Удалить 37 | clear = Очистить 38 | download.url.list = Скачать список ссылок 39 | select.save.dir = Выбрать папку для сохранения 40 | 41 | # Keys for the logs generated by DownloadFileThread 42 | 43 | nonretriable.status.code = Код не возвращаемого статуса 44 | retriable.status.code = Код возвращаемого статуса 45 | server.doesnt.support.resuming.downloads = Сервер не поддерживает возобновление загрузки 46 | # A "magic number" can also be called a file signature 47 | was.unable.to.get.content.type.using.magic.number = Не удалось получить тип контента с использованием магического номера 48 | magic.number.was = Магический номер был 49 | deleting.existing.file = Удаление существующего файла 50 | request.properties = Свойства запроса 51 | download.interrupted = Загрузка прервана 52 | exceeded.maximum.retries = Достигнуто максимальное количество попыток 53 | http.status.exception = Исключение HTTP-статуса 54 | exception.while.downloading.file = Исключение при загрузке файла 55 | failed.to.download = Не удалось загрузить 56 | skipping = Пропуск 57 | file.already.exists = Файл уже существует 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/java,linux,macos,maven,windows 2 | 3 | ### Java ### 4 | # Compiled class file 5 | *.class 6 | 7 | # Log file 8 | *.log 9 | 10 | # BlueJ files 11 | *.ctxt 12 | 13 | # Mobile Tools for Java (J2ME) 14 | .mtj.tmp/ 15 | 16 | # Package Files # 17 | *.jar 18 | *.war 19 | *.ear 20 | *.zip 21 | *.tar.gz 22 | *.rar 23 | 24 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 25 | hs_err_pid* 26 | 27 | ### Linux ### 28 | *~ 29 | 30 | # temporary files which can be created if a process still has a handle open of a deleted file 31 | .fuse_hidden* 32 | 33 | # KDE directory preferences 34 | .directory 35 | 36 | # Linux trash folder which might appear on any partition or disk 37 | .Trash-* 38 | 39 | # .nfs files are created when an open file is removed but is still being accessed 40 | .nfs* 41 | 42 | ### macOS ### 43 | *.DS_Store 44 | .AppleDouble 45 | .LSOverride 46 | 47 | # Icon must end with two \r 48 | Icon 49 | 50 | # Thumbnails 51 | ._* 52 | 53 | # Files that might appear in the root of a volume 54 | .DocumentRevisions-V100 55 | .fseventsd 56 | .Spotlight-V100 57 | .TemporaryItems 58 | .Trashes 59 | .VolumeIcon.icns 60 | .com.apple.timemachine.donotpresent 61 | 62 | # Directories potentially created on remote AFP share 63 | .AppleDB 64 | .AppleDesktop 65 | Network Trash Folder 66 | Temporary Items 67 | .apdisk 68 | 69 | ### Maven ### 70 | target/ 71 | pom.xml.tag 72 | pom.xml.releaseBackup 73 | pom.xml.versionsBackup 74 | pom.xml.next 75 | release.properties 76 | dependency-reduced-pom.xml 77 | buildNumber.properties 78 | .mvn/timing.properties 79 | 80 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 81 | !/.mvn/wrapper/maven-wrapper.jar 82 | 83 | ### Windows ### 84 | # Windows thumbnail cache files 85 | Thumbs.db 86 | ehthumbs.db 87 | ehthumbs_vista.db 88 | 89 | # Folder config file 90 | Desktop.ini 91 | 92 | # Recycle Bin used on file shares 93 | $RECYCLE.BIN/ 94 | 95 | # Windows Installer files 96 | *.cab 97 | *.msi 98 | *.msm 99 | *.msp 100 | 101 | # Windows shortcuts 102 | *.lnk 103 | 104 | ### IDEs ### 105 | .vscode 106 | .idea 107 | .project 108 | 109 | ### Ripme ### 110 | ripme.log 111 | rips/ 112 | .history 113 | ripme.jar.update 114 | *.swp 115 | *.properties 116 | !LabelsBundle*.properties 117 | history.json 118 | *.iml 119 | .settings/ 120 | .classpath 121 | *.txt 122 | bin/ 123 | --------------------------------------------------------------------------------