test: improve flag files
[nikiroo-utils.git] / src / be / nikiroo / fanfix / supported / Cbz.java
... / ...
CommitLineData
1package be.nikiroo.fanfix.supported;
2
3import java.io.File;
4import java.io.IOException;
5import java.io.InputStream;
6import java.net.URL;
7import java.util.ArrayList;
8import java.util.Collections;
9import java.util.HashMap;
10import java.util.List;
11import java.util.Map;
12import java.util.zip.ZipEntry;
13import java.util.zip.ZipInputStream;
14
15import be.nikiroo.fanfix.Instance;
16import be.nikiroo.fanfix.bundles.Config;
17import be.nikiroo.fanfix.data.Chapter;
18import be.nikiroo.fanfix.data.MetaData;
19import be.nikiroo.fanfix.data.Paragraph;
20import be.nikiroo.fanfix.data.Paragraph.ParagraphType;
21import be.nikiroo.fanfix.data.Story;
22import be.nikiroo.utils.IOUtils;
23import be.nikiroo.utils.Image;
24import be.nikiroo.utils.Progress;
25import be.nikiroo.utils.streams.MarkableFileInputStream;
26
27/**
28 * Support class for CBZ files (works better with CBZ created with this program,
29 * as they have some metadata available).
30 *
31 * @author niki
32 */
33class Cbz extends Epub {
34 @Override
35 protected boolean supports(URL url) {
36 return url.toString().toLowerCase().endsWith(".cbz");
37 }
38
39 @Override
40 protected String getDataPrefix() {
41 return "";
42 }
43
44 @Override
45 protected boolean requireInfo() {
46 return false;
47 }
48
49 @Override
50 protected boolean isImagesDocumentByDefault() {
51 return true;
52 }
53
54 @Override
55 protected boolean getCover() {
56 return false;
57 }
58
59 @Override
60 public Story doProcess(Progress pg) throws IOException {
61 if (pg == null) {
62 pg = new Progress();
63 } else {
64 pg.setMinMax(0, 100);
65 }
66
67 Progress pgMeta = new Progress();
68 pg.addProgress(pgMeta, 10);
69 Story story = processMeta(true, pgMeta);
70 MetaData meta = story.getMeta();
71
72 pgMeta.done(); // 10%
73
74 File tmpDir = Instance.getTempFiles().createTempDir("info-text");
75 String basename = null;
76
77 Map<String, Image> images = new HashMap<String, Image>();
78 InputStream cbzIn = null;
79 ZipInputStream zipIn = null;
80 try {
81 cbzIn = new MarkableFileInputStream(getSourceFileOriginal());
82 zipIn = new ZipInputStream(cbzIn);
83 for (ZipEntry entry = zipIn.getNextEntry(); entry != null; entry = zipIn
84 .getNextEntry()) {
85 if (!entry.isDirectory()
86 && entry.getName().startsWith(getDataPrefix())) {
87 String entryLName = entry.getName().toLowerCase();
88 boolean imageEntry = false;
89 for (String ext : bsImages.getImageExt(false)) {
90 if (entryLName.endsWith(ext)) {
91 imageEntry = true;
92 }
93 }
94
95 if (imageEntry) {
96 String uuid = meta.getUuid() + "_" + entry.getName();
97 try {
98 images.put(uuid, new Image(zipIn));
99 } catch (Exception e) {
100 Instance.getTraceHandler().error(e);
101 }
102
103 if (pg.getProgress() < 85) {
104 pg.add(1);
105 }
106 } else if (entryLName.endsWith(".info")) {
107 basename = entryLName.substring(0, entryLName.length()
108 - ".info".length());
109 IOUtils.write(zipIn, new File(tmpDir, entryLName));
110 } else if (entryLName.endsWith(".txt")) {
111 IOUtils.write(zipIn, new File(tmpDir, entryLName));
112 }
113 }
114 }
115
116 String ext = "."
117 + Instance.getConfig()
118 .getString(Config.FILE_FORMAT_IMAGE_FORMAT_COVER)
119 .toLowerCase();
120 String coverName = meta.getUuid() + "_" + basename + ext;
121 Image cover = images.get(coverName);
122 images.remove(coverName);
123
124 pg.setProgress(85);
125
126 // ZIP order is not correct for us
127 List<String> imagesList = new ArrayList<String>(images.keySet());
128 Collections.sort(imagesList);
129
130 pg.setProgress(90);
131
132 // only the description/cover is kept
133 Story origStory = getStoryFromTxt(tmpDir, basename);
134 if (origStory != null) {
135 if (origStory.getMeta().getCover() == null) {
136 origStory.getMeta().setCover(story.getMeta().getCover());
137 }
138 story.setMeta(origStory.getMeta());
139 }
140 if (story.getMeta().getCover() == null) {
141 story.getMeta().setCover(cover);
142 }
143 story.setChapters(new ArrayList<Chapter>());
144
145 // Check if we can find non-images chapters, for hybrid-cbz support
146 if (origStory != null) {
147 for (Chapter chap : origStory) {
148 Boolean isImages = null;
149 for (Paragraph para : chap) {
150 ParagraphType t = para.getType();
151 if (isImages == null && !t.isText(true)) {
152 isImages = true;
153 }
154 if (t.isText(false)) {
155 String line = para.getContent();
156 // Images are saved in text mode as "[image-link]"
157 if (!(line.startsWith("[") && line.endsWith("]"))) {
158 isImages = false;
159 }
160 }
161 }
162
163 if (isImages != null && !isImages) {
164 story.getChapters().add(chap);
165 chap.setNumber(story.getChapters().size());
166 }
167 }
168 }
169
170 if (!imagesList.isEmpty()) {
171 Chapter chap = new Chapter(story.getChapters().size() + 1, null);
172 story.getChapters().add(chap);
173
174 for (String uuid : imagesList) {
175 try {
176 chap.getParagraphs().add(
177 new Paragraph(images.get(uuid)));
178 } catch (Exception e) {
179 Instance.getTraceHandler().error(e);
180 }
181 }
182 }
183
184 if (meta.getCover() == null && !images.isEmpty()) {
185 meta.setCover(images.get(imagesList.get(0)));
186 meta.setFakeCover(true);
187 }
188 } finally {
189 IOUtils.deltree(tmpDir);
190 if (zipIn != null) {
191 zipIn.close();
192 }
193 if (cbzIn != null) {
194 cbzIn.close();
195 }
196 }
197
198 pg.setProgress(100);
199 return story;
200 }
201
202 private Story getStoryFromTxt(File tmpDir, String basename) {
203 Story origStory = null;
204
205 File txt = new File(tmpDir, basename + ".txt");
206 if (!txt.exists()) {
207 basename = null;
208 }
209 if (basename != null) {
210 try {
211 BasicSupport support = BasicSupport.getSupport(txt.toURI()
212 .toURL());
213 origStory = support.process(null);
214 } catch (Exception e) {
215 basename = null;
216 }
217 }
218
219 return origStory;
220
221 }
222}