Skip to content

proxer/ProxerLibJava

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ProxerLibJava Release CircleCI Coverage

What is this?

This is a JVM (Java, Kotlin) and Android library, implementing the API of the Proxer.Me website. This is currently v1. Built on Retrofit, OkHttp and Moshi, it offers great performance and flexibility.

Including in your project

The preferred build system is Gradle.
Add this to your project wide build.gradle:

repositories {
    maven { url "https://jitpack.io" }
}

And this to your module build.gradle:

dependencies {
    implementation 'com.github.proxer:ProxerLibJava:5.4.0'
}

You can also download the jar directly from here, if you prefer.

Note that this jar does not come with the required dependencies. You have to include those manually in that case.

Usage

Initialization

All requests are done through the ProxerApi class. You initialize an instance with the ProxerApi.Builder.
The most simple initialization looks like this:

ProxerApi api = new ProxerApi.Builder("yourApiKey").build();

You can customize the ProxerApi in the following ways:

Method Description
loginTokenManager Sets an own LoginTokenManager for automatic login. This will covered later.
userAgent Sets a custom Http User-Agent to be used. This defaults to ProxerLibJava/<Version> otherwise. Pass an empty String if you don't want to sent one.
moshi Sets a custom Moshi instance, used for parsing. Note, that various adapters are still applied, to make the API work properly.
client Sets a custom OkHttpClient instance, used for Http requests. Note, that various interceptors are still applied, to make the API work properly.
retrofit Sets a custom Retrofit instance.

The API feature a test mode, which does not require a key. For most calls, this returns a predefined result and ignores the actual input. To enable the test mode, pass ProxerApi.Test_KEY or simply "test" to the constructor.

Sending a request

The API is divided in classes for the various request, similar to the actual REST-API.
A simple query for the latest news looks like this:

List<NewsArticle> result = api.notifications()
                .news()
                .build()
                .execute();

The build method returns a ProxerCall object. If you are familiar with OkHttp, this works exactly the same. The ProxerCall object also allows for asynchronous requests:

api.notifications().news()
        .page(0)
        .limit(10)
        .build()
        .enqueue(result -> {
            // Show the result.
        }, error -> {
            // Show the error.
        });

As you can see in the example above, the individual endpoints also allow for various options.

Coroutines

It is also possible to execute requests in a coroutine context when using Kotlin. Use the await extension function on the ProxerCall:

val result = api.notifications().news().build().await()

Cancelling a request

You might want to cancel a request, especially if using on Android:

ProxerCall call = api.[...].build()

call.cancel();

It is an error to execute a cancelled ProxerCall.

Error handling

All errors are encapsulated in a ProxerException. It offers the following info about the error:

Method Description
getErrorType Returns the general error type.
getServerErrorType Returns the type of server error.
getMessage Returns the associated message of the error if it was a server error. Otherwise null.

These are the available general error types:

Type Description
SERVER An error on the server occurred. This can for example be LOGIN_INVALID_CREDENTIALS, signaling that incorrect credentials were passed during login.
TIMEOUT The server did not respond in time.
IO The data transfer failed. This can happen if no network connectivity is present for example.
PARSING The server sent broken data. This happens mostly when the REST-API changed and this library was not adjusted yet.
UNKNOWN Any other type of error. This is an internal error in most cases.

There is a wide range of server errors. Consult the ProxerException class for details.
Here is a selection of important ones:

Type Description
INSUFFICIENT_PERMISSIONS Your API-key is not allowed to access the API.
IP_BLOCKED You sent to many request in a specific time duration.
*_INVALID_* The passed data was not correct.
*_LOGIN_REQUIRED This section can only be accessed as a logged in user.

You catch errors like this (synchronous):

try {
    api.notifications().news()
            .build()
            .execute();
} catch (ProxerException error) {
    // Handle the error here.
}

Or like this (asynchronous):

api.notifications().news()
        .build()
        .enqueue(result -> {
            // No error occurred.
        }, error -> {
            // Handler the error here.
        });

If you just want to present the error to the user, it can be done like so:

void handleError(ProxerException error) {
    switch (error.getErrorType()) {
        case SERVER:
            print(error.getMessage());

            break;
        case TIMEOUT:
            print("The server did not respond in time.");

            break;
        case IO:
            print("Data transfer failed. Check your network connection.");

            break;
        case PARSING:
            print("The server sent broken data.");

            break;
        case UNKNOWN:
            print("An unkown error occurred.");

            break;
    }
}

Login

The ProxerApi offers a mechanism for automatic login.
If you call the user.login API, the relevant information is stored automatically. If you then call user.logout, is is also removed automatically.

You can customize this behaviour through a custom LoginTokenManager.
The most simple one looks like this (Such a LoginTokenManager is used if you do not pass one):

ProxerApi api = new ProxerApi.Builder("yourApiKey")
        .loginTokenManager(new LoginTokenManager() {

            private String token;

            @Nullable
            @Override
            public String provide() {
                return token;
            }

            @Override
            public void persist(@Nullable String loginToken) {
                token = loginToken;
            }
        })
        .build();

The token is only stored in memory with the default LoginTokenManager. This means, that you lose the login information when the application terminates. You may want to persist it into a File or SharedPreferences on Android.

Rate limiting

The api has rate limiting in place with individual limits for each api class. If more requests than the limit are performed, a ProxerException (with the ServerErrorType.IP_BLOCKED) is thrown and the user has to solve a captcha. The link to the captcha page can be obtained with ProxerUrls.captchaWeb().

Rate limit protection

Recent versions have a mechanism for protecting against rate limiting implemented. It can be enabled by calling the method:

ProxerApi api = new ProxerApi.Builder("yourApiKey")
        .enableRateLimitProtection()
        .build();

This cancels requests which would trigger the rate limit and throw a ProxerException (with the ServerErrorType.RATE_LIMIT). The user does not need to solve the captcha but simply wait then.

This does not completely captcha errors. If multiple users call from the same network, the rate limit can still be hit and thus the error needs to be handled properly.

Utils

This library offers two utility classes: ProxerUrls and ProxerUtils.

ProxerUrls

The ProxerUrls class has various static methods for getting often needed urls.
These are returned as an HttpUrl, which has various advantages above the default Java classes.

Retrieving the url to the image of an user can be done like so:

HttpUrl url = ProxerUrls.userImage("image property of the UserInfo entity here");

ProxerUtils

The API often returns entities, which have enums as properties. You may want to get the String representation, which is actually used for communication. To do so, you can use the getApiEnumName method:

String genreAsString = ProxerUtils.getApiEnumName(Genre.ACTION);

The other way around is also available:

Genre genreAsEnum = ProxerUtils.toApiEnum(Genre.class, "Action");

ProGuard/R8

In recent versions of the library, the required config is bundled in the jar.
If you need to provide the config yourself (e.g. when using an older ProGuard version), see the config here and also look for the configs of the used libraries.

More

You can find detailed JavaDoc here.

Working on the library

Recommended development environment is IntelliJ IDEA.
Make sure to run ./gradlew build before importing, so the IDE can pick up generated code.

Dependencies

This library is written in Kotlin and highly relies on Retrofit and OkHttp by Square for the network communication.
Moreover it uses Moshi for response parsing.

Contributions and contributors

A guide for contribution can be found here.

  • @Desnoo for implementing several APIs.