mirror of
https://github.com/nkanaev/yarr.git
synced 2025-05-25 13:39:22 +00:00
Compare commits
7 Commits
24fa90c699
...
b6d53e5807
Author | SHA1 | Date | |
---|---|---|---|
|
b6d53e5807 | ||
|
a895145586 | ||
|
5aec3b4dab | ||
|
d787060a24 | ||
|
c1a29418eb | ||
|
17847f999c | ||
|
3adcddc70c |
@ -18,7 +18,7 @@ Then run one of the corresponding commands:
|
|||||||
make serve # starts a server at http://localhost:7070
|
make serve # starts a server at http://localhost:7070
|
||||||
|
|
||||||
# ... or build a docker image
|
# ... or build a docker image
|
||||||
docker build -t yarr .
|
docker build -t yarr -f etc/dockerfile .
|
||||||
|
|
||||||
## ARM compilation
|
## ARM compilation
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ The instructions below are to cross-compile *yarr* to `Linux/ARM*`.
|
|||||||
|
|
||||||
Build:
|
Build:
|
||||||
|
|
||||||
docker build -t yarr.arm -f dockerfile.arm .
|
docker build -t yarr.arm -f etc/dockerfile.arm .
|
||||||
|
|
||||||
Test:
|
Test:
|
||||||
|
|
@ -4,6 +4,8 @@
|
|||||||
- (fix) duplicate articles caused by the same feed addition (thanks to @adaszko)
|
- (fix) duplicate articles caused by the same feed addition (thanks to @adaszko)
|
||||||
- (fix) relative article links (thanks to @adazsko for the report)
|
- (fix) relative article links (thanks to @adazsko for the report)
|
||||||
- (fix) atom article links stored in id element (thanks to @adazsko for the report)
|
- (fix) atom article links stored in id element (thanks to @adazsko for the report)
|
||||||
|
- (fix) parsing atom feed titles (thanks to @wnh)
|
||||||
|
- (fix) sorting same-day batch articles (thanks to @lamescholar for the report)
|
||||||
|
|
||||||
# v2.4 (2023-08-15)
|
# v2.4 (2023-08-15)
|
||||||
|
|
||||||
|
@ -28,17 +28,17 @@ RUN env \
|
|||||||
CGO_ENABLED=1 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=linux GOARCH=arm64 \
|
GOOS=linux GOARCH=arm64 \
|
||||||
go build \
|
go build \
|
||||||
-tags "sqlite_foreign_keys release linux" \
|
-tags "sqlite_foreign_keys linux" \
|
||||||
-ldflags="-s -w" \
|
-ldflags="-s -w" \
|
||||||
-o /root/out/yarr.arm64 src/main.go
|
-o /root/out/yarr.arm64 ./cmd/yarr
|
||||||
|
|
||||||
RUN env \
|
RUN env \
|
||||||
CC=arm-linux-gnueabihf-gcc \
|
CC=arm-linux-gnueabihf-gcc \
|
||||||
CGO_ENABLED=1 \
|
CGO_ENABLED=1 \
|
||||||
GOOS=linux GOARCH=arm GOARM=7 \
|
GOOS=linux GOARCH=arm GOARM=7 \
|
||||||
go build \
|
go build \
|
||||||
-tags "sqlite_foreign_keys release linux" \
|
-tags "sqlite_foreign_keys linux" \
|
||||||
-ldflags="-s -w" \
|
-ldflags="-s -w" \
|
||||||
-o /root/out/yarr.arm7 src/main.go
|
-o /root/out/yarr.arm7 ./cmd/yarr
|
||||||
|
|
||||||
CMD ["/bin/bash"]
|
CMD ["/bin/bash"]
|
16
makefile
16
makefile
@ -8,26 +8,26 @@ GO_LDFLAGS := $(GO_LDFLAGS) -X 'main.Version=$(VERSION)' -X 'main.GitHash=$(GITH
|
|||||||
|
|
||||||
build_default:
|
build_default:
|
||||||
mkdir -p _output
|
mkdir -p _output
|
||||||
go build -tags "sqlite_foreign_keys release" -ldflags="$(GO_LDFLAGS)" -o _output/yarr src/main.go
|
go build -tags "sqlite_foreign_keys" -ldflags="$(GO_LDFLAGS)" -o _output/yarr ./cmd/yarr
|
||||||
|
|
||||||
build_macos:
|
build_macos:
|
||||||
mkdir -p _output/macos
|
mkdir -p _output/macos
|
||||||
GOOS=darwin GOARCH=amd64 go build -tags "sqlite_foreign_keys release macos" -ldflags="$(GO_LDFLAGS)" -o _output/macos/yarr src/main.go
|
GOOS=darwin GOARCH=amd64 go build -tags "sqlite_foreign_keys macos" -ldflags="$(GO_LDFLAGS)" -o _output/macos/yarr ./cmd/yarr
|
||||||
cp src/platform/icon.png _output/macos/icon.png
|
cp src/platform/icon.png _output/macos/icon.png
|
||||||
go run bin/package_macos.go -outdir _output/macos -version "$(VERSION)"
|
go run ./cmd/package_macos -outdir _output/macos -version "$(VERSION)"
|
||||||
|
|
||||||
build_linux:
|
build_linux:
|
||||||
mkdir -p _output/linux
|
mkdir -p _output/linux
|
||||||
GOOS=linux GOARCH=amd64 go build -tags "sqlite_foreign_keys release linux" -ldflags="$(GO_LDFLAGS)" -o _output/linux/yarr src/main.go
|
GOOS=linux GOARCH=amd64 go build -tags "sqlite_foreign_keys linux" -ldflags="$(GO_LDFLAGS)" -o _output/linux/yarr ./cmd/yarr
|
||||||
|
|
||||||
build_windows:
|
build_windows:
|
||||||
mkdir -p _output/windows
|
mkdir -p _output/windows
|
||||||
go run bin/generate_versioninfo.go -version "$(VERSION)" -outfile src/platform/versioninfo.rc
|
go run ./cmd/generate_versioninfo -version "$(VERSION)" -outfile src/platform/versioninfo.rc
|
||||||
windres -i src/platform/versioninfo.rc -O coff -o src/platform/versioninfo.syso
|
windres -i src/platform/versioninfo.rc -O coff -o src/platform/versioninfo.syso
|
||||||
GOOS=windows GOARCH=amd64 go build -tags "sqlite_foreign_keys release windows" -ldflags="$(GO_LDFLAGS) -H windowsgui" -o _output/windows/yarr.exe src/main.go
|
GOOS=windows GOARCH=amd64 go build -tags "sqlite_foreign_keys windows" -ldflags="$(GO_LDFLAGS) -H windowsgui" -o _output/windows/yarr.exe ./cmd/yarr
|
||||||
|
|
||||||
serve:
|
serve:
|
||||||
go run -tags "sqlite_foreign_keys" src/main.go -db local.db
|
go run -tags "sqlite_foreign_keys" ./cmd/yarr -db local.db
|
||||||
|
|
||||||
test:
|
test:
|
||||||
cd src && go test -tags "sqlite_foreign_keys release" ./...
|
cd src && go test -tags "sqlite_foreign_keys" ./...
|
||||||
|
30
readme.md
30
readme.md
@ -10,27 +10,29 @@ The app is a single binary with an embedded database (SQLite).
|
|||||||
## usage
|
## usage
|
||||||
|
|
||||||
The latest prebuilt binaries for Linux/MacOS/Windows AMD64 are available
|
The latest prebuilt binaries for Linux/MacOS/Windows AMD64 are available
|
||||||
[here](https://github.com/nkanaev/yarr/releases/latest).
|
[here](https://github.com/nkanaev/yarr/releases/latest). Installation instructions:
|
||||||
|
|
||||||
### macos
|
* MacOS
|
||||||
|
|
||||||
Download `yarr-*-macos64.zip`, unzip it, place `yarr.app` in `/Applications` folder, [open the app][macos-open], click the anchor menu bar icon, select "Open".
|
Download `yarr-*-macos64.zip`, unzip it, place `yarr.app` in `/Applications` folder, [open the app][macos-open], click the anchor menu bar icon, select "Open".
|
||||||
|
|
||||||
|
* Windows
|
||||||
|
|
||||||
|
Download `yarr-*-windows64.zip`, unzip it, open `yarr.exe`, click the anchor system tray icon, select "Open".
|
||||||
|
|
||||||
|
* Linux
|
||||||
|
|
||||||
|
Download `yarr-*-linux64.zip`, unzip it, place `yarr` in `$HOME/.local/bin`
|
||||||
|
and run [the script](etc/install-linux.sh).
|
||||||
|
|
||||||
[macos-open]: https://support.apple.com/en-gb/guide/mac-help/mh40616/mac
|
[macos-open]: https://support.apple.com/en-gb/guide/mac-help/mh40616/mac
|
||||||
|
|
||||||
### windows
|
|
||||||
|
|
||||||
Download `yarr-*-windows64.zip`, unzip it, open `yarr.exe`, click the anchor system tray icon, select "Open".
|
|
||||||
|
|
||||||
### linux
|
|
||||||
|
|
||||||
Download `yarr-*-linux64.zip`, unzip it, place `yarr` in `$HOME/.local/bin`
|
|
||||||
and run [the script](etc/install-linux.sh).
|
|
||||||
|
|
||||||
For self-hosting, see `yarr -h` for auth, tls & server configuration flags.
|
For self-hosting, see `yarr -h` for auth, tls & server configuration flags.
|
||||||
For building from source code, see [build.md](build.md)
|
|
||||||
|
|
||||||
For Fever API support, see [fever.md](fever.md).
|
See more:
|
||||||
|
|
||||||
|
* [Building from source code](doc/build.md)
|
||||||
|
* [Fever API support](doc/fever.md)
|
||||||
|
|
||||||
## credits
|
## credits
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
//go:build release
|
|
||||||
// +build release
|
|
||||||
|
|
||||||
package assets
|
package assets
|
||||||
|
|
||||||
import "embed"
|
import "embed"
|
||||||
|
@ -47,6 +47,8 @@ type atomLinks []atomLink
|
|||||||
func (a *atomText) Text() string {
|
func (a *atomText) Text() string {
|
||||||
if a.Type == "html" {
|
if a.Type == "html" {
|
||||||
return htmlutil.ExtractText(a.Data)
|
return htmlutil.ExtractText(a.Data)
|
||||||
|
} else if a.Type == "xhtml" {
|
||||||
|
return htmlutil.ExtractText(a.XML)
|
||||||
}
|
}
|
||||||
return a.Data
|
return a.Data
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,44 @@ func TestAtomHTMLTitle(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAtomXHTMLTitle(t *testing.T) {
|
||||||
|
feed, _ := Parse(strings.NewReader(`
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
<entry><title type="xhtml">say <code>what</code>?</entry>
|
||||||
|
</feed>
|
||||||
|
`))
|
||||||
|
have := feed.Items[0].Title
|
||||||
|
want := "say what?"
|
||||||
|
if !reflect.DeepEqual(want, have) {
|
||||||
|
t.Logf("want: %#v", want)
|
||||||
|
t.Logf("have: %#v", have)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAtomXHTMLNestedTitle(t *testing.T) {
|
||||||
|
feed, _ := Parse(strings.NewReader(`
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
||||||
|
<entry>
|
||||||
|
<title type="xhtml">
|
||||||
|
<div xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<a href="https://example.com">Link to Example</a>
|
||||||
|
</div>
|
||||||
|
</title>
|
||||||
|
</entry>
|
||||||
|
</feed>
|
||||||
|
`))
|
||||||
|
have := feed.Items[0].Title
|
||||||
|
want := "Link to Example"
|
||||||
|
if !reflect.DeepEqual(want, have) {
|
||||||
|
t.Logf("want: %#v", want)
|
||||||
|
t.Logf("have: %#v", have)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestAtomImageLink(t *testing.T) {
|
func TestAtomImageLink(t *testing.T) {
|
||||||
feed, _ := Parse(strings.NewReader(`
|
feed, _ := Parse(strings.NewReader(`
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -75,6 +76,25 @@ type MarkFilter struct {
|
|||||||
Before *time.Time
|
Before *time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ItemList []Item
|
||||||
|
|
||||||
|
func (list ItemList) Len() int {
|
||||||
|
return len(list)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list ItemList) SortKey(i int) string {
|
||||||
|
return list[i].Date.Format(time.RFC3339) + "::" + list[i].GUID
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list ItemList) Less(i, j int) bool {
|
||||||
|
return list.SortKey(i) < list.SortKey(j)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (list ItemList) Swap(i, j int) {
|
||||||
|
list[i], list[j] = list[j], list[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (s *Storage) CreateItems(items []Item) bool {
|
func (s *Storage) CreateItems(items []Item) bool {
|
||||||
tx, err := s.db.Begin()
|
tx, err := s.db.Begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -84,7 +104,10 @@ func (s *Storage) CreateItems(items []Item) bool {
|
|||||||
|
|
||||||
now := time.Now().UTC()
|
now := time.Now().UTC()
|
||||||
|
|
||||||
for _, item := range items {
|
itemsSorted := ItemList(items)
|
||||||
|
sort.Sort(itemsSorted)
|
||||||
|
|
||||||
|
for _, item := range itemsSorted {
|
||||||
_, err = tx.Exec(`
|
_, err = tx.Exec(`
|
||||||
insert into items (
|
insert into items (
|
||||||
guid, feed_id, title, link, date,
|
guid, feed_id, title, link, date,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user