Skip to content

Commit e08e007

Browse files
committed
Refactor and add KDoc to SpamUtils
1 parent 5b831aa commit e08e007

File tree

1 file changed

+104
-32
lines changed

1 file changed

+104
-32
lines changed

app/src/main/java/com/addev/listaspam/SpamUtils.kt

Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.addev.listaspam
22

33
import android.Manifest
4-
import android.app.Activity
54
import android.app.NotificationChannel
65
import android.app.NotificationManager
76
import android.content.Context
@@ -21,6 +20,9 @@ import okhttp3.Response
2120
import org.jsoup.Jsoup
2221
import java.io.IOException
2322

23+
/**
24+
* Utility class for handling spam number checks and notifications.
25+
*/
2426
class SpamUtils {
2527

2628
companion object {
@@ -30,71 +32,114 @@ class SpamUtils {
3032
private const val RESPONDERONO_URL_TEMPLATE = "https://www.responderono.es/numero-de-telefono/%s"
3133
private const val NOTIFICATION_CHANNEL_ID = "NOTIFICATION_CHANNEL"
3234
private const val NOTIFICATION_ID = 1
35+
private const val SPAM_REPORT_THRESHOLD = 1
3336
}
3437

38+
/**
39+
* Checks if a given phone number is considered spam by querying spam databases.
40+
* @param context Context for accessing resources.
41+
* @param number Phone number to check.
42+
* @param callback Callback function to handle the result.
43+
*/
3544
fun checkSpamNumber(context: Context, number: String, callback: (isSpam: Boolean) -> Unit) {
3645
val url = SPAM_URL_TEMPLATE.format(number)
3746
val request = Request.Builder().url(url).build()
3847

3948
OkHttpClient().newCall(request).enqueue(object : Callback {
4049
override fun onFailure(call: Call, e: IOException) {
41-
// Handle error gracefully
42-
Handler(Looper.getMainLooper()).post {
43-
showToast(context, "Failed to check number in www.listaspam.com", Toast.LENGTH_LONG)
44-
callback(false)
45-
}
50+
handleNetworkFailure(context, "Failed to check number in www.listaspam.com", e, callback)
4651
}
4752

4853
override fun onResponse(call: Call, response: Response) {
4954
response.body?.string()?.let { body ->
5055
val spamData = parseHtmlForSpamReports(body)
51-
if (spamData.reports > 1) {
52-
saveSpamNumber(context, number)
53-
sendNotification(context, number)
54-
callback(true)
56+
if (spamData.reports > SPAM_REPORT_THRESHOLD) {
57+
handleSpamNumber(context, number, callback)
5558
} else {
5659
checkResponderono(context, number) { isResponderONoNegative ->
5760
if (isResponderONoNegative) {
58-
saveSpamNumber(context, number)
59-
sendNotification(context, number)
60-
callback(true)
61+
handleSpamNumber(context, number, callback)
6162
} else {
62-
Handler(Looper.getMainLooper()).post {
63-
showToast(context, "Incoming call is not spam", Toast.LENGTH_LONG)
64-
}
65-
removeSpamNumber(context, number)
66-
callback(false)
63+
handleNonSpamNumber(context, number, callback)
6764
}
6865
}
6966
}
70-
}
67+
} ?: handleNetworkFailure(context, "Empty response from www.listaspam.com", null, callback)
7168
}
7269
})
7370
}
7471

75-
fun checkResponderono(context: Context, number: String, callback: (isNegative: Boolean) -> Unit) {
72+
/**
73+
* Checks if a given phone number is considered negative by the ResponderONo database.
74+
* @param context Context for accessing resources.
75+
* @param number Phone number to check.
76+
* @param callback Callback function to handle the result.
77+
*/
78+
private fun checkResponderono(context: Context, number: String, callback: (isNegative: Boolean) -> Unit) {
7679
val url = RESPONDERONO_URL_TEMPLATE.format(number)
7780
val request = Request.Builder().url(url).build()
7881

7982
OkHttpClient().newCall(request).enqueue(object : Callback {
8083
override fun onFailure(call: Call, e: IOException) {
81-
// Handle error gracefully
82-
Handler(Looper.getMainLooper()).post {
83-
showToast(context, "Failed to check number in www.responderono.es", Toast.LENGTH_LONG)
84-
callback(false)
85-
}
84+
handleNetworkFailure(context, "Failed to check number in www.responderono.es", e, callback)
8685
}
8786

8887
override fun onResponse(call: Call, response: Response) {
8988
response.body?.string()?.let { body ->
9089
val isResponderONoNegative = body.contains(".scoreContainer .score.negative")
9190
callback(isResponderONoNegative)
92-
}
91+
} ?: handleNetworkFailure(context, "Empty response from www.responderono.es", null, callback)
9392
}
9493
})
9594
}
9695

97-
fun saveSpamNumber(context: Context, number: String) {
96+
/**
97+
* Handles the scenario when a phone number is identified as spam.
98+
* @param context Context for accessing resources.
99+
* @param number Phone number identified as spam.
100+
* @param callback Callback function to handle the result.
101+
*/
102+
private fun handleSpamNumber(context: Context, number: String, callback: (isSpam: Boolean) -> Unit) {
103+
saveSpamNumber(context, number)
104+
sendNotification(context, number)
105+
callback(true)
106+
}
107+
108+
/**
109+
* Handles the scenario when a phone number is not identified as spam.
110+
* @param context Context for accessing resources.
111+
* @param number Phone number identified as not spam.
112+
* @param callback Callback function to handle the result.
113+
*/
114+
private fun handleNonSpamNumber(context: Context, number: String, callback: (isSpam: Boolean) -> Unit) {
115+
Handler(Looper.getMainLooper()).post {
116+
showToast(context, "Incoming call is not spam", Toast.LENGTH_LONG)
117+
}
118+
removeSpamNumber(context, number)
119+
callback(false)
120+
}
121+
122+
/**
123+
* Handles network failures by showing a toast message and logging the error.
124+
* @param context Context for accessing resources.
125+
* @param message Error message to display.
126+
* @param e Exception that occurred (optional).
127+
* @param callback Callback function to handle the result.
128+
*/
129+
private fun handleNetworkFailure(context: Context, message: String, e: IOException?, callback: (Boolean) -> Unit) {
130+
Handler(Looper.getMainLooper()).post {
131+
showToast(context, message, Toast.LENGTH_LONG)
132+
}
133+
e?.printStackTrace()
134+
callback(false)
135+
}
136+
137+
/**
138+
* Saves a phone number as spam in SharedPreferences.
139+
* @param context Context for accessing resources.
140+
* @param number Phone number to save as spam.
141+
*/
142+
private fun saveSpamNumber(context: Context, number: String) {
98143
val sharedPreferences = context.getSharedPreferences(SPAM_PREFS, Context.MODE_PRIVATE)
99144
val blockedNumbers = sharedPreferences.getStringSet(BLOCK_NUMBERS_KEY, mutableSetOf())?.toMutableSet()
100145
blockedNumbers?.add(number)
@@ -104,7 +149,12 @@ class SpamUtils {
104149
}
105150
}
106151

107-
fun removeSpamNumber(context: Context, number: String) {
152+
/**
153+
* Removes a phone number from spam list in SharedPreferences.
154+
* @param context Context for accessing resources.
155+
* @param number Phone number to remove from spam list.
156+
*/
157+
private fun removeSpamNumber(context: Context, number: String) {
108158
val sharedPreferences = context.getSharedPreferences(SPAM_PREFS, Context.MODE_PRIVATE)
109159
val blockedNumbers = sharedPreferences.getStringSet(BLOCK_NUMBERS_KEY, mutableSetOf())?.toMutableSet()
110160
blockedNumbers?.remove(number)
@@ -114,11 +164,24 @@ class SpamUtils {
114164
}
115165
}
116166

117-
fun showToast(context: Context, message: String, duration: Int = Toast.LENGTH_SHORT) {
118-
Toast.makeText(context, message, duration).show()
167+
/**
168+
* Displays a toast message.
169+
* @param context Context for displaying the toast.
170+
* @param message Message to display.
171+
* @param duration Duration of the toast display.
172+
*/
173+
private fun showToast(context: Context, message: String, duration: Int = Toast.LENGTH_SHORT) {
174+
Handler(Looper.getMainLooper()).post {
175+
Toast.makeText(context, message, duration).show()
176+
}
119177
}
120178

121-
fun sendNotification(context: Context, number: String) {
179+
/**
180+
* Sends a notification indicating that a spam number has been blocked.
181+
* @param context Context for sending the notification.
182+
* @param number Phone number that was blocked.
183+
*/
184+
private fun sendNotification(context: Context, number: String) {
122185
createNotificationChannel(context)
123186
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
124187
.setSmallIcon(R.mipmap.ic_launcher)
@@ -138,6 +201,10 @@ class SpamUtils {
138201
NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, notification)
139202
}
140203

204+
/**
205+
* Creates a notification channel for spam notifications.
206+
* @param context Context for creating the notification channel.
207+
*/
141208
private fun createNotificationChannel(context: Context) {
142209
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
143210
val name = "Spam Blocker Channel"
@@ -153,7 +220,12 @@ class SpamUtils {
153220
}
154221
}
155222

156-
fun parseHtmlForSpamReports(html: String): SpamData {
223+
/**
224+
* Parses HTML content to extract spam report data.
225+
* @param html HTML content to parse.
226+
* @return [SpamData] containing the number of reports and searches.
227+
*/
228+
private fun parseHtmlForSpamReports(html: String): SpamData {
157229
val document = Jsoup.parse(html)
158230
val elementReports = document.select(".n_reports .result").first()
159231
val elementSearches = document.select(".n_search .result").first()

0 commit comments

Comments
 (0)