Skip to content

Commit 8373105

Browse files
committed
Rewrite client core logic, implement Guard API client
1 parent e00cde5 commit 8373105

56 files changed

Lines changed: 1532 additions & 353 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build.gradle

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
apply plugin: 'maven'
66

77
group 'ru.redguy'
8-
version '1.1.4'
8+
version '2.0.0'
99

1010
repositories {
1111
maven {
@@ -14,9 +14,9 @@ repositories {
1414
}
1515

1616
dependencies {
17-
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
18-
implementation 'com.google.code.gson:gson:2.8.9'
19-
implementation 'org.jetbrains:annotations:23.0.0'
17+
implementation 'com.squareup.okhttp3:okhttp:5.3.2'
18+
implementation 'com.google.code.gson:gson:2.13.2'
19+
implementation 'org.jetbrains:annotations:26.1.0'
2020
}
2121

2222
//utf-8

readme.md

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
Library to use [redguy api](https://wiki.redguy.ru/Api "redguy api").
66

77
## Install
8-
gradle
8+
9+
Gradle:
910
```groovy
1011
repositories {
1112
mavenCentral()
@@ -15,6 +16,45 @@ repositories {
1516
}
1617
1718
dependencies {
18-
compile group: 'ru.redguy', name: 'redguyapi', version: '1.1.0'
19+
implementation group: 'ru.redguy', name: 'redguyapi', version: '2.0.0'
1920
}
2021
```
22+
23+
## Usage
24+
25+
```java
26+
RedGuyApi api = RedGuyApi.builder("token")
27+
.baseUrl("https://api.redguy.ru/")
28+
.build();
29+
30+
ServerInfo serverInfo = api.minecraft().serverInfo("play.example.org");
31+
User user = api.users().info();
32+
```
33+
34+
For the default API URL, the short constructor is still available:
35+
36+
```java
37+
RedGuyApi api = new RedGuyApi("token");
38+
```
39+
40+
## Guard API
41+
42+
Guard API uses a separate base URL and Bearer token authorization:
43+
44+
```java
45+
GuardApi guard = GuardApi.builder("token").build();
46+
47+
GasStatus gas = guard.gas().status(123456789L);
48+
AiPack pack = guard.ai().pack("Minecraft");
49+
UserInfoResponse user = guard.users().info(
50+
"123456789",
51+
Arrays.asList("-1001234567890")
52+
);
53+
```
54+
55+
Public Guard endpoints can also be called without a token:
56+
57+
```java
58+
GuardApi guard = GuardApi.builder().build();
59+
GasStatus gas = guard.gas().status(123456789L);
60+
```
Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,13 @@
11
package ru.redguy.redguyapi;
22

3-
public class ApiError extends Exception {
4-
5-
private final int code;
6-
private final String comment;
7-
3+
public class ApiError extends RedGuyApiException {
84
/**
95
* The error returned by the api server, to clarify the reason, see https://wiki.redguy.ru/Api/Errors
106
*
117
* @param code Error id
128
* @param comment Error name
139
*/
1410
public ApiError(int code, String comment) {
15-
super();
16-
this.code = code;
17-
this.comment = comment;
18-
}
19-
20-
@Override
21-
public String getMessage() {
22-
return comment;
23-
}
24-
25-
/**
26-
* Returns error id, to clarify the reason, see https://wiki.redguy.ru/Api/Errors
27-
*
28-
* @return Error id
29-
*/
30-
public int getCode() {
31-
return code;
11+
super(code, comment);
3212
}
3313
}
Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,51 @@
11
package ru.redguy.redguyapi;
22

3-
import org.jetbrains.annotations.Contract;
4-
import org.jetbrains.annotations.NotNull;
3+
import com.google.gson.Gson;
4+
import okhttp3.OkHttpClient;
55
import ru.redguy.redguyapi.hashes.Hashes;
66
import ru.redguy.redguyapi.links.Links;
77
import ru.redguy.redguyapi.minecraft.Minecraft;
8-
import ru.redguy.redguyapi.news.News;
98
import ru.redguy.redguyapi.text.Text;
109
import ru.redguy.redguyapi.token.Token;
1110
import ru.redguy.redguyapi.users.Users;
1211

13-
import java.util.HashMap;
1412
import java.util.Map;
13+
import java.util.Objects;
1514

1615
public class RedGuyApi {
17-
18-
private final Map<String, String> options;
19-
20-
private RedGuyApi() {
21-
this.options = new HashMap<>();
22-
}
16+
private final RedGuyApiClient client;
2317

2418
/**
2519
* Constructs main api object.
2620
*
2721
* @param token Your api token.
2822
*/
2923
public RedGuyApi(String token) {
30-
this.options = verifyOptions(new HashMap<>(), token);
24+
this(RedGuyApiConfig.configBuilder(token).build());
3125
}
3226

3327
/**
3428
* Constructs main api object with specified params.
3529
*
3630
* @param token Your api token.
3731
* @param options Additional client params
32+
* @deprecated use {@link #builder(String)}.
3833
*/
34+
@Deprecated
3935
public RedGuyApi(String token, Map<String, String> options) {
40-
this.options = verifyOptions(options, token);
36+
RedGuyApiConfig.Builder builder = RedGuyApiConfig.configBuilder(token);
37+
if (options.containsKey("baseUrl")) {
38+
builder.baseUrl(options.get("baseUrl"));
39+
}
40+
this.client = new RedGuyApiClient(builder.build());
41+
}
42+
43+
public RedGuyApi(RedGuyApiConfig config) {
44+
this.client = new RedGuyApiClient(Objects.requireNonNull(config, "config"));
4145
}
4246

43-
@NotNull
44-
@Contract("_, _ -> param1")
45-
private Map<String, String> verifyOptions(@NotNull Map<String, String> options, String token) {
46-
options.put("token", token);
47-
return options;
47+
public static Builder builder(String token) {
48+
return new Builder(token);
4849
}
4950

5051
/**
@@ -53,7 +54,7 @@ private Map<String, String> verifyOptions(@NotNull Map<String, String> options,
5354
* @return Minecraft API section
5455
*/
5556
public Minecraft minecraft() {
56-
return new Minecraft(options);
57+
return new Minecraft(client);
5758
}
5859

5960
/**
@@ -62,7 +63,7 @@ public Minecraft minecraft() {
6263
* @return Token API section
6364
*/
6465
public Token token() {
65-
return new Token(options);
66+
return new Token(client);
6667
}
6768

6869
/**
@@ -71,16 +72,7 @@ public Token token() {
7172
* @return Users API section
7273
*/
7374
public Users users() {
74-
return new Users(options);
75-
}
76-
77-
/**
78-
* Returns new instance of News API section
79-
*
80-
* @return News API section
81-
*/
82-
public News news() {
83-
return new News(options);
75+
return new Users(client);
8476
}
8577

8678
/**
@@ -89,7 +81,7 @@ public News news() {
8981
* @return Hashes API section
9082
*/
9183
public Hashes hashes() {
92-
return new Hashes(options);
84+
return new Hashes(client);
9385
}
9486

9587
/**
@@ -98,10 +90,41 @@ public Hashes hashes() {
9890
* @return Links API section
9991
*/
10092
public Links links() {
101-
return new Links(options);
93+
return new Links(client);
10294
}
10395

10496
public Text text() {
105-
return new Text(options);
97+
return new Text(client);
98+
}
99+
100+
public static final class Builder {
101+
private final RedGuyApiConfig.Builder configBuilder;
102+
103+
private Builder(String token) {
104+
this.configBuilder = RedGuyApiConfig.configBuilder(token);
105+
}
106+
107+
public Builder baseUrl(String baseUrl) {
108+
configBuilder.baseUrl(baseUrl);
109+
return this;
110+
}
111+
112+
public Builder httpClient(OkHttpClient httpClient) {
113+
configBuilder.httpClient(httpClient);
114+
return this;
115+
}
116+
117+
public Builder gson(Gson gson) {
118+
configBuilder.gson(gson);
119+
return this;
120+
}
121+
122+
public RedGuyApiConfig config() {
123+
return configBuilder.build();
124+
}
125+
126+
public RedGuyApi build() {
127+
return new RedGuyApi(config());
128+
}
106129
}
107130
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package ru.redguy.redguyapi;
2+
3+
import com.google.gson.JsonElement;
4+
import okhttp3.HttpUrl;
5+
import okhttp3.MediaType;
6+
import okhttp3.Request;
7+
import okhttp3.RequestBody;
8+
import okhttp3.Response;
9+
import okhttp3.ResponseBody;
10+
import org.jetbrains.annotations.NotNull;
11+
import ru.redguy.redguyapi.internal.ApiEnvelope;
12+
13+
import java.io.IOException;
14+
import java.util.Collections;
15+
import java.util.Map;
16+
import java.util.Objects;
17+
18+
public final class RedGuyApiClient {
19+
private static final MediaType JSON_MEDIA_TYPE = MediaType.get("application/json; charset=utf-8");
20+
21+
private final RedGuyApiConfig config;
22+
23+
public RedGuyApiClient(@NotNull RedGuyApiConfig config) {
24+
this.config = config;
25+
}
26+
27+
public <T> T get(String path, Class<T> responseType) throws ApiError, IOException {
28+
return get(path, Collections.emptyMap(), responseType);
29+
}
30+
31+
public <T> T get(String path, Map<String, ?> query, Class<T> responseType) throws ApiError, IOException {
32+
Request request = new Request.Builder()
33+
.url(url(path, query))
34+
.get()
35+
.build();
36+
return execute(request, responseType);
37+
}
38+
39+
public void get(String path, Map<String, ?> query) throws ApiError, IOException {
40+
get(path, query, Void.class);
41+
}
42+
43+
public <T> T post(String path, Object body, Class<T> responseType) throws ApiError, IOException {
44+
return post(path, Collections.emptyMap(), body, responseType);
45+
}
46+
47+
public <T> T post(String path, Map<String, ?> query, Object body, Class<T> responseType) throws ApiError, IOException {
48+
String jsonBody = body instanceof String ? (String) body : config.getGson().toJson(body);
49+
Request request = new Request.Builder()
50+
.url(url(path, query))
51+
.post(RequestBody.create(jsonBody, JSON_MEDIA_TYPE))
52+
.build();
53+
return execute(request, responseType);
54+
}
55+
56+
private <T> T execute(Request request, Class<T> responseType) throws ApiError, IOException {
57+
try (Response response = config.getHttpClient().newCall(request).execute()) {
58+
ResponseBody body = response.body();
59+
String responseBody = body == null ? "" : body.string();
60+
ApiEnvelope result = config.getGson().fromJson(responseBody, ApiEnvelope.class);
61+
if (result == null) {
62+
throw new IOException("Empty API response");
63+
}
64+
if (!result.isSuccessful()) {
65+
throw new ApiError(result.getCode(), result.getComment());
66+
}
67+
if (responseType == null || responseType == Void.class) {
68+
return null;
69+
}
70+
JsonElement responseElement = result.getResponse();
71+
return config.getGson().fromJson(responseElement, responseType);
72+
}
73+
}
74+
75+
private HttpUrl url(String path, Map<String, ?> query) {
76+
HttpUrl.Builder builder = config.getBaseUrl().newBuilder()
77+
.addPathSegments(trimSlashes(path));
78+
builder.addQueryParameter("token", config.getToken());
79+
query.forEach((name, value) -> {
80+
if (value != null) {
81+
builder.addQueryParameter(name, String.valueOf(value));
82+
}
83+
});
84+
return Objects.requireNonNull(builder.build(), "url");
85+
}
86+
87+
private static String trimSlashes(String path) {
88+
String result = path;
89+
while (result.startsWith("/")) {
90+
result = result.substring(1);
91+
}
92+
while (result.endsWith("/")) {
93+
result = result.substring(0, result.length() - 1);
94+
}
95+
return result;
96+
}
97+
}

0 commit comments

Comments
 (0)