You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
391 lines
11 KiB
391 lines
11 KiB
package controllers
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"math"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/akhilrex/podgrab/db"
|
|
"github.com/akhilrex/podgrab/model"
|
|
"github.com/akhilrex/podgrab/service"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type SearchGPodderData struct {
|
|
Q string `binding:"required" form:"q" json:"q" query:"q"`
|
|
SearchSource string `binding:"required" form:"searchSource" json:"searchSource" query:"searchSource"`
|
|
}
|
|
type SettingModel struct {
|
|
DownloadOnAdd bool `form:"downloadOnAdd" json:"downloadOnAdd" query:"downloadOnAdd"`
|
|
InitialDownloadCount int `form:"initialDownloadCount" json:"initialDownloadCount" query:"initialDownloadCount"`
|
|
AutoDownload bool `form:"autoDownload" json:"autoDownload" query:"autoDownload"`
|
|
AppendDateToFileName bool `form:"appendDateToFileName" json:"appendDateToFileName" query:"appendDateToFileName"`
|
|
AppendEpisodeNumberToFileName bool `form:"appendEpisodeNumberToFileName" json:"appendEpisodeNumberToFileName" query:"appendEpisodeNumberToFileName"`
|
|
DarkMode bool `form:"darkMode" json:"darkMode" query:"darkMode"`
|
|
DownloadEpisodeImages bool `form:"downloadEpisodeImages" json:"downloadEpisodeImages" query:"downloadEpisodeImages"`
|
|
GenerateNFOFile bool `form:"generateNFOFile" json:"generateNFOFile" query:"generateNFOFile"`
|
|
DontDownloadDeletedFromDisk bool `form:"dontDownloadDeletedFromDisk" json:"dontDownloadDeletedFromDisk" query:"dontDownloadDeletedFromDisk"`
|
|
BaseUrl string `form:"baseUrl" json:"baseUrl" query:"baseUrl"`
|
|
MaxDownloadConcurrency int `form:"maxDownloadConcurrency" json:"maxDownloadConcurrency" query:"maxDownloadConcurrency"`
|
|
}
|
|
|
|
var searchOptions = map[string]string{
|
|
"itunes": "iTunes",
|
|
"podcastindex": "PodcastIndex",
|
|
}
|
|
var searchProvider = map[string]service.SearchService{
|
|
"itunes": new(service.ItunesService),
|
|
"podcastindex": new(service.PodcastIndexService),
|
|
}
|
|
|
|
func AddPage(c *gin.Context) {
|
|
setting := c.MustGet("setting").(*db.Setting)
|
|
c.HTML(http.StatusOK, "addPodcast.html", gin.H{"title": "Add Podcast", "setting": setting, "searchOptions": searchOptions})
|
|
}
|
|
func HomePage(c *gin.Context) {
|
|
//var podcasts []db.Podcast
|
|
podcasts := service.GetAllPodcasts("")
|
|
setting := c.MustGet("setting").(*db.Setting)
|
|
c.HTML(http.StatusOK, "index.html", gin.H{"title": "Podgrab", "podcasts": podcasts, "setting": setting})
|
|
}
|
|
func PodcastPage(c *gin.Context) {
|
|
var searchByIdQuery SearchByIdQuery
|
|
if c.ShouldBindUri(&searchByIdQuery) == nil {
|
|
|
|
var podcast db.Podcast
|
|
|
|
if err := db.GetPodcastById(searchByIdQuery.Id, &podcast); err == nil {
|
|
var pagination model.Pagination
|
|
if c.ShouldBindQuery(&pagination) == nil {
|
|
var page, count int
|
|
if page = pagination.Page; page == 0 {
|
|
page = 1
|
|
}
|
|
if count = pagination.Count; count == 0 {
|
|
count = 10
|
|
}
|
|
setting := c.MustGet("setting").(*db.Setting)
|
|
totalCount := len(podcast.PodcastItems)
|
|
totalPages := int(math.Ceil(float64(totalCount) / float64(count)))
|
|
nextPage, previousPage := 0, 0
|
|
if page < totalPages {
|
|
nextPage = page + 1
|
|
}
|
|
if page > 1 {
|
|
previousPage = page - 1
|
|
}
|
|
|
|
from := (page - 1) * count
|
|
to := page * count
|
|
if to > totalCount {
|
|
to = totalCount
|
|
}
|
|
c.HTML(http.StatusOK, "episodes.html", gin.H{
|
|
"title": podcast.Title,
|
|
"podcastItems": podcast.PodcastItems[from:to],
|
|
"setting": setting,
|
|
"page": page,
|
|
"count": count,
|
|
"totalCount": totalCount,
|
|
"totalPages": totalPages,
|
|
"nextPage": nextPage,
|
|
"previousPage": previousPage,
|
|
"downloadedOnly": false,
|
|
"podcastId": searchByIdQuery.Id,
|
|
})
|
|
} else {
|
|
c.JSON(http.StatusBadRequest, err)
|
|
}
|
|
} else {
|
|
c.JSON(http.StatusBadRequest, err)
|
|
}
|
|
} else {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"})
|
|
}
|
|
|
|
}
|
|
|
|
func getItemsToPlay(itemIds []string, podcastId string, tagIds []string) []db.PodcastItem {
|
|
var items []db.PodcastItem
|
|
if len(itemIds) > 0 {
|
|
toAdd, _ := service.GetAllPodcastItemsByIds(itemIds)
|
|
items = *toAdd
|
|
|
|
} else if podcastId != "" {
|
|
pod := service.GetPodcastById(podcastId)
|
|
items = pod.PodcastItems
|
|
} else if len(tagIds) != 0 {
|
|
tags := service.GetTagsByIds(tagIds)
|
|
var tagNames []string
|
|
var podIds []string
|
|
for _, tag := range *tags {
|
|
tagNames = append(tagNames, tag.Label)
|
|
for _, pod := range tag.Podcasts {
|
|
podIds = append(podIds, pod.ID)
|
|
}
|
|
}
|
|
items = *service.GetAllPodcastItemsByPodcastIds(podIds)
|
|
}
|
|
return items
|
|
}
|
|
|
|
func PlayerPage(c *gin.Context) {
|
|
|
|
itemIds, hasItemIds := c.GetQueryArray("itemIds")
|
|
podcastId, hasPodcastId := c.GetQuery("podcastId")
|
|
tagIds, hasTagIds := c.GetQueryArray("tagIds")
|
|
title := "Podgrab"
|
|
var items []db.PodcastItem
|
|
var totalCount int64
|
|
if hasItemIds {
|
|
toAdd, _ := service.GetAllPodcastItemsByIds(itemIds)
|
|
items = *toAdd
|
|
totalCount = int64(len(items))
|
|
} else if hasPodcastId {
|
|
pod := service.GetPodcastById(podcastId)
|
|
items = pod.PodcastItems
|
|
title = "Playing: " + pod.Title
|
|
totalCount = int64(len(items))
|
|
} else if hasTagIds {
|
|
tags := service.GetTagsByIds(tagIds)
|
|
var tagNames []string
|
|
var podIds []string
|
|
for _, tag := range *tags {
|
|
tagNames = append(tagNames, tag.Label)
|
|
for _, pod := range tag.Podcasts {
|
|
podIds = append(podIds, pod.ID)
|
|
}
|
|
}
|
|
items = *service.GetAllPodcastItemsByPodcastIds(podIds)
|
|
if len(tagNames) == 1 {
|
|
title = fmt.Sprintf("Playing episodes with tag : %s", (tagNames[0]))
|
|
} else {
|
|
title = fmt.Sprintf("Playing episodes with tags : %s", strings.Join(tagNames, ", "))
|
|
}
|
|
} else {
|
|
title = "Playing Latest Episodes"
|
|
if err := db.GetPaginatedPodcastItems(1, 20, nil, nil, time.Time{}, &items, &totalCount); err != nil {
|
|
fmt.Println(err.Error())
|
|
}
|
|
}
|
|
setting := c.MustGet("setting").(*db.Setting)
|
|
|
|
c.HTML(http.StatusOK, "player.html", gin.H{
|
|
"title": title,
|
|
"podcastItems": items,
|
|
"setting": setting,
|
|
"count": len(items),
|
|
"totalCount": totalCount,
|
|
"downloadedOnly": true,
|
|
})
|
|
|
|
}
|
|
func SettingsPage(c *gin.Context) {
|
|
|
|
setting := c.MustGet("setting").(*db.Setting)
|
|
diskStats, _ := db.GetPodcastEpisodeDiskStats()
|
|
c.HTML(http.StatusOK, "settings.html", gin.H{
|
|
"setting": setting,
|
|
"title": "Update your preferences",
|
|
"diskStats": diskStats,
|
|
})
|
|
|
|
}
|
|
func BackupsPage(c *gin.Context) {
|
|
|
|
files, err := service.GetAllBackupFiles()
|
|
var allFiles []interface{}
|
|
setting := c.MustGet("setting").(*db.Setting)
|
|
|
|
for _, file := range files {
|
|
arr := strings.Split(file, string(os.PathSeparator))
|
|
name := arr[len(arr)-1]
|
|
subsplit := strings.Split(name, "_")
|
|
dateStr := subsplit[2]
|
|
date, err := time.Parse("2006.01.02", dateStr)
|
|
if err == nil {
|
|
toAdd := map[string]interface{}{
|
|
"date": date,
|
|
"name": name,
|
|
"path": strings.ReplaceAll(file, string(os.PathSeparator), "/"),
|
|
}
|
|
allFiles = append(allFiles, toAdd)
|
|
}
|
|
}
|
|
|
|
if err == nil {
|
|
c.HTML(http.StatusOK, "backups.html", gin.H{
|
|
"backups": allFiles,
|
|
"title": "Backups",
|
|
"setting": setting,
|
|
})
|
|
} else {
|
|
c.JSON(http.StatusBadRequest, err)
|
|
}
|
|
|
|
}
|
|
|
|
func getSortOptions() interface{} {
|
|
return []struct {
|
|
Label, Value string
|
|
}{
|
|
{"Release (asc)", "release_asc"},
|
|
{"Release (desc)", "release_desc"},
|
|
{"Duration (asc)", "duration_asc"},
|
|
{"Duration (desc)", "duration_desc"},
|
|
}
|
|
}
|
|
func AllEpisodesPage(c *gin.Context) {
|
|
var filter model.EpisodesFilter
|
|
c.ShouldBindQuery(&filter)
|
|
filter.VerifyPaginationValues()
|
|
setting := c.MustGet("setting").(*db.Setting)
|
|
podcasts := service.GetAllPodcasts("")
|
|
tags, _ := db.GetAllTags("")
|
|
toReturn := gin.H{
|
|
"title": "All Episodes",
|
|
"podcastItems": []db.PodcastItem{},
|
|
"setting": setting,
|
|
"page": filter.Page,
|
|
"count": filter.Count,
|
|
"filter": filter,
|
|
"podcasts": podcasts,
|
|
"tags": tags,
|
|
"sortOptions": getSortOptions(),
|
|
}
|
|
c.HTML(http.StatusOK, "episodes_new.html", toReturn)
|
|
|
|
}
|
|
|
|
func AllTagsPage(c *gin.Context) {
|
|
var pagination model.Pagination
|
|
var page, count int
|
|
c.ShouldBindQuery(&pagination)
|
|
if page = pagination.Page; page == 0 {
|
|
page = 1
|
|
}
|
|
if count = pagination.Count; count == 0 {
|
|
count = 10
|
|
}
|
|
|
|
var tags []db.Tag
|
|
var totalCount int64
|
|
//fmt.Printf("%+v\n", filter)
|
|
|
|
if err := db.GetPaginatedTags(page, count,
|
|
&tags, &totalCount); err == nil {
|
|
|
|
setting := c.MustGet("setting").(*db.Setting)
|
|
totalPages := math.Ceil(float64(totalCount) / float64(count))
|
|
nextPage, previousPage := 0, 0
|
|
if float64(page) < totalPages {
|
|
nextPage = page + 1
|
|
}
|
|
if page > 1 {
|
|
previousPage = page - 1
|
|
}
|
|
toReturn := gin.H{
|
|
"title": "Tags",
|
|
"tags": tags,
|
|
"setting": setting,
|
|
"page": page,
|
|
"count": count,
|
|
"totalCount": totalCount,
|
|
"totalPages": totalPages,
|
|
"nextPage": nextPage,
|
|
"previousPage": previousPage,
|
|
}
|
|
c.HTML(http.StatusOK, "tags.html", toReturn)
|
|
} else {
|
|
c.JSON(http.StatusBadRequest, err)
|
|
}
|
|
|
|
}
|
|
|
|
func Search(c *gin.Context) {
|
|
var searchQuery SearchGPodderData
|
|
if c.ShouldBindQuery(&searchQuery) == nil {
|
|
var searcher service.SearchService
|
|
var isValidSearchProvider bool
|
|
if searcher, isValidSearchProvider = searchProvider[searchQuery.SearchSource]; !isValidSearchProvider {
|
|
searcher = new(service.PodcastIndexService)
|
|
}
|
|
|
|
data := searcher.Query(searchQuery.Q)
|
|
allPodcasts := service.GetAllPodcasts("")
|
|
|
|
urls := make(map[string]string, len(*allPodcasts))
|
|
for _, pod := range *allPodcasts {
|
|
urls[pod.URL] = pod.ID
|
|
}
|
|
for _, pod := range data {
|
|
_, ok := urls[pod.URL]
|
|
pod.AlreadySaved = ok
|
|
}
|
|
c.JSON(200, data)
|
|
}
|
|
|
|
}
|
|
|
|
func GetOmpl(c *gin.Context) {
|
|
|
|
usePodgrabLink := c.DefaultQuery("usePodgrabLink", "false") == "true"
|
|
|
|
data, err := service.ExportOmpl(usePodgrabLink, getBaseUrl(c))
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"message": "Invalid request"})
|
|
return
|
|
}
|
|
c.Header("Content-Disposition", "attachment; filename=podgrab-export.opml")
|
|
c.Data(200, "text/xml", data)
|
|
}
|
|
func UploadOpml(c *gin.Context) {
|
|
file, _, err := c.Request.FormFile("file")
|
|
defer file.Close()
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"message": "Invalid request"})
|
|
return
|
|
}
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
if _, err := io.Copy(buf, file); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"message": "Invalid request"})
|
|
return
|
|
}
|
|
content := string(buf.Bytes())
|
|
err = service.AddOpml(content)
|
|
if err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"message": err.Error()})
|
|
} else {
|
|
c.JSON(200, gin.H{"success": "File uploaded"})
|
|
}
|
|
}
|
|
|
|
func AddNewPodcast(c *gin.Context) {
|
|
var addPodcastData AddPodcastData
|
|
err := c.ShouldBind(&addPodcastData)
|
|
|
|
if err == nil {
|
|
|
|
_, err = service.AddPodcast(addPodcastData.Url)
|
|
if err == nil {
|
|
go service.RefreshEpisodes()
|
|
c.Redirect(http.StatusFound, "/")
|
|
|
|
} else {
|
|
|
|
c.JSON(http.StatusBadRequest, err)
|
|
|
|
}
|
|
} else {
|
|
// fmt.Println(err.Error())
|
|
c.JSON(http.StatusBadRequest, err)
|
|
}
|
|
|
|
}
|