@@ -30,12 +30,12 @@ class TrackingRepository(private val context: Context) {
3030 listOf (" ME" ).any { cleanCode.startsWith(it) } && cleanCode.length >= 12 -> true
3131 listOf (" AJ" ).any { cleanCode.startsWith(it) } && cleanCode.length >= 12 -> true
3232 listOf (" BR" , " SPX" ).any { cleanCode.startsWith(it) } && cleanCode.length >= 12 -> true
33+ listOf (" TX" ).any { cleanCode.startsWith(it) } || listOf (" TX" ).any { cleanCode.endsWith(it) } -> true
3334 listOf (" AD" , " AB" , " AN" ).any { cleanCode.startsWith(it) } && cleanCode.length >= 12 -> true
3435 else -> false
3536 }
3637 }
37-
38- suspend fun trackPackage (code : String , forceRefresh : Boolean = false): TrackingResponse ? {
38+ suspend fun trackPackage (code : String , forceRefresh : Boolean = false, carrier : String = "Auto "): TrackingResponse ? {
3939 val cleanCode = code.trim().uppercase()
4040
4141 if (! forceRefresh) {
@@ -48,14 +48,26 @@ class TrackingRepository(private val context: Context) {
4848
4949 Log .d(" TRACKING" , " Baixando da internet: $cleanCode " )
5050
51- val result = when {
52- listOf (" MZ" , " LJ" , " LOG" ).any { cleanCode.startsWith(it) } -> { trackViaLoggi(cleanCode) }
53- listOf (" NN" , " LP" ).any { cleanCode.startsWith(it) } -> { trackCainiaoFree(cleanCode) }
54- listOf (" ME" ).any { cleanCode.startsWith(it) } -> { trackMelhorRastreioFree(cleanCode) }
55- listOf (" AJ" ).any { cleanCode.startsWith(it) } -> { trackViaAnjun(cleanCode) }
56- listOf (" BR" , " SPX" ).any { cleanCode.startsWith(it) } -> { trackViaSpxWebView(cleanCode) }
57- listOf (" AD" , " AB" , " AN" ).any { cleanCode.startsWith(it) } -> { trackViaLinketrackWebView(cleanCode) }
58- else -> { null }
51+ val result = when (carrier) {
52+ " Correios" -> trackViaLinketrackWebView(cleanCode)
53+ " Loggi" -> trackViaLoggi(cleanCode)
54+ " Shopee" -> trackViaSpxWebView(cleanCode)
55+ " AliExpress" -> trackCainiaoFree(cleanCode)
56+ " Shein" -> trackViaAnjun(cleanCode)
57+ " Melhor Envio" -> trackMelhorRastreioFree(cleanCode)
58+ " Total Express" -> trackViaTotalExpress(cleanCode)
59+ else -> {
60+ when {
61+ listOf (" MZ" , " LJ" , " LOG" ).any { cleanCode.startsWith(it) } -> { trackViaLoggi(cleanCode) }
62+ listOf (" NN" , " LP" ).any { cleanCode.startsWith(it) } -> { trackCainiaoFree(cleanCode) }
63+ listOf (" ME" ).any { cleanCode.startsWith(it) } -> { trackMelhorRastreioFree(cleanCode) }
64+ listOf (" AJ" ).any { cleanCode.startsWith(it) } -> { trackViaAnjun(cleanCode) }
65+ listOf (" BR" , " SPX" ).any { cleanCode.startsWith(it) } -> { trackViaSpxWebView(cleanCode) }
66+ listOf (" TX" ).any { cleanCode.startsWith(it) } || listOf (" TX" ).any { cleanCode.endsWith(it) } -> { trackViaTotalExpress(cleanCode) }
67+ listOf (" AD" , " AB" , " AN" ).any { cleanCode.startsWith(it) } -> { trackViaLinketrackWebView(cleanCode) }
68+ else -> { null }
69+ }
70+ }
5971 }
6072
6173 if (result != null && ! result.events.isNullOrEmpty()) {
@@ -65,6 +77,77 @@ class TrackingRepository(private val context: Context) {
6577 return result
6678 }
6779
80+ private suspend fun trackViaTotalExpress (code : String ): TrackingResponse ? {
81+ return withContext(Dispatchers .IO ) {
82+ try {
83+ val url = " https://totalconecta.totalexpress.com.br/mfe-rastreio/api/order-data?awb=$code &language=pt"
84+ val request = Request .Builder ()
85+ .url(url)
86+ .addHeader(" User-Agent" , " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" )
87+ .addHeader(" Accept" , " application/json, text/plain, */*" )
88+ .addHeader(" Accept-Language" , " pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7" )
89+ .addHeader(" Sec-Ch-Ua" , " \" Chromium\" ;v=\" 122\" , \" Not(A:Brand\" ;v=\" 24\" , \" Google Chrome\" ;v=\" 122\" " )
90+ .addHeader(" Sec-Ch-Ua-Mobile" , " ?0" )
91+ .addHeader(" Sec-Ch-Ua-Platform" , " \" Windows\" " )
92+ .addHeader(" Sec-Fetch-Dest" , " empty" )
93+ .addHeader(" Sec-Fetch-Mode" , " cors" )
94+ .addHeader(" Sec-Fetch-Site" , " same-site" )
95+ .addHeader(" Referer" , " https://totalconecta.totalexpress.com.br/mfe-rastreio/" )
96+ .build()
97+ val response = client.newCall(request).execute()
98+ val body = response.body?.string()
99+ if (! response.isSuccessful) {
100+ return @withContext null
101+ }
102+ if (body.isNullOrBlank()) {
103+ return @withContext null
104+ }
105+ val rawData = gson.fromJson(body, TotalExpressResponse ::class .java)
106+ val layouts = rawData.data?.layouts
107+ if (layouts.isNullOrEmpty()) {
108+ return @withContext null
109+ }
110+ val events = mutableListOf<TrackingEvent >()
111+
112+ layouts.forEach { layout ->
113+ layout.etapas?.forEach { etapa ->
114+ etapa.listaStatus?.forEach { status ->
115+ val dateParts = status.data?.split(" -" )
116+ val formattedDate = if (dateParts != null && dateParts.size == 3 ) {
117+ " ${dateParts[2 ]} /${dateParts[1 ]} /${dateParts[0 ]} "
118+ } else {
119+ status.data ? : " "
120+ }
121+
122+ events.add(
123+ TrackingEvent (
124+ status = status.statusDescricao ? : " Atualização" ,
125+ date = formattedDate,
126+ time = status.hora ? : " " ,
127+ location = status.mensagemEvaTraducao?.mensagemEva ? : " Total Express" ,
128+ subStatus = null
129+ )
130+ )
131+ }
132+ }
133+ }
134+
135+ if (events.isEmpty()) {
136+ Log .e(" TOTAL_EXPRESS" , " Eventos vazios após mapeamento." )
137+ return @withContext null
138+ }
139+
140+ Log .d(" TOTAL_EXPRESS" , " Sucesso! Foram mapeados ${events.size} eventos." )
141+ return @withContext TrackingResponse (tracking_code = code, events = events.reversed())
142+
143+ } catch (e: Exception ) {
144+ Log .e(" TOTAL_EXPRESS" , " Erro fatal no rastreio: ${e.message} " )
145+ e.printStackTrace()
146+ null
147+ }
148+ }
149+ }
150+
68151 private suspend fun trackViaLinketrackWebView (code : String ): TrackingResponse ? {
69152 val cleanCode = code.substringBefore(" |" ).trim()
70153
0 commit comments