package controllers import ( "bytes" "fmt" "io" "math" "net/http" "os" "strings" "time" "github.com/akhilrex/podgrab/db" "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"` } 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 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, gin.H{"error": "Invalid request"}) } } else { c.JSON(http.StatusBadRequest, err) } } else { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) } } func getItemsToPlay(itemId, podcastId string, tagIds []string) []db.PodcastItem { var items []db.PodcastItem if itemId != "" { toAdd := service.GetPodcastItemById(itemId) items = append(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) { itemId, hasItemId := c.GetQuery("itemId") podcastId, hasPodcastId := c.GetQuery("podcastId") tagIds, hasTagIds := c.GetQueryArray("tagIds") title := "Podgrab" var items []db.PodcastItem var totalCount int64 if hasItemId { toAdd := service.GetPodcastItemById(itemId) items = append(items, *toAdd) totalCount = 1 } 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) c.HTML(http.StatusOK, "settings.html", gin.H{ "setting": setting, "title": "Update your preferences", }) } 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 AllEpisodesPage(c *gin.Context) { var pagination 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 filter EpisodesFilter c.ShouldBindQuery(&filter) var podcastItems []db.PodcastItem var totalCount int64 //fmt.Printf("%+v\n", filter) fromDate := time.Time{} if filter.FromDate != "" { parsedDate, err := time.Parse("2006-01-02", strings.Trim(filter.FromDate, "\"")) if err != nil { fromDate = time.Time{} } else { fromDate = parsedDate } } if err := db.GetPaginatedPodcastItems(page, count, nil, filter.PlayedOnly, fromDate, &podcastItems, &totalCount); err == nil { setting := c.MustGet("setting").(*db.Setting) totalPages := int(math.Ceil(float64(totalCount) / float64(count))) nextPage, previousPage := 0, 0 if page < totalPages { nextPage = page + 1 } if page > 1 { previousPage = page - 1 } downloadedOnly := false if filter.DownloadedOnly != nil { downloadedOnly = *filter.DownloadedOnly fmt.Println(downloadedOnly) } toReturn := gin.H{ "title": "All Episodes", "podcastItems": podcastItems, "setting": setting, "page": page, "count": count, "totalCount": totalCount, "totalPages": totalPages, "nextPage": nextPage, "previousPage": previousPage, "downloadedOnly": downloadedOnly, } fmt.Printf("%+v\n", totalCount) c.HTML(http.StatusOK, "episodes.html", toReturn) } else { c.JSON(http.StatusBadRequest, err) } } func AllTagsPage(c *gin.Context) { var pagination 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) { data, err := service.ExportOmpl() 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) } }