api refactored and cleaned

This commit is contained in:
2021-08-31 16:20:09 +03:00
parent c3208fd95e
commit b09ae2049c
40 changed files with 129 additions and 2107 deletions
@@ -1,9 +0,0 @@
package com.meloda.fast.api
interface OnResponseListener<T> {
fun onResponse(response: T)
fun onError(t: Throwable)
}
@@ -0,0 +1,33 @@
package com.meloda.fast.api
import com.meloda.fast.common.AppGlobal
object UserConfig {
private const val TOKEN = "token"
private const val USER_ID = "user_id"
const val FAST_APP_ID = "6964679"
var userId: Int = -1
get() = AppGlobal.preferences.getInt(USER_ID, -1)
set(value) {
field = value
AppGlobal.preferences.edit().putInt(USER_ID, value).apply()
}
var accessToken: String = ""
get() = AppGlobal.preferences.getString(TOKEN, "") ?: ""
set(value) {
field = value
AppGlobal.preferences.edit().putString(TOKEN, value).apply()
}
fun clear() {
accessToken = ""
userId = -1
}
fun isLoggedIn() = userId > 0 && accessToken.isNotBlank()
}
@@ -1,506 +0,0 @@
package com.meloda.fast.api
import android.os.Handler
import android.util.Log
import androidx.annotation.WorkerThread
import com.meloda.fast.BuildConfig
import com.meloda.fast.api.method.MessageMethodSetter
import com.meloda.fast.api.method.MethodSetter
import com.meloda.fast.api.method.UserMethodSetter
import com.meloda.fast.api.network.ErrorCodes
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import org.json.JSONArray
import org.json.JSONObject
import java.util.*
import kotlin.collections.ArrayList
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
@Suppress("UNCHECKED_CAST")
object VKApi {
private const val TAG = "VKM:VKApi"
const val BASE_URL = "https://api.vk.com/method/"
const val API_VERSION = "5.132"
var language: String = ""
var token: String = ""
private lateinit var handler: Handler
fun init(language: String, token: String, handler: Handler) {
VKApi.language = language
VKApi.token = token
VKApi.handler = handler
}
@WorkerThread
@Suppress("UNCHECKED_CAST")
fun <T> execute(url: String, cls: Class<T>?): ArrayList<T>? {
if (BuildConfig.DEBUG) {
Log.w(TAG, "url: $url")
}
val buffer = com.meloda.fast.net.HttpRequest[url].asString()
if (BuildConfig.DEBUG) {
Log.i(TAG, "response: $buffer")
}
val json = JSONObject(buffer)
try {
checkError(json, url)
} catch (ex: VKException) {
throw ex
// if (ex.code == ErrorCodes.TOO_MANY_REQUESTS) {
// Timer().schedule(object : TimerTask() {
// override fun run() {
// execute(url, cls)
// }
// }, 1000)
// } else throw ex
}
when (cls) {
null -> return null
com.meloda.fast.api.model.VKLongPollServer::class.java -> {
json.optJSONObject("response")?.let {
return arrayListOf(com.meloda.fast.api.model.VKLongPollServer(it)) as ArrayList<T>?
}
}
Boolean::class.java -> {
val value = json.optInt("response") == 1
return arrayListOf(value) as ArrayList<T>?
}
Long::class.java -> {
val value = json.optLong("response")
return arrayListOf(value) as ArrayList<T>?
}
Int::class.java -> {
val value = json.optInt("response")
return arrayListOf(value) as ArrayList<T>?
}
}
val response = json.opt("response") ?: return null
val array = optItems(json) ?: return null
val models = ArrayList<T>(array.length())
when (cls) {
com.meloda.fast.api.model.VKUser::class.java -> {
json.optJSONObject("response")?.let { r ->
com.meloda.fast.api.model.VKUser.friendsCount = r.optInt("count")
}
for (i in 0 until array.length()) {
models.add(com.meloda.fast.api.model.VKUser(array.optJSONObject(i)) as T)
}
}
com.meloda.fast.api.model.VKMessage::class.java -> {
response as JSONObject
if (url.contains("messages.getHistory")) {
com.meloda.fast.api.model.VKMessage.lastHistoryCount = response.optInt("count")
response.optJSONArray("profiles")?.let {
val profiles = arrayListOf<com.meloda.fast.api.model.VKUser>()
for (j in 0 until it.length()) {
profiles.add(com.meloda.fast.api.model.VKUser(it.optJSONObject(j)))
}
com.meloda.fast.api.model.VKMessage.profiles = profiles
}
response.optJSONArray("groups")?.let {
val groups = arrayListOf<com.meloda.fast.api.model.VKGroup>()
for (j in 0 until it.length()) {
groups.add(com.meloda.fast.api.model.VKGroup(it.optJSONObject(j)))
}
com.meloda.fast.api.model.VKMessage.groups = groups
}
response.optJSONArray("conversations")?.let {
val conversations = arrayListOf<com.meloda.fast.api.model.VKConversation>()
for (j in 0 until it.length()) {
conversations.add(
com.meloda.fast.api.model.VKConversation(
it.optJSONObject(
j
)
)
)
}
com.meloda.fast.api.model.VKMessage.conversations = conversations
}
}
for (i in 0 until array.length()) {
var source = array.optJSONObject(i)
if (source.has("message")) {
source = source.optJSONObject("message")
}
val message = com.meloda.fast.api.model.VKMessage(source)
models.add(message as T)
}
}
com.meloda.fast.api.model.VKGroup::class.java -> {
for (i in 0 until array.length()) {
models.add(com.meloda.fast.api.model.VKGroup(array.optJSONObject(i)) as T)
}
}
com.meloda.fast.api.model.VKModel::class.java -> {
if (url.contains("messages.getHistoryAttachments")) {
return com.meloda.fast.api.model.VKAttachments.parse(array) as ArrayList<T>
}
}
com.meloda.fast.api.model.VKConversation::class.java -> {
if (url.contains("getConversationsById")) {
for (i in 0 until array.length()) {
val source = array.optJSONObject(i)
models.add(com.meloda.fast.api.model.VKConversation(source) as T)
}
return models
}
json.optJSONObject("response")?.let { r ->
com.meloda.fast.api.model.VKConversation.conversationsCount = r.optInt("count")
}
for (i in 0 until array.length()) {
response as JSONObject
val source = array.optJSONObject(i)
val oConversation = source.optJSONObject("conversation") ?: return null
val oLastMessage = source.optJSONObject("last_message") ?: return null
val conversation = com.meloda.fast.api.model.VKConversation(oConversation).also {
it.lastMessage = com.meloda.fast.api.model.VKMessage(oLastMessage)
}
response.optJSONArray("profiles")?.let {
val profiles = arrayListOf<com.meloda.fast.api.model.VKUser>()
for (j in 0 until it.length()) {
profiles.add(com.meloda.fast.api.model.VKUser(it.optJSONObject(j)))
}
com.meloda.fast.api.model.VKConversation.profiles = profiles
}
response.optJSONArray("groups")?.let {
val groups = arrayListOf<com.meloda.fast.api.model.VKGroup>()
for (j in 0 until it.length()) {
groups.add(com.meloda.fast.api.model.VKGroup(it.optJSONObject(j)))
}
com.meloda.fast.api.model.VKConversation.groups = groups
}
models.add(conversation as T)
}
}
}
return models
}
fun <E> execute(url: String, cls: Class<E>, listener: OnResponseListener<E>?) {
com.meloda.fast.concurrent.TaskManager.execute {
try {
val models = execute(url, cls) ?: return@execute
// listener?.onResponse(models)
} catch (e: Exception) {
e.printStackTrace()
listener?.onError(e)
// it.resumeWithException(e)
}
}
}
suspend fun <E> suspendExecute(url: String, cls: Class<E>): Flow<E> {
return suspendCoroutine {
try {
val models = execute(url, cls)?.asFlow() ?: return@suspendCoroutine
it.resume(models)
} catch (e: Exception) {
e.printStackTrace()
it.resumeWithException(e)
}
}
}
fun <E> executeArray(url: String, cls: Class<E>, listener: OnResponseListener<ArrayList<E>>) {
com.meloda.fast.concurrent.TaskManager.execute {
try {
val models = execute(url, cls)
handler.post { listener.onResponse(models as ArrayList<E>) }
} catch (e: Exception) {
e.printStackTrace()
listener.onError(e)
}
}
}
private fun optItems(source: JSONObject): JSONArray? {
val response = source.opt("response")
return when (response) {
is JSONArray -> response
is JSONObject -> response.optJSONArray("items")
else -> null
}
}
private fun checkError(json: JSONObject, url: String) {
if (json.has("error")) {
val error = json.optJSONObject("error") ?: return
val code = error.optInt("error_code", -1)
val message = error.optString("error_msg", "")
// val e = VKException(url, message, code)
//TODO: add checking invalid session
if (code == 5 && message.contains("invalid session")) {
// context?.startActivity(Intent(context, DropUserDataActivity::class.java).apply {
// addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
// })
}
// if (code == ErrorCodes.CAPTCHA_NEEDED) {
// e.captchaImg = error.optString("captcha_img")
// e.captchaSid = error.optString("captcha_sid")
// }
//
// if (code == ErrorCodes.VALIDATION_REQUIRED) {
// e.redirectUri = error.optString("redirect_uri")
// }
// throw e
}
}
fun users(): VKUsers {
return VKUsers()
}
fun friends(): VKFriends {
return VKFriends()
}
fun messages(): VKMessages {
return VKMessages()
}
fun groups(): VKGroups {
return VKGroups()
}
fun account(): VKAccounts {
return VKAccounts()
}
class VKFriends {
fun get(): MethodSetter {
return MethodSetter("friends.get")
}
}
class VKUsers {
fun get(): UserMethodSetter {
return UserMethodSetter("users.get")
}
}
class VKMessages {
fun get(): MessageMethodSetter {
return MessageMethodSetter("messages.get")
}
fun getConversations(): MessageMethodSetter {
return MessageMethodSetter("messages.getConversations")
}
fun getConversationsById(): MessageMethodSetter {
return MessageMethodSetter("messages.getConversationsById")
}
fun getById(): MessageMethodSetter {
return MessageMethodSetter("messages.getById")
}
fun search(): MessageMethodSetter {
return MessageMethodSetter("messages.search")
}
fun getHistory(): MessageMethodSetter {
return MessageMethodSetter("messages.getHistory")
}
fun getHistoryAttachments(): MessageMethodSetter {
return MessageMethodSetter("messages.getHistoryAttachments")
}
fun send(): MessageMethodSetter {
return MessageMethodSetter("messages.send")
}
fun sendSticker(): MessageMethodSetter {
return MessageMethodSetter("messages.sendSticker")
}
fun delete(): MessageMethodSetter {
return MessageMethodSetter("messages.delete")
}
fun deleteDialog(): MessageMethodSetter {
return MessageMethodSetter("messages.deleteDialog")
}
fun restore(): MessageMethodSetter {
return MessageMethodSetter("messages.restore")
}
fun markAsRead(): MessageMethodSetter {
return MessageMethodSetter("messages.markAsRead")
}
fun markAsImportant(): MessageMethodSetter {
return MessageMethodSetter("messages.markAsImportant")
}
fun getLongPollServer(): MessageMethodSetter {
return MessageMethodSetter("messages.getLongPollServer")
}
/**
* Returns updates in user's private messages.
* To speed up handling of private messages,
* it can be useful to cache previously loaded messages on
* a user's mobile device/desktop, to prevent re-receipt at each call.
* With this method, you can synchronize a local copy of
* the message list with the actual version.
*
*
* Result:
* Returns an object that contains the following fields:
* 1 — history: An array similar to updates field returned
* from the Long Poll server,
* with these exceptions:
* - For events with code 4 (addition of a new message),
* there are no fields except the first three.
* - There are no events with codes 8, 9 (friend goes online/offline)
* or with codes 61, 62 (typing during conversation/chat).
*
*
* 2 — messages: An array of private message objects that were found
* among events with code 4 (addition of a new message)
* from the history field.
* Each object of message contains a set of fields described here.
* The first array element is the total number of messages
*/
fun getLongPollHistory(): MessageMethodSetter {
return MessageMethodSetter("messages.getLongPollHistory")
}
fun getChat(): MessageMethodSetter {
return MessageMethodSetter("messages.getChat")
}
fun createChat(): MessageMethodSetter {
return MessageMethodSetter("messages.createChat")
}
fun editChat(): MessageMethodSetter {
return MessageMethodSetter("messages.editChat")
}
val chatUsers: MessageMethodSetter
get() = MessageMethodSetter("messages.getChatUsers")
fun setActivity(): MessageMethodSetter {
return MessageMethodSetter("messages.setActivity").type(true)
}
fun addChatUser(): MessageMethodSetter {
return MessageMethodSetter("messages.addChatUser")
}
fun removeChatUser(): MessageMethodSetter {
return MessageMethodSetter("messages.removeChatUser")
}
}
class VKGroups {
fun getById(): MethodSetter {
return MethodSetter("groups.getById")
}
fun join(): MethodSetter {
return MethodSetter("groups.join")
}
}
class VKAccounts {
fun setOffline(): MethodSetter {
return MethodSetter("account.setOffline")
}
fun setOnline(): MethodSetter {
return MethodSetter("account.setOnline")
}
}
class SuccessCallback<E>(
private val listener: OnResponseListener<E>?,
private val response: E
) : Runnable {
override fun run() {
listener?.onResponse(response)
}
}
class SuccessArrayCallback<E>(
private val listener: OnResponseListener<ArrayList<E>>?,
private val response: ArrayList<E>
) : Runnable {
override fun run() {
listener?.onResponse(response)
}
}
class ErrorCallback<E>(
private val listener: OnResponseListener<E>?,
private val exception: Exception
) : Runnable {
override fun run() {
listener?.onError(exception)
}
}
}
@@ -1,14 +0,0 @@
package com.meloda.fast.api
enum class VKApiKeys(val value: String) {
READ_MESSAGE("_read_message"),
RESTORE_MESSAGE("_restore_message"),
NEW_MESSAGE("_new_message"),
EDIT_MESSAGE("_edit_message"),
DELETE_MESSAGE("_delete_message"),
UPDATE_MESSAGE("_update_message"),
UPDATE_CONVERSATION("_update_conversation"),
UPDATE_USER("_update_user"),
UPDATE_GROUP("_update_group")
}
@@ -1,84 +0,0 @@
package com.meloda.fast.api
import android.util.Log
import com.meloda.fast.BuildConfig
import com.meloda.fast.UserConfig
import java.net.URLEncoder
object VKAuth {
private const val TAG = "VKM.VKAuth"
object GrantType {
const val PASSWORD = "password"
}
const val scope = "notify," +
"friends," +
"photos," +
"audio," +
"video," +
"docs," +
"status," +
"notes," +
"pages," +
"wall," +
"groups," +
"messages," +
"offline," +
"notifications"
private const val redirectUrl = "https://oauth.vk.com/blank.html"
fun getDirectAuthUrl(
login: String,
password: String,
twoFa: Boolean = false,
twoFaCode: String = "",
captcha: Pair<String, String>? = null
) = "https://oauth.vk.com/token?" +
"grant_type=password&" +
"client_id=${VKConstants.VK_APP_ID}&" +
"client_secret=${VKConstants.VK_SECRET}&" +
"username=$login&" +
"password=$password&" +
"scope=$scope&" +
"2fa_supported=1&" +
"force_sms=${if (twoFa) "1" else "0"}" +
(if (twoFa) "code=$twoFaCode" else "") +
(if (captcha == null) "" else "&captcha_sid=${captcha.first}&captcha_key=${captcha.second}") +
"&v=${URLEncoder.encode(VKApi.API_VERSION, "utf-8")}"
fun getSendSmsCodeUrl(sid: String) = "https://api.vk.com/method/auth.validatePhone?" +
"sid=$sid&" +
"&v=${URLEncoder.encode(VKApi.API_VERSION, "utf-8")}"
fun getOAuthUrl(settings: String) = "https://oauth.vk.com/authorize?" +
"client_id=${UserConfig.FAST_APP_ID}&" +
"display=mobile&" +
"scope=$settings&" +
"redirect_uri=${
URLEncoder.encode(
redirectUrl,
"utf-8"
)
}&" +
"response_type=token&" +
"v=${URLEncoder.encode(VKApi.API_VERSION, "utf-8")}"
fun parseRedirectUrl(url: String): Pair<String, Int> {
val accessToken = VKUtil.extractPattern(url, "access_token=(.*?)&") ?: ""
val userId = VKUtil.extractPattern(url, "user_id=(\\d*)")?.toIntOrNull() ?: -1
if (BuildConfig.DEBUG) {
Log.i(TAG, "access_token=$accessToken")
Log.i(TAG, "user_id=$userId")
}
if (accessToken.isEmpty() || userId == -1) throw Exception(
"Failed to parse redirect url: $url"
)
return accessToken to userId
}
}
@@ -7,6 +7,30 @@ object VKConstants {
const val USER_FIELDS =
"photo_50,photo_100,photo_200,status,screen_name,online,online_mobile,last_seen,verified,sex"
const val API_VERSION = "5.132"
const val VK_APP_ID = "2274003"
const val VK_SECRET = "hHbZxrka2uZ6jB1inYsH"
object Auth {
const val SCOPE = "notify," +
"friends," +
"photos," +
"audio," +
"video," +
"docs," +
"status," +
"notes," +
"pages," +
"wall," +
"groups," +
"messages," +
"offline," +
"notifications"
object GrantType {
const val PASSWORD = "password"
}
}
}
@@ -7,8 +7,8 @@ import org.json.JSONArray
import org.json.JSONObject
import java.text.SimpleDateFormat
import java.util.*
import java.util.regex.Pattern
// TODO: 8/31/2021 review
object VKUtil {
private const val TAG = "VKUtil"
@@ -23,26 +23,6 @@ object VKUtil {
return throwable.error == VKErrors.NEED_CAPTCHA
}
fun extractValidationSid(throwable: Throwable): String? {
if (throwable !is VKException) return null
return throwable.json?.optString("validation_sid")
}
fun extractPattern(string: String, pattern: String): String? {
val p = Pattern.compile(pattern)
val m = p.matcher(string)
return if (!m.find()) null else m.toMatchResult().group(1)
}
private const val pattern_string_profile_id = "^(id)?(\\d{1,10})$"
private val pattern_profile_id = Pattern.compile(pattern_string_profile_id)
fun parseProfileId(text: String): String? {
val m = pattern_profile_id.matcher(text)
return if (!m.find()) null else m.group(2)
}
fun sortMessagesByDate(
values: ArrayList<VKMessage>,
firstOnTop: Boolean
@@ -292,7 +272,7 @@ object VKUtil {
message.text = text
// val fromId =
// if (isMessageHasFlag(flags, "outbox")) com.meloda.fast.UserConfig.userId
// if (isMessageHasFlag(flags, "outbox")) com.meloda.fast.api.UserConfig.userId
// else peerId
message.fromId = peerId
@@ -357,7 +337,7 @@ object VKUtil {
val editTime = array.optInt(10)
message.editTime = editTime
// val out = fromId == com.meloda.fast.UserConfig.userId
// val out = fromId == com.meloda.fast.api.UserConfig.userId
// message.isOut = out
//
// if (message.isFromUser()) {
@@ -1,205 +0,0 @@
package com.meloda.fast.api.method
import com.meloda.fast.util.ArrayUtils
class MessageMethodSetter(name: String) : MethodSetter(name) {
fun out(value: Boolean): MessageMethodSetter {
put("out", value)
return this
}
fun timeOffset(value: Int): MessageMethodSetter {
put("time_offset", value)
return this
}
fun filters(value: Int): MessageMethodSetter {
put("filters", value)
return this
}
fun previewLength(value: Int): MessageMethodSetter {
put("preview_length", value)
return this
}
fun lastMessageId(value: Int): MessageMethodSetter {
put("last_message_id", value)
return this
}
fun unread(value: Boolean): MessageMethodSetter {
put("unread", value)
return this
}
fun messageIds(vararg ids: Int): MessageMethodSetter {
put("message_ids", ArrayUtils.asString(ids))
return this
}
fun messageIds(ids: ArrayList<Int>): MessageMethodSetter {
put("message_ids", ArrayUtils.asString(ids))
return this
}
fun q(query: String): MessageMethodSetter {
put("q", query)
return this
}
fun startMessageId(id: Int): MessageMethodSetter {
put("start_message_id", id)
return this
}
fun peerId(value: Int): MessageMethodSetter {
put("peer_id", value)
return this
}
fun peerIds(vararg values: Int): MessageMethodSetter {
put("peer_ids", com.meloda.fast.util.ArrayUtils.asString(values))
return this
}
fun reversed(value: Boolean): MessageMethodSetter {
put("rev", value)
return this
}
fun domain(value: String): MessageMethodSetter {
put("domain", value)
return this
}
fun chatId(value: Int): MessageMethodSetter {
put("chat_id", value)
return this
}
fun message(message: String): MessageMethodSetter {
put("message", message)
return this
}
fun randomId(value: Int): MessageMethodSetter {
put("random_id", value)
return this
}
fun lat(lat: Double): MessageMethodSetter {
put("lat", lat)
return this
}
fun longitude(value: Long): MessageMethodSetter {
put("LONG", value)
return this
}
fun attachment(attachments: Collection<String>): MessageMethodSetter {
put("attachment", com.meloda.fast.util.ArrayUtils.asString(attachments))
return this
}
fun attachment(vararg attachments: String): MessageMethodSetter {
put("attachment", com.meloda.fast.util.ArrayUtils.asString(*attachments))
return this
}
fun forwardMessages(ids: Collection<String>): MessageMethodSetter {
put("forward_messages", com.meloda.fast.util.ArrayUtils.asString(ids))
return this
}
fun forwardMessages(vararg ids: Int): MessageMethodSetter {
put("forward_messages", com.meloda.fast.util.ArrayUtils.asString(ids))
return this
}
fun stickerId(value: Int): MessageMethodSetter {
put("sticker_id", value)
return this
}
fun messageId(value: Int): MessageMethodSetter {
put("message_id", value)
return this
}
fun important(value: Boolean): MessageMethodSetter {
put("important", value)
return this
}
fun ts(value: Long): MessageMethodSetter {
put("ts", value)
return this
}
fun pts(value: Int): MessageMethodSetter {
put("pts", value)
return this
}
fun msgsLimit(limit: Int): MessageMethodSetter {
put("msgs_limit", limit)
return this
}
fun onlines(onlines: Boolean): MessageMethodSetter {
put("onlines", onlines)
return this
}
fun maxMsgId(id: Int): MessageMethodSetter {
put("max_msg_id", id)
return this
}
fun chatIds(vararg ids: Int): MessageMethodSetter {
put("max_msg_id", com.meloda.fast.util.ArrayUtils.asString(ids))
return this
}
fun chatIds(ids: Collection<Int>): MessageMethodSetter {
put("max_msg_id", com.meloda.fast.util.ArrayUtils.asString(ids))
return this
}
fun title(title: String): MessageMethodSetter {
put("title", title)
return this
}
fun type(typing: Boolean): MessageMethodSetter {
if (typing) {
put("type", "typing")
}
return this
}
fun mediaType(type: String): MessageMethodSetter {
put("media_type", type)
return this
}
fun photoSizes(value: Boolean): MessageMethodSetter {
return put("photo_sizes", value) as MessageMethodSetter
}
fun filter(value: String): MessageMethodSetter {
return put("filter", value) as MessageMethodSetter
}
fun extended(value: Boolean): MessageMethodSetter {
return put("extended", value) as MessageMethodSetter
}
fun markConversationAsRead(asRead: Boolean): MessageMethodSetter {
put("mark_conversation_as_read", asRead)
return this
}
}
@@ -1,169 +0,0 @@
package com.meloda.fast.api.method
import android.util.ArrayMap
import android.util.Log
import com.meloda.fast.BuildConfig
import com.meloda.fast.api.OnResponseListener
import com.meloda.fast.api.VKApi
import kotlinx.coroutines.flow.Flow
import java.net.URLEncoder
@Suppress("UNCHECKED_CAST")
open class MethodSetter(private val name: String) {
private val params: ArrayMap<String, String> = ArrayMap()
fun put(key: String, value: Any): MethodSetter {
params[key] = value.toString()
return this
}
fun put(key: String, value: String): MethodSetter {
params[key] = value
return this
}
fun put(key: String, value: Int): MethodSetter {
params[key] = value.toString()
return this
}
fun put(key: String, value: Long): MethodSetter {
params[key] = value.toString()
return this
}
fun put(key: String, value: Boolean): MethodSetter {
params[key] = if (value) "1" else "0"
return this
}
private fun getSignedUrl(): String {
if (!params.containsKey("access_token")) {
params["access_token"] = VKApi.token
}
if (!params.containsKey("v")) {
params["v"] = VKApi.API_VERSION
}
if (!params.containsKey("lang")) {
params["lang"] = VKApi.language
}
return "${VKApi.BASE_URL}$name?${retrieveParams()}"
}
private fun retrieveParams(): String {
val builder = StringBuilder()
for (i in 0 until params.size) {
val key = params.keyAt(i)
val value = params.valueAt(i)
if (builder.isNotEmpty()) {
builder.append("&")
}
builder.append(key)
builder.append("=")
builder.append(URLEncoder.encode(value, "UTF-8"))
}
val params = builder.toString()
if (BuildConfig.DEBUG) {
Log.i("MethodSetter", "retrieved params: $params")
}
return params
}
suspend fun <E> executeSuspend(cls: Class<E>): Flow<E> {
return VKApi.suspendExecute(getSignedUrl(), cls)
}
fun <E> execute(cls: Class<E>): ArrayList<E>? {
return VKApi.execute(getSignedUrl(), cls)
}
fun <E> executeArray(cls: Class<E>, listener: OnResponseListener<ArrayList<E>>) {
VKApi.executeArray(getSignedUrl(), cls, listener)
}
fun <E> execute(cls: Class<E>, listener: OnResponseListener<E>?) {
VKApi.execute(getSignedUrl(), cls, listener)
}
fun userId(value: Int): MethodSetter {
return put("user_id", value)
}
fun userIds(vararg ids: Int): MethodSetter {
return put("user_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
}
fun userIds(ids: ArrayList<Int>): MethodSetter {
return put("user_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
}
fun ownerId(value: Int): MethodSetter {
return put("owner_id", value)
}
fun groupId(value: Int): MethodSetter {
return put("group_id", value)
}
fun groupIds(vararg ids: Int): MethodSetter {
return put("group_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
}
fun groupIds(ids: ArrayList<Int>): MethodSetter {
return put("group_ids", com.meloda.fast.util.ArrayUtils.asString(ids))
}
fun fields(values: String): MethodSetter {
return put("fields", values)
}
fun count(value: Int): MethodSetter {
return put("count", value)
}
fun sort(value: Int): MethodSetter {
put("sort", value)
return this
}
/**
*
* hints — сортировать по рейтингу, аналогично тому, как друзья сортируются в разделе Мои друзья
* random — возвращает друзей в случайном порядке.
* mobile — возвращает выше тех друзей, у которых установлены мобильные приложения.
* name — сортировать по имени (долго)
*
*/
fun order(value: String): MethodSetter {
put("order", value)
return this
}
fun offset(value: Int = 0): MethodSetter {
return put("offset", value)
}
fun nameCase(value: String): MethodSetter {
return put("name_case", value)
}
fun captchaSid(value: String): MethodSetter {
return put("captcha_sid", value)
}
fun captchaKey(value: String): MethodSetter {
return put("captcha_key", value)
}
}
@@ -1,44 +0,0 @@
package com.meloda.fast.api.method
class UserMethodSetter(name: String) : MethodSetter(name) {
fun extended(extended: Boolean): UserMethodSetter {
put("extended", extended)
return this
}
fun type(type: String): UserMethodSetter {
put("type", type)
return this
}
fun comment(comment: String): UserMethodSetter {
put("comment", comment)
return this
}
fun latitude(latitude: Float): UserMethodSetter {
put("latitude", latitude)
return this
}
fun longitude(longitude: Float): UserMethodSetter {
put("longitude", longitude)
return this
}
fun accuracy(accuracy: Int): UserMethodSetter {
put("accuracy", accuracy)
return this
}
fun timeout(timeout: Int): UserMethodSetter {
put("timeout", timeout)
return this
}
fun radius(radius: Int): UserMethodSetter {
put("radius", radius)
return this
}
}
@@ -1,6 +1,6 @@
package com.meloda.fast.api.network
import com.meloda.fast.api.VKApi
import com.meloda.fast.api.VKConstants
import okhttp3.Interceptor
import okhttp3.Response
import java.net.URLEncoder
@@ -9,7 +9,7 @@ class AuthInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val builder = chain.request().url.newBuilder()
.addQueryParameter("v", URLEncoder.encode(VKApi.API_VERSION, "utf-8"))
.addQueryParameter("v", URLEncoder.encode(VKConstants.API_VERSION, "utf-8"))
return chain.proceed(chain.request().newBuilder().apply { url(builder.build()) }.build())
}