Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,12 @@ Europe:
- Sameday Hungary
- Sameday Romania
- Belpost (BY)

Russia and CIS:
- 5post
- CDEK
- Russian Post (Почта России)

Asia:
- AliExpress Shipping (Cainiao)

Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package dev.itsvic.parceltracker.api

import com.squareup.moshi.JsonClass
import dev.itsvic.parceltracker.R
import retrofit2.Retrofit
import retrofit2.http.GET
import retrofit2.http.Query
import java.time.Instant
import java.time.LocalDateTime
import java.util.TimeZone

object CainiaoDeliveryService : DeliveryService {
override val nameResource: Int = R.string.service_cainiao

override suspend fun getParcel(trackingId: String, postalCode: String?): Parcel {
val resp = service.getParcelDetails(trackingId)
val parcel = resp.module.first()

if (parcel.detailList.isEmpty())
throw ParcelNonExistentException()

val history = parcel.detailList.map {
val (location, desc) = locationRegex.find(it.standerdDesc)!!.destructured

ParcelHistoryItem(
desc,
LocalDateTime.ofInstant(
Instant.ofEpochMilli(it.time),
TimeZone.getDefault().toZoneId()
),
if (location != "") location
else ""
)
}

val status = when (val statusCode = parcel.detailList.first().actionCode) {
"PU_PICKUP_SUCCESS" -> Status.Preadvice
"SC_INBOUND_SUCCESS" -> Status.InWarehouse
"CW_INBOUND" -> Status.InWarehouse
"SC_OUTBOUND_SUCCESS" -> Status.InTransit
"LH_HO_IN_SUCCESS" -> Status.InTransit
"???" -> Status.Delivered
else -> logUnknownStatus("Cainiao", statusCode)
}

return Parcel(trackingId, history, status)
}

private val retrofit = Retrofit.Builder()
.baseUrl("https://global.cainiao.com/global/")
.client(api_client)
.addConverterFactory(api_factory)
.build()

private val service = retrofit.create(API::class.java)

private interface API {
@GET("detail.json")
suspend fun getParcelDetails(
@Query("mailNos") trackingId: String
): ParcelResponse
}

private val locationRegex = Regex("(?:^\\[(.*)\\]\\s+)?(.*)\$")

@JsonClass(generateAdapter = true)
internal data class ParcelResponse(
val module: List<CainiaoParcel>
)

@JsonClass(generateAdapter = true)
internal data class CainiaoParcel(
val status: String,
val detailList: List<ParcelEvent>
)

@JsonClass(generateAdapter = true)
internal data class ParcelEvent(
val time: Long,
val standerdDesc: String, // I can't get over standErdDesc, send help
val actionCode: String
)
}
5 changes: 5 additions & 0 deletions app/src/main/java/dev/itsvic/parceltracker/api/Core.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ enum class Service {
SAMEDAY_HU,
SAMEDAY_RO,
BELPOST,

// Asia
CAINIAO,
}

val serviceOptions =
Expand All @@ -49,6 +52,8 @@ fun getDeliveryService(service: Service): DeliveryService? {
Service.SAMEDAY_RO -> SamedayRomaniaDeliveryService
Service.BELPOST -> BelpostDeliveryService

Service.CAINIAO -> CainiaoDeliveryService

Service.EXAMPLE -> ExampleDeliveryService
else -> null
}
Expand Down
58 changes: 58 additions & 0 deletions app/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<resources>

<string name="status_preadvice">Ещё не отправлено</string>
<string name="status_in_transit">В пути</string>
<string name="status_in_warehouse">Прибыло в сортировочный центр</string>
<string name="status_customs">Прибыло на таможню</string>
<string name="status_out_for_delivery">Отправлено</string>
<string name="status_delivery_failure">Не удалось доставить</string>
<string name="status_delivered">Доставлено</string>
<string name="status_awaiting_pickup">Ожидает получения</string>
<string name="status_picked_up">Получено</string>
<string name="status_unknown">Неизвестный код статуса</string>

<string name="service_undefined">Неопределено</string>
<string name="service_example">Пример Почты</string>
<string name="service_polish_post">Польская Почта</string>

<string name="add_a_parcel">Добавить посылку</string>
<string name="go_back">Назад</string>
<string name="parcel_name">Название</string>
<string name="tracking_id">Трек-номер</string>
<string name="delivery_service">Сервис доставки</string>
<string name="specify_a_postal_code">Указать индекс</string>
<string name="postal_code">Индекс</string>
<string name="add_parcel">Добавить посылку</string>
<string name="specify_postal_code_flavor_text">Некоторые посылки требуют почтовый индекс для получения полной информации.</string>

<string name="no_parcels_flavor">У вас нет посылок.</string>

<string name="current_status">Текущий статус</string>
<string name="parcel_history">История посылки</string>
<string name="human_name_error_text">Имя не должно быть пустым.</string>
<string name="tracking_id_error_text">Трек-номер не должен быть пустым.</string>
<string name="service_error_text">Вы должны выбрать сервис.</string>
<string name="postal_code_error_text">Индекс Имя не должен быть пустым.</string>
<string name="status_network_failure">Ошибка сети</string>
<string name="network_failure_detail">Ваше устройство может быть не подключено к Интернету, проблемы на стороне сервиса доставки, или вы ввели неверную информацию.</string>
<string name="settings">Настройки</string>
<string name="demo_mode_detail">Отображает образцы посылок для демонстрационных целей. Не влияет на пользовательские данные.</string>
<string name="parcel_doesnt_exist_detail">Эта посылка ещё не существует на серверах сервиса доставки. Убедитесь, что её данные верны.</string>
<string name="more_options">Больше опций</string>
<string name="delete">Удалить</string>
<string name="demo_mode">Демо-режим</string>
<string name="demo_mode_action_block">Действие не разрешено в демо-режиме.</string>
<string name="settings_experimental">Экспериментальные опции</string>
<string name="status_no_data">Нет данных</string>
<string name="channel_name">События посылки</string>
<string name="channel_description">Уведомления о текущем статусе посылки</string>
<string name="unmetered_only_setting">Обновлять только на безлимитных сетях</string>
<string name="unmetered_only_setting_detail">Если включено, то Parcel будет обновлять данные о посылках только на безлимитных сетях, как, например, ваша домашняя сеть Wi-Fi.</string>
<string name="edit_parcel">Изменить посылку</string>
<string name="save">Сохранить</string>
<string name="edit">Изменить</string>
<string name="service_dpd_uk">DPD Великобритания</string>
<string name="service_sameday_hu">Sameday Венгрия</string>
<string name="service_sameday_ro">Sameday Румыния</string>
<string name="service_sameday_bg">Sameday Болгария</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
<string name="save">Save</string>
<string name="edit">Edit</string>
<string name="service_dpd_uk">DPD UK</string>
<string name="service_cainiao" translatable="false">Cainiao (AliExpress)</string>
<string name="service_packeta" translatable="false">Packeta</string>
<string name="service_sameday_hu">Sameday Hungary</string>
<string name="service_sameday_ro">Sameday Romania</string>
Expand Down