return price on api call, price hardcoded
This commit is contained in:
153
server.go
153
server.go
@@ -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))
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user