forked from wgroeneveld/go-jamming
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
|
||||
- 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.
|
||||
- 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`
|
||||
|
||||
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:
|
||||
|
||||
|
@ -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`
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ func (rl *RateLimiter) limiterMiddleware(next http.Handler) http.Handler {
|
|||
ip := ipFrom(r)
|
||||
limiter := rl.getVisitor(ip)
|
||||
|
||||
if limiter.Allow() == false {
|
||||
if !limiter.Allow() {
|
||||
log.Error().Str("ip", ip).Msg("Someone spamming? Rate limit hit!")
|
||||
rest.TooManyRequests(w)
|
||||
return
|
||||
|
|
|
@ -21,6 +21,13 @@ type IndiewebDataResult struct {
|
|||
Data []*IndiewebData `json:"json"`
|
||||
}
|
||||
|
||||
func ResultFailure(data []*IndiewebData) IndiewebDataResult {
|
||||
return IndiewebDataResult{
|
||||
Status: "failure",
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func ResultSuccess(data []*IndiewebData) IndiewebDataResult {
|
||||
return IndiewebDataResult{
|
||||
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"
|
||||
valMap, ok2 := val[0].(map[string]string)
|
||||
if !ok2 {
|
||||
str = ""
|
||||
return ""
|
||||
}
|
||||
str = valMap["value"]
|
||||
return valMap["value"]
|
||||
}
|
||||
|
||||
return str
|
||||
|
|
|
@ -70,7 +70,7 @@ func ParseFeed(content []byte) (*Rss2, error) {
|
|||
}
|
||||
|
||||
if v.Version == "2.0" {
|
||||
for i, _ := range v.ItemList {
|
||||
for i := range v.ItemList {
|
||||
if 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 {
|
||||
sinceParam, _ := r.URL.Query()["since"]
|
||||
sinceParam := r.URL.Query()["since"]
|
||||
since := ""
|
||||
if len(sinceParam) > 0 {
|
||||
since = sinceParam[0]
|
||||
|
|
|
@ -14,8 +14,6 @@ import (
|
|||
"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 {
|
||||
RestClient rest.Client
|
||||
Conf *common.Config
|
||||
|
|
|
@ -16,10 +16,7 @@ func isValidUrl(url string) bool {
|
|||
|
||||
func isValidDomain(url string, conf *common.Config) bool {
|
||||
_, err := conf.FetchDomain(url)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return err == nil
|
||||
}
|
||||
|
||||
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.
|
||||
// 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 {
|
||||
var data []*mf.IndiewebData
|
||||
err := r.db.View(func(tx *buntdb.Tx) error {
|
||||
|
@ -160,7 +160,7 @@ func (r *MentionRepoBunt) GetAll(domain string) mf.IndiewebDataResult {
|
|||
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("get all: failed to ascend from view")
|
||||
return mf.IndiewebDataResult{}
|
||||
return mf.ResultFailure(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.
|
||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||
if *verboseFlag == true || *migrateFlag == true {
|
||||
if *verboseFlag || *migrateFlag {
|
||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
|
||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||
}
|
||||
|
||||
if *migrateFlag == true {
|
||||
if *migrateFlag {
|
||||
migrate()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ func Domain(target string) string {
|
|||
withPossibleSubdomain := strings.Split(target, "/")[2]
|
||||
split := strings.Split(withPossibleSubdomain, ".")
|
||||
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])
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue