This commit is contained in:
Aidan Holm
2024-10-26 10:59:45 +00:00
committed by GitHub
8 changed files with 38 additions and 29 deletions

View File

@@ -13,6 +13,7 @@ import (
"github.com/nkanaev/yarr/src/platform" "github.com/nkanaev/yarr/src/platform"
"github.com/nkanaev/yarr/src/server" "github.com/nkanaev/yarr/src/server"
"github.com/nkanaev/yarr/src/storage" "github.com/nkanaev/yarr/src/storage"
"github.com/nkanaev/yarr/src/worker"
) )
var Version string = "0.0" var Version string = "0.0"
@@ -131,7 +132,8 @@ func main() {
log.Fatal("Failed to initialise database: ", err) log.Fatal("Failed to initialise database: ", err)
} }
srv := server.NewServer(store, addr) client := worker.NewClient(Version)
srv := server.NewServer(store, addr, client)
if basepath != "" { if basepath != "" {
srv.BasePath = "/" + strings.Trim(basepath, "/") srv.BasePath = "/" + strings.Trim(basepath, "/")

View File

@@ -10,6 +10,7 @@
- (fix) sorting same-day batch articles (thanks to @lamescholar for the report) - (fix) sorting same-day batch articles (thanks to @lamescholar for the report)
- (fix) showing login page in the selected theme (thanks to @feddiriko for the report) - (fix) showing login page in the selected theme (thanks to @feddiriko for the report)
- (fix) parsing atom feeds with html elements (thanks to @tillcash & @toBeOfUse for the report, @krkk for the fix) - (fix) parsing atom feeds with html elements (thanks to @tillcash & @toBeOfUse for the report, @krkk for the fix)
- (fix) user agent now uses the current version (thanks to @aidanholm)
# v2.4 (2023-08-15) # v2.4 (2023-08-15)

View File

@@ -230,7 +230,7 @@ func (s *Server) handleFeedList(c *router.Context) {
return return
} }
result, err := worker.DiscoverFeed(form.Url) result, err := s.worker.DiscoverFeed(form.Url)
switch { switch {
case err != nil: case err != nil:
log.Printf("Faild to discover feed for %s: %s", form.Url, err) log.Printf("Faild to discover feed for %s: %s", form.Url, err)
@@ -504,7 +504,7 @@ func (s *Server) handlePageCrawl(c *router.Context) {
return return
} }
body, err := worker.GetBody(url) body, err := s.worker.GetBody(url)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
c.Out.WriteHeader(http.StatusBadRequest) c.Out.WriteHeader(http.StatusBadRequest)

View File

@@ -11,10 +11,12 @@ import (
"testing" "testing"
"github.com/nkanaev/yarr/src/storage" "github.com/nkanaev/yarr/src/storage"
"github.com/nkanaev/yarr/src/worker"
) )
func TestStatic(t *testing.T) { func TestStatic(t *testing.T) {
handler := NewServer(nil, "127.0.0.1:8000").handler() client := worker.NewClient("test")
handler := NewServer(nil, "127.0.0.1:8000", client).handler()
url := "/static/javascripts/app.js" url := "/static/javascripts/app.js"
recorder := httptest.NewRecorder() recorder := httptest.NewRecorder()
@@ -26,7 +28,8 @@ func TestStatic(t *testing.T) {
} }
func TestStaticWithBase(t *testing.T) { func TestStaticWithBase(t *testing.T) {
server := NewServer(nil, "127.0.0.1:8000") client := worker.NewClient("test")
server := NewServer(nil, "127.0.0.1:8000", client)
server.BasePath = "/sub" server.BasePath = "/sub"
handler := server.handler() handler := server.handler()
@@ -41,7 +44,8 @@ func TestStaticWithBase(t *testing.T) {
} }
func TestStaticBanTemplates(t *testing.T) { func TestStaticBanTemplates(t *testing.T) {
handler := NewServer(nil, "127.0.0.1:8000").handler() client := worker.NewClient("test")
handler := NewServer(nil, "127.0.0.1:8000", client).handler()
url := "/static/login.html" url := "/static/login.html"
recorder := httptest.NewRecorder() recorder := httptest.NewRecorder()
@@ -56,7 +60,8 @@ func TestIndexGzipped(t *testing.T) {
log.SetOutput(io.Discard) log.SetOutput(io.Discard)
db, _ := storage.New(":memory:") db, _ := storage.New(":memory:")
log.SetOutput(os.Stderr) log.SetOutput(os.Stderr)
handler := NewServer(db, "127.0.0.1:8000").handler() client := worker.NewClient("test")
handler := NewServer(db, "127.0.0.1:8000", client).handler()
url := "/" url := "/"
recorder := httptest.NewRecorder() recorder := httptest.NewRecorder()
@@ -87,7 +92,8 @@ func TestFeedIcons(t *testing.T) {
url := fmt.Sprintf("/api/feeds/%d/icon", feed.Id) url := fmt.Sprintf("/api/feeds/%d/icon", feed.Id)
request := httptest.NewRequest("GET", url, nil) request := httptest.NewRequest("GET", url, nil)
handler := NewServer(db, "127.0.0.1:8000").handler() client := worker.NewClient("test")
handler := NewServer(db, "127.0.0.1:8000", client).handler()
handler.ServeHTTP(recorder, request) handler.ServeHTTP(recorder, request)
response := recorder.Result() response := recorder.Result()

View File

@@ -26,11 +26,11 @@ type Server struct {
KeyFile string KeyFile string
} }
func NewServer(db *storage.Storage, addr string) *Server { func NewServer(db *storage.Storage, addr string, client *worker.Client) *Server {
return &Server{ return &Server{
db: db, db: db,
Addr: addr, Addr: addr,
worker: worker.NewWorker(db), worker: worker.NewWorker(db, client),
cache: make(map[string]interface{}), cache: make(map[string]interface{}),
cache_mutex: &sync.Mutex{}, cache_mutex: &sync.Mutex{},
} }

View File

@@ -30,9 +30,7 @@ func (c *Client) getConditional(url, lastModified, etag string) (*http.Response,
return c.httpClient.Do(req) return c.httpClient.Do(req)
} }
var client *Client func NewClient(version string) *Client {
func init() {
transport := &http.Transport{ transport := &http.Transport{
Proxy: http.ProxyFromEnvironment, Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{ DialContext: (&net.Dialer{
@@ -45,8 +43,9 @@ func init() {
Timeout: time.Second * 30, Timeout: time.Second * 30,
Transport: transport, Transport: transport,
} }
client = &Client{
return &Client{
httpClient: httpClient, httpClient: httpClient,
userAgent: "Yarr/1.0", userAgent: "Yarr/" + version,
} }
} }

View File

@@ -28,10 +28,10 @@ type DiscoverResult struct {
Sources []FeedSource Sources []FeedSource
} }
func DiscoverFeed(candidateUrl string) (*DiscoverResult, error) { func (worker *Worker) DiscoverFeed(candidateUrl string) (*DiscoverResult, error) {
result := &DiscoverResult{} result := &DiscoverResult{}
// Query URL // Query URL
res, err := client.get(candidateUrl) res, err := worker.client.get(candidateUrl)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -74,7 +74,7 @@ func DiscoverFeed(candidateUrl string) (*DiscoverResult, error) {
if sources[0].Url == candidateUrl { if sources[0].Url == candidateUrl {
return nil, errors.New("Recursion!") return nil, errors.New("Recursion!")
} }
return DiscoverFeed(sources[0].Url) return worker.DiscoverFeed(sources[0].Url)
} }
result.Sources = sources result.Sources = sources
@@ -89,7 +89,7 @@ var imageTypes = map[string]bool{
"image/gif": true, "image/gif": true,
} }
func findFavicon(siteUrl, feedUrl string) (*[]byte, error) { func (worker *Worker) findFavicon(siteUrl, feedUrl string) (*[]byte, error) {
urls := make([]string, 0) urls := make([]string, 0)
favicon := func(link string) string { favicon := func(link string) string {
@@ -101,7 +101,7 @@ func findFavicon(siteUrl, feedUrl string) (*[]byte, error) {
} }
if siteUrl != "" { if siteUrl != "" {
if res, err := client.get(siteUrl); err == nil { if res, err := worker.client.get(siteUrl); err == nil {
defer res.Body.Close() defer res.Body.Close()
if body, err := ioutil.ReadAll(res.Body); err == nil { if body, err := ioutil.ReadAll(res.Body); err == nil {
urls = append(urls, scraper.FindIcons(string(body), siteUrl)...) urls = append(urls, scraper.FindIcons(string(body), siteUrl)...)
@@ -117,7 +117,7 @@ func findFavicon(siteUrl, feedUrl string) (*[]byte, error) {
} }
for _, u := range urls { for _, u := range urls {
res, err := client.get(u) res, err := worker.client.get(u)
if err != nil { if err != nil {
continue continue
} }
@@ -166,7 +166,7 @@ func ConvertItems(items []parser.Item, feed storage.Feed) []storage.Item {
return result return result
} }
func listItems(f storage.Feed, db *storage.Storage) ([]storage.Item, error) { func (worker *Worker) listItems(f storage.Feed, db *storage.Storage) ([]storage.Item, error) {
lmod := "" lmod := ""
etag := "" etag := ""
if state := db.GetHTTPState(f.Id); state != nil { if state := db.GetHTTPState(f.Id); state != nil {
@@ -174,7 +174,7 @@ func listItems(f storage.Feed, db *storage.Storage) ([]storage.Item, error) {
etag = state.Etag etag = state.Etag
} }
res, err := client.getConditional(f.FeedLink, lmod, etag) res, err := worker.client.getConditional(f.FeedLink, lmod, etag)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -215,8 +215,8 @@ func getCharset(res *http.Response) string {
return "" return ""
} }
func GetBody(url string) (string, error) { func (worker *Worker) GetBody(url string) (string, error) {
res, err := client.get(url) res, err := worker.client.get(url)
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@@ -13,15 +13,16 @@ const NUM_WORKERS = 4
type Worker struct { type Worker struct {
db *storage.Storage db *storage.Storage
client *Client
pending *int32 pending *int32
refresh *time.Ticker refresh *time.Ticker
reflock sync.Mutex reflock sync.Mutex
stopper chan bool stopper chan bool
} }
func NewWorker(db *storage.Storage) *Worker { func NewWorker(db *storage.Storage, client *Client) *Worker {
pending := int32(0) pending := int32(0)
return &Worker{db: db, pending: &pending} return &Worker{db: db, client: client, pending: &pending}
} }
func (w *Worker) FeedsPending() int32 { func (w *Worker) FeedsPending() int32 {
@@ -48,7 +49,7 @@ func (w *Worker) FindFavicons() {
} }
func (w *Worker) FindFeedFavicon(feed storage.Feed) { func (w *Worker) FindFeedFavicon(feed storage.Feed) {
icon, err := findFavicon(feed.Link, feed.FeedLink) icon, err := w.findFavicon(feed.Link, feed.FeedLink)
if err != nil { if err != nil {
log.Printf("Failed to find favicon for %s (%s): %s", feed.FeedLink, feed.Link, err) log.Printf("Failed to find favicon for %s (%s): %s", feed.FeedLink, feed.Link, err)
} }
@@ -137,7 +138,7 @@ func (w *Worker) refresher(feeds []storage.Feed) {
func (w *Worker) worker(srcqueue <-chan storage.Feed, dstqueue chan<- []storage.Item) { func (w *Worker) worker(srcqueue <-chan storage.Feed, dstqueue chan<- []storage.Item) {
for feed := range srcqueue { for feed := range srcqueue {
items, err := listItems(feed, w.db) items, err := w.listItems(feed, w.db)
if err != nil { if err != nil {
w.db.SetFeedError(feed.Id, err) w.db.SetFeedError(feed.Id, err)
} }