mirror of https://github.com/kurisufriend/Clover
commit
5fd9904ed8
@ -0,0 +1,213 @@ |
|||||||
|
package org.floens.chan.core.site.sites.dvach; |
||||||
|
|
||||||
|
import android.support.annotation.Nullable; |
||||||
|
|
||||||
|
import org.floens.chan.core.model.Post; |
||||||
|
import org.floens.chan.core.model.orm.Board; |
||||||
|
import org.floens.chan.core.model.orm.Loadable; |
||||||
|
import org.floens.chan.core.settings.OptionsSetting; |
||||||
|
import org.floens.chan.core.site.Boards; |
||||||
|
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.SiteSetting; |
||||||
|
import org.floens.chan.core.site.common.CommonReplyHttpCall; |
||||||
|
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.VichanCommentParser; |
||||||
|
import org.floens.chan.core.site.common.vichan.VichanEndpoints; |
||||||
|
import org.floens.chan.core.site.http.DeleteRequest; |
||||||
|
import org.floens.chan.core.site.http.HttpCall; |
||||||
|
import org.floens.chan.core.site.http.Reply; |
||||||
|
import org.floens.chan.core.site.sites.chan4.Chan4; |
||||||
|
import org.floens.chan.utils.Logger; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import okhttp3.HttpUrl; |
||||||
|
|
||||||
|
import static android.support.constraint.Constraints.TAG; |
||||||
|
|
||||||
|
public class Dvach extends CommonSite { |
||||||
|
public static final CommonSiteUrlHandler URL_HANDLER = new CommonSiteUrlHandler() { |
||||||
|
@Override |
||||||
|
public Class<? extends Site> getSiteClass() { |
||||||
|
return Dvach.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public HttpUrl getUrl() { |
||||||
|
return HttpUrl.parse("https:/2ch.hk"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String[] getNames() { |
||||||
|
return new String[]{"dvach", "2ch"}; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String desktopUrl(Loadable loadable, @Nullable Post post) { |
||||||
|
if (loadable.isCatalogMode()) { |
||||||
|
return getUrl().newBuilder().addPathSegment(loadable.boardCode).toString(); |
||||||
|
} else if (loadable.isThreadMode()) { |
||||||
|
return getUrl().newBuilder() |
||||||
|
.addPathSegment(loadable.boardCode).addPathSegment("res") |
||||||
|
.addPathSegment(String.valueOf(loadable.no) + ".html") |
||||||
|
.toString(); |
||||||
|
} else { |
||||||
|
return getUrl().toString(); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
static final String CAPTCHA_KEY = "6LeQYz4UAAAAAL8JCk35wHSv6cuEV5PyLhI6IxsM"; |
||||||
|
|
||||||
|
private OptionsSetting<Chan4.CaptchaType> captchaType; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void initializeSettings() { |
||||||
|
super.initializeSettings(); |
||||||
|
captchaType = new OptionsSetting<>(settingsProvider, |
||||||
|
"preference_captcha_type", |
||||||
|
Chan4.CaptchaType.class, Chan4.CaptchaType.V2JS); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<SiteSetting> settings() { |
||||||
|
return Arrays.asList( |
||||||
|
SiteSetting.forOption( |
||||||
|
captchaType, |
||||||
|
"Captcha type", |
||||||
|
Arrays.asList("Javascript", "Noscript")) |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setup() { |
||||||
|
setName("2ch.hk"); |
||||||
|
setIcon(SiteIcon.fromFavicon(HttpUrl.parse("https://2ch.hk/favicon.ico"))); |
||||||
|
setBoardsType(BoardsType.DYNAMIC); |
||||||
|
|
||||||
|
setResolvable(URL_HANDLER); |
||||||
|
|
||||||
|
setConfig(new CommonConfig() { |
||||||
|
@Override |
||||||
|
public boolean feature(Feature feature) { |
||||||
|
return feature == Feature.POSTING; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
setEndpoints(new VichanEndpoints(this, |
||||||
|
"https://2ch.hk", |
||||||
|
"https://2ch.hk") { |
||||||
|
@Override |
||||||
|
public HttpUrl imageUrl(Post.Builder post, Map<String, String> arg) { |
||||||
|
return root.builder().s(arg.get("path")).url(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public HttpUrl thumbnailUrl(Post.Builder post, boolean spoiler, Map<String, String> arg) { |
||||||
|
return root.builder().s(arg.get("thumbnail")).url(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public HttpUrl boards() { |
||||||
|
return new HttpUrl.Builder().scheme("https").host("2ch.hk").addPathSegment("boards.json").build(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public HttpUrl reply(Loadable loadable) { |
||||||
|
return new HttpUrl.Builder().scheme("https").host("2ch.hk").addPathSegment("makaba").addPathSegment("posting.fcgi").addQueryParameter("json", "1").build(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
setActions(new VichanActions(this) { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setupPost(Reply reply, MultipartHttpCall call) { |
||||||
|
super.setupPost(reply, call); |
||||||
|
|
||||||
|
if (reply.loadable.isThreadMode()) { |
||||||
|
// "thread" is already added in VichanActions.
|
||||||
|
call.parameter("post", "New Reply"); |
||||||
|
} else { |
||||||
|
call.parameter("post", "New Thread"); |
||||||
|
call.parameter("page", "1"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean requirePrepare() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void post(Reply reply, final PostListener postListener) { |
||||||
|
httpCallManager.makeHttpCall(new DvachReplyCall(Dvach.this, reply), new HttpCall.HttpCallback<CommonReplyHttpCall>() { |
||||||
|
@Override |
||||||
|
public void onHttpSuccess(CommonReplyHttpCall httpPost) { |
||||||
|
postListener.onPostComplete(httpPost, httpPost.replyResponse); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onHttpFail(CommonReplyHttpCall httpPost, Exception e) { |
||||||
|
postListener.onPostError(httpPost, e); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean postRequiresAuthentication() { |
||||||
|
return !isLoggedIn(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public SiteAuthentication postAuthenticate() { |
||||||
|
if (isLoggedIn()) { |
||||||
|
return SiteAuthentication.fromNone(); |
||||||
|
} else { |
||||||
|
switch (captchaType.get()) { |
||||||
|
case V2JS: |
||||||
|
return SiteAuthentication.fromCaptcha2(CAPTCHA_KEY, "https://2ch.hk/api/captcha/recaptcha/mobile"); |
||||||
|
case V2NOJS: |
||||||
|
return SiteAuthentication.fromCaptcha2nojs(CAPTCHA_KEY, "https://2ch.hk/api/captcha/recaptcha/mobile"); |
||||||
|
default: |
||||||
|
throw new IllegalArgumentException(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void delete(DeleteRequest deleteRequest, DeleteListener deleteListener) { |
||||||
|
super.delete(deleteRequest, deleteListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void boards(final BoardsListener listener) { |
||||||
|
requestQueue.add(new DvachBoardsRequest(Dvach.this, response -> { |
||||||
|
listener.onBoardsReceived(new Boards(response)); |
||||||
|
}, (error) -> { |
||||||
|
Logger.e(TAG, "Failed to get boards from server", error); |
||||||
|
|
||||||
|
// API fail, provide some default boards
|
||||||
|
List<Board> list = new ArrayList<>(); |
||||||
|
list.add(Board.fromSiteNameCode(Dvach.this, "бред", "b")); |
||||||
|
list.add(Board.fromSiteNameCode(Dvach.this, "Видеоигры, general, официальные треды", "vg")); |
||||||
|
list.add(Board.fromSiteNameCode(Dvach.this, "новости", "news")); |
||||||
|
list.add(Board.fromSiteNameCode(Dvach.this, "политика, новости, ольгинцы, хохлы, либерахи, рептилоиды.. oh shi", "po")); |
||||||
|
Collections.shuffle(list); |
||||||
|
listener.onBoardsReceived(new Boards(list)); |
||||||
|
})); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
setApi(new DvachApi(this)); |
||||||
|
|
||||||
|
setParser(new VichanCommentParser()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,234 @@ |
|||||||
|
package org.floens.chan.core.site.sites.dvach; |
||||||
|
|
||||||
|
import android.util.JsonReader; |
||||||
|
|
||||||
|
import org.floens.chan.core.model.Post; |
||||||
|
import org.floens.chan.core.model.PostImage; |
||||||
|
import org.floens.chan.core.site.SiteEndpoints; |
||||||
|
import org.floens.chan.core.site.common.CommonSite; |
||||||
|
import org.floens.chan.core.site.parser.ChanReaderProcessingQueue; |
||||||
|
import org.jsoup.parser.Parser; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import static org.floens.chan.core.site.SiteEndpoints.makeArgument; |
||||||
|
|
||||||
|
public class DvachApi extends CommonSite.CommonApi { |
||||||
|
DvachApi(CommonSite commonSite) { |
||||||
|
super(commonSite); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void loadThread(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception { |
||||||
|
reader.beginObject(); // Main object
|
||||||
|
|
||||||
|
while (reader.hasNext()) { |
||||||
|
|
||||||
|
if (reader.nextName().equals("threads")) { |
||||||
|
reader.beginArray(); // Threads array
|
||||||
|
|
||||||
|
while (reader.hasNext()) { |
||||||
|
reader.beginObject(); // Posts object
|
||||||
|
if (reader.nextName().equals("posts")) { |
||||||
|
reader.beginArray(); // Posts array
|
||||||
|
while (reader.hasNext()) { |
||||||
|
readPostObject(reader, queue); |
||||||
|
} |
||||||
|
reader.endArray(); |
||||||
|
} |
||||||
|
reader.endObject(); |
||||||
|
} |
||||||
|
|
||||||
|
reader.endArray(); |
||||||
|
} else { |
||||||
|
reader.skipValue(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
reader.endObject(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void loadCatalog(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception { |
||||||
|
reader.beginObject(); // Main 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(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void readPostObject(JsonReader reader, ChanReaderProcessingQueue queue) throws Exception { |
||||||
|
Post.Builder builder = new Post.Builder(); |
||||||
|
builder.board(queue.getLoadable().board); |
||||||
|
|
||||||
|
SiteEndpoints endpoints = queue.getLoadable().getSite().endpoints(); |
||||||
|
|
||||||
|
List<PostImage> files = new ArrayList<>(); |
||||||
|
|
||||||
|
reader.beginObject(); |
||||||
|
while (reader.hasNext()) { |
||||||
|
String key = reader.nextName(); |
||||||
|
|
||||||
|
switch (key) { |
||||||
|
case "name": |
||||||
|
builder.name(reader.nextString()); |
||||||
|
break; |
||||||
|
case "comment": |
||||||
|
builder.comment(reader.nextString()); |
||||||
|
break; |
||||||
|
case "timestamp": |
||||||
|
builder.setUnixTimestampSeconds(reader.nextLong()); |
||||||
|
break; |
||||||
|
case "trip": |
||||||
|
builder.tripcode(reader.nextString()); |
||||||
|
break; |
||||||
|
case "op": |
||||||
|
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 "posts_count": |
||||||
|
builder.replies(reader.nextInt() - 1); |
||||||
|
break; |
||||||
|
case "files_count": |
||||||
|
builder.images(reader.nextInt()); |
||||||
|
break; |
||||||
|
case "lasthit": |
||||||
|
builder.lastModified(reader.nextLong()); |
||||||
|
break; |
||||||
|
case "num": |
||||||
|
String num = reader.nextString(); |
||||||
|
builder.id(Integer.parseInt(num)); |
||||||
|
break; |
||||||
|
case "files": |
||||||
|
reader.beginArray(); |
||||||
|
|
||||||
|
while (reader.hasNext()) { |
||||||
|
PostImage postImage = readPostImage(reader, builder, endpoints); |
||||||
|
if (postImage != null) { |
||||||
|
files.add(postImage); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
reader.endArray(); |
||||||
|
break; |
||||||
|
default: |
||||||
|
// Unknown/ignored key
|
||||||
|
reader.skipValue(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
reader.endObject(); |
||||||
|
|
||||||
|
builder.images(files); |
||||||
|
|
||||||
|
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.imagesCount); |
||||||
|
op.uniqueIps(builder.uniqueIps); |
||||||
|
op.lastModified(builder.lastModified); |
||||||
|
queue.setOp(op); |
||||||
|
} |
||||||
|
|
||||||
|
Post cached = queue.getCachedPost(builder.id); |
||||||
|
if (cached != null) { |
||||||
|
// Id is known, use the cached post object.
|
||||||
|
queue.addForReuse(cached); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
queue.addForParse(builder); |
||||||
|
} |
||||||
|
|
||||||
|
private PostImage readPostImage(JsonReader reader, Post.Builder builder, |
||||||
|
SiteEndpoints endpoints) throws IOException { |
||||||
|
reader.beginObject(); |
||||||
|
|
||||||
|
String path = null; |
||||||
|
long fileSize = 0; |
||||||
|
String fileExt = null; |
||||||
|
int fileWidth = 0; |
||||||
|
int fileHeight = 0; |
||||||
|
String fileName = null; |
||||||
|
String thumbnail = null; |
||||||
|
|
||||||
|
while (reader.hasNext()) { |
||||||
|
switch (reader.nextName()) { |
||||||
|
case "path": |
||||||
|
path = reader.nextString(); |
||||||
|
break; |
||||||
|
case "name": |
||||||
|
fileName = reader.nextString(); |
||||||
|
break; |
||||||
|
case "size": |
||||||
|
fileSize = reader.nextLong(); |
||||||
|
break; |
||||||
|
case "width": |
||||||
|
fileWidth = reader.nextInt(); |
||||||
|
break; |
||||||
|
case "height": |
||||||
|
fileHeight = reader.nextInt(); |
||||||
|
break; |
||||||
|
case "thumbnail": |
||||||
|
thumbnail = reader.nextString(); |
||||||
|
break; |
||||||
|
default: |
||||||
|
reader.skipValue(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
reader.endObject(); |
||||||
|
|
||||||
|
if (fileName != null) { |
||||||
|
fileExt = fileName.substring(fileName.lastIndexOf('.') + 1); |
||||||
|
fileName = fileName.substring(0, fileName.lastIndexOf('.')); |
||||||
|
} |
||||||
|
|
||||||
|
if (path != null && fileName != null) { |
||||||
|
Map<String, String> args = makeArgument("path", path, "thumbnail", thumbnail); |
||||||
|
return new PostImage.Builder() |
||||||
|
.originalName(fileName) |
||||||
|
.thumbnailUrl(endpoints.thumbnailUrl(builder, false, args)) |
||||||
|
.spoilerThumbnailUrl(endpoints.thumbnailUrl(builder, true, args)) |
||||||
|
.imageUrl(endpoints.imageUrl(builder, args)) |
||||||
|
.filename(Parser.unescapeEntities(fileName, false)) |
||||||
|
.extension(fileExt) |
||||||
|
.imageWidth(fileWidth) |
||||||
|
.imageHeight(fileHeight) |
||||||
|
.size(fileSize) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,108 @@ |
|||||||
|
/* |
||||||
|
* 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.sites.dvach; |
||||||
|
|
||||||
|
import android.util.JsonReader; |
||||||
|
|
||||||
|
import com.android.volley.Response.ErrorListener; |
||||||
|
import com.android.volley.Response.Listener; |
||||||
|
|
||||||
|
import org.floens.chan.core.model.orm.Board; |
||||||
|
import org.floens.chan.core.net.JsonReaderRequest; |
||||||
|
import org.floens.chan.core.site.Site; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class DvachBoardsRequest extends JsonReaderRequest<List<Board>> { |
||||||
|
private final Site site; |
||||||
|
|
||||||
|
DvachBoardsRequest(Site site, Listener<List<Board>> listener, ErrorListener errorListener) { |
||||||
|
super(site.endpoints().boards().toString(), listener, errorListener); |
||||||
|
this.site = site; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<Board> readJson(JsonReader reader) throws Exception { |
||||||
|
List<Board> list = new ArrayList<>(); |
||||||
|
|
||||||
|
reader.beginObject(); |
||||||
|
while (reader.hasNext()) { |
||||||
|
String key = reader.nextName(); |
||||||
|
if (key.equals("boards")) { |
||||||
|
reader.beginArray(); |
||||||
|
|
||||||
|
while (reader.hasNext()) { |
||||||
|
Board board = readBoardEntry(reader); |
||||||
|
if (board != null) { |
||||||
|
list.add(board); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
reader.endArray(); |
||||||
|
} else { |
||||||
|
reader.skipValue(); |
||||||
|
} |
||||||
|
} |
||||||
|
reader.endObject(); |
||||||
|
|
||||||
|
return list; |
||||||
|
} |
||||||
|
|
||||||
|
private Board readBoardEntry(JsonReader reader) throws IOException { |
||||||
|
reader.beginObject(); |
||||||
|
|
||||||
|
Board board = new Board(); |
||||||
|
board.siteId = site.id(); |
||||||
|
board.site = site; |
||||||
|
|
||||||
|
while (reader.hasNext()) { |
||||||
|
String key = reader.nextName(); |
||||||
|
|
||||||
|
switch (key) { |
||||||
|
case "name": |
||||||
|
board.name = reader.nextString(); |
||||||
|
break; |
||||||
|
case "id": |
||||||
|
board.code = reader.nextString(); |
||||||
|
break; |
||||||
|
case "bump_limit": |
||||||
|
board.bumpLimit = reader.nextInt(); |
||||||
|
break; |
||||||
|
case "info": |
||||||
|
board.description = reader.nextString(); |
||||||
|
break; |
||||||
|
case "category": |
||||||
|
board.workSafe = !"Взрослым".equals(reader.nextString()); |
||||||
|
break; |
||||||
|
default: |
||||||
|
reader.skipValue(); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
reader.endObject(); |
||||||
|
|
||||||
|
if (!board.finish()) { |
||||||
|
// Invalid data, ignore
|
||||||
|
return null; |
||||||
|
} |
||||||
|
return board; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
/* |
||||||
|
* 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.sites.dvach; |
||||||
|
|
||||||
|
import android.text.TextUtils; |
||||||
|
|
||||||
|
import org.floens.chan.core.site.Site; |
||||||
|
import org.floens.chan.core.site.common.CommonReplyHttpCall; |
||||||
|
import org.floens.chan.core.site.http.Reply; |
||||||
|
import org.jsoup.Jsoup; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.regex.Matcher; |
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
import okhttp3.MediaType; |
||||||
|
import okhttp3.MultipartBody; |
||||||
|
import okhttp3.RequestBody; |
||||||
|
import okhttp3.Response; |
||||||
|
|
||||||
|
public class DvachReplyCall extends CommonReplyHttpCall { |
||||||
|
private static final Pattern ERROR_MESSAGE = Pattern.compile("^\\{\"Error\":-\\d+,\"Reason\":\"(.*)\""); |
||||||
|
private static final Pattern POST_MESSAGE = Pattern.compile("^\\{\"Error\":null,\"Status\":\"OK\",\"Num\":(\\d+)"); |
||||||
|
private static final Pattern THREAD_MESSAGE = Pattern.compile("^\\{\"Error\":null,\"Status\":\"Redirect\",\"Target\":(\\d+)"); |
||||||
|
private static final String PROBABLY_BANNED_TEXT = "banned"; |
||||||
|
|
||||||
|
DvachReplyCall(Site site, Reply reply) { |
||||||
|
super(site, reply); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addParameters(MultipartBody.Builder formBuilder) { |
||||||
|
formBuilder.addFormDataPart("task", "post"); |
||||||
|
formBuilder.addFormDataPart("board", reply.loadable.boardCode); |
||||||
|
formBuilder.addFormDataPart("comment", reply.comment); |
||||||
|
formBuilder.addFormDataPart("thread", String.valueOf(reply.loadable.no)); |
||||||
|
|
||||||
|
formBuilder.addFormDataPart("name", reply.name); |
||||||
|
formBuilder.addFormDataPart("email", reply.options); |
||||||
|
|
||||||
|
if (!reply.loadable.isThreadMode() && !TextUtils.isEmpty(reply.subject)) { |
||||||
|
formBuilder.addFormDataPart("subject", reply.subject); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if (reply.captchaResponse != null) { |
||||||
|
formBuilder.addFormDataPart("captcha_type", "recaptcha"); |
||||||
|
formBuilder.addFormDataPart("captcha_key", Dvach.CAPTCHA_KEY); |
||||||
|
|
||||||
|
if (reply.captchaChallenge != null) { |
||||||
|
formBuilder.addFormDataPart("recaptcha_challenge_field", reply.captchaChallenge); |
||||||
|
formBuilder.addFormDataPart("recaptcha_response_field", reply.captchaResponse); |
||||||
|
} else { |
||||||
|
formBuilder.addFormDataPart("g-recaptcha-response", reply.captchaResponse); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (reply.file != null) { |
||||||
|
formBuilder.addFormDataPart("image", reply.fileName, RequestBody.create( |
||||||
|
MediaType.parse("application/octet-stream"), reply.file |
||||||
|
)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void process(Response response, String result) throws IOException { |
||||||
|
Matcher errorMessageMatcher = ERROR_MESSAGE.matcher(result); |
||||||
|
if (errorMessageMatcher.find()) { |
||||||
|
replyResponse.errorMessage = Jsoup.parse(errorMessageMatcher.group(1)).body().text(); |
||||||
|
replyResponse.probablyBanned = replyResponse.errorMessage.contains(PROBABLY_BANNED_TEXT); |
||||||
|
} else { |
||||||
|
replyResponse.posted = true; |
||||||
|
Matcher postMessageMatcher = POST_MESSAGE.matcher(result); |
||||||
|
if (postMessageMatcher.find()) { |
||||||
|
replyResponse.postNo = Integer.parseInt(postMessageMatcher.group(1)); |
||||||
|
} else { |
||||||
|
Matcher threadMessageMatcher = THREAD_MESSAGE.matcher(result); |
||||||
|
if (threadMessageMatcher.find()) { |
||||||
|
int threadNo = Integer.parseInt(threadMessageMatcher.group(1)); |
||||||
|
replyResponse.threadNo = threadNo; |
||||||
|
replyResponse.postNo = threadNo; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue