Get chapter list

This commit is contained in:
inorichi 2015-10-06 19:44:30 +02:00
parent a78359e4a9
commit a3463addc3
6 changed files with 109 additions and 114 deletions

View file

@ -29,7 +29,7 @@ public class App extends Application {
.appModule(new AppModule(this))
.build();
ACRA.init(this);
//ACRA.init(this);
}
public static App get(Context context) {

View file

@ -1,7 +1,11 @@
package eu.kanade.mangafeed.data.managers;
import com.pushtorefresh.storio.sqlite.StorIOSQLite;
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResult;
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResults;
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects;
import com.pushtorefresh.storio.sqlite.operations.put.PutResult;
import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
import com.pushtorefresh.storio.sqlite.queries.Query;
import java.util.List;
@ -17,7 +21,7 @@ public class ChapterManager extends BaseManager {
super(db);
}
public Observable<List<Chapter>> get(Manga manga) {
private PreparedGetListOfObjects<Chapter> prepareGet(Manga manga) {
return db.get()
.listOfObjects(Chapter.class)
.withQuery(Query.builder()
@ -25,8 +29,11 @@ public class ChapterManager extends BaseManager {
.where(ChaptersTable.COLUMN_MANGA_ID + "=?")
.whereArgs(manga.id)
.build())
.prepare()
.createObservable();
.prepare();
}
public Observable<List<Chapter>> get(Manga manga) {
return prepareGet(manga).createObservable();
}
public Observable<PutResult> insert(Chapter chapter) {
@ -36,16 +43,66 @@ public class ChapterManager extends BaseManager {
.createObservable();
}
public Observable<PutResults<Chapter>> insert(List<Chapter> chapters) {
return db.put()
.objects(chapters)
.prepare()
.createObservable();
}
// Add new chapters or delete if the source deletes them
public Observable insertOrRemove(Manga manga, List<Chapter> chapters) {
// I don't know a better approach
return Observable.create(subscriber -> {
List<Chapter> dbGet = prepareGet(manga).executeAsBlocking();
Observable.just(dbGet)
.doOnNext(dbChapters -> {
Observable.from(chapters)
.filter(c -> !dbChapters.contains(c))
.toList()
.subscribe(newChapters -> {
if (newChapters.size() > 0)
insert(newChapters).subscribe();
});
})
.flatMap(Observable::from)
.filter(c -> !chapters.contains(c))
.toList()
.subscribe(removedChapters -> {
if (removedChapters.size() > 0)
delete(removedChapters).subscribe();
subscriber.onCompleted();
});
});
}
public void createDummyChapters() {
Chapter c;
for (int i = 1; i < 100; i++) {
c = new Chapter();
c.manga_id = 1;
c.manga_id = 1L;
c.name = "Chapter " + i;
c.url = "http://example.com/1";
insert(c).subscribe();
}
}
public Observable<DeleteResults<Chapter>> delete(List<Chapter> chapters) {
return db.delete()
.objects(chapters)
.prepare()
.createObservable();
}
public Observable<DeleteResult> delete(Chapter chapter) {
return db.delete()
.object(chapter)
.prepare()
.createObservable();
}
}

View file

@ -17,7 +17,7 @@ public class Chapter {
@NonNull
@StorIOSQLiteColumn(name = ChaptersTable.COLUMN_MANGA_ID)
public int manga_id;
public Long manga_id;
@NonNull
@StorIOSQLiteColumn(name = ChaptersTable.COLUMN_URL)
@ -35,6 +35,10 @@ public class Chapter {
@StorIOSQLiteColumn(name = ChaptersTable.COLUMN_DATE_FETCH)
public long date_fetch;
@NonNull
@StorIOSQLiteColumn(name = ChaptersTable.COLUMN_DATE_UPLOAD)
public long date_upload;
public Chapter() {}
@ -45,23 +49,17 @@ public class Chapter {
Chapter chapter = (Chapter) o;
if (manga_id != chapter.manga_id) return false;
if (read != chapter.read) return false;
if (date_fetch != chapter.date_fetch) return false;
if (id != null ? !id.equals(chapter.id) : chapter.id != null) return false;
if (!url.equals(chapter.url)) return false;
return name.equals(chapter.name);
return url.equals(chapter.url);
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + manga_id;
result = 31 * result + url.hashCode();
result = 31 * result + name.hashCode();
result = 31 * result + read;
result = 31 * result + (int) (date_fetch ^ (date_fetch >>> 32));
return result;
return url.hashCode();
}
public static Chapter newChapter() {
Chapter c = new Chapter();
return c;
}
}

View file

@ -79,10 +79,9 @@ public class Manga {
this.title = title;
}
public Manga(long id, String title, String author, String artist, String url,
public Manga(String title, String author, String artist, String url,
String description, String genre, String status, int rank,
String thumbnail_url) {
this.id = id;
this.title = title;
this.author = author;
this.artist = artist;
@ -94,10 +93,10 @@ public class Manga {
this.thumbnail_url = thumbnail_url;
}
public static Manga newManga(long id, String title, String author, String artist, String url,
public static Manga newManga(String title, String author, String artist, String url,
String description, String genre, String status, int rank,
String thumbnail_url) {
return new Manga(id, title, author, artist, url, description, genre, status, rank, thumbnail_url);
return new Manga(title, author, artist, url, description, genre, status, rank, thumbnail_url);
}
@Override

View file

@ -2,9 +2,6 @@ package eu.kanade.mangafeed.data.tables;
import android.support.annotation.NonNull;
/**
* Created by len on 23/09/2015.
*/
public class ChaptersTable {
@NonNull
@ -28,6 +25,9 @@ public class ChaptersTable {
@NonNull
public static final String COLUMN_DATE_FETCH = "date_fetch";
@NonNull
public static final String COLUMN_DATE_UPLOAD = "date_upload";
@NonNull
public static String getCreateTableQuery() {
return "CREATE TABLE " + TABLE + "("
@ -37,8 +37,10 @@ public class ChaptersTable {
+ COLUMN_NAME + " TEXT NOT NULL, "
+ COLUMN_READ + " BOOLEAN NOT NULL, "
+ COLUMN_DATE_FETCH + " LONG NOT NULL, "
+ COLUMN_DATE_UPLOAD + " LONG NOT NULL, "
+ "FOREIGN KEY(" + COLUMN_MANGA_ID + ") REFERENCES " + MangasTable.TABLE + "(" + MangasTable.COLUMN_ID + ") "
+ "ON DELETE CASCADE"
+ ");";
}
}

View file

@ -1,19 +1,27 @@
package eu.kanade.mangafeed.sources;
import com.squareup.okhttp.Headers;
import com.squareup.okhttp.Response;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import eu.kanade.mangafeed.data.caches.CacheManager;
import eu.kanade.mangafeed.data.helpers.NetworkHelper;
import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Manga;
import rx.Observable;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import timber.log.Timber;
@ -318,52 +326,35 @@ public class Batoto {
return newManga;
}
*/
public Observable<List<Chapter>> pullChaptersFromNetwork(final String mangaUrl, final String mangaName) {
public Observable<List<Chapter>> pullChaptersFromNetwork(String mangaUrl) {
return mNetworkService
.getResponse(mangaUrl, NetworkModule.NULL_CACHE_CONTROL, REQUEST_HEADERS)
.flatMap(new Func1<Response, Observable<String>>() {
@Override
public Observable<String> call(Response response) {
return mNetworkService.mapResponseToString(response);
}
})
.flatMap(new Func1<String, Observable<List<Chapter>>>() {
@Override
public Observable<List<Chapter>> call(String unparsedHtml) {
return Observable.just(parseHtmlToChapters(mangaUrl, mangaName, unparsedHtml));
}
});
.getStringResponse(mangaUrl, mNetworkService.NULL_CACHE_CONTROL, REQUEST_HEADERS)
.flatMap(unparsedHtml ->
Observable.just(parseHtmlToChapters(unparsedHtml)));
}
private List<Chapter> parseHtmlToChapters(String mangaUrl, String mangaName, String unparsedHtml) {
private List<Chapter> parseHtmlToChapters(String unparsedHtml) {
Document parsedDocument = Jsoup.parse(unparsedHtml);
List<Chapter> chapterList = scrapeChaptersFromParsedDocument(parsedDocument);
chapterList = setSourceForChapterList(chapterList);
chapterList = setParentInfoForChapterList(chapterList, mangaUrl, mangaName);
chapterList = setNumberForChapterList(chapterList);
saveChaptersToDatabase(chapterList, mangaUrl);
return chapterList;
}
private List<Chapter> scrapeChaptersFromParsedDocument(Document parsedDocument) {
List<Chapter> chapterList = new ArrayList<Chapter>();
Elements chapterElements = parsedDocument.select("tr.row.lang_English.chapter_row");
for (Element chapterElement : chapterElements) {
Chapter currentChapter = constructChapterFromHtmlBlock(chapterElement);
System.out.println(currentChapter.name);
chapterList.add(currentChapter);
}
//saveChaptersToDatabase(chapterList, mangaUrl);
return chapterList;
}
private Chapter constructChapterFromHtmlBlock(Element chapterElement) {
Chapter newChapter = DefaultFactory.Chapter.constructDefault();
Chapter newChapter = Chapter.newChapter();
Element urlElement = chapterElement.select("a[href^=http://bato.to/read/").first();
Element nameElement = urlElement;
@ -371,16 +362,17 @@ public class Batoto {
if (urlElement != null) {
String fieldUrl = urlElement.attr("href");
newChapter.setUrl(fieldUrl);
newChapter.url = fieldUrl;
}
if (nameElement != null) {
String fieldName = nameElement.text().trim();
newChapter.setName(fieldName);
newChapter.name = fieldName;
}
if (dateElement != null) {
long fieldDate = parseDateFromElement(dateElement);
newChapter.setDate(fieldDate);
newChapter.date_upload = fieldDate;
}
newChapter.date_fetch = new Date().getTime();
return newChapter;
}
@ -396,77 +388,24 @@ public class Batoto {
// Do Nothing.
}
return DefaultFactory.Chapter.DEFAULT_DATE;
return 0;
}
private List<Chapter> setSourceForChapterList(List<Chapter> chapterList) {
for (Chapter currentChapter : chapterList) {
currentChapter.setSource(NAME);
}
return chapterList;
}
private List<Chapter> setParentInfoForChapterList(List<Chapter> chapterList, String parentUrl, String parentName) {
for (Chapter currentChapter : chapterList) {
currentChapter.setParentUrl(parentUrl);
currentChapter.setParentName(parentName);
}
return chapterList;
}
private List<Chapter> setNumberForChapterList(List<Chapter> chapterList) {
Collections.reverse(chapterList);
for (int index = 0; index < chapterList.size(); index++) {
chapterList.get(index).setNumber(index + 1);
}
return chapterList;
}
private void saveChaptersToDatabase(List<Chapter> chapterList, String parentUrl) {
StringBuilder selection = new StringBuilder();
List<String> selectionArgs = new ArrayList<String>();
selection.append(ApplicationContract.Chapter.COLUMN_SOURCE + " = ?");
selectionArgs.add(NAME);
selection.append(" AND ").append(ApplicationContract.Chapter.COLUMN_PARENT_URL + " = ?");
selectionArgs.add(parentUrl);
mQueryManager.beginApplicationTransaction();
try {
mQueryManager.deleteAllChapter(selection.toString(), selectionArgs.toArray(new String[selectionArgs.size()]))
.toBlocking()
.single();
for (Chapter currentChapter : chapterList) {
mQueryManager.createChapter(currentChapter)
.toBlocking()
.single();
}
mQueryManager.setApplicationTransactionSuccessful();
} finally {
mQueryManager.endApplicationTransaction();
}
}
*/
public Observable<String> pullImageUrlsFromNetwork(final String chapterUrl) {
final List<String> temporaryCachedImageUrls = new ArrayList<>();
return mCacheManager.getImageUrlsFromDiskCache(chapterUrl)
.onErrorResumeNext(throwable -> {
return mNetworkService
.getStringResponse(chapterUrl, mNetworkService.NULL_CACHE_CONTROL, null)
.getStringResponse(chapterUrl, mNetworkService.NULL_CACHE_CONTROL, REQUEST_HEADERS)
.subscribeOn(Schedulers.io())
.flatMap(unparsedHtml -> Observable.from(parseHtmlToPageUrls(unparsedHtml)))
.buffer(3)
.concatMap(batchedPageUrls -> {
List<Observable<String>> imageUrlObservables = new ArrayList<>();
for (String pageUrl : batchedPageUrls) {
Observable<String> temporaryObservable = mNetworkService
.getStringResponse(pageUrl, mNetworkService.NULL_CACHE_CONTROL, null)
.getStringResponse(pageUrl, mNetworkService.NULL_CACHE_CONTROL, REQUEST_HEADERS)
.flatMap(unparsedHtml -> Observable.just(parseHtmlToImageUrl(unparsedHtml)))
.subscribeOn(Schedulers.io());