Adding Captcha support and call the login page when auth failed

This commit is contained in:
Mylloon 2021-08-31 00:28:21 +02:00
parent c29abee329
commit 370c0a83a2
2 changed files with 66 additions and 30 deletions

View file

@ -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)) {

View file

@ -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
} }
} }