709a2ff2b61f58e837ac1ac5454b08f502b39417
[bloat] / service / transport.go
1 package service
2
3 import (
4         "context"
5         "fmt"
6         "net/http"
7         "path"
8
9         "github.com/gorilla/mux"
10 )
11
12 var (
13         ctx       = context.Background()
14         cookieAge = "31536000"
15 )
16
17 func getContextWithSession(ctx context.Context, req *http.Request) context.Context {
18         sessionID, err := req.Cookie("session_id")
19         if err != nil {
20                 return ctx
21         }
22         return context.WithValue(ctx, "session_id", sessionID.Value)
23 }
24
25 func NewHandler(s Service, staticDir string) http.Handler {
26         r := mux.NewRouter()
27
28         r.PathPrefix("/static").Handler(http.StripPrefix("/static",
29                 http.FileServer(http.Dir(path.Join(".", staticDir)))))
30
31         r.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
32                 location := "/signin"
33
34                 sessionID, _ := req.Cookie("session_id")
35                 if sessionID != nil && len(sessionID.Value) > 0 {
36                         location = "/timeline"
37                 }
38
39                 w.Header().Add("Location", location)
40                 w.WriteHeader(http.StatusSeeOther)
41         }).Methods(http.MethodGet)
42
43         r.HandleFunc("/signin", func(w http.ResponseWriter, req *http.Request) {
44                 err := s.ServeSigninPage(ctx, w)
45                 if err != nil {
46                         s.ServeErrorPage(ctx, w, err)
47                         return
48                 }
49         }).Methods(http.MethodGet)
50
51         r.HandleFunc("/signin", func(w http.ResponseWriter, req *http.Request) {
52                 instance := req.FormValue("instance")
53                 url, sessionId, err := s.GetAuthUrl(ctx, instance)
54                 if err != nil {
55                         s.ServeErrorPage(ctx, w, err)
56                         return
57                 }
58
59                 w.Header().Add("Set-Cookie", fmt.Sprintf("session_id=%s;max-age=%s", sessionId, cookieAge))
60                 w.Header().Add("Location", url)
61                 w.WriteHeader(http.StatusSeeOther)
62         }).Methods(http.MethodPost)
63
64         r.HandleFunc("/oauth_callback", func(w http.ResponseWriter, req *http.Request) {
65                 ctx := getContextWithSession(context.Background(), req)
66                 token := req.URL.Query().Get("code")
67                 _, err := s.GetUserToken(ctx, "", nil, token)
68                 if err != nil {
69                         s.ServeErrorPage(ctx, w, err)
70                         return
71                 }
72
73                 w.Header().Add("Location", "/timeline")
74                 w.WriteHeader(http.StatusSeeOther)
75         }).Methods(http.MethodGet)
76
77         r.HandleFunc("/timeline", func(w http.ResponseWriter, req *http.Request) {
78                 ctx := getContextWithSession(context.Background(), req)
79
80                 maxID := req.URL.Query().Get("max_id")
81                 sinceID := req.URL.Query().Get("since_id")
82                 minID := req.URL.Query().Get("min_id")
83
84                 err := s.ServeTimelinePage(ctx, w, nil, maxID, sinceID, minID)
85                 if err != nil {
86                         s.ServeErrorPage(ctx, w, err)
87                         return
88                 }
89         }).Methods(http.MethodGet)
90
91         r.HandleFunc("/thread/{id}", func(w http.ResponseWriter, req *http.Request) {
92                 ctx := getContextWithSession(context.Background(), req)
93                 id, _ := mux.Vars(req)["id"]
94                 reply := req.URL.Query().Get("reply")
95                 err := s.ServeThreadPage(ctx, w, nil, id, len(reply) > 1)
96                 if err != nil {
97                         s.ServeErrorPage(ctx, w, err)
98                         return
99                 }
100         }).Methods(http.MethodGet)
101
102         r.HandleFunc("/like/{id}", func(w http.ResponseWriter, req *http.Request) {
103                 ctx := getContextWithSession(context.Background(), req)
104                 id, _ := mux.Vars(req)["id"]
105                 err := s.Like(ctx, w, nil, id)
106                 if err != nil {
107                         s.ServeErrorPage(ctx, w, err)
108                         return
109                 }
110
111                 w.Header().Add("Location", req.Header.Get("Referer"))
112                 w.WriteHeader(http.StatusSeeOther)
113         }).Methods(http.MethodGet)
114
115         r.HandleFunc("/unlike/{id}", func(w http.ResponseWriter, req *http.Request) {
116                 ctx := getContextWithSession(context.Background(), req)
117                 id, _ := mux.Vars(req)["id"]
118                 err := s.UnLike(ctx, w, nil, id)
119                 if err != nil {
120                         s.ServeErrorPage(ctx, w, err)
121                         return
122                 }
123
124                 w.Header().Add("Location", req.Header.Get("Referer"))
125                 w.WriteHeader(http.StatusSeeOther)
126         }).Methods(http.MethodGet)
127
128         r.HandleFunc("/retweet/{id}", func(w http.ResponseWriter, req *http.Request) {
129                 ctx := getContextWithSession(context.Background(), req)
130                 id, _ := mux.Vars(req)["id"]
131                 err := s.Retweet(ctx, w, nil, id)
132                 if err != nil {
133                         s.ServeErrorPage(ctx, w, err)
134                         return
135                 }
136
137                 w.Header().Add("Location", req.Header.Get("Referer"))
138                 w.WriteHeader(http.StatusSeeOther)
139         }).Methods(http.MethodGet)
140
141         r.HandleFunc("/unretweet/{id}", func(w http.ResponseWriter, req *http.Request) {
142                 ctx := getContextWithSession(context.Background(), req)
143                 id, _ := mux.Vars(req)["id"]
144                 err := s.UnRetweet(ctx, w, nil, id)
145                 if err != nil {
146                         s.ServeErrorPage(ctx, w, err)
147                         return
148                 }
149
150                 w.Header().Add("Location", req.Header.Get("Referer"))
151                 w.WriteHeader(http.StatusSeeOther)
152         }).Methods(http.MethodGet)
153
154         r.HandleFunc("/post", func(w http.ResponseWriter, req *http.Request) {
155                 ctx := getContextWithSession(context.Background(), req)
156                 content := req.FormValue("content")
157                 replyToID := req.FormValue("reply_to_id")
158                 err := s.PostTweet(ctx, w, nil, content, replyToID)
159                 if err != nil {
160                         s.ServeErrorPage(ctx, w, err)
161                         return
162                 }
163
164                 location := "/timeline"
165                 if len(replyToID) > 0 {
166                         location = "/thread/" + replyToID
167                 }
168                 w.Header().Add("Location", location)
169                 w.WriteHeader(http.StatusSeeOther)
170         }).Methods(http.MethodPost)
171
172         r.HandleFunc("/signout", func(w http.ResponseWriter, req *http.Request) {
173                 // TODO remove session from database
174                 w.Header().Add("Set-Cookie", fmt.Sprintf("session_id=;max-age=0"))
175                 w.Header().Add("Location", "/")
176                 w.WriteHeader(http.StatusSeeOther)
177         }).Methods(http.MethodGet)
178
179         return r
180 }