Fanfiction, step 1
[fanfix.git] / src / be / nikiroo / fanfix / searchable / Fanfiction.java
1 package be.nikiroo.fanfix.searchable;
2
3 import java.io.IOException;
4 import java.net.URL;
5 import java.util.ArrayList;
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10
11 import org.jsoup.nodes.Document;
12 import org.jsoup.nodes.Element;
13 import org.jsoup.select.Elements;
14
15 import be.nikiroo.fanfix.Instance;
16 import be.nikiroo.fanfix.bundles.StringId;
17 import be.nikiroo.fanfix.data.MetaData;
18 import be.nikiroo.fanfix.supported.SupportType;
19
20 /**
21 * A {@link BasicSearchable} for Fanfiction.NET.
22 *
23 * @author niki
24 */
25 class Fanfiction extends BasicSearchable {
26 /**
27 * Create a new {@link Fanfiction}.
28 *
29 * @param type
30 * {@link SupportType#FANFICTION}
31 */
32 public Fanfiction(SupportType type) {
33 super(type);
34 }
35
36 @Override
37 public List<SearchableTag> getTags() throws IOException {
38 String storiesName = null;
39 String crossoversName = null;
40 Map<String, String> stories = new HashMap<String, String>();
41 Map<String, String> crossovers = new HashMap<String, String>();
42
43 Document mainPage = load("http://fanfiction.net/");
44 Element menu = mainPage.getElementsByClass("dropdown").first();
45 if (menu != null) {
46 Element ul = menu.getElementsByClass("dropdown-menu").first();
47 if (ul != null) {
48 Map<String, String> currentList = null;
49 for (Element li : ul.getElementsByTag("li")) {
50 if (li.hasClass("disabled")) {
51 if (storiesName == null) {
52 storiesName = li.text();
53 currentList = stories;
54 } else {
55 crossoversName = li.text();
56 currentList = crossovers;
57 }
58 } else if (currentList != null) {
59 Element a = li.getElementsByTag("a").first();
60 if (a != null) {
61 currentList.put(a.absUrl("href"), a.text());
62 }
63 }
64 }
65 }
66 }
67
68 List<SearchableTag> tags = new ArrayList<SearchableTag>();
69
70 if (storiesName != null) {
71 SearchableTag tag = new SearchableTag(null, storiesName, true);
72 for (String id : stories.keySet()) {
73 tag.add(new SearchableTag(id, stories.get(id), false));
74 }
75 tags.add(tag);
76 }
77
78 if (crossoversName != null) {
79 SearchableTag tag = new SearchableTag(null, crossoversName, true);
80 for (String id : crossovers.keySet()) {
81 tag.add(new SearchableTag(id, crossovers.get(id), false));
82 }
83 tags.add(tag);
84 }
85
86 return tags;
87 }
88
89 @Override
90 protected void fillTag(SearchableTag tag) throws IOException {
91 if (tag.getId() == null || tag.isComplete()) {
92 return;
93 }
94
95 boolean subtagIsComplete = !tag.getId().contains("/crossovers/");
96
97 Document doc = load(tag.getId());
98 Element list = doc.getElementById("list_output");
99 if (list != null) {
100 Element table = list.getElementsByTag("table").first();
101 if (table != null) {
102 for (Element div : table.getElementsByTag("div")) {
103 Element a = div.getElementsByTag("a").first();
104 Element span = div.getElementsByTag("span").first();
105
106 if (a != null) {
107 SearchableTag subtag = new SearchableTag(
108 a.absUrl("href"), a.text(), subtagIsComplete);
109 tag.add(subtag);
110 if (span != null) {
111 String nr = span.text();
112 if (nr.startsWith("(")) {
113 nr = nr.substring(1);
114 }
115 if (nr.endsWith(")")) {
116 nr = nr.substring(0, nr.length() - 1);
117 }
118 nr = nr.trim();
119
120 long count = 0;
121 try {
122 if (nr.toLowerCase().endsWith("m")) {
123 count = Long.parseLong(nr.substring(0,
124 nr.length() - 1).trim());
125 count *= 1000000;
126 } else if (nr.toLowerCase().endsWith("k")) {
127 count = Long.parseLong(nr.substring(0,
128 nr.length() - 1).trim());
129 count *= 1000;
130 } else {
131 count = Long.parseLong(nr);
132 }
133 } catch (NumberFormatException pe) {
134 }
135
136 subtag.setCount(count);
137 }
138 }
139 }
140 }
141 }
142
143 tag.setComplete(true);
144 }
145
146 @Override
147 public List<MetaData> search(String search) throws IOException {
148 // TODO Auto-generated method stub
149 return null;
150 }
151
152 @Override
153 public List<MetaData> search(SearchableTag tag) throws IOException {
154 List<MetaData> metas = new ArrayList<MetaData>();
155
156 if (tag.getId() != null) {
157 Document doc = load(tag.getId());
158 for (Element story : doc.getElementsByClass("z-list")) {
159 String title = "";
160 String url = "";
161 String coverUrl = "";
162
163 Element stitle = story.getElementsByClass("stitle").first();
164 if (stitle != null) {
165 title = stitle.text();
166 url = stitle.absUrl("href");
167 Element cover = stitle.getElementsByTag("img").first();
168 if (cover != null) {
169 // note: see data-original if needed?
170 coverUrl = cover.absUrl("src");
171 }
172 }
173
174 String author = "";
175
176 Elements as = story.getElementsByTag("a");
177 if (as.size() > 1) {
178 author = as.get(1).text();
179 }
180
181 String resume = "";
182 String tags = "";
183
184 Elements divs = story.getElementsByTag("div");
185 if (divs.size() > 1 && divs.get(1).childNodeSize() > 0) {
186 resume = divs.get(1).text();
187 if (divs.size() > 2) {
188 tags = divs.get(2).text();
189 resume = resume.substring(0,
190 resume.length() - tags.length()).trim();
191 }
192 }
193
194 MetaData meta = new MetaData();
195 meta.setAuthor(author);
196 // meta.setCover(cover); //TODO ?
197 meta.setImageDocument(false);
198 meta.setResume(getSupport().makeChapter(new URL(tag.getId()),
199 0, Instance.getTrans().getString(StringId.DESCRIPTION),
200 resume));
201 meta.setSource(getType().getSourceName());
202 meta.setTags(Arrays.asList(tags.split(" *- *")));
203 meta.setTitle(title);
204 meta.setUrl(url);
205
206 metas.add(meta);
207 }
208 }
209
210 return metas;
211 }
212
213 public static void main(String[] args) throws IOException {
214 Fanfiction f = new Fanfiction(SupportType.FANFICTION);
215
216 SearchableTag cartoons = f.getTags().get(0).getChildren().get(2);
217 f.fillTag(cartoons);
218 SearchableTag mlp = cartoons.getChildren().get(2);
219 System.out.println(mlp);
220
221 SearchableTag ccartoons = f.getTags().get(1).getChildren().get(0);
222 f.fillTag(ccartoons);
223 SearchableTag cmlp = ccartoons.getChildren().get(0);
224 System.out.println(cmlp);
225
226 f.fillTag(cmlp);
227 System.out.println(cmlp);
228
229 List<MetaData> metas = f.search(mlp);
230 System.out.println(metas);
231 }
232 }