1 package be
.nikiroo
.fanfix
.supported
;
3 import java
.awt
.image
.BufferedImage
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
6 import java
.net
.MalformedURLException
;
8 import java
.util
.ArrayList
;
9 import java
.util
.Collections
;
10 import java
.util
.List
;
11 import java
.util
.Map
.Entry
;
12 import java
.util
.Scanner
;
14 import javax
.imageio
.ImageIO
;
16 import be
.nikiroo
.fanfix
.Instance
;
17 import be
.nikiroo
.fanfix
.data
.MetaData
;
18 import be
.nikiroo
.utils
.StringUtils
;
20 class MangaFox
extends BasicSupport
{
22 protected boolean isHtml() {
27 public String
getSourceName() {
32 protected MetaData
getMeta(URL source
, InputStream in
) throws IOException
{
33 MetaData meta
= new MetaData();
35 meta
.setTitle(getTitle(reset(in
)));
36 meta
.setAuthor(getAuthor(reset(in
)));
37 meta
.setDate(getDate(reset(in
)));
38 meta
.setTags(getTags(reset(in
)));
39 meta
.setSource(getSourceName());
40 meta
.setUrl(source
.toString());
41 meta
.setPublisher(getSourceName());
42 meta
.setUuid(source
.toString());
45 meta
.setSubject("manga");
46 meta
.setType(getType().toString());
47 meta
.setImageDocument(true);
48 meta
.setCover(getCover(reset(in
)));
53 private List
<String
> getTags(InputStream in
) {
54 List
<String
> tags
= new ArrayList
<String
>();
56 String line
= getLine(in
, "/genres/", 0);
58 line
= StringUtils
.unhtml(line
);
59 String
[] tab
= line
.split(",");
61 for (String tag
: tab
) {
70 private String
getTitle(InputStream in
) {
71 String line
= getLine(in
, " property=\"og:title\"", 0);
74 for (int i
= 0; i
< 3; i
++) {
75 pos
= line
.indexOf('"', pos
+ 1);
79 line
= line
.substring(pos
+ 1);
80 pos
= line
.indexOf('"');
82 return line
.substring(0, pos
);
90 private String
getAuthor(InputStream in
) {
91 List
<String
> authors
= new ArrayList
<String
>();
93 String line
= getLine(in
, "/author/", 0, false);
95 for (String ln
: StringUtils
.unhtml(line
).split(",")) {
96 if (ln
!= null && !ln
.trim().isEmpty()
97 && !authors
.contains(ln
.trim())) {
98 authors
.add(ln
.trim());
105 } catch (IOException e
) {
109 line
= getLine(in
, "/artist/", 0, false);
111 for (String ln
: StringUtils
.unhtml(line
).split(",")) {
112 if (ln
!= null && !ln
.trim().isEmpty()
113 && !authors
.contains(ln
.trim())) {
114 authors
.add(ln
.trim());
119 if (authors
.isEmpty()) {
122 StringBuilder builder
= new StringBuilder();
123 for (String author
: authors
) {
124 if (builder
.length() > 0) {
125 builder
.append(", ");
128 builder
.append(author
);
131 return builder
.toString();
135 private String
getDate(InputStream in
) {
136 String line
= getLine(in
, "/released/", 0);
138 line
= StringUtils
.unhtml(line
);
146 protected String
getDesc(URL source
, InputStream in
) {
147 String line
= getLine(in
, " property=\"og:description\"", 0);
150 for (int i
= 0; i
< 3; i
++) {
151 pos
= line
.indexOf('"', pos
+ 1);
155 line
= line
.substring(pos
+ 1);
156 pos
= line
.indexOf('"');
158 return line
.substring(0, pos
);
166 private BufferedImage
getCover(InputStream in
) {
167 String line
= getLine(in
, " property=\"og:image\"", 0);
171 for (int i
= 0; i
< 3; i
++) {
172 pos
= line
.indexOf('"', pos
+ 1);
176 line
= line
.substring(pos
+ 1);
177 pos
= line
.indexOf('"');
179 cover
= line
.substring(0, pos
);
187 coverIn
= openEx(cover
);
189 return ImageIO
.read(coverIn
);
193 } catch (IOException e
) {
201 protected List
<Entry
<String
, URL
>> getChapters(URL source
, InputStream in
) {
202 List
<Entry
<String
, URL
>> urls
= new ArrayList
<Entry
<String
, URL
>>();
204 String volumeAt
= "<h3 class=\"volume\">";
205 String linkAt
= "href=\"http://mangafox.me/";
206 String endAt
= "<script type=\"text/javascript\">";
208 boolean started
= false;
210 @SuppressWarnings("resource")
211 Scanner scan
= new Scanner(in
, "UTF-8");
212 scan
.useDelimiter("\\n");
213 while (scan
.hasNext()) {
214 String line
= scan
.next();
216 if (started
&& line
.contains(endAt
)) {
218 } else if (!started
&& line
.contains(volumeAt
)) {
222 if (started
&& line
.contains(linkAt
)) {
223 // Chapter content url
225 int pos
= line
.indexOf("href=\"");
227 line
= line
.substring(pos
+ "href=\"".length());
228 pos
= line
.indexOf('\"');
230 url
= line
.substring(0, pos
);
236 if (scan
.hasNext()) {
237 name
= StringUtils
.unhtml(scan
.next()).trim();
238 // Remove the "new" tag if present
239 if (name
.endsWith("new")) {
240 name
= name
.substring(0, name
.length() - 3).trim();
244 // to help with the retry and the originalUrl
248 final String key
= name
;
249 final URL value
= new URL(url
);
250 urls
.add(new Entry
<String
, URL
>() {
251 public URL
setValue(URL value
) {
255 public String
getKey() {
259 public URL
getValue() {
263 } catch (MalformedURLException e
) {
269 // the chapters are in reversed order
270 Collections
.reverse(urls
);
276 protected String
getChapterContent(URL source
, InputStream in
, int number
) {
277 StringBuilder builder
= new StringBuilder();
278 String base
= getCurrentReferer().toString();
279 int pos
= base
.lastIndexOf('/');
280 base
= base
.substring(0, pos
+ 1); // including the '/' at the end
282 boolean close
= false;
284 String linkNextLine
= getLine(in
, "return enlarge()", 0);
287 } catch (IOException e
) {
291 String linkImageLine
= getLine(in
, "return enlarge()", 1);
292 String linkNext
= null;
293 String linkImage
= null;
294 pos
= linkNextLine
.indexOf("href=\"");
296 linkNextLine
= linkNextLine
.substring(pos
+ "href=\"".length());
297 pos
= linkNextLine
.indexOf('\"');
299 linkNext
= linkNextLine
.substring(0, pos
);
302 pos
= linkImageLine
.indexOf("src=\"");
304 linkImageLine
= linkImageLine
305 .substring(pos
+ "src=\"".length());
306 pos
= linkImageLine
.indexOf('\"');
308 linkImage
= linkImageLine
.substring(0, pos
);
312 if (linkImage
!= null) {
314 // to help with the retry and the originalUrl, part 1
315 builder
.append(withoutQuery(linkImage
));
316 builder
.append("]\n");
319 // to help with the retry and the originalUrl, part 2
325 } catch (IOException e
) {
331 if (linkNext
!= null && !"javascript:void(0);".equals(linkNext
)) {
334 url
= new URL(base
+ linkNext
);
335 in
= openEx(base
+ linkNext
);
336 setCurrentReferer(url
);
337 } catch (IOException e
) {
338 Instance
.syserr(new IOException(
339 "Cannot get the next manga page which is: "
347 setCurrentReferer(source
);
348 return builder
.toString();
352 protected boolean supports(URL url
) {
353 return "mangafox.me".equals(url
.getHost())
354 || "www.mangafox.me".equals(url
.getHost());
358 * Refresh the {@link URL} by calling {@link MangaFox#openEx(String)}.
363 * @return TRUE if it was refreshed
365 private boolean refresh(String url
) {
369 } catch (Exception e
) {
375 * Open the URL through the cache, but: retry a second time after 100ms if
376 * it fails, remove the query part of the {@link URL} before saving it to
377 * the cache (so it can be recalled later).
382 * @return the resource
384 * @throws IOException
385 * in case of I/O error
387 private InputStream
openEx(String url
) throws IOException
{
389 return Instance
.getCache().open(new URL(url
), this, true,
391 } catch (Exception e
) {
395 } catch (InterruptedException ee
) {
398 return Instance
.getCache().open(new URL(url
), this, true,
404 * Return the same input {@link URL} but without the query part.
407 * the inpiut {@link URL} as a {@link String}
409 * @return the input {@link URL} without query
411 private URL
withoutQuery(String url
) {
414 // Remove the query from o (originalUrl), so it can be cached
417 o
= new URL(o
.getProtocol() + "://" + o
.getHost() + o
.getPath());
420 } catch (MalformedURLException e
) {