e8fbf4db9683e70d58197c870c34ce5f43fa8c1e
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
{
26 static private String BASE_URL
= "http://fanfiction.net/";
29 * Create a new {@link Fanfiction}.
32 * {@link SupportType#FANFICTION}
34 public Fanfiction(SupportType type
) {
39 public List
<SearchableTag
> getTags() throws IOException
{
40 String storiesName
= null;
41 String crossoversName
= null;
42 Map
<String
, String
> stories
= new HashMap
<String
, String
>();
43 Map
<String
, String
> crossovers
= new HashMap
<String
, String
>();
45 Document mainPage
= load(BASE_URL
, true);
46 Element menu
= mainPage
.getElementsByClass("dropdown").first();
48 Element ul
= menu
.getElementsByClass("dropdown-menu").first();
50 Map
<String
, String
> currentList
= null;
51 for (Element li
: ul
.getElementsByTag("li")) {
52 if (li
.hasClass("disabled")) {
53 if (storiesName
== null) {
54 storiesName
= li
.text();
55 currentList
= stories
;
57 crossoversName
= li
.text();
58 currentList
= crossovers
;
60 } else if (currentList
!= null) {
61 Element a
= li
.getElementsByTag("a").first();
63 currentList
.put(a
.absUrl("href"), a
.text());
70 List
<SearchableTag
> tags
= new ArrayList
<SearchableTag
>();
72 if (storiesName
!= null) {
73 SearchableTag tag
= new SearchableTag(null, storiesName
, false);
74 for (String id
: stories
.keySet()) {
75 tag
.add(new SearchableTag(id
, stories
.get(id
), true, false));
80 if (crossoversName
!= null) {
81 SearchableTag tag
= new SearchableTag(null, crossoversName
, false);
82 for (String id
: crossovers
.keySet()) {
83 tag
.add(new SearchableTag(id
, crossovers
.get(id
), false, false));
92 protected void fillTag(SearchableTag tag
) throws IOException
{
93 if (tag
.getId() == null || tag
.isComplete()) {
97 boolean subtagIsLeaf
= !tag
.getId().contains("/crossovers/");
99 Document doc
= load(tag
.getId(), false);
100 Element list
= doc
.getElementById("list_output");
102 Element table
= list
.getElementsByTag("table").first();
104 for (Element div
: table
.getElementsByTag("div")) {
105 Element a
= div
.getElementsByTag("a").first();
106 Element span
= div
.getElementsByTag("span").first();
109 SearchableTag subtag
= new SearchableTag(
110 a
.absUrl("href"), a
.text(), subtagIsLeaf
);
113 String nr
= span
.text();
114 if (nr
.startsWith("(")) {
115 nr
= nr
.substring(1);
117 if (nr
.endsWith(")")) {
118 nr
= nr
.substring(0, nr
.length() - 1);
124 if (nr
.toLowerCase().endsWith("m")) {
125 count
= Long
.parseLong(nr
.substring(0,
126 nr
.length() - 1).trim());
128 } else if (nr
.toLowerCase().endsWith("k")) {
129 count
= Long
.parseLong(nr
.substring(0,
130 nr
.length() - 1).trim());
133 count
= Long
.parseLong(nr
);
135 } catch (NumberFormatException pe
) {
138 subtag
.setCount(count
);
145 tag
.setComplete(true);
149 public List
<MetaData
> search(String search
) throws IOException
{
150 // TODO /search/?reader=1&type=story&keywords=blablablab
155 public List
<MetaData
> search(SearchableTag tag
) throws IOException
{
156 List
<MetaData
> metas
= new ArrayList
<MetaData
>();
158 if (tag
.getId() != null) {
159 Document doc
= load(tag
.getId(), false);
161 Element center
= doc
.getElementsByTag("center").first();
162 if (center
!= null) {
164 for (Element a
: center
.getElementsByTag("a")) {
165 if (a
.absUrl("href").contains("&p=")) {
166 int thisLinkPages
= -1;
168 String
[] tab
= a
.absUrl("href").split("=");
169 tab
= tab
[tab
.length
- 1].split("&");
170 thisLinkPages
= Integer
171 .parseInt(tab
[tab
.length
- 1]);
172 } catch (Exception e
) {
175 pages
= Math
.max(pages
, thisLinkPages
);
182 for (Element story
: doc
.getElementsByClass("z-list")) {
185 String coverUrl
= "";
187 Element stitle
= story
.getElementsByClass("stitle").first();
188 if (stitle
!= null) {
189 title
= stitle
.text();
190 url
= stitle
.absUrl("href");
191 Element cover
= stitle
.getElementsByTag("img").first();
193 // note: see data-original if needed?
194 coverUrl
= cover
.absUrl("src");
200 Elements as
= story
.getElementsByTag("a");
202 author
= as
.get(1).text();
208 Elements divs
= story
.getElementsByTag("div");
209 if (divs
.size() > 1 && divs
.get(1).childNodeSize() > 0) {
210 resume
= divs
.get(1).text();
211 if (divs
.size() > 2) {
212 tags
= divs
.get(2).text();
213 resume
= resume
.substring(0,
214 resume
.length() - tags
.length()).trim();
218 MetaData meta
= new MetaData();
219 meta
.setAuthor(author
);
220 // meta.setCover(cover); //TODO ?
221 meta
.setImageDocument(false);
222 meta
.setResume(getSupport().makeChapter(new URL(tag
.getId()),
223 0, Instance
.getTrans().getString(StringId
.DESCRIPTION
),
225 meta
.setSource(getType().getSourceName());
226 // TODO: remove tags to interpret them instead (lang, words..)
227 meta
.setTags(Arrays
.asList(tags
.split(" *- *")));
228 meta
.setTitle(title
);
238 public static void main(String
[] args
) throws IOException
{
239 Fanfiction f
= new Fanfiction(SupportType
.FANFICTION
);
241 SearchableTag cartoons
= f
.getTags().get(0).getChildren().get(2);
243 SearchableTag mlp
= cartoons
.getChildren().get(2);
244 System
.out
.println(mlp
);
246 SearchableTag ccartoons
= f
.getTags().get(1).getChildren().get(0);
247 f
.fillTag(ccartoons
);
248 SearchableTag cmlp
= ccartoons
.getChildren().get(0);
249 System
.out
.println(cmlp
);
252 System
.out
.println(cmlp
);
254 List
<MetaData
> metas
= f
.search(mlp
);
255 System
.out
.println(mlp
.getPages());
256 //System.out.println(metas);