Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: improve formatting and code quality tools #19

Merged
merged 1 commit into from
Aug 3, 2022
Merged
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
73 changes: 73 additions & 0 deletions .scalafix.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
rules = [
# Disable
# NoInfer
DisableSyntax # Reports an error for disabled features such as var or XML literals.
# RemoveUnused
LeakingImplicitClassVal # Adds 'private' to val parameters of implicit value classes
NoValInForComprehension # Removes deprecated val inside for-comprehension binders
# ProcedureSyntax # Replaces deprecated procedure syntax with explicit ': Unit ='
NoAutoTupling
# RewriteDeprecatedNames # Scalatest 3.1 migration

# Mark case classes as final
# https://nrinaudo.github.io/scala-best-practices/tricky_behaviours/final_case_classes.html
# MissingFinal
]

# https://nrinaudo.github.io/scala-best-practices/unsafe/
DisableSyntax {
noXml = true
noVars = true
noNulls = true
noReturns = true
noFinalize = true
noWhileLoops = true
noAsInstanceOf = true
noIsInstanceOf = true

# motivation https://github.com/sbt/zinc/issues/227
noFinalVal = true

noValPatterns = false
noUniversalEquality = false
noSemicolons = true
noImplicitObject = true

# https://nrinaudo.github.io/scala-best-practices/oop/abstract_fields_as_defs.html
# https://docs.scala-lang.org/tutorials/FAQ/initialization-order.html
noValInAbstract = true
}

Disable.symbols = [
# https://nrinaudo.github.io/scala-best-practices/adts/enumerations_as_adt.html
"scala.Enumeration"

# https://nrinaudo.github.io/scala-best-practices/partial_functions/

"scala.util.Either.LeftProjection.get"
"scala.util.Either.RightProjection.get"

# Wartremover.OptionPartial
"scala.Option.get"
"scala.Some.get"
"scala.None.get"

# Wartremover.TryPartial
"scala.util.Try.get"
"scala.util.Failure.get"
"scala.util.Success.get"
]

Disable.ifSynthetic = [
"scala.Predef.any2stringadd"
"scala.Any"
"scala.AnyVal"
]

NoInfer.disabledTypes = [
"scala.Any"
"scala.AnyVal"
"java.io.Serializable"
"scala.Serializable"
"scala.Product"
]
16 changes: 10 additions & 6 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
version = 2.6.3
# Only format files tracked by git and skip the python folder
version = 3.5.8
runner.dialect = scala3
# Only format files tracked by git
project.git = true
project.excludeFilters = [
"python/"
]
# Because our monitors are wide and names are verbose
maxColumn = 100
# Pretty alignment
Expand All @@ -30,7 +28,13 @@ assumeStandardLibraryStripMargin = true
# For consistency with the call-site: indent args by 2 spaces
continuationIndent.defnSite = 2
# Newlines before toplevel statements for readability
newlines.alwaysBeforeTopLevelStatements = true
newlines.topLevelStatements = [before]
# Keep short Scaladoc comments compact
docstrings.oneline = fold
docstrings.removeEmpty = true
# Wrap long comments if they overflow maxColumn
comments.wrap = trailing
comments.wrapStandaloneSlcAsSlc = true
# Basic syntactic rewrites
rewrite.rules = [
SortImports
Expand Down
6 changes: 5 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ scalaVersion := "3.1.3"

lazy val root = project in file(".")

libraryDependencies ++= Seq("com.typesafe.play" %% "play-ahc-ws" % "2.8.16")
semanticdbEnabled := true

libraryDependencies ++= Seq(
("com.typesafe.play" %% "play-ahc-ws" % "2.8.16").cross(CrossVersion.for3Use2_13)
)
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.10.1")
24 changes: 12 additions & 12 deletions src/main/scala/com/resy/BookReservationWorkflow.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ import scala.language.postfixOps
import scala.util.{Failure, Success, Try}

object BookReservationWorkflow {
implicit val testing = false
implicit val testing: Boolean = false

/**
* STEP 1: FIND RESERVATION (GET CONFIG ID)
/** STEP 1: FIND RESERVATION (GET CONFIG ID)
* @return
*/
private[this] def findReservation: Future[String] = {
Expand All @@ -31,8 +30,7 @@ object BookReservationWorkflow {
sendGetRequest(ResyApiMapKeys.FindReservation, findResQueryParams)
}

/**
* STEP 2: GET RESERVATION DETAILS (GET PAYMENT ID AND BOOK TOKEN)
/** STEP 2: GET RESERVATION DETAILS (GET PAYMENT ID AND BOOK TOKEN)
* @param configId
* @return
*/
Expand All @@ -47,22 +45,22 @@ object BookReservationWorkflow {
sendGetRequest(ResyApiMapKeys.ReservationDetails, findResQueryParams)
}

/**
* STEP 3: BOOK RESERVATION
/** STEP 3: BOOK RESERVATION
* @param resDetailsResp
* @return
*/
def bookReservation(resDetailsResp: String): Future[String] = {
val resDetails = Json.parse(resDetailsResp)
println(s"${DateTime.now} URL Response: $resDetailsResp")

//PaymentMethodId - Searching for this pattern - "payment_methods": [{"is_default": true, "provider_name": "braintree", "id": 123456, "display": "1234", "provider_id": 1}]
// PaymentMethodId - Searching for this pattern - "payment_methods": [{"is_default": true,
// "provider_name": "braintree", "id": 123456, "display": "1234", "provider_id": 1}]
val paymentMethodId =
(resDetails \ "user" \ "payment_methods" \ 0 \ "id").get.toString

println(s"${DateTime.now} Payment Method Id: $paymentMethodId")

//BookToken - Searching for this pattern - "book_token": {"value": "book_token_value"
// BookToken - Searching for this pattern - "book_token": {"value": "book_token_value"
val bookToken =
(resDetails \ "book_token" \ "value").get.toString
.stripPrefix("\"")
Expand All @@ -79,8 +77,8 @@ object BookReservationWorkflow {
sendPostRequest(ResyApiMapKeys.BookReservation, bookResQueryParams)
}

/**
* Same as Step 1 but does a retry. Blocks because the reservation can't proceed without an available reservation
/** Same as Step 1 but does a retry. Blocks because the reservation can't proceed without an
* available reservation
* @param endTime
* @return
*/
Expand All @@ -90,7 +88,9 @@ object BookReservationWorkflow {

println(s"${DateTime.now} URL Response: $findResResp")

//ConfigId - Searching for this pattern - "time_slot": "17:15:00", "badge": null, "service_type_id": 2, "colors": {"background": "2E6D81", "font": "FFFFFF"}, "template": null, "id": 123457
// ConfigId - Searching for this pattern - "time_slot": "17:15:00", "badge": null,
// "service_type_id": 2, "colors": {"background": "2E6D81", "font": "FFFFFF"}, "template": null,
// "id": 123457

val results = Try(
(Json.parse(findResResp) \ "results" \ "venues" \ 0 \ "slots").get
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/com/resy/ResyApiWrapper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.resy.BookingDetails._
import com.resy.ResyApiMapKeys.{BookReservation, FindReservation, ReservationDetails, UserDetails}
import org.joda.time.DateTime
import play.api.libs.ws.ahc.AhcWSClient
import play.api.libs.ws.WSBodyWritables.writeableOf_String

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/com/resy/ResyBookingBot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@ object ResyBookingBot {
println(
s"Sleeping for $hoursRemaining hours, $minutesRemaining minutes and $secondsRemaining seconds"
)

system.scheduler.scheduleOnce(millisUntilTomorrow millis)(bookReservationWorkflow)
}

private[this] def bookReservationWorkflow = {
println(s"Attempting to snipe reservation at ${DateTime.now}")

//Try to get configId of the time slot for 10 seconds
// Try to get configId of the time slot for 10 seconds
val findResResp = retryFindReservation(DateTime.now.plusSeconds(10).getMillis)

//Try to book the reservation
// Try to book the reservation
for {
resDetailsResp <- getReservationDetails(findResResp)
bookResResp <- bookReservation(resDetailsResp)
Expand Down