Quickstart in Go
Een Go-programma dat een token vernieuwt, je schermen oplijst en een playlist op een scherm zet. De blokken op deze pagina vormen samen één bestand.
1 Haal een token op
Open de CMS op Instellingen, Verbonden apps en klik op Genereer token. Een lid zonder beheerdersrechten ziet dit tabblad niet.
Kies daarna de organisatie, die bepaalt welke schermen het programma ziet, en klik op Toestaan. De volgende pagina toont de client ID en het refresh token, één keer. Kopieer ze allebei.
Zet in je terminal de client ID en het pad naar het tokenbestand, en schrijf het refresh token naar dat bestand. read -rs wacht zonder iets te tonen: plak het refresh token en druk op Enter, zo blijft het uit de shell-history:
export GIBEON_CLIENT_ID=CLIENT_ID export GIBEON_REFRESH_TOKEN_FILE=./gibeon-refresh-token touch "$GIBEON_REFRESH_TOKEN_FILE" chmod 600 "$GIBEON_REFRESH_TOKEN_FILE" read -rs GIBEON_REFRESH_TOKEN && printf '%s' "$GIBEON_REFRESH_TOKEN" > "$GIBEON_REFRESH_TOKEN_FILE"
Het programma heeft Go 1.18 of nieuwer nodig. Het gebruikt alleen de standaardbibliotheek, dus er valt niets te installeren. Zet de blokken hieronder in volgorde in main.go en draai go run main.go.
2 Vernieuw het token
Een access token is 60 minuten geldig. Elke vernieuwing geeft ook een nieuw refresh token, dus een waarde in de omgeving is na één run verouderd.
Het programma schrijft het nieuwe token naar een tijdelijk bestand in dezelfde map, zet chmod 600 en hernoemt het over het bestand in GIBEON_REFRESH_TOKEN_FILE. Daarna pas gebruikt het programma het access token. Een proces dat daarbij stopt, houdt zo een werkend refresh token over.
Dit blok bevat ook de imports en de helpers. Bij elke status buiten 2xx stopt send het programma met exitcode 1.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"time"
)
var client = &http.Client{Timeout: 30 * time.Second}
type player struct {
ID string `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
}
// exitOn stops the program with a non-zero exit code.
func exitOn(err error) {
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
// send runs the request and stops the program on any non-2xx status.
func send(req *http.Request) []byte {
response, err := client.Do(req)
exitOn(err)
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
exitOn(err)
if response.StatusCode < 200 || response.StatusCode > 299 {
exitOn(fmt.Errorf("%s %s: %s", req.Method, req.URL, response.Status))
}
return body
}
func refresh() string {
tokenFile := os.Getenv("GIBEON_REFRESH_TOKEN_FILE")
refreshToken, err := os.ReadFile(tokenFile)
exitOn(err)
form := url.Values{
"grant_type": {"refresh_token"},
"client_id": {os.Getenv("GIBEON_CLIENT_ID")},
"refresh_token": {strings.TrimSpace(string(refreshToken))},
}
req, err := http.NewRequest("POST", "https://id.gibeon.io/auth/v1/oauth/token", strings.NewReader(form.Encode()))
exitOn(err)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
var tokens struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
}
exitOn(json.Unmarshal(send(req), &tokens))
if tokens.RefreshToken == "" {
exitOn(fmt.Errorf("the response holds no refresh token"))
}
// Store the new refresh token before anything uses the access token.
tmp, err := os.CreateTemp(filepath.Dir(tokenFile), ".gibeon-refresh-token-*")
exitOn(err)
_, err = tmp.WriteString(tokens.RefreshToken)
exitOn(err)
exitOn(tmp.Close())
exitOn(os.Chmod(tmp.Name(), 0o600))
exitOn(os.Rename(tmp.Name(), tokenFile))
return tokens.AccessToken
} 3 Lijst je schermen op
Dit geeft alle schermen in je tenant. Het programma print van elk scherm de id, name en status, en nooit een token.
func listScreens(accessToken string) {
req, err := http.NewRequest("GET", "https://www.gibeon.io/v1/players", nil)
exitOn(err)
req.Header.Set("Authorization", "Bearer "+accessToken)
var result struct {
Data []player `json:"data"`
}
exitOn(json.Unmarshal(send(req), &result))
for _, p := range result.Data {
fmt.Println(p.ID, p.Name, p.Status)
}
} 4 Wijs een playlist toe en publiceer
Deze stap draait alleen als GIBEON_PLAYER_ID en GIBEON_PLAYLIST_ID gezet zijn. De id van het scherm staat in de lijst uit de vorige stap. De id van de playlist staat in de adresbalk van de CMS als je de playlist opent: /playlists/PLAYLIST_ID/content. Exporteer ze allebei en draai het programma opnieuw.
Een scherm met zones speelt die; anders zijn sequentie; anders zijn planning; anders zijn eigen playlist. De body maakt de sequentie en de planning leeg, dus de playlist speelt tenzij het scherm zones heeft.
De PATCH alleen verandert niets op het scherm: tot je publiceert, blijft het de oude toewijzing tonen. Publiceren bouwt een nieuwe snapshot en geeft het scherm meteen een seintje.
De laatste functie, main, roept de drie in volgorde aan.
func assignAndPublish(accessToken string) {
playerID := os.Getenv("GIBEON_PLAYER_ID")
playlistID := os.Getenv("GIBEON_PLAYLIST_ID")
if playerID == "" || playlistID == "" {
return
}
body, err := json.Marshal(map[string]any{
"playlist_id": playlistID,
"sequence_id": nil,
"planning_id": nil,
})
exitOn(err)
req, err := http.NewRequest("PATCH", fmt.Sprintf("https://www.gibeon.io/v1/players/%s", playerID), bytes.NewReader(body))
exitOn(err)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Content-Type", "application/json")
var result struct {
Data player `json:"data"`
}
exitOn(json.Unmarshal(send(req), &result))
req, err = http.NewRequest("POST", fmt.Sprintf("https://www.gibeon.io/v1/players/%s/publish", playerID), nil)
exitOn(err)
req.Header.Set("Authorization", "Bearer "+accessToken)
send(req)
fmt.Println(result.Data.ID, result.Data.Name, result.Data.Status)
}
func main() {
accessToken := refresh()
listScreens(accessToken)
assignAndPublish(accessToken)
}