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

org.hogel.bookscan.BookscanClient Maven / Gradle / Ivy

package org.hogel.bookscan;

import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.hogel.bookscan.exception.BookscanException;
import org.hogel.bookscan.exception.BookscanNetworkException;
import org.hogel.bookscan.exception.BookscanResponseException;
import org.hogel.bookscan.model.Book;
import org.hogel.bookscan.model.OptimizedBook;
import org.hogel.bookscan.model.OptimizingBook;
import org.hogel.bookscan.reqeust.Request;
import org.jsoup.Connection;
import org.jsoup.helper.HttpConnection;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BookscanClient {
    private static final Logger LOG = LoggerFactory.getLogger(BookscanClient.class);

    private static final Charset UTF8 = Charset.forName("UTF-8");

    private final Connector connector;
    private final ExecutorService executorService;

    public BookscanClient() {
        this(new BasicConnector());
    }

    public BookscanClient(Connector connector) {
        this(Executors.newSingleThreadExecutor(), connector);
    }

    public BookscanClient(ExecutorService executorService, Connector connector) {
        this.connector = connector;
        this.executorService = executorService;
    }

    public boolean isLogin() {
        Map cookies = connector.getCookies();
        return cookies.containsKey("email") && cookies.containsKey("password");
    }

    public Request login(String email, String password) {
        Connection connection = connector.connect(Constants.URL_LOGIN)
            .method(Connection.Method.POST)
            .data("email", email)
            .data("password", password);
        return new Request(executorService, connector, connection) {
            @Override
            public Void get() throws BookscanException {
                Document document = getDocument();
                if (Constants.URL_LOGIN.equals(document.location())) {
                    throw new BookscanResponseException(document);
                }
                return null;
            }
        };
    }

    public Request> fetchBooks() {
        Connection connection = connector.connect(Constants.URL_MYPAGE).method(Connection.Method.GET);
        return new Request>(executorService, connector, connection) {
            @Override
            public List get() throws BookscanException {
                Document document = getDocument();
                Elements bookLinks = document.select("#sortable_box .showbook");
                List books = new ArrayList<>();
                for (Element bookLink : bookLinks) {
                    String url = Constants.URL_ROOT + bookLink.attr("href");
                    List params;
                    try {
                        params = URLEncodedUtils.parse(new URI(url), UTF8.name());
                    } catch (URISyntaxException e) {
                        LOG.error(e.getMessage(), e);
                        continue;
                    }
                    String filename = null, hash = null, digest = null;
                    for (NameValuePair param : params) {
                        switch (param.getName()) {
                            case "f":
                                filename = param.getValue();
                                break;
                            case "h":
                                hash = param.getValue();
                                break;
                            case "d":
                                digest = param.getValue();
                                break;
                        }
                    }
                    if (filename == null || hash == null || digest == null) {
                        continue;
                    }
                    Elements imgElement = bookLink.select("img");
                    Book book;
                    if (imgElement.size() == 0) {
                        book = new Book(filename, hash, digest, null);
                    } else {
                        book = new Book(filename, hash, digest, imgElement.first().attr("data-original"));
                    }
                    books.add(book);
                }
                return books;
            }
        };
    }

    public Request> fetchOptimizedBooks() {
        Connection connection = connector.connect(Constants.URL_OPTIMIZED_BOOKS).method(Connection.Method.GET);
        return new Request>(executorService, connector, connection) {
            @Override
            public List get() throws BookscanException {
                Document document = getDocument();
                Elements bookLinks = document.select("a.download");
                List books = new ArrayList<>();
                for (Element bookLink : bookLinks) {
                    String url = Constants.URL_ROOT + bookLink.attr("href");
                    List params;
                    try {
                        params = URLEncodedUtils.parse(new URI(url), UTF8.name());
                    } catch (URISyntaxException e) {
                        LOG.error(e.getMessage(), e);
                        continue;
                    }
                    String filename = null, digest = null;
                    for (NameValuePair param : params) {
                        switch (param.getName()) {
                            case "f":
                                filename = param.getValue();
                                break;
                            case "d":
                                digest = param.getValue();
                                break;
                        }
                    }
                    if (filename == null || digest == null) {
                        continue;
                    }
                    books.add(new OptimizedBook(filename, digest));
                }
                return books;
            }
        };
    }

    public Request requestBookOptimize(final Book book, final OptimizeOption option) throws BookscanException {
        String optimizeUrl = book.createOptimizeUrl();

        final List types = option.getTypes();
        final List flags = option.getFlags();
        if (types.size() == 0) {
            throw new IllegalArgumentException("Optimize option is not specified");
        }

        List hiddenOptions = fetchHiddenOptimizeOptions(optimizeUrl);

        Connection connection = connector.connect(optimizeUrl).method(Connection.Method.POST);

        for (Connection.KeyVal hiddenOption : hiddenOptions) {
            connection = connection.data(hiddenOption.key(), hiddenOption.value());
        }

        for (OptimizeOption.Type type : types) {
            connection = connection.data(OptimizeOption.OPTIMIZE_TYPE_NAME, type.getValue());
        }

        for (OptimizeOption.Flag flag : flags) {
            connection = connection.data(flag.getInputName(), flag.getValue());
        }

        return new Request(executorService, connector, connection) {
            @Override
            public Void get() throws BookscanException {
                Document document = getDocument();
                if (!book.createOptimizedUrl().equals(document.location())) {
                    throw new BookscanResponseException(document);
                }

                return null;
            }
        };
    }

    public List fetchHiddenOptimizeOptions(String optimizeUrl) throws BookscanNetworkException {
        Connection connection = connector.connect(optimizeUrl).method(Connection.Method.GET);
        try {
            Document document = connector.execute(connection);
            Elements inputs = document.select("input");

            List keyVals = new ArrayList<>();

            for (Element input : inputs) {
                if (input.attr("type").equals("hidden")) {
                    final String name = input.attr("name");
                    final String value = input.attr("value");
                    keyVals.add(HttpConnection.KeyVal.create(name, value));
                }
            }

            return keyVals;
        } catch (IOException e) {
            throw new BookscanNetworkException(e);
        }
    }

    private static final Pattern OPTIMIZING_BOOK_PATTERN =
        Pattern.compile("(.+\\.pdf)\\s*チューニングタイプ:(.+)\\s*チューニング依頼日時:(\\d+年\\d+月\\d+日 \\d+:\\d+)\\s*(.+)\\s+優先度:");
    public Request> fetchOptimizingBooks() {
        Connection connection = connector.connect(Constants.URL_OPTIMIZING_BOOKS).method(Connection.Method.GET);
        return new Request>(executorService, connector, connection) {
            @Override
            public List get() throws BookscanException {
                Document document = getDocument();

                Elements typeLabels = document.getElementsContainingOwnText("チューニングタイプ:");
                List books = new ArrayList<>();
                for (Element typeLabel : typeLabels) {
                    Element container = typeLabel.parent();
                    String text = container.text();

                    Matcher matcher = OPTIMIZING_BOOK_PATTERN.matcher(text);
                    if (!matcher.find()) {
                        continue;
                    }

                    String file = matcher.group(1).trim();
                    String type = matcher.group(2).trim();
                    String requestedAt = matcher.group(3).trim();
                    String status = matcher.group(4).trim();
                    OptimizingBook book = new OptimizingBook(file, type, requestedAt, status);
                    books.add(book);
                }
                return books;
            }
        };
    }

    public Map getCookies() {
        return connector.getCookies();
    }

    public void putCookies(Map cookies) {
        connector.putCookies(cookies);
    }

    public void clearCookies() {
        connector.clearCookies();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy