commit
This commit is contained in:
parent
a8e1256f82
commit
8272b1a6bf
6
go.mod
6
go.mod
|
@ -2,8 +2,10 @@ module git.wavrant.xyz/webrss
|
|||
|
||||
require (
|
||||
github.com/PuerkitoBio/goquery v1.5.0 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.10.0 // indirect
|
||||
github.com/mmcdole/gofeed v1.0.0-beta2 // indirect
|
||||
github.com/gorilla/mux v1.7.0
|
||||
github.com/gorilla/rpc v1.1.0
|
||||
github.com/mattn/go-sqlite3 v1.10.0
|
||||
github.com/mmcdole/gofeed v1.0.0-beta2
|
||||
github.com/mmcdole/goxpp v0.0.0-20181012175147-0068e33feabf // indirect
|
||||
golang.org/x/net v0.0.0-20190322120337-addf6b3196f6 // indirect
|
||||
)
|
||||
|
|
4
go.sum
4
go.sum
|
@ -8,6 +8,10 @@ github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP
|
|||
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
|
||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/rpc v1.1.0 h1:marKfvVP0Gpd/jHlVBKCQ8RAoUPdX7K1Nuh6l1BNh7A=
|
||||
github.com/gorilla/rpc v1.1.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ=
|
||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
github.com/mmcdole/gofeed v1.0.0-beta2 h1:CjQ0ADhAwNSb08zknAkGOEYqr8zfZKfrzgk9BxpWP2E=
|
||||
|
|
167
main.go
167
main.go
|
@ -2,10 +2,16 @@ package main
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
librss "github.com/mmcdole/gofeed"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type FeedManager struct {
|
||||
|
@ -68,7 +74,7 @@ Custom TEXT,
|
|||
FOREIGN KEY(Feed) REFERENCES feeds(Id)
|
||||
)
|
||||
`}
|
||||
|
||||
|
||||
for _, stmt := range createStmts {
|
||||
_, err = db.Exec(stmt)
|
||||
if err != nil {
|
||||
|
@ -126,9 +132,9 @@ func (f *FeedManager) AddFeed(url string) (*sql.Result, error) {
|
|||
return nil, err
|
||||
}
|
||||
query := `insert into feeds (title, description, link, feedLink, updated, updatedParsed,
|
||||
published, publishedParsed, image) values(?, ?, ?, ?, ?, ?, ?, ?, ?);`
|
||||
published, publishedParsed) values(?, ?, ?, ?, ?, ?, ?, ?);`
|
||||
return f.ExecDB(query, feed.Title, feed.Description, feed.Link, feed.FeedLink, feed.Updated, feed.UpdatedParsed,
|
||||
feed.Published, feed.PublishedParsed, feed.Image)
|
||||
feed.Published, feed.PublishedParsed)
|
||||
}
|
||||
|
||||
func (f *FeedManager) RemoveFeed(url string) (*sql.Result, error) {
|
||||
|
@ -146,31 +152,30 @@ func (f *FeedManager) DownloadFeed(url string) (*librss.Feed, error) {
|
|||
return feed, nil
|
||||
}
|
||||
|
||||
func (f *FeedManager) GetFeeds () (map[int]librss.Feed, error) {
|
||||
func (f *FeedManager) GetFeeds() (map[int]librss.Feed, error) {
|
||||
feeds := make(map[int]librss.Feed)
|
||||
|
||||
rows, err := f.QueryDB("select id, link from feeds;")
|
||||
|
||||
rows, err := f.QueryDB("select id, title, feedlink, link from feeds;")
|
||||
if err != nil {
|
||||
return feeds, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
|
||||
for rows.Next() {
|
||||
var link string
|
||||
var link, title, feedLink string
|
||||
var id int
|
||||
err = rows.Scan(&id, &link)
|
||||
err = rows.Scan(&id, &title, &feedLink, &link)
|
||||
if err != nil {
|
||||
return feeds, err
|
||||
}
|
||||
fmt.Println(id, link)
|
||||
|
||||
feeds[id] = librss.Feed{Link:link}
|
||||
|
||||
feeds[id] = librss.Feed{Link: link, FeedLink: feedLink, Title: title}
|
||||
}
|
||||
|
||||
return feeds, nil
|
||||
}
|
||||
|
||||
func (f *FeedManager) Sync() (error) {
|
||||
func (f *FeedManager) Sync() error {
|
||||
feeds, err := f.GetFeeds()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -183,8 +188,8 @@ func (f *FeedManager) Sync() (error) {
|
|||
}
|
||||
|
||||
for _, item := range res.Items {
|
||||
_, err := f.ExecDB("insert into items (feed, Title, Description, Content, Link, Author, GUID, Image) values (?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
id, item.Title, item.Description, item.Content, item.Link, item.Author, item.GUID, item.Image)
|
||||
_, err := f.ExecDB("insert into items (feed, Title, Description, Content, Link, Author, GUID) values (?, ?, ?, ?, ?, ?, ?)",
|
||||
id, item.Title, item.Description, item.Content, item.Link, item.Author, item.GUID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -194,6 +199,105 @@ func (f *FeedManager) Sync() (error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func HomeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
//fmt.Fprintf(w, "hello")
|
||||
http.ServeFile(w, r, "./ui/index.html")
|
||||
}
|
||||
|
||||
func GetFeedsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
defaultDBPath := "./database.db"
|
||||
feedManager := FeedManager{DBPath: defaultDBPath}
|
||||
|
||||
feeds, err := feedManager.GetFeeds()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
feedList := make([]librss.Feed, 0)
|
||||
for _, feed := range feeds {
|
||||
feedList = append(feedList, feed)
|
||||
}
|
||||
|
||||
json, err := json.Marshal(feedList)
|
||||
fmt.Fprintf(w, string(json))
|
||||
}
|
||||
|
||||
func PostFeed(w http.ResponseWriter, r *http.Request) {
|
||||
defaultDBPath := "./database.db"
|
||||
feedManager := FeedManager{DBPath: defaultDBPath}
|
||||
|
||||
new_feed_url := r.FormValue("new_feed_url")
|
||||
|
||||
if new_feed_url == "" {
|
||||
w.WriteHeader(500)
|
||||
}
|
||||
|
||||
feeds, err := feedManager.GetFeeds()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
|
||||
for _, feed := range feeds {
|
||||
if feed.FeedLink == new_feed_url {
|
||||
log.Print("Not adding feed ", new_feed_url, " because it already exists")
|
||||
w.WriteHeader(500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Print("Adding new feed : ", new_feed_url)
|
||||
|
||||
_, err = feedManager.AddFeed(r.FormValue("new_feed_url"))
|
||||
if err != nil {
|
||||
fmt.Fprintf(w, "ERROR")
|
||||
}
|
||||
fmt.Fprintf(w, "OK")
|
||||
}
|
||||
|
||||
func (f *FeedManager) GetItems(feedId int) ([]librss.Item, error) {
|
||||
rows, err := f.QueryDB("select title, description from items where feed=?;", feedId)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
items := make([]librss.Item, 0)
|
||||
for rows.Next() {
|
||||
var title, description string
|
||||
err = rows.Scan(&title, &description)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, librss.Item{Title: title, Description: description})
|
||||
}
|
||||
|
||||
return items, nil
|
||||
}
|
||||
|
||||
func GetItemsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
defaultDBPath := "./database.db"
|
||||
feedManager := FeedManager{DBPath: defaultDBPath}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
feedId, err := strconv.Atoi(vars["feedId"])
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
|
||||
items, err := feedManager.GetItems(feedId)
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
return
|
||||
}
|
||||
|
||||
json, err := json.Marshal(items)
|
||||
fmt.Fprintf(w, string(json))
|
||||
}
|
||||
|
||||
func main() {
|
||||
defaultDBPath := "./database.db"
|
||||
|
||||
|
@ -205,13 +309,40 @@ func main() {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_, err = feedManager.AddFeed("https://www.lemonde.fr/rss/une.xml")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = feedManager.Sync()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
router := mux.NewRouter()
|
||||
|
||||
err := feedManager.Sync()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
router.HandleFunc("/", HomeHandler)
|
||||
|
||||
router.PathPrefix("/static/").Handler(
|
||||
http.StripPrefix(
|
||||
"/static/", http.FileServer(http.Dir("./ui/static"))))
|
||||
|
||||
router.HandleFunc("/api/feeds/", GetFeedsHandler)
|
||||
router.HandleFunc("/api/feeds/{feedId:[0-9]+}/items", GetItemsHandler)
|
||||
router.HandleFunc("/api/feeds/new/", PostFeed).Methods("POST")
|
||||
|
||||
http.Handle("/", router)
|
||||
|
||||
server := &http.Server{
|
||||
Handler: router,
|
||||
Addr: "127.0.0.1:8000",
|
||||
WriteTimeout: 10 * time.Second,
|
||||
ReadTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
log.Print("Listening on 127.0.0.1:8000")
|
||||
log.Fatal(server.ListenAndServe())
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="/static/vue-2.6.10.js"></script>
|
||||
<script src="/static/vue-router-3.0.2.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>WebRSS</h1>
|
||||
<div id="app">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/static/index.js"></script>
|
||||
</html>
|
|
@ -0,0 +1,67 @@
|
|||
const FeedListView = Vue.component("feed-list-view", {
|
||||
data: function () {
|
||||
return {
|
||||
feed_list: [],
|
||||
new_feed_url: "https://linuxfr.org/news.atom"
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
fetchFeeds: function() {
|
||||
let component = this;
|
||||
|
||||
fetch("/api/feeds/")
|
||||
.then(function(response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function(json) {
|
||||
component.feed_list = json;
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log(err);
|
||||
})
|
||||
},
|
||||
onSubmit: function () {
|
||||
let c = this,
|
||||
fd = new FormData();
|
||||
|
||||
fd.set('new_feed_url', this.new_feed_url);
|
||||
|
||||
fetch("/api/feeds/new/", {
|
||||
method: "POST",
|
||||
body: fd
|
||||
})
|
||||
.then(function(response) {
|
||||
console.log(response);
|
||||
c.fetchFeeds();
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log(err);
|
||||
})
|
||||
}
|
||||
},
|
||||
beforeMount: function () {
|
||||
return this.fetchFeeds();
|
||||
},
|
||||
template:`
|
||||
<div>
|
||||
<ul>
|
||||
<li v-for="feed in feed_list">{{ feed.title }}</li>
|
||||
</ul>
|
||||
<form v-on:submit.prevent="onSubmit" action="/api/feeds/new/" method="POST">
|
||||
<input v-model="new_feed_url" name="feed_url">
|
||||
<button type="submit">Add</button>
|
||||
</form>
|
||||
</div>
|
||||
`
|
||||
})
|
||||
|
||||
const router = new VueRouter({
|
||||
routes: [{
|
||||
path: '/',
|
||||
component: FeedListView
|
||||
}]
|
||||
})
|
||||
|
||||
const app = new Vue({
|
||||
router
|
||||
}).$mount("#app")
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue