Compare commits
263 Commits
4411f642e9
...
master
Author | SHA1 | Date | |
---|---|---|---|
367d80d846 | |||
a6a1ab96c9 | |||
2442170b40 | |||
38fe5621f2 | |||
c190ede8b6 | |||
bfc3c5b605 | |||
a88c29ce23 | |||
7b6332b514 | |||
fccf64441b | |||
39722fc399 | |||
34f7342957 | |||
7ad6fb1be5 | |||
1bd9d8fa1a | |||
a7d1578ced | |||
c94e72a309 | |||
7b28cb4d6c | |||
957f2f97fa | |||
ccf32fcb48 | |||
ca167ec694 | |||
678829235f | |||
8078e82cb6 | |||
89c848e459 | |||
c6dfd0c8eb | |||
f0a59c3282 | |||
598f44795a | |||
05e2e4adc3 | |||
dab39ddd1c | |||
03b45b5129 | |||
b171ca2018 | |||
d6971db4c6 | |||
f59b36756e | |||
bd91c03dd5 | |||
ac665e509a | |||
17b97dc9d9 | |||
67b412bff9 | |||
8fafe56e2a | |||
3c8d1cc8ad | |||
4b65153d64 | |||
6823e54822 | |||
a50dee555c | |||
80ac94f47c | |||
398845a2c8 | |||
1ab78de857 | |||
32ded00d4b | |||
b305d0ba2d | |||
45ec521f80 | |||
abfcf170f2 | |||
4aee33cc40 | |||
835fdd91a6 | |||
ae896ddd4c | |||
1b8ed8b27b | |||
c2bc1fa098 | |||
bee1c7e8be | |||
c1bb4f83b4 | |||
f943a1dea3 | |||
0d607f9f08 | |||
1b2069eebf | |||
4e7224f5e8 | |||
38b1db9fdc | |||
6d1733ff2b | |||
65d2c91115 | |||
700fc9f9c1 | |||
4c63890d2a | |||
f5f9b2a190 | |||
1dd7da92b6 | |||
6505823b89 | |||
7425156a1d | |||
6794622d00 | |||
d43f4c7af1 | |||
3e5100e0fc | |||
0e0a46d875 | |||
020b31c472 | |||
1f334aeb41 | |||
cd841658ec | |||
ac2bd66439 | |||
79a2fa0b6e | |||
6946b9724f | |||
d1656b7182 | |||
2b164eba6c | |||
a6731e8c8d | |||
20844bc19a | |||
affe67a889 | |||
f3136fb2cb | |||
242e4fff2e | |||
f4862641f5 | |||
039ccb92e5 | |||
0d28111346 | |||
fcb20e8c7e | |||
51d5d43674 | |||
74b5bf977c | |||
a22740793f | |||
275276606f | |||
ccf950c849 | |||
388c805ac7 | |||
71f8e853ea | |||
7a3d871178 | |||
dc2c6e1f7c | |||
4fa16e8bec | |||
1465b1ac6a | |||
cfe69fef74 | |||
561319f448 | |||
20fbbef775 | |||
3c14ad11cb | |||
d62c45962d | |||
4ac1632c48 | |||
6f54afaf80 | |||
191f42ea8e | |||
6068b2ba2c | |||
4945338be6 | |||
103d6bb2fc | |||
f8f5c78f2c | |||
d5aa6d26a0 | |||
5aa6363bb9 | |||
16a8646085 | |||
3901f2f947 | |||
7bf8d6ef3d | |||
c2dbc64dc4 | |||
d9fd2731f1 | |||
464ebf0132 | |||
879e187b0f | |||
546fdbf8c3 | |||
9a79d1324a | |||
c6347beece | |||
bb2c72c574 | |||
3f2b092e88 | |||
b4666ddf14 | |||
176ecdb34a | |||
ec7a9c5c6c | |||
4356af0368 | |||
0baffb48f5 | |||
4cc5230850 | |||
ba29d73636 | |||
61d3fc4695 | |||
69df5d4249 | |||
e7733bbe62 | |||
c314166571 | |||
58651f7626 | |||
7c6d9ddc59 | |||
f46d78d3ec | |||
4098f91bc0 | |||
c5e12f5dd4 | |||
4cd6d8b1ac | |||
317a6be545 | |||
ee094be2eb | |||
6bff73fd72 | |||
9060cf8929 | |||
32e364a38c | |||
88b62cc225 | |||
438abb5591 | |||
aeec428d48 | |||
a58edf7961 | |||
9f11aa362a | |||
3f050ae976 | |||
6b7bca3b90 | |||
e7932b8025 | |||
0a56bef53d | |||
6eb13e18eb | |||
2bbc6c6011 | |||
9babf45272 | |||
2a47e9eca9 | |||
991aad6502 | |||
616603a5b4 | |||
d439a7936a | |||
e250eb4a50 | |||
3e983b0886 | |||
49646b5e88 | |||
2789603657 | |||
1bf59d38db | |||
e350b039d2 | |||
80daf3899a | |||
142ed5f86e | |||
d72cfa69bb | |||
254e960447 | |||
387c1b1f0c | |||
123b01d1d0 | |||
a9f3f74880 | |||
9140dbc838 | |||
e754c0a5f1 | |||
9eaca049b7 | |||
c49961b92d | |||
5511d1198d | |||
bc99e9cd0e | |||
c50e10fb8a | |||
1cdc936d9d | |||
590de72807 | |||
0c2aae0c70 | |||
f86ec987b8 | |||
6766a38bc7 | |||
540b1cce2a | |||
df0ae55173 | |||
c4548ab896 | |||
33353845df | |||
4dbea283ab | |||
6728b47e1c | |||
e0ddf6c4bf | |||
74c2c89385 | |||
54db9d441d | |||
85ff8d6b02 | |||
fe9e213d95 | |||
d90923a87f | |||
0f82b63aed | |||
0eed3836a3 | |||
f8f8234860 | |||
4bf18b2a6b | |||
38c1e87856 | |||
a9714edde0 | |||
7bad6904a4 | |||
c41ab02d7d | |||
24287fe27e | |||
9d3d367ba6 | |||
fe3f449c9e | |||
468595bdda | |||
e9b27f2727 | |||
87a5b6cca1 | |||
38ce19b527 | |||
5db350e419 | |||
219fa775fb | |||
f1c3d016e3 | |||
461e74449f | |||
0930ebd37e | |||
0b7da61a89 | |||
f354da035c | |||
1353f579fe | |||
a8886de801 | |||
678da17139 | |||
12cd2cdb5b | |||
acda1e20ad | |||
39cbbd5035 | |||
e37def7f71 | |||
67fe068e15 | |||
d48030e2fe | |||
5c932cdab9 | |||
db02375b6e | |||
d96c3d95cf | |||
c0d394ccfb | |||
a266bd9a94 | |||
610a092353 | |||
0d7e67b4b5 | |||
d6a9f39f32 | |||
887ca5ea8f | |||
dec889deca | |||
328038facb | |||
b20c3f68c9 | |||
f293d74a85 | |||
0bb74087ab | |||
abe03a9b7b | |||
9ee1999bec | |||
332fb1821b | |||
311c7d1e16 | |||
0b32953424 | |||
35eda54647 | |||
b8f225dabf | |||
71a78696ba | |||
e5543a9ab9 | |||
b9a1e0bd3a | |||
0b88b0ab34 | |||
4bffef5254 | |||
601dc3a723 | |||
26be41582f | |||
f5fe55db6c | |||
f3c889ad8b | |||
ca598de2ad | |||
cec65d42f2 |
32
.gitea/workflows/ci.yml
Normal file
32
.gitea/workflows/ci.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: Deploy to Dokku
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["master"]
|
||||||
|
paths-ignore:
|
||||||
|
- .gitignore
|
||||||
|
- README.md
|
||||||
|
- LICENSE
|
||||||
|
- servers.json
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: ["ubuntu-latest"]
|
||||||
|
runs-on: ${{ matrix.arch }}
|
||||||
|
|
||||||
|
# Steps to run
|
||||||
|
steps:
|
||||||
|
# Checkout the repo
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
# Deploy to Dokku
|
||||||
|
- name: Push to dokku
|
||||||
|
uses: dokku/github-action@master
|
||||||
|
with:
|
||||||
|
git_remote_url: "ssh://dokku@10.0.50.65:22/pia-servers"
|
||||||
|
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}
|
@ -1,52 +0,0 @@
|
|||||||
name: Fetch new Pia Servers
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "@hourly"
|
|
||||||
push:
|
|
||||||
branches: ["master"]
|
|
||||||
paths-ignore:
|
|
||||||
- .gitignore
|
|
||||||
- README.md
|
|
||||||
- LICENSE
|
|
||||||
- servers.json
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
docker:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
arch: ["ubuntu-latest"]
|
|
||||||
git-version: ["2.44.0"]
|
|
||||||
java-version: ["17"]
|
|
||||||
maven-version: ["3.8.5"]
|
|
||||||
runs-on: ${{ matrix.arch }}
|
|
||||||
|
|
||||||
# Steps to run
|
|
||||||
steps:
|
|
||||||
# Checkout the repo
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# Setup Java and Maven
|
|
||||||
- name: Set up JDK and Maven
|
|
||||||
uses: s4u/setup-maven-action@v1.12.0
|
|
||||||
with:
|
|
||||||
java-version: ${{ matrix.java-version }}
|
|
||||||
distribution: "zulu"
|
|
||||||
maven-version: ${{ matrix.maven-version }}
|
|
||||||
|
|
||||||
- name: Build PIA Servers
|
|
||||||
run: mvn clean package -T 2C -q
|
|
||||||
|
|
||||||
- name: Fetch new PIA servers
|
|
||||||
run: java -jar target/PIA-Servers.jar
|
|
||||||
|
|
||||||
- name: Commit and push changes
|
|
||||||
run: |
|
|
||||||
git config --global user.email "liam+pia-servers-ci@fascinated.cc"
|
|
||||||
git config --global user.name "PIA Servers CI"
|
|
||||||
git add servers.json
|
|
||||||
git add README.md
|
|
||||||
git commit -m "Scheduled update"
|
|
||||||
git push https://pia-servers-ci:${{ secrets.AUTH_TOKEN }}@git.fascinated.cc/Fascinated/PIA-Servers
|
|
||||||
|
|
32
Dockerfile
Normal file
32
Dockerfile
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Stage 1: Build the application
|
||||||
|
FROM maven:3.9.6-eclipse-temurin-17-alpine AS builder
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /home/container
|
||||||
|
|
||||||
|
# Copy the current directory contents into the container at /home/container
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the jar
|
||||||
|
RUN mvn package -q -Dmaven.test.skip -DskipTests -T2C
|
||||||
|
|
||||||
|
# Stage 2: Create the final lightweight image
|
||||||
|
FROM eclipse-temurin:17.0.11_9-jre-focal
|
||||||
|
|
||||||
|
# Install Git
|
||||||
|
RUN apt-get update && apt-get install -y git
|
||||||
|
|
||||||
|
# Set the app to be in production mode
|
||||||
|
ENV ENVIRONMENT=production
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /home/container
|
||||||
|
|
||||||
|
# Copy the built jar file from the builder stage
|
||||||
|
COPY --from=builder /home/container/target/PIA-Servers.jar .
|
||||||
|
|
||||||
|
# Copy the old servers.json file
|
||||||
|
COPY --from=builder /home/container/servers.json .
|
||||||
|
|
||||||
|
# Run the jar file
|
||||||
|
CMD java -jar PIA-Servers.jar -Djava.awt.headless=true
|
201
README.md
201
README.md
@ -1,106 +1,109 @@
|
|||||||
# PIA Server List
|
# PIA Server List
|
||||||
|
|
||||||
 
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
This is a list of the OpenVPN servers provided by Private Internet Access (PIA). The list is updated hourly.
|
This is a list of the OpenVPN servers provided by Private Internet Access (PIA). The list is updated hourly. </br>
|
||||||
|
Servers that have not been active in the last 2 weeks will be automatically removed.
|
||||||
|
|
||||||
## Servers
|
## Servers
|
||||||
| Region | Servers |
|
| Region | Servers |
|
||||||
|----------------------|---------|
|
|----------------------|---------|
|
||||||
| japan | 18 |
|
| ca_montreal | 816 |
|
||||||
| albania | 18 |
|
| netherlands | 811 |
|
||||||
| poland | 18 |
|
| us_texas | 708 |
|
||||||
| us_florida | 18 |
|
| us_chicago | 702 |
|
||||||
| andorra | 18 |
|
| ca_toronto | 643 |
|
||||||
| venezuela | 18 |
|
| us_silicon_valley | 601 |
|
||||||
| moldova | 18 |
|
| us_washington_dc | 589 |
|
||||||
| estonia | 18 |
|
| us_atlanta | 565 |
|
||||||
| ca_vancouver | 18 |
|
| us_west | 559 |
|
||||||
| sweden | 18 |
|
| ca_vancouver | 547 |
|
||||||
| united_arab_emirates | 18 |
|
| us_las_vegas | 542 |
|
||||||
| us_seattle | 18 |
|
| us_new_york | 541 |
|
||||||
| saudi_arabia | 18 |
|
| us_east | 536 |
|
||||||
| philippines | 18 |
|
| uk_london | 533 |
|
||||||
| us_las_vegas | 18 |
|
| us_california | 526 |
|
||||||
| us_east | 18 |
|
| us_florida | 496 |
|
||||||
| de_berlin | 18 |
|
| us_seattle | 496 |
|
||||||
| uk_manchester | 18 |
|
| ca_ontario | 430 |
|
||||||
| switzerland | 18 |
|
| au_melbourne | 426 |
|
||||||
| armenia | 18 |
|
| switzerland | 420 |
|
||||||
| vietnam | 18 |
|
| de_frankfurt | 417 |
|
||||||
| turkey | 18 |
|
| us_houston | 384 |
|
||||||
| ukraine | 18 |
|
| au_sydney | 355 |
|
||||||
| austria | 18 |
|
| uk_southampton | 318 |
|
||||||
| spain | 18 |
|
| japan | 308 |
|
||||||
| algeria | 18 |
|
| de_berlin | 261 |
|
||||||
| portugal | 18 |
|
| us_denver | 231 |
|
||||||
| cambodia | 18 |
|
| uk_manchester | 224 |
|
||||||
| lithuania | 18 |
|
| singapore | 218 |
|
||||||
| monaco | 18 |
|
| france | 202 |
|
||||||
| hungary | 18 |
|
| sweden | 192 |
|
||||||
| greenland | 18 |
|
| au_perth | 183 |
|
||||||
| panama | 18 |
|
| new_zealand | 183 |
|
||||||
| greece | 18 |
|
| mexico | 139 |
|
||||||
| us_california | 18 |
|
| ireland | 132 |
|
||||||
| luxembourg | 18 |
|
| romania | 120 |
|
||||||
| mongolia | 18 |
|
| estonia | 117 |
|
||||||
| us_west | 18 |
|
| norway | 112 |
|
||||||
| cyprus | 18 |
|
| belgium | 102 |
|
||||||
| italy | 18 |
|
| israel | 100 |
|
||||||
| finland | 18 |
|
| spain | 99 |
|
||||||
| nigeria | 18 |
|
| denmark | 96 |
|
||||||
| hong_kong | 18 |
|
| czech_republic | 94 |
|
||||||
| singapore | 18 |
|
| italy | 87 |
|
||||||
| mexico | 18 |
|
| finland | 84 |
|
||||||
| us_denver | 18 |
|
| bahamas | 78 |
|
||||||
| bahamas | 18 |
|
| argentina | 75 |
|
||||||
| norway | 18 |
|
| austria | 71 |
|
||||||
| au_perth | 18 |
|
| panama | 71 |
|
||||||
| bulgaria | 18 |
|
| brazil | 69 |
|
||||||
| ca_toronto | 18 |
|
| poland | 64 |
|
||||||
| us_new_york | 18 |
|
| luxembourg | 62 |
|
||||||
| uk_london | 18 |
|
| latvia | 60 |
|
||||||
| macao | 18 |
|
| ukraine | 59 |
|
||||||
| georgia | 18 |
|
| india | 59 |
|
||||||
| argentina | 18 |
|
| lithuania | 56 |
|
||||||
| liechtenstein | 18 |
|
| greenland | 56 |
|
||||||
| france | 18 |
|
| turkey | 52 |
|
||||||
| serbia | 18 |
|
| slovakia | 52 |
|
||||||
| slovakia | 18 |
|
| andorra | 48 |
|
||||||
| us_chicago | 18 |
|
| vietnam | 46 |
|
||||||
| belgium | 18 |
|
| taiwan | 46 |
|
||||||
| us_washington_dc | 18 |
|
| venezuela | 45 |
|
||||||
| netherlands | 18 |
|
| greece | 45 |
|
||||||
| isle_of_man | 18 |
|
| portugal | 43 |
|
||||||
| taiwan | 18 |
|
| united_arab_emirates | 38 |
|
||||||
| sri_lanka | 18 |
|
| china | 38 |
|
||||||
| czech_republic | 18 |
|
| malta | 37 |
|
||||||
| morocco | 18 |
|
| albania | 36 |
|
||||||
| us_texas | 18 |
|
| philippines | 36 |
|
||||||
| uk_southampton | 18 |
|
| algeria | 36 |
|
||||||
| brazil | 18 |
|
| qatar | 33 |
|
||||||
| de_frankfurt | 18 |
|
| bangladesh | 31 |
|
||||||
| romania | 18 |
|
| hungary | 30 |
|
||||||
| india | 18 |
|
| liechtenstein | 29 |
|
||||||
| us_silicon_valley | 18 |
|
| isle_of_man | 29 |
|
||||||
| au_sydney | 18 |
|
| saudi_arabia | 28 |
|
||||||
| denmark | 18 |
|
| bulgaria | 28 |
|
||||||
| au_melbourne | 18 |
|
| south_africa | 28 |
|
||||||
| ca_ontario | 18 |
|
| macao | 26 |
|
||||||
| latvia | 18 |
|
| montenegro | 26 |
|
||||||
| kazakhstan | 18 |
|
| nigeria | 25 |
|
||||||
| new_zealand | 18 |
|
| moldova | 24 |
|
||||||
| us_houston | 18 |
|
| cambodia | 24 |
|
||||||
| south_africa | 18 |
|
| cyprus | 24 |
|
||||||
| egypt | 18 |
|
| morocco | 24 |
|
||||||
| malta | 18 |
|
| egypt | 24 |
|
||||||
| iceland | 18 |
|
| iceland | 24 |
|
||||||
| macedonia | 18 |
|
| kazakhstan | 23 |
|
||||||
| ca_montreal | 18 |
|
| macedonia | 23 |
|
||||||
| montenegro | 18 |
|
| monaco | 22 |
|
||||||
| qatar | 18 |
|
| georgia | 22 |
|
||||||
| china | 18 |
|
| hong_kong | 20 |
|
||||||
| israel | 18 |
|
| serbia | 15 |
|
||||||
| bangladesh | 18 |
|
| armenia | 12 |
|
||||||
| us_atlanta | 18 |
|
| mongolia | 12 |
|
||||||
| ireland | 18 |
|
| sri_lanka | 11 |
|
17
pom.xml
17
pom.xml
@ -68,6 +68,15 @@
|
|||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<!-- Repos -->
|
||||||
|
<repositories>
|
||||||
|
<!-- Jitpack - Used for dnsjava -->
|
||||||
|
<repository>
|
||||||
|
<id>jitpack.io</id>
|
||||||
|
<url>https://jitpack.io</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Libraries -->
|
<!-- Libraries -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -83,6 +92,14 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- DNS -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.dnsjava</groupId>
|
||||||
|
<artifactId>dnsjava</artifactId>
|
||||||
|
<version>v3.5.2</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Archive Utilities -->
|
<!-- Archive Utilities -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.codehaus.plexus</groupId>
|
<groupId>org.codehaus.plexus</groupId>
|
||||||
|
6
renovate.json
Normal file
6
renovate.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
|
"extends": [
|
||||||
|
"local>Fascinated/renovate-config"
|
||||||
|
]
|
||||||
|
}
|
94282
servers.json
94282
servers.json
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,6 @@
|
|||||||
package cc.fascinated.piaservers;
|
package cc.fascinated.piaservers;
|
||||||
|
|
||||||
import cc.fascinated.piaservers.pia.PiaManager;
|
import cc.fascinated.piaservers.pia.PiaManager;
|
||||||
import cc.fascinated.piaservers.readme.ReadMeManager;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
@ -14,6 +13,5 @@ public class Main {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new PiaManager();
|
new PiaManager();
|
||||||
new ReadMeManager();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
13
src/main/java/cc/fascinated/piaservers/common/Config.java
Normal file
13
src/main/java/cc/fascinated/piaservers/common/Config.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package cc.fascinated.piaservers.common;
|
||||||
|
|
||||||
|
public class Config {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we in production?
|
||||||
|
*
|
||||||
|
* @return If we are in production
|
||||||
|
*/
|
||||||
|
public static boolean isProduction() {
|
||||||
|
return System.getenv().containsKey("ENVIRONMENT") && System.getenv("ENVIRONMENT").equals("production");
|
||||||
|
}
|
||||||
|
}
|
55
src/main/java/cc/fascinated/piaservers/common/GitUtils.java
Normal file
55
src/main/java/cc/fascinated/piaservers/common/GitUtils.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package cc.fascinated.piaservers.common;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class GitUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commit files to git
|
||||||
|
*
|
||||||
|
* @param message The commit message
|
||||||
|
* @param files The files to commit
|
||||||
|
*/
|
||||||
|
public static void commitFiles(String message, Path... files) {
|
||||||
|
System.out.println("Committing files");
|
||||||
|
if (Config.isProduction()) {
|
||||||
|
runCommand("git", "config", "--global", "user.email", "fascinated-helper@fascinated.cc");
|
||||||
|
runCommand("git", "config", "--global", "user.name", "Fascinated's Helper");
|
||||||
|
for (Path file : files) {
|
||||||
|
runCommand("git", "add", file.toAbsolutePath().toString());
|
||||||
|
}
|
||||||
|
runCommand("git", "commit", "-m", message);
|
||||||
|
runCommand("git", "push", "https://fascinated-helper:%s@git.fascinated.cc/Fascinated/PIA-Servers".formatted(System.getenv("AUTH_TOKEN")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the repository
|
||||||
|
*/
|
||||||
|
public static void cloneRepo() {
|
||||||
|
if (Config.isProduction()) {
|
||||||
|
System.out.println("Cloning repository");
|
||||||
|
runCommand("git", "clone", "https://git.fascinated.cc/Fascinated/PIA-Servers.git");
|
||||||
|
runCommand("mv", "PIA-Servers/.git", ".");
|
||||||
|
runCommand("rm", "-rf", "PIA-Servers");
|
||||||
|
runCommand("git", "pull"); // Pull the latest changes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run a system command
|
||||||
|
*
|
||||||
|
* @param args The command to run (with arguments)
|
||||||
|
*/
|
||||||
|
private static void runCommand(String... args) {
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder(args);
|
||||||
|
processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
|
||||||
|
processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||||
|
try {
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
process.waitFor();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,19 @@
|
|||||||
package cc.fascinated.piaservers.model;
|
package cc.fascinated.piaservers.model;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@AllArgsConstructor @Getter
|
@AllArgsConstructor @Getter @Setter
|
||||||
|
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
|
||||||
public class PiaServer {
|
public class PiaServer {
|
||||||
/**
|
/**
|
||||||
* The IP of this server.
|
* The IP of this server.
|
||||||
*/
|
*/
|
||||||
|
@EqualsAndHashCode.Include
|
||||||
private final String ip;
|
private final String ip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
package cc.fascinated.piaservers.model;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@AllArgsConstructor @Getter
|
|
||||||
public class PiaServerToken {
|
|
||||||
/**
|
|
||||||
* The hostname for this server.
|
|
||||||
*/
|
|
||||||
private final String hostname;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The region this server is in.
|
|
||||||
*/
|
|
||||||
private final String region;
|
|
||||||
}
|
|
@ -1,124 +1,142 @@
|
|||||||
package cc.fascinated.piaservers.pia;
|
package cc.fascinated.piaservers.pia;
|
||||||
|
|
||||||
import cc.fascinated.piaservers.Main;
|
import cc.fascinated.piaservers.Main;
|
||||||
|
import cc.fascinated.piaservers.common.GitUtils;
|
||||||
import cc.fascinated.piaservers.model.PiaServer;
|
import cc.fascinated.piaservers.model.PiaServer;
|
||||||
import cc.fascinated.piaservers.model.PiaServerToken;
|
import cc.fascinated.piaservers.readme.ReadMeManager;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
|
import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
|
||||||
|
import org.xbill.DNS.Record;
|
||||||
|
import org.xbill.DNS.*;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.InetAddress;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
import java.net.http.HttpResponse;
|
import java.net.http.HttpResponse;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class PiaManager {
|
public class PiaManager {
|
||||||
|
|
||||||
private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
|
private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
|
||||||
private static final String PIA_OPENVPN_CONFIGS_URL = "https://www.privateinternetaccess.com/openvpn/openvpn.zip";
|
private static final String PIA_OPENVPN_CONFIGS_URL = "https://www.privateinternetaccess.com/openvpn/openvpn.zip";
|
||||||
private static final long REMOVAL_THRESHOLD = TimeUnit.DAYS.toMicros(14); // 2 weeks
|
private static final long REMOVAL_THRESHOLD = TimeUnit.DAYS.toMicros(14); // 2 weeks
|
||||||
public static List<PiaServer> SERVERS = new ArrayList<>();
|
public static Set<PiaServer> SERVERS = new HashSet<>();
|
||||||
|
private static Path README_PATH;
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public PiaManager() {
|
public PiaManager() {
|
||||||
File serversFile = new File("servers.json");
|
File serversFile = new File("servers.json");
|
||||||
if (!serversFile.exists()) {
|
if (!serversFile.exists()) {
|
||||||
System.out.println("serversFile.json does not exist, creating...");
|
System.out.println("The servers file doesn't exist, creating it...");
|
||||||
serversFile.createNewFile();
|
serversFile.createNewFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PiaServerToken> piaDomain = getPiaDomains();
|
|
||||||
System.out.println("Found " + piaDomain.size() + " pia domains");
|
|
||||||
|
|
||||||
// Load the serversFile from the file
|
// Load the serversFile from the file
|
||||||
SERVERS = Main.GSON.fromJson(Files.readString(serversFile.toPath()), new TypeToken<List<PiaServer>>() {}.getType());
|
SERVERS = Main.GSON.fromJson(Files.readString(serversFile.toPath()), new TypeToken<Set<PiaServer>>() {}.getType());
|
||||||
if (SERVERS == null) {
|
if (SERVERS == null) {
|
||||||
SERVERS = new ArrayList<>();
|
SERVERS = new HashSet<>();
|
||||||
}
|
}
|
||||||
List<PiaServer> toRemove = new ArrayList<>();
|
System.out.printf("Loaded %s servers from the file%n", SERVERS.size());
|
||||||
|
|
||||||
System.out.println("Removing old servers...");
|
// Set the DNS resolver to Cloudflare
|
||||||
// Get the servers that need to be removed
|
Lookup.setDefaultResolver(new SimpleResolver("1.1.1.1"));
|
||||||
for (PiaServer server : SERVERS) {
|
|
||||||
if (server.getLastSeen().getTime() < System.currentTimeMillis() - REMOVAL_THRESHOLD) {
|
GitUtils.cloneRepo(); // Clone the repository
|
||||||
toRemove.add(server);
|
|
||||||
|
// Update the servers every 5 minutes
|
||||||
|
new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateServers(serversFile); // Update the servers
|
||||||
|
README_PATH = ReadMeManager.updateReadme(); // Update the README.md
|
||||||
}
|
}
|
||||||
}
|
}, 0, TimeUnit.MINUTES.toMillis(5));
|
||||||
SERVERS.removeAll(toRemove); // Remove the servers
|
|
||||||
System.out.printf("Removed %s old servers\n", toRemove.size());
|
// Commit the files every hour
|
||||||
|
new Timer().scheduleAtFixedRate(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
GitUtils.commitFiles("Scheduled update", serversFile.toPath(), README_PATH); // Commit the files
|
||||||
|
}
|
||||||
|
}, TimeUnit.MINUTES.toMillis(3), TimeUnit.HOURS.toMillis(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
public static void updateServers(File serversFile) {
|
||||||
|
List<PiaServer> servers = getPiaServers();
|
||||||
|
|
||||||
|
// Remove the servers that haven't been active in 2 weeks
|
||||||
|
int before = SERVERS.size();
|
||||||
|
SERVERS.removeIf(server -> System.currentTimeMillis() - server.getLastSeen().getTime() > REMOVAL_THRESHOLD);
|
||||||
|
System.out.printf("Removed %s servers that haven't been active in 2 weeks%n", before - SERVERS.size());
|
||||||
|
|
||||||
// Add the new servers to the list
|
// Add the new servers to the list
|
||||||
for (PiaServerToken serverToken : piaDomain) {
|
int newServers = 0;
|
||||||
InetAddress address = InetAddress.getByName(serverToken.getHostname());
|
for (PiaServer piaServer : servers) {
|
||||||
|
boolean newServer = SERVERS.stream().noneMatch(server -> server.getIp().equals(piaServer.getIp()));
|
||||||
|
if (newServer) {
|
||||||
|
newServers++;
|
||||||
|
}
|
||||||
|
|
||||||
// Add the server to the list
|
// Add the server to the list
|
||||||
SERVERS.add(new PiaServer(address.getHostAddress(), serverToken.getRegion(), new Date()));
|
SERVERS.add(piaServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the servers to the file
|
// Save the servers to the file
|
||||||
Files.writeString(serversFile.toPath(), Main.GSON.toJson(SERVERS));
|
Files.writeString(serversFile.toPath(), Main.GSON.toJson(SERVERS));
|
||||||
System.out.printf("Wrote %s servers to the file\n", SERVERS.size());
|
System.out.printf("Wrote %s servers to the file (+%s new)%n", SERVERS.size(), newServers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private static List<PiaServerToken> getPiaDomains() {
|
private static List<PiaServer> getPiaServers() {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
.uri(URI.create(PIA_OPENVPN_CONFIGS_URL))
|
.uri(URI.create(PIA_OPENVPN_CONFIGS_URL))
|
||||||
.GET()
|
.GET()
|
||||||
.build();
|
.build();
|
||||||
// Send the request and get the response
|
|
||||||
HttpResponse<Path> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofFile(Files.createTempFile("openvpn", ".zip")));
|
HttpResponse<Path> response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofFile(Files.createTempFile("openvpn", ".zip")));
|
||||||
if (response.statusCode() != 200) {
|
if (response.statusCode() != 200) {
|
||||||
System.out.println("Failed to get the PIA OpenVPN configs, status code: " + response.statusCode());
|
throw new IOException("Failed to get the PIA OpenVPN configs, status code: " + response.statusCode());
|
||||||
System.exit(1);
|
|
||||||
}
|
}
|
||||||
|
System.out.printf("Downloaded the OpenVPN configs in %sms%n", System.currentTimeMillis() - start);
|
||||||
Path downloadedFile = response.body();
|
Path downloadedFile = response.body();
|
||||||
File tempDir = Files.createTempDirectory("openvpn").toFile();
|
File tempDir = Files.createTempDirectory("openvpn").toFile();
|
||||||
ZipUnArchiver unArchiver = new ZipUnArchiver();
|
ZipUnArchiver unArchiver = new ZipUnArchiver();
|
||||||
|
|
||||||
// Extract the downloaded file
|
|
||||||
unArchiver.setSourceFile(downloadedFile.toFile());
|
unArchiver.setSourceFile(downloadedFile.toFile());
|
||||||
unArchiver.setDestDirectory(tempDir);
|
unArchiver.setDestDirectory(tempDir);
|
||||||
unArchiver.extract();
|
unArchiver.extract();
|
||||||
|
|
||||||
// Get the extracted files
|
|
||||||
File[] files = tempDir.listFiles();
|
File[] files = tempDir.listFiles();
|
||||||
if (files == null || files.length == 0) {
|
if (files == null || files.length == 0) {
|
||||||
System.out.println("Failed to extract the OpenVPN configs");
|
throw new IOException("Failed to extract the OpenVPN configs");
|
||||||
System.exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for the server domains
|
List<PiaServer> servers = new ArrayList<>();
|
||||||
List<PiaServerToken> domains = new ArrayList<>();
|
|
||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory() || !file.getName().endsWith(".ovpn")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!file.getName().endsWith(".ovpn")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Read the file and get the server domain
|
|
||||||
List<String> lines = Files.readAllLines(file.toPath());
|
List<String> lines = Files.readAllLines(file.toPath());
|
||||||
for (String line : lines) {
|
for (String line : lines) {
|
||||||
if (line.startsWith("remote ")) {
|
if (line.startsWith("remote ")) {
|
||||||
String[] parts = line.split(" ");
|
String[] parts = line.split(" ");
|
||||||
String domain = parts[1];
|
String hostname = parts[1];
|
||||||
String region = file.getName().split("\\.")[0];
|
String region = file.getName().split("\\.")[0];
|
||||||
|
Record[] records = new Lookup(hostname, Type.A).run();
|
||||||
domains.add(new PiaServerToken(domain, region));
|
if (records != null) {
|
||||||
|
for (Record record : records) {
|
||||||
|
ARecord aRecord = (ARecord) record;
|
||||||
|
servers.add(new PiaServer(aRecord.getAddress().getHostAddress(), region, new Date()));
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return servers;
|
||||||
return domains;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,24 +5,25 @@ import cc.fascinated.piaservers.model.PiaServer;
|
|||||||
import cc.fascinated.piaservers.pia.PiaManager;
|
import cc.fascinated.piaservers.pia.PiaManager;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.Path;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class ReadMeManager {
|
public class ReadMeManager {
|
||||||
|
private static final DecimalFormat decimalFormat = new DecimalFormat("#,###");
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public ReadMeManager() {
|
public static Path updateReadme() {
|
||||||
|
System.out.println("Updating README.md");
|
||||||
InputStream readmeStream = Main.class.getResourceAsStream("/README.md");
|
InputStream readmeStream = Main.class.getResourceAsStream("/README.md");
|
||||||
if (readmeStream == null) {
|
if (readmeStream == null) {
|
||||||
System.out.println("Failed to find README.md");
|
System.out.println("Failed to find README.md");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
File readmeFile = new File("README.md");
|
File readmeFile = new File("README.md");
|
||||||
if (!readmeFile.exists()) { // Create the file if it doesn't exist
|
if (!readmeFile.exists()) { // Create the file if it doesn't exist
|
||||||
@ -31,21 +32,25 @@ public class ReadMeManager {
|
|||||||
// Get the contents of the README.md
|
// Get the contents of the README.md
|
||||||
String contents = new String(readmeStream.readAllBytes());
|
String contents = new String(readmeStream.readAllBytes());
|
||||||
|
|
||||||
// Replace the placeholders in the README.md file
|
|
||||||
contents = contents.replace("{server_count}", String.valueOf(PiaManager.SERVERS.size()));
|
|
||||||
contents = contents.replace("{last_update}", new Date().toString().replaceAll(" ", "_"));
|
|
||||||
|
|
||||||
// Write total servers per-region
|
|
||||||
Map<String, Integer> regionCounts = new HashMap<>();
|
Map<String, Integer> regionCounts = new HashMap<>();
|
||||||
for (PiaServer server : PiaManager.SERVERS) {
|
for (PiaServer server : PiaManager.SERVERS) {
|
||||||
String region = server.getRegion();
|
String region = server.getRegion();
|
||||||
regionCounts.put(region, regionCounts.getOrDefault(region, 0) + 1);
|
regionCounts.put(region, regionCounts.getOrDefault(region, 0) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace the placeholders in the README.md file
|
||||||
|
contents = contents.replace("{server_count}", decimalFormat.format(PiaManager.SERVERS.size()));
|
||||||
|
contents = contents.replace("{last_update}", new Date().toString().replaceAll(" ", "_"));
|
||||||
|
contents = contents.replace("{region_count}", decimalFormat.format(regionCounts.size()));
|
||||||
|
|
||||||
|
// Write total servers per-region
|
||||||
contents = contents.replace("{server_table}", regionCounts.entrySet().stream()
|
contents = contents.replace("{server_table}", regionCounts.entrySet().stream()
|
||||||
.sorted((a, b) -> Integer.compare(b.getValue(), a.getValue())) // Sort from highest to lowest
|
.sorted((a, b) -> Integer.compare(b.getValue(), a.getValue())) // Sort from highest to lowest
|
||||||
.map(entry -> "| " + entry.getKey() + " | " + entry.getValue() + " |") // Map the region to the count
|
.map(entry -> "| " + entry.getKey() + " | " + entry.getValue() + " |") // Map the region to the count
|
||||||
.reduce((a, b) -> a + "\n" + b).orElse("")); // Reduce the entries to a single string
|
.reduce((a, b) -> a + "\n" + b).orElse("")); // Reduce the entries to a single string
|
||||||
|
|
||||||
Files.write(readmeFile.toPath(), contents.getBytes());
|
Files.write(readmeFile.toPath(), contents.getBytes());
|
||||||
|
System.out.println("Finished updating README.md");
|
||||||
|
return readmeFile.toPath();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
# PIA Server List
|
# PIA Server List
|
||||||
|
|
||||||
 
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
This is a list of the OpenVPN servers provided by Private Internet Access (PIA). The list is updated hourly.
|
This is a list of the OpenVPN servers provided by Private Internet Access (PIA). The list is updated hourly. </br>
|
||||||
|
Servers that have not been active in the last 2 weeks will be automatically removed.
|
||||||
|
|
||||||
## Servers
|
## Servers
|
||||||
| Region | Servers |
|
| Region | Servers |
|
||||||
|
Reference in New Issue
Block a user