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