mirror of
https://github.com/glanceapp/glance.git
synced 2024-12-23 23:49:28 +01:00
Allow using alternative links for YT, HN and reddit
This commit is contained in:
parent
d5d6103327
commit
44a153d30a
@ -434,6 +434,7 @@ Preview:
|
||||
| ---- | ---- | -------- | ------- |
|
||||
| channels | array | yes | |
|
||||
| limit | integer | no | 25 |
|
||||
| video-url-template | string | no | https://www.youtube.com/watch?v={VIDEO-ID} |
|
||||
|
||||
##### `channels`
|
||||
A list of channel IDs. One way of getting the ID of a channel is going to the channel's page and clicking on its description:
|
||||
@ -447,6 +448,17 @@ Then scroll down and click on "Share channel", then "Copy channel ID":
|
||||
##### `limit`
|
||||
The maximum number of videos to show.
|
||||
|
||||
##### `video-url-template`
|
||||
Used to replace the default link for videos. Useful when you're running your own YouTube front-end. Example:
|
||||
|
||||
```yaml
|
||||
video-url-template: https://invidious.your-domain.com/watch?v={VIDEO-ID}
|
||||
```
|
||||
|
||||
Placeholders:
|
||||
|
||||
`{VIDEO-ID}` - the ID of the video
|
||||
|
||||
### Hacker News
|
||||
Display a list of posts from [Hacker News](https://news.ycombinator.com/).
|
||||
|
||||
@ -466,6 +478,19 @@ Preview:
|
||||
| ---- | ---- | -------- | ------- |
|
||||
| limit | integer | no | 15 |
|
||||
| collapse-after | integer | no | 5 |
|
||||
| comments-url-template | string | no | https://news.ycombinator.com/item?id={POST-ID} |
|
||||
|
||||
##### `comments-url-template`
|
||||
Used to replace the default link for post comments. Useful if you want to use an alternative front-end. Example:
|
||||
|
||||
```yaml
|
||||
comments-url-template: https://www.hckrnws.com/stories/{POST-PATH}
|
||||
```
|
||||
|
||||
Placeholders:
|
||||
|
||||
`{POST-ID}` - the ID of the post
|
||||
|
||||
|
||||
### Reddit
|
||||
Display a list of posts from a specific subreddit.
|
||||
@ -488,6 +513,7 @@ Example:
|
||||
| style | string | no | vertical-list |
|
||||
| limit | integer | no | 15 |
|
||||
| collapse-after | integer | no | 5 |
|
||||
| comments-url-template | string | no | https://www.reddit.com/{POST-PATH} |
|
||||
|
||||
##### `subreddit`
|
||||
The subreddit for which to fetch the posts from.
|
||||
@ -513,6 +539,25 @@ The maximum number of posts to show.
|
||||
##### `collapse-after`
|
||||
How many posts are visible before the "SHOW MORE" button appears. Set to `-1` to never collapse. Not available when using the `vertical-cards` and `horizontal-cards` styles.
|
||||
|
||||
##### `comments-url-template`
|
||||
Used to replace the default link for post comments. Useful if you want to use the old Reddit design or any other 3rd party front-end. Example:
|
||||
|
||||
```yaml
|
||||
comments-url-template: https://old.reddit.com/{POST-PATH}
|
||||
```
|
||||
|
||||
Placeholders:
|
||||
|
||||
`{POST-PATH}` - the full path to the post, such as:
|
||||
|
||||
```
|
||||
r/selfhosted/comments/bsp01i/welcome_to_rselfhosted_please_read_this_first/
|
||||
```
|
||||
|
||||
`{POST-ID}` - the ID that comes after `/comments/`
|
||||
|
||||
`{SUBREDDIT}` - the subreddit name
|
||||
|
||||
### Weather
|
||||
Display weather information for a specific location. The data is provided by https://open-meteo.com/.
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -28,7 +29,7 @@ func getHackerNewsTopPostIds() ([]int, error) {
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func getHackerNewsPostsFromIds(postIds []int) (ForumPosts, error) {
|
||||
func getHackerNewsPostsFromIds(postIds []int, commentsUrlTemplate string) (ForumPosts, error) {
|
||||
requests := make([]*http.Request, len(postIds))
|
||||
|
||||
for i, id := range postIds {
|
||||
@ -52,9 +53,17 @@ func getHackerNewsPostsFromIds(postIds []int) (ForumPosts, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
var commentsUrl string
|
||||
|
||||
if commentsUrlTemplate == "" {
|
||||
commentsUrl = "https://news.ycombinator.com/item?id=" + strconv.Itoa(results[i].Id)
|
||||
} else {
|
||||
commentsUrl = strings.ReplaceAll(commentsUrlTemplate, "{POST-ID}", strconv.Itoa(results[i].Id))
|
||||
}
|
||||
|
||||
posts = append(posts, ForumPost{
|
||||
Title: results[i].Title,
|
||||
DiscussionUrl: "https://news.ycombinator.com/item?id=" + strconv.Itoa(results[i].Id),
|
||||
DiscussionUrl: commentsUrl,
|
||||
TargetUrl: results[i].TargetUrl,
|
||||
TargetUrlDomain: extractDomainFromUrl(results[i].TargetUrl),
|
||||
CommentCount: results[i].CommentCount,
|
||||
@ -74,7 +83,7 @@ func getHackerNewsPostsFromIds(postIds []int) (ForumPosts, error) {
|
||||
return posts, nil
|
||||
}
|
||||
|
||||
func FetchHackerNewsTopPosts(limit int) (ForumPosts, error) {
|
||||
func FetchHackerNewsTopPosts(limit int, commentsUrlTemplate string) (ForumPosts, error) {
|
||||
postIds, err := getHackerNewsTopPostIds()
|
||||
|
||||
if err != nil {
|
||||
@ -85,5 +94,5 @@ func FetchHackerNewsTopPosts(limit int) (ForumPosts, error) {
|
||||
postIds = postIds[:limit]
|
||||
}
|
||||
|
||||
return getHackerNewsPostsFromIds(postIds)
|
||||
return getHackerNewsPostsFromIds(postIds, commentsUrlTemplate)
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"html"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -12,6 +13,7 @@ type subredditResponseJson struct {
|
||||
Data struct {
|
||||
Children []struct {
|
||||
Data struct {
|
||||
Id string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Upvotes int `json:"ups"`
|
||||
Url string `json:"url"`
|
||||
@ -28,7 +30,7 @@ type subredditResponseJson struct {
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func FetchSubredditPosts(subreddit string) (ForumPosts, error) {
|
||||
func FetchSubredditPosts(subreddit string, commentsUrlTemplate string) (ForumPosts, error) {
|
||||
requestUrl := fmt.Sprintf("https://www.reddit.com/r/%s/hot.json", url.QueryEscape(subreddit))
|
||||
request, err := http.NewRequest("GET", requestUrl, nil)
|
||||
|
||||
@ -57,9 +59,19 @@ func FetchSubredditPosts(subreddit string) (ForumPosts, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
var commentsUrl string
|
||||
|
||||
if commentsUrlTemplate == "" {
|
||||
commentsUrl = "https://www.reddit.com" + post.Permalink
|
||||
} else {
|
||||
commentsUrl = strings.ReplaceAll(commentsUrlTemplate, "{SUBREDDIT}", subreddit)
|
||||
commentsUrl = strings.ReplaceAll(commentsUrl, "{POST-ID}", post.Id)
|
||||
commentsUrl = strings.ReplaceAll(commentsUrl, "{POST-PATH}", strings.TrimLeft(post.Permalink, "/"))
|
||||
}
|
||||
|
||||
forumPost := ForumPost{
|
||||
Title: html.UnescapeString(post.Title),
|
||||
DiscussionUrl: "https://www.reddit.com" + post.Permalink,
|
||||
DiscussionUrl: commentsUrl,
|
||||
TargetUrlDomain: post.Domain,
|
||||
CommentCount: post.CommentsCount,
|
||||
Score: post.Upvotes,
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -38,7 +39,7 @@ func parseYoutubeFeedTime(t string) time.Time {
|
||||
return parsedTime
|
||||
}
|
||||
|
||||
func FetchYoutubeChannelUploads(channelIds []string) (Videos, error) {
|
||||
func FetchYoutubeChannelUploads(channelIds []string, videoUrlTemplate string) (Videos, error) {
|
||||
requests := make([]*http.Request, 0, len(channelIds))
|
||||
|
||||
for i := range channelIds {
|
||||
@ -75,10 +76,24 @@ func FetchYoutubeChannelUploads(channelIds []string) (Videos, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
var videoUrl string
|
||||
|
||||
if videoUrlTemplate == "" {
|
||||
videoUrl = video.Link.Href
|
||||
} else {
|
||||
parsedUrl, err := url.Parse(video.Link.Href)
|
||||
|
||||
if err == nil {
|
||||
videoUrl = strings.ReplaceAll(videoUrlTemplate, "{VIDEO-ID}", parsedUrl.Query().Get("v"))
|
||||
} else {
|
||||
videoUrl = "#"
|
||||
}
|
||||
}
|
||||
|
||||
videos = append(videos, Video{
|
||||
ThumbnailUrl: video.Group.Thumbnail.Url,
|
||||
Title: video.Title,
|
||||
Url: video.Link.Href,
|
||||
Url: videoUrl,
|
||||
Author: response.Channel,
|
||||
AuthorUrl: response.ChannelLink.Href + "/videos",
|
||||
TimePosted: parseYoutubeFeedTime(video.Published),
|
||||
|
@ -10,10 +10,11 @@ import (
|
||||
)
|
||||
|
||||
type HackerNews struct {
|
||||
widgetBase `yaml:",inline"`
|
||||
Posts feed.ForumPosts `yaml:"-"`
|
||||
Limit int `yaml:"limit"`
|
||||
CollapseAfter int `yaml:"collapse-after"`
|
||||
widgetBase `yaml:",inline"`
|
||||
Posts feed.ForumPosts `yaml:"-"`
|
||||
Limit int `yaml:"limit"`
|
||||
CollapseAfter int `yaml:"collapse-after"`
|
||||
CommentsUrlTemplate string `yaml:"comments-url-template"`
|
||||
}
|
||||
|
||||
func (widget *HackerNews) Initialize() error {
|
||||
@ -31,7 +32,7 @@ func (widget *HackerNews) Initialize() error {
|
||||
}
|
||||
|
||||
func (widget *HackerNews) Update(ctx context.Context) {
|
||||
posts, err := feed.FetchHackerNewsTopPosts(40)
|
||||
posts, err := feed.FetchHackerNewsTopPosts(40, widget.CommentsUrlTemplate)
|
||||
|
||||
if !widget.canContinueUpdateAfterHandlingErr(err) {
|
||||
return
|
||||
|
@ -11,12 +11,13 @@ import (
|
||||
)
|
||||
|
||||
type Reddit struct {
|
||||
widgetBase `yaml:",inline"`
|
||||
Posts feed.ForumPosts `yaml:"-"`
|
||||
Subreddit string `yaml:"subreddit"`
|
||||
Style string `yaml:"style"`
|
||||
Limit int `yaml:"limit"`
|
||||
CollapseAfter int `yaml:"collapse-after"`
|
||||
widgetBase `yaml:",inline"`
|
||||
Posts feed.ForumPosts `yaml:"-"`
|
||||
Subreddit string `yaml:"subreddit"`
|
||||
Style string `yaml:"style"`
|
||||
CommentsUrlTemplate string `yaml:"comments-url-template"`
|
||||
Limit int `yaml:"limit"`
|
||||
CollapseAfter int `yaml:"collapse-after"`
|
||||
}
|
||||
|
||||
func (widget *Reddit) Initialize() error {
|
||||
@ -38,7 +39,7 @@ func (widget *Reddit) Initialize() error {
|
||||
}
|
||||
|
||||
func (widget *Reddit) Update(ctx context.Context) {
|
||||
posts, err := feed.FetchSubredditPosts(widget.Subreddit)
|
||||
posts, err := feed.FetchSubredditPosts(widget.Subreddit, widget.CommentsUrlTemplate)
|
||||
|
||||
if !widget.canContinueUpdateAfterHandlingErr(err) {
|
||||
return
|
||||
|
@ -10,10 +10,11 @@ import (
|
||||
)
|
||||
|
||||
type Videos struct {
|
||||
widgetBase `yaml:",inline"`
|
||||
Videos feed.Videos `yaml:"-"`
|
||||
Channels []string `yaml:"channels"`
|
||||
Limit int `yaml:"limit"`
|
||||
widgetBase `yaml:",inline"`
|
||||
Videos feed.Videos `yaml:"-"`
|
||||
VideoUrlTemplate string `yaml:"video-url-template"`
|
||||
Channels []string `yaml:"channels"`
|
||||
Limit int `yaml:"limit"`
|
||||
}
|
||||
|
||||
func (widget *Videos) Initialize() error {
|
||||
@ -27,7 +28,7 @@ func (widget *Videos) Initialize() error {
|
||||
}
|
||||
|
||||
func (widget *Videos) Update(ctx context.Context) {
|
||||
videos, err := feed.FetchYoutubeChannelUploads(widget.Channels)
|
||||
videos, err := feed.FetchYoutubeChannelUploads(widget.Channels, widget.VideoUrlTemplate)
|
||||
|
||||
if !widget.canContinueUpdateAfterHandlingErr(err) {
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user