From ede3e69f5cf948d2f279cda8a2609aa7ac49abb8 Mon Sep 17 00:00:00 2001 From: Floens Date: Sun, 6 Aug 2017 10:12:12 +0200 Subject: [PATCH] Work on abstracting the html parser. --- .../java/org/floens/chan/chan/ChanLoader.java | 10 +- .../chan/chan/ChanLoaderRequestParams.java | 7 +- .../chan/core/manager/BoardManager.java | 13 + .../java/org/floens/chan/core/site/Site.java | 5 +- .../chan/core/site/common/ChanReader.java | 12 + .../common/ChanReaderProcessingQueue.java | 63 ++++ .../core/site/common/ChanReaderRequest.java | 276 ++---------------- .../core/site/common/FutabaChanReader.java | 242 +++++++++++++++ .../chan/core/site/sites/chan4/Chan4.java | 9 +- .../chan/core/site/sites/chan8/Chan8.java | 14 +- 10 files changed, 380 insertions(+), 271 deletions(-) create mode 100644 Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReader.java create mode 100644 Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderProcessingQueue.java create mode 100644 Clover/app/src/main/java/org/floens/chan/core/site/common/FutabaChanReader.java diff --git a/Clover/app/src/main/java/org/floens/chan/chan/ChanLoader.java b/Clover/app/src/main/java/org/floens/chan/chan/ChanLoader.java index 1ece12a0..2e58000f 100644 --- a/Clover/app/src/main/java/org/floens/chan/chan/ChanLoader.java +++ b/Clover/app/src/main/java/org/floens/chan/chan/ChanLoader.java @@ -25,8 +25,10 @@ import com.android.volley.VolleyError; import org.floens.chan.core.exception.ChanLoaderException; import org.floens.chan.core.model.ChanThread; -import org.floens.chan.core.model.orm.Loadable; import org.floens.chan.core.model.Post; +import org.floens.chan.core.model.orm.Loadable; +import org.floens.chan.core.site.common.ChanReader; +import org.floens.chan.core.site.common.ChanReaderRequest; import org.floens.chan.ui.helper.PostHelper; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.Logger; @@ -235,7 +237,11 @@ public class ChanLoader implements Response.ErrorListener, Response.Listener cached = thread == null ? new ArrayList() : thread.posts; - request = loadable.getSite().loaderRequest(new ChanLoaderRequestParams(loadable, cached, this, this)); + ChanReader chanReader = loadable.getSite().chanReader(); + + ChanLoaderRequestParams requestParams = new ChanLoaderRequestParams(loadable, chanReader, cached, this, this); + ChanReaderRequest readerRequest = new ChanReaderRequest(requestParams); + request = new ChanLoaderRequest(readerRequest); volleyRequestQueue.add(request.getVolleyRequest()); diff --git a/Clover/app/src/main/java/org/floens/chan/chan/ChanLoaderRequestParams.java b/Clover/app/src/main/java/org/floens/chan/chan/ChanLoaderRequestParams.java index 0536bf1d..6a7b8b52 100644 --- a/Clover/app/src/main/java/org/floens/chan/chan/ChanLoaderRequestParams.java +++ b/Clover/app/src/main/java/org/floens/chan/chan/ChanLoaderRequestParams.java @@ -20,8 +20,9 @@ package org.floens.chan.chan; import com.android.volley.Response; -import org.floens.chan.core.model.orm.Loadable; import org.floens.chan.core.model.Post; +import org.floens.chan.core.model.orm.Loadable; +import org.floens.chan.core.site.common.ChanReader; import java.util.List; @@ -34,6 +35,8 @@ public class ChanLoaderRequestParams { */ public final Loadable loadable; + public final ChanReader chanReader; + /** * Cached Post objects from previous loads, or an empty list. */ @@ -50,11 +53,13 @@ public class ChanLoaderRequestParams { public final Response.ErrorListener errorListener; public ChanLoaderRequestParams(Loadable loadable, + ChanReader chanReader, List cached, Response.Listener listener, Response.ErrorListener errorListener) { this.loadable = loadable; + this.chanReader = chanReader; this.cached = cached; this.listener = listener; this.errorListener = errorListener; diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java index 270afbde..62eeed57 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/manager/BoardManager.java @@ -75,6 +75,19 @@ public class BoardManager { fetchLimitedSitesTheirBoards(); } + public Board getForCode(Site site, String code) { + if (site.boardsType() == Site.BoardsType.DYNAMIC) { + for (Board board : getSavedBoards()) { + if (board.site == site && board.code.equals(code)) { + return board; + } + } + return null; + } else { + return Board.fromSiteNameCode(site, code, code); + } + } + public List getSavedBoards() { return savedBoards; } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/Site.java b/Clover/app/src/main/java/org/floens/chan/core/site/Site.java index 074cd8dc..cbfd4e3a 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/Site.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/Site.java @@ -19,13 +19,12 @@ package org.floens.chan.core.site; import android.support.annotation.Nullable; -import org.floens.chan.chan.ChanLoaderRequest; -import org.floens.chan.chan.ChanLoaderRequestParams; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.json.site.SiteConfig; import org.floens.chan.core.model.json.site.SiteUserSettings; import org.floens.chan.core.model.orm.Board; import org.floens.chan.core.model.orm.Loadable; +import org.floens.chan.core.site.common.ChanReader; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.DeleteResponse; import org.floens.chan.core.site.http.HttpCall; @@ -145,7 +144,7 @@ public interface Site { void onBoardNonexistent(); } - ChanLoaderRequest loaderRequest(ChanLoaderRequestParams request); + ChanReader chanReader(); void post(Reply reply, PostListener postListener); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReader.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReader.java new file mode 100644 index 00000000..e0c98728 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReader.java @@ -0,0 +1,12 @@ +package org.floens.chan.core.site.common; + + +import android.util.JsonReader; + +public interface ChanReader { + void loadThread(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception; + + void loadCatalog(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception; + + void readPostObject(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception; +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderProcessingQueue.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderProcessingQueue.java new file mode 100644 index 00000000..bbe68093 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderProcessingQueue.java @@ -0,0 +1,63 @@ +package org.floens.chan.core.site.common; + + +import android.annotation.SuppressLint; + +import org.floens.chan.core.model.Post; +import org.floens.chan.core.model.orm.Loadable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +class ChanReaderProcessingQueue { + @SuppressLint("UseSparseArrays") + private Map cachedByNo = new HashMap<>(); + private Loadable loadable; + + private List toReuse = new ArrayList<>(); + private List toParse = new ArrayList<>(); + private Post.Builder op; + + public ChanReaderProcessingQueue(List toReuse, Loadable loadable) { + this.loadable = loadable; + + for (int i = 0; i < toReuse.size(); i++) { + Post cache = toReuse.get(i); + cachedByNo.put(cache.no, cache); + } + } + + public Post getCachedPost(int no) { + return cachedByNo.get(no); + } + + public void addForReuse(Post post) { + toReuse.add(post); + } + + public void addForParse(Post.Builder postBuilder) { + toParse.add(postBuilder); + } + + public void setOp(Post.Builder op) { + this.op = op; + } + + public Loadable getLoadable() { + return loadable; + } + + List getToReuse() { + return toReuse; + } + + List getToParse() { + return toParse; + } + + Post.Builder getOp() { + return op; + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java index 700ce062..5302ca54 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/ChanReaderRequest.java @@ -25,15 +25,11 @@ import org.floens.chan.chan.ChanParser; import org.floens.chan.core.database.DatabaseManager; import org.floens.chan.core.database.DatabaseSavedReplyManager; import org.floens.chan.core.manager.FilterEngine; +import org.floens.chan.core.model.Post; import org.floens.chan.core.model.orm.Filter; import org.floens.chan.core.model.orm.Loadable; -import org.floens.chan.core.model.Post; -import org.floens.chan.core.model.PostHttpIcon; -import org.floens.chan.core.model.PostImage; import org.floens.chan.core.net.JsonReaderRequest; -import org.floens.chan.core.site.SiteEndpoints; import org.floens.chan.utils.Time; -import org.jsoup.parser.Parser; import java.util.ArrayList; import java.util.HashMap; @@ -79,7 +75,7 @@ public class ChanReaderRequest extends JsonReaderRequest { private Loadable loadable; private List cached; - private Post.Builder op; + private ChanReader reader; private DatabaseSavedReplyManager databaseSavedReplyManager; private List filters; @@ -92,6 +88,7 @@ public class ChanReaderRequest extends JsonReaderRequest { // Copy the loadable and cached list. The cached array may changed/cleared by other threads. loadable = request.loadable.copy(); cached = new ArrayList<>(request.cached); + reader = request.chanReader; filters = new ArrayList<>(); List enabledFilters = filterEngine.getEnabledFilters(); @@ -152,18 +149,12 @@ public class ChanReaderRequest extends JsonReaderRequest { long load = Time.startTiming(); - ProcessingQueue processing = new ProcessingQueue(); - - Map cachedByNo = new HashMap<>(); - for (int i = 0; i < cached.size(); i++) { - Post cache = cached.get(i); - cachedByNo.put(cache.no, cache); - } + ChanReaderProcessingQueue processing = new ChanReaderProcessingQueue(cached, loadable); if (loadable.isThreadMode()) { - loadThread(reader, processing, cachedByNo); + this.reader.loadThread(reader, processing); } else if (loadable.isCatalogMode()) { - loadCatalog(reader, processing, cachedByNo); + this.reader.loadCatalog(reader, processing); } else { throw new IllegalArgumentException("Unknown mode"); } @@ -173,20 +164,23 @@ public class ChanReaderRequest extends JsonReaderRequest { } List list = parsePosts(processing); - return processPosts(list); + return processPosts(processing.getOp(), list); } // Concurrently parses the new posts with an executor - private List parsePosts(ProcessingQueue queue) throws InterruptedException, ExecutionException { + private List parsePosts(ChanReaderProcessingQueue queue) throws InterruptedException, ExecutionException { long parsePosts = Time.startTiming(); List total = new ArrayList<>(); - total.addAll(queue.cached); + List cached = queue.getToReuse(); + total.addAll(cached); + + List toParse = queue.getToParse(); - List> tasks = new ArrayList<>(queue.toParse.size()); - for (int i = 0; i < queue.toParse.size(); i++) { - Post.Builder post = queue.toParse.get(i); + List> tasks = new ArrayList<>(toParse.size()); + for (int i = 0; i < toParse.size(); i++) { + Post.Builder post = toParse.get(i); tasks.add(new PostParseCallable(filterEngine, filters, databaseSavedReplyManager, post, chanParser)); } @@ -208,8 +202,8 @@ public class ChanReaderRequest extends JsonReaderRequest { return total; } - private ChanLoaderResponse processPosts(List serverPosts) throws Exception { - ChanLoaderResponse response = new ChanLoaderResponse(op, new ArrayList(serverPosts.size())); + private ChanLoaderResponse processPosts(Post.Builder op, List allPost) throws Exception { + ChanLoaderResponse response = new ChanLoaderResponse(op, new ArrayList(allPost.size())); List cachedPosts = new ArrayList<>(); List newPosts = new ArrayList<>(); @@ -225,8 +219,8 @@ public class ChanReaderRequest extends JsonReaderRequest { } Map serverPostsByNo = new HashMap<>(); - for (int i = 0; i < serverPosts.size(); i++) { - Post post = serverPosts.get(i); + for (int i = 0; i < allPost.size(); i++) { + Post post = allPost.get(i); serverPostsByNo.put(post.no, post); } @@ -243,8 +237,8 @@ public class ChanReaderRequest extends JsonReaderRequest { long newCheck = Time.startTiming(); // If there's a post in the list from the server, that's not in the cached list, add it. - for (int i = 0; i < serverPosts.size(); i++) { - Post serverPost = serverPosts.get(i); + for (int i = 0; i < allPost.size(); i++) { + Post serverPost = allPost.get(i); if (!cachedPostsByNo.containsKey(serverPost.no)) { newPosts.add(serverPost); } @@ -253,7 +247,7 @@ public class ChanReaderRequest extends JsonReaderRequest { Time.endTiming("New check", newCheck); } } else { - newPosts.addAll(serverPosts); + newPosts.addAll(allPost); } List allPosts = new ArrayList<>(cachedPosts.size() + newPosts.size()); @@ -308,230 +302,4 @@ public class ChanReaderRequest extends JsonReaderRequest { return response; } - - private void loadThread(JsonReader reader, ProcessingQueue queue, Map cachedByNo) throws Exception { - reader.beginObject(); - // Page object - while (reader.hasNext()) { - String key = reader.nextName(); - if (key.equals("posts")) { - reader.beginArray(); - // Thread array - while (reader.hasNext()) { - // Thread object - readPostObject(reader, queue, cachedByNo); - } - reader.endArray(); - } else { - reader.skipValue(); - } - } - reader.endObject(); - } - - private void loadCatalog(JsonReader reader, ProcessingQueue queue, Map cachedByNo) throws Exception { - reader.beginArray(); // Array of pages - - while (reader.hasNext()) { - reader.beginObject(); // Page object - - while (reader.hasNext()) { - if (reader.nextName().equals("threads")) { - reader.beginArray(); // Threads array - - while (reader.hasNext()) { - readPostObject(reader, queue, cachedByNo); - } - - reader.endArray(); - } else { - reader.skipValue(); - } - } - - reader.endObject(); - } - - reader.endArray(); - } - - private void readPostObject(JsonReader reader, ProcessingQueue queue, Map cachedByNo) throws Exception { - Post.Builder builder = new Post.Builder(); - builder.board(loadable.board); - - // File - String fileId = null; - String fileExt = null; - int fileWidth = 0; - int fileHeight = 0; - long fileSize = 0; - boolean fileSpoiler = false; - String fileName = null; - - // Country flag - String countryCode = null; - String trollCountryCode = null; - String countryName = null; - - // 4chan pass leaf - int since4pass = 0; - - reader.beginObject(); - while (reader.hasNext()) { - String key = reader.nextName(); - - switch (key) { - case "no": - builder.id(reader.nextInt()); - break; - /*case "now": - post.date = reader.nextString(); - break;*/ - case "sub": - builder.subject(reader.nextString()); - break; - case "name": - builder.name(reader.nextString()); - break; - case "com": - builder.comment(reader.nextString()); - break; - case "tim": - fileId = reader.nextString(); - break; - case "time": - builder.setUnixTimestampSeconds(reader.nextLong()); - break; - case "ext": - fileExt = reader.nextString().replace(".", ""); - break; - case "w": - fileWidth = reader.nextInt(); - break; - case "h": - fileHeight = reader.nextInt(); - break; - case "fsize": - fileSize = reader.nextLong(); - break; - case "filename": - fileName = reader.nextString(); - break; - case "trip": - builder.tripcode(reader.nextString()); - break; - case "country": - countryCode = reader.nextString(); - break; - case "troll_country": - trollCountryCode = reader.nextString(); - break; - case "country_name": - countryName = reader.nextString(); - break; - case "spoiler": - fileSpoiler = reader.nextInt() == 1; - break; - case "resto": - int opId = reader.nextInt(); - builder.op(opId == 0); - builder.opId(opId); - break; - case "sticky": - builder.sticky(reader.nextInt() == 1); - break; - case "closed": - builder.closed(reader.nextInt() == 1); - break; - case "archived": - builder.archived(reader.nextInt() == 1); - break; - case "replies": - builder.replies(reader.nextInt()); - break; - case "images": - builder.images(reader.nextInt()); - break; - case "unique_ips": - builder.uniqueIps(reader.nextInt()); - break; - case "id": - builder.posterId(reader.nextString()); - break; - case "capcode": - builder.moderatorCapcode(reader.nextString()); - break; - case "since4pass": - since4pass = reader.nextInt(); - break; - default: - // Unknown/ignored key - reader.skipValue(); - break; - } - } - reader.endObject(); - - if (builder.op) { - // Update OP fields later on the main thread - op = new Post.Builder(); - op.closed(builder.closed); - op.archived(builder.archived); - op.sticky(builder.sticky); - op.replies(builder.replies); - op.images(builder.images); - op.uniqueIps(builder.uniqueIps); - } - - Post cached = cachedByNo.get(builder.id); - if (cached != null) { - // Id is known, use the cached post object. - queue.cached.add(cached); - return; - } - - SiteEndpoints endpoints = loadable.getSite().endpoints(); - if (fileId != null && fileName != null && fileExt != null) { - Map hack = new HashMap<>(2); - hack.put("tim", fileId); - hack.put("ext", fileExt); - builder.image(new PostImage.Builder() - .originalName(String.valueOf(fileId)) - .thumbnailUrl(endpoints.thumbnailUrl(builder, fileSpoiler, hack)) - .imageUrl(endpoints.imageUrl(builder, hack)) - .filename(Parser.unescapeEntities(fileName, false)) - .extension(fileExt) - .imageWidth(fileWidth) - .imageHeight(fileHeight) - .spoiler(fileSpoiler) - .size(fileSize) - .build()); - } - - if (countryCode != null && countryName != null) { - Map arg = new HashMap<>(1); - arg.put("country_code", countryCode); - HttpUrl countryUrl = endpoints.icon(builder, "country", arg); - builder.addHttpIcon(new PostHttpIcon(countryUrl, countryName)); - } - - if (trollCountryCode != null && countryName != null) { - Map arg = new HashMap<>(1); - arg.put("troll_country_code", trollCountryCode); - HttpUrl countryUrl = endpoints.icon(builder, "troll_country", arg); - builder.addHttpIcon(new PostHttpIcon(countryUrl, countryName)); - } - - if (since4pass != 0) { - HttpUrl iconUrl = endpoints.icon(builder, "since4pass", null); - builder.addHttpIcon(new PostHttpIcon(iconUrl, String.valueOf(since4pass))); - } - - queue.toParse.add(builder); - } - - private static class ProcessingQueue { - public List cached = new ArrayList<>(); - public List toParse = new ArrayList<>(); - } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/common/FutabaChanReader.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/FutabaChanReader.java new file mode 100644 index 00000000..0814fa12 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/FutabaChanReader.java @@ -0,0 +1,242 @@ +package org.floens.chan.core.site.common; + + +import android.util.JsonReader; + +import org.floens.chan.core.model.Post; +import org.floens.chan.core.model.PostHttpIcon; +import org.floens.chan.core.model.PostImage; +import org.floens.chan.core.site.SiteEndpoints; +import org.jsoup.parser.Parser; + +import java.util.HashMap; +import java.util.Map; + +import okhttp3.HttpUrl; + +public class FutabaChanReader implements ChanReader { + @Override + public void loadThread(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception { + reader.beginObject(); + // Page object + while (reader.hasNext()) { + String key = reader.nextName(); + if (key.equals("posts")) { + reader.beginArray(); + // Thread array + while (reader.hasNext()) { + // Thread object + readPostObject(reader, queue); + } + reader.endArray(); + } else { + reader.skipValue(); + } + } + reader.endObject(); + } + + @Override + public void loadCatalog(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception { + reader.beginArray(); // Array of pages + + while (reader.hasNext()) { + reader.beginObject(); // Page object + + while (reader.hasNext()) { + if (reader.nextName().equals("threads")) { + reader.beginArray(); // Threads array + + while (reader.hasNext()) { + readPostObject(reader, queue); + } + + reader.endArray(); + } else { + reader.skipValue(); + } + } + + reader.endObject(); + } + + reader.endArray(); + } + + @Override + public void readPostObject(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception { + Post.Builder builder = new Post.Builder(); + builder.board(queue.getLoadable().board); + + // File + String fileId = null; + String fileExt = null; + int fileWidth = 0; + int fileHeight = 0; + long fileSize = 0; + boolean fileSpoiler = false; + String fileName = null; + + // Country flag + String countryCode = null; + String trollCountryCode = null; + String countryName = null; + + // 4chan pass leaf + int since4pass = 0; + + reader.beginObject(); + while (reader.hasNext()) { + String key = reader.nextName(); + + switch (key) { + case "no": + builder.id(reader.nextInt()); + break; + /*case "now": + post.date = reader.nextString(); + break;*/ + case "sub": + builder.subject(reader.nextString()); + break; + case "name": + builder.name(reader.nextString()); + break; + case "com": + builder.comment(reader.nextString()); + break; + case "tim": + fileId = reader.nextString(); + break; + case "time": + builder.setUnixTimestampSeconds(reader.nextLong()); + break; + case "ext": + fileExt = reader.nextString().replace(".", ""); + break; + case "w": + fileWidth = reader.nextInt(); + break; + case "h": + fileHeight = reader.nextInt(); + break; + case "fsize": + fileSize = reader.nextLong(); + break; + case "filename": + fileName = reader.nextString(); + break; + case "trip": + builder.tripcode(reader.nextString()); + break; + case "country": + countryCode = reader.nextString(); + break; + case "troll_country": + trollCountryCode = reader.nextString(); + break; + case "country_name": + countryName = reader.nextString(); + break; + case "spoiler": + fileSpoiler = reader.nextInt() == 1; + break; + case "resto": + int opId = reader.nextInt(); + builder.op(opId == 0); + builder.opId(opId); + break; + case "sticky": + builder.sticky(reader.nextInt() == 1); + break; + case "closed": + builder.closed(reader.nextInt() == 1); + break; + case "archived": + builder.archived(reader.nextInt() == 1); + break; + case "replies": + builder.replies(reader.nextInt()); + break; + case "images": + builder.images(reader.nextInt()); + break; + case "unique_ips": + builder.uniqueIps(reader.nextInt()); + break; + case "id": + builder.posterId(reader.nextString()); + break; + case "capcode": + builder.moderatorCapcode(reader.nextString()); + break; + case "since4pass": + since4pass = reader.nextInt(); + break; + default: + // Unknown/ignored key + reader.skipValue(); + break; + } + } + reader.endObject(); + + if (builder.op) { + // Update OP fields later on the main thread + Post.Builder op = new Post.Builder(); + op.closed(builder.closed); + op.archived(builder.archived); + op.sticky(builder.sticky); + op.replies(builder.replies); + op.images(builder.images); + op.uniqueIps(builder.uniqueIps); + queue.setOp(op); + } + + Post cached = queue.getCachedPost(builder.id); + if (cached != null) { + // Id is known, use the cached post object. + queue.addForReuse(cached); + return; + } + + SiteEndpoints endpoints = queue.getLoadable().getSite().endpoints(); + if (fileId != null && fileName != null && fileExt != null) { + Map hack = new HashMap<>(2); + hack.put("tim", fileId); + hack.put("ext", fileExt); + builder.image(new PostImage.Builder() + .originalName(String.valueOf(fileId)) + .thumbnailUrl(endpoints.thumbnailUrl(builder, fileSpoiler, hack)) + .imageUrl(endpoints.imageUrl(builder, hack)) + .filename(Parser.unescapeEntities(fileName, false)) + .extension(fileExt) + .imageWidth(fileWidth) + .imageHeight(fileHeight) + .spoiler(fileSpoiler) + .size(fileSize) + .build()); + } + + if (countryCode != null && countryName != null) { + Map arg = new HashMap<>(1); + arg.put("country_code", countryCode); + HttpUrl countryUrl = endpoints.icon(builder, "country", arg); + builder.addHttpIcon(new PostHttpIcon(countryUrl, countryName)); + } + + if (trollCountryCode != null && countryName != null) { + Map arg = new HashMap<>(1); + arg.put("troll_country_code", trollCountryCode); + HttpUrl countryUrl = endpoints.icon(builder, "troll_country", arg); + builder.addHttpIcon(new PostHttpIcon(countryUrl, countryName)); + } + + if (since4pass != 0) { + HttpUrl iconUrl = endpoints.icon(builder, "since4pass", null); + builder.addHttpIcon(new PostHttpIcon(iconUrl, String.valueOf(since4pass))); + } + + queue.addForParse(builder); + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java index 2454c917..b0ebfb8c 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java @@ -26,8 +26,6 @@ import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; -import org.floens.chan.chan.ChanLoaderRequest; -import org.floens.chan.chan.ChanLoaderRequestParams; import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.orm.Board; @@ -41,7 +39,8 @@ import org.floens.chan.core.site.SiteBase; import org.floens.chan.core.site.SiteEndpoints; import org.floens.chan.core.site.SiteIcon; import org.floens.chan.core.site.SiteRequestModifier; -import org.floens.chan.core.site.common.ChanReaderRequest; +import org.floens.chan.core.site.common.ChanReader; +import org.floens.chan.core.site.common.FutabaChanReader; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.HttpCall; import org.floens.chan.core.site.http.HttpCallManager; @@ -403,8 +402,8 @@ public class Chan4 extends SiteBase { } @Override - public ChanLoaderRequest loaderRequest(ChanLoaderRequestParams request) { - return new ChanLoaderRequest(new ChanReaderRequest(request)); + public ChanReader chanReader() { + return new FutabaChanReader(); } @Override diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java index 0ea11daa..56a94e85 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java @@ -21,8 +21,7 @@ package org.floens.chan.core.site.sites.chan8; import android.support.annotation.Nullable; import android.webkit.WebView; -import org.floens.chan.chan.ChanLoaderRequest; -import org.floens.chan.chan.ChanLoaderRequestParams; +import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.orm.Board; import org.floens.chan.core.model.orm.Loadable; @@ -33,7 +32,8 @@ import org.floens.chan.core.site.SiteBase; import org.floens.chan.core.site.SiteEndpoints; import org.floens.chan.core.site.SiteIcon; import org.floens.chan.core.site.SiteRequestModifier; -import org.floens.chan.core.site.common.ChanReaderRequest; +import org.floens.chan.core.site.common.ChanReader; +import org.floens.chan.core.site.common.FutabaChanReader; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.HttpCall; import org.floens.chan.core.site.http.LoginRequest; @@ -45,6 +45,8 @@ import java.util.Map; import okhttp3.HttpUrl; import okhttp3.Request; +import static org.floens.chan.Chan.getGraph; + public class Chan8 extends SiteBase { public static final Resolvable RESOLVABLE = new Resolvable() { @Override @@ -218,12 +220,12 @@ public class Chan8 extends SiteBase { @Override public Board board(String code) { - return null; + return getGraph().get(BoardManager.class).getForCode(this, code); } @Override - public ChanLoaderRequest loaderRequest(ChanLoaderRequestParams request) { - return new ChanLoaderRequest(new ChanReaderRequest(request)); + public ChanReader chanReader() { + return new FutabaChanReader(); } @Override