Adding Captcha support and call the login page when auth failed
This commit is contained in:
parent
c29abee329
commit
370c0a83a2
2 changed files with 66 additions and 30 deletions
|
@ -22,6 +22,7 @@ import androidx.core.content.ContextCompat
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,7 +163,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
button?.setOnClickListener {
|
button?.setOnClickListener {
|
||||||
val password = Credentials().get(1)
|
val password = Credentials().get(1)
|
||||||
if (password != null) { // call script
|
if (password != null) { // call script
|
||||||
callScript(user, password.toString(), button?.text.toString())
|
callScrapper(user, password.toString(), button?.text.toString())
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(applicationContext, R.string.notConnected, Toast.LENGTH_LONG)
|
Toast.makeText(applicationContext, R.string.notConnected, Toast.LENGTH_LONG)
|
||||||
.show()
|
.show()
|
||||||
|
@ -222,6 +223,36 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun callScrapper(user: String, password: String, app: String, captchaID: String? = null, captchaResponse: String? = null) {
|
||||||
|
if (ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.INTERNET)
|
||||||
|
!= PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
Toast.makeText(this@MainActivity, R.string.internetPermission, Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
this.finishAffinity()
|
||||||
|
} else {
|
||||||
|
runBlocking {
|
||||||
|
val returns: MutableList<String>? = Scraper(user, password, app, captchaID = captchaID, captchaResponse = captchaResponse, debug = true).search()
|
||||||
|
if (returns != null) { // if job is needed
|
||||||
|
if (returns[0] == "errorNotConnected") loginPage()
|
||||||
|
if (returns[0] == "loginAttemptsExceeded") {
|
||||||
|
val builder: android.app.AlertDialog.Builder = android.app.AlertDialog.Builder(
|
||||||
|
instance)
|
||||||
|
builder.setTitle("Captcha")
|
||||||
|
builder.setMessage(returns[1])
|
||||||
|
val input = EditText(instance)
|
||||||
|
input.inputType = InputType.TYPE_CLASS_TEXT
|
||||||
|
builder.setView(input)
|
||||||
|
builder.setPositiveButton(R.string.validate) { _, _ -> callScrapper(user, password, app, returns[2], input.text.toString()) }
|
||||||
|
builder.setNeutralButton(R.string.cancel) { dialog, _ -> dialog.cancel() }
|
||||||
|
|
||||||
|
builder.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun settingsPage() {
|
private fun settingsPage() {
|
||||||
setContentView(R.layout.activity_settings)
|
setContentView(R.layout.activity_settings)
|
||||||
|
@ -252,18 +283,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun callScript(user: String, password: String, app: String) {
|
|
||||||
if (ContextCompat.checkSelfPermission(this@MainActivity, Manifest.permission.INTERNET)
|
|
||||||
!= PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
Toast.makeText(this@MainActivity, R.string.internetPermission, Toast.LENGTH_SHORT)
|
|
||||||
.show()
|
|
||||||
this.finishAffinity()
|
|
||||||
} else {
|
|
||||||
Scraper(user, password, app = app, debug = true).search()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (prefs!!.getBoolean("firstrun", true)) {
|
if (prefs!!.getBoolean("firstrun", true)) {
|
||||||
|
|
|
@ -14,6 +14,8 @@ class Scraper(
|
||||||
private var password: String,
|
private var password: String,
|
||||||
private var app: String,
|
private var app: String,
|
||||||
private var debug: Boolean = false,
|
private var debug: Boolean = false,
|
||||||
|
private var captchaID: String? = null,
|
||||||
|
private var captchaResponse: String? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private var url: String = "https://forum.mobilism.org"
|
private var url: String = "https://forum.mobilism.org"
|
||||||
|
@ -31,13 +33,18 @@ class Scraper(
|
||||||
return "${if (code != null) "[$code]" else ""}${if ((message.isNotEmpty()) and (code is Int)) " " else ""}$message."
|
return "${if (code != null) "[$code]" else ""}${if ((message.isNotEmpty()) and (code is Int)) " " else ""}$message."
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun connect() {
|
private fun connect(): MutableList<String>? {
|
||||||
if (debug) println("Connection attempt...")
|
if (debug) println("Connection attempt...")
|
||||||
retry++
|
retry++
|
||||||
FuelManager.instance.basePath = url
|
FuelManager.instance.basePath = url
|
||||||
FuelManager.instance.baseParams = listOf("mode" to "login")
|
FuelManager.instance.baseParams = listOf("mode" to "login")
|
||||||
|
val params = mutableListOf("username" to pseudo, "password" to password, "login" to "Login")
|
||||||
|
if (captchaID != null) {
|
||||||
|
params.add("qa_answer" to captchaResponse.toString())
|
||||||
|
params.add("qa_confirm_id" to captchaID.toString())
|
||||||
|
}
|
||||||
val session = "/ucp.php"
|
val session = "/ucp.php"
|
||||||
.httpPost(listOf("username" to pseudo, "password" to password, "login" to "Login"))
|
.httpPost(params)
|
||||||
.responseString { _, response, result ->
|
.responseString { _, response, result ->
|
||||||
when (result) {
|
when (result) {
|
||||||
is FuelFailure -> {
|
is FuelFailure -> {
|
||||||
|
@ -51,36 +58,45 @@ class Scraper(
|
||||||
}
|
}
|
||||||
val data = session.join().data.decodeToString()
|
val data = session.join().data.decodeToString()
|
||||||
sid = "(?<=sid=)(.{32})".toRegex().find(data)?.value
|
sid = "(?<=sid=)(.{32})".toRegex().find(data)?.value
|
||||||
if (errorNotConnected in data) return if (loginAttemptsExceeded in data) error(loginAttemptsExceeded) else error(data)
|
if (errorNotConnected in data) return error(data)
|
||||||
Credentials().storeSID(sid.toString())
|
Credentials().storeSID(sid.toString())
|
||||||
return search()
|
return search()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun error(htmlPage: String) {
|
private fun error(htmlPage: String): MutableList<String>? {
|
||||||
var message = ""
|
var message = ""
|
||||||
|
var array: MutableList<String>? = null
|
||||||
if (errorNotConnected in htmlPage) {
|
if (errorNotConnected in htmlPage) {
|
||||||
|
if (loginAttemptsExceeded in htmlPage) {
|
||||||
|
message = applicationContext().getString(R.string.loginAttemptsExceeded)
|
||||||
|
val qaConfirmID = "(?<=qa_confirm_id\" value=\")(.{32})".toRegex().find(htmlPage)?.value
|
||||||
|
var answer = "(?<=answer\">)(.*)</l".toRegex().find(htmlPage)?.value
|
||||||
|
answer = answer?.dropLast(3)
|
||||||
|
array = mutableListOf("loginAttemptsExceeded", answer.toString(), qaConfirmID.toString())
|
||||||
|
} else {
|
||||||
message = "${applicationContext().getString(R.string.connectionFailed)}\n${applicationContext().getString(R.string.credentialsDeleted)}."
|
message = "${applicationContext().getString(R.string.connectionFailed)}\n${applicationContext().getString(R.string.credentialsDeleted)}."
|
||||||
Credentials().delete()
|
Credentials().delete()
|
||||||
} else if (loginAttemptsExceeded in htmlPage) {
|
array = mutableListOf("errorNotConnected")
|
||||||
message = applicationContext().getString(R.string.loginAttemptsExceeded)
|
}
|
||||||
}
|
}
|
||||||
println(errorFormat(message = message))
|
println(errorFormat(message = message))
|
||||||
Toast.makeText(applicationContext(), message, Toast.LENGTH_LONG)
|
Toast.makeText(applicationContext(), message, Toast.LENGTH_LONG)
|
||||||
.show()
|
.show()
|
||||||
|
|
||||||
|
return array
|
||||||
}
|
}
|
||||||
|
|
||||||
fun search() { // Do the research.
|
fun search(): MutableList<String>? { // Do the research.
|
||||||
if (sid == null) {
|
if (sid == null) {
|
||||||
println(errorFormat(message = "No SID found"))
|
println(errorFormat(message = "SID not found"))
|
||||||
if (retry < 3) return connect() else return
|
return if (retry < 3) connect() else null
|
||||||
} else {
|
} else {
|
||||||
if (debug) println("SID recovered")
|
if (debug) println("SID recovered")
|
||||||
retry = 0
|
retry = 0
|
||||||
}
|
}
|
||||||
if (debug) println("Going to search page...")
|
if (debug) println("Going to search page...")
|
||||||
FuelManager.instance.basePath = url
|
FuelManager.instance.basePath = url
|
||||||
FuelManager.instance.baseParams =
|
FuelManager.instance.baseParams = listOf("sid" to sid, "sr" to "topics", "sf" to "titleonly")
|
||||||
listOf("sid" to sid, "sr" to "topics", "sf" to "titleonly")
|
|
||||||
val session = "/search.php"
|
val session = "/search.php"
|
||||||
.httpGet(listOf("keywords" to app))
|
.httpGet(listOf("keywords" to app))
|
||||||
.responseString { _, response, result ->
|
.responseString { _, response, result ->
|
||||||
|
@ -95,15 +111,16 @@ class Scraper(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val data = session.join().data.decodeToString()
|
val data = session.join().data.decodeToString()
|
||||||
if (searchNotLogged in data) {
|
return if (searchNotLogged in data) {
|
||||||
println(errorFormat(message = "The SID doesn't work, new attempt..."))
|
println(errorFormat(message = "The SID doesn't work, new attempt..."))
|
||||||
if (retry < 3) return connect() else return
|
if (retry < 3) connect() else null
|
||||||
} else return parse(data)
|
} else parse(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parse(htmlPage: String) {
|
private fun parse(htmlPage: String): MutableList<String>? {
|
||||||
if (debug) println("Fetching results for $app...")
|
if (debug) println("Fetching results for $app...")
|
||||||
// println(htmlPage)
|
// println(htmlPage)
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue