diff --git a/INSTALL.md b/INSTALL.md
index ef978da..035a857 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -21,7 +21,6 @@ Place a `config.json` file in the same directory that looks like this: (below ar
"port": 1337,
"host": "localhost",
"token": "miauwkes",
- "utcOffset": 60,
"allowedWebmentionSources": [
"brainbaking.com",
"jefklakscodex.com"
@@ -38,7 +37,6 @@ Place a `config.json` file in the same directory that looks like this: (below ar
- port, host: http server params
- token, allowedWebmentionSources: see below, used for authentication
- blacklist/whitelist: domains from which we do (NOT) send to or accept mentions from.
-- utcOffset: offset in minutes for date processing, starting from UTC time.
If a config file is missing, or required keys are missing, a warning will be generated and default values will be used instead. See `common/config.go`.
diff --git a/README.md b/README.md
index ef5cf77..3fb67c9 100644
--- a/README.md
+++ b/README.md
@@ -200,6 +200,8 @@ Each mention has to be manually approved. An e-mail to `localhost:25` (a local P
Approved mentions will have their domain added to the whitelist. Rejected mentions will have their domain added to the blacklist.
+Read more about how spam moderation works at https://brainbaking.com/post/2022/04/fighting-webmention-and-pingback-spam/
+
### Manually blacklisting partial domains
In that case, simply add the domain to the `blacklist` in `config.json`.
diff --git a/app/admin/dashboard.html b/app/admin/dashboard.html
index 94afb9f..99662c9 100644
--- a/app/admin/dashboard.html
+++ b/app/admin/dashboard.html
@@ -24,7 +24,7 @@
Mentions To Approve
{{ range $domain, $mentions := .Mentions }}
- 🌐 Domain {{ $domain }} »
+
{{ if $mentions }}
diff --git a/app/admin/handler.go b/app/admin/handler.go
index 5437aeb..a6c2162 100644
--- a/app/admin/handler.go
+++ b/app/admin/handler.go
@@ -28,9 +28,14 @@ type dashboardMention struct {
RejectURL string
}
+type domainMention struct {
+ Name string
+ MentionsURL string
+}
+
type dashboardData struct {
Config string
- Mentions map[string][]dashboardMention
+ Mentions map[domainMention][]dashboardMention
}
type dashboardModerated struct {
@@ -62,10 +67,14 @@ func indiewebDataToDashboardMention(c *common.Config, dbMentions []*mf.IndiewebD
func getDashboardData(c *common.Config, repo db.MentionRepo) *dashboardData {
data := &dashboardData{
Config: c.String(),
- Mentions: map[string][]dashboardMention{},
+ Mentions: map[domainMention][]dashboardMention{},
}
for _, domain := range c.AllowedWebmentionSources {
- data.Mentions[domain] = indiewebDataToDashboardMention(c, repo.GetAllToModerate(domain).Data)
+ domainKey := domainMention{
+ Name: domain,
+ MentionsURL: fmt.Sprintf("%swebmention/%s/%s", c.BaseURL, domain, c.Token),
+ }
+ data.Mentions[domainKey] = indiewebDataToDashboardMention(c, repo.GetAllToModerate(domain).Data)
}
return data
diff --git a/app/mf/microformats.go b/app/mf/microformats.go
index 9e34431..542eba4 100644
--- a/app/mf/microformats.go
+++ b/app/mf/microformats.go
@@ -92,8 +92,8 @@ func (id *IndiewebData) IsEmpty() bool {
return id.Url == ""
}
-func PublishedNow(zone *time.Location) string {
- return common.Now().UTC().In(zone).Format(dateFormatWithTimeZone)
+func PublishedNow() string {
+ return common.Now().UTC().Format(dateFormatWithTimeZone)
}
func shorten(txt string) string {
@@ -174,10 +174,10 @@ func Prop(mf *microformats.Microformat, key string) *microformats.Microformat {
return mfEmpty()
}
-func Published(hEntry *microformats.Microformat, zone *time.Location) string {
+func Published(hEntry *microformats.Microformat) string {
publishedDate := Str(hEntry, "published")
if publishedDate == "" {
- return PublishedNow(zone)
+ return PublishedNow()
}
for _, format := range supportedFormats {
@@ -188,7 +188,7 @@ func Published(hEntry *microformats.Microformat, zone *time.Location) string {
return formatted.Format(dateFormatWithTimeZone)
}
- return PublishedNow(zone)
+ return PublishedNow()
}
func NewAuthor(hEntry *microformats.Microformat, hCard *microformats.Microformat) IndiewebAuthor {
diff --git a/app/mf/microformats_test.go b/app/mf/microformats_test.go
index bc435c9..6eb3f0a 100644
--- a/app/mf/microformats_test.go
+++ b/app/mf/microformats_test.go
@@ -52,6 +52,13 @@ func TestResultFailureEmptyEncodesAsEmptyJSONArray(t *testing.T) {
}
func TestPublished(t *testing.T) {
+ common.Now = func() time.Time {
+ return time.Date(2020, time.January, 1, 12, 30, 0, 0, time.UTC)
+ }
+ nowString := "2020-01-01T12:30:00+00:00"
+ defer func() {
+ common.Now = time.Now
+ }()
cases := []struct {
label string
raw string
@@ -83,14 +90,14 @@ func TestPublished(t *testing.T) {
"2021-04-25T00:00:00+00:00",
},
{
- "Returns current date if property with correct timezone not found",
+ "Returns current UTC date if property with correct timezone not found",
"",
- "2020-01-01T13:30:00+01:00",
+ nowString,
},
{
- "Reverts to current date if not in correct ISO8601 datetime format",
+ "Reverts to current UTC date if not in correct ISO8601 datetime format",
"26 April 2021",
- "2020-01-01T13:30:00+01:00",
+ nowString,
},
{
"https://www.ietf.org/rfc/rfc3339.txt example 1",
@@ -105,12 +112,12 @@ func TestPublished(t *testing.T) {
{
"https://www.ietf.org/rfc/rfc3339.txt example 3 explicitly not implemented",
"1990-12-31T23:59:60Z",
- "2020-01-01T13:30:00+01:00",
+ nowString,
},
{
"https://www.ietf.org/rfc/rfc3339.txt example 4 explicitly not implemented",
"1990-12-31T15:59:60-08:00",
- "2020-01-01T13:30:00+01:00",
+ nowString,
},
{
"https://www.ietf.org/rfc/rfc3339.txt example 5 with seconds ignored",
@@ -118,13 +125,6 @@ func TestPublished(t *testing.T) {
"1937-01-01T12:00:27+00:20",
},
}
- common.Now = func() time.Time {
- return time.Date(2020, time.January, 1, 12, 30, 0, 0, time.UTC)
- }
- utcPlusOne := time.FixedZone("UTC+1", 60*60)
- defer func() {
- common.Now = time.Now
- }()
for _, tc := range cases {
t.Run(tc.label, func(t *testing.T) {
@@ -134,7 +134,7 @@ func TestPublished(t *testing.T) {
}
theTime := Published(µformats.Microformat{
Properties: props,
- }, utcPlusOne)
+ })
assert.Equal(t, tc.expectedTime, theTime)
})
diff --git a/app/server.go b/app/server.go
index 395c242..12c9d71 100644
--- a/app/server.go
+++ b/app/server.go
@@ -3,7 +3,7 @@ package app
import (
"brainbaking.com/go-jamming/db"
"brainbaking.com/go-jamming/rest"
- "github.com/MagnusFrater/helmet"
+ "github.com/goddtriffin/helmet"
"net/http"
"strconv"
"strings"
diff --git a/app/webmention/recv/receive.go b/app/webmention/recv/receive.go
index b4cff68..0cb4b13 100644
--- a/app/webmention/recv/receive.go
+++ b/app/webmention/recv/receive.go
@@ -122,7 +122,7 @@ func (recv *Receiver) parseBodyAsIndiewebSite(hEntry *microformats.Microformat,
Author: mf.NewAuthor(hEntry, hCard),
Content: mf.Content(hEntry),
Url: mf.Url(hEntry, wm.Source),
- Published: mf.Published(hEntry, recv.Conf.Zone()),
+ Published: mf.Published(hEntry),
Source: wm.Source,
Target: wm.Target,
IndiewebType: mf.Type(hEntry),
@@ -137,7 +137,7 @@ func (recv *Receiver) parseBodyAsNonIndiewebSite(body string, wm mf.Mention) *mf
},
Name: title,
Content: title,
- Published: mf.PublishedNow(recv.Conf.Zone()),
+ Published: mf.PublishedNow(),
Url: wm.Source,
IndiewebType: mf.TypeMention,
Source: wm.Source,
diff --git a/common/config.go b/common/config.go
index 1a7b4cb..a1b142c 100644
--- a/common/config.go
+++ b/common/config.go
@@ -8,7 +8,6 @@ import (
"io/fs"
"io/ioutil"
"strings"
- "time"
)
type Config struct {
@@ -17,7 +16,6 @@ type Config struct {
AdminEmail string `json:"adminEmail"`
Port int `json:"port"`
Token string `json:"token"`
- UtcOffset int `json:"utcOffset"`
AllowedWebmentionSources []string `json:"allowedWebmentionSources"`
Blacklist []string `json:"blacklist"`
Whitelist []string `json:"whitelist"`
@@ -39,10 +37,6 @@ func isListedIn(url string, list []string) bool {
return Includes(list, domain)
}
-func (c *Config) Zone() *time.Location {
- return time.FixedZone("local", c.UtcOffset*60)
-}
-
func (c *Config) missingKeys() []string {
keys := []string{}
if c.Port == 0 {
@@ -142,7 +136,6 @@ func defaultConfig() *Config {
BaseURL: "https://jam.brainbaking.com/",
Port: 1337,
Token: "miauwkes",
- UtcOffset: 60,
AllowedWebmentionSources: []string{"brainbaking.com", "jefklakscodex.com"},
Blacklist: []string{"youtube.com"},
Whitelist: []string{"brainbaking.com"},
diff --git a/common/config_test.go b/common/config_test.go
index 1c3e273..0cd6dc1 100644
--- a/common/config_test.go
+++ b/common/config_test.go
@@ -26,7 +26,6 @@ func TestReadFromJsonWithCorrectJsonData(t *testing.T) {
"host": "localhost",
"baseURL": "https://jam.brainbaking.com/",
"token": "miauwkes",
- "utcOffset": 60,
"allowedWebmentionSources": [
"snoopy.be"
],
diff --git a/go.mod b/go.mod
index dddf83c..5a03be1 100644
--- a/go.mod
+++ b/go.mod
@@ -3,13 +3,13 @@ module brainbaking.com/go-jamming
go 1.16
require (
- github.com/MagnusFrater/helmet v1.0.0
+ github.com/goddtriffin/helmet v1.0.2
github.com/gorilla/mux v1.8.0
github.com/hashicorp/go-cleanhttp v0.5.1
github.com/hashicorp/go-retryablehttp v0.6.8
github.com/rs/zerolog v1.21.0
github.com/stretchr/testify v1.7.0
github.com/tidwall/buntdb v1.2.3
- golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
+ golang.org/x/time v0.0.0-20220411224347-583f2d630306
willnorris.com/go/microformats v1.1.1
)
diff --git a/go.sum b/go.sum
index 7c14741..52ee545 100644
--- a/go.sum
+++ b/go.sum
@@ -1,11 +1,11 @@
-github.com/MagnusFrater/helmet v1.0.0 h1:xzKXDZIXg4ik05MCVHZN3mTOc+3Skzm552nujJ5PzYI=
-github.com/MagnusFrater/helmet v1.0.0/go.mod h1:giGWX/jKRWjf+jxEmKOXyBdtz7VmAK3SEbadVV2pdxA=
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/goddtriffin/helmet v1.0.2 h1:iKahg/oRPrDNz6yhE12WL1YoWsd2NJjtCH+zolqxToo=
+github.com/goddtriffin/helmet v1.0.2/go.mod h1:UJAbeAOVaXjrOJPMgVLjoDM5ePko0PJX7C8IUDGsu+k=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
@@ -68,6 +68,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
+golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=