1
0
mirror of https://github.com/mrusme/neonmodem.git synced 2024-11-03 04:27:16 -05:00
neonmodem/system/hackernews/hackernews.go

272 lines
4.9 KiB
Go
Raw Normal View History

2022-12-31 12:30:26 -05:00
package hackernews
import (
"context"
"errors"
"fmt"
2022-12-31 12:30:26 -05:00
"strconv"
"time"
2022-12-31 13:50:55 -05:00
md "github.com/JohannesKaufmann/html-to-markdown"
2022-12-31 12:30:26 -05:00
hn "github.com/hermanschaaf/hackernews"
"github.com/mrusme/gobbs/models/author"
"github.com/mrusme/gobbs/models/forum"
"github.com/mrusme/gobbs/models/post"
"github.com/mrusme/gobbs/models/reply"
"github.com/mrusme/gobbs/system/adapter"
"go.uber.org/zap"
)
type System struct {
ID int
2022-12-31 12:30:26 -05:00
config map[string]interface{}
logger *zap.SugaredLogger
client *hn.Client
}
func (sys *System) GetID() int {
return sys.ID
}
func (sys *System) SetID(id int) {
sys.ID = id
}
2022-12-31 12:30:26 -05:00
func (sys *System) GetConfig() map[string]interface{} {
return sys.config
}
func (sys *System) SetConfig(cfg *map[string]interface{}) {
sys.config = *cfg
}
func (sys *System) SetLogger(logger *zap.SugaredLogger) {
sys.logger = logger
}
2023-01-05 00:23:25 -05:00
func (sys *System) GetCapabilities() adapter.Capabilities {
2022-12-31 12:30:26 -05:00
var caps []adapter.Capability
2023-01-05 00:04:20 -05:00
caps = append(caps,
adapter.Capability{
ID: "list:posts",
Name: "List Posts",
},
adapter.Capability{
ID: "list:replies",
Name: "List Replies",
},
)
2022-12-31 12:30:26 -05:00
return caps
}
func (sys *System) FilterValue() string {
return fmt.Sprintf(
"Hacker News https://news.ycombinator.com",
)
}
func (sys *System) Title() string {
2023-01-04 23:59:37 -05:00
return "news.ycombinator.com"
}
func (sys *System) Description() string {
return fmt.Sprintf(
"Hacker News",
)
}
2022-12-31 12:30:26 -05:00
func (sys *System) Load() error {
sys.client = hn.NewClient()
return nil
}
2023-01-05 11:43:52 -05:00
func (sys *System) ListForums() ([]forum.Forum, error) {
return []forum.Forum{
{
ID: "top",
Name: "Top HN Stories",
SysIDX: sys.ID,
},
{
ID: "best",
Name: "Best HN Stories",
SysIDX: sys.ID,
},
{
ID: "new",
Name: "New HN Stories",
SysIDX: sys.ID,
},
{
ID: "ask",
Name: "Ask HN",
SysIDX: sys.ID,
},
{
ID: "show",
Name: "Show HN",
SysIDX: sys.ID,
},
{
ID: "jobs",
Name: "Jobs HN",
SysIDX: sys.ID,
},
}, nil
}
func (sys *System) ListPosts(forumID string) ([]post.Post, error) {
var stories []int
var err error
switch forumID {
case "top":
stories, err = sys.client.TopStories(context.Background())
case "best":
stories, err = sys.client.BestStories(context.Background())
case "ask":
stories, err = sys.client.AskStories(context.Background())
case "show":
stories, err = sys.client.ShowStories(context.Background())
case "jobs":
stories, err = sys.client.JobStories(context.Background())
default:
stories, err = sys.client.NewStories(context.Background())
}
2022-12-31 12:30:26 -05:00
if err != nil {
return []post.Post{}, err
}
2022-12-31 13:50:55 -05:00
converter := md.NewConverter("", true, nil)
2022-12-31 12:30:26 -05:00
var models []post.Post
for _, story := range stories[0:10] {
i, err := sys.client.GetItem(context.Background(), story)
if err != nil {
sys.logger.Error(err)
continue
}
t := "post"
body := i.Text
if i.URL != "" {
t = "url"
body = i.URL
2022-12-31 13:50:55 -05:00
} else {
bodyMd, err := converter.ConvertString(i.Text)
if err == nil {
body = bodyMd
}
2022-12-31 12:30:26 -05:00
}
createdAt := time.Unix(int64(i.Time), 0)
lastCommentedAt := createdAt
var replies []reply.Reply
for _, commentID := range i.Kids {
replies = append(replies, reply.Reply{
ID: strconv.Itoa(commentID),
})
}
models = append(models, post.Post{
ID: strconv.Itoa(i.ID),
Subject: i.Title,
Body: body,
Type: t,
Pinned: false,
Closed: i.Deleted,
CreatedAt: createdAt,
LastCommentedAt: lastCommentedAt,
Author: author.Author{
ID: i.By,
Name: i.By,
},
Forum: forum.Forum{
ID: "new",
Name: "New",
2023-01-05 11:43:52 -05:00
SysIDX: sys.ID,
2022-12-31 12:30:26 -05:00
},
Replies: replies,
SysIDX: sys.ID,
2022-12-31 12:30:26 -05:00
})
}
return models, nil
}
func (sys *System) LoadPost(p *post.Post) error {
2022-12-31 13:50:55 -05:00
return sys.loadReplies(&p.Replies)
}
func (sys *System) loadReplies(replies *[]reply.Reply) error {
2022-12-31 13:50:55 -05:00
converter := md.NewConverter("", true, nil)
for r := 0; r < len(*replies); r++ {
re := &(*replies)[r]
2022-12-31 12:30:26 -05:00
id, err := strconv.Atoi(re.ID)
2022-12-31 12:30:26 -05:00
if err != nil {
sys.logger.Error(err)
continue
}
i, err := sys.client.GetItem(context.Background(), id)
if err != nil {
sys.logger.Error(err)
continue
}
if i.Deleted || i.Dead {
re.Deleted = true
}
2022-12-31 12:30:26 -05:00
createdAt := time.Unix(int64(i.Time), 0)
re.Body = i.Text
2022-12-31 13:50:55 -05:00
bodyMd, err := converter.ConvertString(i.Text)
if err == nil {
re.Body = bodyMd
}
2022-12-31 12:30:26 -05:00
re.CreatedAt = createdAt
2022-12-31 12:30:26 -05:00
re.Author = author.Author{
2022-12-31 12:30:26 -05:00
ID: i.By,
Name: i.By,
}
re.SysIDX = sys.ID
for _, commentID := range i.Kids {
re.Replies = append(re.Replies, reply.Reply{
ID: strconv.Itoa(commentID),
})
}
if err := sys.loadReplies(&re.Replies); err != nil {
sys.logger.Error(err)
}
2022-12-31 12:30:26 -05:00
}
2022-12-31 12:30:26 -05:00
return nil
}
func (sys *System) CreatePost(p *post.Post) error {
return errors.New("Sorry, this feature isn't available yet for Hacker News!")
}
func (sys *System) CreateReply(r *reply.Reply) error {
return errors.New("Sorry, this feature isn't available yet for Hacker News!")
}