From ae7a884ec828934b48608113ead2931e21a208db Mon Sep 17 00:00:00 2001 From: Sam J <47988070+sam-jeffery@users.noreply.github.com> Date: Sat, 31 May 2025 16:46:21 +0100 Subject: [PATCH 1/3] Add Cainiao delivery service --- README.md | 1 + .../api/CainiaoDeliveryService.kt | 107 ++++++++++++++++++ .../java/dev/itsvic/parceltracker/api/Core.kt | 3 + app/src/main/res/values-cs/strings.xml | 3 +- app/src/main/res/values-de/strings.xml | 3 +- app/src/main/res/values-hu/strings.xml | 3 +- app/src/main/res/values-ja/strings.xml | 3 +- app/src/main/res/values-pl/strings.xml | 3 +- app/src/main/res/values-sv/strings.xml | 3 +- app/src/main/res/values-th/strings.xml | 3 +- app/src/main/res/values-tr/strings.xml | 3 +- app/src/main/res/values-uk/strings.xml | 3 +- app/src/main/res/values/strings.xml | 2 + 13 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt diff --git a/README.md b/README.md index be71b40..263faa4 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Similarly, we have `./scripts/sort-strings.sh` to sort translation files by key. ## Supported services International: +- Cainiao - DHL - GLS - UPS diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt b/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt new file mode 100644 index 0000000..fb55cc8 --- /dev/null +++ b/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt @@ -0,0 +1,107 @@ +package dev.itsvic.parceltracker.api + +import com.squareup.moshi.JsonClass +import dev.itsvic.parceltracker.R +import retrofit2.Retrofit +import retrofit2.converter.moshi.MoshiConverterFactory +import retrofit2.http.GET +import retrofit2.http.Query +import java.time.Instant +import java.time.LocalDateTime +import java.time.ZoneId +import java.util.Locale + +object CainiaoDeliveryService : DeliveryService { + override val nameResource: Int = R.string.service_cainiao + override val acceptsPostCode: Boolean = false + override val requiresPostCode: Boolean = false + + override suspend fun getParcel(trackingID: String, postalCode: String?): Parcel { + var userLocale = Locale.getDefault() + var language = userLocale.language + val country = userLocale.country + + val parcelResp = service.getParcel(trackingID, "$language-$country", "$language-$country") + + if (!parcelResp.success || parcelResp.module.isEmpty() || parcelResp.module.first().detailList.isEmpty()) { + throw ParcelNonExistentException() + } + + val parcel = parcelResp.module.first() + + val history = + parcel.detailList.map { + ParcelHistoryItem( + it.standerdDesc, + // Sometimes new parcels have no timezone info, so default to origin country (china) + LocalDateTime.ofInstant(Instant.ofEpochMilli(it.time), ZoneId.of(if (it.timeZone.isBlank()) "GMT+8" else it.timeZone)), + "" + ) + } + + // Based on the few tracking numbers I have, there may be more + val status = + when (parcel.detailList.first().actionCode) { + "GWMS_ACCEPT" -> Status.Preadvice + "GWMS_PACKAGE" -> Status.AwaitingPickup + "GWMS_OUTBOUND" -> Status.InTransit + "PU_PICKUP_SUCCESS" -> Status.PickedUp + "CW_OUTBOUND" -> Status.InTransit + "SC_INBOUND_SUCCESS" -> Status.InWarehouse + "SC_OUTBOUND_SUCCESS" -> Status.InTransit + "LH_HO_IN_SUCCESS" -> Status.InWarehouse + "LH_HO_AIRLINE" -> Status.InTransit + "LH_DEPART" -> Status.InTransit + "LH_ARRIVE" -> Status.InWarehouse + "CC_EX_START" -> Status.Customs + "CC_EX_SUCCESS" -> Status.CustomsSuccess + "CC_HO_IN_SUCCESS" -> Status.Customs + "CC_HO_OUT_SUCCESS" -> Status.InTransit + "CC_IM_START" -> Status.Customs + "CC_IM_SUCCESS" -> Status.CustomsSuccess + "GTMS_ACCEPT" -> Status.InTransit + "GTMS_DO_ARRIVE" -> Status.InWarehouse + "GTMS_DO_DEPART" -> Status.OutForDelivery + "GTMS_STATION_OUT" -> Status.InTransit + "GTMS_SIGNED" -> Status.Delivered + else -> + logUnknownStatus( + "Cainiao", parcel.detailList.first().actionCode) + } + + return Parcel(trackingID, history, status) + } + + private val retrofit = + Retrofit.Builder() + .baseUrl("https://global.cainiao.com/global/") + .client(api_client) + .addConverterFactory(MoshiConverterFactory.create(api_moshi)) + .build() + + private val service = retrofit.create(API::class.java) + + private interface API { + @GET("detail.json") + suspend fun getParcel(@Query("mailNos") trackingID: String, @Query("lang") lang: String, @Query("language") language: String): ParcelResponse + } + + @JsonClass(generateAdapter = true) + internal data class ParcelResponse( + val module: List, + val success: Boolean, + ) + + @JsonClass(generateAdapter = true) + internal data class CainiaoParcel( + val detailList: List, + ) + + @JsonClass(generateAdapter = true) + internal data class Event( + val actionCode: String, + val standerdDesc: String, + val time: Long, + val timeZone: String, + ) +} diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/Core.kt b/app/src/main/java/dev/itsvic/parceltracker/api/Core.kt index ddc3f20..fa04ec1 100644 --- a/app/src/main/java/dev/itsvic/parceltracker/api/Core.kt +++ b/app/src/main/java/dev/itsvic/parceltracker/api/Core.kt @@ -19,6 +19,7 @@ enum class Service { EXAMPLE, // International + CAINIAO, DHL, GLS, UPS, @@ -60,6 +61,7 @@ val serviceOptions = fun getDeliveryService(service: Service): DeliveryService? { return when (service) { + Service.CAINIAO -> CainiaoDeliveryService Service.DHL -> DhlDeliveryService Service.GLS -> GLSGlobalDeliveryService Service.UPS -> UPSDeliveryService @@ -123,6 +125,7 @@ enum class Status(val nameResource: Int) { InTransit(R.string.status_in_transit), InWarehouse(R.string.status_in_warehouse), Customs(R.string.status_customs), + CustomsSuccess(R.string.status_customs_cleared), OutForDelivery(R.string.status_out_for_delivery), DeliveryFailure(R.string.status_delivery_failure), Delivered(R.string.status_delivered), diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 1fc9f1d..6115a0a 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -51,7 +51,8 @@ Volitelné. S poštovním směrovacím číslem můžete získat přístup k více informacím, jako je poloha. Čeká na vyzvednutí Dorazilo na celnici - Doručeno + Celní odbavení + Doručeno Nepodařilo se doručit Na cestě Dorazilo na depo diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 5bbb40e..a7ab01f 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -58,7 +58,8 @@ Optional. Mit einer Postleitzahl könnten zusätzliche Informationen wie Standort angezeigt werden. Abholung ausstehend Beim Zoll eingetroffen - Zugestellt + Vom Zoll abgefertigt + Zugestellt Zustellung fehlgeschlagen Unterwegs Im Paketzentrum eingetroffen diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index ed522bb..22d15cb 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -52,7 +52,8 @@ Opcionális. További információ jelenhet meg az irányítószám megadásával, például a címzett címe. Átvételre vár Vámkezelés alatt - Kiszállítva + Vámkezelés befejezve + Kiszállítva Sikertelen kiszállítás Úton Megérkezett a depóba diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 1e36323..284ca73 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -58,7 +58,8 @@ 任意の設定です。郵便番号を入力すると、場所などの追加情報にアクセスできる場合があります。 ピックアップ待ち 税関に到着 - 配達済み + 通関済み + 配達済み 配達に失敗 輸送中 倉庫に到着 diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 51dcf2a..7c60591 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -58,7 +58,8 @@ Opcjonalne. Możesz uzyskać dostęp do dodatkowych informacji, takich jak lokalizacja, z kodem pocztowym. Oczekiwanie na odbiór Dotarła do odprawy celnej - Dostarczona + Odprawa celna zakończona + Dostarczona Nie udało się dostarczyć W tranzycie Dotarła do magazynu diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 1f53372..478d519 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -57,7 +57,8 @@ Valfritt. Du kan kanske få tillgång till extra information, såsom läge, med ett postnummer. Väntar på upphämtning Anlänt till tullen - Levererat + Tullklarering slutförd + Levererat Leveransen misslyckades I transitering Anlänt till lagret diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 53ec094..990f853 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -47,7 +47,8 @@ เลือกที่จะไม่ใส่ได้ แต่คุณอาจจะเห็นข้อมูลเพิ่มเติม เช่น ตำแหน่ง เมื่อคุณระบุรหัสไปรษณีย์ กำลังรอบริษัทขนส่งรับพัสดุ พัสดุถึงศุลกากร - การนำส่งพัสดุสำเร็จ + ผ่านพิธีการศุลกากรแล้ว + การนำส่งพัสดุสำเร็จ การนำส่งพัสดุล้มเหลว พัสดุอยู่ระหว่างการขนส่ง พัสดุถึงคลังสินค้า diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 898743f..cd12efe 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -56,7 +56,8 @@ İsteğe bağlı. Posta kodu ile konum gibi ek bilgilere erişebilirsiniz. Teslim alınmayı bekliyor Gümrüğe ulaştı - Teslim edildi + Gümrükten geçti + Teslim edildi Teslim edilemedi Yolda Depoya ulaştı diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index eec80f2..efa8ff0 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -56,7 +56,8 @@ Додатково. Ми мложете отримати більше інформації, таку як розташування, за допомогою поштового індексу. Очікує одержання Прибула на митницю - Доставлена + Митне оформлення завершено + Доставлена Невдала доставка В дорозі Прибула на склад diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c108898..1c9a741 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -39,6 +39,7 @@ Save An Post Belpost + Cainiao DHL DPD UK eKart @@ -69,6 +70,7 @@ Optional. You may be able to access extra information, such as location, with a postal code. Awaiting pickup Arrived at customs + Cleared customs Delivered Failed to deliver In transit From 3ccb701c1761c7ba51fd62cdd8ddc277b0ebbced Mon Sep 17 00:00:00 2001 From: Sam J <47988070+sam-jeffery@users.noreply.github.com> Date: Sat, 31 May 2025 18:46:26 +0100 Subject: [PATCH 2/3] Run formatting and sort strings --- .../api/CainiaoDeliveryService.kt | 29 +++++++++++-------- app/src/main/res/values-cs/strings.xml | 4 +-- app/src/main/res/values-de/strings.xml | 4 +-- app/src/main/res/values-hu/strings.xml | 4 +-- app/src/main/res/values-ja/strings.xml | 4 +-- app/src/main/res/values-pl/strings.xml | 4 +-- app/src/main/res/values-sv/strings.xml | 4 +-- app/src/main/res/values-th/strings.xml | 4 +-- app/src/main/res/values-tr/strings.xml | 4 +-- app/src/main/res/values-uk/strings.xml | 4 +-- 10 files changed, 35 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt b/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt index fb55cc8..ac7f237 100644 --- a/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt +++ b/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt @@ -2,14 +2,14 @@ package dev.itsvic.parceltracker.api import com.squareup.moshi.JsonClass import dev.itsvic.parceltracker.R -import retrofit2.Retrofit -import retrofit2.converter.moshi.MoshiConverterFactory -import retrofit2.http.GET -import retrofit2.http.Query import java.time.Instant import java.time.LocalDateTime import java.time.ZoneId import java.util.Locale +import retrofit2.Retrofit +import retrofit2.converter.moshi.MoshiConverterFactory +import retrofit2.http.GET +import retrofit2.http.Query object CainiaoDeliveryService : DeliveryService { override val nameResource: Int = R.string.service_cainiao @@ -23,7 +23,9 @@ object CainiaoDeliveryService : DeliveryService { val parcelResp = service.getParcel(trackingID, "$language-$country", "$language-$country") - if (!parcelResp.success || parcelResp.module.isEmpty() || parcelResp.module.first().detailList.isEmpty()) { + if (!parcelResp.success || + parcelResp.module.isEmpty() || + parcelResp.module.first().detailList.isEmpty()) { throw ParcelNonExistentException() } @@ -34,9 +36,10 @@ object CainiaoDeliveryService : DeliveryService { ParcelHistoryItem( it.standerdDesc, // Sometimes new parcels have no timezone info, so default to origin country (china) - LocalDateTime.ofInstant(Instant.ofEpochMilli(it.time), ZoneId.of(if (it.timeZone.isBlank()) "GMT+8" else it.timeZone)), - "" - ) + LocalDateTime.ofInstant( + Instant.ofEpochMilli(it.time), + ZoneId.of(if (it.timeZone.isBlank()) "GMT+8" else it.timeZone)), + "") } // Based on the few tracking numbers I have, there may be more @@ -64,9 +67,7 @@ object CainiaoDeliveryService : DeliveryService { "GTMS_DO_DEPART" -> Status.OutForDelivery "GTMS_STATION_OUT" -> Status.InTransit "GTMS_SIGNED" -> Status.Delivered - else -> - logUnknownStatus( - "Cainiao", parcel.detailList.first().actionCode) + else -> logUnknownStatus("Cainiao", parcel.detailList.first().actionCode) } return Parcel(trackingID, history, status) @@ -83,7 +84,11 @@ object CainiaoDeliveryService : DeliveryService { private interface API { @GET("detail.json") - suspend fun getParcel(@Query("mailNos") trackingID: String, @Query("lang") lang: String, @Query("language") language: String): ParcelResponse + suspend fun getParcel( + @Query("mailNos") trackingID: String, + @Query("lang") lang: String, + @Query("language") language: String + ): ParcelResponse } @JsonClass(generateAdapter = true) diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 6115a0a..666ec55 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -51,8 +51,8 @@ Volitelné. S poštovním směrovacím číslem můžete získat přístup k více informacím, jako je poloha. Čeká na vyzvednutí Dorazilo na celnici - Celní odbavení - Doručeno + Celní odbavení + Doručeno Nepodařilo se doručit Na cestě Dorazilo na depo diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index a7ab01f..56d766a 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -58,8 +58,8 @@ Optional. Mit einer Postleitzahl könnten zusätzliche Informationen wie Standort angezeigt werden. Abholung ausstehend Beim Zoll eingetroffen - Vom Zoll abgefertigt - Zugestellt + Vom Zoll abgefertigt + Zugestellt Zustellung fehlgeschlagen Unterwegs Im Paketzentrum eingetroffen diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 22d15cb..206a034 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -52,8 +52,8 @@ Opcionális. További információ jelenhet meg az irányítószám megadásával, például a címzett címe. Átvételre vár Vámkezelés alatt - Vámkezelés befejezve - Kiszállítva + Vámkezelés befejezve + Kiszállítva Sikertelen kiszállítás Úton Megérkezett a depóba diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 284ca73..c4146a4 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -58,8 +58,8 @@ 任意の設定です。郵便番号を入力すると、場所などの追加情報にアクセスできる場合があります。 ピックアップ待ち 税関に到着 - 通関済み - 配達済み + 通関済み + 配達済み 配達に失敗 輸送中 倉庫に到着 diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 7c60591..8ede860 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -58,8 +58,8 @@ Opcjonalne. Możesz uzyskać dostęp do dodatkowych informacji, takich jak lokalizacja, z kodem pocztowym. Oczekiwanie na odbiór Dotarła do odprawy celnej - Odprawa celna zakończona - Dostarczona + Odprawa celna zakończona + Dostarczona Nie udało się dostarczyć W tranzycie Dotarła do magazynu diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 478d519..7d4d4a0 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -57,8 +57,8 @@ Valfritt. Du kan kanske få tillgång till extra information, såsom läge, med ett postnummer. Väntar på upphämtning Anlänt till tullen - Tullklarering slutförd - Levererat + Tullklarering slutförd + Levererat Leveransen misslyckades I transitering Anlänt till lagret diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 990f853..8888227 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -47,8 +47,8 @@ เลือกที่จะไม่ใส่ได้ แต่คุณอาจจะเห็นข้อมูลเพิ่มเติม เช่น ตำแหน่ง เมื่อคุณระบุรหัสไปรษณีย์ กำลังรอบริษัทขนส่งรับพัสดุ พัสดุถึงศุลกากร - ผ่านพิธีการศุลกากรแล้ว - การนำส่งพัสดุสำเร็จ + ผ่านพิธีการศุลกากรแล้ว + การนำส่งพัสดุสำเร็จ การนำส่งพัสดุล้มเหลว พัสดุอยู่ระหว่างการขนส่ง พัสดุถึงคลังสินค้า diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index cd12efe..ab96fa1 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -56,8 +56,8 @@ İsteğe bağlı. Posta kodu ile konum gibi ek bilgilere erişebilirsiniz. Teslim alınmayı bekliyor Gümrüğe ulaştı - Gümrükten geçti - Teslim edildi + Gümrükten geçti + Teslim edildi Teslim edilemedi Yolda Depoya ulaştı diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index efa8ff0..e54ca18 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -56,8 +56,8 @@ Додатково. Ми мложете отримати більше інформації, таку як розташування, за допомогою поштового індексу. Очікує одержання Прибула на митницю - Митне оформлення завершено - Доставлена + Митне оформлення завершено + Доставлена Невдала доставка В дорозі Прибула на склад From 5f5dca054b08e71590fe3e3c3eac0670044eac08 Mon Sep 17 00:00:00 2001 From: Sam J <47988070+sam-jeffery@users.noreply.github.com> Date: Sat, 31 May 2025 21:15:24 +0100 Subject: [PATCH 3/3] Add tracking status for failed delivery --- .../java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt b/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt index ac7f237..41d42ab 100644 --- a/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt +++ b/app/src/main/java/dev/itsvic/parceltracker/api/CainiaoDeliveryService.kt @@ -62,11 +62,13 @@ object CainiaoDeliveryService : DeliveryService { "CC_HO_OUT_SUCCESS" -> Status.InTransit "CC_IM_START" -> Status.Customs "CC_IM_SUCCESS" -> Status.CustomsSuccess + "TD_TRANSWH_OUTBOUND" -> Status.InTransit "GTMS_ACCEPT" -> Status.InTransit "GTMS_DO_ARRIVE" -> Status.InWarehouse "GTMS_DO_DEPART" -> Status.OutForDelivery "GTMS_STATION_OUT" -> Status.InTransit "GTMS_SIGNED" -> Status.Delivered + "GTMS_DEL_FAILURE" -> Status.DeliveryFailure else -> logUnknownStatus("Cainiao", parcel.detailList.first().actionCode) }