Skip to content

Commit b856f14

Browse files
committed
feat: forumer, main logic is written
1 parent 335bcf0 commit b856f14

File tree

6 files changed

+115
-37
lines changed

6 files changed

+115
-37
lines changed

app/discorder/main.go

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type DiscordMessage struct {
5151
ID types.DiscordMessageID
5252
Content string
5353
Timestamp time.Time
54+
Embeds []*discordgo.MessageEmbed
5455
}
5556

5657
func (d Discorder) GetLatestMessages(channelID types.DiscordChannelID) ([]DiscordMessage, error) {
@@ -67,6 +68,7 @@ func (d Discorder) GetLatestMessages(channelID types.DiscordChannelID) ([]Discor
6768
ID: types.DiscordMessageID(msg.ID),
6869
Content: msg.Content,
6970
Timestamp: msg.Timestamp,
71+
Embeds: msg.Embeds,
7072
})
7173
}
7274

@@ -119,37 +121,47 @@ func (d Discorder) GetOwnerID(channelID types.DiscordChannelID) (types.DiscordOw
119121
}
120122

121123
type deduplicator struct {
122-
repeatCheckers []func(msgs []DiscordMessage) bool
124+
dupCheckers []func(msgs []DiscordMessage) bool
123125
}
124126

125-
func NewDeduplicator(checkers ...func(msgs []DiscordMessage) bool) *deduplicator {
127+
type DuplicatedError struct {
128+
}
129+
130+
func (d DuplicatedError) Error() string { return "This msg is duplicated" }
131+
132+
func NewDeduplicator(isDuplicaters ...func(msgs []DiscordMessage) bool) *deduplicator {
126133
d := &deduplicator{
127-
repeatCheckers: checkers,
134+
dupCheckers: isDuplicaters,
128135
}
129136
return d
130137
}
131138

132139
func (d *deduplicator) isDuplicated(msgs []DiscordMessage) bool {
133-
for _, checker := range d.repeatCheckers {
134-
if checker(msgs) {
140+
for _, isDup := range d.dupCheckers {
141+
if isDup(msgs) {
135142
return true
136143
}
137144
}
138145
return false
139146
}
140147

141-
func (dg Discorder) SendDeduplicatedMsg(deduplicator *deduplicator, msg string, channel types.DiscordChannelID) {
142-
logus.Info("sent_message= " + msg)
143-
msgs, err := dg.GetLatestMessages(channel)
148+
func (d Discorder) SendDeduplicatedMsg(
149+
deduplicator *deduplicator,
150+
channel types.DiscordChannelID,
151+
send_callback func(channel types.DiscordChannelID, dg *discordgo.Session) error,
152+
) error {
153+
msgs, err := d.GetLatestMessages(channel)
144154

145155
if logus.CheckError(err, "failed to get discord latest msgs") {
146-
return
156+
return err
147157
}
148158

149159
if deduplicator.isDuplicated(msgs) {
150-
logus.Debug("not sending duplicated", logus.ChannelID(channel), logus.DiscordMessage(msg))
151-
return
160+
logus.Debug("not sending duplicated", logus.ChannelID(channel))
161+
return DuplicatedError{}
152162
}
153163

154-
dg.SengMessage(channel, msg)
164+
err = send_callback(channel, d.dg)
165+
logus.CheckWarn(err, "failed sending message in discorder", logus.ChannelID(channel))
166+
return err
155167
}

app/forumer/forum_post_test.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ func FixtureLatestThread() *forum_types.LatestThread {
2222
}
2323
}
2424

25-
func TestGetDetailedPost(t *testing.T) {
26-
thread := FixtureLatestThread()
27-
25+
func FixtureDetailedRequester() func(mt MethodType, u forum_types.Url) (*QueryResult, error) {
2826
detailed_post_content_filepath := filepath.Join(utils.GetCurrrentFolder(), "test_data", "detailed_post_content.html")
2927
if _, err := os.Stat(detailed_post_content_filepath); err != nil {
3028
query, err := NewQuery("GET", "https://discoverygc.com/forums/showthread.php?tid=200175&action=lastpost")
@@ -39,6 +37,13 @@ func TestGetDetailedPost(t *testing.T) {
3937
ResponseFullUrl: `https://discoverygc.com/forums/showthread.php?tid=200175&pid=2315295#pid2315295`,
4038
}, nil
4139
}
40+
return mocked_requester
41+
}
42+
43+
func TestGetDetailedPost(t *testing.T) {
44+
thread := FixtureLatestThread()
45+
46+
mocked_requester := FixtureDetailedRequester()
4247
detailed_post, err := NewDetailedPostRequester(WithMockedRequester(mocked_requester)).GetDetailedPost(thread)
4348
_ = detailed_post
4449
fmt.Println("err=", err)

app/forumer/forum_threads_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"github.com/stretchr/testify/assert"
1212
)
1313

14-
func TestGetPosts(t *testing.T) {
14+
func FixtureMockedThreadsRequester() func(mt MethodType, u forum_types.Url) (*QueryResult, error) {
1515
thread_post_content_filepath := filepath.Join(utils.GetCurrrentFolder(), "test_data", "latest_threads.html")
1616
if _, err := os.Stat(thread_post_content_filepath); err != nil {
1717
query, err := NewQuery("GET", ThreadPageURL)
@@ -26,8 +26,11 @@ func TestGetPosts(t *testing.T) {
2626
ResponseFullUrl: `https://discoverygc.com/forums/portal.php`,
2727
}, nil
2828
}
29-
30-
threads, err := NewLatestThreads(WithMockedPageRequester(mocked_requester)).GetLatestThreads()
29+
return mocked_requester
30+
}
31+
func TestGetPosts(t *testing.T) {
32+
mocked_threads_requester := FixtureMockedThreadsRequester()
33+
threads, err := NewLatestThreads(WithMockedPageRequester(mocked_threads_requester)).GetLatestThreads()
3134
assert.Nil(t, err, "expected nil as error")
3235
assert.Greater(t, len(threads), 0)
3336
}

app/forumer/forum_types/post.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,3 @@ type Post struct {
1212
PostPermamentLink PostPermamentLink
1313
ThreadFullName ThreadFullName
1414
}
15-
16-
func (p Post) Render() string {
17-
// TODO Write your code
18-
return ""
19-
}

app/forumer/run.go

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@ import (
77
"darkbot/app/forumer/forum_types"
88
"darkbot/app/settings/logus"
99
"darkbot/app/settings/types"
10+
"fmt"
1011
"strings"
1112
"time"
13+
14+
"github.com/bwmarrin/discordgo"
1215
)
1316

17+
type iThreadsRequester interface {
18+
GetLatestThreads(opts ...threadPageParam) ([]*forum_types.LatestThread, error)
19+
}
1420
type Forumer struct {
1521
Discorder discorder.Discorder
1622
*configurator.Configurators
17-
threads_requester *ThreadsRequester
23+
threads_requester iThreadsRequester
1824
post_requester *PostRequester
1925

2026
cache map[ThreadCacheKey]*forum_types.Post
@@ -33,11 +39,11 @@ func NewThreadCacheKey(thread *forum_types.LatestThread) ThreadCacheKey {
3339
type forumerParam func(forum *Forumer)
3440

3541
func WithThreadsRequester(
36-
threads_page_requester *ThreadsRequester) forumerParam {
42+
threads_page_requester iThreadsRequester) forumerParam {
3743
return func(forum *Forumer) { forum.threads_requester = threads_page_requester }
3844
}
39-
func WithDetailedPostRequest(threads_page_requester *ThreadsRequester) forumerParam {
40-
return func(forum *Forumer) { forum.threads_requester = threads_page_requester }
45+
func WithDetailedPostRequest(post_requester *PostRequester) forumerParam {
46+
return func(forum *Forumer) { forum.post_requester = post_requester }
4147
}
4248

4349
func NewForumer(dbpath types.Dbpath, opts ...forumerParam) *Forumer {
@@ -47,6 +53,7 @@ func NewForumer(dbpath types.Dbpath, opts ...forumerParam) *Forumer {
4753
Configurators: configurator.NewConfigugurators(dbpath),
4854
threads_requester: NewLatestThreads(),
4955
post_requester: NewDetailedPostRequester(),
56+
cache: make(map[ThreadCacheKey]*forum_types.Post),
5057
}
5158

5259
for _, opt := range opts {
@@ -90,9 +97,7 @@ func (v *Forumer) update() {
9097
}
9198

9299
for _, thread := range threads {
93-
94100
v.GetPost(thread, func(new_post *forum_types.Post) {
95-
// Insert code to push post to channels
96101
for _, channel := range channelIDs {
97102
watch_tags, err := v.Forum.Watch.TagsList(channel)
98103
if logus.CheckDebug(err, "failed to get watch tags") {
@@ -121,18 +126,36 @@ func (v *Forumer) update() {
121126
continue
122127
}
123128

124-
// Check against deduplication
129+
duplication_checker := discorder.NewDeduplicator(func(msgs []discorder.DiscordMessage) bool {
130+
for _, msg := range msgs {
131+
content := msg.Content
132+
for _, embed := range msg.Embeds {
133+
content += embed.Description
134+
}
135+
136+
if strings.Contains(content, string(new_post.PostID)) &&
137+
strings.Contains(content, string(new_post.ThreadID)) {
138+
return true
139+
}
140+
}
141+
return false
142+
})
125143
v.Discorder.SendDeduplicatedMsg(
126-
discorder.NewDeduplicator(),
127-
new_post.Render(),
128-
channel,
129-
)
144+
duplication_checker, channel, func(channel types.DiscordChannelID, dg *discordgo.Session) error {
145+
dg_msg := &discordgo.MessageSend{Embed: &discordgo.MessageEmbed{}}
146+
dg_msg.Embed.Title = `✉️ You've got mail`
147+
dg_msg.Embed.Timestamp = string(new_post.LastUpdated)
148+
149+
var content strings.Builder
150+
content.WriteString(fmt.Sprintf("New post in [%s](<%s>)\n", new_post.ThreadFullName, new_post.PostPermamentLink))
151+
content.WriteString(fmt.Sprintf("Topic started by [%s](<%s>)", new_post.PostAuthorName, new_post.PostAuthorLink))
152+
content.WriteString(fmt.Sprintf("```%s```", new_post.PostContent[:600]))
153+
dg_msg.Embed.Description = content.String()
154+
return nil
155+
})
130156
}
131-
132157
})
133158
}
134-
135-
_ = channelIDs
136159
}
137160

138161
func (v *Forumer) Run() {

app/forumer/run_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,41 @@
11
package forumer
2+
3+
import (
4+
"darkbot/app/configurator"
5+
"darkbot/app/forumer/forum_types"
6+
"darkbot/app/settings/logus"
7+
"darkbot/app/settings/types"
8+
"testing"
9+
)
10+
11+
type MockedThreadsQuery struct {
12+
threads []*forum_types.LatestThread
13+
}
14+
15+
func (m MockedThreadsQuery) GetLatestThreads(opts ...threadPageParam) ([]*forum_types.LatestThread, error) {
16+
return m.threads, nil
17+
}
18+
19+
func newMockedThreadsQuery() MockedThreadsQuery {
20+
mocked_threads_requester := FixtureMockedThreadsRequester()
21+
threads_requester := NewLatestThreads(WithMockedPageRequester(mocked_threads_requester))
22+
threads, err := threads_requester.GetLatestThreads()
23+
logus.CheckFatal(err, "unexpected error from GetLatestThreads")
24+
one_thread := threads[:1]
25+
return MockedThreadsQuery{threads: one_thread}
26+
}
27+
28+
func TestForumerSending(t *testing.T) {
29+
30+
mocked_post_requester := FixtureDetailedRequester()
31+
configurator.FixtureMigrator(func(dbpath types.Dbpath) {
32+
forum := NewForumer(
33+
dbpath,
34+
WithThreadsRequester(newMockedThreadsQuery()),
35+
WithDetailedPostRequest(NewDetailedPostRequester(WithMockedRequester(mocked_post_requester))),
36+
)
37+
38+
forum.update()
39+
})
40+
41+
}

0 commit comments

Comments
 (0)