commit ea151d1de7bacc24fca339c19d8afd2089c4b2fa Author: Robert Gerus Date: Mon Jun 13 19:26:48 2016 +0200 Frog tipper! First and final release! diff --git a/frog-tipper.go b/frog-tipper.go new file mode 100644 index 0000000..0f37281 --- /dev/null +++ b/frog-tipper.go @@ -0,0 +1,109 @@ +// Copyright 2015 Robert S. Gerus. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/cookiejar" + "sync" + "time" +) + +type tip struct { + Number int `json:"number"` + Tip string `json:"tip"` +} + +type tips struct { + Tips []tip `json:"tips"` + lock sync.RWMutex +} + +func (tips *tips) fetchTips() error { + tips.lock.Lock() + defer tips.lock.Unlock() + + data, err := httpGet("http://frog.tips/api/1/tips/") + if err != nil { + return err + } + + err = json.Unmarshal(data, tips) + if err != nil { + return err + } + + return nil +} + +func (tips *tips) popTip() string { + if len(tips.Tips) == 0 { + if err := tips.fetchTips(); err != nil { + return fmt.Sprint(err) + } + } + + tips.lock.RLock() + defer tips.lock.RUnlock() + + rmsg := tips.Tips[len(tips.Tips)-1].Tip + tips.Tips = tips.Tips[:len(tips.Tips)-1] + + return rmsg +} + +func main() { + var t tips + for { + fmt.Println(t.popTip()) + } +} + +func httpGet(link string) ([]byte, error) { + var buf []byte + cj, err := cookiejar.New(nil) + tr := &http.Transport{ + TLSHandshakeTimeout: 20 * time.Second, + ResponseHeaderTimeout: 20 * time.Second, + } + client := &http.Client{ + Transport: tr, + Jar: cj, + } + + req, err := http.NewRequest("GET", link, nil) + if err != nil { + return []byte{}, err + } + + req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36") + + resp, err := client.Do(req) + if err != nil { + return []byte{}, err + } + defer resp.Body.Close() + + // 5MiB + if resp.ContentLength > 5*1024*1024 || resp.ContentLength < 0 { + buf = make([]byte, 5*1024*1024) + } else if resp.ContentLength == 0 { + return []byte{}, nil + } else { + buf = make([]byte, resp.ContentLength) + } + + i, err := io.ReadFull(resp.Body, buf) + if err == io.ErrUnexpectedEOF { + buf = buf[:i] + } else if err != nil { + return []byte{}, err + } + + return buf, nil +}