New support: YiffStar (still no logged-in content)
[nikiroo-utils.git] / src / be / nikiroo / fanfix / supported / YiffStar.java
CommitLineData
a4143cd7
NR
1package be.nikiroo.fanfix.supported;
2
3import java.awt.image.BufferedImage;
4import java.io.IOException;
5import java.io.InputStream;
6import java.net.URL;
7import java.util.ArrayList;
8import java.util.List;
9import java.util.Map;
10import java.util.Map.Entry;
11import java.util.Scanner;
12
13import be.nikiroo.fanfix.Instance;
14import be.nikiroo.fanfix.data.MetaData;
15import be.nikiroo.utils.StringUtils;
16
17/**
18 * Support class for <a href="https://sofurry.com/">SoFurry.com</a>, a Furry
19 * website supporting images and stories (we only retrieve the stories).
20 *
21 * @author niki
22 */
23class YiffStar extends BasicSupport {
24
25 @Override
26 public String getSourceName() {
27 return "YiffStar";
28 }
29
30 @Override
31 protected MetaData getMeta(URL source, InputStream in) throws IOException {
32 MetaData meta = new MetaData();
33
34 meta.setTitle(getTitle(reset(in)));
35 meta.setAuthor(getAuthor(source, reset(in)));
36 meta.setDate("");
37 meta.setTags(getTags(reset(in)));
38 meta.setSource(getSourceName());
39 meta.setUrl(source.toString());
40 meta.setPublisher(getSourceName());
41 meta.setUuid(source.toString());
42 meta.setLuid("");
43 meta.setLang("EN");
44 meta.setSubject("Furry");
45 meta.setType(getType().toString());
46 meta.setImageDocument(false);
47 meta.setCover(getCover(source, reset(in)));
48
49 return meta;
50 }
51
52 @Override
53 protected boolean supports(URL url) {
54 String host = url.getHost();
55 if (host.startsWith("www.")) {
56 host = host.substring("www.".length());
57 }
58
59 return "sofurry.com".equals(host);
60 }
61
62 @Override
63 protected boolean isHtml() {
64 return true;
65 }
66
67 @Override
68 public Map<String, String> getCookies() {
69 // TODO
70 // Cookies will actually be retained by the cache manager once logged in
71 // But we need to connect here and notify the cache manager
72
73 return super.getCookies();
74 }
75
76 @Override
77 public URL getCanonicalUrl(URL source) throws IOException {
78 if (source.getPath().startsWith("/view")) {
79 InputStream in = Instance.getCache().open(source, this, false);
80 String line = getLine(in, "/browse/folder/", 0);
81 String[] tab = line.split("\"");
82 if (tab.length > 1) {
83 String groupUrl = source.getProtocol() + "://"
84 + source.getHost() + tab[1];
85 return new URL(groupUrl);
86 }
87 }
88
89 return super.getCanonicalUrl(source);
90 }
91
92 private List<String> getTags(InputStream in) {
93 List<String> tags = new ArrayList<String>();
94
95 String line = getLine(in, "class=\"sf-story-big-tags", 0);
96 if (line != null) {
97 String[] tab = StringUtils.unhtml(line).split(",");
98 for (String possibleTag : tab) {
99 String tag = possibleTag.trim();
100 if (!tag.isEmpty() && !tag.equals("...") && !tags.contains(tag)) {
101 tags.add(tag);
102 }
103 }
104 }
105
106 return tags;
107 }
108
109 private BufferedImage getCover(URL source, InputStream in)
110 throws IOException {
111
112 List<Entry<String, URL>> chaps = getChapters(source, in);
113 if (!chaps.isEmpty()) {
114 in = Instance.getCache().open(chaps.get(0).getValue(), this, true);
115 String line = getLine(in, " name=\"og:image\"", 0);
116 if (line != null) {
117 int pos = -1;
118 for (int i = 0; i < 3; i++) {
119 pos = line.indexOf('"', pos + 1);
120 }
121
122 if (pos >= 0) {
123 line = line.substring(pos + 1);
124 pos = line.indexOf('"');
125 if (pos >= 0) {
126 line = line.substring(0, pos);
127 if (line.contains("/thumb?")) {
128 line = line.replace("/thumb?",
129 "/auxiliaryContent?type=25&");
130 return getImage(this, null, line);
131 }
132 }
133 }
134 }
135 }
136
137 return null;
138 }
139
140 private String getAuthor(URL source, InputStream in) throws IOException {
141 String author = getLine(in, "class=\"onlinestatus", 0);
142 if (author != null) {
143 return StringUtils.unhtml(author).trim();
144 }
145
146 return null;
147 }
148
149 private String getTitle(InputStream in) throws IOException {
150 String title = getLine(in, "class=\"sflabel pagetitle", 0);
151 if (title != null) {
152 if (title.contains("(series)")) {
153 title = title.replace("(series)", "");
154 }
155 return StringUtils.unhtml(title).trim();
156 }
157
158 return null;
159 }
160
161 @Override
162 protected String getDesc(URL source, InputStream in) throws IOException {
163 return null; // TODO: no description at all? Cannot find one...
164 }
165
166 @Override
167 protected List<Entry<String, URL>> getChapters(URL source, InputStream in)
168 throws IOException {
169 List<Entry<String, URL>> urls = new ArrayList<Entry<String, URL>>();
170
171 @SuppressWarnings("resource")
172 Scanner scan = new Scanner(in, "UTF-8");
173 scan.useDelimiter("\\n");
174 while (scan.hasNext()) {
175 String line = scan.next();
176 if (line.contains("\"/view/") && line.contains("title=")) {
177 String[] tab = line.split("\"");
178 if (tab.length > 5) {
179 String link = tab[5];
180 if (link.startsWith("/")) {
181 link = source.getProtocol() + "://" + source.getHost()
182 + link;
183 }
184 final URL value = new URL(link);
185 final String key = StringUtils.unhtml(line).trim();
186 urls.add(new Entry<String, URL>() {
187 public URL setValue(URL value) {
188 return null;
189 }
190
191 public URL getValue() {
192 return value;
193 }
194
195 public String getKey() {
196 return key;
197 }
198 });
199 }
200 }
201 }
202
203 return urls;
204 }
205
206 @Override
207 protected String getChapterContent(URL source, InputStream in, int number)
208 throws IOException {
209 StringBuilder builder = new StringBuilder();
210
211 String startAt = "id=\"sfContentBody";
212 String endAt = "id=\"recommendationArea";
213 boolean ok = false;
214
215 @SuppressWarnings("resource")
216 Scanner scan = new Scanner(in, "UTF-8");
217 scan.useDelimiter("\\n");
218 while (scan.hasNext()) {
219 String line = scan.next();
220 if (!ok && line.contains(startAt)) {
221 ok = true;
222 } else if (ok && line.contains(endAt)) {
223 ok = false;
224 break;
225 }
226
227 if (ok) {
228 builder.append(line);
229 builder.append('\n');
230 }
231 }
232
233 return builder.toString();
234 }
235}