pull/24/head
Akhil Gupta 4 years ago
parent 2d8f34ace2
commit 84b98b3524

@ -3,15 +3,160 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" integrity="sha512-EZLkOqwILORob+p0BXZc+Vm3RgJBOe1Iq/0fiI7r/wJgzOFZMlsqTa29UEl6v6U6gsV4uIpsNZoV32YZqrCRCQ==" crossorigin="anonymous" />
<title>PodGrab</title>
<style>
.container {
max-width: 800px; }
.header {
margin-top: 6rem;
text-align: center; }
.value-prop {
margin-top: 1rem; }
.value-props {
margin-top: 4rem;
margin-bottom: 4rem; }
.docs-header {
text-transform: uppercase;
font-size: 1.4rem;
letter-spacing: .2rem;
font-weight: 600; }
.docs-section {
border-top: 1px solid #eee;
padding: 4rem 0;
margin-bottom: 0;}
.value-img {
display: block;
text-align: center;
margin: 2.5rem auto 0; }
.example-grid .column,
.example-grid .columns {
background: #EEE;
text-align: center;
border-radius: 4px;
font-size: 1rem;
text-transform: uppercase;
height: 30px;
line-height: 30px;
margin-bottom: .75rem;
font-weight: 600;
letter-spacing: .1rem; }
.docs-example .row,
.docs-example.row,
.docs-example form {
margin-bottom: 0; }
.docs-example h1,
.docs-example h2,
.docs-example h3,
.docs-example h4,
.docs-example h5,
.docs-example h6 {
margin-bottom: 1rem; }
.heading-font-size {
font-size: 1.2rem;
color: #999;
letter-spacing: normal; }
.code-example {
margin-top: 1.5rem;
margin-bottom: 0; }
.code-example-body {
white-space: pre;
word-wrap: break-word }
.example {
position: relative;
margin-top: 4rem; }
.example-header {
font-weight: 600;
margin-top: 1.5rem;
margin-bottom: .5rem; }
.example-description {
margin-bottom: 1.5rem; }
.example-screenshot-wrapper {
display: block;
position: relative;
overflow: hidden;
border-radius: 6px;
border: 1px solid #eee;
height: 250px; }
.example-screenshot {
width: 100%;
height: auto; }
.example-screenshot.coming-soon {
width: auto;
position: absolute;
background: #eee;
top: 5px;
right: 5px;
bottom: 5px;
left: 5px; }
.navbar {
display: none; }
/* Larger than phone */
@media (min-width: 550px) {
.header {
margin-top: 18rem;
}
.value-props {
margin-top: 9rem;
margin-bottom: 7rem; }
.value-img {
margin-bottom: 1rem; }
.example-grid .column,
.example-grid .columns {
margin-bottom: 1.5rem; }
.docs-section {
padding: 6rem 0; }
.example-send-yourself-copy {
float: right;
margin-top: 12px; }
.example-screenshot-wrapper {
position: absolute;
width: 48%;
height: 100%;
left: 0;
max-height: none; }
}
/* Larger than tablet */
@media (min-width: 750px) {
}
</style>
</head>
<body>
<div class="container">
<section class="header">
<h1>{{ .title }}</h1>
</section>
<div class="row">
<form action="/" method="post">
<div class="ten columns">
<input type="url" name="url" id="url" placeholder="Enter Podcast RSS feed" class="u-full-width">
</div><div class="two columns">
<input type="submit" value="Save" class="u-full-width button-primary">
</div>
</form>
</div>
<br>
{{range .podcasts}}
<div class="podcasts row">
<div class="columns three">
<img class="u-full-width" src="{{ .Image }}" alt="{{ .Title }}">
</div>
<div class="columns eight">
<h3>{{.Title}}</h3>
<p>{{ .Summary }}</p>
</div>
<div class="columns one">
{{ len .PodcastItems }} episodes
</div>
<ol>
{{range .podcasts}}
<li>{{.Title}}
</li> {{end}}
</ol>
</div>
<hr>
{{end}}
</div>
</body>
</html>

@ -20,7 +20,7 @@ type SearchByIdQuery struct {
}
type AddPodcastData struct {
url string `binding:"required" form:"url" json:"url"`
Url string `binding:"required" form:"url" json:"url"`
}
func GetAllPodcasts(c *gin.Context) {
@ -85,7 +85,7 @@ func AddPodcast(c *gin.Context) {
err := c.ShouldBindJSON(&addPodcastData)
if err == nil {
service.AddPodcast(addPodcastData.url)
service.AddPodcast(addPodcastData.Url)
// fmt.Println(time.Unix(addPodcastData.StartDate, 0))
c.JSON(200, addPodcastData)
} else {

@ -61,7 +61,7 @@ func CreatePodcast(podcast *Podcast) error {
}
func CreatePodcastItem(podcastItem *PodcastItem) error {
tx := DB.Create(&podcastItem)
tx := DB.Omit("Podcast").Create(&podcastItem)
return tx.Error
}
func UpdatePodcastItem(podcastItem *PodcastItem) error {

@ -7,8 +7,10 @@ require (
github.com/gin-gonic/gin v1.6.3
github.com/gobeam/stringy v0.0.0-20200717095810-8a3637503f62
github.com/jasonlvhit/gocron v0.0.1
github.com/microcosm-cc/bluemonday v1.0.4
github.com/satori/go.uuid v1.2.0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect
gorm.io/driver/sqlite v1.1.3
gorm.io/gorm v1.20.2
)

@ -1,5 +1,9 @@
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
@ -28,6 +32,8 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jasonlvhit/gocron v0.0.1 h1:qTt5qF3b3srDjeOIR4Le1LfeyvoYzJlYpqvG7tJX5YU=
github.com/jasonlvhit/gocron v0.0.1/go.mod h1:k9a3TV8VcU73XZxfVHCHWMWF9SOqgoku0/QlY2yvlA4=
@ -49,6 +55,8 @@ github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
github.com/mattn/go-sqlite3 v1.14.3 h1:j7a/xn1U6TKA/PHHxqZuzh64CdtRc7rU9M+AvkOl5bA=
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
@ -69,14 +77,19 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c h1:dk0ukUIHmGHqASjP0iue2261isepFCC6XRCSd1nHgDw=
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c/go.mod h1:iQL9McJNjoIa5mjH6nYTCTZXUN6RP+XW3eib7Ya3XcI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -85,6 +98,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

@ -64,8 +64,30 @@ func main() {
r.GET("/", func(c *gin.Context) {
//var podcasts []db.Podcast
podcasts := service.GetAllPodcasts()
c.HTML(http.StatusOK, "index.html", gin.H{"title": "Main website", "podcasts": podcasts})
c.HTML(http.StatusOK, "index.html", gin.H{"title": "Podgrab", "podcasts": podcasts})
})
r.POST(
"/", func(c *gin.Context) {
var addPodcastData controllers.AddPodcastData
err := c.ShouldBind(&addPodcastData)
if err == nil {
_, err = service.AddPodcast(addPodcastData.Url)
if err == nil {
c.Redirect(http.StatusFound, "/")
} else {
c.JSON(http.StatusBadRequest, err)
}
} else {
// fmt.Println(err.Error())
c.JSON(http.StatusBadRequest, err)
}
})
go intiCron()
@ -74,7 +96,7 @@ func main() {
}
func intiCron() {
gocron.Every(20).Minutes().Do(service.DownloadMissingEpisodes)
gocron.Every(20).Minutes().Do(service.RefreshEpisodes)
//gocron.Every(5).Minutes().Do(service.DownloadMissingEpisodes)
gocron.Every(5).Minutes().Do(service.RefreshEpisodes)
<-gocron.Start()
}

@ -11,14 +11,18 @@ import (
"time"
"github.com/akhilrex/podgrab/db"
"github.com/microcosm-cc/bluemonday"
"gorm.io/gorm"
)
//Fetch is
func FetchURL(url string) (PodcastData, error) {
body := makeQuery(url)
body, err := makeQuery(url)
if err != nil {
return PodcastData{}, err
}
var response PodcastData
err := xml.Unmarshal(body, &response)
err = xml.Unmarshal(body, &response)
return response, err
}
func GetAllPodcasts() *[]db.Podcast {
@ -31,15 +35,17 @@ func AddPodcast(url string) (db.Podcast, error) {
data, err := FetchURL(url)
if err != nil {
fmt.Println("Error")
log.Fatal(err)
//log.Fatal(err)
return db.Podcast{}, err
}
var podcast db.Podcast
err = db.GetPodcastByTitleAndAuthor(data.Channel.Title, data.Channel.Author, &podcast)
if errors.Is(err, gorm.ErrRecordNotFound) {
p := bluemonday.StripTagsPolicy()
podcast := db.Podcast{
Title: data.Channel.Title,
Summary: data.Channel.Summary,
Summary: p.Sanitize(data.Channel.Summary),
Author: data.Channel.Author,
Image: data.Channel.Image.URL,
URL: url,
@ -58,7 +64,7 @@ func AddPodcastItems(podcast *db.Podcast) error {
log.Fatal(err)
return err
}
p := bluemonday.StripTagsPolicy()
for i := 0; i < 5; i++ {
obj := data.Channel.Item[i]
var podcastItem db.PodcastItem
@ -69,7 +75,7 @@ func AddPodcastItems(podcast *db.Podcast) error {
podcastItem = db.PodcastItem{
PodcastID: podcast.ID,
Title: obj.Title,
Summary: obj.Summary,
Summary: p.Sanitize(obj.Summary),
EpisodeType: obj.EpisodeType,
Duration: duration,
PubDate: pubDate,
@ -120,24 +126,24 @@ func RefreshEpisodes() error {
return nil
}
func makeQuery(url string) []byte {
func makeQuery(url string) ([]byte, error) {
//link := "https://www.goodreads.com/search/index.xml?q=Good%27s+Omens&key=" + "jCmNlIXjz29GoB8wYsrd0w"
//link := "https://www.goodreads.com/search/index.xml?key=jCmNlIXjz29GoB8wYsrd0w&q=Ender%27s+Game"
//fmt.Println(url)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
log.Fatal(err)
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
return nil, err
}
defer resp.Body.Close()
fmt.Println("Response status:", resp.Status)
body, err := ioutil.ReadAll(resp.Body)
return body
return body, nil
}

Loading…
Cancel
Save