Skip to content

Commit 7e19557

Browse files
Merge branch 'main' into Recurring-tasks-WorkManager
2 parents ac984f9 + ed1c57c commit 7e19557

File tree

7 files changed

+62
-62
lines changed

7 files changed

+62
-62
lines changed

app/src/main/java/org/wikipedia/dataclient/Service.kt

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ interface Service {
171171
suspend fun getSiteInfoWithMagicWords(): MwQueryResponse
172172

173173
@GET(MW_API_PREFIX + "action=parse&prop=text&mobileformat=1")
174-
fun parsePage(@Query("page") pageTitle: String): Observable<MwParseResponse>
174+
suspend fun parsePage(@Query("page") pageTitle: String): MwParseResponse
175175

176176
@GET(MW_API_PREFIX + "action=parse&prop=text&mobileformat=1")
177-
fun parseText(@Query("text") text: String): Observable<MwParseResponse>
177+
suspend fun parseText(@Query("text") text: String): MwParseResponse
178178

179179
@GET(MW_API_PREFIX + "action=parse&prop=text&mobileformat=1&mainpage=1")
180180
suspend fun parseTextForMainPage(@Query("page") mainPageTitle: String): MwParseResponse
@@ -317,10 +317,7 @@ interface Service {
317317
@get:GET(MW_API_PREFIX + "action=query&meta=authmanagerinfo|tokens&amirequestsfor=create&type=createaccount")
318318
val authManagerInfo: Observable<MwQueryResponse>
319319

320-
@get:GET(MW_API_PREFIX + "action=query&meta=userinfo&uiprop=groups|blockinfo|editcount|latestcontrib|hasmsg")
321-
val userInfo: Observable<MwQueryResponse>
322-
323-
@GET(MW_API_PREFIX + "action=query&meta=userinfo&uiprop=groups|blockinfo|editcount|latestcontrib|hasmsg")
320+
@GET(MW_API_PREFIX + "action=query&meta=userinfo&uiprop=groups|blockinfo|editcount|latestcontrib|hasmsg|options")
324321
suspend fun getUserInfo(): MwQueryResponse
325322

326323
@GET(MW_API_PREFIX + "action=query&list=users&usprop=editcount|groups|registration|rights")
@@ -456,7 +453,7 @@ interface Service {
456453
@Field("data-ge-task-image-recommendation") imageRecommendationJson: String? = null,
457454
): Edit
458455

459-
@GET(MW_API_PREFIX + "action=query&list=usercontribs&ucprop=ids|title|timestamp|comment|size|flags|sizediff|tags&meta=userinfo&uiprop=groups|blockinfo|editcount|latestcontrib|rights")
456+
@GET(MW_API_PREFIX + "action=query&list=usercontribs&ucprop=ids|title|timestamp|comment|size|flags|sizediff|tags&meta=userinfo&uiprop=groups|blockinfo|editcount|latestcontrib|rights|registrationdate")
460457
suspend fun getUserContributions(
461458
@Query("ucuser") username: String,
462459
@Query("uclimit") maxCount: Int,

app/src/main/java/org/wikipedia/dataclient/mwapi/MwServiceError.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package org.wikipedia.dataclient.mwapi
22

3+
import kotlinx.coroutines.CoroutineExceptionHandler
4+
import kotlinx.coroutines.runBlocking
35
import kotlinx.serialization.SerialName
46
import kotlinx.serialization.Serializable
57
import org.wikipedia.dataclient.ServiceError
68
import org.wikipedia.util.DateUtil
79
import org.wikipedia.util.StringUtil
810
import org.wikipedia.util.ThrowableUtil
11+
import org.wikipedia.util.log.L
912
import java.util.*
1013

1114
@Serializable
@@ -36,7 +39,11 @@ class MwServiceError(val code: String? = null,
3639
init {
3740
// Special case: if it's a Blocked error, parse the blockinfo structure ourselves.
3841
if (("blocked" == code || "autoblocked" == code) && data?.blockinfo != null) {
39-
html = ThrowableUtil.getBlockMessageHtml(data.blockinfo)
42+
runBlocking(CoroutineExceptionHandler { _, t ->
43+
L.e(t)
44+
}) {
45+
html = ThrowableUtil.getBlockMessageHtml(data.blockinfo)
46+
}
4047
}
4148
}
4249

app/src/main/java/org/wikipedia/edit/EditSectionActivity.kt

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@ import androidx.core.os.postDelayed
2121
import androidx.core.view.isGone
2222
import androidx.core.view.isVisible
2323
import androidx.core.widget.doAfterTextChanged
24+
import androidx.lifecycle.lifecycleScope
2425
import com.google.android.material.dialog.MaterialAlertDialogBuilder
2526
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
2627
import io.reactivex.rxjava3.disposables.CompositeDisposable
2728
import io.reactivex.rxjava3.schedulers.Schedulers
29+
import kotlinx.coroutines.CoroutineExceptionHandler
30+
import kotlinx.coroutines.launch
2831
import org.wikipedia.Constants
2932
import org.wikipedia.R
3033
import org.wikipedia.WikipediaApp
@@ -41,7 +44,6 @@ import org.wikipedia.databinding.DialogWithCheckboxBinding
4144
import org.wikipedia.databinding.ItemEditActionbarButtonBinding
4245
import org.wikipedia.dataclient.ServiceFactory
4346
import org.wikipedia.dataclient.mwapi.MwException
44-
import org.wikipedia.dataclient.mwapi.MwParseResponse
4547
import org.wikipedia.dataclient.mwapi.MwServiceError
4648
import org.wikipedia.dataclient.okhttp.OkHttpConnectionFactory
4749
import org.wikipedia.edit.insertmedia.InsertMediaActivity
@@ -418,23 +420,24 @@ class EditSectionActivity : BaseActivity(), ThemeChooserDialog.Callback, EditPre
418420
*/
419421
private fun handleEditingException(caught: MwException) {
420422
val code = caught.title
421-
422-
// In the case of certain AbuseFilter responses, they are sent as a code, instead of a
423-
// fully parsed response. We need to make one more API call to get the parsed message:
424-
if (code.startsWith("abusefilter-") && caught.message.contains("abusefilter-") && caught.message.length < 100) {
425-
disposables.add(ServiceFactory.get(pageTitle.wikiSite).parsePage("MediaWiki:" + StringUtil.sanitizeAbuseFilterCode(caught.message))
426-
.subscribeOn(Schedulers.io())
427-
.observeOn(AndroidSchedulers.mainThread())
428-
.subscribe({ response: MwParseResponse -> showError(MwException(MwServiceError(code, response.text))) }) { showError(it) })
429-
} else if ("editconflict" == code) {
430-
MaterialAlertDialogBuilder(this@EditSectionActivity)
423+
lifecycleScope.launch(CoroutineExceptionHandler { _, t ->
424+
showError(t)
425+
}) {
426+
// In the case of certain AbuseFilter responses, they are sent as a code, instead of a
427+
// fully parsed response. We need to make one more API call to get the parsed message:
428+
if (code.startsWith("abusefilter-") && caught.message.contains("abusefilter-") && caught.message.length < 100) {
429+
val response = ServiceFactory.get(pageTitle.wikiSite).parsePage("MediaWiki:" + StringUtil.sanitizeAbuseFilterCode(caught.message))
430+
showError(MwException(MwServiceError(code, response.text)))
431+
} else if ("editconflict" == code) {
432+
MaterialAlertDialogBuilder(this@EditSectionActivity)
431433
.setTitle(R.string.edit_conflict_title)
432434
.setMessage(R.string.edit_conflict_message)
433435
.setPositiveButton(R.string.edit_conflict_dialog_ok_button_text, null)
434436
.show()
435-
resetToStart()
436-
} else {
437-
showError(caught)
437+
resetToStart()
438+
} else {
439+
showError(caught)
440+
}
438441
}
439442
}
440443

app/src/main/java/org/wikipedia/suggestededits/SuggestedEditsTasksFragment.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ class SuggestedEditsTasksFragment : Fragment() {
209209

210210
setUpTasks()
211211

212+
if (displayedTasks.isEmpty() && !viewModel.blockMessageWikipedia.isNullOrEmpty()) {
213+
clearContents()
214+
setIPBlockedStatus()
215+
return
216+
}
217+
212218
binding.tasksRecyclerView.adapter!!.notifyDataSetChanged()
213219
setUserStatsViewsAndTooltips()
214220

@@ -376,10 +382,6 @@ class SuggestedEditsTasksFragment : Fragment() {
376382
displayedTasks.add(addImageCaptionsTask)
377383
displayedTasks.add(addImageTagsTask)
378384
}
379-
380-
if (displayedTasks.isEmpty() && !viewModel.blockMessageWikipedia.isNullOrEmpty()) {
381-
setIPBlockedStatus()
382-
}
383385
}
384386

385387
private inner class TaskViewCallback : SuggestedEditsTaskView.Callback {

app/src/main/java/org/wikipedia/suggestededits/SuggestedEditsTasksFragmentViewModel.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import org.wikipedia.dataclient.mwapi.UserContribution
1616
import org.wikipedia.usercontrib.UserContribStats
1717
import org.wikipedia.util.Resource
1818
import org.wikipedia.util.ThrowableUtil
19+
import java.time.Instant
1920
import java.time.temporal.ChronoUnit
2021
import java.util.Date
2122

@@ -84,7 +85,14 @@ class SuggestedEditsTasksFragmentViewModel : ViewModel() {
8485
wikiSupportsImageRecommendations = true
8586

8687
homeSiteResponse.query?.userInfo?.let {
87-
allowToPatrolEdits = it.rights.contains("rollback") || it.groups().contains("sysop")
88+
// T371442: In the case of Igbo Wikipedia, allow patrolling if the user has 500 or more edits, and 30 days of tenure.
89+
// For all other wikis, allow patrolling if the user has rollback rights or is an admin.
90+
if (WikipediaApp.instance.wikiSite.languageCode == "ig") {
91+
allowToPatrolEdits = it.editCount >= 500 && it.registrationDate.toInstant().plus(30, ChronoUnit.DAYS).isBefore(Instant.now())
92+
} else {
93+
allowToPatrolEdits = it.rights.contains("rollback") || it.groups().contains("sysop")
94+
}
95+
8896
if (it.isBlocked) {
8997
blockMessageWikipedia = ThrowableUtil.getBlockMessageHtml(it, WikipediaApp.instance.wikiSite)
9098
}

app/src/main/java/org/wikipedia/util/ThrowableUtil.kt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package org.wikipedia.util
22

33
import android.content.Context
4-
import androidx.annotation.WorkerThread
5-
import io.reactivex.rxjava3.core.Observable
4+
import kotlinx.coroutines.Dispatchers
5+
import kotlinx.coroutines.async
6+
import kotlinx.coroutines.withContext
67
import org.json.JSONException
78
import org.wikipedia.R
89
import org.wikipedia.WikipediaApp
@@ -13,7 +14,6 @@ import org.wikipedia.dataclient.mwapi.MwException
1314
import org.wikipedia.dataclient.mwapi.MwServiceError
1415
import org.wikipedia.dataclient.okhttp.HttpStatusException
1516
import org.wikipedia.login.LoginFailedException
16-
import org.wikipedia.util.log.L
1717
import java.net.SocketException
1818
import java.net.SocketTimeoutException
1919
import java.net.UnknownHostException
@@ -91,17 +91,16 @@ object ThrowableUtil {
9191
return t is MwException && t.error.code?.contains("notloggedin") == true
9292
}
9393

94-
@WorkerThread
95-
fun getBlockMessageHtml(blockInfo: MwServiceError.BlockInfo, wikiSite: WikiSite = WikipediaApp.instance.wikiSite): String {
94+
suspend fun getBlockMessageHtml(blockInfo: MwServiceError.BlockInfo, wikiSite: WikiSite = WikipediaApp.instance.wikiSite): String {
9695
var html = ""
97-
Observable.zip(ServiceFactory.get(wikiSite).userInfo,
98-
ServiceFactory.get(wikiSite).parsePage("MediaWiki:Blockedtext"),
99-
ServiceFactory.get(wikiSite).parseText(blockInfo.blockReason)) { userInfoResponse, blockedParseResponse, reasonParseResponse ->
100-
parseBlockedError(
101-
blockedParseResponse.text, blockInfo,
102-
reasonParseResponse.text, userInfoResponse.query?.userInfo!!.name
103-
)
104-
}.blockingSubscribe({ html = it }) { L.e(it) }
96+
withContext(Dispatchers.IO) {
97+
val userInfoCall = async { ServiceFactory.get(wikiSite).getUserInfo() }
98+
val blockedPageCall = async { ServiceFactory.get(wikiSite).parsePage("MediaWiki:Blockedtext") }
99+
val reasonTextCall = async { ServiceFactory.get(wikiSite).parseText(blockInfo.blockReason) }
100+
101+
html = parseBlockedError(blockedPageCall.await().text, blockInfo,
102+
reasonTextCall.await().text, userInfoCall.await().query?.userInfo!!.name)
103+
}
105104
return html
106105
}
107106

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.wikipedia.login
22

3+
import kotlinx.coroutines.runBlocking
34
import org.junit.Test
45
import org.wikipedia.test.MockRetrofitTest
56

@@ -9,27 +10,10 @@ class UserExtendedInfoClientTest : MockRetrofitTest() {
910
fun testRequestSuccess() {
1011
enqueueFromFile("user_extended_info.json")
1112
val id = 24531888
12-
apiService.userInfo.test().await()
13-
.assertComplete().assertNoErrors()
14-
.assertValue {
15-
it.query?.userInfo?.id == id &&
16-
it.query?.getUserResponse("USER")?.name == "USER"
17-
}
18-
}
19-
20-
@Test
21-
@Throws(Throwable::class)
22-
fun testRequestResponse404() {
23-
enqueue404()
24-
apiService.userInfo.test().await()
25-
.assertError(Exception::class.java)
26-
}
27-
28-
@Test
29-
@Throws(Throwable::class)
30-
fun testRequestResponseMalformed() {
31-
enqueueMalformed()
32-
apiService.userInfo.test().await()
33-
.assertError(Exception::class.java)
13+
runBlocking {
14+
val userInfo = apiService.getUserInfo()
15+
assert(userInfo.query?.userInfo?.id == id)
16+
assert(userInfo.query?.getUserResponse("USER")?.name == "USER")
17+
}
3418
}
3519
}

0 commit comments

Comments
 (0)