Skip to content

Commit

Permalink
fix: use new tgtg auth mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
hugo-vrijswijk committed Nov 25, 2024
1 parent 053aede commit 534a097
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 20 deletions.
3 changes: 1 addition & 2 deletions Auth.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ final class Auth(tgtg: TooGoodToGo, config: AuthConfig)(using log: Logger[IO]):
case None => log.info("TooGoodToGo email:") *> readLine
case Some(value) => value.pure[IO]
creds <- tgtg.getCredentials(Email(email))
_ <- log.info(show"user-id: ${creds.userId}") *>
log.info(show"refresh-token: ${creds.refreshToken}") *>
_ <- log.info(show"refresh-token: ${creds.refreshToken}") *>
log.info(show"Use these credentials as config (arguments or environment variables)")
yield ()

Expand Down
9 changes: 2 additions & 7 deletions Config.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type UserId = UserId.Type
object ApiToken extends NewType[String]
type ApiToken = ApiToken.Type

case class TgtgConfig(refreshToken: ApiToken, userId: UserId)
case class TgtgConfig(refreshToken: ApiToken)
case class RedisConfig(host: Host)
case class ServerConfig(
intervals: Option[NonEmptyList[FiniteDuration]],
Expand Down Expand Up @@ -73,7 +73,6 @@ object Config:

private given Argument[ApiToken] = Argument.from("token")(ApiToken(_).validNel)
private given Argument[Email] = Argument.from("email")(Email(_).validNel)
private given Argument[UserId] = Argument.from("user_id")(UserId(_).validNel)

private given Argument[CronExpr] = Argument.from("cron")(c =>
Cron
Expand All @@ -88,10 +87,6 @@ object Config:
Opts.option[ApiToken]("refresh-token", refreshHelp, "r") orElse
Opts.env[ApiToken]("TGTG_REFRESH_TOKEN", refreshHelp)

private val userIdHelp =
"User id for TooGoodToGo. Get it using the `tgtg auth` command."
val userId = Opts.option[UserId]("user-id", userIdHelp, "u") orElse Opts.env[UserId]("TGTG_USER_ID", userIdHelp)

private val gotifyHelp = "Gotify token for notifications (optional)."
private val gotifyToken =
Opts.option[ApiToken]("gotify-token", gotifyHelp) orElse Opts.env[ApiToken]("GOTIFY_TOKEN", gotifyHelp)
Expand Down Expand Up @@ -127,7 +122,7 @@ object Config:
val cronitor = (Opts.option[ApiToken]("cronitor-token", cronitorHelp) orElse
Opts.env[ApiToken]("CRONITOR_TOKEN", cronitorHelp)).orNone

val tgtg = (refreshToken, userId).mapN(TgtgConfig.apply)
val tgtg = refreshToken.map(TgtgConfig.apply)

private val redisHostHelp =
"Specify the Redis host for storing authentication tokens and notification history cache. If not set a local cache.json file will be used instead."
Expand Down
5 changes: 1 addition & 4 deletions Model.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import java.util.concurrent.TimeUnit
import scala.concurrent.duration.FiniteDuration

case class GetItemsRequest(
user_id: UserId,
origin: Origin = Origin(),
// radius: Int = 21,
page: Int = 1,
Expand Down Expand Up @@ -65,9 +64,7 @@ case class LoginResponse(state: String, polling_id: Option[String]) derives Deco
case class PollRequest(email: Email, request_polling_id: String, device_type: String = "ANDROID")
derives Encoder.AsObject

case class PollResponse(refresh_token: ApiToken, startup_data: StartupData) derives Decoder
case class StartupData(user: StartupUser) derives Decoder
case class StartupUser(user_id: UserId) derives Decoder
case class PollResponse(refresh_token: ApiToken) derives Decoder

given Codec[FiniteDuration] =
Codec.from(
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The application operates in two modes:
1. **One-shot Mode**: Checks for boxes once and then exits.
2. **Server Mode**: Continuously monitors for boxes at [configured schedules](#schedules) without exiting.

To run the application, provide your TooGoodToGo user ID and refresh token as environment variables (`TGTG_USER_ID` and `TGTG_REFRESH_TOKEN`) or as arguments (`--user-id` and `--refresh-token`) and a [notification provider](#notifications).
To run the application, provide your TooGoodToGo and refresh token as environment variables (`TGTG_REFRESH_TOKEN`) or as arguments (`--refresh-token`) and a [notification provider](#notifications).

For detailed information about available options, use the following command:

Expand Down
12 changes: 6 additions & 6 deletions TooGoodToGo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ import scala.concurrent.duration.*

class TooGoodToGo(http: Backend[IO])(using log: Logger[IO]):
private val baseUri = uri"https://apptoogoodtogo.com/api/"
private val refreshEndpoint = uri"${baseUri}auth/v3/token/refresh"
private val refreshEndpoint = uri"${baseUri}auth/v4/token/refresh"
private val itemsEndpoint = uri"${baseUri}item/v8/"
private val loginEndpoint = uri"${baseUri}auth/v3/authByEmail"
private val authPollEndpoint = uri"${baseUri}auth/v3/authByRequestPollingId"
private val loginEndpoint = uri"${baseUri}auth/v4/authByEmail"
private val authPollEndpoint = uri"${baseUri}auth/v4/authByRequestPollingId"

def getItems(cache: CacheService, config: TgtgConfig) =
def retrieveItems(access: AccessToken) =
headers()
.flatMap(baseHeaders =>
basicRequest
.body(GetItemsRequest(config.userId))
.body(GetItemsRequest())
.post(itemsEndpoint)
.cookies(access.cookies.toSeq*)
.headers(baseHeaders*)
Expand Down Expand Up @@ -62,7 +62,7 @@ class TooGoodToGo(http: Backend[IO])(using log: Logger[IO]):
)
)

cache.retrieveOrSet(action, CacheKey(s"tgtg-accessToken/${config.userId}"), a => a.ttl / 4 * 3)
cache.retrieveOrSet(action, CacheKey(s"tgtg/accessToken"), a => a.ttl / 4 * 3)
end getAccessToken

def getCredentials(email: Email): IO[TgtgConfig] =
Expand Down Expand Up @@ -107,7 +107,7 @@ class TooGoodToGo(http: Backend[IO])(using log: Logger[IO]):
pollRequest.flatMap {
case None => IO.sleep(pollSleep) >> poll(triesLeft - 1)
case Some(value) =>
TgtgConfig(refreshToken = value.refresh_token, userId = value.startup_data.user.user_id).pure
TgtgConfig(refreshToken = value.refresh_token).pure
}
log.info(
"Check your mailbox on PC to continue... (Mailbox on mobile won't work, if you have installed tgtg app.)\n"
Expand Down

0 comments on commit 534a097

Please sign in to comment.