Skip to content
This repository was archived by the owner on Apr 18, 2023. It is now read-only.

Commit 7a14cc9

Browse files
committed
init
1 parent 12bfc9f commit 7a14cc9

File tree

7 files changed

+375
-0
lines changed

7 files changed

+375
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# idea & maven
2+
target/
3+
.idea/
4+
*.iml
5+
16
# Compiled class file
27
*.class
38

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
# AUpdater-Public
22
DDNS client for DNSPod
3+
4+
## Usage
5+
```shell
6+
$ java -jar AUpdater.jar [configPath] [--test]
7+
```

aupdater.properties

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
login_token=
2+
token_id=
3+
domain_id=
4+
subdomain_id=
5+
subdomain_name=
6+
record_line=\u9ed8\u8ba4
7+
update_interval_minutes=30
8+
update_interval_minutes_err=10

aupdater.service

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[Unit]
2+
Description=AUpdater DDNS Client
3+
Wants=network-online.target
4+
After=network-online.target
5+
6+
[Service]
7+
Type=simple
8+
ExecStart=java -Xmx16m -jar /root/AUpdater.jar /root/aupdater.properties
9+
ExecStop=/bin/kill -15 $MAINPID
10+
SuccessExitStatus=143
11+
12+
[Install]
13+
WantedBy=multi-user.target

pom.xml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>vip.floatationdevice</groupId>
8+
<artifactId>aupdater</artifactId>
9+
<version>1.0</version>
10+
11+
<properties>
12+
<maven.compiler.source>8</maven.compiler.source>
13+
<maven.compiler.target>8</maven.compiler.target>
14+
</properties>
15+
16+
<dependencies>
17+
<dependency>
18+
<groupId>cn.hutool</groupId>
19+
<artifactId>hutool-http</artifactId>
20+
<version>5.7.14</version>
21+
</dependency>
22+
<dependency>
23+
<groupId>cn.hutool</groupId>
24+
<artifactId>hutool-json</artifactId>
25+
<version>5.7.14</version>
26+
</dependency>
27+
</dependencies>
28+
29+
<build>
30+
<plugins>
31+
<!-- special thanks to https://stackoverflow.com/questions/1729054/including-dependencies-in-a-jar-with-maven -->
32+
<plugin>
33+
<artifactId>maven-assembly-plugin</artifactId>
34+
<version>3.1.1</version>
35+
<executions>
36+
<execution>
37+
<id>make-assembly</id>
38+
<phase>package</phase>
39+
<goals>
40+
<goal>single</goal>
41+
</goals>
42+
</execution>
43+
</executions>
44+
<configuration>
45+
<descriptorRefs>
46+
<descriptorRef>jar-with-dependencies</descriptorRef>
47+
</descriptorRefs>
48+
<archive>
49+
<manifest>
50+
<mainClass>vip.floatationdevice.aupdater.AUpdater</mainClass>
51+
</manifest>
52+
</archive>
53+
</configuration>
54+
</plugin>
55+
<plugin>
56+
<groupId>org.apache.maven.plugins</groupId>
57+
<artifactId>maven-compiler-plugin</artifactId>
58+
<version>3.8.1</version>
59+
<configuration>
60+
<source>1.8</source>
61+
<target>1.8</target>
62+
<encoding>UTF-8</encoding>
63+
</configuration>
64+
</plugin>
65+
</plugins>
66+
</build>
67+
68+
</project>
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package vip.floatationdevice.aupdater;
2+
3+
import static vip.floatationdevice.aupdater.Util.*;
4+
5+
public class AUpdater
6+
{
7+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
8+
// runtime values
9+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10+
11+
static String ip, prevIP;
12+
13+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
14+
// config values
15+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16+
17+
// default config file path: "./aupdater.properties"
18+
// can be overridden by command line argument
19+
static String configPath ="aupdater.properties";
20+
21+
static String
22+
login_token,
23+
subdomain_name,
24+
record_line;
25+
static int
26+
token_id,
27+
domain_id,
28+
subdomain_id,
29+
update_interval_minutes,
30+
update_interval_minutes_err;
31+
32+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33+
// api related
34+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
35+
36+
final static String
37+
API_URL = "https://dnsapi.cn/",
38+
UA = "AUpdater/1.0(mcumbrella@protonmail.com)",
39+
LANG = "en",
40+
ERR_ON_EMPTY = "no";
41+
42+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
43+
// main
44+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
45+
46+
public static void main(String[] args)
47+
{
48+
// override default config path?
49+
switch(args.length)
50+
{
51+
case 0:
52+
break;
53+
case 1:
54+
case 2:
55+
configPath = args[0];
56+
break;
57+
default:
58+
System.err.println("Usage: java -jar AUpdater.jar [configPath] [--test]");
59+
System.exit(1);
60+
}
61+
62+
// load config
63+
try
64+
{
65+
System.out.println("Loading config");
66+
loadConfig();
67+
System.out.println("Config loaded");
68+
// just a test?
69+
if(args.length == 2)
70+
{
71+
if(args[1].equals("--test"))
72+
{
73+
System.out.println("=================================================="
74+
+ "\nConfig file test passed:"
75+
+ "\n login_token = " + login_token
76+
+ "\n token_id = "+ token_id
77+
+ "\n domain_id = " + domain_id
78+
+ "\n subdomain_id = " + subdomain_id
79+
+ "\n subdomain_name = " + subdomain_name
80+
+ "\n record_line = " + record_line
81+
+ "\n update_interval_minutes = " + update_interval_minutes
82+
+ "\n update_interval_minutes_err = " + update_interval_minutes_err
83+
+ "\n=================================================="
84+
);
85+
System.exit(0);
86+
}
87+
else
88+
{
89+
System.err.println("Usage: java -jar AUpdater.jar [configPath] [--test]");
90+
System.exit(1);
91+
}
92+
}
93+
}catch (Exception e)
94+
{
95+
System.err.println("Error loading config file");
96+
e.printStackTrace();
97+
System.exit(-1);
98+
}
99+
100+
// get previous IP first
101+
try
102+
{
103+
System.out.println("Getting previous IP record");
104+
prevIP = getPreviousIP();
105+
System.out.println("Previous IP: " + prevIP);
106+
}catch (Exception e)
107+
{
108+
System.err.println("Getting previous IP address failed");
109+
e.printStackTrace();
110+
prevIP="0.0.0.0";
111+
}
112+
113+
// run updater loop
114+
try
115+
{
116+
do
117+
{
118+
// get local ip
119+
try
120+
{
121+
System.out.println("Getting local IP address");
122+
ip = getLocalIP();
123+
System.out.println("Local IP: " + ip);
124+
}catch(Exception e)
125+
{
126+
System.err.println("Getting local IP address failed");
127+
e.printStackTrace();
128+
ip = prevIP;
129+
System.out.println("Next update scheduled in "+update_interval_minutes_err+" minute(s)");
130+
Thread.sleep((long)update_interval_minutes_err*60*1000);
131+
continue;
132+
}
133+
134+
// skip if ip is the same as previous
135+
if(ip.equals(prevIP))
136+
{
137+
System.out.println("IP address is the same as previous one\nNext update scheduled in "+update_interval_minutes+" minute(s)");
138+
Thread.sleep((long)update_interval_minutes*60*1000);
139+
continue;
140+
}
141+
142+
// update record
143+
try
144+
{
145+
System.out.println("Updating record");
146+
updateRecord();
147+
System.out.println("Update record success: " + prevIP + " to " + ip);
148+
}catch(Exception e)
149+
{
150+
System.err.println("Failed to update record");
151+
e.printStackTrace();
152+
System.out.println("Next update scheduled in " + update_interval_minutes_err + " minute(s)");
153+
Thread.sleep((long)update_interval_minutes_err*60*1000);
154+
continue;
155+
}
156+
157+
// update previous ip, sleep for 30 minutes
158+
prevIP=ip;
159+
System.out.println("Next update scheduled in " + update_interval_minutes + " minute(s)");
160+
Thread.sleep((long)update_interval_minutes*60*1000);
161+
}while(true);
162+
}catch (InterruptedException e){e.printStackTrace();}
163+
}
164+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
package vip.floatationdevice.aupdater;
2+
3+
import cn.hutool.core.io.IORuntimeException;
4+
import cn.hutool.http.HttpRequest;
5+
import cn.hutool.json.JSONObject;
6+
import cn.hutool.json.JSONUtil;
7+
8+
import java.io.BufferedReader;
9+
import java.io.FileReader;
10+
import java.util.Properties;
11+
12+
import static vip.floatationdevice.aupdater.AUpdater.*;
13+
14+
public class Util
15+
{
16+
static void checkNullArguments(Object... objects)
17+
{
18+
for(Object o : objects)
19+
if(o == null || o.toString().isEmpty())
20+
throw new IllegalArgumentException("Null value detected");
21+
}
22+
23+
static void loadConfig() throws Exception
24+
{
25+
BufferedReader f = new BufferedReader(new FileReader(configPath));
26+
Properties p = new Properties();
27+
p.load(f);
28+
f.close();
29+
login_token = p.getProperty("login_token");
30+
token_id = Integer.parseUnsignedInt(p.getProperty("token_id"));
31+
domain_id = Integer.parseUnsignedInt(p.getProperty("domain_id"));
32+
subdomain_id = Integer.parseUnsignedInt(p.getProperty("subdomain_id"));
33+
subdomain_name = p.getProperty("subdomain_name");
34+
record_line = p.getProperty("record_line");
35+
update_interval_minutes = Integer.parseUnsignedInt(p.getProperty("update_interval_minutes"));
36+
update_interval_minutes_err = Integer.parseUnsignedInt(p.getProperty("update_interval_minutes_err"));
37+
checkNullArguments(
38+
login_token,
39+
token_id,
40+
domain_id,
41+
subdomain_id,
42+
subdomain_name,
43+
record_line,
44+
update_interval_minutes,
45+
update_interval_minutes_err
46+
);
47+
if(update_interval_minutes == 0 || update_interval_minutes_err == 0)
48+
throw new IllegalArgumentException("Interval must >0");
49+
}
50+
51+
static String getGeneralArgs()
52+
{
53+
return "login_token=" + token_id + "," + login_token + "&format=json&lang=" + LANG + "&err_on_empty=" + ERR_ON_EMPTY;
54+
}
55+
56+
static String getLocalIP()
57+
{
58+
String result = HttpRequest.get("http://pv.sohu.com/cityjson?ie=utf-8").execute().body();
59+
String t = result.substring(result.indexOf("{"),result.lastIndexOf("}")+1);
60+
if(JSONUtil.isJson(t))
61+
{
62+
String cip = JSONUtil.parseObj(t).getStr("cip");
63+
if(cip == null) throw new NullPointerException("No IP address found in JSON string:\n" + t);
64+
return cip;
65+
}
66+
else throw new ClassCastException("Result is not JSON string:\n" + t);
67+
}
68+
69+
static String getPreviousIP()
70+
{
71+
String result = HttpRequest.post(API_URL + "Record.Info")
72+
.clearHeaders()
73+
.header("User-Agent", UA)
74+
.header("Accept", "application/json")
75+
.body(getGeneralArgs()
76+
+"&domain_id=" + domain_id
77+
+"&record_id=" + subdomain_id
78+
+"&remark=\"\""
79+
).execute().body();
80+
if(JSONUtil.isJson(result))
81+
{
82+
JSONObject json = JSONUtil.parseObj(result);
83+
int statusCode = Integer.parseInt(json.getByPath("status.code").toString());
84+
if(statusCode == 1) return json.getByPath("record.value").toString();
85+
else throw new IllegalStateException("API status code is not 1:\n" + result);
86+
}
87+
else throw new ClassCastException("Result is not JSON string:\n" + result);
88+
}
89+
90+
static void updateRecord() throws IORuntimeException
91+
{
92+
String result = HttpRequest.post(API_URL + "Record.Modify")
93+
.clearHeaders()
94+
.header("User-Agent", UA)
95+
.header("Accept", "application/json")
96+
.body(getGeneralArgs()
97+
+"&domain_id=" + domain_id
98+
+"&record_id=" + subdomain_id
99+
+"&sub_domain=" + subdomain_name
100+
+"&record_type=A"
101+
+"&value=" + ip
102+
+"&record_line=" + record_line
103+
+"&mx=1"
104+
).execute().body();
105+
if(JSONUtil.isJson(result))
106+
{
107+
if (Integer.parseInt(JSONUtil.parseObj(result).getByPath("status.code").toString()) != 1)
108+
throw new IllegalStateException("API status code is not 1:\n" + result);
109+
}
110+
else throw new IllegalStateException("Result is not JSON string:\n" + result);
111+
}
112+
}

0 commit comments

Comments
 (0)