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 be
.nikiroo
.fanfix
.Instance
;
15 import be
.nikiroo
.fanfix
.data
.MetaData
;
16 import be
.nikiroo
.utils
.IOUtils
;
17 import be
.nikiroo
.utils
.StringUtils
;
19 class MangaFox
extends BasicSupport
{
21 protected boolean isHtml() {
26 public String
getSourceName() {
31 protected MetaData
getMeta(URL source
, InputStream in
) throws IOException
{
32 MetaData meta
= new MetaData();
34 meta
.setTitle(getTitle(reset(in
)));
35 meta
.setAuthor(getAuthor(reset(in
)));
36 meta
.setDate(getDate(reset(in
)));
37 meta
.setTags(getTags(reset(in
)));
38 meta
.setSource(getSourceName());
39 meta
.setUrl(source
.toString());
40 meta
.setPublisher(getSourceName());
41 meta
.setUuid(source
.toString());
44 meta
.setSubject("manga");
45 meta
.setType(getType().toString());
46 meta
.setImageDocument(true);
47 meta
.setCover(getCover(reset(in
)));
52 private List
<String
> getTags(InputStream in
) {
53 List
<String
> tags
= new ArrayList
<String
>();
55 String line
= getLine(in
, "/genres/", 0);
57 line
= StringUtils
.unhtml(line
);
58 String
[] tab
= line
.split(",");
60 for (String tag
: tab
) {
69 private String
getTitle(InputStream in
) {
70 String line
= getLine(in
, " property=\"og:title\"", 0);
73 for (int i
= 0; i
< 3; i
++) {
74 pos
= line
.indexOf('"', pos
+ 1);
78 line
= line
.substring(pos
+ 1);
79 pos
= line
.indexOf('"');
81 return line
.substring(0, pos
);
89 private String
getAuthor(InputStream in
) {
90 List
<String
> authors
= new ArrayList
<String
>();
92 String line
= getLine(in
, "/author/", 0, false);
94 for (String ln
: StringUtils
.unhtml(line
).split(",")) {
95 if (ln
!= null && !ln
.trim().isEmpty()
96 && !authors
.contains(ln
.trim())) {
97 authors
.add(ln
.trim());
104 } catch (IOException e
) {
108 line
= getLine(in
, "/artist/", 0, false);
110 for (String ln
: StringUtils
.unhtml(line
).split(",")) {
111 if (ln
!= null && !ln
.trim().isEmpty()
112 && !authors
.contains(ln
.trim())) {
113 authors
.add(ln
.trim());
118 if (authors
.isEmpty()) {
121 StringBuilder builder
= new StringBuilder();
122 for (String author
: authors
) {
123 if (builder
.length() > 0) {
124 builder
.append(", ");
127 builder
.append(author
);
130 return builder
.toString();
134 private String
getDate(InputStream in
) {
135 String line
= getLine(in
, "/released/", 0);
137 line
= StringUtils
.unhtml(line
);
145 protected String
getDesc(URL source
, InputStream in
) {
146 String line
= getLine(in
, " property=\"og:description\"", 0);
149 for (int i
= 0; i
< 3; i
++) {
150 pos
= line
.indexOf('"', pos
+ 1);
154 line
= line
.substring(pos
+ 1);
155 pos
= line
.indexOf('"');
157 return line
.substring(0, pos
);
165 private BufferedImage
getCover(InputStream in
) {
166 String line
= getLine(in
, " property=\"og:image\"", 0);
170 for (int i
= 0; i
< 3; i
++) {
171 pos
= line
.indexOf('"', pos
+ 1);
175 line
= line
.substring(pos
+ 1);
176 pos
= line
.indexOf('"');
178 cover
= line
.substring(0, pos
);
186 coverIn
= openEx(cover
);
188 return IOUtils
.toImage(coverIn
);
192 } catch (IOException e
) {
200 protected List
<Entry
<String
, URL
>> getChapters(URL source
, InputStream in
) {
201 List
<Entry
<String
, URL
>> urls
= new ArrayList
<Entry
<String
, URL
>>();
203 String volumeAt
= "<h3 class=\"volume\">";
204 String linkAt
= "href=\"http://mangafox.me/";
205 String endAt
= "<script type=\"text/javascript\">";
207 boolean started
= false;
209 @SuppressWarnings("resource")
210 Scanner scan
= new Scanner(in
, "UTF-8");
211 scan
.useDelimiter("\\n");
212 while (scan
.hasNext()) {
213 String line
= scan
.next();
215 if (started
&& line
.contains(endAt
)) {
217 } else if (!started
&& line
.contains(volumeAt
)) {
221 if (started
&& line
.contains(linkAt
)) {
222 // Chapter content url
224 int pos
= line
.indexOf("href=\"");
226 line
= line
.substring(pos
+ "href=\"".length());
227 pos
= line
.indexOf('\"');
229 url
= line
.substring(0, pos
);
235 if (scan
.hasNext()) {
236 name
= StringUtils
.unhtml(scan
.next()).trim();
237 // Remove the "new" tag if present
238 if (name
.endsWith("new")) {
239 name
= name
.substring(0, name
.length() - 3).trim();
243 // to help with the retry and the originalUrl
247 final String key
= name
;
248 final URL value
= new URL(url
);
249 urls
.add(new Entry
<String
, URL
>() {
250 public URL
setValue(URL value
) {
254 public String
getKey() {
258 public URL
getValue() {
262 } catch (MalformedURLException e
) {
268 // the chapters are in reversed order
269 Collections
.reverse(urls
);
275 protected String
getChapterContent(URL source
, InputStream in
, int number
) {
276 StringBuilder builder
= new StringBuilder();
277 String base
= getCurrentReferer().toString();
278 int pos
= base
.lastIndexOf('/');
279 base
= base
.substring(0, pos
+ 1); // including the '/' at the end
281 boolean close
= false;
283 String linkNextLine
= getLine(in
, "return enlarge()", 0);
286 } catch (IOException e
) {
290 String linkImageLine
= getLine(in
, "return enlarge()", 1);
291 String linkNext
= null;
292 String linkImage
= null;
293 pos
= linkNextLine
.indexOf("href=\"");
295 linkNextLine
= linkNextLine
.substring(pos
+ "href=\"".length());
296 pos
= linkNextLine
.indexOf('\"');
298 linkNext
= linkNextLine
.substring(0, pos
);
301 pos
= linkImageLine
.indexOf("src=\"");
303 linkImageLine
= linkImageLine
304 .substring(pos
+ "src=\"".length());
305 pos
= linkImageLine
.indexOf('\"');
307 linkImage
= linkImageLine
.substring(0, pos
);
311 if (linkImage
!= null) {
313 // to help with the retry and the originalUrl, part 1
314 builder
.append(withoutQuery(linkImage
));
315 builder
.append("]\n");
318 // to help with the retry and the originalUrl, part 2
324 } catch (IOException e
) {
330 if (linkNext
!= null && !"javascript:void(0);".equals(linkNext
)) {
333 url
= new URL(base
+ linkNext
);
334 in
= openEx(base
+ linkNext
);
335 setCurrentReferer(url
);
336 } catch (IOException e
) {
337 Instance
.syserr(new IOException(
338 "Cannot get the next manga page which is: "
346 setCurrentReferer(source
);
347 return builder
.toString();
351 protected boolean supports(URL url
) {
352 return "mangafox.me".equals(url
.getHost())
353 || "www.mangafox.me".equals(url
.getHost());
357 * Refresh the {@link URL} by calling {@link MangaFox#openEx(String)}.
362 * @return TRUE if it was refreshed
364 private boolean refresh(String url
) {
368 } catch (Exception e
) {
374 * Open the URL through the cache, but: retry a second time after 100ms if
375 * it fails, remove the query part of the {@link URL} before saving it to
376 * the cache (so it can be recalled later).
381 * @return the resource
383 * @throws IOException
384 * in case of I/O error
386 private InputStream
openEx(String url
) throws IOException
{
388 return Instance
.getCache().open(new URL(url
), this, true,
390 } catch (Exception e
) {
394 } catch (InterruptedException ee
) {
397 return Instance
.getCache().open(new URL(url
), this, true,
403 * Return the same input {@link URL} but without the query part.
406 * the inpiut {@link URL} as a {@link String}
408 * @return the input {@link URL} without query
410 private URL
withoutQuery(String url
) {
413 // Remove the query from o (originalUrl), so it can be cached
416 o
= new URL(o
.getProtocol() + "://" + o
.getHost() + o
.getPath());
419 } catch (MalformedURLException e
) {