Skip to content

Instantly share code, notes, and snippets.

@xthezealot
Last active November 8, 2017 09:12
Show Gist options
  • Save xthezealot/1cb3cff4bfda78736e94f9fcaa18a1df to your computer and use it in GitHub Desktop.
Save xthezealot/1cb3cff4bfda78736e94f9fcaa18a1df to your computer and use it in GitHub Desktop.
iPhone X availability - BE
package main
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
)
const (
reserveSubdomain = "reserve-prime"
locale = "BE/fr_BE"
store = "R486"
product = "iPhoneX"
errNoAvailabilities = "État du stock indisponible"
)
var (
model *Model
cmdOpenUsed bool
)
// Model defines an iPhone model.
type Model struct {
Code string
Name string
}
var models = []*Model{
{"MQAD2ZD/A", "iPhone X 64 Go Argent"},
{"MQAC2ZD/A", "iPhone X 64 Go Gris sidéral"},
{"MQAG2ZD/A", "iPhone X 256 Go Argent"},
{"MQAF2ZD/A", "iPhone X 256 Go Gris sidéral"},
}
func main() {
fmt.Print(`
___ __ __ _ ____ __ _ __
/ | / /__ _____/ /____ (_) __ \/ /_ ____ ____ ___ | |/ /
/ /| | / / _ \/ ___/ __/ _ \ / / /_/ / __ \/ __ \/ __ \/ _ \ | /
/ ___ |/ / __/ / / /_/ __/ / / ____/ / / / /_/ / / / / __/ / |
/_/ |_/_/\___/_/ \__/\___/ /_/_/ /_/ /_/\____/_/ /_/\___/ /_/|_|
Uniquement pour l'Apple Store de Bruxelles.
Liste des modèles :
`)
for i, model := range models {
fmt.Printf("\t%2d — %s\n", i+1, model.Name)
}
fmt.Print("\n")
ModelChoice:
fmt.Printf("Veuillez sélectionner le modèle souhaité (nombre entre 1 et %d) : ", len(models))
modelChoice, err := bufio.NewReader(os.Stdin).ReadString('\n')
if err != nil {
goto ModelChoice
}
modelChoiceN, _ := strconv.Atoi(strings.TrimSpace(modelChoice))
if modelChoiceN < 1 || modelChoiceN > len(models) {
goto ModelChoice
}
model = models[modelChoiceN-1]
fmt.Printf("\nVérification du stock d'%s (%s) :\n", model.Name, model.Code)
for {
time.Sleep(2 * time.Second)
ok, err := isAvailable(model)
if err != nil {
log.Println("[ERREUR]", err)
continue
} else if !ok {
fmt.Print(strRequest)
continue
}
fmt.Print(strIsAvailable)
if !cmdOpenUsed {
if err = open("https://" + reserveSubdomain + ".apple.com/" + locale + "/reserve/" + product + "?channel=1&carrier=&store=" + url.QueryEscape(store) + "&partNumber=" + url.QueryEscape(model.Code)).Start(); err != nil {
log.Println("[ERREUR]", err)
}
cmdOpenUsed = true
}
if err = soundAlert(); err != nil {
log.Println("[ERREUR]", err)
}
}
}
// isAvailable checks if the wanted model is available.
func isAvailable(model *Model) (ok bool, err error) {
defer func() {
if r := recover(); r != nil {
err = errors.New(errNoAvailabilities)
return
}
}()
var res *http.Response
res, err = http.Get("https://" + reserveSubdomain + ".apple.com/" + locale + "/reserve/" + product + "/availability.json")
if err != nil {
return
}
if res.StatusCode < 200 || res.StatusCode > 299 {
err = errors.New(errNoAvailabilities)
return
}
var js map[string]interface{}
jsdec := json.NewDecoder(res.Body)
if err = jsdec.Decode(&js); err != nil {
return
}
ok = js["stores"].(map[string]interface{})[store].(map[string]interface{})[model.Code].(map[string]interface{})["availability"].(map[string]interface{})["unlocked"].(bool)
return
}
package main
import "os/exec"
const (
strRequest = "∙"
strIsAvailable = "✅ "
)
func open(url string) *exec.Cmd {
return exec.Command("open", url)
}
func soundAlert() error {
return exec.Command("say", "Votre iPhone est disponible à la réservation !").Run()
}
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
)
const (
strRequest = "."
strIsAvailable = "!"
)
func open(url string) *exec.Cmd {
return exec.Command(filepath.Join(os.Getenv("SYSTEMROOT"), "System32", "rundll32.exe"), "url.dll,FileProtocolHandler", url)
}
func soundAlert() (err error) {
_, err = fmt.Print("\a")
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment