2016-07-07 09:39:32 +02:00
|
|
|
/*
|
|
|
|
* Twidere - Twitter client for Android
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012-2014 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.activity
|
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
import android.accounts.Account
|
2016-12-02 05:36:50 +01:00
|
|
|
import android.accounts.AccountAuthenticatorResponse
|
|
|
|
import android.accounts.AccountManager
|
2016-07-07 09:39:32 +02:00
|
|
|
import android.app.Activity
|
|
|
|
import android.app.Dialog
|
2017-01-19 12:43:20 +01:00
|
|
|
import android.content.ActivityNotFoundException
|
2016-07-07 09:39:32 +02:00
|
|
|
import android.content.Context
|
|
|
|
import android.content.DialogInterface
|
|
|
|
import android.content.Intent
|
|
|
|
import android.content.res.ColorStateList
|
|
|
|
import android.net.Uri
|
|
|
|
import android.os.AsyncTask
|
|
|
|
import android.os.Bundle
|
2017-01-19 12:43:20 +01:00
|
|
|
import android.support.customtabs.CustomTabsIntent
|
2016-07-07 09:39:32 +02:00
|
|
|
import android.support.v4.app.DialogFragment
|
|
|
|
import android.support.v4.content.ContextCompat
|
2016-12-16 10:13:35 +01:00
|
|
|
import android.support.v4.util.ArraySet
|
2016-07-07 09:39:32 +02:00
|
|
|
import android.support.v4.view.ViewCompat
|
|
|
|
import android.support.v7.app.AlertDialog
|
|
|
|
import android.text.Editable
|
|
|
|
import android.text.InputType
|
|
|
|
import android.text.TextUtils
|
|
|
|
import android.text.TextWatcher
|
|
|
|
import android.util.Log
|
|
|
|
import android.view.Menu
|
|
|
|
import android.view.MenuItem
|
|
|
|
import android.view.View
|
|
|
|
import android.view.View.OnClickListener
|
|
|
|
import android.widget.EditText
|
|
|
|
import android.widget.TextView
|
|
|
|
import android.widget.Toast
|
2016-12-03 06:48:40 +01:00
|
|
|
import com.bluelinelabs.logansquare.LoganSquare
|
2016-07-07 09:39:32 +02:00
|
|
|
import com.rengwuxian.materialedittext.MaterialEditText
|
|
|
|
import kotlinx.android.synthetic.main.activity_sign_in.*
|
2016-12-16 10:13:35 +01:00
|
|
|
import org.mariotaku.kpreferences.get
|
2017-01-02 09:33:27 +01:00
|
|
|
import org.mariotaku.ktextension.*
|
2016-07-07 09:39:32 +02:00
|
|
|
import org.mariotaku.microblog.library.MicroBlog
|
|
|
|
import org.mariotaku.microblog.library.MicroBlogException
|
|
|
|
import org.mariotaku.microblog.library.twitter.TwitterOAuth
|
|
|
|
import org.mariotaku.microblog.library.twitter.auth.BasicAuthorization
|
|
|
|
import org.mariotaku.microblog.library.twitter.auth.EmptyAuthorization
|
|
|
|
import org.mariotaku.microblog.library.twitter.model.Paging
|
|
|
|
import org.mariotaku.microblog.library.twitter.model.User
|
|
|
|
import org.mariotaku.restfu.http.Endpoint
|
|
|
|
import org.mariotaku.restfu.oauth.OAuthAuthorization
|
|
|
|
import org.mariotaku.restfu.oauth.OAuthToken
|
|
|
|
import org.mariotaku.twidere.BuildConfig
|
|
|
|
import org.mariotaku.twidere.R
|
|
|
|
import org.mariotaku.twidere.TwidereConstants.*
|
2016-12-03 06:48:40 +01:00
|
|
|
import org.mariotaku.twidere.annotation.AccountType
|
2016-12-12 06:42:27 +01:00
|
|
|
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_API_CONFIG
|
2016-12-09 06:26:26 +01:00
|
|
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants.KEY_CREDENTIALS_TYPE
|
2017-01-19 12:43:20 +01:00
|
|
|
import org.mariotaku.twidere.constant.chromeCustomTabKey
|
2016-12-12 06:42:27 +01:00
|
|
|
import org.mariotaku.twidere.constant.defaultAPIConfigKey
|
2016-12-16 10:13:35 +01:00
|
|
|
import org.mariotaku.twidere.constant.randomizeAccountNameKey
|
2016-12-29 06:50:18 +01:00
|
|
|
import org.mariotaku.twidere.extension.model.getColor
|
|
|
|
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
|
2016-12-15 06:11:32 +01:00
|
|
|
import org.mariotaku.twidere.extension.model.official
|
2017-01-25 13:08:23 +01:00
|
|
|
import org.mariotaku.twidere.fragment.APIEditorDialogFragment
|
2016-07-07 09:39:32 +02:00
|
|
|
import org.mariotaku.twidere.fragment.BaseDialogFragment
|
|
|
|
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
2016-12-12 06:42:27 +01:00
|
|
|
import org.mariotaku.twidere.model.CustomAPIConfig
|
2016-12-03 06:48:40 +01:00
|
|
|
import org.mariotaku.twidere.model.ParcelableUser
|
|
|
|
import org.mariotaku.twidere.model.SingleResponse
|
|
|
|
import org.mariotaku.twidere.model.UserKey
|
2016-12-15 06:11:32 +01:00
|
|
|
import org.mariotaku.twidere.model.account.AccountExtras
|
2016-12-03 06:48:40 +01:00
|
|
|
import org.mariotaku.twidere.model.account.StatusNetAccountExtras
|
|
|
|
import org.mariotaku.twidere.model.account.TwitterAccountExtras
|
|
|
|
import org.mariotaku.twidere.model.account.cred.BasicCredentials
|
|
|
|
import org.mariotaku.twidere.model.account.cred.Credentials
|
|
|
|
import org.mariotaku.twidere.model.account.cred.EmptyCredentials
|
|
|
|
import org.mariotaku.twidere.model.account.cred.OAuthCredentials
|
2016-12-15 06:11:32 +01:00
|
|
|
import org.mariotaku.twidere.model.analyzer.SignIn
|
2016-12-04 04:58:03 +01:00
|
|
|
import org.mariotaku.twidere.model.util.AccountUtils
|
|
|
|
import org.mariotaku.twidere.model.util.ParcelableUserUtils
|
|
|
|
import org.mariotaku.twidere.model.util.UserKeyUtils
|
2016-07-07 09:39:32 +02:00
|
|
|
import org.mariotaku.twidere.util.*
|
|
|
|
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.*
|
|
|
|
import org.mariotaku.twidere.util.view.ConsumerKeySecretValidator
|
2017-01-07 17:13:11 +01:00
|
|
|
import java.io.IOException
|
2016-07-07 09:39:32 +02:00
|
|
|
import java.lang.ref.WeakReference
|
2016-12-16 10:13:35 +01:00
|
|
|
import java.util.*
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-02 05:36:50 +01:00
|
|
|
|
2017-01-25 13:08:23 +01:00
|
|
|
class SignInActivity : BaseActivity(), OnClickListener, TextWatcher, APIEditorDialogFragment.APIEditorCallback {
|
2016-12-12 06:42:27 +01:00
|
|
|
private lateinit var apiConfig: CustomAPIConfig
|
2016-07-07 09:39:32 +02:00
|
|
|
private var apiChangeTimestamp: Long = 0
|
|
|
|
private var signInTask: AbstractSignInTask? = null
|
|
|
|
|
2016-12-02 05:36:50 +01:00
|
|
|
private var accountAuthenticatorResponse: AccountAuthenticatorResponse? = null
|
|
|
|
private var accountAuthenticatorResult: Bundle? = null
|
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
accountAuthenticatorResponse = intent.getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE)
|
|
|
|
accountAuthenticatorResponse?.onRequestContinued()
|
|
|
|
|
|
|
|
setContentView(R.layout.activity_sign_in)
|
|
|
|
|
|
|
|
if (savedInstanceState != null) {
|
2016-12-12 06:42:27 +01:00
|
|
|
apiConfig = savedInstanceState.getParcelable(EXTRA_API_CONFIG)
|
2016-12-02 05:36:50 +01:00
|
|
|
apiChangeTimestamp = savedInstanceState.getLong(EXTRA_API_LAST_CHANGE)
|
2016-12-12 06:42:27 +01:00
|
|
|
} else {
|
|
|
|
apiConfig = kPreferences[defaultAPIConfigKey]
|
2016-12-02 05:36:50 +01:00
|
|
|
}
|
|
|
|
|
2016-12-12 06:42:27 +01:00
|
|
|
val isTwipOMode = apiConfig.credentialsType == Credentials.Type.EMPTY
|
2016-12-02 05:36:50 +01:00
|
|
|
usernamePasswordContainer.visibility = if (isTwipOMode) View.GONE else View.VISIBLE
|
|
|
|
|
|
|
|
editUsername.addTextChangedListener(this)
|
|
|
|
editPassword.addTextChangedListener(this)
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-02 05:36:50 +01:00
|
|
|
signIn.setOnClickListener(this)
|
|
|
|
signUp.setOnClickListener(this)
|
|
|
|
passwordSignIn.setOnClickListener(this)
|
|
|
|
|
|
|
|
val color = ColorStateList.valueOf(ContextCompat.getColor(this,
|
|
|
|
R.color.material_light_green))
|
|
|
|
ViewCompat.setBackgroundTintList(signIn, color)
|
|
|
|
|
|
|
|
|
|
|
|
val consumerKey = preferences.getString(KEY_CONSUMER_KEY, null)
|
|
|
|
val consumerSecret = preferences.getString(KEY_CONSUMER_SECRET, null)
|
|
|
|
if (BuildConfig.SHOW_CUSTOM_TOKEN_DIALOG && savedInstanceState == null &&
|
|
|
|
!preferences.getBoolean(KEY_CONSUMER_KEY_SECRET_SET, false) &&
|
|
|
|
!Utils.isCustomConsumerKeySecret(consumerKey, consumerSecret)) {
|
|
|
|
val df = SetConsumerKeySecretDialogFragment()
|
|
|
|
df.isCancelable = false
|
|
|
|
df.show(supportFragmentManager, "set_consumer_key_secret")
|
|
|
|
}
|
|
|
|
|
|
|
|
updateSignInType()
|
|
|
|
setSignInButton()
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
2016-12-02 05:36:50 +01:00
|
|
|
override fun onDestroy() {
|
|
|
|
loaderManager.destroyLoader(0)
|
|
|
|
super.onDestroy()
|
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-02 05:36:50 +01:00
|
|
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
2016-12-29 06:50:18 +01:00
|
|
|
super.onCreateOptionsMenu(menu)
|
2016-12-02 05:36:50 +01:00
|
|
|
menuInflater.inflate(R.menu.menu_sign_in, menu)
|
|
|
|
return true
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
2016-12-02 05:36:50 +01:00
|
|
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
2016-07-07 09:39:32 +02:00
|
|
|
when (requestCode) {
|
|
|
|
REQUEST_EDIT_API -> {
|
|
|
|
if (resultCode == Activity.RESULT_OK) {
|
2016-12-12 06:42:27 +01:00
|
|
|
apiConfig = data!!.getParcelableExtra(EXTRA_API_CONFIG)
|
2016-07-07 09:39:32 +02:00
|
|
|
updateSignInType()
|
|
|
|
}
|
|
|
|
setSignInButton()
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
REQUEST_BROWSER_SIGN_IN -> {
|
|
|
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
|
|
|
doBrowserLogin(data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
super.onActivityResult(requestCode, resultCode, data)
|
|
|
|
}
|
|
|
|
|
2016-12-02 05:36:50 +01:00
|
|
|
override fun finish() {
|
|
|
|
accountAuthenticatorResponse?.let { response ->
|
|
|
|
// send the result bundle back if set, otherwise send an error.
|
|
|
|
if (accountAuthenticatorResult != null) {
|
|
|
|
response.onResult(accountAuthenticatorResult)
|
|
|
|
} else {
|
|
|
|
response.onError(AccountManager.ERROR_CODE_CANCELED, "canceled")
|
|
|
|
}
|
|
|
|
accountAuthenticatorResponse = null
|
|
|
|
}
|
|
|
|
super.finish()
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-07-07 09:39:32 +02:00
|
|
|
override fun onClick(v: View) {
|
|
|
|
when (v) {
|
|
|
|
signUp -> {
|
2017-01-19 12:43:20 +01:00
|
|
|
val signUpUrl = apiConfig.signUpUrl ?: return
|
|
|
|
val uri = Uri.parse(signUpUrl)
|
|
|
|
if (preferences[chromeCustomTabKey]) {
|
|
|
|
val builder = CustomTabsIntent.Builder()
|
|
|
|
builder.setToolbarColor(overrideTheme.colorToolbar)
|
|
|
|
val intent = builder.build()
|
|
|
|
try {
|
|
|
|
intent.launchUrl(this, uri)
|
|
|
|
} catch (e: ActivityNotFoundException) {
|
|
|
|
// Ignore
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
val intent = Intent(Intent.ACTION_VIEW, uri)
|
|
|
|
try {
|
|
|
|
startActivity(intent)
|
|
|
|
} catch (e: ActivityNotFoundException) {
|
|
|
|
// Ignore
|
|
|
|
}
|
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
signIn -> {
|
|
|
|
if (usernamePasswordContainer.visibility != View.VISIBLE) {
|
|
|
|
editUsername.text = null
|
|
|
|
editPassword.text = null
|
|
|
|
}
|
|
|
|
doLogin()
|
|
|
|
}
|
|
|
|
passwordSignIn -> {
|
2017-01-19 12:43:20 +01:00
|
|
|
executeAfterFragmentResumed { fragment ->
|
2016-07-07 09:39:32 +02:00
|
|
|
val df = PasswordSignInDialogFragment()
|
2017-01-19 12:43:20 +01:00
|
|
|
df.show(fragment.supportFragmentManager, "password_sign_in")
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
|
|
when (item.itemId) {
|
|
|
|
android.R.id.home -> {
|
|
|
|
val accountKeys = DataStoreUtils.getActivatedAccountKeys(this)
|
2016-12-03 06:48:40 +01:00
|
|
|
if (accountKeys.isNotEmpty()) {
|
2016-07-07 09:39:32 +02:00
|
|
|
onBackPressed()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
R.id.settings -> {
|
|
|
|
if (signInTask != null && signInTask!!.status == AsyncTask.Status.RUNNING)
|
|
|
|
return false
|
|
|
|
val intent = Intent(this, SettingsActivity::class.java)
|
|
|
|
startActivity(intent)
|
|
|
|
}
|
|
|
|
R.id.edit_api -> {
|
|
|
|
if (signInTask != null && signInTask!!.status == AsyncTask.Status.RUNNING)
|
|
|
|
return false
|
|
|
|
setDefaultAPI()
|
2017-01-25 13:08:23 +01:00
|
|
|
val df = APIEditorDialogFragment()
|
|
|
|
df.arguments = Bundle {
|
|
|
|
this[EXTRA_API_CONFIG] = apiConfig
|
|
|
|
this[APIEditorDialogFragment.EXTRA_SHOW_LOAD_DEFAULTS] = true
|
|
|
|
}
|
|
|
|
df.show(supportFragmentManager, "edit_api_config")
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return super.onOptionsItemSelected(item)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
2016-12-21 09:53:53 +01:00
|
|
|
super.onPrepareOptionsMenu(menu)
|
2016-07-07 09:39:32 +02:00
|
|
|
val itemBrowser = menu.findItem(R.id.open_in_browser)
|
|
|
|
if (itemBrowser != null) {
|
2016-12-12 06:42:27 +01:00
|
|
|
val is_oauth = apiConfig.credentialsType == Credentials.Type.OAUTH
|
2016-07-07 09:39:32 +02:00
|
|
|
itemBrowser.isVisible = is_oauth
|
|
|
|
itemBrowser.isEnabled = is_oauth
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2017-01-25 13:08:23 +01:00
|
|
|
override fun onSaveInstanceState(outState: Bundle) {
|
2016-12-12 06:42:27 +01:00
|
|
|
outState.putParcelable(EXTRA_API_CONFIG, apiConfig)
|
2016-07-07 09:39:32 +02:00
|
|
|
outState.putLong(EXTRA_API_LAST_CHANGE, apiChangeTimestamp)
|
|
|
|
super.onSaveInstanceState(outState)
|
|
|
|
}
|
|
|
|
|
2016-12-02 05:36:50 +01:00
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
2016-07-07 09:39:32 +02:00
|
|
|
setSignInButton()
|
|
|
|
}
|
|
|
|
|
2017-01-25 13:08:23 +01:00
|
|
|
override fun onSaveAPIConfig(config: CustomAPIConfig) {
|
|
|
|
apiConfig = config
|
|
|
|
|
|
|
|
updateSignInType()
|
|
|
|
setSignInButton()
|
|
|
|
invalidateOptionsMenu()
|
|
|
|
}
|
|
|
|
|
|
|
|
internal fun updateSignInType() {
|
|
|
|
when (apiConfig.credentialsType) {
|
|
|
|
Credentials.Type.XAUTH, Credentials.Type.BASIC -> {
|
|
|
|
usernamePasswordContainer.visibility = View.VISIBLE
|
|
|
|
}
|
|
|
|
Credentials.Type.EMPTY -> {
|
|
|
|
usernamePasswordContainer.visibility = View.GONE
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
usernamePasswordContainer.visibility = View.GONE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal fun openBrowserLogin(): Boolean {
|
|
|
|
if (apiConfig.credentialsType != Credentials.Type.OAUTH || signInTask != null && signInTask!!.status == AsyncTask.Status.RUNNING)
|
|
|
|
return true
|
|
|
|
val intent = Intent(this, BrowserSignInActivity::class.java)
|
|
|
|
intent.putExtra(EXTRA_API_CONFIG, apiConfig)
|
|
|
|
startActivityForResult(intent, REQUEST_BROWSER_SIGN_IN)
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2016-07-07 09:39:32 +02:00
|
|
|
internal fun doLogin() {
|
|
|
|
if (signInTask != null && signInTask!!.status == AsyncTask.Status.RUNNING) {
|
|
|
|
signInTask!!.cancel(true)
|
|
|
|
}
|
2017-01-07 17:13:11 +01:00
|
|
|
if (apiConfig.credentialsType == Credentials.Type.OAUTH) {
|
2016-07-07 09:39:32 +02:00
|
|
|
openBrowserLogin()
|
|
|
|
return
|
|
|
|
}
|
2016-12-12 06:42:27 +01:00
|
|
|
|
2016-07-07 09:39:32 +02:00
|
|
|
val username = editUsername.text.toString()
|
|
|
|
val password = editPassword.text.toString()
|
2017-01-07 17:13:11 +01:00
|
|
|
signInTask = SignInTask(this, username, password, apiConfig)
|
2016-07-07 09:39:32 +02:00
|
|
|
AsyncTaskUtils.executeTask<AbstractSignInTask, Any>(signInTask)
|
|
|
|
}
|
|
|
|
|
2017-01-25 13:08:23 +01:00
|
|
|
internal fun onSignInResult(result: SignInResponse) {
|
|
|
|
val am = AccountManager.get(this)
|
|
|
|
setSignInButton()
|
|
|
|
if (result.alreadyLoggedIn) {
|
|
|
|
result.updateAccount(am)
|
|
|
|
Toast.makeText(this, R.string.error_already_logged_in, Toast.LENGTH_SHORT).show()
|
|
|
|
} else {
|
|
|
|
result.addAccount(am, preferences[randomizeAccountNameKey])
|
|
|
|
Analyzer.log(SignIn(true, accountType = result.accountType.first, credentialsType = apiConfig.credentialsType,
|
|
|
|
officialKey = result.accountType.second?.official ?: false))
|
|
|
|
finishSignIn()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal fun dismissDialogFragment(tag: String) {
|
|
|
|
executeAfterFragmentResumed {
|
|
|
|
val fm = supportFragmentManager
|
|
|
|
val f = fm.findFragmentByTag(tag)
|
|
|
|
if (f is DialogFragment) {
|
|
|
|
f.dismiss()
|
|
|
|
}
|
|
|
|
Unit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal fun onSignInError(exception: Exception) {
|
|
|
|
if (BuildConfig.DEBUG) {
|
|
|
|
Log.w(LOGTAG, exception)
|
|
|
|
}
|
|
|
|
var errorReason: String? = null
|
|
|
|
if (exception is AuthenticityTokenException) {
|
|
|
|
Toast.makeText(this, R.string.wrong_api_key, Toast.LENGTH_SHORT).show()
|
|
|
|
errorReason = "wrong_api_key"
|
|
|
|
} else if (exception is WrongUserPassException) {
|
|
|
|
Toast.makeText(this, R.string.wrong_username_password, Toast.LENGTH_SHORT).show()
|
|
|
|
errorReason = "wrong_username_password"
|
|
|
|
} else if (exception is SignInTask.WrongBasicCredentialException) {
|
|
|
|
Toast.makeText(this, R.string.wrong_username_password, Toast.LENGTH_SHORT).show()
|
|
|
|
errorReason = "wrong_username_password"
|
|
|
|
} else if (exception is SignInTask.WrongAPIURLFormatException) {
|
|
|
|
Toast.makeText(this, R.string.wrong_api_key, Toast.LENGTH_SHORT).show()
|
|
|
|
errorReason = "wrong_api_key"
|
|
|
|
} else if (exception is LoginVerificationException) {
|
|
|
|
Toast.makeText(this, R.string.login_verification_failed, Toast.LENGTH_SHORT).show()
|
|
|
|
errorReason = "login_verification_failed"
|
|
|
|
} else if (exception is AuthenticationException) {
|
|
|
|
Utils.showErrorMessage(this, getString(R.string.action_signing_in), exception.cause, true)
|
|
|
|
} else {
|
|
|
|
Utils.showErrorMessage(this, getString(R.string.action_signing_in), exception, true)
|
|
|
|
}
|
|
|
|
Analyzer.log(SignIn(false, credentialsType = apiConfig.credentialsType,
|
|
|
|
errorReason = errorReason, accountType = apiConfig.type))
|
|
|
|
}
|
|
|
|
|
|
|
|
internal fun onSignInStart() {
|
|
|
|
showSignInProgressDialog()
|
|
|
|
}
|
|
|
|
|
|
|
|
internal fun showSignInProgressDialog() {
|
|
|
|
executeAfterFragmentResumed {
|
|
|
|
if (isFinishing) return@executeAfterFragmentResumed
|
|
|
|
val fm = supportFragmentManager
|
|
|
|
val ft = fm.beginTransaction()
|
|
|
|
val fragment = ProgressDialogFragment()
|
|
|
|
fragment.isCancelable = false
|
|
|
|
fragment.show(ft, FRAGMENT_TAG_SIGN_IN_PROGRESS)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal fun setUsernamePassword(username: String, password: String) {
|
|
|
|
editUsername.setText(username)
|
|
|
|
editPassword.setText(password)
|
|
|
|
}
|
|
|
|
|
2016-07-07 09:39:32 +02:00
|
|
|
private fun doBrowserLogin(intent: Intent?) {
|
|
|
|
if (intent == null) return
|
2016-12-12 06:42:27 +01:00
|
|
|
if (signInTask?.status == AsyncTask.Status.RUNNING) {
|
|
|
|
signInTask?.cancel(true)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
val verifier = intent.getStringExtra(EXTRA_OAUTH_VERIFIER)
|
|
|
|
val requestToken = OAuthToken(intent.getStringExtra(EXTRA_REQUEST_TOKEN),
|
|
|
|
intent.getStringExtra(EXTRA_REQUEST_TOKEN_SECRET))
|
2017-01-07 17:13:11 +01:00
|
|
|
signInTask = BrowserSignInTask(this, apiConfig, requestToken, verifier)
|
2016-07-07 09:39:32 +02:00
|
|
|
AsyncTaskUtils.executeTask<AbstractSignInTask, Any>(signInTask)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun setDefaultAPI() {
|
|
|
|
val apiLastChange = preferences.getLong(KEY_API_LAST_CHANGE, apiChangeTimestamp)
|
|
|
|
val defaultApiChanged = apiLastChange != apiChangeTimestamp
|
|
|
|
val apiUrlFormat = Utils.getNonEmptyString(preferences, KEY_API_URL_FORMAT, DEFAULT_TWITTER_API_URL_FORMAT)
|
2016-12-09 06:26:26 +01:00
|
|
|
val authType = preferences.getString(KEY_CREDENTIALS_TYPE, Credentials.Type.OAUTH)
|
2016-07-07 09:39:32 +02:00
|
|
|
val sameOAuthSigningUrl = preferences.getBoolean(KEY_SAME_OAUTH_SIGNING_URL, false)
|
|
|
|
val noVersionSuffix = preferences.getBoolean(KEY_NO_VERSION_SUFFIX, false)
|
|
|
|
val consumerKey = Utils.getNonEmptyString(preferences, KEY_CONSUMER_KEY, TWITTER_CONSUMER_KEY)
|
|
|
|
val consumerSecret = Utils.getNonEmptyString(preferences, KEY_CONSUMER_SECRET, TWITTER_CONSUMER_SECRET)
|
2016-12-12 06:42:27 +01:00
|
|
|
if (TextUtils.isEmpty(apiConfig.apiUrlFormat) || defaultApiChanged) {
|
|
|
|
apiConfig.apiUrlFormat = apiUrlFormat
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
if (defaultApiChanged) {
|
2016-12-12 06:42:27 +01:00
|
|
|
apiConfig.credentialsType = authType
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
if (defaultApiChanged) {
|
2016-12-12 06:42:27 +01:00
|
|
|
apiConfig.isSameOAuthUrl = sameOAuthSigningUrl
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
if (defaultApiChanged) {
|
2016-12-12 06:42:27 +01:00
|
|
|
apiConfig.isNoVersionSuffix = noVersionSuffix
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-12 06:42:27 +01:00
|
|
|
if (TextUtils.isEmpty(apiConfig.consumerKey) || defaultApiChanged) {
|
|
|
|
apiConfig.consumerKey = consumerKey
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-12 06:42:27 +01:00
|
|
|
if (TextUtils.isEmpty(apiConfig.consumerSecret) || defaultApiChanged) {
|
|
|
|
apiConfig.consumerSecret = consumerSecret
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
if (defaultApiChanged) {
|
|
|
|
apiChangeTimestamp = apiLastChange
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun setSignInButton() {
|
2016-12-12 06:42:27 +01:00
|
|
|
when (apiConfig.credentialsType) {
|
2016-12-03 06:48:40 +01:00
|
|
|
Credentials.Type.XAUTH, Credentials.Type.BASIC -> {
|
2016-07-07 09:39:32 +02:00
|
|
|
passwordSignIn.visibility = View.GONE
|
2016-12-03 06:48:40 +01:00
|
|
|
signIn.isEnabled = editPassword.text.isNotEmpty() && editUsername.text.isNotEmpty()
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-03 06:48:40 +01:00
|
|
|
Credentials.Type.OAUTH -> {
|
2016-07-07 09:39:32 +02:00
|
|
|
passwordSignIn.visibility = View.VISIBLE
|
|
|
|
signIn.isEnabled = true
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
passwordSignIn.visibility = View.GONE
|
|
|
|
signIn.isEnabled = true
|
|
|
|
}
|
|
|
|
}
|
2017-01-19 12:43:20 +01:00
|
|
|
signUp.visibility = if (apiConfig.signUpUrl != null) {
|
|
|
|
View.VISIBLE
|
|
|
|
} else {
|
|
|
|
View.GONE
|
|
|
|
}
|
|
|
|
passwordSignIn.visibility = if (apiConfig.type == null || apiConfig.type == AccountType.TWITTER) {
|
|
|
|
View.VISIBLE
|
|
|
|
} else {
|
|
|
|
View.GONE
|
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
2016-12-17 05:10:24 +01:00
|
|
|
|
|
|
|
private fun finishSignIn() {
|
|
|
|
if (accountAuthenticatorResponse != null) {
|
|
|
|
accountAuthenticatorResult = Bundle {
|
|
|
|
this[AccountManager.KEY_BOOLEAN_RESULT] = true
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
val intent = Intent(this, HomeActivity::class.java)
|
2017-01-07 17:13:11 +01:00
|
|
|
//TODO refresh timelines
|
2016-12-17 05:10:24 +01:00
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
|
|
|
|
startActivity(intent)
|
2016-12-03 06:48:40 +01:00
|
|
|
}
|
2016-12-17 05:10:24 +01:00
|
|
|
finish()
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
internal abstract class AbstractSignInTask(activity: SignInActivity) : AsyncTask<Any, Runnable, SingleResponse<SignInResponse>>() {
|
2016-07-07 09:39:32 +02:00
|
|
|
|
|
|
|
protected val activityRef: WeakReference<SignInActivity>
|
|
|
|
|
|
|
|
init {
|
|
|
|
this.activityRef = WeakReference(activity)
|
|
|
|
}
|
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
override final fun doInBackground(vararg args: Any?): SingleResponse<SignInResponse> {
|
|
|
|
try {
|
|
|
|
return SingleResponse.getInstance(performLogin())
|
|
|
|
} catch (e: Exception) {
|
|
|
|
return SingleResponse.getInstance(e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract fun performLogin(): SignInResponse
|
|
|
|
|
|
|
|
override fun onPostExecute(result: SingleResponse<SignInResponse>) {
|
2016-07-07 09:39:32 +02:00
|
|
|
val activity = activityRef.get()
|
2016-12-15 06:49:18 +01:00
|
|
|
activity?.dismissDialogFragment(FRAGMENT_TAG_SIGN_IN_PROGRESS)
|
2016-12-03 06:48:40 +01:00
|
|
|
if (result.hasData()) {
|
|
|
|
activity?.onSignInResult(result.data!!)
|
|
|
|
} else {
|
|
|
|
activity?.onSignInError(result.exception!!)
|
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun onPreExecute() {
|
|
|
|
val activity = activityRef.get()
|
|
|
|
activity?.onSignInStart()
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onProgressUpdate(vararg values: Runnable) {
|
|
|
|
for (value in values) {
|
|
|
|
value.run()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(MicroBlogException::class)
|
|
|
|
internal fun analyseUserProfileColor(user: User?): Int {
|
|
|
|
if (user == null) throw MicroBlogException("Unable to get user info")
|
2016-12-09 14:20:02 +01:00
|
|
|
return ParcelableUserUtils.parseColor(user.profileLinkColor)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Created by mariotaku on 16/7/7.
|
|
|
|
*/
|
|
|
|
internal class BrowserSignInTask(
|
|
|
|
context: SignInActivity,
|
2017-01-07 17:13:11 +01:00
|
|
|
private val apiConfig: CustomAPIConfig,
|
2016-07-07 09:39:32 +02:00
|
|
|
private val requestToken: OAuthToken,
|
2017-01-07 17:13:11 +01:00
|
|
|
private val oauthVerifier: String?
|
2016-07-07 09:39:32 +02:00
|
|
|
) : AbstractSignInTask(context) {
|
|
|
|
|
|
|
|
private val context: Context
|
|
|
|
|
|
|
|
init {
|
|
|
|
this.context = context
|
|
|
|
}
|
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
@Throws(Exception::class)
|
|
|
|
override fun performLogin(): SignInResponse {
|
2017-01-07 17:13:11 +01:00
|
|
|
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
|
|
|
|
var endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiConfig.apiUrlFormat,
|
|
|
|
apiConfig.isSameOAuthUrl)
|
2016-12-08 16:45:07 +01:00
|
|
|
val oauth = newMicroBlogInstance(context, endpoint = endpoint,
|
2017-01-07 17:13:11 +01:00
|
|
|
auth = OAuthAuthorization(apiConfig.consumerKey, apiConfig.consumerSecret),
|
2016-12-08 16:45:07 +01:00
|
|
|
cls = TwitterOAuth::class.java)
|
2016-12-03 06:48:40 +01:00
|
|
|
val accessToken: OAuthToken
|
|
|
|
if (oauthVerifier != null) {
|
|
|
|
accessToken = oauth.getAccessToken(requestToken, oauthVerifier)
|
|
|
|
} else {
|
|
|
|
accessToken = oauth.getAccessToken(requestToken)
|
|
|
|
}
|
2017-01-07 17:13:11 +01:00
|
|
|
val auth = OAuthAuthorization(apiConfig.consumerKey,
|
|
|
|
apiConfig.consumerSecret, accessToken)
|
|
|
|
endpoint = MicroBlogAPIFactory.getOAuthEndpoint(apiConfig.apiUrlFormat, "api", versionSuffix,
|
|
|
|
apiConfig.isSameOAuthUrl)
|
2016-12-08 16:45:07 +01:00
|
|
|
|
|
|
|
val twitter = newMicroBlogInstance(context, endpoint = endpoint, auth = auth,
|
|
|
|
cls = MicroBlog::class.java)
|
2016-12-03 06:48:40 +01:00
|
|
|
val apiUser = twitter.verifyCredentials()
|
|
|
|
var color = analyseUserProfileColor(apiUser)
|
2017-01-07 17:13:11 +01:00
|
|
|
val accountType = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
2016-12-03 06:48:40 +01:00
|
|
|
val userId = apiUser.id!!
|
|
|
|
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
|
|
|
|
val user = ParcelableUserUtils.fromUser(apiUser, accountKey)
|
2016-12-15 06:11:32 +01:00
|
|
|
val am = AccountManager.get(context)
|
|
|
|
val account = AccountUtils.findByAccountKey(am, accountKey)
|
2016-12-03 06:48:40 +01:00
|
|
|
if (account != null) {
|
2016-12-15 06:11:32 +01:00
|
|
|
color = account.getColor(am)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-03 06:48:40 +01:00
|
|
|
val credentials = OAuthCredentials()
|
2017-01-07 17:13:11 +01:00
|
|
|
credentials.api_url_format = apiConfig.apiUrlFormat
|
|
|
|
credentials.no_version_suffix = apiConfig.isNoVersionSuffix
|
2016-12-03 06:48:40 +01:00
|
|
|
|
2017-01-07 17:13:11 +01:00
|
|
|
credentials.same_oauth_signing_url = apiConfig.isSameOAuthUrl
|
2016-12-03 06:48:40 +01:00
|
|
|
|
2017-01-07 17:13:11 +01:00
|
|
|
credentials.consumer_key = apiConfig.consumerKey
|
|
|
|
credentials.consumer_secret = apiConfig.consumerSecret
|
2016-12-03 06:48:40 +01:00
|
|
|
credentials.access_token = accessToken.oauthToken
|
|
|
|
credentials.access_token_secret = accessToken.oauthTokenSecret
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
return SignInResponse(account != null, Credentials.Type.OAUTH, credentials, user, color,
|
|
|
|
accountType)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Created by mariotaku on 16/7/7.
|
|
|
|
*/
|
|
|
|
class InputLoginVerificationDialogFragment : BaseDialogFragment(), DialogInterface.OnClickListener, DialogInterface.OnShowListener {
|
|
|
|
|
|
|
|
private var callback: SignInTask.InputLoginVerificationCallback? = null
|
2016-07-12 03:22:33 +02:00
|
|
|
var challengeType: String? = null
|
2016-07-07 09:39:32 +02:00
|
|
|
|
|
|
|
internal fun setCallback(callback: SignInTask.InputLoginVerificationCallback) {
|
|
|
|
this.callback = callback
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun onCancel(dialog: DialogInterface?) {
|
|
|
|
callback!!.challengeResponse = null
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
|
|
val builder = AlertDialog.Builder(context)
|
|
|
|
builder.setTitle(R.string.login_verification)
|
|
|
|
builder.setView(R.layout.dialog_login_verification_code)
|
|
|
|
builder.setPositiveButton(android.R.string.ok, this)
|
|
|
|
builder.setNegativeButton(android.R.string.cancel, this)
|
|
|
|
val dialog = builder.create()
|
|
|
|
dialog.setOnShowListener(this)
|
|
|
|
return dialog
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onClick(dialog: DialogInterface, which: Int) {
|
|
|
|
when (which) {
|
|
|
|
DialogInterface.BUTTON_POSITIVE -> {
|
|
|
|
val alertDialog = dialog as AlertDialog
|
|
|
|
val editVerification = (alertDialog.findViewById(R.id.edit_verification_code) as EditText?)!!
|
|
|
|
callback!!.challengeResponse = ParseUtils.parseString(editVerification.text)
|
|
|
|
}
|
|
|
|
DialogInterface.BUTTON_NEGATIVE -> {
|
|
|
|
callback!!.challengeResponse = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onShow(dialog: DialogInterface) {
|
|
|
|
val alertDialog = dialog as AlertDialog
|
|
|
|
val verificationHint = alertDialog.findViewById(R.id.verification_hint) as TextView?
|
|
|
|
val editVerification = alertDialog.findViewById(R.id.edit_verification_code) as EditText?
|
|
|
|
if (verificationHint == null || editVerification == null) return
|
2016-07-12 03:22:33 +02:00
|
|
|
when {
|
|
|
|
"Push".equals(challengeType, ignoreCase = true) -> {
|
|
|
|
verificationHint.setText(R.string.login_verification_push_hint)
|
|
|
|
editVerification.visibility = View.GONE
|
|
|
|
}
|
|
|
|
"RetypePhoneNumber".equals(challengeType, ignoreCase = true) -> {
|
|
|
|
verificationHint.setText(R.string.login_challenge_retype_phone_hint)
|
|
|
|
editVerification.inputType = InputType.TYPE_CLASS_PHONE
|
|
|
|
editVerification.visibility = View.VISIBLE
|
|
|
|
}
|
|
|
|
"RetypeEmail".equals(challengeType, ignoreCase = true) -> {
|
|
|
|
verificationHint.setText(R.string.login_challenge_retype_email_hint)
|
|
|
|
editVerification.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
|
|
|
|
editVerification.visibility = View.VISIBLE
|
|
|
|
}
|
|
|
|
"Sms".equals(challengeType, ignoreCase = true) -> {
|
|
|
|
verificationHint.setText(R.string.login_verification_pin_hint)
|
|
|
|
editVerification.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|
|
|
|
editVerification.visibility = View.VISIBLE
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
verificationHint.text = getString(R.string.unsupported_login_verification_type_name,
|
|
|
|
challengeType)
|
|
|
|
editVerification.visibility = View.VISIBLE
|
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class PasswordSignInDialogFragment : BaseDialogFragment() {
|
|
|
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
|
|
val builder = AlertDialog.Builder(context)
|
|
|
|
builder.setView(R.layout.dialog_password_sign_in)
|
|
|
|
builder.setPositiveButton(R.string.sign_in) { dialog, which ->
|
|
|
|
val alertDialog = dialog as AlertDialog
|
|
|
|
val editUsername = alertDialog.findViewById(R.id.username) as EditText?
|
|
|
|
val editPassword = alertDialog.findViewById(R.id.password) as EditText?
|
|
|
|
assert(editUsername != null && editPassword != null)
|
|
|
|
val activity = activity as SignInActivity
|
|
|
|
activity.setUsernamePassword(editUsername!!.text.toString(),
|
|
|
|
editPassword!!.text.toString())
|
|
|
|
activity.doLogin()
|
|
|
|
}
|
|
|
|
builder.setNegativeButton(android.R.string.cancel, null)
|
|
|
|
|
|
|
|
val alertDialog = builder.create()
|
|
|
|
alertDialog.setOnShowListener { dialog ->
|
|
|
|
val materialDialog = dialog as AlertDialog
|
|
|
|
val editUsername = materialDialog.findViewById(R.id.username) as EditText?
|
|
|
|
val editPassword = materialDialog.findViewById(R.id.password) as EditText?
|
|
|
|
assert(editUsername != null && editPassword != null)
|
|
|
|
val textWatcher = object : TextWatcher {
|
|
|
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
|
|
|
val button = materialDialog.getButton(DialogInterface.BUTTON_POSITIVE) ?: return
|
|
|
|
button.isEnabled = editUsername!!.length() > 0 && editPassword!!.length() > 0
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun afterTextChanged(s: Editable) {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
editUsername!!.addTextChangedListener(textWatcher)
|
|
|
|
editPassword!!.addTextChangedListener(textWatcher)
|
|
|
|
}
|
|
|
|
return alertDialog
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class SetConsumerKeySecretDialogFragment : BaseDialogFragment() {
|
|
|
|
|
|
|
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
|
|
val builder = AlertDialog.Builder(activity)
|
|
|
|
builder.setView(R.layout.dialog_set_consumer_key_secret)
|
|
|
|
builder.setPositiveButton(android.R.string.ok) { dialog, which ->
|
2016-08-20 03:59:48 +02:00
|
|
|
val editConsumerKey = (dialog as Dialog).findViewById(R.id.editConsumerKey) as EditText
|
|
|
|
val editConsumerSecret = dialog.findViewById(R.id.editConsumerSecret) as EditText
|
2016-12-24 13:47:35 +01:00
|
|
|
val apiConfig = kPreferences[defaultAPIConfigKey]
|
|
|
|
apiConfig.consumerKey = editConsumerKey.text.toString()
|
|
|
|
apiConfig.consumerSecret = editConsumerSecret.text.toString()
|
|
|
|
kPreferences[defaultAPIConfigKey] = apiConfig
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
val dialog = builder.create()
|
|
|
|
dialog.setOnShowListener(DialogInterface.OnShowListener { dialog ->
|
|
|
|
val activity = activity ?: return@OnShowListener
|
2016-08-20 03:59:48 +02:00
|
|
|
val editConsumerKey = (dialog as Dialog).findViewById(R.id.editConsumerKey) as MaterialEditText
|
|
|
|
val editConsumerSecret = dialog.findViewById(R.id.editConsumerSecret) as MaterialEditText
|
2016-07-07 09:39:32 +02:00
|
|
|
editConsumerKey.addValidator(ConsumerKeySecretValidator(getString(R.string.invalid_consumer_key)))
|
|
|
|
editConsumerSecret.addValidator(ConsumerKeySecretValidator(getString(R.string.invalid_consumer_secret)))
|
2016-12-24 13:47:35 +01:00
|
|
|
val apiConfig = kPreferences[defaultAPIConfigKey]
|
|
|
|
editConsumerKey.setText(apiConfig.consumerKey)
|
|
|
|
editConsumerSecret.setText(apiConfig.consumerSecret)
|
2016-07-07 09:39:32 +02:00
|
|
|
})
|
|
|
|
return dialog
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
internal data class SignInResponse(
|
|
|
|
val alreadyLoggedIn: Boolean,
|
2016-12-08 08:33:13 +01:00
|
|
|
@Credentials.Type val credsType: String = Credentials.Type.EMPTY,
|
2016-12-03 06:48:40 +01:00
|
|
|
val credentials: Credentials,
|
|
|
|
val user: ParcelableUser,
|
2016-07-07 09:39:32 +02:00
|
|
|
val color: Int = 0,
|
2016-12-15 06:11:32 +01:00
|
|
|
val accountType: Pair<String, AccountExtras?>
|
2016-07-07 09:39:32 +02:00
|
|
|
) {
|
|
|
|
|
2016-12-12 06:42:27 +01:00
|
|
|
private fun writeAccountInfo(action: (k: String, v: String?) -> Unit) {
|
|
|
|
action(ACCOUNT_USER_DATA_KEY, user.key.toString())
|
|
|
|
action(ACCOUNT_USER_DATA_TYPE, accountType.first)
|
|
|
|
action(ACCOUNT_USER_DATA_CREDS_TYPE, credsType)
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-12 06:42:27 +01:00
|
|
|
action(ACCOUNT_USER_DATA_ACTIVATED, true.toString())
|
2017-01-02 09:33:27 +01:00
|
|
|
action(ACCOUNT_USER_DATA_COLOR, toHexColor(color, format = HexColorFormat.RGB))
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-12 06:42:27 +01:00
|
|
|
action(ACCOUNT_USER_DATA_USER, LoganSquare.serialize(user))
|
2016-12-15 06:11:32 +01:00
|
|
|
action(ACCOUNT_USER_DATA_EXTRAS, accountType.second?.convert { LoganSquare.serialize(it) })
|
2016-12-08 08:33:13 +01:00
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-08 08:33:13 +01:00
|
|
|
private fun writeAuthToken(am: AccountManager, account: Account) {
|
2016-12-15 02:15:15 +01:00
|
|
|
val authToken = LoganSquare.serialize(credentials)
|
|
|
|
am.setAuthToken(account, ACCOUNT_AUTH_TOKEN_TYPE, authToken)
|
2016-12-03 06:48:40 +01:00
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
fun updateAccount(am: AccountManager) {
|
|
|
|
val account = AccountUtils.findByAccountKey(am, user.key) ?: return
|
2016-12-12 06:42:27 +01:00
|
|
|
writeAccountInfo { k, v ->
|
2016-12-08 08:33:13 +01:00
|
|
|
am.setUserData(account, k, v)
|
|
|
|
}
|
|
|
|
writeAuthToken(am, account)
|
2016-12-03 06:48:40 +01:00
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-16 10:13:35 +01:00
|
|
|
fun addAccount(am: AccountManager, randomizeAccountName: Boolean): Account {
|
|
|
|
var accountName: String
|
|
|
|
if (randomizeAccountName) {
|
|
|
|
val usedNames = ArraySet<String>()
|
|
|
|
AccountUtils.getAccounts(am).mapTo(usedNames, Account::name)
|
|
|
|
do {
|
|
|
|
accountName = UUID.randomUUID().toString()
|
|
|
|
} while (usedNames.contains(accountName))
|
|
|
|
} else {
|
|
|
|
accountName = generateAccountName(user.screen_name, user.key.host)
|
|
|
|
}
|
|
|
|
val account = Account(accountName, ACCOUNT_TYPE)
|
2016-12-12 06:42:27 +01:00
|
|
|
val accountPosition = AccountUtils.getAccounts(am).size
|
|
|
|
// Don't add UserData in this method, see http://stackoverflow.com/a/29776224/859190
|
|
|
|
am.addAccountExplicitly(account, null, null)
|
|
|
|
writeAccountInfo { k, v ->
|
|
|
|
am.setUserData(account, k, v)
|
2016-12-08 08:33:13 +01:00
|
|
|
}
|
2016-12-12 06:42:27 +01:00
|
|
|
am.setUserData(account, ACCOUNT_USER_DATA_POSITION, accountPosition.toString())
|
2016-12-09 06:26:26 +01:00
|
|
|
writeAuthToken(am, account)
|
2016-12-08 08:33:13 +01:00
|
|
|
return account
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-15 02:15:15 +01:00
|
|
|
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
internal class SignInTask(
|
|
|
|
activity: SignInActivity,
|
|
|
|
private val username: String,
|
|
|
|
private val password: String,
|
2017-01-07 17:13:11 +01:00
|
|
|
private val apiConfig: CustomAPIConfig
|
2016-12-03 06:48:40 +01:00
|
|
|
) : AbstractSignInTask(activity) {
|
2017-01-07 17:13:11 +01:00
|
|
|
private val verificationCallback = InputLoginVerificationCallback()
|
|
|
|
private val userAgent = UserAgentUtils.getDefaultUserAgentString(activity)
|
|
|
|
private val apiUrlFormat = apiConfig.apiUrlFormat ?: DEFAULT_TWITTER_API_URL_FORMAT
|
2016-07-07 09:39:32 +02:00
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
@Throws(Exception::class)
|
|
|
|
override fun performLogin(): SignInResponse {
|
2017-01-07 17:13:11 +01:00
|
|
|
when (apiConfig.credentialsType) {
|
2016-12-03 06:48:40 +01:00
|
|
|
Credentials.Type.OAUTH -> return authOAuth()
|
|
|
|
Credentials.Type.XAUTH -> return authxAuth()
|
|
|
|
Credentials.Type.BASIC -> return authBasic()
|
|
|
|
Credentials.Type.EMPTY -> return authTwipOMode()
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-03 06:48:40 +01:00
|
|
|
return authOAuth()
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(OAuthPasswordAuthenticator.AuthenticationException::class, MicroBlogException::class)
|
|
|
|
private fun authOAuth(): SignInResponse {
|
2016-12-03 06:48:40 +01:00
|
|
|
val activity = activityRef.get() ?: throw InterruptedException()
|
2016-07-07 09:39:32 +02:00
|
|
|
val endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
2017-01-07 17:13:11 +01:00
|
|
|
apiConfig.isSameOAuthUrl)
|
|
|
|
val auth = OAuthAuthorization(apiConfig.consumerKey,
|
|
|
|
apiConfig.consumerSecret)
|
2016-12-08 16:45:07 +01:00
|
|
|
val oauth = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
|
|
|
|
cls = TwitterOAuth::class.java)
|
2016-07-07 09:39:32 +02:00
|
|
|
val authenticator = OAuthPasswordAuthenticator(oauth,
|
|
|
|
verificationCallback, userAgent)
|
|
|
|
val accessToken = authenticator.getOAuthAccessToken(username, password)
|
2016-12-03 06:48:40 +01:00
|
|
|
val userId = accessToken.userId!!
|
2016-07-07 09:39:32 +02:00
|
|
|
return getOAuthSignInResponse(activity, accessToken, userId,
|
2016-12-03 06:48:40 +01:00
|
|
|
Credentials.Type.OAUTH)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(MicroBlogException::class)
|
|
|
|
private fun authxAuth(): SignInResponse {
|
2016-12-03 06:48:40 +01:00
|
|
|
val activity = activityRef.get() ?: throw InterruptedException()
|
2016-07-07 09:39:32 +02:00
|
|
|
var endpoint = MicroBlogAPIFactory.getOAuthSignInEndpoint(apiUrlFormat,
|
2017-01-07 17:13:11 +01:00
|
|
|
apiConfig.isSameOAuthUrl)
|
|
|
|
var auth = OAuthAuthorization(apiConfig.consumerKey,
|
|
|
|
apiConfig.consumerSecret)
|
2016-12-08 16:45:07 +01:00
|
|
|
val oauth = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
|
|
|
|
cls = TwitterOAuth::class.java)
|
2016-07-07 09:39:32 +02:00
|
|
|
val accessToken = oauth.getAccessToken(username, password)
|
|
|
|
var userId: String? = accessToken.userId
|
|
|
|
if (userId == null) {
|
|
|
|
// Trying to fix up userId if accessToken doesn't contain one.
|
2017-01-07 17:13:11 +01:00
|
|
|
auth = OAuthAuthorization(apiConfig.consumerKey,
|
|
|
|
apiConfig.consumerSecret, accessToken)
|
|
|
|
endpoint = MicroBlogAPIFactory.getOAuthRestEndpoint(apiUrlFormat, apiConfig.isSameOAuthUrl,
|
|
|
|
apiConfig.isNoVersionSuffix)
|
2016-12-08 16:45:07 +01:00
|
|
|
val microBlog = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
|
|
|
|
cls = MicroBlog::class.java)
|
2016-07-07 09:39:32 +02:00
|
|
|
userId = microBlog.verifyCredentials().id
|
|
|
|
}
|
2016-12-03 06:48:40 +01:00
|
|
|
return getOAuthSignInResponse(activity, accessToken, userId!!, Credentials.Type.XAUTH)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(MicroBlogException::class, OAuthPasswordAuthenticator.AuthenticationException::class)
|
|
|
|
private fun authBasic(): SignInResponse {
|
2016-12-03 06:48:40 +01:00
|
|
|
val activity = activityRef.get() ?: throw InterruptedException()
|
2017-01-07 17:13:11 +01:00
|
|
|
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
|
2016-07-07 09:39:32 +02:00
|
|
|
val endpoint = Endpoint(MicroBlogAPIFactory.getApiUrl(apiUrlFormat, "api",
|
|
|
|
versionSuffix))
|
|
|
|
val auth = BasicAuthorization(username, password)
|
2016-12-08 16:45:07 +01:00
|
|
|
val twitter = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
|
|
|
|
cls = MicroBlog::class.java)
|
2016-12-03 06:48:40 +01:00
|
|
|
val apiUser: User
|
2016-07-07 09:39:32 +02:00
|
|
|
try {
|
2016-12-03 06:48:40 +01:00
|
|
|
apiUser = twitter.verifyCredentials()
|
2016-07-07 09:39:32 +02:00
|
|
|
} catch (e: MicroBlogException) {
|
|
|
|
if (e.statusCode == 401) {
|
|
|
|
throw WrongBasicCredentialException()
|
|
|
|
} else if (e.statusCode == 404) {
|
|
|
|
throw WrongAPIURLFormatException()
|
|
|
|
}
|
|
|
|
throw e
|
|
|
|
}
|
|
|
|
|
2016-12-03 06:48:40 +01:00
|
|
|
val userId = apiUser.id!!
|
|
|
|
var color = analyseUserProfileColor(apiUser)
|
2017-01-07 17:13:11 +01:00
|
|
|
val accountType = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
2016-12-03 06:48:40 +01:00
|
|
|
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
|
|
|
|
val user = ParcelableUserUtils.fromUser(apiUser, accountKey)
|
2016-12-15 06:11:32 +01:00
|
|
|
val am = AccountManager.get(activity)
|
|
|
|
val account = AccountUtils.findByAccountKey(am, accountKey)
|
2016-07-07 09:39:32 +02:00
|
|
|
if (account != null) {
|
2016-12-15 06:11:32 +01:00
|
|
|
color = account.getColor(am)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-03 06:48:40 +01:00
|
|
|
val credentials = BasicCredentials()
|
|
|
|
credentials.api_url_format = apiUrlFormat
|
2017-01-07 17:13:11 +01:00
|
|
|
credentials.no_version_suffix = apiConfig.isNoVersionSuffix
|
2016-12-03 06:48:40 +01:00
|
|
|
credentials.username = username
|
|
|
|
credentials.password = password
|
|
|
|
return SignInResponse(account != null, Credentials.Type.BASIC, credentials, user,
|
|
|
|
color, accountType)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Throws(MicroBlogException::class)
|
|
|
|
private fun authTwipOMode(): SignInResponse {
|
2016-12-03 06:48:40 +01:00
|
|
|
val activity = activityRef.get() ?: throw InterruptedException()
|
2017-01-07 17:13:11 +01:00
|
|
|
val versionSuffix = if (apiConfig.isNoVersionSuffix) null else "1.1"
|
2016-07-07 09:39:32 +02:00
|
|
|
val endpoint = Endpoint(MicroBlogAPIFactory.getApiUrl(apiUrlFormat, "api",
|
|
|
|
versionSuffix))
|
|
|
|
val auth = EmptyAuthorization()
|
2016-12-08 16:45:07 +01:00
|
|
|
val twitter = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
|
|
|
|
cls = MicroBlog::class.java)
|
2016-12-03 06:48:40 +01:00
|
|
|
val apiUser = twitter.verifyCredentials()
|
|
|
|
val userId = apiUser.id!!
|
|
|
|
var color = analyseUserProfileColor(apiUser)
|
2017-01-07 17:13:11 +01:00
|
|
|
val accountType = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
2016-12-03 06:48:40 +01:00
|
|
|
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
|
|
|
|
val user = ParcelableUserUtils.fromUser(apiUser, accountKey)
|
2016-12-15 06:11:32 +01:00
|
|
|
val am = AccountManager.get(activity)
|
|
|
|
val account = AccountUtils.findByAccountKey(am, accountKey)
|
2016-07-07 09:39:32 +02:00
|
|
|
if (account != null) {
|
2016-12-15 06:11:32 +01:00
|
|
|
color = account.getColor(am)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-03 06:48:40 +01:00
|
|
|
val credentials = EmptyCredentials()
|
|
|
|
credentials.api_url_format = apiUrlFormat
|
2017-01-07 17:13:11 +01:00
|
|
|
credentials.no_version_suffix = apiConfig.isNoVersionSuffix
|
2016-12-03 06:48:40 +01:00
|
|
|
|
|
|
|
return SignInResponse(account != null, Credentials.Type.EMPTY, credentials, user, color,
|
|
|
|
accountType)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Throws(MicroBlogException::class)
|
|
|
|
private fun getOAuthSignInResponse(activity: SignInActivity,
|
|
|
|
accessToken: OAuthToken,
|
2016-12-03 06:48:40 +01:00
|
|
|
userId: String, @Credentials.Type authType: String): SignInResponse {
|
2017-01-07 17:13:11 +01:00
|
|
|
val auth = OAuthAuthorization(apiConfig.consumerKey,
|
|
|
|
apiConfig.consumerSecret, accessToken)
|
2016-07-07 09:39:32 +02:00
|
|
|
val endpoint = MicroBlogAPIFactory.getOAuthRestEndpoint(apiUrlFormat,
|
2017-01-07 17:13:11 +01:00
|
|
|
apiConfig.isSameOAuthUrl, apiConfig.isNoVersionSuffix)
|
2016-12-08 16:45:07 +01:00
|
|
|
val twitter = newMicroBlogInstance(activity, endpoint = endpoint, auth = auth,
|
|
|
|
cls = MicroBlog::class.java)
|
2016-12-03 06:48:40 +01:00
|
|
|
val apiUser = twitter.verifyCredentials()
|
|
|
|
var color = analyseUserProfileColor(apiUser)
|
2017-01-07 17:13:11 +01:00
|
|
|
val accountType = SignInActivity.detectAccountType(twitter, apiUser, apiConfig.type)
|
2016-12-03 06:48:40 +01:00
|
|
|
val accountKey = UserKey(userId, UserKeyUtils.getUserHost(apiUser))
|
|
|
|
val user = ParcelableUserUtils.fromUser(apiUser, accountKey)
|
2016-12-15 06:11:32 +01:00
|
|
|
val am = AccountManager.get(activity)
|
|
|
|
val account = AccountUtils.findByAccountKey(am, accountKey)
|
2016-07-07 09:39:32 +02:00
|
|
|
if (account != null) {
|
2016-12-15 06:11:32 +01:00
|
|
|
color = account.getColor(am)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2016-12-03 06:48:40 +01:00
|
|
|
val credentials = OAuthCredentials()
|
|
|
|
credentials.api_url_format = apiUrlFormat
|
2017-01-07 17:13:11 +01:00
|
|
|
credentials.no_version_suffix = apiConfig.isNoVersionSuffix
|
2016-12-03 06:48:40 +01:00
|
|
|
|
2017-01-07 17:13:11 +01:00
|
|
|
credentials.same_oauth_signing_url = apiConfig.isSameOAuthUrl
|
2016-12-03 06:48:40 +01:00
|
|
|
|
2017-01-07 17:13:11 +01:00
|
|
|
credentials.consumer_key = apiConfig.consumerKey
|
|
|
|
credentials.consumer_secret = apiConfig.consumerSecret
|
2016-12-03 06:48:40 +01:00
|
|
|
credentials.access_token = accessToken.oauthToken
|
|
|
|
credentials.access_token_secret = accessToken.oauthTokenSecret
|
|
|
|
|
|
|
|
return SignInResponse(account != null, authType, credentials, user, color, accountType)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
internal class WrongBasicCredentialException : OAuthPasswordAuthenticator.AuthenticationException()
|
|
|
|
|
|
|
|
internal class WrongAPIURLFormatException : OAuthPasswordAuthenticator.AuthenticationException()
|
|
|
|
|
|
|
|
internal inner class InputLoginVerificationCallback : OAuthPasswordAuthenticator.LoginVerificationCallback {
|
|
|
|
|
|
|
|
var isChallengeFinished: Boolean = false
|
|
|
|
|
|
|
|
var challengeResponse: String? = null
|
|
|
|
set(value) {
|
|
|
|
isChallengeFinished = true
|
|
|
|
field = value
|
|
|
|
}
|
|
|
|
|
2016-07-14 14:00:27 +02:00
|
|
|
override fun getLoginVerification(challengeType: String): String? {
|
2016-07-07 09:39:32 +02:00
|
|
|
// Dismiss current progress dialog
|
|
|
|
publishProgress(Runnable {
|
2016-12-15 06:49:18 +01:00
|
|
|
activityRef.get()?.dismissDialogFragment(SignInActivity.FRAGMENT_TAG_SIGN_IN_PROGRESS)
|
2016-07-07 09:39:32 +02:00
|
|
|
})
|
|
|
|
// Show verification input dialog and wait for user input
|
|
|
|
publishProgress(Runnable {
|
|
|
|
val activity = activityRef.get() ?: return@Runnable
|
|
|
|
activity.executeAfterFragmentResumed { activity ->
|
|
|
|
val sia = activity as SignInActivity
|
|
|
|
val df = InputLoginVerificationDialogFragment()
|
|
|
|
df.isCancelable = false
|
|
|
|
df.setCallback(this@InputLoginVerificationCallback)
|
2016-07-12 03:22:33 +02:00
|
|
|
df.challengeType = challengeType
|
2016-12-15 06:49:18 +01:00
|
|
|
df.show(sia.supportFragmentManager, "login_challenge_$challengeType")
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
})
|
|
|
|
while (!isChallengeFinished) {
|
|
|
|
// Wait for 50ms
|
|
|
|
try {
|
|
|
|
Thread.sleep(50)
|
|
|
|
} catch (e: InterruptedException) {
|
|
|
|
// Ignore
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
// Show progress dialog
|
|
|
|
publishProgress(Runnable {
|
|
|
|
val activity = activityRef.get() ?: return@Runnable
|
|
|
|
activity.showSignInProgressDialog()
|
|
|
|
})
|
|
|
|
return challengeResponse
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
companion object {
|
|
|
|
|
|
|
|
val FRAGMENT_TAG_SIGN_IN_PROGRESS = "sign_in_progress"
|
|
|
|
private val EXTRA_API_LAST_CHANGE = "api_last_change"
|
|
|
|
private val DEFAULT_TWITTER_API_URL_FORMAT = "https://[DOMAIN.]twitter.com/"
|
|
|
|
|
2017-01-07 17:13:11 +01:00
|
|
|
@Throws(IOException::class)
|
|
|
|
internal fun detectAccountType(twitter: MicroBlog, user: User, type: String?): Pair<String, AccountExtras?> {
|
|
|
|
when (type) {
|
|
|
|
AccountType.STATUSNET -> {
|
2017-01-25 13:08:23 +01:00
|
|
|
return getStatusNetAccountType(twitter)
|
2017-01-07 17:13:11 +01:00
|
|
|
}
|
|
|
|
AccountType.TWITTER -> {
|
2017-01-25 13:08:23 +01:00
|
|
|
return getTwitterAccountType(twitter)
|
2017-01-07 17:13:11 +01:00
|
|
|
}
|
|
|
|
AccountType.FANFOU -> {
|
|
|
|
return Pair(AccountType.FANFOU, null)
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
if (UserKeyUtils.isFanfouUser(user)) {
|
|
|
|
return Pair(AccountType.FANFOU, null)
|
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
}
|
2016-12-12 06:42:27 +01:00
|
|
|
return Pair(AccountType.TWITTER, null)
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
2017-01-25 13:08:23 +01:00
|
|
|
|
|
|
|
private fun getStatusNetAccountType(twitter: MicroBlog): Pair<String, StatusNetAccountExtras> {
|
|
|
|
// Get StatusNet specific resource
|
|
|
|
val config = twitter.statusNetConfig
|
|
|
|
val extras = StatusNetAccountExtras()
|
|
|
|
val site = config.site
|
|
|
|
if (site != null) {
|
|
|
|
extras.textLimit = site.textLimit
|
|
|
|
}
|
|
|
|
return Pair(AccountType.STATUSNET, extras)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun getTwitterAccountType(twitter: MicroBlog): Pair<String, TwitterAccountExtras> {
|
|
|
|
val extras = TwitterAccountExtras()
|
|
|
|
try {
|
|
|
|
// Get Twitter official only resource
|
|
|
|
val paging = Paging()
|
|
|
|
paging.count(1)
|
|
|
|
twitter.getActivitiesAboutMe(paging)
|
|
|
|
extras.setIsOfficialCredentials(true)
|
|
|
|
} catch (e: MicroBlogException) {
|
|
|
|
// Ignore
|
|
|
|
}
|
|
|
|
return Pair(AccountType.TWITTER, extras)
|
|
|
|
}
|
2016-07-07 09:39:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|