diff --git a/frontend/app.js b/frontend/app.js
index bb9a30c..dac154b 100644
--- a/frontend/app.js
+++ b/frontend/app.js
@@ -25,9 +25,26 @@ new Vue({
this.modalTweet = tweet
},
+ deleteTweet(tweet) {
+ axios
+ .delete(`/api/${tweet.id}`)
+ .then(() => {
+ const tweets = []
+
+ for (const t in this.tweets) {
+ if (t.id !== tweet.id) {
+ tweets.push(t)
+ }
+ }
+
+ this.tweets = tweets
+ })
+ .catch(err => console.log(err))
+ },
+
favourite(tweet) {
axios
- .post('/api/favourite', { id: tweet.id })
+ .put(`/api/${tweet.id}/favorite`)
.then(res => {
if (res.data.length === 0) {
this.refetch(tweet)
@@ -49,7 +66,7 @@ new Vue({
refetch(tweet) {
axios
- .post('/api/refresh', { id: tweet.id })
+ .put(`/api/${tweet.id}/refresh`)
.then(res => {
if (res.data.length === 0) {
return
@@ -82,7 +99,7 @@ new Vue({
triggerForceFetch() {
axios
- .post('/api/force-reload')
+ .put('/api/force-reload')
.then(() => {
this.notify('Force refresh triggered, reloading tweets in 10s')
window.setTimeout(() => this.refresh(true), 10000)
diff --git a/frontend/index.html b/frontend/index.html
index db1f22a..f2c70f1 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -63,6 +63,9 @@
{{ tweet.images.length }}
+
+
+
diff --git a/go.mod b/go.mod
index f35ce1a..76b5734 100644
--- a/go.mod
+++ b/go.mod
@@ -11,6 +11,7 @@ require (
github.com/dustin/go-jsonpointer v0.0.0-20160814072949-ba0abeacc3dc // indirect
github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect
github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17 // indirect
+ github.com/gorilla/mux v1.7.3
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.4.1
diff --git a/go.sum b/go.sum
index 793fe36..dab706b 100644
--- a/go.sum
+++ b/go.sum
@@ -17,6 +17,8 @@ github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad h1:Qk76DOWdOp+GlyDKB
github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad/go.mod h1:mPKfmRa823oBIgl2r20LeMSpTAteW5j7FLkc0vjmzyQ=
github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17 h1:GOfMz6cRgTJ9jWV0qAezv642OhPnKEG7gtUjJSdStHE=
github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17/go.mod h1:HfkOCN6fkKKaPSAeNq/er3xObxTW4VLeY6UUK895gLQ=
+github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
+github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
diff --git a/http.go b/http.go
index 3a6cf3b..8a6770e 100644
--- a/http.go
+++ b/http.go
@@ -8,29 +8,49 @@ import (
"strings"
"github.com/ChimeraCoder/anaconda"
+ "github.com/gorilla/mux"
+ "github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
func init() {
- http.HandleFunc("/api/favourite", handleFavorite)
- http.HandleFunc("/api/force-reload", handleForceReload)
- http.HandleFunc("/api/page", handlePage)
- http.HandleFunc("/api/refresh", handleTweetRefresh)
- http.HandleFunc("/api/since", handleNewest)
+ router.HandleFunc("/api/{tweetID}/favorite", handleFavorite).Methods(http.MethodPut)
+ router.HandleFunc("/api/{tweetID}", handleDelete).Methods(http.MethodDelete)
+ router.HandleFunc("/api/force-reload", handleForceReload).Methods(http.MethodPut)
+ router.HandleFunc("/api/page", handlePage).Methods(http.MethodGet)
+ router.HandleFunc("/api/{tweetID}/refresh", handleTweetRefresh).Methods(http.MethodPut)
+ router.HandleFunc("/api/since", handleNewest).Methods(http.MethodGet)
+}
+
+func handleDelete(w http.ResponseWriter, r *http.Request) {
+ var vars = mux.Vars(r)
+
+ tweetID, err := strconv.ParseInt(vars["tweetID"], 10, 64)
+ if err != nil {
+ http.Error(w, errors.Wrap(err, "Unable to parse TweetID").Error(), http.StatusBadRequest)
+ return
+ }
+
+ if err := tweetStore.DeleteTweetByID(uint64(tweetID)); err != nil {
+ log.WithError(err).Error("Unable to delete tweet")
+ http.Error(w, "Something went wrong", http.StatusInternalServerError)
+ return
+ }
+
+ w.WriteHeader(http.StatusNoContent)
}
// handleFavorite takes the ID of a tweet and submits a favorite to Twitter
func handleFavorite(w http.ResponseWriter, r *http.Request) {
- req := struct {
- ID int64 `json:"id,string"`
- }{}
+ var vars = mux.Vars(r)
- if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.ID == 0 {
- http.Error(w, "Need to specify id", http.StatusBadRequest)
+ tweetID, err := strconv.ParseInt(vars["tweetID"], 10, 64)
+ if err != nil {
+ http.Error(w, errors.Wrap(err, "Unable to parse TweetID").Error(), http.StatusBadRequest)
return
}
- tweet, err := twitter.Favorite(req.ID)
+ tweet, err := twitter.Favorite(tweetID)
if err != nil {
log.WithError(err).Error("Unable to favourite tweet")
http.Error(w, "Something went wrong", http.StatusInternalServerError)
@@ -55,11 +75,6 @@ func handleFavorite(w http.ResponseWriter, r *http.Request) {
// handleForceReload issues a full load of the latest tweets to update their state
func handleForceReload(w http.ResponseWriter, r *http.Request) {
- if r.Method != http.MethodPost {
- http.Error(w, "This needs to be POST", http.StatusBadRequest)
- return
- }
-
go loadAndStoreTweets(true)
w.WriteHeader(http.StatusNoContent)
@@ -94,20 +109,19 @@ func handlePage(w http.ResponseWriter, r *http.Request) {
// handleTweetRefresh refreshes the state of the tweet with the given ID against the Twitter API
func handleTweetRefresh(w http.ResponseWriter, r *http.Request) {
- req := struct {
- ID int64 `json:"id,string"`
- }{}
+ var vars = mux.Vars(r)
- if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.ID == 0 {
- http.Error(w, "Need to specify id", http.StatusBadRequest)
+ tweetID, err := strconv.ParseInt(vars["tweetID"], 10, 64)
+ if err != nil {
+ http.Error(w, errors.Wrap(err, "Unable to parse TweetID").Error(), http.StatusBadRequest)
return
}
- tweet, err := twitter.GetTweet(req.ID, url.Values{})
+ tweet, err := twitter.GetTweet(tweetID, url.Values{})
if err != nil {
if strings.Contains(err.Error(), "No status found with that ID.") {
- log.WithField("id", req.ID).Info("Removing no longer existing tweet")
- if err = tweetStore.DeleteTweetByID(uint64(req.ID)); err != nil {
+ log.WithField("id", tweetID).Info("Removing no longer existing tweet")
+ if err = tweetStore.DeleteTweetByID(uint64(tweetID)); err != nil {
log.WithError(err).Error("Unable to delete tweet")
http.Error(w, "Something went wrong", http.StatusInternalServerError)
}
diff --git a/main.go b/main.go
index 2d75c18..18bae30 100644
--- a/main.go
+++ b/main.go
@@ -9,6 +9,7 @@ import (
"time"
"github.com/ChimeraCoder/anaconda"
+ "github.com/gorilla/mux"
log "github.com/sirupsen/logrus"
hhelp "github.com/Luzifer/go_helpers/v2/http"
@@ -30,6 +31,7 @@ var (
VersionAndExit bool `flag:"version" default:"false" description:"Prints current version and exits"`
}{}
+ router = mux.NewRouter()
tweetStore *store
twitter *anaconda.TwitterApi
@@ -72,8 +74,8 @@ func main() {
log.WithField("version", version).Info("MediaTimeline Viewer started")
- http.Handle("/", http.FileServer(http.Dir(cfg.Frontend)))
- http.ListenAndServe(cfg.Listen, hhelp.NewHTTPLogHandler(http.DefaultServeMux))
+ router.Handle("/", http.FileServer(http.Dir(cfg.Frontend)))
+ http.ListenAndServe(cfg.Listen, hhelp.NewHTTPLogHandler(router))
}
func loadAndStoreTweets(forceRefresh bool) {