| 1 | package be.nikiroo.fanfix.supported; |
| 2 | |
| 3 | import java.io.IOException; |
| 4 | import java.io.InputStream; |
| 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.helper.DataUtil; |
| 14 | import org.jsoup.nodes.Element; |
| 15 | import org.jsoup.select.Elements; |
| 16 | |
| 17 | import be.nikiroo.fanfix.Instance; |
| 18 | import be.nikiroo.fanfix.data.MetaData; |
| 19 | import be.nikiroo.utils.Image; |
| 20 | import be.nikiroo.utils.Progress; |
| 21 | import be.nikiroo.utils.StringUtils; |
| 22 | |
| 23 | class MangaLel extends BasicSupport { |
| 24 | @Override |
| 25 | protected boolean isHtml() { |
| 26 | return true; |
| 27 | } |
| 28 | |
| 29 | @Override |
| 30 | public String getSourceName() { |
| 31 | return "MangaLel.com"; |
| 32 | } |
| 33 | |
| 34 | @Override |
| 35 | protected MetaData getMeta() throws IOException { |
| 36 | MetaData meta = new MetaData(); |
| 37 | |
| 38 | String[] authorDateTag = getAuthorDateTag(); |
| 39 | |
| 40 | meta.setTitle(getTitle()); |
| 41 | meta.setAuthor(authorDateTag[0]); |
| 42 | meta.setDate(authorDateTag[1]); |
| 43 | meta.setTags(explode(authorDateTag[2])); |
| 44 | meta.setSource(getSourceName()); |
| 45 | meta.setUrl(getSource().toString()); |
| 46 | meta.setPublisher(getSourceName()); |
| 47 | meta.setUuid(getSource().toString()); |
| 48 | meta.setLuid(""); |
| 49 | meta.setLang("fr"); |
| 50 | meta.setSubject("manga"); |
| 51 | meta.setType(getType().toString()); |
| 52 | meta.setImageDocument(true); |
| 53 | meta.setCover(getCover()); |
| 54 | |
| 55 | return meta; |
| 56 | } |
| 57 | |
| 58 | private String getTitle() { |
| 59 | Element doc = getSourceNode(); |
| 60 | Element h2 = doc.getElementsByClass("widget-title").first(); |
| 61 | if (h2 != null) { |
| 62 | return StringUtils.unhtml(h2.text()).trim(); |
| 63 | } |
| 64 | |
| 65 | return null; |
| 66 | } |
| 67 | |
| 68 | // 0 = author |
| 69 | // 1 = date |
| 70 | // 2 = tags |
| 71 | private String[] getAuthorDateTag() { |
| 72 | String[] tab = new String[3]; |
| 73 | |
| 74 | Element doc = getSourceNode(); |
| 75 | Element tabEls = doc.getElementsByClass("dl-horizontal").first(); |
| 76 | int prevOk = 0; |
| 77 | for (Element tabEl : tabEls.children()) { |
| 78 | String txt = tabEl.text().trim(); |
| 79 | if (prevOk > 0) { |
| 80 | if (tab[prevOk - 1] == null) { |
| 81 | tab[prevOk - 1] = ""; |
| 82 | } else { |
| 83 | tab[prevOk - 1] += ", "; |
| 84 | } |
| 85 | |
| 86 | tab[prevOk - 1] += txt; |
| 87 | prevOk = 0; |
| 88 | } else { |
| 89 | if (txt.equals("Auteur(s)") || txt.equals("Artist(s)")) { |
| 90 | prevOk = 1; |
| 91 | } else if (txt.equals("Date de sortie")) { |
| 92 | prevOk = 2; |
| 93 | } else if (txt.equals("Type") || txt.equals("Catégories")) { |
| 94 | prevOk = 3; |
| 95 | } else { |
| 96 | prevOk = 0; |
| 97 | } |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | for (int i = 0; i < 3; i++) { |
| 102 | String list = ""; |
| 103 | for (String item : explode(tab[i])) { |
| 104 | if (!list.isEmpty()) { |
| 105 | list = list + ", "; |
| 106 | } |
| 107 | list += item; |
| 108 | } |
| 109 | tab[i] = list; |
| 110 | } |
| 111 | |
| 112 | return tab; |
| 113 | } |
| 114 | |
| 115 | @Override |
| 116 | protected String getDesc() { |
| 117 | String desc = null; |
| 118 | |
| 119 | Element doc = getSourceNode(); |
| 120 | Element title = doc.getElementsByClass("well").first(); |
| 121 | if (title != null) { |
| 122 | desc = StringUtils.unhtml(title.text()).trim(); |
| 123 | if (desc.startsWith("Résumé")) { |
| 124 | desc = desc.substring("Résumé".length()).trim(); |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | return desc; |
| 129 | } |
| 130 | |
| 131 | private Image getCover() { |
| 132 | Element doc = getSourceNode(); |
| 133 | Element cover = doc.getElementsByClass("img-responsive").first(); |
| 134 | |
| 135 | if (cover != null) { |
| 136 | String coverUrl = cover.absUrl("src"); |
| 137 | |
| 138 | InputStream coverIn; |
| 139 | try { |
| 140 | coverIn = Instance.getCache().open(new URL(coverUrl), this, |
| 141 | true); |
| 142 | try { |
| 143 | return new Image(coverIn); |
| 144 | } finally { |
| 145 | coverIn.close(); |
| 146 | } |
| 147 | } catch (IOException e) { |
| 148 | Instance.getTraceHandler().error(e); |
| 149 | } |
| 150 | } |
| 151 | |
| 152 | return null; |
| 153 | } |
| 154 | |
| 155 | @Override |
| 156 | protected List<Entry<String, URL>> getChapters(Progress pg) { |
| 157 | List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>(); |
| 158 | |
| 159 | int i = 0; |
| 160 | Element doc = getSourceNode(); |
| 161 | Elements chapEls = doc.getElementsByClass("chapters").first() |
| 162 | .getElementsByTag("li"); |
| 163 | for (Element chapEl : chapEls) { |
| 164 | Element titleEl = chapEl.getElementsByTag("h5").first(); |
| 165 | String title = StringUtils.unhtml(titleEl.text()).trim(); |
| 166 | |
| 167 | // because Atril does not support strange file names |
| 168 | title = Integer.toString(chapEls.size() - i); |
| 169 | |
| 170 | Element linkEl = chapEl.getElementsByTag("h5").first() |
| 171 | .getElementsByTag("a").first(); |
| 172 | String link = linkEl.absUrl("href"); |
| 173 | |
| 174 | try { |
| 175 | urls.add(new AbstractMap.SimpleEntry<String, URL>(title, |
| 176 | new URL(link))); |
| 177 | } catch (MalformedURLException e) { |
| 178 | Instance.getTraceHandler().error(e); |
| 179 | } |
| 180 | |
| 181 | i++; |
| 182 | } |
| 183 | |
| 184 | Collections.reverse(urls); |
| 185 | return urls; |
| 186 | } |
| 187 | |
| 188 | @Override |
| 189 | protected String getChapterContent(URL chapUrl, int number, Progress pg) |
| 190 | throws IOException { |
| 191 | if (pg == null) { |
| 192 | pg = new Progress(); |
| 193 | } |
| 194 | |
| 195 | StringBuilder builder = new StringBuilder(); |
| 196 | |
| 197 | InputStream in = Instance.getCache().open(chapUrl, this, false); |
| 198 | try { |
| 199 | Element pageDoc = DataUtil.load(in, "UTF-8", chapUrl.toString()); |
| 200 | Elements linkEls = pageDoc.getElementsByClass("img-responsive"); |
| 201 | for (Element linkEl : linkEls) { |
| 202 | if (linkEl.hasAttr("data-src")) { |
| 203 | builder.append("["); |
| 204 | builder.append(linkEl.absUrl("data-src").trim()); |
| 205 | builder.append("]<br/>"); |
| 206 | } |
| 207 | } |
| 208 | |
| 209 | } finally { |
| 210 | in.close(); |
| 211 | } |
| 212 | |
| 213 | return builder.toString(); |
| 214 | } |
| 215 | |
| 216 | /** |
| 217 | * Explode an HTML comma-separated list of values into a non-duplicate text |
| 218 | * {@link List} . |
| 219 | * |
| 220 | * @param values |
| 221 | * the comma-separated values in HTML format |
| 222 | * |
| 223 | * @return the full list with no duplicate in text format |
| 224 | */ |
| 225 | private List<String> explode(String values) { |
| 226 | List<String> list = new ArrayList<String>(); |
| 227 | if (values != null && !values.isEmpty()) { |
| 228 | for (String auth : values.split(",")) { |
| 229 | String a = StringUtils.unhtml(auth).trim(); |
| 230 | if (!a.isEmpty() && !list.contains(a.trim())) { |
| 231 | list.add(a); |
| 232 | } |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | return list; |
| 237 | } |
| 238 | |
| 239 | @Override |
| 240 | protected boolean supports(URL url) { |
| 241 | return "manga-lel.com".equals(url.getHost()) |
| 242 | || "www.manga-lel.com".equals(url.getHost()); |
| 243 | } |
| 244 | } |