parent
104691d8d0
commit
73619da1fb
|
@ -21,6 +21,7 @@ buildscript {
|
|||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven { url "https://jitpack.io" }
|
||||
}
|
||||
|
||||
}
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
|
||||
|
|
|
@ -7,5 +7,6 @@ include ':twidere.donate.nyanwp'
|
|||
include ':twidere.donate.nyanwp.wear'
|
||||
include ':twidere.component.nyan'
|
||||
include ':twidere.extension.twitlonger'
|
||||
include ':twidere.extension.streaming'
|
||||
include ':twidere.extension.push.xiaomi'
|
||||
include ':twidere.extension.launcher.compose'
|
|
@ -37,11 +37,15 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
apt 'com.bluelinelabs:logansquare-compiler:1.0.6'
|
||||
apt 'com.bluelinelabs:logansquare-compiler:1.1.0'
|
||||
apt 'com.hannesdorfmann.parcelableplease:processor:1.0.1'
|
||||
compile 'com.android.support:support-annotations:22.1.1'
|
||||
compile 'com.android.support:support-v4:22.1.1'
|
||||
compile 'com.bluelinelabs:logansquare:1.0.6'
|
||||
compile 'com.bluelinelabs:logansquare:1.1.0'
|
||||
compile 'org.apache.commons:commons-lang3:3.4'
|
||||
compile 'com.github.mariotaku:RestFu:6ef0913'
|
||||
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.1'
|
||||
compile 'com.fasterxml.jackson.core:jackson-databind:2.4.4'
|
||||
compile project(':twidere.component.querybuilder')
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public interface Converter {
|
||||
|
||||
Object convert(RestHttpResponse response, Type type) throws Exception;
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
public interface ErrorCallback {
|
||||
|
||||
void error(Throwable t);
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.mime.BaseTypedData;
|
||||
import org.mariotaku.simplerestapi.http.mime.TypedData;
|
||||
import org.mariotaku.simplerestapi.param.File;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public final class FileValue {
|
||||
private final File annotation;
|
||||
private final Object value;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FileValue{" +
|
||||
"annotation=" + annotation +
|
||||
", value=" + value +
|
||||
'}';
|
||||
}
|
||||
|
||||
public FileValue(File annotation, Object value) {
|
||||
this.annotation = annotation;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public TypedData body() {
|
||||
return BaseTypedData.wrap(value);
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
public interface RawCallback extends ErrorCallback {
|
||||
void result(RestHttpResponse result) throws IOException;
|
||||
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.simplerestapi;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.mime.FormTypedBody;
|
||||
import org.mariotaku.simplerestapi.http.mime.MultipartTypedBody;
|
||||
import org.mariotaku.simplerestapi.http.mime.TypedData;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/11.
|
||||
*/
|
||||
public final class RequestInfo {
|
||||
|
||||
|
||||
private String method;
|
||||
private String path;
|
||||
|
||||
private List<Pair<String, String>> queries, forms, headers;
|
||||
private List<Pair<String, TypedData>> parts;
|
||||
private Map<String, Object> extras;
|
||||
private FileValue file;
|
||||
private Body body;
|
||||
|
||||
private TypedData bodyCache;
|
||||
|
||||
public RequestInfo(String method, String path, List<Pair<String, String>> queries,
|
||||
List<Pair<String, String>> forms, List<Pair<String, String>> headers,
|
||||
List<Pair<String, TypedData>> parts, FileValue file, Body body, Map<String, Object> extras) {
|
||||
this.method = method;
|
||||
this.path = path;
|
||||
this.queries = queries;
|
||||
this.forms = forms;
|
||||
this.headers = headers;
|
||||
this.parts = parts;
|
||||
this.extras = extras;
|
||||
this.file = file;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public List<Pair<String, String>> getQueries() {
|
||||
return queries;
|
||||
}
|
||||
|
||||
public List<Pair<String, String>> getForms() {
|
||||
return forms;
|
||||
}
|
||||
|
||||
public List<Pair<String, String>> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public List<Pair<String, TypedData>> getParts() {
|
||||
return parts;
|
||||
}
|
||||
|
||||
public Map<String, Object> getExtras() {
|
||||
return extras;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TypedData getBody() {
|
||||
if (bodyCache != null) return bodyCache;
|
||||
if (body == null) return null;
|
||||
switch (body.value()) {
|
||||
case FORM: {
|
||||
bodyCache = new FormTypedBody(getForms());
|
||||
break;
|
||||
}
|
||||
case MULTIPART: {
|
||||
bodyCache = new MultipartTypedBody(getParts());
|
||||
break;
|
||||
}
|
||||
case FILE: {
|
||||
bodyCache = file.body();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bodyCache;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
RequestInfo create(RestMethodInfo methodInfo);
|
||||
}
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.Authorization;
|
||||
import org.mariotaku.simplerestapi.http.Endpoint;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpClient;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpRequest;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public class RestAPIFactory {
|
||||
|
||||
private Endpoint endpoint;
|
||||
private Authorization authorization;
|
||||
private Converter converter;
|
||||
private RestHttpClient restClient;
|
||||
private RestHttpRequest.Factory requestFactory;
|
||||
private ExceptionFactory exceptionFactory;
|
||||
private RequestInfo.Factory requestInfoFactory;
|
||||
|
||||
public void setEndpoint(Endpoint endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public void setAuthorization(Authorization authorization) {
|
||||
this.authorization = authorization;
|
||||
}
|
||||
|
||||
public void setConverter(Converter converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public void setClient(RestHttpClient restClient) {
|
||||
this.restClient = restClient;
|
||||
}
|
||||
|
||||
public void setRequestFactory(RestHttpRequest.Factory factory) {
|
||||
this.requestFactory = factory;
|
||||
}
|
||||
|
||||
public void setExceptionFactory(ExceptionFactory factory) {
|
||||
this.exceptionFactory = factory;
|
||||
}
|
||||
|
||||
public RestAPIFactory() {
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T build(Class<T> cls) {
|
||||
final ClassLoader classLoader = cls.getClassLoader();
|
||||
final Class[] interfaces = new Class[]{cls};
|
||||
return (T) Proxy.newProxyInstance(classLoader, interfaces, new RestInvocationHandler(endpoint,
|
||||
authorization, restClient, converter, requestInfoFactory, requestFactory, exceptionFactory));
|
||||
}
|
||||
|
||||
public static RestClient getRestClient(Object obj) {
|
||||
final InvocationHandler handler = Proxy.getInvocationHandler(obj);
|
||||
if (!(handler instanceof RestClient)) throw new IllegalArgumentException();
|
||||
return (RestClient) handler;
|
||||
}
|
||||
|
||||
public void setRequestInfoFactory(RequestInfo.Factory requestInfoFactory) {
|
||||
this.requestInfoFactory = requestInfoFactory;
|
||||
}
|
||||
|
||||
private static class RestInvocationHandler implements InvocationHandler, RestClient {
|
||||
private final Endpoint endpoint;
|
||||
private final Authorization authorization;
|
||||
private final Converter converter;
|
||||
private final RestHttpRequest.Factory requestFactory;
|
||||
private final ExceptionFactory exceptionFactory;
|
||||
private final RequestInfo.Factory requestInfoFactory;
|
||||
|
||||
@Override
|
||||
public Endpoint getEndpoint() {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestHttpClient getRestClient() {
|
||||
return restClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Converter getConverter() {
|
||||
return converter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authorization getAuthorization() {
|
||||
return authorization;
|
||||
}
|
||||
|
||||
private final RestHttpClient restClient;
|
||||
|
||||
public RestInvocationHandler(Endpoint endpoint, Authorization authorization,
|
||||
RestHttpClient restClient, Converter converter,
|
||||
RequestInfo.Factory requestInfoFactory, RestHttpRequest.Factory requestFactory, ExceptionFactory exceptionFactory) {
|
||||
this.endpoint = endpoint;
|
||||
this.authorization = authorization;
|
||||
this.restClient = restClient;
|
||||
this.converter = converter;
|
||||
this.requestInfoFactory = requestInfoFactory;
|
||||
this.requestFactory = requestFactory != null ? requestFactory : new RestHttpRequest.DefaultFactory();
|
||||
this.exceptionFactory = exceptionFactory != null ? exceptionFactory : new DefaultExceptionFactory();
|
||||
}
|
||||
|
||||
@SuppressWarnings("TryWithIdenticalCatches")
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
|
||||
final RestMethodInfo methodInfo = RestMethodInfo.get(method, args);
|
||||
final RequestInfo requestInfo;
|
||||
if (requestInfoFactory != null) {
|
||||
requestInfo = requestInfoFactory.create(methodInfo);
|
||||
} else {
|
||||
requestInfo = methodInfo.toRequestInfo();
|
||||
}
|
||||
final RestHttpRequest restHttpRequest = requestFactory.create(endpoint, requestInfo, authorization);
|
||||
final Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
RestHttpResponse response = null;
|
||||
try {
|
||||
response = restClient.execute(restHttpRequest);
|
||||
if (parameterTypes.length > 0) {
|
||||
final Class<?> lastParameterType = parameterTypes[parameterTypes.length - 1];
|
||||
if (RestCallback.class.isAssignableFrom(lastParameterType)) {
|
||||
final Method callbackMethod = lastParameterType.getMethod("result", Object.class);
|
||||
final RestCallback<?> callback = (RestCallback<?>) args[args.length - 1];
|
||||
final Object object = converter.convert(response, method.getGenericReturnType());
|
||||
if (callback != null) {
|
||||
callbackMethod.invoke(callback, object);
|
||||
}
|
||||
return null;
|
||||
} else if (RawCallback.class.isAssignableFrom(lastParameterType)) {
|
||||
final RawCallback callback = (RawCallback) args[args.length - 1];
|
||||
callback.result(response);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return converter.convert(response, method.getGenericReturnType());
|
||||
} catch (IOException e) {
|
||||
final Exception re = exceptionFactory.newException(e, response);
|
||||
if (parameterTypes.length > 0) {
|
||||
final Class<?> lastParameterType = parameterTypes[parameterTypes.length - 1];
|
||||
if (ErrorCallback.class.isAssignableFrom(lastParameterType)) {
|
||||
final ErrorCallback callback = (ErrorCallback) args[args.length - 1];
|
||||
if (callback != null) {
|
||||
callback.error(re);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw re;
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
Utils.closeSilently(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface ExceptionFactory {
|
||||
|
||||
Exception newException(Throwable cause, RestHttpResponse response);
|
||||
|
||||
}
|
||||
|
||||
public static final class DefaultExceptionFactory implements ExceptionFactory {
|
||||
|
||||
@Override
|
||||
public Exception newException(Throwable cause, RestHttpResponse response) {
|
||||
final RestException e = new RestException(cause);
|
||||
e.setResponse(response);
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
public interface RestCallback<T> extends ErrorCallback {
|
||||
void result(T result);
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.Authorization;
|
||||
import org.mariotaku.simplerestapi.http.Endpoint;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpClient;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/19.
|
||||
*/
|
||||
public interface RestClient {
|
||||
Endpoint getEndpoint();
|
||||
|
||||
RestHttpClient getRestClient();
|
||||
|
||||
Converter getConverter();
|
||||
|
||||
Authorization getAuthorization();
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
public class RestException extends RuntimeException {
|
||||
public RestException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public RestException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RestException() {
|
||||
}
|
||||
|
||||
public RestException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
private RestHttpResponse response;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestException{" +
|
||||
"response=" + response +
|
||||
"} " + super.toString();
|
||||
}
|
||||
|
||||
public RestHttpResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setResponse(RestHttpResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface RestMethod {
|
||||
|
||||
String value();
|
||||
|
||||
boolean hasBody() default false;
|
||||
}
|
|
@ -1,339 +0,0 @@
|
|||
package org.mariotaku.simplerestapi;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.apache.commons.lang3.NotImplementedException;
|
||||
import org.mariotaku.simplerestapi.http.ValueMap;
|
||||
import org.mariotaku.simplerestapi.http.mime.BaseTypedData;
|
||||
import org.mariotaku.simplerestapi.http.mime.TypedData;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Extra;
|
||||
import org.mariotaku.simplerestapi.param.File;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.simplerestapi.param.Header;
|
||||
import org.mariotaku.simplerestapi.param.Part;
|
||||
import org.mariotaku.simplerestapi.param.Path;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public final class RestMethodInfo {
|
||||
|
||||
private final RestMethod method;
|
||||
private final String path;
|
||||
private final Body body;
|
||||
|
||||
private final HashMap<Path, Object> paths;
|
||||
private final HashMap<Query, Object> queries;
|
||||
private final HashMap<Header, Object> headers;
|
||||
private final HashMap<Form, Object> forms;
|
||||
private final HashMap<Part, Object> parts;
|
||||
private final HashMap<Extra, Object> extras;
|
||||
private final FileValue file;
|
||||
|
||||
private ArrayList<Pair<String, String>> queriesCache, formsCache, headersCache;
|
||||
private ArrayList<Pair<String, TypedData>> partsCache;
|
||||
private Map<String, Object> extrasCache;
|
||||
private TypedData bodyCache;
|
||||
|
||||
RestMethodInfo(final RestMethod method, String path, final Body body, final HashMap<Path, Object> paths, final HashMap<Query, Object> queries,
|
||||
final HashMap<Header, Object> headers, final HashMap<Form, Object> forms, final HashMap<Part, Object> parts,
|
||||
final FileValue file, HashMap<Extra, Object> extras) {
|
||||
this.method = method;
|
||||
this.path = path;
|
||||
this.body = body;
|
||||
this.paths = paths;
|
||||
this.queries = queries;
|
||||
this.headers = headers;
|
||||
this.forms = forms;
|
||||
this.parts = parts;
|
||||
this.extras = extras;
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
static RestMethodInfo get(Method method, Object[] args) {
|
||||
RestMethod restMethod = null;
|
||||
String pathFormat = null;
|
||||
for (Annotation annotation : method.getAnnotations()) {
|
||||
final Class<?> annotationType = annotation.annotationType();
|
||||
restMethod = annotationType.getAnnotation(RestMethod.class);
|
||||
if (restMethod != null) {
|
||||
try {
|
||||
pathFormat = (String) annotationType.getMethod("value").invoke(annotation);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
final Body body = method.getAnnotation(Body.class);
|
||||
final HashMap<Path, Object> paths = new HashMap<>();
|
||||
final HashMap<Query, Object> queries = new HashMap<>();
|
||||
final HashMap<Header, Object> headers = new HashMap<>();
|
||||
final HashMap<Form, Object> forms = new HashMap<>();
|
||||
final HashMap<Part, Object> parts = new HashMap<>();
|
||||
final HashMap<Extra, Object> extras = new HashMap<>();
|
||||
FileValue file = null;
|
||||
final Annotation[][] annotations = method.getParameterAnnotations();
|
||||
for (int i = 0, j = annotations.length; i < j; i++) {
|
||||
final Path path = getAnnotation(annotations[i], Path.class);
|
||||
if (path != null) {
|
||||
paths.put(path, args[i]);
|
||||
}
|
||||
final Query query = getAnnotation(annotations[i], Query.class);
|
||||
if (query != null) {
|
||||
queries.put(query, args[i]);
|
||||
}
|
||||
final Header header = getAnnotation(annotations[i], Header.class);
|
||||
if (header != null) {
|
||||
headers.put(header, args[i]);
|
||||
}
|
||||
final Form form = getAnnotation(annotations[i], Form.class);
|
||||
if (form != null) {
|
||||
forms.put(form, args[i]);
|
||||
}
|
||||
final Part part = getAnnotation(annotations[i], Part.class);
|
||||
if (part != null) {
|
||||
parts.put(part, args[i]);
|
||||
}
|
||||
final File paramFile = getAnnotation(annotations[i], File.class);
|
||||
if (paramFile != null) {
|
||||
if (file == null) {
|
||||
file = new FileValue(paramFile, args[i]);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
final Extra extra = getAnnotation(annotations[i], Extra.class);
|
||||
if (extra != null) {
|
||||
extras.put(extra, args[i]);
|
||||
}
|
||||
}
|
||||
checkMethod(restMethod, body, forms, parts, file);
|
||||
return new RestMethodInfo(restMethod, pathFormat, body, paths, queries, headers, forms, parts, file, extras);
|
||||
}
|
||||
|
||||
private static String[] getValueMapKeys(String[] annotationValue, ValueMap valueMap) {
|
||||
return annotationValue != null && annotationValue.length > 0 ? annotationValue : valueMap.keys();
|
||||
}
|
||||
|
||||
private static void checkMethod(RestMethod restMethod, Body body, HashMap<Form, Object> forms, HashMap<Part, Object> parts, FileValue file) {
|
||||
if (restMethod == null)
|
||||
throw new NotImplementedException("Method must has annotation annotated with @RestMethod");
|
||||
if (restMethod.hasBody() && body == null) {
|
||||
throw new IllegalArgumentException("@Body required for method " + restMethod.value());
|
||||
} else if (!restMethod.hasBody() && body != null) {
|
||||
throw new IllegalArgumentException(restMethod.value() + " does not allow body");
|
||||
}
|
||||
if (body == null) return;
|
||||
switch (body.value()) {
|
||||
case FILE: {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("@File annotation is required");
|
||||
}
|
||||
if (!forms.isEmpty() || !parts.isEmpty()) {
|
||||
throw new IllegalArgumentException("Only arguments with @File annotation allowed");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MULTIPART: {
|
||||
if (!forms.isEmpty() || file != null) {
|
||||
throw new IllegalArgumentException("Only arguments with @Part annotation allowed");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FORM: {
|
||||
if (file != null || !parts.isEmpty()) {
|
||||
throw new IllegalArgumentException("Only arguments with @Form annotation allowed");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends Annotation> T getAnnotation(Annotation[] annotations, Class<T> annotationClass) {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotationClass.isAssignableFrom(annotation.annotationType())) {
|
||||
return (T) annotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Map<String, Object> getExtras() {
|
||||
if (extrasCache != null) return extrasCache;
|
||||
final Map<String, Object> map = new HashMap<>();
|
||||
for (Map.Entry<Extra, Object> entry : extras.entrySet()) {
|
||||
final Extra extra = entry.getKey();
|
||||
final Object value = entry.getValue();
|
||||
if (value instanceof ValueMap) {
|
||||
final ValueMap valueMap = (ValueMap) value;
|
||||
for (String key : getValueMapKeys(extra.value(), valueMap)) {
|
||||
if (valueMap.has(key)) {
|
||||
map.put(key, valueMap.get(key));
|
||||
}
|
||||
}
|
||||
} else if (value != null) {
|
||||
for (String key : extra.value()) {
|
||||
map.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return extrasCache = map;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Pair<String, String>> getForms() {
|
||||
if (formsCache != null) return formsCache;
|
||||
final ArrayList<Pair<String, String>> list = new ArrayList<>();
|
||||
for (Map.Entry<Form, Object> entry : forms.entrySet()) {
|
||||
final Form form = entry.getKey();
|
||||
final Object value = entry.getValue();
|
||||
if (value == null) continue;
|
||||
if (value instanceof ValueMap) {
|
||||
final ValueMap valueMap = (ValueMap) value;
|
||||
for (String key : getValueMapKeys(form.value(), valueMap)) {
|
||||
if (valueMap.has(key)) {
|
||||
list.add(Pair.create(key, String.valueOf(valueMap.get(key))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final char delimiter = form.arrayDelimiter();
|
||||
String valueString = Utils.toString(value, delimiter);
|
||||
for (String key : form.value()) {
|
||||
list.add(Pair.create(key, valueString));
|
||||
}
|
||||
}
|
||||
}
|
||||
return formsCache = list;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Pair<String, TypedData>> getParts() {
|
||||
if (partsCache != null) return partsCache;
|
||||
final ArrayList<Pair<String, TypedData>> list = new ArrayList<>();
|
||||
for (Map.Entry<Part, Object> entry : parts.entrySet()) {
|
||||
final Part part = entry.getKey();
|
||||
final String[] names = part.value();
|
||||
final Object value = entry.getValue();
|
||||
if (value instanceof TypedData) {
|
||||
list.add(Pair.create(names[0], (TypedData) value));
|
||||
} else if (value != null) {
|
||||
list.add(Pair.create(names[0], BaseTypedData.wrap(value)));
|
||||
}
|
||||
}
|
||||
return partsCache = list;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Pair<String, String>> getHeaders() {
|
||||
if (headersCache != null) return headersCache;
|
||||
final ArrayList<Pair<String, String>> list = new ArrayList<>();
|
||||
for (Map.Entry<Header, Object> entry : headers.entrySet()) {
|
||||
final Header header = entry.getKey();
|
||||
final Object value = entry.getValue();
|
||||
if (value instanceof ValueMap) {
|
||||
final ValueMap valueMap = (ValueMap) value;
|
||||
for (String key : getValueMapKeys(header.value(), valueMap)) {
|
||||
if (valueMap.has(key)) {
|
||||
list.add(Pair.create(key, String.valueOf(valueMap.get(key))));
|
||||
}
|
||||
}
|
||||
} else if (value != null) {
|
||||
for (String key : header.value()) {
|
||||
list.add(Pair.create(key, String.valueOf(value)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return headersCache = list;
|
||||
}
|
||||
|
||||
public RestMethod getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getPath() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int start, end, prevEnd = -1;
|
||||
while ((start = path.indexOf('{', prevEnd)) != -1 && (end = path.indexOf('}', start)) != -1) {
|
||||
sb.append(path.substring(prevEnd + 1, start));
|
||||
final String key = path.substring(start + 1, end);
|
||||
final String replacement = findPathReplacement(key);
|
||||
if (replacement == null)
|
||||
throw new IllegalArgumentException("Path key {" + key + "} not bound");
|
||||
sb.append(replacement);
|
||||
prevEnd = end;
|
||||
}
|
||||
sb.append(path.substring(prevEnd + 1));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Pair<String, String>> getQueries() {
|
||||
if (queriesCache != null) return queriesCache;
|
||||
final ArrayList<Pair<String, String>> list = new ArrayList<>();
|
||||
for (Map.Entry<Query, Object> entry : queries.entrySet()) {
|
||||
final Query form = entry.getKey();
|
||||
final Object value = entry.getValue();
|
||||
if (value == null) continue;
|
||||
if (value instanceof ValueMap) {
|
||||
final ValueMap valueMap = (ValueMap) value;
|
||||
for (String key : getValueMapKeys(form.value(), valueMap)) {
|
||||
if (valueMap.has(key)) {
|
||||
list.add(Pair.create(key, String.valueOf(valueMap.get(key))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final char delimiter = form.arrayDelimiter();
|
||||
String valueString = Utils.toString(value, delimiter);
|
||||
for (String key : form.value()) {
|
||||
list.add(Pair.create(key, valueString));
|
||||
}
|
||||
}
|
||||
}
|
||||
return queriesCache = list;
|
||||
}
|
||||
|
||||
private String findPathReplacement(String key) {
|
||||
for (Map.Entry<Path, Object> entry : paths.entrySet()) {
|
||||
final Path path = entry.getKey();
|
||||
if (key.equals(path.value())) {
|
||||
if (path.encoded()) {
|
||||
return String.valueOf(entry.getValue());
|
||||
} else {
|
||||
return Utils.encode(String.valueOf(entry.getValue()), "UTF-8");
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public RequestInfo toRequestInfo() {
|
||||
return new RequestInfo(getMethod().value(), getPath(), getQueries(), getForms(),
|
||||
getHeaders(), getParts(), getFile(), getBody(), getExtras());
|
||||
}
|
||||
|
||||
public RequestInfo toRequestInfo(RequestInfo.Factory factory) {
|
||||
return factory.create(this);
|
||||
}
|
||||
|
||||
public Body getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public FileValue getFile() {
|
||||
return file;
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.simplerestapi;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Array;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/4.
|
||||
*/
|
||||
public class Utils {
|
||||
public static String[] split(final String str, final String separator) {
|
||||
String[] returnValue;
|
||||
int index = str.indexOf(separator);
|
||||
if (index == -1) {
|
||||
returnValue = new String[]{str};
|
||||
} else {
|
||||
final List<String> strList = new ArrayList<>();
|
||||
int oldIndex = 0;
|
||||
while (index != -1) {
|
||||
final String subStr = str.substring(oldIndex, index);
|
||||
strList.add(subStr);
|
||||
oldIndex = index + separator.length();
|
||||
index = str.indexOf(separator, oldIndex);
|
||||
}
|
||||
if (oldIndex != str.length()) {
|
||||
strList.add(str.substring(oldIndex));
|
||||
}
|
||||
returnValue = strList.toArray(new String[strList.size()]);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public static void closeSilently(Closeable c) {
|
||||
if (c == null) return;
|
||||
try {
|
||||
c.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value string to be encoded
|
||||
* @return encoded string
|
||||
* @see <a href="http://wiki.oauth.net/TestCases">OAuth / TestCases</a>
|
||||
* @see <a
|
||||
* href="http://groups.google.com/group/oauth/browse_thread/thread/a8398d0521f4ae3d/9d79b698ab217df2?hl=en&lnk=gst&q=space+encoding#9d79b698ab217df2">Space
|
||||
* encoding - OAuth | Google Groups</a>
|
||||
* @see <a href="http://tools.ietf.org/html/rfc3986#section-2.1">RFC 3986 -
|
||||
* Uniform Resource Identifier (URI): Generic Syntax - 2.1.
|
||||
* Percent-Encoding</a>
|
||||
*/
|
||||
public static String encode(final String value, String encoding) {
|
||||
String encoded;
|
||||
try {
|
||||
encoded = URLEncoder.encode(value, encoding);
|
||||
} catch (final UnsupportedEncodingException ignore) {
|
||||
return null;
|
||||
}
|
||||
final StringBuilder buf = new StringBuilder(encoded.length());
|
||||
char focus;
|
||||
for (int i = 0; i < encoded.length(); i++) {
|
||||
focus = encoded.charAt(i);
|
||||
if (focus == '*') {
|
||||
buf.append("%2A");
|
||||
} else if (focus == '+') {
|
||||
buf.append("%20");
|
||||
} else if (focus == '%' && i + 1 < encoded.length() && encoded.charAt(i + 1) == '7'
|
||||
&& encoded.charAt(i + 2) == 'E') {
|
||||
buf.append('~');
|
||||
i += 2;
|
||||
} else {
|
||||
buf.append(focus);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public static void parseGetParameters(final String queryString, final List<Pair<String, String>> params,
|
||||
final String encoding) {
|
||||
final String[] queryStrings = split(queryString, "&");
|
||||
try {
|
||||
for (final String query : queryStrings) {
|
||||
final String[] split = split(query, "=");
|
||||
final String key = URLDecoder.decode(split[0], encoding);
|
||||
if (split.length == 2) {
|
||||
params.add(new ImmutablePair<>(key, URLDecoder.decode(split[1], encoding)));
|
||||
} else {
|
||||
params.add(new ImmutablePair<>(key, ""));
|
||||
}
|
||||
}
|
||||
} catch (final UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean copyStream(InputStream is, OutputStream os) throws IOException {
|
||||
return copyStream(is, os, 8192);
|
||||
}
|
||||
|
||||
public static boolean copyStream(InputStream is, OutputStream os, int bufferSize)
|
||||
throws IOException {
|
||||
final byte[] bytes = new byte[bufferSize];
|
||||
int count;
|
||||
while ((count = is.read(bytes, 0, bufferSize)) != -1) {
|
||||
os.write(bytes, 0, count);
|
||||
}
|
||||
os.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <T> T assertNotNull(@Nullable T obj) {
|
||||
if (obj == null) throw new NullPointerException();
|
||||
return obj;
|
||||
}
|
||||
|
||||
private static final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
char[] hexChars = new char[bytes.length * 2];
|
||||
for (int j = 0; j < bytes.length; j++) {
|
||||
int v = bytes[j] & 0xFF;
|
||||
hexChars[j * 2] = hexArray[v >>> 4];
|
||||
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
||||
}
|
||||
return new String(hexChars);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String toString(@NonNull Object value, char delimiter) {
|
||||
final Class<?> valueClass = value.getClass();
|
||||
if (valueClass.isArray()) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0, j = Array.getLength(value); i < j; i++) {
|
||||
if (i != 0) {
|
||||
sb.append(delimiter);
|
||||
}
|
||||
sb.append(Array.get(value, i));
|
||||
}
|
||||
return sb.toString();
|
||||
} else {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.simplerestapi.http;
|
||||
|
||||
import org.mariotaku.simplerestapi.RequestInfo;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/4.
|
||||
*/
|
||||
public interface Authorization {
|
||||
String getHeader(Endpoint endpoint, RequestInfo info);
|
||||
|
||||
boolean hasAuthorization();
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public enum BodyType {
|
||||
FORM, MULTIPART, FILE
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http;
|
||||
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/4.
|
||||
*/
|
||||
public final class ContentType {
|
||||
|
||||
public static final ContentType OCTET_STREAM = ContentType.parse("application/octet-stream");
|
||||
|
||||
private final String contentType;
|
||||
private final List<Pair<String, String>> parameters;
|
||||
|
||||
public ContentType(String contentType, Charset charset) {
|
||||
this(contentType, new ArrayList<Pair<String, String>>());
|
||||
addParameter("charset", charset.name());
|
||||
}
|
||||
|
||||
public ContentType(String contentType) {
|
||||
this(contentType, new ArrayList<Pair<String, String>>());
|
||||
}
|
||||
|
||||
public ContentType(String contentType, List<Pair<String, String>> parameters) {
|
||||
this.contentType = contentType;
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public boolean addParameter(String name, String value) {
|
||||
return parameters.add(Pair.create(name, value));
|
||||
}
|
||||
|
||||
public ContentType parameter(String name, String value) {
|
||||
addParameter(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String parameter(String name) {
|
||||
for (Pair<String, String> parameter : parameters) {
|
||||
if (name.equalsIgnoreCase(parameter.first)) return parameter.second;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ContentType{" +
|
||||
"contentType='" + contentType + '\'' +
|
||||
", parameters=" + parameters +
|
||||
'}';
|
||||
}
|
||||
|
||||
public Charset getCharset() {
|
||||
if (parameters == null) return null;
|
||||
final String charset = parameter("charset");
|
||||
if (charset != null) return Charset.forName(charset);
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public String toHeader() {
|
||||
final StringBuilder sb = new StringBuilder(contentType);
|
||||
for (Pair<String, String> parameter : parameters) {
|
||||
sb.append("; ");
|
||||
sb.append(parameter.first);
|
||||
sb.append("=");
|
||||
sb.append(parameter.second);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static ContentType parse(String string) {
|
||||
final List<Pair<String, String>> parameters = new ArrayList<>();
|
||||
int previousIndex = string.indexOf(';', 0);
|
||||
String contentType;
|
||||
if (previousIndex == -1) {
|
||||
contentType = string;
|
||||
} else {
|
||||
contentType = string.substring(0, previousIndex);
|
||||
}
|
||||
while (previousIndex != -1) {
|
||||
final int idx = string.indexOf(';', previousIndex + 1);
|
||||
final String[] segs;
|
||||
if (idx < 0) {
|
||||
segs = Utils.split(string.substring(previousIndex + 1, string.length()).trim(), "=");
|
||||
} else {
|
||||
segs = Utils.split(string.substring(previousIndex + 1, idx).trim(), "=");
|
||||
}
|
||||
if (segs.length == 2) {
|
||||
parameters.add(Pair.create(segs[0], segs[1]));
|
||||
}
|
||||
if (idx < 0) {
|
||||
break;
|
||||
}
|
||||
previousIndex = idx;
|
||||
}
|
||||
return new ContentType(contentType, parameters);
|
||||
}
|
||||
|
||||
public ContentType charset(Charset charset) {
|
||||
removeParameter("charset");
|
||||
return parameter("charset", charset.name());
|
||||
}
|
||||
|
||||
private void removeParameter(String name) {
|
||||
for (int i = parameters.size() - 1; i >= 0; i++) {
|
||||
if (name.equals(parameters.get(i).first)) {
|
||||
parameters.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http;
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.simplerestapi.RequestInfo;
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public class Endpoint {
|
||||
|
||||
private String url;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public Endpoint(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public static String constructUrl(String endpoint, RequestInfo requestInfo) {
|
||||
return constructUrl(endpoint, requestInfo.getPath(), requestInfo.getQueries());
|
||||
}
|
||||
|
||||
public String construct(String path, List<Pair<String, String>> queries) {
|
||||
return constructUrl(url, path, queries);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final String construct(String path, Pair<String, String>... queries) {
|
||||
return constructUrl(url, path, Arrays.asList(queries));
|
||||
}
|
||||
|
||||
public static String constructUrl(String endpoint, String path, List<Pair<String, String>> queries) {
|
||||
if (endpoint == null) throw new NullPointerException("Endpoint is null");
|
||||
final StringBuilder urlBuilder = new StringBuilder();
|
||||
if (endpoint.charAt(endpoint.length() - 1) == '/') {
|
||||
urlBuilder.append(endpoint.substring(0, endpoint.length() - 1));
|
||||
} else {
|
||||
urlBuilder.append(endpoint);
|
||||
}
|
||||
if (path != null) {
|
||||
if (path.charAt(0) != '/') {
|
||||
urlBuilder.append('/');
|
||||
}
|
||||
urlBuilder.append(path);
|
||||
}
|
||||
return constructUrl(urlBuilder.toString(), queries);
|
||||
}
|
||||
|
||||
public static String constructUrl(String url, List<Pair<String, String>> queries) {
|
||||
if (queries == null || queries.isEmpty()) return url;
|
||||
final StringBuilder urlBuilder = new StringBuilder(url);
|
||||
for (int i = 0, j = queries.size(); i < j; i++) {
|
||||
final Pair<String, String> item = queries.get(i);
|
||||
urlBuilder.append(i != 0 ? '&' : '?');
|
||||
urlBuilder.append(Utils.encode(item.first, "UTF-8"));
|
||||
urlBuilder.append('=');
|
||||
urlBuilder.append(Utils.encode(item.second, "UTF-8"));
|
||||
}
|
||||
return urlBuilder.toString();
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public static String constructUrl(String url, Pair<String, String>... queries) {
|
||||
return constructUrl(url, Arrays.asList(queries));
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
public interface RestHttpClient {
|
||||
|
||||
@NonNull
|
||||
RestHttpResponse execute(RestHttpRequest request) throws IOException;
|
||||
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.simplerestapi.RequestInfo;
|
||||
import org.mariotaku.simplerestapi.http.mime.TypedData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
public final class RestHttpRequest {
|
||||
|
||||
private final String method;
|
||||
private final String url;
|
||||
private final List<Pair<String, String>> headers;
|
||||
private final TypedData body;
|
||||
private final Object extra;
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public List<Pair<String, String>> getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
public TypedData getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public Object getExtra() {
|
||||
return extra;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RestRequest{" +
|
||||
"method='" + method + '\'' +
|
||||
", url='" + url + '\'' +
|
||||
", headers=" + headers +
|
||||
", body=" + body +
|
||||
'}';
|
||||
}
|
||||
|
||||
public RestHttpRequest(String method, String url, List<Pair<String, String>> headers, TypedData body, Object extra) {
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
this.headers = headers;
|
||||
this.body = body;
|
||||
this.extra = extra;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String method;
|
||||
private String url;
|
||||
private List<Pair<String, String>> headers;
|
||||
private TypedData body;
|
||||
private Object extra;
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
public Builder method(String method) {
|
||||
this.method = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder url(String url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder headers(List<Pair<String, String>> headers) {
|
||||
this.headers = headers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder body(TypedData body) {
|
||||
this.body = body;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder extra(Object extra) {
|
||||
this.extra = extra;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RestHttpRequest build() {
|
||||
return new RestHttpRequest(method, url, headers, body, extra);
|
||||
}
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
RestHttpRequest create(@NonNull Endpoint endpoint, @NonNull RequestInfo info, @Nullable Authorization authorization);
|
||||
}
|
||||
|
||||
|
||||
public static final class DefaultFactory implements Factory {
|
||||
|
||||
@Override
|
||||
public RestHttpRequest create(@NonNull Endpoint endpoint, @NonNull RequestInfo requestInfo, @Nullable Authorization authorization) {
|
||||
final String url = Endpoint.constructUrl(endpoint.getUrl(), requestInfo);
|
||||
final ArrayList<Pair<String, String>> headers = new ArrayList<>(requestInfo.getHeaders());
|
||||
|
||||
if (authorization != null && authorization.hasAuthorization()) {
|
||||
headers.add(Pair.create("Authorization", authorization.getHeader(endpoint, requestInfo)));
|
||||
}
|
||||
return new RestHttpRequest(requestInfo.getMethod(), url, headers, requestInfo.getBody(), null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http;
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.mime.TypedData;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
public abstract class RestHttpResponse implements Closeable {
|
||||
public abstract int getStatus();
|
||||
|
||||
public abstract List<Pair<String, String>> getHeaders();
|
||||
|
||||
public abstract TypedData getBody();
|
||||
|
||||
public String getHeader(String name) {
|
||||
if (name == null) throw new NullPointerException();
|
||||
final List<Pair<String, String>> headers = getHeaders();
|
||||
if (headers == null) return null;
|
||||
for (Pair<String, String> header : headers) {
|
||||
if (header.first.equalsIgnoreCase(name)) return header.second;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String[] getHeaders(String name) {
|
||||
if (name == null) throw new NullPointerException();
|
||||
final List<Pair<String, String>> headers = getHeaders();
|
||||
if (headers == null) return new String[0];
|
||||
final ArrayList<String> result = new ArrayList<>();
|
||||
for (Pair<String, String> header : headers) {
|
||||
if (name.equalsIgnoreCase(header.first)) {
|
||||
result.add(header.second);
|
||||
}
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the code is in [200..300), which means the request was
|
||||
* successfully received, understood, and accepted.
|
||||
*/
|
||||
public boolean isSuccessful() {
|
||||
final int status = getStatus();
|
||||
return status >= 200 && status < 300;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.simplerestapi.http;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/8.
|
||||
*/
|
||||
public class SimpleValueMap implements ValueMap {
|
||||
|
||||
private final Map<String, Object> internalMap = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public boolean has(String key) {
|
||||
return internalMap.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String key) {
|
||||
return internalMap.get(key);
|
||||
}
|
||||
|
||||
protected void put(String key, Object value) {
|
||||
internalMap.put(key, value);
|
||||
}
|
||||
|
||||
protected void remove(String key) {
|
||||
internalMap.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] keys() {
|
||||
final Set<String> keySet = internalMap.keySet();
|
||||
return keySet.toArray(new String[keySet.size()]);
|
||||
}
|
||||
|
||||
protected void copyValue(ValueMap from, String key) {
|
||||
if (from.has(key)) {
|
||||
put(key, from.get(key));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public interface ValueMap {
|
||||
|
||||
boolean has(String key);
|
||||
|
||||
Object get(String key);
|
||||
|
||||
String[] keys();
|
||||
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http.mime;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.ContentType;
|
||||
import org.mariotaku.simplerestapi.io.StreamingGZIPInputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
public class BaseTypedData implements TypedData {
|
||||
|
||||
private final ContentType contentType;
|
||||
private final long contentLength;
|
||||
private final InputStream stream;
|
||||
private final String contentEncoding;
|
||||
|
||||
public BaseTypedData(ContentType contentType, String contentEncoding, long contentLength, InputStream stream) throws IOException {
|
||||
this.contentType = contentType;
|
||||
this.contentEncoding = contentEncoding;
|
||||
this.contentLength = contentLength;
|
||||
if ("gzip".equals(contentEncoding)) {
|
||||
this.stream = new StreamingGZIPInputStream(stream);
|
||||
} else {
|
||||
this.stream = stream;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType contentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String contentEncoding() {
|
||||
return contentEncoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() {
|
||||
return contentLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BaseTypedData{" +
|
||||
"contentType=" + contentType +
|
||||
", contentLength=" + contentLength +
|
||||
", stream=" + stream +
|
||||
", contentEncoding='" + contentEncoding + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(@NonNull OutputStream os) throws IOException {
|
||||
final byte[] buffer = new byte[8192];
|
||||
for (int len; (len = stream.read(buffer)) != -1; ) {
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InputStream stream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
public static TypedData wrap(Object value) {
|
||||
if (value instanceof TypedData) {
|
||||
return (TypedData) value;
|
||||
} else if (value instanceof java.io.File) {
|
||||
return new FileTypedData((java.io.File) value);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static Reader reader(TypedData data) throws IOException {
|
||||
final ContentType contentType = data.contentType();
|
||||
final Charset charset = contentType != null ? contentType.getCharset() : null;
|
||||
return new InputStreamReader(data.stream(), charset != null ? charset : Charset.defaultCharset());
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.simplerestapi.http.mime;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
import org.mariotaku.simplerestapi.http.ContentType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/6.
|
||||
*/
|
||||
public class FileTypedData implements TypedData {
|
||||
|
||||
private long length = -1;
|
||||
private File file;
|
||||
private ContentType contentType;
|
||||
private String fileName;
|
||||
private InputStream stream;
|
||||
|
||||
public FileTypedData(File file, ContentType contentType) {
|
||||
this.file = file;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public FileTypedData(InputStream stream, String fileName, long length, ContentType contentType) {
|
||||
this.stream = stream;
|
||||
this.fileName = fileName;
|
||||
this.length = length;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public FileTypedData(File file) {
|
||||
this(file, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() {
|
||||
if (length != -1) return length;
|
||||
if (file == null) return -1;
|
||||
return length = file.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(@NonNull OutputStream os) throws IOException {
|
||||
Utils.copyStream(stream(), os);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InputStream stream() throws IOException {
|
||||
if (stream != null) return stream;
|
||||
return stream = new FileInputStream(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType contentType() {
|
||||
if (contentType == null) {
|
||||
return ContentType.OCTET_STREAM;
|
||||
}
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String contentEncoding() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String fileName() {
|
||||
if (fileName != null) return fileName;
|
||||
return fileName = file.getName();
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http.mime;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
import org.mariotaku.simplerestapi.http.ContentType;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public class FormTypedBody implements TypedData {
|
||||
|
||||
private final List<Pair<String, String>> forms;
|
||||
private final Charset charset;
|
||||
|
||||
public FormTypedBody(List<Pair<String, String>> forms) {
|
||||
this.forms = forms;
|
||||
this.charset = Charset.forName("UTF-8");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType contentType() {
|
||||
return new ContentType("application/x-www-form-urlencoded", charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String contentEncoding() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
private void toRawBytes() {
|
||||
if (bytes != null) return;
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0, j = forms.size(); i < j; i++) {
|
||||
if (i != 0) {
|
||||
sb.append('&');
|
||||
}
|
||||
final Pair<String, String> form = forms.get(i);
|
||||
sb.append(Utils.encode(form.first, charset.name()));
|
||||
sb.append('=');
|
||||
sb.append(Utils.encode(form.second, charset.name()));
|
||||
}
|
||||
bytes = sb.toString().getBytes(charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() {
|
||||
toRawBytes();
|
||||
return bytes.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(@NonNull OutputStream os) throws IOException {
|
||||
toRawBytes();
|
||||
os.write(bytes);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InputStream stream() {
|
||||
toRawBytes();
|
||||
return new ByteArrayInputStream(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// No-op
|
||||
}
|
||||
}
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.simplerestapi.http.mime;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
import org.mariotaku.simplerestapi.http.ContentType;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/5.
|
||||
*/
|
||||
public class MultipartTypedBody implements TypedData {
|
||||
private final List<Pair<String, TypedData>> parts;
|
||||
private final ContentType contentType;
|
||||
|
||||
|
||||
private static final byte[] COLONSPACE = {':', ' '};
|
||||
private static final byte[] CRLF = {'\r', '\n'};
|
||||
private static final byte[] DASHDASH = {'-', '-'};
|
||||
private final String boundary;
|
||||
|
||||
private boolean lengthSet;
|
||||
private long length;
|
||||
|
||||
public MultipartTypedBody(List<Pair<String, TypedData>> parts) {
|
||||
this.parts = parts;
|
||||
this.contentType = ContentType.parse("multipart/form-data");
|
||||
boundary = Utils.bytesToHex(UUID.randomUUID().toString().getBytes());
|
||||
contentType.addParameter("boundary", boundary);
|
||||
}
|
||||
|
||||
public MultipartTypedBody() {
|
||||
this(new ArrayList<Pair<String, TypedData>>());
|
||||
}
|
||||
|
||||
public void add(@NonNull String name, @NonNull TypedData data) {
|
||||
parts.add(Pair.create(name, data));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContentType contentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String contentEncoding() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() throws IOException {
|
||||
if (!lengthSet) {
|
||||
length = 0;
|
||||
for (Pair<String, TypedData> part : parts) {
|
||||
length += part.second.length();
|
||||
}
|
||||
lengthSet = true;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(@NonNull OutputStream os) throws IOException {
|
||||
for (Pair<String, TypedData> part : parts) {
|
||||
os.write(DASHDASH);
|
||||
os.write(boundary.getBytes());
|
||||
os.write(CRLF);
|
||||
final ContentType contentDisposition = new ContentType("form-data").parameter("name", part.first);
|
||||
final ContentType contentType = part.second.contentType();
|
||||
final long contentLength = part.second.length();
|
||||
if (part.second instanceof FileTypedData) {
|
||||
contentDisposition.addParameter("filename", ((FileTypedData) part.second).fileName());
|
||||
}
|
||||
os.write("Content-Disposition".getBytes());
|
||||
os.write(COLONSPACE);
|
||||
os.write(contentDisposition.toHeader().getBytes());
|
||||
os.write(CRLF);
|
||||
if (contentType != null) {
|
||||
os.write("Content-Type".getBytes());
|
||||
os.write(COLONSPACE);
|
||||
os.write(contentType.toHeader().getBytes());
|
||||
os.write(CRLF);
|
||||
}
|
||||
if (contentLength != -1) {
|
||||
os.write("Content-Length".getBytes());
|
||||
os.write(COLONSPACE);
|
||||
os.write(String.valueOf(contentLength).getBytes());
|
||||
os.write(CRLF);
|
||||
}
|
||||
os.write(CRLF);
|
||||
part.second.writeTo(os);
|
||||
os.write(CRLF);
|
||||
}
|
||||
os.write(DASHDASH);
|
||||
os.write(boundary.getBytes());
|
||||
os.write(DASHDASH);
|
||||
os.write(CRLF);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InputStream stream() throws IOException {
|
||||
final ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
writeTo(os);
|
||||
return new ByteArrayInputStream(os.toByteArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
for (Pair<String, TypedData> part : parts) {
|
||||
part.second.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.simplerestapi.http.mime;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
import org.mariotaku.simplerestapi.http.ContentType;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/12.
|
||||
*/
|
||||
public class StringTypedData implements TypedData {
|
||||
|
||||
private final ContentType contentType;
|
||||
private final byte[] data;
|
||||
private ByteArrayInputStream is;
|
||||
|
||||
public StringTypedData(String string, Charset charset) {
|
||||
this.contentType = ContentType.parse("text/plain").charset(charset);
|
||||
this.data = string.getBytes(charset);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ContentType contentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String contentEncoding() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long length() throws IOException {
|
||||
return data.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(@NonNull OutputStream os) throws IOException {
|
||||
os.write(data);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InputStream stream() throws IOException {
|
||||
if (is != null) return is;
|
||||
return is = new ByteArrayInputStream(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
Utils.closeSilently(is);
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.http.mime;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.ContentType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
public interface TypedData {
|
||||
@Nullable
|
||||
ContentType contentType();
|
||||
|
||||
String contentEncoding();
|
||||
|
||||
long length() throws IOException;
|
||||
|
||||
void writeTo(@NonNull OutputStream os) throws IOException;
|
||||
|
||||
@NonNull
|
||||
InputStream stream() throws IOException;
|
||||
|
||||
void close() throws IOException;
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.io;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
public final class StreamingGZIPInputStream extends GZIPInputStream {
|
||||
private final InputStream wrapped;
|
||||
|
||||
public StreamingGZIPInputStream(InputStream is) throws IOException {
|
||||
super(is);
|
||||
wrapped = is;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides behavior of GZIPInputStream which assumes we have all the data available
|
||||
* which is not true for streaming. We instead rely on the underlying stream to tell us
|
||||
* how much data is available.
|
||||
* <p/>
|
||||
* Programs should not count on this method to return the actual number
|
||||
* of bytes that could be read without blocking.
|
||||
*
|
||||
* @return - whatever the wrapped InputStream returns
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public int available() throws IOException {
|
||||
return wrapped.available();
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.method;
|
||||
|
||||
import org.mariotaku.simplerestapi.RestMethod;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@RestMethod(value = "GET", hasBody = false)
|
||||
public @interface GET {
|
||||
String METHOD = "GET";
|
||||
|
||||
String value();
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.method;
|
||||
|
||||
import org.mariotaku.simplerestapi.RestMethod;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/7.
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@RestMethod(value = "POST", hasBody = true)
|
||||
public @interface POST {
|
||||
String METHOD = "POST";
|
||||
|
||||
String value();
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.param;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Body {
|
||||
BodyType value();
|
||||
|
||||
String encoding() default "";
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.param;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Extra {
|
||||
String[] value();
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.param;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface File {
|
||||
String contentType() default "";
|
||||
|
||||
String encoding() default "";
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.param;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Form {
|
||||
String[] value() default {};
|
||||
|
||||
char arrayDelimiter() default ',';
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.param;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Header {
|
||||
String[] value();
|
||||
char arrayDelimiter() default ',';
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.param;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Part {
|
||||
String[] value();
|
||||
char arrayDelimiter() default ',';
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.param;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Path {
|
||||
String value();
|
||||
|
||||
boolean encoded() default false;
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package org.mariotaku.simplerestapi.param;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Query {
|
||||
String[] value() default {};
|
||||
char arrayDelimiter() default ',';
|
||||
}
|
|
@ -22,18 +22,17 @@ package org.mariotaku.twidere.api.twitter;
|
|||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpRequest;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.RestHttpRequest;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
import org.mariotaku.twidere.api.twitter.http.HttpResponseCode;
|
||||
import org.mariotaku.twidere.api.twitter.model.ErrorInfo;
|
||||
import org.mariotaku.twidere.api.twitter.model.RateLimitStatus;
|
||||
import org.mariotaku.twidere.api.twitter.model.TwitterResponse;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.RateLimitStatusJSONImpl;
|
||||
import org.mariotaku.twidere.api.twitter.util.InternalParseUtil;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.http.HttpResponseCode;
|
||||
import org.mariotaku.twidere.api.twitter.util.InternalParseUtil;
|
||||
|
||||
/**
|
||||
* An exception class that will be thrown when TwitterAPI calls are failed.<br>
|
||||
* In case the Twitter server returned HTTP error code, you can get the HTTP
|
||||
|
@ -84,13 +83,16 @@ public class TwitterException extends Exception implements TwitterResponse, Http
|
|||
this(message);
|
||||
setResponse(res);
|
||||
request = req;
|
||||
statusCode = res != null ? res.getStatus() : -1;
|
||||
}
|
||||
|
||||
public void setResponse(RestHttpResponse res) {
|
||||
response = res;
|
||||
if (res != null) {
|
||||
rateLimitStatus = RateLimitStatusJSONImpl.createFromResponseHeader(res);
|
||||
statusCode = res.getStatus();
|
||||
} else {
|
||||
rateLimitStatus = null;
|
||||
statusCode = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
package org.mariotaku.twidere.api.twitter;
|
||||
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Extra;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Extra;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,16 +19,15 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.http.mime.FileTypedData;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Part;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Part;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.restfu.http.mime.FileTypedData;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.MediaUploadResponse;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
public interface TwitterUpload {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.api.twitter;
|
||||
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/26.
|
||||
*/
|
||||
public interface TwitterUserStream {
|
||||
|
||||
@GET("/user.json")
|
||||
void getUserStream(UserStreamCallback callback);
|
||||
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.api.twitter;
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.mariotaku.restfu.callback.RawCallback;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.model.StatusDeletionNotice;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
import org.mariotaku.twidere.api.twitter.model.UserList;
|
||||
import org.mariotaku.twidere.api.twitter.model.Warning;
|
||||
import org.mariotaku.twidere.api.twitter.util.CRLFLineReader;
|
||||
import org.mariotaku.twidere.api.twitter.util.JSONObjectType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/26.
|
||||
*/
|
||||
public abstract class UserStreamCallback implements RawCallback {
|
||||
|
||||
private boolean disconnected;
|
||||
|
||||
@Override
|
||||
public final void result(final RestHttpResponse response) throws IOException {
|
||||
if (!response.isSuccessful()) {
|
||||
final TwitterException cause = new TwitterException();
|
||||
cause.setResponse(response);
|
||||
onException(cause);
|
||||
return;
|
||||
}
|
||||
final ObjectMapper mapper = new ObjectMapper(LoganSquare.JSON_FACTORY);
|
||||
final CRLFLineReader reader = new CRLFLineReader(new InputStreamReader(response.getBody().stream(), "UTF-8"));
|
||||
for (String line; (line = reader.readLine()) != null && !disconnected; ) {
|
||||
if (line.isEmpty()) continue;
|
||||
JsonNode rootNode = mapper.readTree(line);
|
||||
switch (JSONObjectType.determine(rootNode)) {
|
||||
case SENDER: {
|
||||
break;
|
||||
}
|
||||
case STATUS: {
|
||||
onStatus(LoganSquare.mapperFor(Status.class).parse(rootNode.traverse()));
|
||||
break;
|
||||
}
|
||||
case DIRECT_MESSAGE: {
|
||||
onDirectMessage(LoganSquare.mapperFor(DirectMessage.class).parse(rootNode.traverse()));
|
||||
break;
|
||||
}
|
||||
case DELETE: {
|
||||
break;
|
||||
}
|
||||
case LIMIT:
|
||||
break;
|
||||
case STALL_WARNING:
|
||||
break;
|
||||
case SCRUB_GEO:
|
||||
break;
|
||||
case FRIENDS:
|
||||
break;
|
||||
case FAVORITE: {
|
||||
onFavorite(parse(User.class, rootNode.get("source")),
|
||||
parse(User.class, rootNode.get("target")),
|
||||
parse(Status.class, rootNode.get("target_object")));
|
||||
break;
|
||||
}
|
||||
case UNFAVORITE:
|
||||
break;
|
||||
case FOLLOW:
|
||||
break;
|
||||
case UNFOLLOW:
|
||||
break;
|
||||
case USER_LIST_MEMBER_ADDED:
|
||||
break;
|
||||
case USER_LIST_MEMBER_DELETED:
|
||||
break;
|
||||
case USER_LIST_SUBSCRIBED:
|
||||
break;
|
||||
case USER_LIST_UNSUBSCRIBED:
|
||||
break;
|
||||
case USER_LIST_CREATED:
|
||||
break;
|
||||
case USER_LIST_UPDATED:
|
||||
break;
|
||||
case USER_LIST_DESTROYED:
|
||||
break;
|
||||
case USER_UPDATE:
|
||||
break;
|
||||
case USER_DELETE:
|
||||
break;
|
||||
case USER_SUSPEND:
|
||||
break;
|
||||
case BLOCK:
|
||||
break;
|
||||
case UNBLOCK:
|
||||
break;
|
||||
case DISCONNECTION:
|
||||
break;
|
||||
case UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
response.close();
|
||||
}
|
||||
|
||||
private static <T> T parse(final Class<T> cls, final JsonNode json) throws IOException {
|
||||
return LoganSquare.mapperFor(cls).parse(json.traverse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void error(final Throwable cause) {
|
||||
onException(cause);
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
disconnected = true;
|
||||
}
|
||||
|
||||
public abstract void onBlock(User source, User blockedUser);
|
||||
|
||||
public abstract void onDeletionNotice(long directMessageId, long userId);
|
||||
|
||||
public abstract void onDeletionNotice(StatusDeletionNotice statusDeletionNotice);
|
||||
|
||||
public abstract void onDirectMessage(DirectMessage directMessage);
|
||||
|
||||
public abstract void onException(Throwable ex);
|
||||
|
||||
public abstract void onFavorite(User source, User target, Status favoritedStatus);
|
||||
|
||||
public abstract void onFollow(User source, User followedUser);
|
||||
|
||||
public abstract void onFriendList(long[] friendIds);
|
||||
|
||||
public abstract void onScrubGeo(long userId, long upToStatusId);
|
||||
|
||||
public abstract void onStallWarning(Warning warn);
|
||||
|
||||
public abstract void onStatus(Status status);
|
||||
|
||||
public abstract void onTrackLimitationNotice(int numberOfLimitedStatuses);
|
||||
|
||||
public abstract void onUnblock(User source, User unblockedUser);
|
||||
|
||||
public abstract void onUnfavorite(User source, User target, Status unfavoritedStatus);
|
||||
|
||||
public abstract void onUserListCreation(User listOwner, UserList list);
|
||||
|
||||
public abstract void onUserListDeletion(User listOwner, UserList list);
|
||||
|
||||
public abstract void onUserListMemberAddition(User addedMember, User listOwner, UserList list);
|
||||
|
||||
public abstract void onUserListMemberDeletion(User deletedMember, User listOwner, UserList list);
|
||||
|
||||
public abstract void onUserListSubscription(User subscriber, User listOwner, UserList list);
|
||||
|
||||
public abstract void onUserListUnsubscription(User subscriber, User listOwner, UserList list);
|
||||
|
||||
public abstract void onUserListUpdate(User listOwner, UserList list);
|
||||
|
||||
public abstract void onUserProfileUpdate(User updatedUser);
|
||||
}
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
|
|
|
@ -19,17 +19,16 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
|
||||
/**
|
||||
* @author Joern Huxhorn - jhuxhorn at googlemail.com
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Friendship;
|
||||
import org.mariotaku.twidere.api.twitter.model.FriendshipUpdate;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Language;
|
||||
import org.mariotaku.twidere.api.twitter.model.RateLimitStatus;
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.PageableResponseList;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Activity;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Path;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Path;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.param.Path;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.param.Path;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
|
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.simplerestapi.param.Path;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.annotation.param.Path;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
import org.mariotaku.twidere.api.twitter.model.SavedSearch;
|
||||
|
|
|
@ -19,12 +19,11 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.QueryResult;
|
||||
import org.mariotaku.twidere.api.twitter.model.SearchQuery;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
public interface SearchResource {
|
||||
|
|
|
@ -19,10 +19,10 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.GeoLocation;
|
||||
import org.mariotaku.twidere.api.twitter.model.Location;
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.simplerestapi.param.Path;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.annotation.param.Path;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.IDs;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
|
|
|
@ -19,14 +19,14 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.api;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.BodyType;
|
||||
import org.mariotaku.simplerestapi.http.mime.FileTypedData;
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.simplerestapi.method.POST;
|
||||
import org.mariotaku.simplerestapi.param.Body;
|
||||
import org.mariotaku.simplerestapi.param.Form;
|
||||
import org.mariotaku.simplerestapi.param.Part;
|
||||
import org.mariotaku.simplerestapi.param.Query;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.POST;
|
||||
import org.mariotaku.restfu.annotation.param.Body;
|
||||
import org.mariotaku.restfu.annotation.param.Form;
|
||||
import org.mariotaku.restfu.annotation.param.Part;
|
||||
import org.mariotaku.restfu.annotation.param.Query;
|
||||
import org.mariotaku.restfu.http.BodyType;
|
||||
import org.mariotaku.restfu.http.mime.FileTypedData;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.AccountSettings;
|
||||
import org.mariotaku.twidere.api.twitter.model.Category;
|
||||
|
|
|
@ -21,9 +21,9 @@ package org.mariotaku.twidere.api.twitter.auth;
|
|||
|
||||
import android.util.Base64;
|
||||
|
||||
import org.mariotaku.simplerestapi.RequestInfo;
|
||||
import org.mariotaku.simplerestapi.http.Authorization;
|
||||
import org.mariotaku.simplerestapi.http.Endpoint;
|
||||
import org.mariotaku.restfu.RestRequestInfo;
|
||||
import org.mariotaku.restfu.http.Authorization;
|
||||
import org.mariotaku.restfu.http.Endpoint;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/19.
|
||||
|
@ -39,7 +39,7 @@ public final class BasicAuthorization implements Authorization {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(Endpoint endpoint, RequestInfo info) {
|
||||
public String getHeader(Endpoint endpoint, RestRequestInfo info) {
|
||||
if (!hasAuthorization()) return null;
|
||||
return "Basic " + Base64.encodeToString((user + ":" + password).getBytes(), Base64.NO_WRAP);
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.auth;
|
||||
|
||||
import org.mariotaku.simplerestapi.RequestInfo;
|
||||
import org.mariotaku.simplerestapi.http.Authorization;
|
||||
import org.mariotaku.simplerestapi.http.Endpoint;
|
||||
import org.mariotaku.restfu.RestRequestInfo;
|
||||
import org.mariotaku.restfu.http.Authorization;
|
||||
import org.mariotaku.restfu.http.Endpoint;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/19.
|
||||
|
@ -29,7 +29,7 @@ import org.mariotaku.simplerestapi.http.Endpoint;
|
|||
public final class EmptyAuthorization implements Authorization {
|
||||
|
||||
@Override
|
||||
public String getHeader(Endpoint endpoint, RequestInfo info) {
|
||||
public String getHeader(Endpoint endpoint, RestRequestInfo info) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,10 @@ package org.mariotaku.twidere.api.twitter.auth;
|
|||
import android.util.Base64;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.simplerestapi.RequestInfo;
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
import org.mariotaku.simplerestapi.http.Authorization;
|
||||
import org.mariotaku.simplerestapi.http.Endpoint;
|
||||
import org.mariotaku.restfu.RestRequestInfo;
|
||||
import org.mariotaku.restfu.Utils;
|
||||
import org.mariotaku.restfu.http.Authorization;
|
||||
import org.mariotaku.restfu.http.Endpoint;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.InvalidKeyException;
|
||||
|
@ -130,7 +130,7 @@ public class OAuthAuthorization implements Authorization, OAuthSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(Endpoint endpoint, RequestInfo request) {
|
||||
public String getHeader(Endpoint endpoint, RestRequestInfo request) {
|
||||
if (!(endpoint instanceof OAuthEndpoint))
|
||||
throw new IllegalArgumentException("OAuthEndpoint required");
|
||||
final OAuthEndpoint oauthEndpoint = (OAuthEndpoint) endpoint;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.auth;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.Endpoint;
|
||||
import org.mariotaku.restfu.http.Endpoint;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
|
|
|
@ -19,9 +19,10 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.auth;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
import org.mariotaku.simplerestapi.http.ValueMap;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.restfu.Utils;
|
||||
import org.mariotaku.restfu.http.ValueMap;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.ParseException;
|
||||
|
@ -63,21 +64,21 @@ public class OAuthToken implements ValueMap {
|
|||
List<Pair<String, String>> params = new ArrayList<>();
|
||||
Utils.parseGetParameters(body, params, charset.name());
|
||||
for (Pair<String, String> param : params) {
|
||||
switch (param.getKey()) {
|
||||
switch (param.first) {
|
||||
case "oauth_token": {
|
||||
oauthToken = param.getValue();
|
||||
oauthToken = param.second;
|
||||
break;
|
||||
}
|
||||
case "oauth_token_secret": {
|
||||
oauthTokenSecret = param.getValue();
|
||||
oauthTokenSecret = param.second;
|
||||
break;
|
||||
}
|
||||
case "user_id": {
|
||||
userId = Long.parseLong(param.getValue());
|
||||
userId = Long.parseLong(param.second);
|
||||
break;
|
||||
}
|
||||
case "screen_name": {
|
||||
screenName = param.getValue();
|
||||
screenName = param.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.SimpleValueMap;
|
||||
import org.mariotaku.restfu.http.SimpleValueMap;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/13.
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.bluelinelabs.logansquare.typeconverters.TypeConverter;
|
|||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.ValueMap;
|
||||
import org.mariotaku.restfu.http.ValueMap;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.GeoPoint;
|
||||
|
||||
import java.io.IOException;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.ValueMap;
|
||||
import org.mariotaku.restfu.http.ValueMap;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.SimpleValueMap;
|
||||
import org.mariotaku.restfu.http.SimpleValueMap;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/2/6.
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.SimpleValueMap;
|
||||
import org.mariotaku.restfu.http.SimpleValueMap;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/6.
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.mariotaku.twidere.api.twitter.model;
|
|||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.SimpleValueMap;
|
||||
import org.mariotaku.restfu.http.SimpleValueMap;
|
||||
|
||||
/**
|
||||
* A data class represents search query.<br>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.SimpleValueMap;
|
||||
import org.mariotaku.restfu.http.SimpleValueMap;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/6.
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/26.
|
||||
*/
|
||||
public interface StatusDeletionNotice {
|
||||
long getStatusId();
|
||||
}
|
|
@ -19,8 +19,8 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
import org.mariotaku.simplerestapi.http.SimpleValueMap;
|
||||
import org.mariotaku.restfu.Utils;
|
||||
import org.mariotaku.restfu.http.SimpleValueMap;
|
||||
|
||||
public final class StatusUpdate extends SimpleValueMap {
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
|
||||
/**
|
||||
* Super interface of Twitter Response data interfaces which indicates that rate
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.SimpleValueMap;
|
||||
import org.mariotaku.restfu.http.SimpleValueMap;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/8.
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/26.
|
||||
*/
|
||||
public interface Warning {
|
||||
}
|
|
@ -26,7 +26,7 @@ import com.bluelinelabs.logansquare.typeconverters.TypeConverter;
|
|||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.RateLimitStatus;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
|
|
|
@ -22,7 +22,7 @@ package org.mariotaku.twidere.api.twitter.model.impl;
|
|||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.RateLimitStatus;
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model.impl;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
|
@ -17,24 +17,19 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.extension.streaming.util;
|
||||
package org.mariotaku.twidere.api.twitter.model.impl;
|
||||
|
||||
import android.content.Context;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.http.HttpClient;
|
||||
import org.mariotaku.twidere.api.twitter.http.HttpClientConfiguration;
|
||||
import org.mariotaku.twidere.api.twitter.http.HttpClientFactory;
|
||||
import org.mariotaku.twidere.api.twitter.model.StatusDeletionNotice;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/1/22.
|
||||
* Created by mariotaku on 15/5/26.
|
||||
*/
|
||||
public class OkHttpClientFactory implements HttpClientFactory {
|
||||
public OkHttpClientFactory(Context context) {
|
||||
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
public class StatusDeletionNoticeImpl implements StatusDeletionNotice {
|
||||
@Override
|
||||
public HttpClient getInstance(HttpClientConfiguration conf) {
|
||||
return new OkHttpClientImpl(conf);
|
||||
public long getStatusId() {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.model.impl;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.RateLimitStatus;
|
||||
import org.mariotaku.twidere.api.twitter.model.TwitterResponse;
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.api.twitter.model.impl;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.Warning;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/26.
|
||||
*/
|
||||
@JsonObject
|
||||
public class WarningImpl implements Warning {
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.api.twitter.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
||||
/**
|
||||
* CRLFLineReader implements a readLine() method that requires
|
||||
* exactly CRLF to terminate an input line.
|
||||
* This is required for IMAP, which allows bare CR and LF.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public final class CRLFLineReader extends BufferedReader
|
||||
{
|
||||
private static final char LF = '\n';
|
||||
private static final char CR = '\r';
|
||||
|
||||
/**
|
||||
* Creates a CRLFLineReader that wraps an existing Reader
|
||||
* input source.
|
||||
* @param reader The Reader input source.
|
||||
*/
|
||||
public CRLFLineReader(Reader reader)
|
||||
{
|
||||
super(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a line of text.
|
||||
* A line is considered to be terminated by carriage return followed immediately by a linefeed.
|
||||
* This contrasts with BufferedReader which also allows other combinations.
|
||||
* @since 3.0
|
||||
*/
|
||||
@Override
|
||||
public String readLine() throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int intch;
|
||||
boolean prevWasCR = false;
|
||||
synchronized(lock) { // make thread-safe (hopefully!)
|
||||
while((intch = read()) != -1)
|
||||
{
|
||||
if (prevWasCR && intch == LF) {
|
||||
return sb.substring(0, sb.length()-1);
|
||||
}
|
||||
if (intch == CR) {
|
||||
prevWasCR = true;
|
||||
} else {
|
||||
prevWasCR = false;
|
||||
}
|
||||
sb.append((char) intch);
|
||||
}
|
||||
}
|
||||
String string = sb.toString();
|
||||
if (string.length() == 0) { // immediate EOF
|
||||
return null;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
package org.mariotaku.twidere.api.twitter.util;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
import org.mariotaku.twidere.api.twitter.model.TwitterResponse;
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.api.twitter.util;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
/**
|
||||
* @author Dan Checkoway - dcheckoway at gmail.com
|
||||
* @since Twitter4J 2.1.9
|
||||
*/
|
||||
public final class JSONObjectType {
|
||||
public enum Type {
|
||||
SENDER,
|
||||
STATUS,
|
||||
DIRECT_MESSAGE,
|
||||
DELETE,
|
||||
LIMIT,
|
||||
STALL_WARNING,
|
||||
SCRUB_GEO,
|
||||
FRIENDS,
|
||||
FAVORITE,
|
||||
UNFAVORITE,
|
||||
FOLLOW,
|
||||
UNFOLLOW,
|
||||
USER_LIST_MEMBER_ADDED,
|
||||
USER_LIST_MEMBER_DELETED,
|
||||
USER_LIST_SUBSCRIBED,
|
||||
USER_LIST_UNSUBSCRIBED,
|
||||
USER_LIST_CREATED,
|
||||
USER_LIST_UPDATED,
|
||||
USER_LIST_DESTROYED,
|
||||
USER_UPDATE,
|
||||
USER_DELETE,
|
||||
USER_SUSPEND,
|
||||
BLOCK,
|
||||
UNBLOCK,
|
||||
DISCONNECTION,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the respective object type for a given JSONObject. This
|
||||
* method inspects the object to figure out what type of object it
|
||||
* represents. This is useful when processing JSON events of mixed type
|
||||
* from a stream, in which case you may need to know what type of object
|
||||
* to construct, or how to handle the event properly.
|
||||
*
|
||||
* @param json the JSONObject whose type should be determined
|
||||
* @return the determined JSONObjectType, or null if not recognized
|
||||
*/
|
||||
public static Type determine(JsonNode json) {
|
||||
// This code originally lived in AbstractStreamImplementation.
|
||||
// I've moved it in here to expose it as a public encapsulation of
|
||||
// the object type determination logic.
|
||||
if (json.hasNonNull("sender")) {
|
||||
return Type.SENDER;
|
||||
} else if (json.hasNonNull("text")) {
|
||||
return Type.STATUS;
|
||||
} else if (json.hasNonNull("direct_message")) {
|
||||
return Type.DIRECT_MESSAGE;
|
||||
} else if (json.hasNonNull("delete")) {
|
||||
return Type.DELETE;
|
||||
} else if (json.hasNonNull("limit")) {
|
||||
return Type.LIMIT;
|
||||
} else if (json.hasNonNull("warning")) {
|
||||
return Type.STALL_WARNING;
|
||||
} else if (json.hasNonNull("scrub_geo")) {
|
||||
return Type.SCRUB_GEO;
|
||||
} else if (json.hasNonNull("friends")) {
|
||||
return Type.FRIENDS;
|
||||
} else if (json.hasNonNull("event")) {
|
||||
String event;
|
||||
event = json.get("event").asText("event");
|
||||
if ("favorite".equals(event)) {
|
||||
return Type.FAVORITE;
|
||||
} else if ("unfavorite".equals(event)) {
|
||||
return Type.UNFAVORITE;
|
||||
} else if ("follow".equals(event)) {
|
||||
return Type.FOLLOW;
|
||||
} else if ("unfollow".equals(event)) {
|
||||
return Type.UNFOLLOW;
|
||||
} else if (event.startsWith("list")) {
|
||||
if ("list_member_added".equals(event)) {
|
||||
return Type.USER_LIST_MEMBER_ADDED;
|
||||
} else if ("list_member_removed".equals(event)) {
|
||||
return Type.USER_LIST_MEMBER_DELETED;
|
||||
} else if ("list_user_subscribed".equals(event)) {
|
||||
return Type.USER_LIST_SUBSCRIBED;
|
||||
} else if ("list_user_unsubscribed".equals(event)) {
|
||||
return Type.USER_LIST_UNSUBSCRIBED;
|
||||
} else if ("list_created".equals(event)) {
|
||||
return Type.USER_LIST_CREATED;
|
||||
} else if ("list_updated".equals(event)) {
|
||||
return Type.USER_LIST_UPDATED;
|
||||
} else if ("list_destroyed".equals(event)) {
|
||||
return Type.USER_LIST_DESTROYED;
|
||||
}
|
||||
} else if ("user_update".equals(event)) {
|
||||
return Type.USER_UPDATE;
|
||||
} else if ("user_delete".equals(event)) {
|
||||
return Type.USER_DELETE;
|
||||
} else if ("user_suspend".equals(event)) {
|
||||
return Type.USER_SUSPEND;
|
||||
} else if ("block".equals(event)) {
|
||||
return Type.BLOCK;
|
||||
} else if ("unblock".equals(event)) {
|
||||
return Type.UNBLOCK;
|
||||
}
|
||||
} else if (json.hasNonNull("disconnect")) {
|
||||
return Type.DISCONNECTION;
|
||||
}
|
||||
return Type.UNKNOWN;
|
||||
}
|
||||
}
|
|
@ -25,11 +25,11 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
|||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
import org.mariotaku.simplerestapi.Converter;
|
||||
import org.mariotaku.simplerestapi.Utils;
|
||||
import org.mariotaku.simplerestapi.http.ContentType;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.simplerestapi.http.mime.TypedData;
|
||||
import org.mariotaku.restfu.Converter;
|
||||
import org.mariotaku.restfu.Utils;
|
||||
import org.mariotaku.restfu.http.ContentType;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.mime.TypedData;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
|
||||
import org.mariotaku.twidere.api.twitter.model.AccountSettings;
|
||||
|
@ -52,6 +52,7 @@ import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
|||
import org.mariotaku.twidere.api.twitter.model.SavedSearch;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.model.StatusActivitySummary;
|
||||
import org.mariotaku.twidere.api.twitter.model.StatusDeletionNotice;
|
||||
import org.mariotaku.twidere.api.twitter.model.TimeZone;
|
||||
import org.mariotaku.twidere.api.twitter.model.TranslationResult;
|
||||
import org.mariotaku.twidere.api.twitter.model.Trend;
|
||||
|
@ -60,6 +61,7 @@ import org.mariotaku.twidere.api.twitter.model.UrlEntity;
|
|||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
import org.mariotaku.twidere.api.twitter.model.UserList;
|
||||
import org.mariotaku.twidere.api.twitter.model.UserMentionEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.Warning;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.AccountSettingsImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.ActivityImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.CardEntityImpl;
|
||||
|
@ -80,6 +82,7 @@ import org.mariotaku.twidere.api.twitter.model.impl.RelationshipWrapper;
|
|||
import org.mariotaku.twidere.api.twitter.model.impl.ResponseListImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.SavedSearchImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.StatusActivitySummaryImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.StatusDeletionNoticeImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.StatusImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.TimeZoneImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.TranslationResultImpl;
|
||||
|
@ -91,6 +94,7 @@ import org.mariotaku.twidere.api.twitter.model.impl.UrlEntityImpl;
|
|||
import org.mariotaku.twidere.api.twitter.model.impl.UserImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.UserListImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.UserMentionEntityImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.WarningImpl;
|
||||
import org.mariotaku.twidere.api.twitter.model.impl.Wrapper;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -145,6 +149,8 @@ public class TwitterConverter implements Converter {
|
|||
TypeConverterMapper.register(AccountSettings.class, AccountSettingsImpl.class);
|
||||
TypeConverterMapper.register(IDs.class, IDsImpl.class, IDsImpl.MAPPER);
|
||||
TypeConverterMapper.register(Activity.class, ActivityImpl.class, ActivityImpl.MAPPER);
|
||||
TypeConverterMapper.register(Warning.class, WarningImpl.class);
|
||||
TypeConverterMapper.register(StatusDeletionNotice.class, StatusDeletionNoticeImpl.class);
|
||||
|
||||
LoganSquare.registerTypeConverter(Indices.class, Indices.CONVERTER);
|
||||
LoganSquare.registerTypeConverter(GeoLocation.class, GeoLocation.CONVERTER);
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.mariotaku.twidere.constant;
|
|||
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.annotation.Preference;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
import org.mariotaku.twidere.model.ParcelableCredentials;
|
||||
|
||||
import static org.mariotaku.twidere.annotation.Preference.Type.BOOLEAN;
|
||||
import static org.mariotaku.twidere.annotation.Preference.Type.INT;
|
||||
|
@ -240,7 +240,7 @@ public interface SharedPreferenceConstants {
|
|||
String KEY_SAME_OAUTH_SIGNING_URL = "same_oauth_signing_url";
|
||||
@Preference(type = BOOLEAN, hasDefault = true, defaultBoolean = false)
|
||||
String KEY_NO_VERSION_SUFFIX = "no_version_suffix";
|
||||
@Preference(type = INT, hasDefault = true, defaultInt = Accounts.AUTH_TYPE_OAUTH)
|
||||
@Preference(type = INT, hasDefault = true, defaultInt = ParcelableCredentials.AUTH_TYPE_OAUTH)
|
||||
String KEY_AUTH_TYPE = "auth_type";
|
||||
@Preference(type = STRING, hasDefault = true, defaultString = TwidereConstants.TWITTER_CONSUMER_KEY)
|
||||
String KEY_CONSUMER_KEY = "consumer_key";
|
||||
|
|
|
@ -29,6 +29,8 @@ import android.support.annotation.Nullable;
|
|||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
|
||||
|
||||
import org.mariotaku.querybuilder.Columns.Column;
|
||||
import org.mariotaku.querybuilder.Expression;
|
||||
|
@ -41,6 +43,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@ParcelablePlease(allFields = false)
|
||||
@JsonObject
|
||||
public class ParcelableAccount implements Parcelable {
|
||||
|
||||
|
@ -57,28 +60,35 @@ public class ParcelableAccount implements Parcelable {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "screen_name")
|
||||
public String screen_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "name")
|
||||
public String name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "profile_image_url")
|
||||
public String profile_image_url;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "profile_banner_url")
|
||||
public String profile_banner_url;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "account_id")
|
||||
public long account_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "color")
|
||||
public int color;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_activated")
|
||||
public boolean is_activated;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_dummy")
|
||||
public boolean is_dummy;
|
||||
|
||||
|
@ -95,14 +105,7 @@ public class ParcelableAccount implements Parcelable {
|
|||
}
|
||||
|
||||
public ParcelableAccount(final Parcel source) {
|
||||
is_dummy = source.readInt() == 1;
|
||||
is_activated = source.readInt() == 1;
|
||||
account_id = source.readLong();
|
||||
name = source.readString();
|
||||
screen_name = source.readString();
|
||||
profile_image_url = source.readString();
|
||||
profile_banner_url = source.readString();
|
||||
color = source.readInt();
|
||||
ParcelableAccountParcelablePlease.readFromParcel(this, source);
|
||||
}
|
||||
|
||||
public ParcelableAccount() {
|
||||
|
@ -116,14 +119,7 @@ public class ParcelableAccount implements Parcelable {
|
|||
|
||||
@Override
|
||||
public void writeToParcel(final Parcel out, final int flags) {
|
||||
out.writeInt(is_dummy ? 1 : 0);
|
||||
out.writeInt(is_activated ? 1 : 0);
|
||||
out.writeLong(account_id);
|
||||
out.writeString(name);
|
||||
out.writeString(screen_name);
|
||||
out.writeString(profile_image_url);
|
||||
out.writeString(profile_banner_url);
|
||||
out.writeInt(color);
|
||||
ParcelableAccountParcelablePlease.writeToParcel(this, out, flags);
|
||||
}
|
||||
|
||||
public static ParcelableAccount dummyAccount() {
|
||||
|
@ -287,109 +283,6 @@ public class ParcelableAccount implements Parcelable {
|
|||
+ ", is_activated=" + is_activated + ", is_dummy=" + is_dummy + "}";
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
public static class ParcelableCredentials extends ParcelableAccount {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableCredentials> CREATOR = new Parcelable.Creator<ParcelableCredentials>() {
|
||||
|
||||
@Override
|
||||
public ParcelableCredentials createFromParcel(final Parcel in) {
|
||||
return new ParcelableCredentials(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableCredentials[] newArray(final int size) {
|
||||
return new ParcelableCredentials[size];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@JsonField(name = "auth_type")
|
||||
public int auth_type;
|
||||
|
||||
@JsonField(name = "consumer_key")
|
||||
public String consumer_key;
|
||||
|
||||
@JsonField(name = "consumer_secret")
|
||||
public String consumer_secret;
|
||||
|
||||
@JsonField(name = "basic_auth_username")
|
||||
public String basic_auth_username;
|
||||
|
||||
@JsonField(name = "basic_auth_password")
|
||||
public String basic_auth_password;
|
||||
|
||||
@JsonField(name = "oauth_token")
|
||||
public String oauth_token;
|
||||
|
||||
@JsonField(name = "oauth_token_secret")
|
||||
public String oauth_token_secret;
|
||||
|
||||
@JsonField(name = "api_url_format")
|
||||
public String api_url_format;
|
||||
|
||||
@JsonField(name = "same_oauth_signing_url")
|
||||
public boolean same_oauth_signing_url;
|
||||
|
||||
@JsonField(name = "no_version_suffix")
|
||||
public boolean no_version_suffix;
|
||||
|
||||
public ParcelableCredentials() {
|
||||
}
|
||||
|
||||
public ParcelableCredentials(final Cursor cursor, final Indices indices) {
|
||||
super(cursor, indices);
|
||||
auth_type = cursor.getInt(indices.auth_type);
|
||||
consumer_key = cursor.getString(indices.consumer_key);
|
||||
consumer_secret = cursor.getString(indices.consumer_secret);
|
||||
basic_auth_username = cursor.getString(indices.basic_auth_username);
|
||||
basic_auth_password = cursor.getString(indices.basic_auth_password);
|
||||
oauth_token = cursor.getString(indices.oauth_token);
|
||||
oauth_token_secret = cursor.getString(indices.oauth_token_secret);
|
||||
api_url_format = cursor.getString(indices.api_url_format);
|
||||
same_oauth_signing_url = cursor.getInt(indices.same_oauth_signing_url) == 1;
|
||||
no_version_suffix = cursor.getInt(indices.no_version_suffix) == 1;
|
||||
}
|
||||
|
||||
public ParcelableCredentials(Parcel in) {
|
||||
super(in);
|
||||
auth_type = in.readInt();
|
||||
consumer_key = in.readString();
|
||||
consumer_secret = in.readString();
|
||||
basic_auth_username = in.readString();
|
||||
basic_auth_password = in.readString();
|
||||
oauth_token = in.readString();
|
||||
oauth_token_secret = in.readString();
|
||||
api_url_format = in.readString();
|
||||
same_oauth_signing_url = in.readInt() == 1;
|
||||
no_version_suffix = in.readInt() == 1;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
out.writeInt(auth_type);
|
||||
out.writeString(consumer_key);
|
||||
out.writeString(consumer_secret);
|
||||
out.writeString(basic_auth_username);
|
||||
out.writeString(basic_auth_password);
|
||||
out.writeString(oauth_token);
|
||||
out.writeString(oauth_token_secret);
|
||||
out.writeString(api_url_format);
|
||||
out.writeInt(same_oauth_signing_url ? 1 : 0);
|
||||
out.writeInt(no_version_suffix ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccountWithCredentials{auth_type=" + auth_type + ", consumer_key=" + consumer_key
|
||||
+ ", consumer_secret=" + consumer_secret + ", basic_auth_password=" + basic_auth_password
|
||||
+ ", oauth_token=" + oauth_token + ", oauth_token_secret=" + oauth_token_secret
|
||||
+ ", api_url_format=" + api_url_format + ", same_oauth_signing_url=" + same_oauth_signing_url + "}";
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Indices {
|
||||
|
||||
public final int screen_name, name, account_id, profile_image_url, profile_banner_url, color, is_activated,
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.model;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/26.
|
||||
*/
|
||||
@JsonObject
|
||||
@ParcelablePlease(allFields = false)
|
||||
public class ParcelableCredentials extends ParcelableAccount {
|
||||
|
||||
public static final Creator<org.mariotaku.twidere.model.ParcelableCredentials> CREATOR = new Creator<org.mariotaku.twidere.model.ParcelableCredentials>() {
|
||||
|
||||
@Override
|
||||
public ParcelableCredentials createFromParcel(final Parcel in) {
|
||||
return new ParcelableCredentials(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelableCredentials[] newArray(final int size) {
|
||||
return new ParcelableCredentials[size];
|
||||
}
|
||||
};
|
||||
|
||||
public static final int AUTH_TYPE_OAUTH = 0;
|
||||
public static final int AUTH_TYPE_XAUTH = 1;
|
||||
public static final int AUTH_TYPE_BASIC = 2;
|
||||
public static final int AUTH_TYPE_TWIP_O_MODE = 3;
|
||||
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "auth_type")
|
||||
public int auth_type;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "consumer_key")
|
||||
public String consumer_key;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "consumer_secret")
|
||||
public String consumer_secret;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "basic_auth_username")
|
||||
public String basic_auth_username;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "basic_auth_password")
|
||||
public String basic_auth_password;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "oauth_token")
|
||||
public String oauth_token;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "oauth_token_secret")
|
||||
public String oauth_token_secret;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "api_url_format")
|
||||
public String api_url_format;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "same_oauth_signing_url")
|
||||
public boolean same_oauth_signing_url;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "no_version_suffix")
|
||||
public boolean no_version_suffix;
|
||||
|
||||
public ParcelableCredentials() {
|
||||
}
|
||||
|
||||
public ParcelableCredentials(final Cursor cursor, final Indices indices) {
|
||||
super(cursor, indices);
|
||||
auth_type = cursor.getInt(indices.auth_type);
|
||||
consumer_key = cursor.getString(indices.consumer_key);
|
||||
consumer_secret = cursor.getString(indices.consumer_secret);
|
||||
basic_auth_username = cursor.getString(indices.basic_auth_username);
|
||||
basic_auth_password = cursor.getString(indices.basic_auth_password);
|
||||
oauth_token = cursor.getString(indices.oauth_token);
|
||||
oauth_token_secret = cursor.getString(indices.oauth_token_secret);
|
||||
api_url_format = cursor.getString(indices.api_url_format);
|
||||
same_oauth_signing_url = cursor.getInt(indices.same_oauth_signing_url) == 1;
|
||||
no_version_suffix = cursor.getInt(indices.no_version_suffix) == 1;
|
||||
}
|
||||
|
||||
public ParcelableCredentials(Parcel in) {
|
||||
super(in);
|
||||
ParcelableCredentialsParcelablePlease.readFromParcel(this, in);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
super.writeToParcel(out, flags);
|
||||
ParcelableCredentialsParcelablePlease.writeToParcel(this, out, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AccountWithCredentials{auth_type=" + auth_type + ", consumer_key=" + consumer_key
|
||||
+ ", consumer_secret=" + consumer_secret + ", basic_auth_password=" + basic_auth_password
|
||||
+ ", oauth_token=" + oauth_token + ", oauth_token_secret=" + oauth_token_secret
|
||||
+ ", api_url_format=" + api_url_format + ", same_oauth_signing_url=" + same_oauth_signing_url + "}";
|
||||
}
|
||||
}
|
|
@ -7,11 +7,13 @@ import android.text.TextUtils;
|
|||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@JsonObject
|
||||
@ParcelablePlease(allFields = false)
|
||||
public class ParcelableMediaUpdate implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableMediaUpdate> CREATOR = new Parcelable.Creator<ParcelableMediaUpdate>() {
|
||||
|
|
|
@ -30,7 +30,18 @@ import android.text.TextUtils;
|
|||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.BindingValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.BooleanValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.ImageValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.StringValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.UserValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.Place;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||
import org.mariotaku.twidere.util.HtmlEscapeHelper;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
|
@ -43,24 +54,16 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.BindingValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.BooleanValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.ImageValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.StringValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.CardEntity.UserValue;
|
||||
import org.mariotaku.twidere.api.twitter.model.Place;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@JsonObject
|
||||
@ParcelablePlease(allFields = false)
|
||||
public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus> {
|
||||
|
||||
public static final Parcelable.Creator<ParcelableStatus> CREATOR = new Parcelable.Creator<ParcelableStatus>() {
|
||||
@Override
|
||||
public ParcelableStatus createFromParcel(final Parcel in) {
|
||||
return new ParcelableStatus(in);
|
||||
ParcelableStatus status = new ParcelableStatus();
|
||||
ParcelableStatusParcelablePlease.readFromParcel(status, in);
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -68,8 +71,7 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
return new ParcelableStatus[size];
|
||||
}
|
||||
};
|
||||
@JsonField(name = "id")
|
||||
public long id;
|
||||
|
||||
public static final Comparator<ParcelableStatus> REVERSE_ID_COMPARATOR = new Comparator<ParcelableStatus>() {
|
||||
|
||||
@Override
|
||||
|
@ -80,10 +82,7 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
return (int) diff;
|
||||
}
|
||||
};
|
||||
@JsonField(name = "account_id")
|
||||
public long account_id;
|
||||
@JsonField(name = "timestamp")
|
||||
public long timestamp;
|
||||
|
||||
public static final Comparator<ParcelableStatus> TIMESTAMP_COMPARATOR = new Comparator<ParcelableStatus>() {
|
||||
|
||||
@Override
|
||||
|
@ -94,111 +93,164 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
return (int) diff;
|
||||
}
|
||||
};
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "id")
|
||||
public long id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "account_id")
|
||||
public long account_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "timestamp")
|
||||
public long timestamp;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_id")
|
||||
public long user_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_id")
|
||||
public long retweet_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_id")
|
||||
public long retweeted_by_user_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_timestamp")
|
||||
public long retweet_timestamp;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_count")
|
||||
public long retweet_count;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "favorite_count")
|
||||
public long favorite_count;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "reply_count")
|
||||
public long reply_count;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "descendent_reply_count")
|
||||
public long descendent_reply_count;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_status_id")
|
||||
public long in_reply_to_status_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_user_id")
|
||||
public long in_reply_to_user_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "my_retweet_id")
|
||||
public long my_retweet_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quote_id")
|
||||
public long quote_id;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quote_timestamp")
|
||||
public long quote_timestamp;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_by_user_id")
|
||||
public long quoted_by_user_id;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_gap")
|
||||
public boolean is_gap;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_retweet")
|
||||
public boolean is_retweet;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_favorite")
|
||||
public boolean is_favorite;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_possibly_sensitive")
|
||||
public boolean is_possibly_sensitive;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_following")
|
||||
public boolean user_is_following;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_protected")
|
||||
public boolean user_is_protected;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_is_verified")
|
||||
public boolean user_is_verified;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "is_quote")
|
||||
public boolean is_quote;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_by_user_is_protected")
|
||||
public boolean quoted_by_user_is_protected;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_by_user_is_verified")
|
||||
public boolean quoted_by_user_is_verified;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_name")
|
||||
public String retweeted_by_user_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_screen_name")
|
||||
public String retweeted_by_user_screen_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_profile_image")
|
||||
public String retweeted_by_user_profile_image;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_html")
|
||||
public String text_html;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_plain")
|
||||
public String text_plain;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_name")
|
||||
public String user_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_screen_name")
|
||||
public String user_screen_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_name")
|
||||
public String in_reply_to_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "in_reply_to_screen_name")
|
||||
public String in_reply_to_screen_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "source")
|
||||
public String source;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_profile_image_url")
|
||||
public String user_profile_image_url;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "text_unescaped")
|
||||
public String text_unescaped;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "card_name")
|
||||
public String card_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quote_text_html")
|
||||
public String quote_text_html;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quote_text_plain")
|
||||
public String quote_text_plain;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quote_text_unescaped")
|
||||
public String quote_text_unescaped;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quote_source")
|
||||
public String quote_source;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_by_user_name")
|
||||
public String quoted_by_user_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_by_user_screen_name")
|
||||
public String quoted_by_user_screen_name;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quoted_by_user_profile_image")
|
||||
public String quoted_by_user_profile_image;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "location")
|
||||
public ParcelableLocation location;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "place_full_name")
|
||||
public String place_full_name;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "mentions")
|
||||
public ParcelableUserMention[] mentions;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "media")
|
||||
public ParcelableMedia[] media;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "quote_media")
|
||||
public ParcelableMedia[] quote_media;
|
||||
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "card")
|
||||
public ParcelableCardEntity card;
|
||||
|
||||
|
@ -264,62 +316,6 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
public ParcelableStatus() {
|
||||
}
|
||||
|
||||
public ParcelableStatus(final Parcel in) {
|
||||
id = in.readLong();
|
||||
account_id = in.readLong();
|
||||
timestamp = in.readLong();
|
||||
user_id = in.readLong();
|
||||
retweet_id = in.readLong();
|
||||
retweet_timestamp = in.readLong();
|
||||
retweeted_by_user_id = in.readLong();
|
||||
retweet_count = in.readLong();
|
||||
favorite_count = in.readLong();
|
||||
reply_count = in.readLong();
|
||||
descendent_reply_count = in.readLong();
|
||||
in_reply_to_status_id = in.readLong();
|
||||
is_gap = in.readByte() == 1;
|
||||
is_retweet = in.readByte() == 1;
|
||||
is_favorite = in.readByte() == 1;
|
||||
user_is_protected = in.readByte() == 1;
|
||||
user_is_verified = in.readByte() == 1;
|
||||
retweeted_by_user_name = in.readString();
|
||||
retweeted_by_user_screen_name = in.readString();
|
||||
retweeted_by_user_profile_image = in.readString();
|
||||
text_html = in.readString();
|
||||
text_plain = in.readString();
|
||||
user_name = in.readString();
|
||||
user_screen_name = in.readString();
|
||||
in_reply_to_screen_name = in.readString();
|
||||
source = in.readString();
|
||||
user_profile_image_url = in.readString();
|
||||
media = in.createTypedArray(ParcelableMedia.CREATOR);
|
||||
quote_media = in.createTypedArray(ParcelableMedia.CREATOR);
|
||||
location = in.readParcelable(ParcelableLocation.class.getClassLoader());
|
||||
my_retweet_id = in.readLong();
|
||||
is_possibly_sensitive = in.readByte() == 1;
|
||||
user_is_following = in.readByte() == 1;
|
||||
text_unescaped = in.readString();
|
||||
in_reply_to_user_id = in.readLong();
|
||||
in_reply_to_name = in.readString();
|
||||
mentions = in.createTypedArray(ParcelableUserMention.CREATOR);
|
||||
card = in.readParcelable(ParcelableCardEntity.class.getClassLoader());
|
||||
place_full_name = in.readString();
|
||||
is_quote = in.readByte() == 1;
|
||||
quote_id = in.readLong();
|
||||
quote_text_html = in.readString();
|
||||
quote_text_plain = in.readString();
|
||||
quote_text_unescaped = in.readString();
|
||||
quote_timestamp = in.readLong();
|
||||
quoted_by_user_id = in.readLong();
|
||||
quoted_by_user_name = in.readString();
|
||||
quoted_by_user_screen_name = in.readString();
|
||||
quoted_by_user_profile_image = in.readString();
|
||||
quoted_by_user_is_protected = in.readByte() == 1;
|
||||
quoted_by_user_is_verified = in.readByte() == 1;
|
||||
quote_source = in.readString();
|
||||
card_name = card != null ? card.name : null;
|
||||
}
|
||||
|
||||
public ParcelableStatus(final ParcelableStatus orig, final long override_my_retweet_id,
|
||||
final long override_retweet_count) {
|
||||
id = orig.id;
|
||||
|
@ -847,58 +843,7 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
|||
|
||||
@Override
|
||||
public void writeToParcel(final Parcel out, final int flags) {
|
||||
out.writeLong(id);
|
||||
out.writeLong(account_id);
|
||||
out.writeLong(timestamp);
|
||||
out.writeLong(user_id);
|
||||
out.writeLong(retweet_id);
|
||||
out.writeLong(retweet_timestamp);
|
||||
out.writeLong(retweeted_by_user_id);
|
||||
out.writeLong(retweet_count);
|
||||
out.writeLong(favorite_count);
|
||||
out.writeLong(reply_count);
|
||||
out.writeLong(descendent_reply_count);
|
||||
out.writeLong(in_reply_to_status_id);
|
||||
out.writeByte((byte) (is_gap ? 1 : 0));
|
||||
out.writeByte((byte) (is_retweet ? 1 : 0));
|
||||
out.writeByte((byte) (is_favorite ? 1 : 0));
|
||||
out.writeByte((byte) (user_is_protected ? 1 : 0));
|
||||
out.writeByte((byte) (user_is_verified ? 1 : 0));
|
||||
out.writeString(retweeted_by_user_name);
|
||||
out.writeString(retweeted_by_user_screen_name);
|
||||
out.writeString(retweeted_by_user_profile_image);
|
||||
out.writeString(text_html);
|
||||
out.writeString(text_plain);
|
||||
out.writeString(user_name);
|
||||
out.writeString(user_screen_name);
|
||||
out.writeString(in_reply_to_screen_name);
|
||||
out.writeString(source);
|
||||
out.writeString(user_profile_image_url);
|
||||
out.writeTypedArray(media, flags);
|
||||
out.writeTypedArray(quote_media, flags);
|
||||
out.writeParcelable(location, flags);
|
||||
out.writeLong(my_retweet_id);
|
||||
out.writeByte((byte) (is_possibly_sensitive ? 1 : 0));
|
||||
out.writeByte((byte) (user_is_following ? 1 : 0));
|
||||
out.writeString(text_unescaped);
|
||||
out.writeLong(in_reply_to_user_id);
|
||||
out.writeString(in_reply_to_name);
|
||||
out.writeTypedArray(mentions, flags);
|
||||
out.writeParcelable(card, flags);
|
||||
out.writeString(place_full_name);
|
||||
out.writeByte((byte) (is_quote ? 1 : 0));
|
||||
out.writeLong(quote_id);
|
||||
out.writeString(quote_text_html);
|
||||
out.writeString(quote_text_plain);
|
||||
out.writeString(quote_text_unescaped);
|
||||
out.writeLong(quote_timestamp);
|
||||
out.writeLong(quoted_by_user_id);
|
||||
out.writeString(quoted_by_user_name);
|
||||
out.writeString(quoted_by_user_screen_name);
|
||||
out.writeString(quoted_by_user_profile_image);
|
||||
out.writeByte((byte) (quoted_by_user_is_protected ? 1 : 0));
|
||||
out.writeByte((byte) (quoted_by_user_is_verified ? 1 : 0));
|
||||
out.writeString(quote_source);
|
||||
ParcelableStatusParcelablePlease.writeToParcel(this, out, flags);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -59,11 +59,6 @@ public interface TwidereDataStore {
|
|||
|
||||
public static interface Accounts extends BaseColumns {
|
||||
|
||||
int AUTH_TYPE_OAUTH = 0;
|
||||
int AUTH_TYPE_XAUTH = 1;
|
||||
int AUTH_TYPE_BASIC = 2;
|
||||
int AUTH_TYPE_TWIP_O_MODE = 3;
|
||||
|
||||
String TABLE_NAME = "accounts";
|
||||
String CONTENT_PATH = TABLE_NAME;
|
||||
Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, CONTENT_PATH);
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.mariotaku.twidere.api.twitter.model.Trends;
|
|||
import org.mariotaku.twidere.api.twitter.model.UrlEntity;
|
||||
import org.mariotaku.twidere.api.twitter.model.User;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.model.ParcelableCredentials;
|
||||
import org.mariotaku.twidere.model.ParcelableDirectMessage;
|
||||
import org.mariotaku.twidere.model.ParcelableLocation;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
|
@ -76,7 +77,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
if (basicUsername == null || basicPassword == null) return null;
|
||||
values.put(Accounts.BASIC_AUTH_USERNAME, basicUsername);
|
||||
values.put(Accounts.BASIC_AUTH_PASSWORD, basicPassword);
|
||||
values.put(Accounts.AUTH_TYPE, Accounts.AUTH_TYPE_BASIC);
|
||||
values.put(Accounts.AUTH_TYPE, ParcelableCredentials.AUTH_TYPE_BASIC);
|
||||
values.put(Accounts.ACCOUNT_ID, user.getId());
|
||||
values.put(Accounts.SCREEN_NAME, user.getScreenName());
|
||||
values.put(Accounts.NAME, user.getName());
|
||||
|
@ -118,7 +119,7 @@ public final class ContentValuesCreator implements TwidereConstants {
|
|||
final boolean noVersionSuffix) {
|
||||
if (user == null || user.getId() <= 0) return null;
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Accounts.AUTH_TYPE, Accounts.AUTH_TYPE_TWIP_O_MODE);
|
||||
values.put(Accounts.AUTH_TYPE, ParcelableCredentials.AUTH_TYPE_TWIP_O_MODE);
|
||||
values.put(Accounts.ACCOUNT_ID, user.getId());
|
||||
values.put(Accounts.SCREEN_NAME, user.getScreenName());
|
||||
values.put(Accounts.NAME, user.getName());
|
||||
|
|
|
@ -25,11 +25,11 @@ import com.bluelinelabs.logansquare.LoganSquare;
|
|||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.mariotaku.simplerestapi.http.Endpoint;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpClient;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpRequest;
|
||||
import org.mariotaku.simplerestapi.http.RestHttpResponse;
|
||||
import org.mariotaku.simplerestapi.method.GET;
|
||||
import org.mariotaku.restfu.annotation.method.GET;
|
||||
import org.mariotaku.restfu.http.Endpoint;
|
||||
import org.mariotaku.restfu.http.RestHttpClient;
|
||||
import org.mariotaku.restfu.http.RestHttpRequest;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.util.HtmlLinkExtractor.HtmlLink;
|
||||
|
||||
|
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* 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.mariotaku.twidere.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.mariotaku.restfu.ExceptionFactory;
|
||||
import org.mariotaku.restfu.HttpRequestFactory;
|
||||
import org.mariotaku.restfu.RequestInfoFactory;
|
||||
import org.mariotaku.restfu.RestMethodInfo;
|
||||
import org.mariotaku.restfu.RestRequestInfo;
|
||||
import org.mariotaku.restfu.annotation.RestMethod;
|
||||
import org.mariotaku.restfu.http.Authorization;
|
||||
import org.mariotaku.restfu.http.Endpoint;
|
||||
import org.mariotaku.restfu.http.FileValue;
|
||||
import org.mariotaku.restfu.http.RestHttpRequest;
|
||||
import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.mime.StringTypedData;
|
||||
import org.mariotaku.restfu.http.mime.TypedData;
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterOAuth;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterUpload;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterUserStream;
|
||||
import org.mariotaku.twidere.api.twitter.auth.BasicAuthorization;
|
||||
import org.mariotaku.twidere.api.twitter.auth.EmptyAuthorization;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthEndpoint;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
|
||||
import org.mariotaku.twidere.api.twitter.util.TwitterConverter;
|
||||
import org.mariotaku.twidere.model.ConsumerKeyType;
|
||||
import org.mariotaku.twidere.model.ParcelableCredentials;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/5/26.
|
||||
*/
|
||||
public class TwitterAPIUtils implements TwidereConstants {
|
||||
|
||||
public static Endpoint getEndpoint(ParcelableCredentials credentials, Class<?> cls) {
|
||||
final String apiUrlFormat;
|
||||
final boolean sameOAuthSigningUrl = credentials.same_oauth_signing_url;
|
||||
final boolean noVersionSuffix = credentials.no_version_suffix;
|
||||
if (!isEmpty(credentials.api_url_format)) {
|
||||
apiUrlFormat = credentials.api_url_format;
|
||||
} else {
|
||||
apiUrlFormat = DEFAULT_TWITTER_API_URL_FORMAT;
|
||||
}
|
||||
final String domain, versionSuffix;
|
||||
if (Twitter.class.isAssignableFrom(cls)) {
|
||||
domain = "api";
|
||||
versionSuffix = noVersionSuffix ? null : "/1.1/";
|
||||
} else if (TwitterUpload.class.isAssignableFrom(cls)) {
|
||||
domain = "upload";
|
||||
versionSuffix = noVersionSuffix ? null : "/1.1/";
|
||||
} else if (TwitterOAuth.class.isAssignableFrom(cls)) {
|
||||
domain = "api";
|
||||
versionSuffix = "oauth";
|
||||
} else if (TwitterUserStream.class.isAssignableFrom(cls)) {
|
||||
domain = "userstream";
|
||||
versionSuffix = noVersionSuffix ? null : "/1.1/";
|
||||
} else {
|
||||
throw new TwitterConverter.UnsupportedTypeException(cls);
|
||||
}
|
||||
final String endpointUrl;
|
||||
endpointUrl = getApiUrl(apiUrlFormat, domain, versionSuffix);
|
||||
if (credentials.auth_type == ParcelableCredentials.AUTH_TYPE_XAUTH || credentials.auth_type == ParcelableCredentials.AUTH_TYPE_OAUTH) {
|
||||
final String signEndpointUrl;
|
||||
if (!sameOAuthSigningUrl) {
|
||||
signEndpointUrl = getApiUrl(DEFAULT_TWITTER_API_URL_FORMAT, domain, versionSuffix);
|
||||
} else {
|
||||
signEndpointUrl = endpointUrl;
|
||||
}
|
||||
return new OAuthEndpoint(endpointUrl, signEndpointUrl);
|
||||
}
|
||||
return new Endpoint(endpointUrl);
|
||||
}
|
||||
|
||||
public static Authorization getAuthorization(ParcelableCredentials credentials) {
|
||||
switch (credentials.auth_type) {
|
||||
case ParcelableCredentials.AUTH_TYPE_OAUTH:
|
||||
case ParcelableCredentials.AUTH_TYPE_XAUTH: {
|
||||
final String consumerKey = TextUtils.isEmpty(credentials.consumer_key) ?
|
||||
TWITTER_CONSUMER_KEY_LEGACY : credentials.consumer_key;
|
||||
final String consumerSecret = TextUtils.isEmpty(credentials.consumer_secret) ?
|
||||
TWITTER_CONSUMER_SECRET_LEGACY : credentials.consumer_secret;
|
||||
final OAuthToken accessToken = new OAuthToken(credentials.oauth_token, credentials.oauth_token_secret);
|
||||
return new OAuthAuthorization(consumerKey, consumerSecret, accessToken);
|
||||
}
|
||||
case ParcelableCredentials.AUTH_TYPE_BASIC: {
|
||||
final String screenName = credentials.screen_name;
|
||||
final String username = credentials.basic_auth_username;
|
||||
final String loginName = username != null ? username : screenName;
|
||||
final String password = credentials.basic_auth_password;
|
||||
if (isEmpty(loginName) || isEmpty(password)) return null;
|
||||
return new BasicAuthorization(loginName, password);
|
||||
}
|
||||
}
|
||||
return new EmptyAuthorization();
|
||||
}
|
||||
|
||||
private static void addParameter(List<Pair<String, String>> params, String name, Object value) {
|
||||
params.add(Pair.create(name, String.valueOf(value)));
|
||||
}
|
||||
|
||||
private static void addPart(List<Pair<String, TypedData>> params, String name, Object value) {
|
||||
final TypedData typedData = new StringTypedData(String.valueOf(value), Charset.defaultCharset());
|
||||
params.add(Pair.create(name, typedData));
|
||||
}
|
||||
|
||||
public static String getApiBaseUrl(String format, final String domain) {
|
||||
if (format == null) return null;
|
||||
final Matcher matcher = Pattern.compile("\\[(\\.?)DOMAIN(\\.?)\\]").matcher(format);
|
||||
if (!matcher.find()) {
|
||||
// For backward compatibility
|
||||
format = substituteLegacyApiBaseUrl(format, domain);
|
||||
if (!format.endsWith("/1.1") && !format.endsWith("/1.1/")) {
|
||||
return format;
|
||||
}
|
||||
final String versionSuffix = "/1.1";
|
||||
final int suffixLength = versionSuffix.length();
|
||||
final int lastIndex = format.lastIndexOf(versionSuffix);
|
||||
return format.substring(0, lastIndex) + format.substring(lastIndex + suffixLength);
|
||||
}
|
||||
if (TextUtils.isEmpty(domain)) return matcher.replaceAll("");
|
||||
return matcher.replaceAll(String.format("$1%s$2", domain));
|
||||
}
|
||||
|
||||
private static String substituteLegacyApiBaseUrl(@NonNull String format, String domain) {
|
||||
final int startOfHost = format.indexOf("://") + 3, endOfHost = format.indexOf('/', startOfHost);
|
||||
final String host = endOfHost != -1 ? format.substring(startOfHost, endOfHost) : format.substring(startOfHost);
|
||||
if (!host.equalsIgnoreCase("api.twitter.com")) return format;
|
||||
return format.substring(0, startOfHost) + domain + ".twitter.com" + format.substring(endOfHost);
|
||||
}
|
||||
|
||||
public static String getApiUrl(final String pattern, final String domain, final String appendPath) {
|
||||
final String urlBase = getApiBaseUrl(pattern, domain);
|
||||
if (urlBase == null) return null;
|
||||
if (appendPath == null) return urlBase.endsWith("/") ? urlBase : urlBase + "/";
|
||||
final StringBuilder sb = new StringBuilder(urlBase);
|
||||
if (urlBase.endsWith("/")) {
|
||||
sb.append(appendPath.startsWith("/") ? appendPath.substring(1) : appendPath);
|
||||
} else {
|
||||
if (appendPath.startsWith("/")) {
|
||||
sb.append(appendPath);
|
||||
} else {
|
||||
sb.append('/');
|
||||
sb.append(appendPath);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getUserAgentName(ConsumerKeyType type) {
|
||||
switch (type) {
|
||||
case TWITTER_FOR_ANDROID: {
|
||||
return "TwitterAndroid";
|
||||
}
|
||||
case TWITTER_FOR_IPHONE: {
|
||||
return "Twitter-iPhone";
|
||||
}
|
||||
case TWITTER_FOR_IPAD: {
|
||||
return "Twitter-iPad";
|
||||
}
|
||||
case TWITTER_FOR_MAC: {
|
||||
return "Twitter-Mac";
|
||||
}
|
||||
}
|
||||
return "Twitter";
|
||||
}
|
||||
|
||||
public static String getTwidereUserAgent(final Context context) {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
try {
|
||||
final PackageInfo pi = pm.getPackageInfo(TWIDERE_PACKAGE_NAME, 0);
|
||||
return TWIDERE_APP_NAME + " " + TWIDERE_PROJECT_URL + " / " + pi.versionName;
|
||||
} catch (final PackageManager.NameNotFoundException e) {
|
||||
return TWIDERE_APP_NAME + " " + TWIDERE_PROJECT_URL;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TwidereRequestInfoFactory implements RequestInfoFactory {
|
||||
@Override
|
||||
public RestRequestInfo create(RestMethodInfo methodInfo) {
|
||||
final RestMethod method = methodInfo.getMethod();
|
||||
final String path = methodInfo.getPath();
|
||||
final List<Pair<String, String>> queries = new ArrayList<>(methodInfo.getQueries());
|
||||
final List<Pair<String, String>> forms = new ArrayList<>(methodInfo.getForms());
|
||||
final List<Pair<String, String>> headers = methodInfo.getHeaders();
|
||||
final List<Pair<String, TypedData>> parts = methodInfo.getParts();
|
||||
final FileValue file = methodInfo.getFile();
|
||||
final Map<String, Object> extras = methodInfo.getExtras();
|
||||
if (parts.isEmpty()) {
|
||||
final List<Pair<String, String>> params = method.hasBody() ? forms : queries;
|
||||
addParameter(params, "include_cards", true);
|
||||
addParameter(params, "cards_platform", "Android-12");
|
||||
addParameter(params, "include_entities", true);
|
||||
addParameter(params, "include_my_retweet", 1);
|
||||
addParameter(params, "include_rts", 1);
|
||||
addParameter(params, "include_reply_count", true);
|
||||
addParameter(params, "include_descendent_reply_count", true);
|
||||
} else {
|
||||
addPart(parts, "include_cards", true);
|
||||
addPart(parts, "cards_platform", "Android-12");
|
||||
addPart(parts, "include_entities", true);
|
||||
addPart(parts, "include_my_retweet", 1);
|
||||
addPart(parts, "include_rts", 1);
|
||||
addPart(parts, "include_reply_count", true);
|
||||
addPart(parts, "include_descendent_reply_count", true);
|
||||
}
|
||||
return new RestRequestInfo(method.value(), path, queries, forms, headers, parts, file,
|
||||
methodInfo.getBody(), extras);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TwidereHttpRequestFactory implements HttpRequestFactory {
|
||||
|
||||
private final String userAgent;
|
||||
|
||||
public TwidereHttpRequestFactory(final String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestHttpRequest create(@NonNull Endpoint endpoint, @NonNull RestRequestInfo info,
|
||||
@Nullable Authorization authorization) {
|
||||
final String restMethod = info.getMethod();
|
||||
final String url = Endpoint.constructUrl(endpoint.getUrl(), info);
|
||||
final ArrayList<Pair<String, String>> headers = new ArrayList<>(info.getHeaders());
|
||||
|
||||
if (authorization != null && authorization.hasAuthorization()) {
|
||||
headers.add(Pair.create("Authorization", authorization.getHeader(endpoint, info)));
|
||||
}
|
||||
headers.add(Pair.create("User-Agent", userAgent));
|
||||
return new RestHttpRequest(restMethod, url, headers, info.getBody(), null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TwidereExceptionFactory implements ExceptionFactory {
|
||||
@Override
|
||||
public Exception newException(Throwable cause, RestHttpRequest request, RestHttpResponse response) {
|
||||
final TwitterException te = new TwitterException(cause);
|
||||
te.setResponse(response);
|
||||
return te;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,6 +29,16 @@ android {
|
|||
versionCode 14
|
||||
versionName "1.12 (0.3.0-dev)"
|
||||
}
|
||||
packagingOptions {
|
||||
exclude 'META-INF/DEPENDENCIES'
|
||||
exclude 'META-INF/LICENSE'
|
||||
exclude 'META-INF/LICENSE.txt'
|
||||
exclude 'META-INF/license.txt'
|
||||
exclude 'META-INF/NOTICE'
|
||||
exclude 'META-INF/NOTICE.txt'
|
||||
exclude 'META-INF/notice.txt'
|
||||
exclude 'META-INF/ASL2.0'
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
|
@ -42,8 +52,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile 'com.squareup.okhttp:okhttp:2.3.0'
|
||||
compile 'com.squareup.okhttp:okhttp:2.4.0'
|
||||
compile project(':twidere.library.extension')
|
||||
compile project(':twidere.component.twitter4j.streaming')
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue