All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.robertograham.fortnite2.implementation.DefaultAccountResource Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
package io.github.robertograham.fortnite2.implementation;

import io.github.robertograham.fortnite2.domain.Account;
import io.github.robertograham.fortnite2.resource.AccountResource;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.apache.http.HttpHeaders.AUTHORIZATION;

final class DefaultAccountResource implements AccountResource {

    private static final int MAX_ID_COUNT_PER_ACCOUNTS_REQUEST = 100;
    private final CloseableHttpClient httpClient;
    private final OptionalResponseHandlerProvider optionalResponseHandlerProvider;
    private final Supplier accessTokenSupplier;
    private final Supplier sessionAccountIdSupplier;

    private DefaultAccountResource(final CloseableHttpClient httpClient,
                                   final OptionalResponseHandlerProvider optionalResponseHandlerProvider,
                                   final Supplier accessTokenSupplier,
                                   final Supplier sessionAccountIdSupplier) {
        this.httpClient = httpClient;
        this.optionalResponseHandlerProvider = optionalResponseHandlerProvider;
        this.accessTokenSupplier = accessTokenSupplier;
        this.sessionAccountIdSupplier = sessionAccountIdSupplier;
    }

    static DefaultAccountResource newInstance(final CloseableHttpClient httpClient,
                                              final OptionalResponseHandlerProvider optionalResponseHandlerProvider,
                                              final Supplier sessionTokenSupplier,
                                              final Supplier sessionAccountIdSupplier) {
        return new DefaultAccountResource(
            httpClient,
            optionalResponseHandlerProvider,
            sessionTokenSupplier,
            sessionAccountIdSupplier
        );
    }

    @Override
    public Optional findOneByDisplayName(final String displayName) throws IOException {
        Objects.requireNonNull(displayName, "displayName cannot be null");
        try {
            return httpClient.execute(
                RequestBuilder.get(new URIBuilder()
                    .setScheme("https")
                    .setHost("account-public-service-prod03.ol.epicgames.com")
                    .setPath(String.format(
                        "/%s/%s",
                        "account/api/public/account/displayName",
                        displayName
                    ))
                    .build())
                    .setHeader(AUTHORIZATION, "bearer " + accessTokenSupplier.get())
                    .build(),
                optionalResponseHandlerProvider.forClass(DefaultAccount.class)
            )
                .map(Function.identity());
        } catch (final URISyntaxException exception) {
            throw new IOException("Bad URI", exception);
        }
    }

    @Override
    public Optional findOneBySessionAccountId() throws IOException {
        return findAllByAccountIds(sessionAccountIdSupplier.get())
            .flatMap((final var accountSet) ->
                accountSet.stream()
                    .findFirst()
            );
    }

    @Override
    public Optional> findAllByAccountIds(final String... accountIds) throws IOException {
        Objects.requireNonNull(accountIds, "accountIds cannot be null");
        if (Arrays.stream(accountIds)
            .anyMatch(Objects::isNull))
            throw new NullPointerException("accountIds cannot contain null value");
        final var accountIdPartitionSetSet = IntStream.range(0, accountIds.length)
            .boxed()
            .collect(Collectors.groupingBy((final var integer) ->
                integer / MAX_ID_COUNT_PER_ACCOUNTS_REQUEST
            ))
            .values()
            .stream()
            .map((final var integerList) ->
                integerList.stream()
                    .map((final var integer) -> accountIds[integer])
                    .collect(Collectors.toSet())
            )
            .collect(Collectors.toSet());
        final var optionalAccountSetSet = new HashSet>>();
        for (final var accountIdPartitionSet : accountIdPartitionSetSet)
            optionalAccountSetSet.add(findAllByAccountIds(accountIdPartitionSet));
        return optionalAccountSetSet.stream()
            .reduce((final var optionalAccountSet,
                     final var optionalAccountSetAccumulator) ->
                optionalAccountSetAccumulator.map((final var accountSet) -> {
                    accountSet.addAll(optionalAccountSet.orElseGet(HashSet::new));
                    return accountSet;
                })
            )
            .orElseGet(Optional::empty);
    }

    private Optional> findAllByAccountIds(final Set accountIds) throws IOException {
        return httpClient.execute(
            RequestBuilder.get("https://account-public-service-prod03.ol.epicgames.com/account/api/public/account")
                .addParameters(accountIds.stream()
                    .map((final var accountIdString) -> new BasicNameValuePair("accountId", accountIdString))
                    .toArray(BasicNameValuePair[]::new))
                .setHeader(AUTHORIZATION, "bearer " + accessTokenSupplier.get())
                .build(),
            optionalResponseHandlerProvider.forClass(DefaultAccount[].class)
        )
            .map(Set::of);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy