Merge pull request #7 from mgifos/gc-update-6

Gc login update #6
master
Nikola Petkov 8 years ago committed by GitHub
commit 67d103c39f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      build.sbt
  2. 3
      project/plugins.sbt
  3. 54
      src/main/scala/com.github.mgifos.workouts/GarminConnect.scala
  4. 2
      src/test/resources/ultra-80k-runnersworld.csv
  5. 2
      version.sbt

@ -1,6 +1,7 @@
name := "quick-plan" import com.typesafe.sbt.packager.SettingsHelper._
import ReleaseTransformations._
version := "0.1" name := "quick-plan"
lazy val root = (project in file(".")).enablePlugins( lazy val root = (project in file(".")).enablePlugins(
JavaAppPackaging, JavaAppPackaging,
@ -19,4 +20,19 @@ libraryDependencies ++= Seq(
"com.typesafe.play" %% "play-json" % "2.6.9", "com.typesafe.play" %% "play-json" % "2.6.9",
"com.typesafe.scala-logging" %% "scala-logging" % "3.7.2", "com.typesafe.scala-logging" %% "scala-logging" % "3.7.2",
"org.scalatest" %% "scalatest" % "3.0.5" % "test" "org.scalatest" %% "scalatest" % "3.0.5" % "test"
) )
releaseProcess := Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest,
setReleaseVersion,
commitReleaseVersion,
tagRelease,
setNextVersion,
commitNextVersion,
pushChanges
)
makeDeploymentSettings(Universal, packageBin in Universal, "zip")

@ -1,3 +1,4 @@
addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.8")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.3")
addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2") addSbtPlugin("org.scalariform" % "sbt-scalariform" % "1.8.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.3.3")

@ -30,7 +30,7 @@ case class GarminWorkout(name: String, id: Long)
class GarminConnect(email: String, password: String)(implicit system: ActorSystem, executionContext: ExecutionContext, mat: Materializer) { class GarminConnect(email: String, password: String)(implicit system: ActorSystem, executionContext: ExecutionContext, mat: Materializer) {
case class Session(username: String, headers: Seq[HttpHeader]) case class Session(headers: Seq[HttpHeader])
case class Login(forceNewSession: Boolean) case class Login(forceNewSession: Boolean)
@ -206,9 +206,10 @@ class GarminConnect(email: String, password: String)(implicit system: ActorSyste
def extractCookies(res: HttpResponse) = res.headers.collect { case x: `Set-Cookie` => x.cookie }.map(c => Cookie(c.name, c.value)) def extractCookies(res: HttpResponse) = res.headers.collect { case x: `Set-Cookie` => x.cookie }.map(c => Cookie(c.name, c.value))
def redirectionLoop(count: Int, url: String, acc: Seq[Cookie]): Future[Seq[Cookie]] = { def redirectionLoop(count: Int, url: String, acc: Seq[Cookie]): Future[Seq[Cookie]] = {
Http().singleRequest { val req = HttpRequest(uri = Uri(url)).withHeaders(acc)
HttpRequest(uri = Uri(url)).withHeaders(acc) log.debug(s"Login redirection no $count with req: $req")
}.withoutBody.flatMap { res => Http().singleRequest(req).withoutBody.flatMap { res =>
log.debug(s"Res: $res")
val cookies = extractCookies(res) val cookies = extractCookies(res)
res.headers.find(_.name() == "Location") match { res.headers.find(_.name() == "Location") match {
case Some(header) => case Some(header) =>
@ -226,10 +227,33 @@ class GarminConnect(email: String, password: String)(implicit system: ActorSyste
} }
val params = Map( val params = Map(
"service" -> "https://connect.garmin.com/post-auth/login",
"clientId" -> "GarminConnect", "clientId" -> "GarminConnect",
//"connectLegalTerms" -> "true",
"consumeServiceTicket" -> "false",
//"createAccountShown" -> "true",
//"cssUrl" -> "https://static.garmincdn.com/com.garmin.connect/ui/css/gauth-custom-v1.2-min.css",
//"displayNameShown" -> "false",
//"embedWidget" -> "false",
"gauthHost" -> "https://sso.garmin.com/sso", "gauthHost" -> "https://sso.garmin.com/sso",
"consumeServiceTicket" -> "false") //"generateExtraServiceTicket" -> "false",
//"generateNoServiceTicket" -> "false",
//"globalOptInChecked" -> "false",
//"globalOptInShown" -> "true",
//"id" -> "gauth-widget",
//"initialFocus" -> "true",
//"locale" -> "en_US",
//"locationPromptShown" -> "true",
//"mobile" -> "false",
//"openCreateAccount" -> "false",
//"privacyStatementUrl" -> "//connect.garmin.com/en-US/privacy/",
//"redirectAfterAccountCreationUrl" -> "https://connect.garmin.com/modern/",
//"redirectAfterAccountLoginUrl" -> "https://connect.garmin.com/modern/",
//"rememberMeChecked" -> "false",
//"rememberMeShown" -> "true",
"service" -> "https://connect.garmin.com/modern",
//"source" -> "https://connect.garmin.com/en-US/signin",
//"webhost" -> "https://connect.garmin.com"
)
for { for {
res1 <- Http().singleRequest(HttpRequest(uri = Uri("https://sso.garmin.com/sso/login").withQuery(Query(params)))).withoutBody res1 <- Http().singleRequest(HttpRequest(uri = Uri("https://sso.garmin.com/sso/login").withQuery(Query(params)))).withoutBody
res2 <- Http().singleRequest( res2 <- Http().singleRequest(
@ -239,21 +263,9 @@ class GarminConnect(email: String, password: String)(implicit system: ActorSyste
entity = FormData(Map( entity = FormData(Map(
"username" -> email, "username" -> email,
"password" -> password, "password" -> password,
"_eventId" -> "submit", "embed" -> "false")).toEntity).withHeaders(extractCookies(res1))).withoutBody
"embed" -> "true")).toEntity).withHeaders(extractCookies(res1))).withoutBody sessionCookies <- redirectionLoop(0, "https://connect.garmin.com/modern", extractCookies(res2))
sessionCookies <- redirectionLoop(0, "https://connect.garmin.com/post-auth/login", extractCookies(res2)) } yield Session(sessionCookies)
username <- getUsername(sessionCookies)
} yield Session(username, sessionCookies)
}
private def getUsername(sessionCookies: Seq[HttpHeader]): Future[String] = {
val req = HttpRequest(GET, Uri("https://connect.garmin.com/user/username")).withHeaders(sessionCookies)
Http().singleRequest(req).flatMap { res =>
if (res.status != StatusCodes.OK) throw new Error("Login failed!")
res.body.map { json =>
(Json.parse(json) \ "username").as[String]
}
}
} }
} }
} }

@ -86,7 +86,7 @@ WEEK,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday,Estimated km,,Dura
13,,"15k, 6x1.6k @TMP",8k jog,"15k, middle 5k @MP",,4h run,5h run,128.0,,3:00:00,30.0,18.6 13,,"15k, 6x1.6k @TMP",8k jog,"15k, middle 5k @MP",,4h run,5h run,128.0,,3:00:00,30.0,18.6
14,,"workout: 15k, 4x1.6k @TMP 14,,"workout: 15k, 4x1.6k @TMP
- warmup: 3km @z2 - warmup: 3km @z2
- repeat: 2 - repeat: 4
- run: 1600m @ 5:00-4:30 - run: 1600m @ 5:00-4:30
- recover: 1400m @z2 - recover: 1400m @z2
- run: 1km @z2 - run: 1km @z2

1 WEEK Monday Tuesday Wednesday Thursday Friday Saturday Sunday Estimated km Duration Avg km Miles
86
87
88
89
90
91
92

@ -1 +1 @@
version in ThisBuild := "0.1-SNAPSHOT" version in ThisBuild := "0.3-SNAPSHOT"

Loading…
Cancel
Save