com.nttec.everychan.chans.sich.SichModule.java Source code

Java tutorial

Introduction

Here is the source code for com.nttec.everychan.chans.sich.SichModule.java

Source

/*
 * Everychan Android (Meta Imageboard Client)
 * Copyright (C) 2014-2016  miku-nyan <https://github.com/miku-nyan>
 *     
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.nttec.everychan.chans.sich;

import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.tuple.Pair;
import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.HttpHeaders;
import cz.msebera.android.httpclient.entity.mime.content.ByteArrayBody;
import cz.msebera.android.httpclient.message.BasicHeader;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.support.v4.content.res.ResourcesCompat;
import com.nttec.everychan.R;
import com.nttec.everychan.api.AbstractVichanModule;
import com.nttec.everychan.api.interfaces.CancellableTask;
import com.nttec.everychan.api.interfaces.ProgressListener;
import com.nttec.everychan.api.models.AttachmentModel;
import com.nttec.everychan.api.models.BadgeIconModel;
import com.nttec.everychan.api.models.BoardModel;
import com.nttec.everychan.api.models.DeletePostModel;
import com.nttec.everychan.api.models.PostModel;
import com.nttec.everychan.api.models.SendPostModel;
import com.nttec.everychan.api.models.SimpleBoardModel;
import com.nttec.everychan.api.models.UrlPageModel;
import com.nttec.everychan.api.util.ChanModels;
import com.nttec.everychan.common.IOUtils;
import com.nttec.everychan.http.ExtendedMultipartBuilder;
import com.nttec.everychan.http.streamer.HttpRequestModel;
import com.nttec.everychan.http.streamer.HttpResponseModel;
import com.nttec.everychan.http.streamer.HttpStreamer;
import com.nttec.everychan.lib.org_json.JSONObject;

public class SichModule extends AbstractVichanModule {
    private static final String CHAN_NAME = "sich.co.ua";
    private static final String DEFAULT_DOMAIN = "sich.co.ua";
    private static final String[] ATTACHMENT_FORMATS = new String[] { "bmp", "gif", "jpeg", "jpg", "png", "mp4",
            "webm" };
    private static final SimpleBoardModel[] BOARDS = new SimpleBoardModel[] {
            ChanModels.obtainSimpleBoardModel(CHAN_NAME, "b", "", "?", true),
            ChanModels.obtainSimpleBoardModel(CHAN_NAME, "int", "International", "?", false),
            ChanModels.obtainSimpleBoardModel(CHAN_NAME, "a", "?", "", false),
            ChanModels.obtainSimpleBoardModel(CHAN_NAME, "f", "", "", true),
            ChanModels.obtainSimpleBoardModel(CHAN_NAME, "po", "", "", false),
            ChanModels.obtainSimpleBoardModel(CHAN_NAME, "soc", "", "", false), };
    private static final Pattern ERROR_PATTERN = Pattern.compile("<h2 [^>]*>(.*?)</h2>");

    public SichModule(SharedPreferences preferences, Resources resources) {
        super(preferences, resources);
    }

    @Override
    public String getChanName() {
        return CHAN_NAME;
    }

    @Override
    public String getDisplayingName() {
        return "";
    }

    @Override
    public Drawable getChanFavicon() {
        return ResourcesCompat.getDrawable(resources, R.drawable.favicon_sich, null);
    }

    @Override
    protected boolean canCloudflare() {
        return true;
    }

    @Override
    protected String getUsingDomain() {
        return DEFAULT_DOMAIN;
    }

    @Override
    protected boolean canHttps() {
        return true;
    }

    @Override
    protected boolean useHttpsDefaultValue() {
        return true;
    }

    @Override
    protected SimpleBoardModel[] getBoardsList() {
        return BOARDS;
    }

    @Override
    public BoardModel getBoard(String shortName, ProgressListener listener, CancellableTask task) throws Exception {
        BoardModel model = super.getBoard(shortName, listener, task);
        model.bumpLimit = 250;
        model.allowNames = false;
        model.allowSage = false;
        model.allowEmails = false;
        model.attachmentsMaxCount = 4;
        model.attachmentsFormatFilters = ATTACHMENT_FORMATS;
        return model;
    }

    @Override
    protected PostModel mapPostModel(JSONObject object, String boardName) {
        PostModel model = super.mapPostModel(object, boardName);
        model.comment = model.comment.replaceAll("style=\"text-decoration:line-through;\">", "class=\"s\">");
        model.comment = model.comment.replaceAll("class=\"quote dice\">", "class=\"unkfunc\">");
        if (boardName.equals("int")) {
            String country = object.optString("country");
            if (country != null && country.length() > 0) {
                model.icons = new BadgeIconModel[] { new BadgeIconModel() };
                model.icons[0].source = "/static/flags/" + country.toLowerCase(Locale.US) + ".png";
                model.icons[0].description = object.optString("country_name", country);
            }
        }
        return model;
    }

    @Override
    protected AttachmentModel mapAttachment(JSONObject object, String boardName, boolean isSpoiler) {
        String ext = object.optString("ext", "");
        if (!ext.equals("")) {
            AttachmentModel attachment = new AttachmentModel();
            switch (ext) {
            case ".jpeg":
            case ".jpg":
            case ".png":
                attachment.type = AttachmentModel.TYPE_IMAGE_STATIC;
                break;
            case ".gif":
                attachment.type = AttachmentModel.TYPE_IMAGE_GIF;
                break;
            case ".webm":
            case ".mp4":
                attachment.type = AttachmentModel.TYPE_VIDEO;
                break;
            default:
                attachment.type = AttachmentModel.TYPE_OTHER_FILE;
            }
            attachment.size = object.optInt("fsize", -1);
            if (attachment.size > 0)
                attachment.size = Math.round(attachment.size / 1024f);
            attachment.width = object.optInt("w", -1);
            attachment.height = object.optInt("h", -1);
            attachment.originalName = object.optString("filename", "") + ext;
            attachment.isSpoiler = isSpoiler;
            String tim = object.optString("tim", "");
            String _t_ext = object.optString("_t_ext", ".png");
            if (tim.length() > 0 && _t_ext != ".webm") {
                attachment.thumbnail = isSpoiler ? null : ("/" + boardName + "/thumb/" + tim + _t_ext);
                attachment.path = "/" + boardName + "/src/" + tim + ext;
                return attachment;
            }
        }
        return null;
    }

    @Override
    public String sendPost(SendPostModel model, ProgressListener listener, CancellableTask task) throws Exception {
        UrlPageModel urlModel = new UrlPageModel();
        urlModel.chanName = CHAN_NAME;
        urlModel.boardName = model.boardName;
        if (model.threadNumber == null) {
            urlModel.type = UrlPageModel.TYPE_BOARDPAGE;
            urlModel.boardPage = UrlPageModel.DEFAULT_FIRST_PAGE;
        } else {
            urlModel.type = UrlPageModel.TYPE_THREADPAGE;
            urlModel.threadNumber = model.threadNumber;
        }
        String referer = buildUrl(urlModel);
        List<Pair<String, String>> fields = VichanAntiBot.getFormValues(referer, task, httpClient);

        if (task != null && task.isCancelled())
            throw new Exception("interrupted");

        ExtendedMultipartBuilder postEntityBuilder = ExtendedMultipartBuilder.create()
                .setCharset(Charset.forName("UTF-8")).setDelegates(listener, task);
        for (Pair<String, String> pair : fields) {
            if (pair.getKey().equals("spoiler"))
                continue;
            String val;
            switch (pair.getKey()) {
            case "subject":
                val = model.subject;
                break;
            case "body":
                val = model.comment;
                break;
            case "password":
                val = model.password;
                break;
            default:
                val = pair.getValue();
            }
            int i = 1;
            String fileNo;
            switch (pair.getKey()) {
            case "file":
            case "file2":
            case "file3":
            case "file4":
                fileNo = pair.getKey().replaceAll("[\\D]", "");
                if (fileNo != "") {
                    i = Integer.parseInt(fileNo);
                }
                if (model.attachments == null || model.attachments.length < i) {
                    postEntityBuilder.addPart(pair.getKey(), new ByteArrayBody(new byte[0], ""));
                } else {
                    postEntityBuilder.addFile(pair.getKey(), model.attachments[i - 1], model.randomHash);
                }
                break;
            default:
                postEntityBuilder.addString(pair.getKey(), val);
            }
        }

        String url = getUsingUrl() + "post.php";
        Header[] customHeaders = new Header[] { new BasicHeader(HttpHeaders.REFERER, referer) };
        HttpRequestModel request = HttpRequestModel.builder().setPOST(postEntityBuilder.build())
                .setCustomHeaders(customHeaders).setNoRedirect(true).build();
        HttpResponseModel response = null;
        try {
            response = HttpStreamer.getInstance().getFromUrl(url, request, httpClient, listener, task);
            if (response.statusCode == 200 || response.statusCode == 400) {
                ByteArrayOutputStream output = new ByteArrayOutputStream(1024);
                IOUtils.copyStream(response.stream, output);
                String htmlResponse = output.toString("UTF-8");
                Matcher errorMatcher = ERROR_PATTERN.matcher(htmlResponse);
                if (errorMatcher.find())
                    throw new Exception(errorMatcher.group(1));
            } else if (response.statusCode == 303) {
                for (Header header : response.headers) {
                    if (header != null && HttpHeaders.LOCATION.equalsIgnoreCase(header.getName())) {
                        return fixRelativeUrl(header.getValue());
                    }
                }
            }
            throw new Exception(response.statusCode + " - " + response.statusReason);
        } finally {
            if (response != null)
                response.release();
        }
    }

    @Override
    protected String getDeleteFormValue(DeletePostModel model) {
        return model.boardName.equals("int") ? "Delete" : "";
    }

    @Override
    protected String getReportFormValue(DeletePostModel model) {
        return model.boardName.equals("int") ? "Report" : "???";
    }
}