Merge branch 'master' into subtree
[nikiroo-utils.git] / supported / Fimfiction.java
CommitLineData
08fe2e33
NR
1package be.nikiroo.fanfix.supported;
2
68686a37 3import java.io.IOException;
08fe2e33
NR
4import java.io.InputStream;
5import java.net.MalformedURLException;
6import java.net.URL;
ce297a79 7import java.util.AbstractMap;
08fe2e33
NR
8import java.util.ArrayList;
9import java.util.HashMap;
10import java.util.List;
11import java.util.Map;
12import java.util.Map.Entry;
13import java.util.Scanner;
14
15import be.nikiroo.fanfix.Instance;
68686a37 16import be.nikiroo.fanfix.data.MetaData;
16a81ef7 17import be.nikiroo.utils.Image;
ed08c171 18import be.nikiroo.utils.Progress;
68686a37 19import be.nikiroo.utils.StringUtils;
08fe2e33
NR
20
21/**
22 * Support class for <a href="http://www.fimfiction.net/">FimFiction.net</a>
23 * stories, a website dedicated to My Little Pony.
24 *
25 * @author niki
26 */
0ffa4754 27class Fimfiction extends BasicSupport_Deprecated {
08fe2e33
NR
28 @Override
29 protected boolean isHtml() {
30 return true;
31 }
32
08fe2e33 33 @Override
68686a37
NR
34 protected MetaData getMeta(URL source, InputStream in) throws IOException {
35 MetaData meta = new MetaData();
36
37 meta.setTitle(getTitle(reset(in)));
38 meta.setAuthor(getAuthor(reset(in)));
39 meta.setDate(getDate(reset(in)));
40 meta.setTags(getTags(reset(in)));
2206ef66 41 meta.setUrl(source.toString());
68686a37
NR
42 meta.setUuid(source.toString());
43 meta.setLuid("");
276f95c6 44 meta.setLang("en");
68686a37 45 meta.setSubject("MLP");
68686a37
NR
46 meta.setImageDocument(false);
47 meta.setCover(getCover(reset(in)));
48
49 return meta;
08fe2e33
NR
50 }
51
52 @Override
53 public Map<String, String> getCookies() {
54 Map<String, String> cookies = new HashMap<String, String>();
55 cookies.put("view_mature", "true");
56 return cookies;
57 }
58
68686a37 59 private List<String> getTags(InputStream in) {
08fe2e33
NR
60 List<String> tags = new ArrayList<String>();
61 tags.add("MLP");
62
63 @SuppressWarnings("resource")
64 Scanner scan = new Scanner(in, "UTF-8");
65 scan.useDelimiter("\\n");
c3c79003 66 boolean started = false;
08fe2e33
NR
67 while (scan.hasNext()) {
68 String line = scan.next();
c3c79003
NR
69
70 if (!started) {
71 started = line.contains("\"story_container\"");
72 }
73
74 if (started && line.contains("class=\"tag-")) {
75 if (line.contains("index.php")) {
76 break; // end of *this story* tags
08fe2e33
NR
77 }
78
e1168b3c
NR
79 String keyword = "title=\"";
80 Scanner tagScanner = new Scanner(line);
81 tagScanner.useDelimiter(keyword);
82 if (tagScanner.hasNext()) {
83 tagScanner.next();// Ignore first one
84 }
85 while (tagScanner.hasNext()) {
86 String tag = tagScanner.next();
87 if (tag.contains("\"")) {
88 tag = tag.split("\"")[0];
89 tag = StringUtils.unhtml(tag).trim();
90 if (!tag.isEmpty() && !tags.contains(tag)) {
91 tags.add(tag);
92 }
c3c79003 93 }
08fe2e33 94 }
e1168b3c 95 tagScanner.close();
08fe2e33
NR
96 }
97 }
98
99 return tags;
100 }
101
68686a37 102 private String getTitle(InputStream in) {
08fe2e33
NR
103 String line = getLine(in, " property=\"og:title\"", 0);
104 if (line != null) {
105 int pos = -1;
106 for (int i = 0; i < 3; i++) {
107 pos = line.indexOf('"', pos + 1);
108 }
109
110 if (pos >= 0) {
111 line = line.substring(pos + 1);
112 pos = line.indexOf('"');
113 if (pos >= 0) {
68686a37 114 return StringUtils.unhtml(line.substring(0, pos)).trim();
08fe2e33
NR
115 }
116 }
117 }
118
119 return null;
120 }
121
68686a37 122 private String getAuthor(InputStream in) {
08fe2e33
NR
123 String line = getLine(in, " href=\"/user/", 0);
124 if (line != null) {
125 int pos = line.indexOf('"');
126 if (pos >= 0) {
127 line = line.substring(pos + 1);
128 pos = line.indexOf('"');
129 if (pos >= 0) {
130 line = line.substring(0, pos);
131 pos = line.lastIndexOf('/');
132 if (pos >= 0) {
133 line = line.substring(pos + 1);
134 return line.replace('+', ' ');
135 }
136 }
137 }
138 }
139
140 return null;
141 }
142
68686a37 143 private String getDate(InputStream in) {
08fe2e33
NR
144 String line = getLine(in, "<span class=\"date\">", 0);
145 if (line != null) {
146 int pos = -1;
147 for (int i = 0; i < 3; i++) {
148 pos = line.indexOf('>', pos + 1);
149 }
150
151 if (pos >= 0) {
152 line = line.substring(pos + 1);
153 pos = line.indexOf('<');
154 if (pos >= 0) {
155 return line.substring(0, pos).trim();
156 }
157 }
158 }
159
160 return null;
161 }
162
163 @Override
164 protected String getDesc(URL source, InputStream in) {
165 // the og: meta version is the SHORT resume, this is the LONG resume
83f66cbb 166 return getLine(in, "class=\"description-text bbcode\"", 1);
08fe2e33
NR
167 }
168
16a81ef7 169 private Image getCover(InputStream in) {
08fe2e33 170 // Note: the 'og:image' is the SMALL cover, not the full version
83f66cbb 171 String cover = getLine(in, "class=\"story_container__story_image\"", 1);
08fe2e33
NR
172 if (cover != null) {
173 int pos = cover.indexOf('"');
174 if (pos >= 0) {
175 cover = cover.substring(pos + 1);
176 pos = cover.indexOf('"');
177 if (pos >= 0) {
178 cover = cover.substring(0, pos);
179 }
180 }
181 }
182
333f0e7b 183 return getImage(this, null, cover);
08fe2e33
NR
184 }
185
186 @Override
ed08c171
NR
187 protected List<Entry<String, URL>> getChapters(URL source, InputStream in,
188 Progress pg) {
08fe2e33
NR
189 List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>();
190 @SuppressWarnings("resource")
191 Scanner scan = new Scanner(in, "UTF-8");
192 scan.useDelimiter("\\n");
83f66cbb 193 boolean started = false;
08fe2e33 194 while (scan.hasNext()) {
83f66cbb
NR
195 String line = scan.next().trim();
196
197 if (!started) {
198 started = line.equals("<!--Chapters-->");
199 } else {
200 if (line.equals("</form>")) {
201 break;
202 }
203
e1168b3c
NR
204 if (line.startsWith("<a href=")
205 || line.contains("class=\"chapter-title\"")) {
83f66cbb
NR
206 // Chapter name
207 String name = line;
208 int pos = name.indexOf('>');
08fe2e33 209 if (pos >= 0) {
83f66cbb
NR
210 name = name.substring(pos + 1);
211 pos = name.indexOf('<');
212 if (pos >= 0) {
213 name = name.substring(0, pos);
214 }
08fe2e33 215 }
83f66cbb
NR
216 // Chapter content
217 pos = line.indexOf('/');
08fe2e33 218 if (pos >= 0) {
83f66cbb
NR
219 line = line.substring(pos); // we take the /, not +1
220 pos = line.indexOf('"');
221 if (pos >= 0) {
222 line = line.substring(0, pos);
223 }
08fe2e33 224 }
08fe2e33 225
83f66cbb 226 try {
ce297a79
NR
227 urls.add(new AbstractMap.SimpleEntry<String, URL>(name,
228 new URL("http://www.fimfiction.net" + line)));
83f66cbb 229 } catch (MalformedURLException e) {
d66deb8d 230 Instance.getInstance().getTraceHandler().error(e);
83f66cbb 231 }
08fe2e33
NR
232 }
233 }
234 }
235
236 return urls;
237 }
238
239 @Override
ed08c171
NR
240 protected String getChapterContent(URL source, InputStream in, int number,
241 Progress pg) {
83f66cbb 242 return getLine(in, "<div class=\"bbcode\">", 1);
08fe2e33
NR
243 }
244
245 @Override
246 protected boolean supports(URL url) {
247 return "fimfiction.net".equals(url.getHost())
248 || "www.fimfiction.net".equals(url.getHost());
249 }
250}