/* * Copyright (C) 2014 Hippo Seven * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.hippo.ehviewer.ehclient; import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.AbstractMap.SimpleEntry; import java.util.LinkedList; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.hippo.ehviewer.ListUrls; import com.hippo.ehviewer.data.Comment; import com.hippo.ehviewer.data.NormalPreviewList; import com.hippo.ehviewer.util.Log; public class DetailParser { private static final String OFFENSIVE_STRING = "

(And if you choose to ignore this warning, you lose all rights to complain about it in the future.)

"; private static final String PINING_STRING = "

This gallery is pining for the fjords.

"; public static final int DETAIL = 0x1; public static final int TAG = 0x2; public static final int PREVIEW_INFO = 0x4; public static final int PREVIEW = 0x8; public static final int COMMENT = 0x10; public static final int OFFENSIVE = 0x20; public static final int PINING = 0x40; private static final CommentSort cs = new CommentSort(); private int mMode; public String thumb; public String title; public String title_jpn; public int category; public String uploader; public String posted; public int pages; public String size; public String resized; public String parent; public String visible; public String language; public int people; public float rating; public String firstPage; public int previewPerPage; public int previewSum; public LinkedHashMap>> tags; public NormalPreviewList previewList; public LinkedList comments; public void setMode(int mode) { mMode = mode; } public int parser(String body) { int re = 0; Pattern p; Matcher m; if (body.contains(OFFENSIVE_STRING)) { return OFFENSIVE; } if (body.contains(PINING_STRING)) { return PINING; } // Get detail if ((mMode & DETAIL) != 0) { p = Pattern .compile("
]+/>
" // thumb + "" + "
" + "

([^<>]+)

" // title + "

([^<>]*)

" // title_jpn might be empty string + "
" + ".+" + "
]+><[^<>]*alt=\"([\\w|\\-]+)\"[^<>]*/>
" // category + "
]+>([^<>]+)" // uploader + ".+" + "]*>Posted:]*>([\\w|\\-|\\s|:]+)" // posted + "]*>Images:]*>([\\d]+) @ ([\\w|\\.|\\s]+)" // pages and size + "]*>Resized:]*>([^<>]+)" // resized + "]*>Parent:]*>(?:]*>)?([^<>]+)(?:)?" // parent + "]*>Visible:]*>([^<>]+)" // visible + "]*>Language:]*>([^<>]+)" // language + ".+" + "\\(([\\d|,]+)\\)" // people + "" + "]*>([^<>]+)" // rating + ".+" + "
]*>(?:]*>)?]*href=\"([^<>\"]+)\"[^<>]*>"); // get firstPage m = p.matcher(body); if (m.find()) { re |= DETAIL; thumb = m.group(1); title = m.group(2); title_jpn = m.group(3); category = EhClient.getType(m.group(4)); uploader = m.group(5); posted = m.group(6); pages = Integer.parseInt(m.group(7)); size = m.group(8); resized = m.group(9); parent = m.group(10); visible = m.group(11); language = m.group(12); people = Integer.parseInt(m.group(13).replace(",", "")); Pattern pattern = Pattern.compile("([\\d|\\.]+)"); Matcher matcher = pattern.matcher(m.group(14)); if (matcher.find()) rating = Float.parseFloat(matcher.group(1)); else rating = Float.NaN; firstPage = m.group(15); } } // Get tag if ((mMode & TAG) != 0) { tags = new LinkedHashMap>>(); p = Pattern .compile("]*>([^<>]+):(?:]*>]*>[^<>]*[^<>]*]*>\\d+[^<>]*
)+"); m = p.matcher(body); while (m.find()) { re |= TAG; String groupName = m.group(1); LinkedList> group = getTagGroup(m.group(0)); if (group != null) { tags.put(groupName, group); } } } // Get preview info if ((mMode & PREVIEW_INFO) != 0) { p = Pattern.compile("

Showing ([\\d|,]+) - ([\\d|,]+) of ([\\d|,]+) images

"); m = p.matcher(body); if (m.find()) { re |= PREVIEW_INFO; previewPerPage = Integer.parseInt(m.group(2).replace(",", "")) - Integer.parseInt(m.group(1).replace(",", "")) + 1; int total = Integer.parseInt(m.group(3).replace(",", "")); previewSum = (total + previewPerPage - 1) / previewPerPage; } } // Get preview if ((mMode & PREVIEW) != 0) { p = Pattern .compile("]*class=\"gdtm\"[^<>]*>]*width:(\\d+)[^<>]*height:(\\d+)[^<>]*\\((.+?)\\)[^<>]*-(\\d+)px[^<>]*>]*href=\"(.+?)\"[^<>]*>"); m = p.matcher(body); while (m.find()) { if (previewList == null) { re |= PREVIEW; previewList = new NormalPreviewList(); } previewList.addItem(m.group(3), m.group(4), "0", m.group(1), m.group(2), m.group(5)); } } // Get comment if ((mMode & COMMENT) != 0) { p = Pattern .compile("
Posted on ([^<>]+) by ]+>([^<>]+).*?
(.*?)
"); m = p.matcher(body); comments = new LinkedList(); while (m.find()) { re |= COMMENT; comments.add(new Comment(m.group(1), m.group(2), m.group(3))); } Collections.sort(comments, cs); } return re; } private LinkedList> getTagGroup(String pageContent) { LinkedList> list = new LinkedList>(); Pattern p = Pattern.compile("]*>([^<>]+) \\(]*>([\\d|,]+)\\)"); Matcher m = p.matcher(pageContent); while (m.find()) list.add(new SimpleEntry(m.group(1), Integer.parseInt(m.group(2).replace(",", "")))); if (list.size() == 0) return null; else return list; } static class CommentSort implements Comparator { private int compareNum(String n1, String n2, int median) { int re = 0; for (int i = 0; i < median; i++) { re *= 10; re += n1.charAt(i) - n2.charAt(i); } return re; } private int getMonth(String m) { if (m.equals("January")) return 1; else if (m.equals("February")) return 2; else if (m.equals("March")) return 3; else if (m.equals("April")) return 4; else if (m.equals("May")) return 5; else if (m.equals("June")) return 6; else if (m.equals("July")) return 7; else if (m.equals("August")) return 8; else if (m.equals("September")) return 9; else if (m.equals("October")) return 10; else if (m.equals("November")) return 11; else if (m.equals("December")) return 12; else return 0; } @Override public int compare(Comment c1, Comment c2) { int re = 0; Pattern p = Pattern.compile("(\\d{2}) (\\w+) (\\d{4}), (\\d{2}):(\\d{2})"); Matcher m1 = p.matcher(c1.time); Matcher m2 = p.matcher(c2.time); if (!m1.find() || !m2.find()) return 0; // year re += compareNum(m1.group(3), m2.group(3), 4); re <<= 4; // Month re += getMonth(m1.group(2)) - getMonth(m2.group(2)); re <<= 5; // Day re += compareNum(m1.group(1), m2.group(1), 2); re <<= 5; // Hour re += compareNum(m1.group(4), m2.group(4), 2); re <<= 6; // Minute re += compareNum(m1.group(5), m2.group(5), 2); return re; } } }