From 745c41eb61391f87c21eae659934a74a46556b7f Mon Sep 17 00:00:00 2001 From: Isaiah W Date: Tue, 8 Apr 2025 21:37:55 -0500 Subject: [PATCH 1/7] update from codeberg repo --- .idea/discord.xml | 14 +++++ .../parceltracker/api/USPSDeliveryService.kt | 61 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 3 files changed, 76 insertions(+) create mode 100644 .idea/discord.xml create mode 100644 app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..912db82 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt new file mode 100644 index 0000000..6bfb52d --- /dev/null +++ b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt @@ -0,0 +1,61 @@ +package dev.itsvic.parceltracker.api + +import dev.itsvic.parceltracker.R +import okhttp3.MediaType +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.coroutines.executeAsync +import android.util.Log +import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi +import org.json.JSONObject +import kotlinx.coroutines.ExperimentalCoroutinesApi +import retrofit2.Retrofit + +object USPSDeliveryService : DeliveryService { + override val nameResource: Int = R.string.service_usps + override val acceptsPostCode: Boolean = false + override val requiresPostCode: Boolean = false + + override suspend fun getParcel(trackingId: String, postCode: String?): Parcel { + + return Parcel( + trackingId, + "history", + "status", + "metadata" + ) + } + + private val retrofit = Retrofit.Builder().baseUrl("https://api.usps.com/").client(api_client) + .addConverterFactory(api_factory).build() + + @OptIn(ExperimentalCoroutinesApi::class) + private suspend fun getOauthToken(clientId: String, clientSecret: String): String { + // this is all coming from https://developers.usps.com/Oauth + val GRANT_TYPE = "authorization_code" + val TOKEN_URL = "https://apis.usps.com/oauth2/v3/token" + + // this should work trust me + val body = """{ + |"grant_type": "$GRANT_TYPE", + |"client_id": "$clientId", + |"client_secret": "$clientSecret"}""".trimMargin() + .toRequestBody("application/json".toMediaType()) + + val request = Request.Builder().post(body).url(TOKEN_URL).build() + + api_client.newCall(request).executeAsync().use { response -> + Log.d("USPS", "Got Response") + var jsonWebToken = "" + if (response.code == 200) { + jsonWebToken = JSONObject(response.body.string()).optString("access_token", "") + Log.d("USPS", "Got Oauth2 token! $jsonWebToken") + // TODO: verify access token with provided public key + // if the USPS gets hacked we may have bigger problems on our hands than inaccurate package tracking + } else Log.d("USPS", "Couldn't get Oauth2 token ): response code was ${response.code}") + return jsonWebToken + } + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 32aa6f3..973ed92 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,4 +84,5 @@ API keys Ukrposhta GLS Hungary + USPS From dd5d4c890f8a0e2b61125db117a773758b069dfa Mon Sep 17 00:00:00 2001 From: Isaiah W Date: Tue, 8 Apr 2025 21:52:27 -0500 Subject: [PATCH 2/7] add tracking scope --- .../itsvic/parceltracker/api/USPSDeliveryService.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt index 6bfb52d..a6b607e 100644 --- a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt +++ b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi import org.json.JSONObject import kotlinx.coroutines.ExperimentalCoroutinesApi import retrofit2.Retrofit +import retrofit2.http.Path object USPSDeliveryService : DeliveryService { override val nameResource: Int = R.string.service_usps @@ -31,16 +32,28 @@ object USPSDeliveryService : DeliveryService { private val retrofit = Retrofit.Builder().baseUrl("https://api.usps.com/").client(api_client) .addConverterFactory(api_factory).build() + private val service = retrofit.create(API::class.java) + + private interface API { + @GET("tracking") + suspend fun getStatus( + @Path("trackingId") trackingId: String, + + ) + } + @OptIn(ExperimentalCoroutinesApi::class) private suspend fun getOauthToken(clientId: String, clientSecret: String): String { // this is all coming from https://developers.usps.com/Oauth val GRANT_TYPE = "authorization_code" + val SCOPES = listOf("tracking") val TOKEN_URL = "https://apis.usps.com/oauth2/v3/token" // this should work trust me val body = """{ |"grant_type": "$GRANT_TYPE", |"client_id": "$clientId", + |"scope": "${SCOPES.joinToString(" ")}" |"client_secret": "$clientSecret"}""".trimMargin() .toRequestBody("application/json".toMediaType()) From 695a13cfc119732562d442bebfbc2ce27dba6e18 Mon Sep 17 00:00:00 2001 From: Isaiah W Date: Tue, 8 Apr 2025 21:53:29 -0500 Subject: [PATCH 3/7] oopsie (: --- .idea/discord.xml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .idea/discord.xml diff --git a/.idea/discord.xml b/.idea/discord.xml deleted file mode 100644 index 912db82..0000000 --- a/.idea/discord.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - \ No newline at end of file From 5d0887f4722c0b7511eeeeba2dcb1dc68cca1b1b Mon Sep 17 00:00:00 2001 From: Isaiah W Date: Wed, 9 Apr 2025 17:01:56 -0500 Subject: [PATCH 4/7] checkpoint --- .../parceltracker/api/USPSDeliveryService.kt | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt index a6b607e..3566138 100644 --- a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt +++ b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt @@ -8,11 +8,17 @@ import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.coroutines.executeAsync import android.util.Log +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi import org.json.JSONObject import kotlinx.coroutines.ExperimentalCoroutinesApi import retrofit2.Retrofit +import retrofit2.http.Body import retrofit2.http.Path +import retrofit2.http.GET +import retrofit2.http.Header +import retrofit2.http.POST object USPSDeliveryService : DeliveryService { override val nameResource: Int = R.string.service_usps @@ -35,27 +41,39 @@ object USPSDeliveryService : DeliveryService { private val service = retrofit.create(API::class.java) private interface API { - @GET("tracking") + @POST("oauth2/v3/token") + suspend fun getOauthToken( + @Body data: GetOauthToken + ): OauthTokenResponse + + @GET("tracking/v3/tracking") suspend fun getStatus( @Path("trackingId") trackingId: String, - + @Header("Authorization") authorization: String ) } + @JsonClass(generateAdapter = true) + internal data class GetOauthToken( + // from https://developers.usps.com/Oauth + val clientId: String, + val clientSecret: String, + val grantType: String = "authorization_code", + val scopes: List = listOf("tracking"), + val tokenUrl: String = "https://apis.usps.com/oauth2/v3/token", + ) + + @JsonClass(generateAdapter = true) + internal data class OauthTokenResponse( + + ) + +/* @OptIn(ExperimentalCoroutinesApi::class) private suspend fun getOauthToken(clientId: String, clientSecret: String): String { - // this is all coming from https://developers.usps.com/Oauth - val GRANT_TYPE = "authorization_code" - val SCOPES = listOf("tracking") - val TOKEN_URL = "https://apis.usps.com/oauth2/v3/token" // this should work trust me - val body = """{ - |"grant_type": "$GRANT_TYPE", - |"client_id": "$clientId", - |"scope": "${SCOPES.joinToString(" ")}" - |"client_secret": "$clientSecret"}""".trimMargin() - .toRequestBody("application/json".toMediaType()) + val tokenResp = service.getOauthToken() val request = Request.Builder().post(body).url(TOKEN_URL).build() @@ -70,5 +88,5 @@ object USPSDeliveryService : DeliveryService { } else Log.d("USPS", "Couldn't get Oauth2 token ): response code was ${response.code}") return jsonWebToken } - } + }*/ } From fe19d33af614fde2893b6dd6e75d9164a79faf3b Mon Sep 17 00:00:00 2001 From: Isaiah W Date: Thu, 10 Apr 2025 21:35:06 -0500 Subject: [PATCH 5/7] split point --- .../parceltracker/api/USPSDeliveryService.kt | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt index 3566138..f3609d7 100644 --- a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt +++ b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt @@ -26,7 +26,7 @@ object USPSDeliveryService : DeliveryService { override val requiresPostCode: Boolean = false override suspend fun getParcel(trackingId: String, postCode: String?): Parcel { - + val oauthToken = return Parcel( trackingId, "history", @@ -50,7 +50,7 @@ object USPSDeliveryService : DeliveryService { suspend fun getStatus( @Path("trackingId") trackingId: String, @Header("Authorization") authorization: String - ) + ): StatusResponse } @JsonClass(generateAdapter = true) @@ -65,7 +65,20 @@ object USPSDeliveryService : DeliveryService { @JsonClass(generateAdapter = true) internal data class OauthTokenResponse( + val oauthToken: String + ) + @JsonClass(generateAdapter = true) + internal data class StatusResponse( + val expectedDeliveryDate: String, + val expectedDeliveryTime: String, + val guaranteedDeliveryDate: String, + val eventSummaries: List + ) + + @JsonClass(generateAdapter = true) + internal data class EventSummary( + val eventDescription: String ) /* From 234a04d430141ffb35e1681a6c51e10d69cf7a08 Mon Sep 17 00:00:00 2001 From: Isaiah W Date: Fri, 18 Apr 2025 16:34:55 -0500 Subject: [PATCH 6/7] try just adding the library --- app/build.gradle.kts | 1 + .../dev/itsvic/parceltracker/api/USPSDeliveryService.kt | 8 ++++---- gradle/libs.versions.toml | 2 ++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0c1ab86..196722d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -117,6 +117,7 @@ dependencies { implementation(libs.work.runtime.ktx) implementation(libs.kotlinx.coroutines.guava) implementation(libs.androidx.browser) + implementation(libs.skrapeit) ksp(libs.room.compiler) ksp(libs.moshi.kotlin.codegen) diff --git a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt index f3609d7..c652d70 100644 --- a/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt +++ b/app/src/main/java/dev/itsvic/parceltracker/api/USPSDeliveryService.kt @@ -19,6 +19,7 @@ import retrofit2.http.Path import retrofit2.http.GET import retrofit2.http.Header import retrofit2.http.POST +import java.time.LocalDateTime object USPSDeliveryService : DeliveryService { override val nameResource: Int = R.string.service_usps @@ -26,12 +27,11 @@ object USPSDeliveryService : DeliveryService { override val requiresPostCode: Boolean = false override suspend fun getParcel(trackingId: String, postCode: String?): Parcel { - val oauthToken = + // dummy stuff just so this compiles return Parcel( trackingId, - "history", - "status", - "metadata" + listOf(ParcelHistoryItem("", LocalDateTime.now(), "")), + Status.DeliveryFailure ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1a187b2..6402ddd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -17,6 +17,7 @@ kotlinxSerializationJson = "1.7.3" room = "2.6.1" datastorePreferences = "1.1.4" retrofit = "2.11.0" +skrapeit = "1.2.2" work = "2.10.0" kotlinxCoroutinesGuava = "1.10.1" material3 = "1.4.0-alpha11" @@ -53,6 +54,7 @@ room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" } androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastorePreferences" } retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } converter-moshi = { group = "com.squareup.retrofit2", name = "converter-moshi", version.ref = "retrofit" } +skrapeit = { module = "it.skrape:skrapeit", version.ref = "skrapeit" } work-runtime = { group = "androidx.work", name = "work-runtime", version.ref = "work" } work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" } kotlinx-coroutines-guava = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-guava", version.ref = "kotlinxCoroutinesGuava" } From fc157d1618ac78335d88c2eb0935314c7d594929 Mon Sep 17 00:00:00 2001 From: Isaiah W Date: Tue, 22 Apr 2025 22:23:24 -0500 Subject: [PATCH 7/7] no mo browser --- app/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 196722d..0c1ab86 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -117,7 +117,6 @@ dependencies { implementation(libs.work.runtime.ktx) implementation(libs.kotlinx.coroutines.guava) implementation(libs.androidx.browser) - implementation(libs.skrapeit) ksp(libs.room.compiler) ksp(libs.moshi.kotlin.codegen)