initial api work

This commit is contained in:
stryan 2020-03-29 18:16:01 -04:00
commit f960eab641
6 changed files with 424 additions and 0 deletions

63
backend/addViews.go Normal file
View File

@ -0,0 +1,63 @@
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"github.com/gorilla/mux"
)
func addMovie(w http.ResponseWriter, r *http.Request) {
var newmov Movie
reqBody, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Fprintf(w, "Please enter a movie")
}
json.Unmarshal(reqBody, &newmov)
fmt.Println(newmov)
mov, err := db.CreateMovie(newmov.Title, newmov.Imdb)
if err != nil || mov.ID == 0 {
fmt.Fprintf(w, "Error creating movie")
return
}
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(mov)
}
func addTaggedMovie(w http.ResponseWriter, r *http.Request) {
movieIDstr := mux.Vars(r)["mid"]
tagIDstr := mux.Vars(r)["tid"]
movieID, err := strconv.Atoi(movieIDstr)
if err != nil {
fmt.Fprintf(w, "Error: invalid movie ID passed")
return
}
tagID, err := strconv.Atoi(tagIDstr)
if err != nil {
fmt.Fprintf(w, "Error: invalid tag ID passed")
return
}
err = db.TagMovie(tagID, movieID)
if err != nil {
fmt.Fprintf(w, "Error tagging movie")
}
json.NewEncoder(w).Encode("tagged")
}
func addTag(w http.ResponseWriter, r *http.Request) {
var newtag Tag
reqBody, err := ioutil.ReadAll(r.Body)
if err != nil {
fmt.Fprintf(w, "Please enter a tag")
}
json.Unmarshal(reqBody, &newtag)
tag, _ := db.CreateTag(newtag.Name)
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(tag)
}

60
backend/delViews.go Normal file
View File

@ -0,0 +1,60 @@
package main
import (
"fmt"
"net/http"
"strconv"
"github.com/gorilla/mux"
)
func delOneMovie(w http.ResponseWriter, r *http.Request) {
movieIDstr := mux.Vars(r)["id"]
movieID, err := strconv.Atoi(movieIDstr)
if err != nil {
fmt.Fprintf(w, "Error: invalid movie ID passed")
return
}
err = db.DeleteMovie(movieID)
if err != nil {
fmt.Fprintf(w, "Error deleting movie")
return
}
fmt.Fprintf(w, "Movie deleted succesfully")
}
func delOneTag(w http.ResponseWriter, r *http.Request) {
tagIDstr := mux.Vars(r)["id"]
tagID, err := strconv.Atoi(tagIDstr)
if err != nil {
fmt.Fprintf(w, "Error: invalid tag ID passed")
return
}
err = db.DeleteTag(tagID)
if err != nil {
fmt.Fprintf(w, "Error deleting tag")
return
}
fmt.Fprintf(w, "Tag deleted succesfully")
}
func delTaggedMovie(w http.ResponseWriter, r *http.Request) {
movieIDstr := mux.Vars(r)["mid"]
tagIDstr := mux.Vars(r)["tid"]
movieID, err := strconv.Atoi(movieIDstr)
if err != nil {
fmt.Fprintf(w, "Error: invalid movie ID passed")
return
}
tagID, err := strconv.Atoi(tagIDstr)
if err != nil {
fmt.Fprintf(w, "Error: invalid tag ID passed")
return
}
err = db.UnTagMovie(tagID, movieID)
if err != nil {
fmt.Fprintf(w, "Error untagging movie")
return
}
fmt.Fprintf(w, "Untagged movie")
}

78
backend/getViews.go Normal file
View File

@ -0,0 +1,78 @@
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"github.com/gorilla/mux"
)
func homeLink(w http.ResponseWriter, r *http.Request) {
movies, err := db.GetMovies()
if err != nil {
log.Fatal("Error showing homepage (all movies)")
}
json.NewEncoder(w).Encode(movies)
}
func getMovies(w http.ResponseWriter, r *http.Request) {
movies, err := db.GetMovies()
if err != nil {
log.Fatal("Error getting all movies")
}
json.NewEncoder(w).Encode(movies)
}
func getOneMovie(w http.ResponseWriter, r *http.Request) {
movieIDstr := mux.Vars(r)["id"]
movieID, err := strconv.Atoi(movieIDstr)
if err != nil {
log.Println("Error: invalid movie ID passed")
return
}
mov, err := db.GetMovieById(movieID)
if err != nil {
log.Fatal("Error getting one movie")
}
json.NewEncoder(w).Encode(mov)
}
func getTaggedMovies(w http.ResponseWriter, r *http.Request) {
tagIDstr := mux.Vars(r)["id"]
tagID, err := strconv.Atoi(tagIDstr)
if err != nil {
fmt.Fprintf(w, "Error: invalid tag ID passed")
return
}
movies, err := db.GetMoviesByTag(tagID)
if err != nil {
fmt.Fprintf(w, "Error fetching movies by tag")
return
}
json.NewEncoder(w).Encode(movies)
}
func getTags(w http.ResponseWriter, r *http.Request) {
tags, err := db.GetTags()
if err != nil {
log.Fatal("Error getting all tags")
}
json.NewEncoder(w).Encode(tags)
}
func getOneTag(w http.ResponseWriter, r *http.Request) {
tagIDstr := mux.Vars(r)["id"]
tagID, err := strconv.Atoi(tagIDstr)
if err != nil {
log.Println("Error: invalid tag ID passed")
return
}
tag, err := db.GetTagById(tagID)
if err != nil {
log.Fatal("Error getting one tag")
}
json.NewEncoder(w).Encode(tag)
}

49
backend/main.go Normal file
View File

@ -0,0 +1,49 @@
package main
import (
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
var db MovieDB
func main() {
setupDB()
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/", homeLink)
router.HandleFunc("/movie", getMovies).Methods("GET")
router.HandleFunc("/movie", addMovie).Methods("POST")
router.HandleFunc("/movie/{id}", getOneMovie).Methods("GET")
router.HandleFunc("/movie/{id}", delOneMovie).Methods("DELETE")
router.HandleFunc("/movie/tag/{id}", getTaggedMovies).Methods("GET")
router.HandleFunc("/movie/{mid}/tag/{tid}", addTaggedMovie).Methods("POST")
router.HandleFunc("/movie/{mid}/tag/{tid}", delTaggedMovie).Methods("DELETE")
router.HandleFunc("/tag", getTags).Methods("GET")
router.HandleFunc("/tag", addTag).Methods("POST")
router.HandleFunc("/tag/{id}", getOneTag).Methods("GET")
router.HandleFunc("/tag/{id}", delOneTag).Methods("DELETE")
log.Fatal(http.ListenAndServe(":8080", router))
}
func setupDB() {
db = CreateMemDB()
id1, _ := db.CreateMovie("Murder By Death", "tt0074937")
id2, _ := db.CreateMovie("Satanic Panic", "tt8510350")
id3, _ := db.CreateMovie("Event Horizon", "tt0119081")
id4, _ := db.CreateMovie("Shrek", "tt0126029")
fmt.Printf("Created %v %v %v %v\n", id1, id2, id3, id4)
t1, _ := db.CreateTag("deea")
t2, _ := db.CreateTag("steve")
t3, _ := db.CreateTag("bad")
fmt.Printf("Created tags %v %v %v\n", t1, t2, t3)
db.TagMovie(t1.ID, id1.ID)
db.TagMovie(t2.ID, id2.ID)
db.TagMovie(t3.ID, id3.ID)
db.TagMovie(t3.ID, id4.ID)
}

146
backend/mem.go Normal file
View File

@ -0,0 +1,146 @@
package main
import (
"errors"
)
type MemDB struct {
MovieList map[int]*Movie
TagList map[int]*Tag
TagToMovie map[string][]int
mId int
tId int
}
func CreateMemDB() *MemDB {
return &MemDB{make(map[int]*Movie), make(map[int]*Tag), make(map[string][]int), 1, 1}
}
func (m *MemDB) CreateMovie(title, imdb string) (Movie, error) {
mov := Movie{m.mId, title, imdb, []*Tag{}}
m.MovieList[m.mId] = &mov
m.mId = m.mId + 1
return mov, nil
}
func (m *MemDB) UpdateMovie(id int, title string, imdb string) error {
m.MovieList[id].Title = title
m.MovieList[id].Imdb = imdb
return nil
}
func (m *MemDB) GetMovies(limit ...int) ([]Movie, error) {
lim := -1
var res []Movie
if len(limit) > 0 {
lim = limit[0]
}
count := 0
for _, mov := range m.MovieList {
if count == lim {
break
}
res = append(res, *mov)
}
return res, nil
}
func (m *MemDB) GetMovieById(id int) (Movie, error) {
mov := m.MovieList[id]
if mov.ID == 0 {
return *mov, errors.New("No movie found!")
} else {
return *mov, nil
}
}
func (m *MemDB) GetMoviesByTag(id int) ([]Movie, error) {
tag := m.TagList[id]
if tag.Name == "" {
return []Movie{}, nil //nonexistent tag is a valid option
}
var res []Movie
movies := m.TagToMovie[tag.Name]
for _, movID := range movies {
res = append(res, *m.MovieList[movID])
}
return res, nil
}
func (m *MemDB) DeleteMovie(id int) error {
delete(m.MovieList, id)
return nil
}
func (m *MemDB) CreateTag(name string) (Tag, error) {
tag := Tag{m.tId, name}
m.TagList[m.tId] = &tag
m.tId = m.tId + 1
return tag, nil
}
func (m *MemDB) DeleteTag(id int) error {
tag := m.TagList[id]
delete(m.TagList, id)
delete(m.TagToMovie, tag.Name)
return nil
}
func (m *MemDB) GetTags(limit ...int) ([]Tag, error) {
lim := -1
var res []Tag
if len(limit) > 0 {
lim = limit[0]
}
count := 0
for _, tag := range m.TagList {
if count == lim {
break
}
res = append(res, *tag)
}
return res, nil
}
func (m *MemDB) GetTagById(id int) (Tag, error) {
tag := m.TagList[id]
if tag.ID == 0 {
return *tag, errors.New("No tag found!")
} else {
return *tag, nil
}
}
func (m *MemDB) TagMovie(tagId int, movieId int) error {
mov := m.MovieList[movieId]
tag := m.TagList[tagId]
if mov.ID == 0 {
return errors.New("No movie found for tagging!")
}
if tag.ID == 0 {
return errors.New("No tag found for tagging!")
}
m.TagToMovie[tag.Name] = append(m.TagToMovie[tag.Name], movieId)
mov.Tags = append(mov.Tags, tag)
return nil
}
func (m *MemDB) UnTagMovie(tagId int, movieId int) error {
mov := m.MovieList[movieId]
tag := m.TagList[tagId]
if mov.ID == 0 {
return errors.New("No movie found for untagging!")
}
if tag.ID == 0 {
return errors.New("No tag found for untagging!")
}
for i, v := range m.TagToMovie[tag.Name] {
if v == movieId {
m.TagToMovie[tag.Name][i] = m.TagToMovie[tag.Name][len(m.TagToMovie[tag.Name])-1]
m.TagToMovie[tag.Name] = m.TagToMovie[tag.Name][:len(m.TagToMovie[tag.Name])-1]
break
}
}
return nil
}

28
backend/types.go Normal file
View File

@ -0,0 +1,28 @@
package main
type Movie struct {
ID int `json:"id"`
Title string `json:"title"`
Imdb string `json:"imdb"`
Tags []*Tag `json:"tags"`
}
type Tag struct {
ID int `db:"id" json:"id"`
Name string `db:"name" json:"name"`
}
type MovieDB interface {
CreateMovie(title string, imdb string) (Movie, error)
UpdateMovie(id int, title string, imbd string) error
GetMovies(limit ...int) ([]Movie, error)
GetMovieById(id int) (Movie, error)
GetMoviesByTag(id int) ([]Movie, error)
DeleteMovie(id int) error
CreateTag(name string) (Tag, error)
DeleteTag(id int) error
GetTags(limit ...int) ([]Tag, error)
GetTagById(id int) (Tag, error)
TagMovie(tagId int, movieId int) error
UnTagMovie(tagId int, movieId int) error
}