You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
203 lines
4.6 KiB
Go
203 lines
4.6 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/gob"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
|
|
"git.sp4ke.com/sp4ke/bit4sat/ln"
|
|
"git.sp4ke.com/sp4ke/bit4sat/storage"
|
|
"git.sp4ke.com/sp4ke/bit4sat/utils"
|
|
"github.com/gin-contrib/sessions"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func download(c *gin.Context) {
|
|
var ok bool
|
|
|
|
dlId := c.Param("dlId")
|
|
|
|
// Get upload id for dl id
|
|
upId, err := storage.GetUploadIdForDlId(dlId)
|
|
if err != nil {
|
|
utils.JSONErr(c, http.StatusNotFound, "this file does not exist anymore")
|
|
return
|
|
}
|
|
|
|
// Get the download session
|
|
session, err := SessionStore.Get(c.Request, DlSessionKey)
|
|
if err != nil {
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
dlSess := session.Values["session-id"]
|
|
dlIdVal := session.Values["dlId"]
|
|
|
|
var sessDlId string
|
|
|
|
// If no dlId was stored before than this is a new download
|
|
if dlIdVal == nil {
|
|
sessDlId = dlId
|
|
} else {
|
|
|
|
if sessDlId, ok = dlIdVal.(string); !ok {
|
|
log.Printf("cannot cast sessDlId value")
|
|
utils.JSONErr(c, http.StatusExpectationFailed,
|
|
"start a new download session session")
|
|
return
|
|
}
|
|
|
|
}
|
|
|
|
// Test if we are alread in a download session
|
|
// If the stored dlId is different than the
|
|
// current dl id it means we're downloading a different
|
|
// file
|
|
if dlSess == nil || (sessDlId != dlId) {
|
|
// This is a new download session
|
|
log.Println("new download session")
|
|
|
|
session.Values["dlId"] = dlId
|
|
|
|
// Create a unique session id for this download session
|
|
sessId, err := storage.GetShortId()
|
|
if err != nil {
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
log.Printf("going to generate invoice for %s", upId)
|
|
|
|
//TODO: use fee asked by uploader
|
|
//
|
|
// Get upload data asked by uploader
|
|
up, err := storage.GetUploadById(upId)
|
|
if err != nil {
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
// Get files metadata for upload
|
|
var upFilesMeta []storage.FileUpload
|
|
upFilesMeta, err = storage.GetUploadFilesMeta(upId)
|
|
if err != nil {
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
session.Values["files"] = upFilesMeta
|
|
|
|
invoiceOpts := ln.InvoiceOpts{
|
|
Amount: up.AskAmount,
|
|
Curr: ln.CurrencyID[up.AskCurrency],
|
|
Memo: fmt.Sprintf("bit4sat download: %s", sessId),
|
|
}
|
|
|
|
log.Printf("invoice opts %#v", invoiceOpts)
|
|
|
|
invoice, err := ln.NewInvoice(invoiceOpts)
|
|
if err != nil {
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
// Store invoice
|
|
|
|
session.Values["session-id"] = sessId
|
|
session.Values["invoice"] = invoice
|
|
|
|
invoiceExpires := time.Time(invoice.ExpiresAt).Sub(time.Now()).Seconds()
|
|
|
|
//TODO: this session can be reused during this hour
|
|
session.Options.MaxAge = int(invoiceExpires)
|
|
|
|
//log.Printf("session: %#v", session.Values)
|
|
|
|
err = session.Save(c.Request, c.Writer)
|
|
if err != nil {
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusPaymentRequired, gin.H{
|
|
"invoice": invoice,
|
|
"files": upFilesMeta,
|
|
})
|
|
|
|
// This is a returning download session to pay the invoice
|
|
} else {
|
|
log.Printf("continue download session id: %s", dlSess)
|
|
|
|
invVal := session.Values["invoice"]
|
|
var invoice = &ln.Invoice{}
|
|
if invoice, ok = invVal.(*ln.Invoice); !ok {
|
|
log.Printf("Could not find invoice in session %s", dlSess)
|
|
session.Options.MaxAge = -1
|
|
|
|
err = session.Save(c.Request, c.Writer)
|
|
if err != nil {
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
utils.JSONErr(c, http.StatusExpectationFailed,
|
|
"invoice not found, start a new download session session")
|
|
return
|
|
}
|
|
|
|
//TODO: Check if invoice paid ??
|
|
|
|
//If paid return the files else return the invoice to pay
|
|
|
|
filesVal := session.Values["files"]
|
|
var filesMeta = &[]storage.FileUpload{}
|
|
if filesMeta, ok = filesVal.(*[]storage.FileUpload); !ok {
|
|
// The cookie broke ???
|
|
session.Options.MaxAge = -1
|
|
|
|
err = session.Save(c.Request, c.Writer)
|
|
if err != nil {
|
|
utils.JSONErrPriv(c, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
utils.JSONErr(c, http.StatusExpectationFailed,
|
|
"start a new download session session")
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusPaymentRequired, gin.H{
|
|
"invoice": invoice,
|
|
"files": filesMeta,
|
|
})
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func TestDownHandler(c *gin.Context) {
|
|
sess := sessions.Default(c)
|
|
|
|
test := sess.Get("test")
|
|
log.Printf("%#v", test)
|
|
if test != nil {
|
|
sess.Clear()
|
|
sess.Save()
|
|
c.String(http.StatusOK, "I remember you")
|
|
} else {
|
|
sess.Set("test", 1)
|
|
sess.Save()
|
|
c.String(http.StatusOK, "i dont remember you")
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func init() {
|
|
gob.Register(&ln.Invoice{})
|
|
gob.Register(&[]storage.FileUpload{})
|
|
}
|