Merge branch 'master' into subtree
[nikiroo-utils.git] / supported / MangaHub.java
1 package be.nikiroo.fanfix.supported;
2
3 import java.io.IOException;
4 import java.net.HttpURLConnection;
5 import java.net.MalformedURLException;
6 import java.net.URL;
7 import java.util.AbstractMap;
8 import java.util.ArrayList;
9 import java.util.Collections;
10 import java.util.List;
11 import java.util.Map.Entry;
12
13 import org.jsoup.nodes.Element;
14
15 import be.nikiroo.fanfix.Instance;
16 import be.nikiroo.fanfix.bundles.Config;
17 import be.nikiroo.fanfix.data.MetaData;
18 import be.nikiroo.utils.Image;
19 import be.nikiroo.utils.Progress;
20 import be.nikiroo.utils.StringUtils;
21
22 /**
23 * Support class for <a href="https://mangahub.io/">MangaHub</a>, a website
24 * dedicated to Manga.
25 *
26 * @author niki
27 */
28 class MangaHub extends BasicSupport {
29 @Override
30 protected boolean isHtml() {
31 return true;
32 }
33
34 @Override
35 protected MetaData getMeta() throws IOException {
36 MetaData meta = new MetaData();
37
38 meta.setTitle(getTitle());
39 meta.setDate("");
40 meta.setAuthor(getAuthor());
41 meta.setTags(getTags());
42 meta.setSource(getType().getSourceName());
43 meta.setUrl(getSource().toString());
44 meta.setPublisher(getType().getSourceName());
45 meta.setUuid(getSource().toString());
46 meta.setLuid("");
47 meta.setLang("en");
48 meta.setSubject("manga");
49 meta.setType(getType().toString());
50 meta.setImageDocument(true);
51 meta.setCover(getCover());
52
53 return meta;
54 }
55
56 private String getTitle() {
57 Element doc = getSourceNode();
58
59 Element el = doc.getElementsByTag("h1").first();
60 if (el != null) {
61 return StringUtils.unhtml(el.text()).trim();
62 }
63
64 return null;
65 }
66
67 private String getAuthor() {
68 String author = "";
69
70 Element el = getSourceNode().select("h1+div span:not([class])").first();
71 if (el != null)
72 author = StringUtils.unhtml(el.text()).trim();
73 return author;
74 }
75
76 private List<String> getTags() {
77 return getListA("genre-label");
78 }
79
80 private List<String> getListA(String uniqueClass) {
81 List<String> list = new ArrayList<String>();
82
83 Element doc = getSourceNode();
84 Element el = doc.getElementsByClass(uniqueClass).first();
85 if (el != null) {
86 for (Element valueA : el.getElementsByTag("a")) {
87 list.add(StringUtils.unhtml(valueA.text()).trim());
88 }
89 }
90
91 return list;
92 }
93
94 @Override
95 protected String getDesc() {
96 Element doc = getSourceNode();
97 Element title = doc.getElementsByClass("fullcontent").first();
98 if (title != null) {
99 return StringUtils.unhtml(title.text()).trim();
100 }
101
102 return null;
103 }
104
105 private Image getCover() {
106 Element doc = getSourceNode();
107 Element cover = doc.getElementsByClass("manga-thumb").first();
108 if (cover != null) {
109 try {
110 return bsImages.getImage(this, new URL(cover.absUrl("src")));
111 } catch (MalformedURLException e) {
112 Instance.getInstance().getTraceHandler().error(e);
113 }
114 }
115
116 return null;
117 }
118
119 @Override
120 protected List<Entry<String, URL>> getChapters(Progress pg) {
121 List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>();
122
123 Element doc = getSourceNode();
124 for (Element el : doc.getElementsByClass("list-group-item")) {
125 Element urlEl = el.getElementsByTag("a").first();
126 if (urlEl == null)
127 continue;
128
129 String url = urlEl.absUrl("href");
130
131 String title = "";
132 el = el.getElementsByClass("text-secondary").first();
133 if (el != null) {
134 title = StringUtils.unhtml(el.text()).trim();
135 }
136
137 try {
138 urls.add(new AbstractMap.SimpleEntry<String, URL>(title, new URL(url)));
139 } catch (Exception e) {
140 Instance.getInstance().getTraceHandler().error(e);
141 }
142 }
143
144 // by default, the chapters are in reversed order
145 Collections.reverse(urls);
146
147 return urls;
148 }
149
150 @Override
151 protected String getChapterContent(URL chapUrl, int number, Progress pg) throws IOException {
152 if (pg == null) {
153 pg = new Progress();
154 }
155
156 // 1. Get the title and chapter url part
157 String path = chapUrl.getPath();
158 if (path.endsWith("/")) {
159 path = path.substring(0, path.length() - "/".length());
160 }
161 String tab[] = path.split("/");
162 String chap = tab[tab.length - 1];
163 String title = tab[tab.length - 2];
164
165 if (chap.startsWith("chapter-")) {
166 chap = chap.substring("chapter-".length());
167 }
168
169 // 2. generate an image base
170 String base = "https://img.mghubcdn.com/file/imghub/" + title + "/" + chap + "/";
171
172 // 3. add each chapter
173 StringBuilder builder = new StringBuilder();
174
175 int i = 1;
176 String url = base + i + ".jpg";
177 while (getHttpStatus(new URL(url)) != 404) {
178 builder.append("[");
179 builder.append(url);
180 builder.append("]<br/>");
181
182 i++;
183 url = base + i + ".jpg";
184 }
185
186 return builder.toString();
187 }
188
189 // HTTP response code, or -1 if other error
190 // TODO: move that to Downloader?
191 private int getHttpStatus(URL url) {
192 try {
193 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
194 try {
195 conn.setRequestMethod("HEAD");
196 conn.setRequestProperty("User-Agent", Instance.getInstance().getConfig().getString(Config.NETWORK_USER_AGENT));
197 conn.setRequestProperty("Accept-Encoding", "gzip");
198 conn.setRequestProperty("Accept", "*/*");
199 conn.setRequestProperty("Charset", "utf-8");
200
201 return conn.getResponseCode();
202 } finally {
203 conn.disconnect();
204 }
205 } catch (Exception e) {
206 return -1;
207 }
208 }
209
210 @Override
211 protected boolean supports(URL url) {
212 return "mangahub.io".equals(url.getHost()) || "www.mangahub.io".equals(url.getHost());
213 }
214 }