forked from wgroeneveld/go-jamming
had a "Go" at golangci-lint run and fixed a few hickups"
"
This commit is contained in:
parent
80bc4dfe59
commit
3d3f17590e
10
README.md
10
README.md
|
@ -90,6 +90,7 @@ Place a `config.json` file in the same directory that looks like this: (below ar
|
||||||
|
|
||||||
- port, host: http server params
|
- port, host: http server params
|
||||||
- token, allowedWebmentionSources: see below, used for authentication
|
- token, allowedWebmentionSources: see below, used for authentication
|
||||||
|
- disallowedWebmentionDomains: if an URL from that domain is encountered in your feed, ignore it. Does not send mentions to it.
|
||||||
- utcOffset: offset in minutes for date processing, starting from UTC time.
|
- utcOffset: offset in minutes for date processing, starting from UTC time.
|
||||||
- conString: file path to store all mentions and author avatars in a simple key/value store, based on [buntdb](https://github.com/tidwall/buntdb).
|
- conString: file path to store all mentions and author avatars in a simple key/value store, based on [buntdb](https://github.com/tidwall/buntdb).
|
||||||
|
|
||||||
|
@ -122,7 +123,7 @@ This also saves the author picture/avatar locally - if present in the microforma
|
||||||
|
|
||||||
#### 1.2 `GET /webmention/:domain/:token`
|
#### 1.2 `GET /webmention/:domain/:token`
|
||||||
|
|
||||||
Retrieves a JSON array with relevant webmentions stored for that domain. The token should match. See configuration to fiddle with it yourself. Environment variables are supported, although I haven't used them yet.
|
Retrieves a JSON array with relevant webmentions stored for that domain. The token should match. See configuration to fiddle with it yourself.
|
||||||
|
|
||||||
Example response:
|
Example response:
|
||||||
|
|
||||||
|
@ -147,7 +148,12 @@ Example response:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Author picture paths are relative to the jamming server since they're locally stored.
|
A few remarks:
|
||||||
|
|
||||||
|
- `picture`: Author picture paths are relative to the jamming server since they're locally stored.
|
||||||
|
- `published`: This is not processed and simply taken over from the microformat.
|
||||||
|
- `target` is your domain, `source` is... well... the source.
|
||||||
|
- `content`: Does not contain HTML. Automatically capped at 250 characters if needed.
|
||||||
|
|
||||||
#### 1.3 `PUT /webmention/:domain/:token`
|
#### 1.3 `PUT /webmention/:domain/:token`
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (rl *RateLimiter) limiterMiddleware(next http.Handler) http.Handler {
|
||||||
ip := ipFrom(r)
|
ip := ipFrom(r)
|
||||||
limiter := rl.getVisitor(ip)
|
limiter := rl.getVisitor(ip)
|
||||||
|
|
||||||
if limiter.Allow() == false {
|
if !limiter.Allow() {
|
||||||
log.Error().Str("ip", ip).Msg("Someone spamming? Rate limit hit!")
|
log.Error().Str("ip", ip).Msg("Someone spamming? Rate limit hit!")
|
||||||
rest.TooManyRequests(w)
|
rest.TooManyRequests(w)
|
||||||
return
|
return
|
||||||
|
|
|
@ -21,6 +21,13 @@ type IndiewebDataResult struct {
|
||||||
Data []*IndiewebData `json:"json"`
|
Data []*IndiewebData `json:"json"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ResultFailure(data []*IndiewebData) IndiewebDataResult {
|
||||||
|
return IndiewebDataResult{
|
||||||
|
Status: "failure",
|
||||||
|
Data: data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func ResultSuccess(data []*IndiewebData) IndiewebDataResult {
|
func ResultSuccess(data []*IndiewebData) IndiewebDataResult {
|
||||||
return IndiewebDataResult{
|
return IndiewebDataResult{
|
||||||
Status: "success",
|
Status: "success",
|
||||||
|
@ -75,9 +82,9 @@ func Str(mf *microformats.Microformat, key string) string {
|
||||||
// in very weird cases, it could be a map holding a value, like in mf2's "photo"
|
// in very weird cases, it could be a map holding a value, like in mf2's "photo"
|
||||||
valMap, ok2 := val[0].(map[string]string)
|
valMap, ok2 := val[0].(map[string]string)
|
||||||
if !ok2 {
|
if !ok2 {
|
||||||
str = ""
|
return ""
|
||||||
}
|
}
|
||||||
str = valMap["value"]
|
return valMap["value"]
|
||||||
}
|
}
|
||||||
|
|
||||||
return str
|
return str
|
||||||
|
|
|
@ -70,7 +70,7 @@ func ParseFeed(content []byte) (*Rss2, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.Version == "2.0" {
|
if v.Version == "2.0" {
|
||||||
for i, _ := range v.ItemList {
|
for i := range v.ItemList {
|
||||||
if v.ItemList[i].Content != "" {
|
if v.ItemList[i].Content != "" {
|
||||||
v.ItemList[i].Description = v.ItemList[i].Content
|
v.ItemList[i].Description = v.ItemList[i].Content
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ func HandlePut(conf *common.Config, repo db.MentionRepo) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSinceQueryParam(r *http.Request) string {
|
func getSinceQueryParam(r *http.Request) string {
|
||||||
sinceParam, _ := r.URL.Query()["since"]
|
sinceParam := r.URL.Query()["since"]
|
||||||
since := ""
|
since := ""
|
||||||
if len(sinceParam) > 0 {
|
if len(sinceParam) > 0 {
|
||||||
since = sinceParam[0]
|
since = sinceParam[0]
|
||||||
|
|
|
@ -14,8 +14,6 @@ import (
|
||||||
"willnorris.com/go/microformats"
|
"willnorris.com/go/microformats"
|
||||||
)
|
)
|
||||||
|
|
||||||
// used as a "class" to iject dependencies, just to be able to test. Do NOT like htis.
|
|
||||||
// Is there a better way? e.g. in validate, I just pass rest.Client as an arg. Not great either.
|
|
||||||
type Receiver struct {
|
type Receiver struct {
|
||||||
RestClient rest.Client
|
RestClient rest.Client
|
||||||
Conf *common.Config
|
Conf *common.Config
|
||||||
|
|
|
@ -16,10 +16,7 @@ func isValidUrl(url string) bool {
|
||||||
|
|
||||||
func isValidDomain(url string, conf *common.Config) bool {
|
func isValidDomain(url string, conf *common.Config) bool {
|
||||||
_, err := conf.FetchDomain(url)
|
_, err := conf.FetchDomain(url)
|
||||||
if err != nil {
|
return err == nil
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isValidTargetUrl(url string, httpClient rest.Client) bool {
|
func isValidTargetUrl(url string, httpClient rest.Client) bool {
|
||||||
|
|
|
@ -146,7 +146,7 @@ func (r *MentionRepoBunt) GetPicture(domain string) []byte {
|
||||||
|
|
||||||
// GetAll returns a wrapped data result for all mentions for a particular domain.
|
// GetAll returns a wrapped data result for all mentions for a particular domain.
|
||||||
// Intentionally ignores marshal errors, db should be consistent!
|
// Intentionally ignores marshal errors, db should be consistent!
|
||||||
// Warning, this will potentially marshall 10k strings!
|
// Warning, this will potentially marshall 10k strings! See benchmark test.
|
||||||
func (r *MentionRepoBunt) GetAll(domain string) mf.IndiewebDataResult {
|
func (r *MentionRepoBunt) GetAll(domain string) mf.IndiewebDataResult {
|
||||||
var data []*mf.IndiewebData
|
var data []*mf.IndiewebData
|
||||||
err := r.db.View(func(tx *buntdb.Tx) error {
|
err := r.db.View(func(tx *buntdb.Tx) error {
|
||||||
|
@ -160,7 +160,7 @@ func (r *MentionRepoBunt) GetAll(domain string) mf.IndiewebDataResult {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("get all: failed to ascend from view")
|
log.Error().Err(err).Msg("get all: failed to ascend from view")
|
||||||
return mf.IndiewebDataResult{}
|
return mf.ResultFailure(data)
|
||||||
}
|
}
|
||||||
return mf.ResultSuccess(data)
|
return mf.ResultSuccess(data)
|
||||||
}
|
}
|
||||||
|
|
4
main.go
4
main.go
|
@ -20,12 +20,12 @@ func main() {
|
||||||
|
|
||||||
// logs by default to Stderr (/var/log/syslog). Rolling files possible via lumberjack.
|
// logs by default to Stderr (/var/log/syslog). Rolling files possible via lumberjack.
|
||||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||||
if *verboseFlag == true || *migrateFlag == true {
|
if *verboseFlag || *migrateFlag {
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *migrateFlag == true {
|
if *migrateFlag {
|
||||||
migrate()
|
migrate()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func Domain(target string) string {
|
||||||
withPossibleSubdomain := strings.Split(target, "/")[2]
|
withPossibleSubdomain := strings.Split(target, "/")[2]
|
||||||
split := strings.Split(withPossibleSubdomain, ".")
|
split := strings.Split(withPossibleSubdomain, ".")
|
||||||
if len(split) == 2 {
|
if len(split) == 2 {
|
||||||
return withPossibleSubdomain // that was the extention, not the subdomain.
|
return withPossibleSubdomain // that was the extension, not the subdomain.
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%s.%s", split[1], split[2])
|
return fmt.Sprintf("%s.%s", split[1], split[2])
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue