1 package be
.nikiroo
.fanfix
.searchable
;
3 import java
.io
.IOException
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Arrays
;
7 import java
.util
.HashMap
;
11 import org
.jsoup
.nodes
.Document
;
12 import org
.jsoup
.nodes
.Element
;
13 import org
.jsoup
.select
.Elements
;
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
;
21 * A {@link BasicSearchable} for Fanfiction.NET.
25 class Fanfiction
extends BasicSearchable
{
27 * Create a new {@link Fanfiction}.
30 * {@link SupportType#FANFICTION}
32 public Fanfiction(SupportType type
) {
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
>();
43 Document mainPage
= load("http://fanfiction.net/");
44 Element menu
= mainPage
.getElementsByClass("dropdown").first();
46 Element ul
= menu
.getElementsByClass("dropdown-menu").first();
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
;
55 crossoversName
= li
.text();
56 currentList
= crossovers
;
58 } else if (currentList
!= null) {
59 Element a
= li
.getElementsByTag("a").first();
61 currentList
.put(a
.absUrl("href"), a
.text());
68 List
<SearchableTag
> tags
= new ArrayList
<SearchableTag
>();
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));
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));
90 protected void fillTag(SearchableTag tag
) throws IOException
{
91 if (tag
.getId() == null || tag
.isComplete()) {
95 boolean subtagIsComplete
= !tag
.getId().contains("/crossovers/");
97 Document doc
= load(tag
.getId());
98 Element list
= doc
.getElementById("list_output");
100 Element table
= list
.getElementsByTag("table").first();
102 for (Element div
: table
.getElementsByTag("div")) {
103 Element a
= div
.getElementsByTag("a").first();
104 Element span
= div
.getElementsByTag("span").first();
107 SearchableTag subtag
= new SearchableTag(
108 a
.absUrl("href"), a
.text(), subtagIsComplete
);
111 String nr
= span
.text();
112 if (nr
.startsWith("(")) {
113 nr
= nr
.substring(1);
115 if (nr
.endsWith(")")) {
116 nr
= nr
.substring(0, nr
.length() - 1);
122 if (nr
.toLowerCase().endsWith("m")) {
123 count
= Long
.parseLong(nr
.substring(0,
124 nr
.length() - 1).trim());
126 } else if (nr
.toLowerCase().endsWith("k")) {
127 count
= Long
.parseLong(nr
.substring(0,
128 nr
.length() - 1).trim());
131 count
= Long
.parseLong(nr
);
133 } catch (NumberFormatException pe
) {
136 subtag
.setCount(count
);
143 tag
.setComplete(true);
147 public List
<MetaData
> search(String search
) throws IOException
{
148 // TODO Auto-generated method stub
153 public List
<MetaData
> search(SearchableTag tag
) throws IOException
{
154 List
<MetaData
> metas
= new ArrayList
<MetaData
>();
156 if (tag
.getId() != null) {
157 Document doc
= load(tag
.getId());
158 for (Element story
: doc
.getElementsByClass("z-list")) {
161 String coverUrl
= "";
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();
169 // note: see data-original if needed?
170 coverUrl
= cover
.absUrl("src");
176 Elements as
= story
.getElementsByTag("a");
178 author
= as
.get(1).text();
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();
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
),
201 meta
.setSource(getType().getSourceName());
202 meta
.setTags(Arrays
.asList(tags
.split(" *- *")));
203 meta
.setTitle(title
);
213 public static void main(String
[] args
) throws IOException
{
214 Fanfiction f
= new Fanfiction(SupportType
.FANFICTION
);
216 SearchableTag cartoons
= f
.getTags().get(0).getChildren().get(2);
218 SearchableTag mlp
= cartoons
.getChildren().get(2);
219 System
.out
.println(mlp
);
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
);
227 System
.out
.println(cmlp
);
229 List
<MetaData
> metas
= f
.search(mlp
);
230 System
.out
.println(metas
);