/* * Overchan 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 nya.miku.wishmaster.chans.dvach; import android.annotation.SuppressLint; import java.io.IOException; import java.io.InputStream; import java.text.DateFormat; import java.text.DateFormatSymbols; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang3.StringEscapeUtils; import nya.miku.wishmaster.api.models.AttachmentModel; import nya.miku.wishmaster.api.models.BadgeIconModel; import nya.miku.wishmaster.api.models.PostModel; import nya.miku.wishmaster.api.models.ThreadModel; import nya.miku.wishmaster.api.util.RegexUtils; import nya.miku.wishmaster.api.util.WakabaReader; @SuppressLint("SimpleDateFormat") public class DvachReader extends WakabaReader { private static final Pattern COUNTRYBALL_PATTERN = Pattern.compile("url\\('(.*?)'"); private static final Pattern ADMIN_MARK_PATTERN = Pattern.compile("<span class=\"red italic\">(.*?)</span>"); private static final Pattern DATE_PATTERN = Pattern.compile("(\\d+ \\w+ \\d+ \\d\\d:\\d\\d:\\d\\d)$"); private static final DateFormat DATE_FORMAT; static { DateFormatSymbols dvachSymbols = new DateFormatSymbols(); dvachSymbols.setMonths(new String[] { "Янв", "Фев", "Мар", "Апр", "Мая", "Июн", "Июл", "Авг", "Сен", "Окт", "Ноя", "Дек" }); DATE_FORMAT = new SimpleDateFormat("dd MMM yyyy HH:mm:ss", dvachSymbols); DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+3")); } private static final char[] TRIP_FILTER = "<span class=\"postertrip \">".toCharArray(); private static final char[] TINATRIP_FILTER = "<span class=\"postertrip vip\">".toCharArray(); private static final char[] NUM_FILTER = "<a id=\"".toCharArray(); private static final char[] LABELOPEN_FILTER = "<label>".toCharArray(); private static final char[] LABELCLOSE_FILTER = "</label>".toCharArray(); private static final char[] COUNTRYBALL_FILTER = "<div class=\"countryball\"".toCharArray(); private int curTripPos = 0; private int curTinaTripPos = 0; private int curNumPos = 0; private int curLabelOpenPos = 0; private int curLabelClosePos = 0; private int curCountryBallPos = 0; private StringBuilder dateBuf = new StringBuilder(); private boolean inDate = false; public DvachReader(InputStream in) { super(in, null, true); } @Override protected void customFilters(int ch) throws IOException { if (inDate) dateBuf.append((char) ch); if (ch == TRIP_FILTER[curTripPos]) { ++curTripPos; if (curTripPos == TRIP_FILTER.length) { currentPost.trip = StringEscapeUtils.unescapeHtml4(RegexUtils.removeHtmlTags(readUntilSequence("</span>".toCharArray()))).trim(); curTripPos = 0; } } else { if (curTripPos != 0) curTripPos = ch == TRIP_FILTER[0] ? 1 : 0; } if (ch == TINATRIP_FILTER[curTinaTripPos]) { ++curTinaTripPos; if (curTinaTripPos == TINATRIP_FILTER.length) { currentPost.trip = StringEscapeUtils.unescapeHtml4(RegexUtils.removeHtmlTags(readUntilSequence("</span>".toCharArray()))).trim() + '\u2655'; curTinaTripPos = 0; } } else { if (curTinaTripPos != 0) curTinaTripPos = ch == TINATRIP_FILTER[0] ? 1 : 0; } if (ch == NUM_FILTER[curNumPos]) { ++curNumPos; if (curNumPos == NUM_FILTER.length) { currentPost.number = readUntilSequence("\"".toCharArray()); curNumPos = 0; } } else { if (curNumPos != 0) curNumPos = ch == NUM_FILTER[0] ? 1 : 0; } if (ch == LABELOPEN_FILTER[curLabelOpenPos]) { ++curLabelOpenPos; if (curLabelOpenPos == LABELOPEN_FILTER.length) { inDate = true; dateBuf.setLength(0); curLabelOpenPos = 0; } } else { if (curLabelOpenPos != 0) curLabelOpenPos = ch == LABELOPEN_FILTER[0] ? 1 : 0; } if (ch == LABELCLOSE_FILTER[curLabelClosePos]) { ++curLabelClosePos; if (curLabelClosePos == LABELCLOSE_FILTER.length) { inDate = false; parseDvachDate(dateBuf.toString()); curLabelClosePos = 0; } } else { if (curLabelClosePos != 0) curLabelClosePos = ch == LABELCLOSE_FILTER[0] ? 1 : 0; } if (ch == COUNTRYBALL_FILTER[curCountryBallPos]) { ++curCountryBallPos; if (curCountryBallPos == COUNTRYBALL_FILTER.length) { parseCountryBall(readUntilSequence(">".toCharArray())); curCountryBallPos = 0; } } else { if (curCountryBallPos != 0) curCountryBallPos = ch == COUNTRYBALL_FILTER[0] ? 1 : 0; } } private void parseCountryBall(String countryBall) { Matcher countryBallMatcher = COUNTRYBALL_PATTERN.matcher(countryBall); if (countryBallMatcher.find()) { BadgeIconModel badge = new BadgeIconModel(); badge.source = countryBallMatcher.group(1); if (badge.source.endsWith(".png") && badge.source.indexOf('/') != -1) badge.description = badge.source.substring(badge.source.lastIndexOf('/') + 1, badge.source.length() - 4); currentPost.icons = new BadgeIconModel[] { badge }; } } @Override protected void parseDate(String date) {} //turn off default implementation from WakabaReader private void parseDvachDate(String date) { date = date.substring(0, date.length() - 8).trim(); Matcher dateMatcher = DATE_PATTERN.matcher(date); if (dateMatcher.find()) { try { currentPost.timestamp = DATE_FORMAT.parse(dateMatcher.group(1)).getTime(); } catch (ParseException e) {} } } @Override protected void postprocessPost(PostModel post) { post.comment = RegexUtils.replaceAll(post.comment, ADMIN_MARK_PATTERN, "<font color=\"red\"><em>$1</em></font>"); if (post.attachments != null) for (AttachmentModel attachment : post.attachments) attachment.originalName = null; } @Override protected void parseAttachment(String html) { super.parseAttachment(html.replace("kbps", "")); } @Override public ThreadModel[] readWakabaPage() throws IOException { ThreadModel[] result = super.readWakabaPage(); if (result != null) for (ThreadModel model : result) model.attachmentsCount = -1; return result; } }