Skip to content

Commit 90685e4

Browse files
committed
vpnfail scraper added + more output info
1 parent 7f307e4 commit 90685e4

File tree

5 files changed

+135
-5
lines changed

5 files changed

+135
-5
lines changed

build.gradle.kts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,17 @@ launch4j {
4747
version = "1.0"
4848
textVersion = "1.0"
4949
language = "ENGLISH_UK"
50-
//icon = "${projectDir}/icons/myApp.ico"
5150
}
5251

5352
lateinit var jarFile: File
5453

5554
tasks.withType<Jar> {
5655
archiveFileName.set("proxy-scraper.jar")
5756
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
58-
// Otherwise you'll get a "No main manifest attribute" error
5957
manifest {
6058
attributes["Main-Class"] = "scraper/Main"
6159
}
62-
63-
// To add all of the dependencies otherwise a "NoClassDefFoundError" error
6460
from(sourceSets.main.get().output)
65-
6661
dependsOn(configurations.runtimeClasspath)
6762
from({
6863
configurations.runtimeClasspath.get().filter { it.name.endsWith("jar") }.map { zipTree(it) }

src/main/kotlin/plugin/httpclient/freeproxyapi/FreeProxyApiData.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package plugin.httpclient.freeproxyapi
22

3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
4+
import com.fasterxml.jackson.annotation.JsonInclude
35
import com.fasterxml.jackson.annotation.JsonProperty
6+
import com.fasterxml.jackson.databind.annotation.JsonSerialize
47

8+
@JsonInclude(JsonInclude.Include.NON_NULL)
9+
@JsonIgnoreProperties(ignoreUnknown = true)
10+
@JsonSerialize
511
data class FreeProxyApiData(
612
@JsonProperty("Host")
713
val host : String,
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package plugin.httpclient.vpnfail
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper
4+
import com.fasterxml.jackson.module.kotlin.readValue
5+
import kotlinx.coroutines.Dispatchers
6+
import kotlinx.coroutines.async
7+
import kotlinx.coroutines.runBlocking
8+
import mu.KotlinLogging
9+
import scraper.net.CoroutinesHttpClient
10+
import scraper.plugin.Plugin
11+
import scraper.plugin.PluginFactory
12+
import scraper.plugin.hook.ProxyWebsite
13+
import scraper.util.NetworkUtils
14+
import scraper.util.data.ProxyData
15+
import java.net.http.HttpResponse
16+
17+
/**
18+
* GeoNode - 17/02/2023
19+
* @author Kai
20+
*
21+
* Source: https://vpn.fail/
22+
* Endpoint: https://vpn.fail/free-proxy/json
23+
* Method: GET
24+
*
25+
* ContentType: JSON
26+
* Format:
27+
* [
28+
* {
29+
* "proxy": "39.104.62.128:8123",
30+
* "type": "socks5",
31+
* }
32+
* ]
33+
*/
34+
@Suppress("unused")
35+
class VpnFail : Plugin, ProxyWebsite {
36+
37+
private val endpointUrl = "https://vpn.fail/free-proxy/json"
38+
39+
private val logger = KotlinLogging.logger { }
40+
41+
override val proxies : MutableList<ProxyData> = mutableListOf()
42+
43+
private var completed : Boolean = false
44+
45+
override fun register() {
46+
PluginFactory.register(this)
47+
}
48+
49+
override fun initialize() : Boolean {
50+
logger.info { "Initializing" }
51+
52+
try {
53+
this.thenConnect()
54+
} catch (ex : Exception) {
55+
completed = true
56+
logger.error { ex.message }
57+
}
58+
59+
return true
60+
}
61+
62+
override fun thenConnect() {
63+
logger.info { "Connecting" }
64+
65+
val response = mutableMapOf<String, HttpResponse<String>?>()
66+
runBlocking {
67+
val result = async(Dispatchers.IO) {
68+
val client = CoroutinesHttpClient()
69+
client.contentType = arrayOf("content-type", "application/json")
70+
val data = client.fetch(endpointUrl, null)
71+
data
72+
}
73+
response["json"] = result.await()
74+
}
75+
76+
if (response.isNotEmpty()) {
77+
this.thenHandleData(response)
78+
} else {
79+
logger.error { "Failed to connect to $endpointUrl" }
80+
}
81+
}
82+
83+
override fun thenHandleData(data : MutableMap<String, *>) {
84+
logger.info { "Handling Data" }
85+
86+
val mapper = ObjectMapper()
87+
val values = mapper.readValue<List<VpnFailData>>((data.getValue("json") as HttpResponse<String>).body())
88+
val allowedProtocols = arrayOf("socks4", "socks5", "http", "https")
89+
90+
for(value in values) {
91+
if(!NetworkUtils.isValidIpAndPort(value.host) || !allowedProtocols.contains(value.protocol)) {
92+
continue
93+
}
94+
val ip = value.host.split(":")[0]
95+
val port = value.host.split(":")[1]
96+
val proxy = ProxyData(ip, port.toInt(), value.protocol)
97+
proxies.add(proxy)
98+
}
99+
100+
logger.info { "Collected ${proxies.size} proxies" }
101+
completed = true
102+
this.finallyComplete()
103+
}
104+
105+
override fun finallyComplete() : Boolean {
106+
return completed
107+
}
108+
109+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package plugin.httpclient.vpnfail
2+
3+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
4+
import com.fasterxml.jackson.annotation.JsonInclude
5+
import com.fasterxml.jackson.annotation.JsonProperty
6+
import com.fasterxml.jackson.databind.annotation.JsonSerialize
7+
8+
@JsonInclude(JsonInclude.Include.NON_NULL)
9+
@JsonIgnoreProperties(ignoreUnknown = true)
10+
@JsonSerialize
11+
data class VpnFailData(
12+
@JsonProperty("proxy")
13+
val host : String,
14+
@JsonProperty("type")
15+
val protocol : String
16+
)

src/main/kotlin/scraper/Main.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ class Main {
8787

8888
val jsonFile = Path.of("$outputPath/proxies.json").toFile()
8989
mapper.writeValue(jsonFile, proxyList)
90+
91+
logger.info { "Total unique proxies collected: ${allProxies.size}" }
92+
logger.info { "HTTP:[${proxyList.http.size}] | HTTPS:[${proxyList.https.size}] " +
93+
"| SOCKS4:[${proxyList.socks4.size}] | SOCKS5:[${proxyList.socks5.size}]" }
9094
}
9195

9296
}

0 commit comments

Comments
 (0)