return price on api call, price hardcoded

This commit is contained in:
GotPPay
2018-04-24 22:47:50 +02:00
parent 8e34bbab63
commit 239ea7135f

153
server.go
View File

@@ -2,14 +2,13 @@ package main
import ( import (
"fmt" "fmt"
"github.com/PuerkitoBio/goquery"
"github.com/benbjohnson/phantomjs"
"log" "log"
"math"
"net/http" "net/http"
"strconv" "strconv"
"strings" "strings"
//"gopkg.in/headzoo/surf.v1"
"github.com/PuerkitoBio/goquery"
//"sourcegraph.com/sourcegraph/go-selenium"
"github.com/benbjohnson/phantomjs"
) )
const validNumberOfURLParams = 5 const validNumberOfURLParams = 5
@@ -18,6 +17,15 @@ const countParamIndex = 4
const validNumberOfSizeParams = 2 const validNumberOfSizeParams = 2
const maxExpectedNumberOfQuantities = 15 const maxExpectedNumberOfQuantities = 15
const numberOfTabsToSizeGroup = 12
const numberOfArrowDownToCustomSize = 4
const validMinWidth = 25.4
const validMaxWidth = 914.4
const validMinHeight = 25.4
const validMaxHeigh = 609.59
const epsilon = 0.1
const stickerMuleURL = "https://www.stickermule.com/uk/products/die-cut-stickers" const stickerMuleURL = "https://www.stickermule.com/uk/products/die-cut-stickers"
@@ -26,36 +34,39 @@ const (
invalidNumberOfParamsError = "Number of params not correct, expected /WIDTHxLENGTH/count" invalidNumberOfParamsError = "Number of params not correct, expected /WIDTHxLENGTH/count"
invalidNumberOfSizeParamError = "Size not correct, expected /WIDTHxLENGTH/count" invalidNumberOfSizeParamError = "Size not correct, expected /WIDTHxLENGTH/count"
invalidParamsType = "Params should be numbers" invalidParamsType = "Params should be numbers"
invalidParamsSize = "Params should be in range"
tooManyQuantities = "Too many quantities. Didn't expect this" errorSimulatingInput = "Error with simulating user input"
tooManyQuantities = "Too many quantities. Didn't expect this"
failedToGetPrice = "Failed to get price"
) )
var listOfValidQuantities []int16 var listOfValidQuantities []int16
var stickerMuleWebPage *phantomjs.WebPage var stickerMuleWebPage *phantomjs.WebPage
var stickerMuleWebPageDocument *goquery.Document var stickerMuleWebPageDocument *goquery.Document
func getListOfQuantities() error { func getListOfQuantities() error {
result := make([]int16, maxExpectedNumberOfQuantities) result := make([]int16, maxExpectedNumberOfQuantities)
resultCount := 0 resultCount := 0
wasError := false wasError := false
whichError := error(nil) whichError := error(nil)
stickerMuleWebPageDocument.Find("label.quantity").Each(func(_ int, s *goquery.Selection){ stickerMuleWebPageDocument.Find("label.quantity").Each(func(_ int, s *goquery.Selection) {
if wasError{ if wasError {
return return
} }
numberWithoutComma := strings.Replace(s.Text(), ",","",-1) numberWithoutComma := strings.Replace(s.Text(), ",", "", -1)
trimmedNumber := strings.TrimSpace(numberWithoutComma) trimmedNumber := strings.TrimSpace(numberWithoutComma)
if sizeInt64, err := strconv.ParseInt(trimmedNumber, 10, 16); err != nil {
if sizeInt64, err := strconv.ParseInt(trimmedNumber,10,16) ; err != nil {
wasError = true wasError = true
whichError = err whichError = err
}else{ } else {
result[resultCount] = int16(sizeInt64) result[resultCount] = int16(sizeInt64)
} }
resultCount+=1 resultCount += 1
if resultCount == 15 { if resultCount == 15 {
wasError = true wasError = true
whichError = fmt.Errorf(tooManyQuantities) whichError = fmt.Errorf(tooManyQuantities)
@@ -70,6 +81,80 @@ func getListOfQuantities() error {
return nil return nil
} }
func floatToString(number float64) string {
return strconv.FormatFloat(number, 'f', 1, 64)
}
func getStickerPrice(width, height float64, quantity int) (int, error) {
//simulate click on "Custom size radio button"
if _, err := stickerMuleWebPage.Evaluate("function(){document.getElementById('variant_77').click();}"); err != nil {
return 0, err
}
//set value for width
if _, err := stickerMuleWebPage.Evaluate("function(){document.getElementById('width').value = " + floatToString(width) + ";}"); err != nil {
return 0, err
}
//set value for height
if _, err := stickerMuleWebPage.Evaluate("function(){document.getElementById('height').value = " + floatToString(height) + ";}"); err != nil {
return 0, err
}
//check if input boxes accepted passed values
valuesFromInputBoxes, err := stickerMuleWebPage.Evaluate("function(){return {width: document.getElementById('width').value, height: document.getElementById('height').value};}")
if err != nil {
return 0, err
}
valuesMap, ok := valuesFromInputBoxes.(map[string]interface{})
if !ok {
return 0, fmt.Errorf(invalidParamsType)
}
redWidthString, ok := valuesMap["width"].(string)
if !ok {
return 0, fmt.Errorf(invalidParamsType)
}
redHeightString, ok := valuesMap["height"].(string)
if !ok {
return 0, fmt.Errorf(invalidParamsType)
}
widthValue, err := strconv.ParseFloat(redWidthString, 64)
if err != nil {
return 0, fmt.Errorf(invalidParamsType)
}
heightValue, err := strconv.ParseFloat(redHeightString, 64)
if err != nil {
return 0, fmt.Errorf(invalidParamsType)
}
if math.Abs(widthValue-width) > epsilon || math.Abs(heightValue-height) > epsilon {
return 0, fmt.Errorf(invalidParamsType)
}
//Now read price for selected quantity
priceValue, err := stickerMuleWebPage.Evaluate("function(){return {price: document.getElementById('price_200_id').innerHTML};}")
//TODO : price is empty because setting value for width and height doesn't fire event listener
//on input fields and prices are not loaded. Find another way to simulate user input
priceMap, ok := priceValue.(map[string]interface{})
if !ok {
return 0, fmt.Errorf(failedToGetPrice)
}
_, ok = priceMap["price"].(string)
if !ok {
return 0, fmt.Errorf(failedToGetPrice)
}
return 100, nil
}
func errorResponse(w http.ResponseWriter, errType string) { func errorResponse(w http.ResponseWriter, errType string) {
fmt.Fprintf(w, errType) fmt.Fprintf(w, errType)
} }
@@ -79,26 +164,34 @@ func diecutHandler(w http.ResponseWriter, r *http.Request) {
if size := strings.Split(params[sizeParamIndex], "x"); len(size) == validNumberOfSizeParams { if size := strings.Split(params[sizeParamIndex], "x"); len(size) == validNumberOfSizeParams {
count := params[countParamIndex] count := params[countParamIndex]
width, wOk := strconv.ParseInt(size[0], 10, 16) width, wOk := strconv.ParseFloat(size[0], 64)
height, hOk := strconv.ParseInt(size[1], 10, 16) height, hOk := strconv.ParseFloat(size[1], 64)
countNumber, cOk := strconv.ParseInt(count, 10, 16) countNumber, cOk := strconv.ParseInt(count, 10, 16)
countNumber16 := int16(countNumber) countNumber16 := int16(countNumber)
foundValidQuantity := false foundValidQuantity := false
for _, value := range(listOfValidQuantities){ for _, value := range listOfValidQuantities {
if value == countNumber16 { if value == countNumber16 {
foundValidQuantity = true foundValidQuantity = true
break break
} }
} }
if wOk != nil || hOk != nil || cOk != nil || !foundValidQuantity { validWidth := width >= validMinWidth && width <= validMaxWidth
validHeight := height >= validMinHeight && height <= validMaxHeigh
if wOk != nil || hOk != nil || cOk != nil || !foundValidQuantity || !validWidth || !validHeight {
errorResponse(w, invalidParamsType) errorResponse(w, invalidParamsType)
} else { } else {
fmt.Fprintf(w, "%dx%d | %d", width, height, countNumber) price, err := getStickerPrice(width, height, int(countNumber))
if err != nil {
errorResponse(w, failedToGetPrice)
} else {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, "{price:%d, currency: \"USD\"}", price)
}
} }
} else { } else {
@@ -113,14 +206,17 @@ func defaultHandler(w http.ResponseWriter, r *http.Request) {
errorResponse(w, invalidURL) errorResponse(w, invalidURL)
} }
func initWebPage() error{ func initWebPage() error {
p := phantomjs.DefaultProcess p := phantomjs.DefaultProcess
stickerMuleWebPage, err := p.CreateWebPage() localStickerMuleWebPage, err := p.CreateWebPage()
if err != nil { if err != nil {
return err return err
} }
//keep pointer to web page in global space, so page is not re-created every time API is called
stickerMuleWebPage = localStickerMuleWebPage
// Open a URL. // Open a URL.
if err := stickerMuleWebPage.Open(stickerMuleURL); err != nil { if err := stickerMuleWebPage.Open(stickerMuleURL); err != nil {
return err return err
@@ -131,7 +227,7 @@ func initWebPage() error{
return err return err
} }
stickerMuleWebPageDocument,err = goquery.NewDocumentFromReader(strings.NewReader(content)) stickerMuleWebPageDocument, err = goquery.NewDocumentFromReader(strings.NewReader(content))
if err != nil { if err != nil {
return err return err
} }
@@ -139,14 +235,14 @@ func initWebPage() error{
return nil return nil
} }
func closingCleanUp(){ func closingCleanUp() {
phantomjs.DefaultProcess.Close() phantomjs.DefaultProcess.Close()
stickerMuleWebPage.Close() stickerMuleWebPage.Close()
} }
func main() { func main() {
//init phantomJS //init phantomJS
if err:= phantomjs.DefaultProcess.Open(); err != nil { if err := phantomjs.DefaultProcess.Open(); err != nil {
fmt.Println("Error : ", err) fmt.Println("Error : ", err)
return return
} }
@@ -154,13 +250,13 @@ func main() {
defer closingCleanUp() defer closingCleanUp()
//init web page and document //init web page and document
if err:= initWebPage() ; err != nil { if err := initWebPage(); err != nil {
fmt.Println("Error : ", err) fmt.Println("Error : ", err)
return return
} }
//init valid values for stickers quantity //init valid values for stickers quantity
if err:= getListOfQuantities() ; err != nil { if err := getListOfQuantities(); err != nil {
fmt.Println("Error : ", err) fmt.Println("Error : ", err)
return return
} }
@@ -170,6 +266,5 @@ func main() {
fmt.Println("Server running on localhost:8080") fmt.Println("Server running on localhost:8080")
log.Fatal(http.ListenAndServe(":8080", nil)) log.Fatal(http.ListenAndServe(":8080", nil))
} }