2024-02-14 00:56:11 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2024-05-17 00:59:46 +02:00
|
|
|
"database/sql"
|
2024-03-04 16:26:34 +01:00
|
|
|
"fmt"
|
2024-05-17 00:59:46 +02:00
|
|
|
"io"
|
|
|
|
"log"
|
2024-02-14 00:56:11 +01:00
|
|
|
"net/http"
|
2024-05-17 00:59:46 +02:00
|
|
|
"os"
|
2024-03-04 16:26:34 +01:00
|
|
|
"strconv"
|
2024-02-14 00:56:11 +01:00
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
2024-03-04 16:26:34 +01:00
|
|
|
"github.com/jaswdr/faker"
|
2024-05-17 00:59:46 +02:00
|
|
|
_ "github.com/mattn/go-sqlite3"
|
2024-02-14 00:56:11 +01:00
|
|
|
)
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
// This is taken from our DB model
|
|
|
|
type video struct {
|
2024-05-17 00:59:46 +02:00
|
|
|
ID int `json:"id"`
|
|
|
|
Filepath string `json:"filepath"`
|
2024-02-14 00:56:11 +01:00
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
// videos slice to seed record video data.
|
|
|
|
var videos []video
|
2024-02-14 00:56:11 +01:00
|
|
|
|
|
|
|
func main() {
|
2024-05-17 00:59:46 +02:00
|
|
|
// taken from https://github.com/mattn/go-sqlite3/blob/v1.14.22/_example/simple/simple.go
|
|
|
|
db := initDb()
|
|
|
|
if db == nil {
|
|
|
|
log.Fatal("Couldn't create DB")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer db.Close()
|
2024-05-17 01:03:02 +02:00
|
|
|
defer os.Remove("./videos.db")
|
2024-03-04 16:26:34 +01:00
|
|
|
|
2024-05-17 00:59:46 +02:00
|
|
|
rows, err := db.Query("select * from videos")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
|
|
var id int
|
|
|
|
var name string
|
|
|
|
err = rows.Scan(&id, &name)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
fmt.Println(id, name)
|
|
|
|
}
|
|
|
|
err = rows.Err()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Legacy
|
|
|
|
faker := faker.New()
|
2024-03-04 16:26:34 +01:00
|
|
|
for i := 0; i < 10; i++ {
|
2024-05-17 00:59:46 +02:00
|
|
|
videos = append(videos, video{ID: i, Filepath: faker.File().AbsoluteFilePathForUnix(5)})
|
2024-03-04 16:26:34 +01:00
|
|
|
}
|
|
|
|
|
2024-02-14 00:56:11 +01:00
|
|
|
router := gin.Default()
|
2024-02-23 23:57:41 +01:00
|
|
|
router.SetTrustedProxies(nil)
|
|
|
|
|
2024-04-14 20:52:06 +02:00
|
|
|
router.POST("/upload", ReceiveFile)
|
2024-03-04 16:26:34 +01:00
|
|
|
router.GET("/videos", getvideos)
|
|
|
|
router.GET("/videos/:id", getvideoByID)
|
|
|
|
router.POST("/videos", postvideos)
|
|
|
|
router.DELETE("/videos", delvideos)
|
|
|
|
router.DELETE("/videos/:id", delvideoByID)
|
|
|
|
router.PATCH("/videos/:id", updatevideo)
|
2024-02-14 00:56:11 +01:00
|
|
|
|
|
|
|
router.Run("localhost:8080")
|
|
|
|
}
|
|
|
|
|
2024-05-17 00:59:46 +02:00
|
|
|
func initDb() *sql.DB {
|
|
|
|
os.Remove("./videos.db")
|
|
|
|
|
|
|
|
db, err := sql.Open("sqlite3", "./videos.db")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
sqlStmt := `
|
|
|
|
create table videos (id integer not null primary key, filepath text);
|
|
|
|
delete from videos;
|
|
|
|
`
|
|
|
|
_, err = db.Exec(sqlStmt)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("%q: %s\n", err, sqlStmt)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
faker := faker.New()
|
|
|
|
|
|
|
|
tx, err := db.Begin()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
stmt, err := tx.Prepare("insert into videos(id, filepath) values(?, ?)")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
defer stmt.Close()
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
_, err = stmt.Exec(i, faker.File().AbsoluteFilePathForUnix(5))
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
err = tx.Commit()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return db
|
|
|
|
}
|
|
|
|
|
|
|
|
func remove(slice []video, s int) []video {
|
|
|
|
return append(slice[:s], slice[s+1:]...)
|
|
|
|
}
|
|
|
|
|
2024-04-14 20:52:06 +02:00
|
|
|
func ReceiveFile(c *gin.Context) {
|
2024-05-17 00:59:46 +02:00
|
|
|
// maybe even re-verify mime-type (before or after upload)
|
|
|
|
|
|
|
|
fileName := c.GetHeader("file-name")
|
|
|
|
/*
|
|
|
|
get data from request
|
|
|
|
write append data to file
|
|
|
|
*/
|
|
|
|
data, err := io.ReadAll(c.Request.Body)
|
|
|
|
if err != nil {
|
|
|
|
c.IndentedJSON(http.StatusBadRequest, "Unknown Error")
|
|
|
|
} else {
|
|
|
|
f, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
if _, err := f.Write(data); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := f.Close(); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.IndentedJSON(http.StatusOK, "Received chunk")
|
|
|
|
}
|
2024-04-14 20:52:06 +02:00
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
// getvideos responds with the list of all videos as JSON.
|
|
|
|
func getvideos(c *gin.Context) {
|
|
|
|
c.IndentedJSON(http.StatusOK, videos)
|
2024-02-14 00:56:11 +01:00
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
// postvideos adds an video from JSON received in the request body.
|
|
|
|
func postvideos(c *gin.Context) {
|
|
|
|
var newvideo video
|
2024-02-14 00:56:11 +01:00
|
|
|
|
|
|
|
// Call BindJSON to bind the received JSON to
|
2024-03-04 16:26:34 +01:00
|
|
|
// newvideo.
|
|
|
|
if err := c.BindJSON(&newvideo); err != nil {
|
2024-02-23 23:23:06 +01:00
|
|
|
c.Status(http.StatusBadRequest)
|
2024-02-14 00:56:11 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
for _, a := range videos {
|
|
|
|
if a == newvideo {
|
2024-02-23 23:23:06 +01:00
|
|
|
c.Status(http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
// Add the new video to the slice.
|
|
|
|
videos = append(videos, newvideo)
|
|
|
|
c.IndentedJSON(http.StatusCreated, newvideo)
|
2024-02-14 00:56:11 +01:00
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
// getvideoByID locates the video whose ID value matches the id
|
|
|
|
// parameter sent by the client, then returns that video as a response.
|
|
|
|
func getvideoByID(c *gin.Context) {
|
|
|
|
inputId := c.Param("id")
|
2024-02-14 00:56:11 +01:00
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
// Loop through the list of videos, looking for
|
|
|
|
// an video whose ID value matches the parameter.
|
|
|
|
for _, a := range videos {
|
|
|
|
if strconv.Itoa(a.ID) == inputId {
|
|
|
|
c.IndentedJSON(http.StatusOK, a)
|
2024-02-14 00:56:11 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2024-03-04 16:26:34 +01:00
|
|
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "video not found"})
|
2024-02-14 00:56:11 +01:00
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
func delvideos(c *gin.Context) {
|
|
|
|
videos = []video{}
|
|
|
|
c.IndentedJSON(http.StatusOK, videos)
|
2024-02-14 00:56:11 +01:00
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
func delvideoByID(c *gin.Context) {
|
|
|
|
inputId := c.Param("id")
|
2024-02-14 00:56:11 +01:00
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
for s, a := range videos {
|
|
|
|
if strconv.Itoa(a.ID) == inputId {
|
|
|
|
videos = remove(videos, s)
|
|
|
|
c.IndentedJSON(http.StatusCreated, videos)
|
2024-02-14 00:56:11 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2024-03-04 16:26:34 +01:00
|
|
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "video not found"})
|
2024-02-14 00:56:11 +01:00
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
func updatevideo(c *gin.Context) {
|
|
|
|
inputId := c.Param("id")
|
2024-02-14 00:56:11 +01:00
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
var newvideo video
|
2024-02-14 00:56:11 +01:00
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
if err := c.BindJSON(&newvideo); err != nil {
|
2024-02-14 00:56:11 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-03-04 16:26:34 +01:00
|
|
|
for s, a := range videos {
|
|
|
|
if strconv.Itoa(a.ID) == inputId {
|
|
|
|
videos = remove(videos, s)
|
|
|
|
videos = append(videos, newvideo)
|
|
|
|
c.IndentedJSON(http.StatusCreated, newvideo)
|
2024-02-14 00:56:11 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2024-03-04 16:26:34 +01:00
|
|
|
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "video not found"})
|
2024-02-14 00:56:11 +01:00
|
|
|
}
|