HomeArtTechHackBlockchain
ONLINE ·
Index
/
Technology
/
Article

เขียน Go ดึงข้อมูลเกมส์ลดราคาของ Nintendo Switch ใช้งานเอง (ภาค 2)

Operator
Khomkrid Lerdprasert
Filed
November 24, 2020
Channel
Technology
Read
~1 min
เขียน Go ดึงข้อมูลเกมส์ลดราคาของ Nintendo Switch ใช้งานเอง (ภาค 2)

มาทำ Restful API กันต่อด้วย “github.com/gorilla/mux”

ต่อจากบทความ ที่แล้วนะครับ เขียน Go ดึงข้อมูลเกมส์ลดราคาของ Nintendo Switch ใช้งานเอง

รอบนี้เราจะมาลิส API กันก่อน ว่าจะทำอะไรกันต่อ

Latest Released Game List

https://ec.nintendo.com/api/US/en/search/new?count=30&offset=0

Downloading Game Ranking

https://ec.nintendo.com/api/JP/ja/search/ranking?count=10&offset=0

Game Details

https://ec.nintendo.com/JP/ja/titles/70010000012325

โดยจะเห็นว่ายังมีเหลือ API สำหรับดึง Latest Released Game List แต่ละประเทศ

เราจะมาทำการแก้ไข package discount กันก่อน เพื่อให้ function ที่ดึงเกมส์กับราคาของเรารับค่า parameter เข้าไปเป็น string country code แล้วให้ return ออกมาเป็น URL แทน

ดังนั้นเราจะสร้าง map string ขึ้นมาใช้งาน

var API = map[string]string{
"JP": "https://ec.nintendo.com/api/JP/ja/search/sales?count=30&offset=0",
"US": "https://ec.nintendo.com/api/US/en/search/sales?count=30&offset=0",
"GB": "https://ec.nintendo.com/api/GB/en/search/sales?count=10&offset=0",
"CA": "https://ec.nintendo.com/api/CA/en/search/sales?count=30&offset=0#Canada",
"AU": "https://ec.nintendo.com/api/AU/en/search/sales?count=10&offset=0#Australia",
"NZ": "https://ec.nintendo.com/api/NZ/en/search/sales?count=10&offset=0#NewZealand",
"CZ": "https://ec.nintendo.com/api/CZ/en/search/sales?count=10&offset=0#Czech",
"DK": "https://ec.nintendo.com/api/DK/en/search/sales?count=10&offset=0#Denmark",
"FI": "https://ec.nintendo.com/api/FI/en/search/sales?count=10&offset=0#Finland",
"GR": "https://ec.nintendo.com/api/GR/en/search/sales?count=10&offset=0#Greece",
"HU": "https://ec.nintendo.com/api/HU/en/search/sales?count=10&offset=0#Hungary",
"NO": "https://ec.nintendo.com/api/NO/en/search/sales?count=10&offset=0#Norway",
"PL": "https://ec.nintendo.com/api/PL/en/search/sales?count=10&offset=0#Poland",
"ZA": "https://ec.nintendo.com/api/ZA/en/search/sales?count=10&offset=0#SouthAfrica",
"SE": "https://ec.nintendo.com/api/SE/en/search/sales?count=10&offset=0#Sweden",
"DE": "https://ec.nintendo.com/api/DE/de/search/sales?count=10&offset=0",
"CH": "https://ec.nintendo.com/api/CH/de/search/sales?count=10&offset=0#Switzerland",
"FR": "https://ec.nintendo.com/api/FR/fr/search/sales?count=10&offset=0",
"BE-fr": "https://ec.nintendo.com/api/BE/fr/search/sales?count=10&offset=0#Belgium",
"IT": "https://ec.nintendo.com/api/IT/it/search/sales?count=10&offset=0",
"NL": "https://ec.nintendo.com/api/NL/nl/search/sales?count=10&offset=0",
"BE-nl": "https://ec.nintendo.com/api/BE/nl/search/sales?count=10&offset=0#Belgium",
"RU": "https://ec.nintendo.com/api/RU/ru/search/sales?count=30&offset=0",
"ES": "https://ec.nintendo.com/api/ES/es/search/sales?count=30&offset=0",
"MX": "https://ec.nintendo.com/api/MX/es/search/sales?count=30&offset=0#Mexico",
"CO": "https://ec.nintendo.com/api/CO/es/search/sales?count=10&offset=0#Columbia",
"AR": "https://ec.nintendo.com/api/AR/es/search/sales?count=10&offset=0#Argentina",
"CL": "https://ec.nintendo.com/api/CL/es/search/sales?count=10&offset=0#Chile",
"PE": "https://ec.nintendo.com/api/PE/es/search/sales?count=10&offset=0#Peru",
"PT": "https://ec.nintendo.com/api/PT/pt/search/sales?count=30&offset=0",
"BR": "https://ec.nintendo.com/api/BR/pt/search/sales?count=10&offset=0",
"HK": "https://ec.nintendo.com/api/HK/zh/search/sales?count=10&offset=0",
"KR": "https://ec.nintendo.com/api/KR/ko/search/sales?count=10&offset=0",
}

และเราจะลบ

const (
JP = iota
US
GB
.
.
.
)
var api = []string{
.
.
.
.
}

ออกไป และทำการแก้ไข function GetDiscountGameFrom ให้รับ Argument เข้ามาเป็น string แทน เพื่อนำไป map กับ API ที่เราสร้างขึ้นมาก่อนหน้า

func GetDiscountGameFrom(api string) []byte {

จากนั้นเราจะไปแก้ไข package main ของเรา ก็คือ deshop.go เพื่อให้ code เราเรียกใช้งาน gorilla mux เพื่อเอาไปทำเป็น Resful API โดยจะให้

path /discounts/{country} ไปดึงรายชื่อเกมส์แต่ละประเทศ

package main
import (
"fmt"
"net/http"
"github.com/aofiee/deshop/discount"
"github.com/gorilla/mux"
)
func main() {
handleRequest()
}
func handleRequest() {
r := mux.NewRouter()
r.HandleFunc("/discounts/{country}", gameList)
http.Handle("/", r)
http.ListenAndServe(":1234", nil)
}
func gameList(w http.ResponseWriter, r *http.Request) {
param := mux.Vars(r)
w.WriteHeader(http.StatusOK)
response := discount.GetDiscountGameFrom(discount.API[param["country"]])
fmt.Fprint(w, string(response))
}

และเราจะทำการ Implement เพื่อให้

path /new-release/{country} สำหรับแสดง New Release ของประเทศนั้นๆ

path /ranking/{country} Downloading Game Ranking

path/game/detail/{country}/{gameID} Game Details

ก่อนอื่นเราจะไป rename package discount เป็นชื่อ eshop แทน เพื่อที่จะใช้ type structure บางตัวแทนกันได้

และเราจะทำการสร้าง function GetNewReleaseFromCountry ขึ้นมา โดยจะรับ parameter เป็น country code ในรูปแบบ string

func GetNewReleaseFromCountry(country string) {
var lang = `en`
if country == `JP` {
lang = `jp`
}
newReleaseAPI := `https://ec.nintendo.com/api/` + country + `/` + lang + `/search/new?count=30&offset=0`
data, err := http.Get(newReleaseAPI)
if err != nil {
return
}
if data.StatusCode != 200 {
return
}
body, err := ioutil.ReadAll(data.Body)
data.Body.Close()
if err != nil {
return
}
contents := Contents{}
json.Unmarshal([]byte(body), &contents)
fmt.Println("", contents)
}

จะเห็นว่าในส่วนของการเตรียม Data structure ออกมาให้อยู่ในรูปแบบที่เราต้องการ มันซ้ำกับการดึง Game discount ดังนั้นเราจะมายุบส่วนที่มันซ้ำออกมาเป็นอีกหนึ่ง function ก็จะได้ว่า

func buildResult(contents Contents, country string) []byte {
gameList := []GameDetail{}
for _, game := range contents.Contents {
price := getPriceWithCountryAndGameID(country, game.ID)
FormalName := []rune(game.FormalName)
gameFetch := GameDetail{
ID: game.ID,
Name: string(FormalName),
Banner: game.HeroBannerURL,
Prices: price,
}
gameList = append(gameList, gameFetch)
}
result, _ := json.MarshalIndent(gameList, "", " ")
return result
}

จากนั้นก็ไปยุบ code ข้างใน GetDiscountGameFrom และ GetNewReleaseFromCountry ซะ

func GetDiscountGameFrom(api string) []byte {
data, err := http.Get(api)
if err != nil {
return nil
}
if data.StatusCode != 200 {
return nil
}
body, err := ioutil.ReadAll(data.Body)
data.Body.Close()
if err != nil {
return nil
}
contents := Contents{}
json.Unmarshal([]byte(body), &contents)
u, _ := url.Parse(api)
country := parserURL(u)
return buildResult(contents, country)
}
func GetNewReleaseFromCountry(country string) []byte {
var lang = `en`
if country == `JP` {
lang = `jp`
}
newReleaseAPI := `https://ec.nintendo.com/api/` + country + `/` + lang + `/search/new?count=30&offset=0`
data, err := http.Get(newReleaseAPI)
if err != nil {
return nil
}
if data.StatusCode != 200 {
return nil
}
body, err := ioutil.ReadAll(data.Body)
data.Body.Close()
if err != nil {
return nil
}
contents := Contents{}
json.Unmarshal([]byte(body), &contents)
return buildResult(contents, country)
}

หลังจากนั้นเราจะมี ทำ function เพื่อ ดึง ranking กัน หลังจากดู result ที่ได้ และ code ที่เขียน ทำให้เห็นว่า new release, discount, ranking ใช้ api ร่วมกันได้หมดเลย งั้นเราจะยุบทั้งหมด มาใช้ตัวเดียวกัน โดยเราจะสร้าง function ขึ้นมาใหม่ชื่อว่า GetEndpoint โดยจะรับ parameter เป็น country string, service string และ return กลับไปเป็น []byte

//GetEndpoint func
func GetEndpoint(country string, service string) []byte {
var lang = `en`
if country == `JP` {
lang = `ja`
}
var path string
switch service {
case `sale`:
path = `sales?count=30&offset=0`
break
case `new`:
path = `new?count=30&offset=0`
break
case `ranking`:
path = `ranking?count=10&offset=0`
break
}
endpoint := `https://ec.nintendo.com/api/` + country + `/` + lang + `/search/` + path
return getEndpointData(country, endpoint)
}
//getEndpointData func
func getEndpointData(country string, endpoint string) []byte {
data, err := http.Get(endpoint)
if err != nil {
return nil
}
if data.StatusCode != 200 {
return nil
}
body, err := ioutil.ReadAll(data.Body)
data.Body.Close()
if err != nil {
return nil
}
contents := Contents{}
json.Unmarshal([]byte(body), &contents)
return buildResult(contents, country)
}

และทำการลบ  GetDiscountGameFrom และ GetNewReleaseFromCountry รวมทั้ง map string ทิ้งไปได้เลย ไม่เอามาใช้แล้ว

และทำการแก้ไข deshop.go ให้เรียกจาก function เดียว

package main
import (
"fmt"
"net/http"
"github.com/aofiee/deshop/eshop"
"github.com/gorilla/mux"
)
func main() {
handleRequest()
}
func handleRequest() {
r := mux.NewRouter()
r.HandleFunc("/discounts/{country}", gameList)
r.HandleFunc("/new-release/{country}", newRelease)
r.HandleFunc("/ranking/{country}", newRelease)
http.Handle("/", r)
http.ListenAndServe(":1234", nil)
}
func newRelease(w http.ResponseWriter, r *http.Request) {
param := mux.Vars(r)
w.WriteHeader(http.StatusOK)
response := eshop.GetEndpoint(param["country"], `new`)
fmt.Fprint(w, string(response))
}
func gameList(w http.ResponseWriter, r *http.Request) {
param := mux.Vars(r)
w.WriteHeader(http.StatusOK)
response := eshop.GetEndpoint(param["country"], `sale`)
fmt.Fprint(w, string(response))
}
func rankingList(w http.ResponseWriter, r *http.Request) {
param := mux.Vars(r)
w.WriteHeader(http.StatusOK)
response := eshop.GetEndpoint(param["country"], `ranking`)
fmt.Fprint(w, string(response))
}

Download Sourcode ได้ที่นี่

◎ Tags

##Go lang##Nintendo Switch
Khomkrid Lerdprasert
Operator

Khomkrid Lerdprasert

Technical Lead — building AI-powered platforms, omni-channel chat systems, and telemedicine solutions with Go, Next.js & clean architecture. 20+ years shipping software from crypto wallets to e-learning systems. Bangkok-based. Writes code late at night, brews beer on weekends.

GithubInstagram
Previous · transmission
เขียน Go ดึงข้อมูลเกมส์ลดราคาของ Nintendo Switch ใช้งานเอง
Next · transmission
เขียน Store Procedure เพื่อ Insert Random Coupon ลง Mysql
Metadata
Channel
Technology
Filed
November 24, 2020
Read
~1 min
Language
TH / EN
Transmit

Related

สร้าง Key pair เพื่อทำการ signing document signature ด้วย Go lang
Khomkrid Lerdprasert
March 13, 2024
1 min
aofiee.dev
signal / noise / code · craft
© 2019 – 2026, Khomkrid Lerdprasert.
All transmissions logged.
No newsletter. No profiling. Cookies require consent.
PGP · 7F3D 2024 A21E B584 · 0x7F3D
Channels
  • Art & Culture
  • Technology
  • Hack 101
  • Blockchain 101
  • Archive / All posts
— END OF TRANSMISSION —
// powered by curiosity, coffee, & wuxia
BKK · 13°45′N · 100°30′E