@@ -10,6 +10,8 @@ import android.provider.ContactsContract
1010import android.widget.Toast
1111import androidx.core.content.ContextCompat
1212import com.addev.listaspam.R
13+ import com.google.i18n.phonenumbers.PhoneNumberUtil
14+ import com.google.i18n.phonenumbers.Phonenumber
1315import kotlinx.coroutines.CoroutineScope
1416import kotlinx.coroutines.Dispatchers
1517import kotlinx.coroutines.launch
@@ -18,6 +20,7 @@ import okhttp3.OkHttpClient
1820import okhttp3.Request
1921import org.jsoup.Jsoup
2022import java.io.IOException
23+ import java.util.Locale
2124
2225/* *
2326 * Utility class for handling spam number checks and notifications.
@@ -27,8 +30,10 @@ class SpamUtils {
2730 companion object {
2831 // URLs
2932 const val LISTA_SPAM_URL_TEMPLATE = " https://www.listaspam.com/busca.php?Telefono=%s"
33+ const val LISTA_SPAM_CSS_SELECTOR = " .data_top .phone_rating.result-3, .data_top .phone_rating.result-2, .data_top .phone_rating.result-1, .alert-icon-big"
3034 private const val RESPONDERONO_URL_TEMPLATE =
3135 " https://www.responderono.es/numero-de-telefono/%s"
36+ private const val RESPONDERONO_CSS_SELECTOR = " .scoreContainer .score.negative"
3237 private const val CLEVER_DIALER_URL_TEMPLATE = " https://www.cleverdialer.es/numero/%s"
3338 }
3439
@@ -44,14 +49,28 @@ class SpamUtils {
4449 fun checkSpamNumber (context : Context , number : String , callback : (isSpam: Boolean ) -> Unit ) {
4550 CoroutineScope (Dispatchers .IO ).launch {
4651 if (! isBlockingEnabled(context)) {
52+ showToast(context, context.getString(R .string.blocking_disabled), Toast .LENGTH_LONG )
53+ return @launch
54+ }
55+
56+ if (number.isNullOrBlank() && shouldBlockHiddenNumbers(context)) {
57+ showToast(context, context.getString(R .string.block_hidden_number), Toast .LENGTH_LONG )
58+ handleSpamNumber(context, number, false , callback)
4759 return @launch
4860 }
4961
5062 if (isNumberWhitelisted(context, number)) {
5163 return @launch
5264 }
5365
66+ if (isInternationalCall(number) && shouldBlockInternationalNumbers(context)) {
67+ showToast(context, context.getString(R .string.block_international_call), Toast .LENGTH_LONG )
68+ handleSpamNumber(context, number, false , callback)
69+ return @launch
70+ }
71+
5472 if (isNumberBlocked(context, number)) {
73+ showToast(context, context.getString(R .string.block_already_blocked_number), Toast .LENGTH_LONG )
5574 handleSpamNumber(context, number, callback)
5675 return @launch
5776 }
@@ -60,7 +79,9 @@ class SpamUtils {
6079 if (isNumberInAgenda(context, number)) {
6180 return @launch
6281 } else if (shouldBlockNonContacts(context)) {
63- handleSpamNumber(context, number, callback)
82+ showToast(context, context.getString(R .string.block_non_contact), Toast .LENGTH_LONG )
83+ handleSpamNumber(context, number, false , callback)
84+ return @launch
6485 }
6586 }
6687
@@ -81,13 +102,39 @@ class SpamUtils {
81102 }
82103
83104 if (isSpam) {
105+ showToast(context, context.getString(R .string.block_non_contact), Toast .LENGTH_LONG )
84106 handleSpamNumber(context, number, callback)
85107 } else {
86108 handleNonSpamNumber(context, number, callback)
87109 }
88110 }
89111 }
90112
113+
114+ fun isInternationalCall (phoneNumber : String ): Boolean {
115+ // Get an instance of PhoneNumberUtil
116+ val phoneNumberUtil = PhoneNumberUtil .getInstance()
117+
118+ try {
119+ // Parse the phone number
120+ val parsedNumber: Phonenumber .PhoneNumber = phoneNumberUtil.parse(phoneNumber, null )
121+
122+ // Get the country code of the parsed number
123+ val phoneCountryCode = parsedNumber.countryCode
124+
125+ // Get the device's country code based on locale
126+ val deviceCountryCode = PhoneNumberUtil .getInstance()
127+ .getCountryCodeForRegion(Locale .getDefault().country)
128+
129+ // Check if the country codes are different
130+ return phoneCountryCode != deviceCountryCode
131+
132+ } catch (e: Exception ) {
133+ e.printStackTrace()
134+ return false
135+ }
136+ }
137+
91138 /* *
92139 * Normalizes a phone number by removing all non-digit characters.
93140 *
@@ -140,7 +187,7 @@ class SpamUtils {
140187 val url = LISTA_SPAM_URL_TEMPLATE .format(number)
141188 return checkUrlForSpam(
142189 url,
143- " .data_top .phone_rating.result-3, .data_top .phone_rating.result-2, .data_top .phone_rating.result-1, .alert-icon-big "
190+ LISTA_SPAM_CSS_SELECTOR
144191 )
145192 }
146193
@@ -152,7 +199,7 @@ class SpamUtils {
152199 */
153200 private suspend fun checkResponderono (number : String ): Boolean {
154201 val url = RESPONDERONO_URL_TEMPLATE .format(number)
155- return checkUrlForSpam(url, " .scoreContainer .score.negative " )
202+ return checkUrlForSpam(url, RESPONDERONO_CSS_SELECTOR )
156203 }
157204
158205 /* *
@@ -191,7 +238,24 @@ class SpamUtils {
191238 number : String ,
192239 callback : (isSpam: Boolean ) -> Unit
193240 ) {
194- saveSpamNumber(context, number)
241+ handleSpamNumber(context, number, true , callback)
242+ }
243+
244+ /* *
245+ * Handles the scenario when a phone number is identified as spam.
246+ * @param context Context for accessing resources.
247+ * @param number Phone number identified as spam.
248+ * @param callback Callback function to handle the result.
249+ */
250+ private fun handleSpamNumber (
251+ context : Context ,
252+ number : String ,
253+ saveNumber : Boolean ,
254+ callback : (isSpam: Boolean ) -> Unit
255+ ) {
256+ if (saveNumber) {
257+ saveSpamNumber(context, number)
258+ }
195259 sendNotification(context, number)
196260 callback(true )
197261 }
0 commit comments