organize actions and the parser for vichan

refactor-toolbar
Floens 8 years ago
parent c1b1e67bc6
commit 0ce246d859
  1. BIN
      Clover/app/src/main/assets/icons/8chan.png
  2. 34
      Clover/app/src/main/java/org/floens/chan/core/site/common/CommonSite.java
  3. 119
      Clover/app/src/main/java/org/floens/chan/core/site/common/vichan/VichanActions.java
  4. 32
      Clover/app/src/main/java/org/floens/chan/core/site/common/vichan/VichanCommentParser.java
  5. 67
      Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java
  6. 103
      Clover/app/src/main/java/org/floens/chan/core/site/sites/lainchan/Lainchan.java

Binary file not shown.

Before

Width:  |  Height:  |  Size: 411 B

@ -315,10 +315,10 @@ public abstract class CommonSite extends SiteBase {
} }
public static abstract class CommonEndpoints implements SiteEndpoints { public static abstract class CommonEndpoints implements SiteEndpoints {
private CommonSite commonSite; protected CommonSite site;
public CommonEndpoints(CommonSite commonSite) { public CommonEndpoints(CommonSite site) {
this.commonSite = commonSite; this.site = site;
} }
@NonNull @NonNull
@ -407,7 +407,13 @@ public abstract class CommonSite extends SiteBase {
} }
} }
public abstract class CommonActions implements SiteActions { public static abstract class CommonActions implements SiteActions {
protected CommonSite site;
public CommonActions(CommonSite site) {
this.site = site;
}
public void setupPost(Reply reply, MultipartHttpCall call) { public void setupPost(Reply reply, MultipartHttpCall call) {
} }
@ -416,8 +422,8 @@ public abstract class CommonSite extends SiteBase {
@Override @Override
public void boards(BoardsListener boardsListener) { public void boards(BoardsListener boardsListener) {
if (!staticBoards.isEmpty()) { if (!site.staticBoards.isEmpty()) {
boardsListener.onBoardsReceived(new Boards(staticBoards)); boardsListener.onBoardsReceived(new Boards(site.staticBoards));
} }
} }
@ -425,17 +431,17 @@ public abstract class CommonSite extends SiteBase {
public void post(Reply reply, PostListener postListener) { public void post(Reply reply, PostListener postListener) {
ReplyResponse replyResponse = new ReplyResponse(); ReplyResponse replyResponse = new ReplyResponse();
reply.password = Long.toHexString(secureRandom.nextLong()); reply.password = Long.toHexString(site.secureRandom.nextLong());
replyResponse.password = reply.password; replyResponse.password = reply.password;
MultipartHttpCall call = new MultipartHttpCall(CommonSite.this) { MultipartHttpCall call = new MultipartHttpCall(site) {
@Override @Override
public void process(Response response, String result) throws IOException { public void process(Response response, String result) throws IOException {
handlePost(replyResponse, response, result); handlePost(replyResponse, response, result);
} }
}; };
call.url(endpoints().reply(reply.loadable)); call.url(site.endpoints().reply(reply.loadable));
if (requirePrepare()) { if (requirePrepare()) {
Handler handler = new Handler(Looper.getMainLooper()); Handler handler = new Handler(Looper.getMainLooper());
@ -453,7 +459,7 @@ public abstract class CommonSite extends SiteBase {
} }
private void makePostCall(HttpCall call, ReplyResponse replyResponse, PostListener postListener) { private void makePostCall(HttpCall call, ReplyResponse replyResponse, PostListener postListener) {
httpCallManager.makeHttpCall(call, new HttpCall.HttpCallback<HttpCall>() { site.httpCallManager.makeHttpCall(call, new HttpCall.HttpCallback<HttpCall>() {
@Override @Override
public void onHttpSuccess(HttpCall httpCall) { public void onHttpSuccess(HttpCall httpCall) {
postListener.onPostComplete(httpCall, replyResponse); postListener.onPostComplete(httpCall, replyResponse);
@ -510,15 +516,15 @@ public abstract class CommonSite extends SiteBase {
} }
public static abstract class CommonApi implements ChanReader { public static abstract class CommonApi implements ChanReader {
private CommonSite commonSite; protected CommonSite site;
public CommonApi(CommonSite commonSite) { public CommonApi(CommonSite site) {
this.commonSite = commonSite; this.site = site;
} }
@Override @Override
public PostParser getParser() { public PostParser getParser() {
return commonSite.postParser; return site.postParser;
} }
} }

@ -0,0 +1,119 @@
/*
* Clover - 4chan browser https://github.com/Floens/Clover/
* Copyright (C) 2014 Floens
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.floens.chan.core.site.common.vichan;
import org.floens.chan.core.site.SiteAuthentication;
import org.floens.chan.core.site.common.CommonSite;
import org.floens.chan.core.site.common.MultipartHttpCall;
import org.floens.chan.core.site.http.Reply;
import org.floens.chan.core.site.http.ReplyResponse;
import org.jsoup.Jsoup;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import okhttp3.HttpUrl;
import okhttp3.Response;
import static android.text.TextUtils.isEmpty;
public class VichanActions extends CommonSite.CommonActions {
public VichanActions(CommonSite commonSite) {
super(commonSite);
}
@Override
public void setupPost(Reply reply, MultipartHttpCall call) {
call.parameter("board", reply.loadable.board.code);
if (reply.loadable.isThreadMode()) {
call.parameter("thread", String.valueOf(reply.loadable.no));
}
// Added with VichanAntispam.
// call.parameter("post", "Post");
call.parameter("password", reply.password);
call.parameter("name", reply.name);
call.parameter("email", reply.options);
if (!isEmpty(reply.subject)) {
call.parameter("subject", reply.subject);
}
call.parameter("body", reply.comment);
if (reply.file != null) {
call.fileParameter("file", reply.fileName, reply.file);
}
if (reply.spoilerImage) {
call.parameter("spoiler", "on");
}
}
@Override
public boolean requirePrepare() {
return true;
}
@Override
public void prepare(MultipartHttpCall call, Reply reply, ReplyResponse replyResponse) {
VichanAntispam antispam = new VichanAntispam(
HttpUrl.parse(site.resolvable().desktopUrl(reply.loadable, null)));
antispam.addDefaultIgnoreFields();
for (Map.Entry<String, String> e : antispam.get().entrySet()) {
call.parameter(e.getKey(), e.getValue());
}
}
@Override
public void handlePost(ReplyResponse replyResponse, Response response, String result) {
Matcher auth = Pattern.compile(".*\"captcha\": ?true.*").matcher(result);
Matcher err = Pattern.compile(".*<h1[^>]*>Error</h1>.*<h2[^>]*>(.*?)</h2>.*").matcher(result);
if (auth.find()) {
replyResponse.requireAuthentication = true;
replyResponse.errorMessage = result;
} else if (err.find()) {
replyResponse.errorMessage = Jsoup.parse(err.group(1)).body().text();
} else {
HttpUrl url = response.request().url();
Matcher m = Pattern.compile("/\\w+/\\w+/(\\d+).html").matcher(url.encodedPath());
try {
if (m.find()) {
replyResponse.threadNo = Integer.parseInt(m.group(1));
String fragment = url.encodedFragment();
if (fragment != null) {
replyResponse.postNo = Integer.parseInt(fragment);
} else {
replyResponse.postNo = replyResponse.threadNo;
}
replyResponse.posted = true;
}
} catch (NumberFormatException ignored) {
replyResponse.errorMessage = "Error posting: could not find posted thread.";
}
}
}
@Override
public SiteAuthentication postAuthenticate() {
return SiteAuthentication.fromNone();
}
}

@ -0,0 +1,32 @@
/*
* Clover - 4chan browser https://github.com/Floens/Clover/
* Copyright (C) 2014 Floens
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.floens.chan.core.site.common.vichan;
import org.floens.chan.core.site.parser.CommentParser;
import org.floens.chan.core.site.parser.StyleRule;
import java.util.regex.Pattern;
public class VichanCommentParser extends CommentParser {
public VichanCommentParser() {
addDefaultRules();
setQuotePattern(Pattern.compile(".*#(\\d+)"));
setFullQuotePattern(Pattern.compile("/(\\w+)/\\w+/(\\d+)\\.html#(\\d+)"));
rule(StyleRule.tagRule("p").cssClass("quote").color(StyleRule.Color.INLINE_QUOTE).linkify());
}
}

@ -9,22 +9,15 @@ import org.floens.chan.core.site.SiteAuthentication;
import org.floens.chan.core.site.SiteIcon; import org.floens.chan.core.site.SiteIcon;
import org.floens.chan.core.site.common.CommonSite; import org.floens.chan.core.site.common.CommonSite;
import org.floens.chan.core.site.common.MultipartHttpCall; import org.floens.chan.core.site.common.MultipartHttpCall;
import org.floens.chan.core.site.common.vichan.VichanActions;
import org.floens.chan.core.site.common.vichan.VichanApi; import org.floens.chan.core.site.common.vichan.VichanApi;
import org.floens.chan.core.site.common.vichan.VichanCommentParser;
import org.floens.chan.core.site.common.vichan.VichanEndpoints; import org.floens.chan.core.site.common.vichan.VichanEndpoints;
import org.floens.chan.core.site.http.Reply; import org.floens.chan.core.site.http.Reply;
import org.floens.chan.core.site.http.ReplyResponse;
import org.floens.chan.core.site.parser.CommentParser;
import org.floens.chan.core.site.parser.StyleRule;
import org.jsoup.Jsoup;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import okhttp3.Response;
import static android.text.TextUtils.isEmpty;
public class Chan8 extends CommonSite { public class Chan8 extends CommonSite {
public static final CommonSiteUrlHandler URL_HANDLER = new CommonSiteUrlHandler() { public static final CommonSiteUrlHandler URL_HANDLER = new CommonSiteUrlHandler() {
@ -100,60 +93,24 @@ public class Chan8 extends CommonSite {
} }
}); });
setActions(new CommonActions() { setActions(new VichanActions(this) {
@Override @Override
public void setupPost(Reply reply, MultipartHttpCall call) { public void setupPost(Reply reply, MultipartHttpCall call) {
call.parameter("board", reply.loadable.board.code); super.setupPost(reply, call);
if (reply.loadable.isThreadMode()) { if (reply.loadable.isThreadMode()) {
// "thread" is already added in VichanActions.
call.parameter("post", "New Reply"); call.parameter("post", "New Reply");
call.parameter("thread", String.valueOf(reply.loadable.no));
} else { } else {
call.parameter("post", "New Thread"); call.parameter("post", "New Thread");
call.parameter("page", "1"); call.parameter("page", "1");
} }
call.parameter("pwd", reply.password);
call.parameter("name", reply.name);
call.parameter("email", reply.options);
if (!reply.loadable.isThreadMode() && !isEmpty(reply.subject)) {
call.parameter("subject", reply.subject);
}
call.parameter("body", reply.comment);
if (reply.file != null) {
call.fileParameter("file", reply.fileName, reply.file);
}
if (reply.spoilerImage) {
call.parameter("spoiler", "on");
}
} }
@Override @Override
public void handlePost(ReplyResponse replyResponse, Response response, String result) { public boolean requirePrepare() {
Matcher auth = Pattern.compile(".*\"captcha\": ?true.*").matcher(result); // We don't need to check the antispam fields for 8chan.
Matcher err = Pattern.compile(".*<h1>Error</h1>.*<h2[^>]*>(.*?)</h2>.*").matcher(result); return false;
if (auth.find()) {
replyResponse.requireAuthentication = true;
replyResponse.errorMessage = result;
} else if (err.find()) {
replyResponse.errorMessage = Jsoup.parse(err.group(1)).body().text();
} else {
HttpUrl url = response.request().url();
Matcher m = Pattern.compile("/\\w+/\\w+/(\\d+).html").matcher(url.encodedPath());
try {
if (m.find()) {
replyResponse.threadNo = Integer.parseInt(m.group(1));
replyResponse.postNo = Integer.parseInt(url.encodedFragment());
replyResponse.posted = true;
}
} catch (NumberFormatException ignored) {
replyResponse.errorMessage = "Error posting: could not find posted thread.";
}
}
} }
@Override @Override
@ -166,12 +123,6 @@ public class Chan8 extends CommonSite {
setApi(new VichanApi(this)); setApi(new VichanApi(this));
CommentParser commentParser = new CommentParser(); setParser(new VichanCommentParser());
commentParser.addDefaultRules();
commentParser.setQuotePattern(Pattern.compile(".*#(\\d+)"));
commentParser.setFullQuotePattern(Pattern.compile("/(\\w+)/\\w+/(\\d+)\\.html#(\\d+)"));
commentParser.rule(StyleRule.tagRule("p").cssClass("quote").color(StyleRule.Color.INLINE_QUOTE).linkify());
setParser(commentParser);
} }
} }

@ -23,27 +23,14 @@ import org.floens.chan.core.model.Post;
import org.floens.chan.core.model.orm.Board; import org.floens.chan.core.model.orm.Board;
import org.floens.chan.core.model.orm.Loadable; import org.floens.chan.core.model.orm.Loadable;
import org.floens.chan.core.site.Site; import org.floens.chan.core.site.Site;
import org.floens.chan.core.site.SiteAuthentication;
import org.floens.chan.core.site.SiteIcon; import org.floens.chan.core.site.SiteIcon;
import org.floens.chan.core.site.common.CommonSite; import org.floens.chan.core.site.common.CommonSite;
import org.floens.chan.core.site.common.MultipartHttpCall; import org.floens.chan.core.site.common.vichan.VichanActions;
import org.floens.chan.core.site.common.vichan.VichanAntispam;
import org.floens.chan.core.site.common.vichan.VichanApi; import org.floens.chan.core.site.common.vichan.VichanApi;
import org.floens.chan.core.site.common.vichan.VichanCommentParser;
import org.floens.chan.core.site.common.vichan.VichanEndpoints; import org.floens.chan.core.site.common.vichan.VichanEndpoints;
import org.floens.chan.core.site.http.Reply;
import org.floens.chan.core.site.http.ReplyResponse;
import org.floens.chan.core.site.parser.CommentParser;
import org.floens.chan.core.site.parser.StyleRule;
import org.jsoup.Jsoup;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import okhttp3.HttpUrl; import okhttp3.HttpUrl;
import okhttp3.Response;
import static android.text.TextUtils.isEmpty;
public class Lainchan extends CommonSite { public class Lainchan extends CommonSite {
public static final CommonSiteUrlHandler URL_HANDLER = new CommonSiteUrlHandler() { public static final CommonSiteUrlHandler URL_HANDLER = new CommonSiteUrlHandler() {
@ -111,90 +98,8 @@ public class Lainchan extends CommonSite {
setEndpoints(new VichanEndpoints(this, setEndpoints(new VichanEndpoints(this,
"https://lainchan.org", "https://lainchan.org",
"https://lainchan.org")); "https://lainchan.org"));
setActions(new VichanActions(this));
setActions(new CommonActions() {
@Override
public void setupPost(Reply reply, MultipartHttpCall call) {
call.parameter("board", reply.loadable.board.code);
if (reply.loadable.isThreadMode()) {
call.parameter("thread", String.valueOf(reply.loadable.no));
} else {
// call.parameter("page", "1");
}
call.parameter("password", reply.password);
call.parameter("name", reply.name);
call.parameter("email", reply.options);
if (!reply.loadable.isThreadMode() && !isEmpty(reply.subject)) {
call.parameter("subject", reply.subject);
}
call.parameter("body", reply.comment);
if (reply.file != null) {
call.fileParameter("file", reply.fileName, reply.file);
}
if (reply.spoilerImage) {
call.parameter("spoiler", "on");
}
}
@Override
public boolean requirePrepare() {
return true;
}
@Override
public void prepare(MultipartHttpCall call, Reply reply, ReplyResponse replyResponse) {
VichanAntispam antispam = new VichanAntispam(
HttpUrl.parse(resolvable().desktopUrl(reply.loadable, null)));
antispam.addDefaultIgnoreFields();
for (Map.Entry<String, String> e : antispam.get().entrySet()) {
call.parameter(e.getKey(), e.getValue());
}
}
@Override
public void handlePost(ReplyResponse replyResponse, Response response, String result) {
Matcher auth = Pattern.compile(".*\"captcha\": ?true.*").matcher(result);
Matcher err = Pattern.compile(".*<h1[^>]*>Error</h1>.*<h2[^>]*>(.*?)</h2>.*").matcher(result);
if (auth.find()) {
replyResponse.requireAuthentication = true;
replyResponse.errorMessage = result;
} else if (err.find()) {
replyResponse.errorMessage = Jsoup.parse(err.group(1)).body().text();
} else {
HttpUrl url = response.request().url();
Matcher m = Pattern.compile("/\\w+/\\w+/(\\d+).html").matcher(url.encodedPath());
try {
if (m.find()) {
replyResponse.threadNo = Integer.parseInt(m.group(1));
replyResponse.postNo = Integer.parseInt(url.encodedFragment());
replyResponse.posted = true;
}
} catch (NumberFormatException ignored) {
replyResponse.errorMessage = "Error posting: could not find posted thread.";
}
}
}
@Override
public SiteAuthentication postAuthenticate() {
return SiteAuthentication.fromNone();
}
});
setApi(new VichanApi(this)); setApi(new VichanApi(this));
setParser(new VichanCommentParser());
CommentParser commentParser = new CommentParser();
commentParser.addDefaultRules();
commentParser.setQuotePattern(Pattern.compile(".*#(\\d+)"));
commentParser.setFullQuotePattern(Pattern.compile("/(\\w+)/\\w+/(\\d+)\\.html#(\\d+)"));
commentParser.rule(StyleRule.tagRule("p").cssClass("quote").color(StyleRule.Color.INLINE_QUOTE).linkify());
setParser(commentParser);
} }
} }

Loading…
Cancel
Save