1
0
Fork 0

Initial commit

This commit is contained in:
Andrew Tomaka 2016-02-22 11:44:56 -05:00
commit c86a245309
3 changed files with 152 additions and 0 deletions

25
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,25 @@
stages:
- build
- deploy
build:
stage: build
script:
- docker build -t atomaka/punaday-api .
except:
- tags
tags:
- docker
deploy:
stage: deploy
script:
- VERSION=$(git describe --tags)
- docker build -t atomaka/punaday-api .
- docker tag atomaka/punaday-api:latest docker.atomaka.com/atomaka/punaday-api:$VERSION
- docker tag atomaka/punaday-api:latest docker.atomaka.com/atomaka/punaday-api:latest
- docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD -e me@atomaka.com docker.atomaka.com
- docker push docker.atomaka.com/atomaka/punaday-api
only:
- tags
tags:
- docker

12
Dockerfile Normal file
View file

@ -0,0 +1,12 @@
FROM alpine:latest
COPY . /go/src/github.com/atomaka/punaday-api
RUN apk update \
&& apk add --no-cache go git \
&& cd /go/src/github.com/atomaka/punaday-api \
&& export GOPATH=/go \
&& go get \
&& go build -o /bin/punaday-api \
&& rm -rf /go \
&& apk del --purge git go \
&& rm -rf /var/cache/apk*
ENTRYPOINT ["/bin/punaday-api"]

115
main.go Normal file
View file

@ -0,0 +1,115 @@
package main
import (
"encoding/json"
"log"
"net/http"
"strconv"
"golang.org/x/net/html"
)
const PUN_BASE = "http://www.punoftheday.com"
const RANDOM_PUN = PUN_BASE + "/cgi-bin/randompun.pl"
const SELECT_PUN = PUN_BASE + "/pun"
type Pun struct {
Id int `json:"-"`
Url string `json:"url"`
Text string `json:"text"`
}
type Error struct {
Status int `json:"-"`
Detail string `json:"error"`
}
func main() {
http.HandleFunc("/puns/random", RandomPun)
http.HandleFunc("/puns/", ShowPun)
http.HandleFunc("/", NotFound)
log.Fatal(http.ListenAndServe(":8080", nil))
}
func NotFound(w http.ResponseWriter, r *http.Request) {
log.Printf("404 Not Found: %v\n", r.URL.Path)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
err := &Error{404, "not_found"}
w.WriteHeader(err.Status)
json.NewEncoder(w).Encode(err)
}
func WritePun(w http.ResponseWriter, r *http.Request, pun Pun) {
log.Printf("200 OK: %v\n", r.URL.Path)
w.Header().Set("Content-Type", "application/json; charset=utf-8")
json.NewEncoder(w).Encode(pun)
}
func ShowPun(w http.ResponseWriter, r *http.Request) {
id := r.URL.Path[len("/puns/"):]
pun := getPun(SELECT_PUN + "/" + id)
if id != strconv.Itoa(pun.Id) {
NotFound(w, r)
} else {
WritePun(w, r, pun)
}
}
func RandomPun(w http.ResponseWriter, r *http.Request) {
pun := getPun(RANDOM_PUN)
WritePun(w, r, pun)
}
func getPun(url string) Pun {
resp, err := http.Get(url)
if err != nil {
log.Println("ERROR: Unable to access " + url)
}
b := resp.Body
defer b.Close()
pun := Pun{}
z := html.NewTokenizer(b)
for {
tt := z.Next()
switch {
case tt == html.ErrorToken:
return pun
case tt == html.StartTagToken:
t := z.Token()
isParagraph := t.Data == "p"
isInput := t.Data == "input"
if isParagraph && pun.Text == "" {
z.Next()
t := z.Token()
pun.Text = t.Data
}
if isInput {
if getAttr("name", t) == "PunID" {
pun.Id, _ = strconv.Atoi(getAttr("value", t))
pun.Url = SELECT_PUN + "/" + strconv.Itoa(pun.Id)
}
}
}
}
}
func getAttr(at string, t html.Token) string {
var val string
for _, a := range t.Attr {
if a.Key == at {
val = a.Val
}
}
return val
}