Add NodeInfo endpoints
Includes new instance stats and the new option to show user stats, as well.
This commit is contained in:
parent
39477cfcab
commit
1a6f61690e
4
app.go
4
app.go
|
@ -18,6 +18,10 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
staticDir = "static/"
|
staticDir = "static/"
|
||||||
|
|
||||||
|
serverSoftware = "Write Freely"
|
||||||
|
softwareURL = "https://writefreely.org"
|
||||||
|
softwareVer = "0.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type app struct {
|
type app struct {
|
||||||
|
|
|
@ -27,6 +27,8 @@ type (
|
||||||
MultiUser bool `ini:"multiuser"`
|
MultiUser bool `ini:"multiuser"`
|
||||||
OpenSignups bool `ini:"open_signups"`
|
OpenSignups bool `ini:"open_signups"`
|
||||||
Federation bool `ini:"federation"`
|
Federation bool `ini:"federation"`
|
||||||
|
PublicStats bool `ini:"public_stats"`
|
||||||
|
Private bool `ini:"private"`
|
||||||
|
|
||||||
Name string `ini:"site_name"`
|
Name string `ini:"site_name"`
|
||||||
|
|
||||||
|
@ -56,6 +58,7 @@ func New() *Config {
|
||||||
},
|
},
|
||||||
App: AppCfg{
|
App: AppCfg{
|
||||||
Federation: true,
|
Federation: true,
|
||||||
|
PublicStats: true,
|
||||||
MinUsernameLen: 3,
|
MinUsernameLen: 3,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
package writefreely
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/writeas/go-nodeinfo"
|
||||||
|
"github.com/writeas/web-core/log"
|
||||||
|
"github.com/writeas/writefreely/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type nodeInfoResolver struct {
|
||||||
|
cfg *config.Config
|
||||||
|
db *datastore
|
||||||
|
}
|
||||||
|
|
||||||
|
func nodeInfoConfig(cfg *config.Config) *nodeinfo.Config {
|
||||||
|
name := cfg.App.SiteName
|
||||||
|
return &nodeinfo.Config{
|
||||||
|
BaseURL: cfg.Server.Host,
|
||||||
|
InfoURL: "/api/nodeinfo",
|
||||||
|
|
||||||
|
Metadata: nodeinfo.Metadata{
|
||||||
|
NodeName: name,
|
||||||
|
NodeDescription: "Minimal, federated blogging platform.",
|
||||||
|
Private: cfg.App.Private,
|
||||||
|
Software: nodeinfo.SoftwareMeta{
|
||||||
|
HomePage: softwareURL,
|
||||||
|
GitHub: "https://github.com/writeas/writefreely",
|
||||||
|
Follow: "https://writing.exchange/@write_as",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Protocols: []nodeinfo.NodeProtocol{
|
||||||
|
nodeinfo.ProtocolActivityPub,
|
||||||
|
},
|
||||||
|
Services: nodeinfo.Services{
|
||||||
|
Inbound: []nodeinfo.NodeService{},
|
||||||
|
Outbound: []nodeinfo.NodeService{},
|
||||||
|
},
|
||||||
|
Software: nodeinfo.SoftwareInfo{
|
||||||
|
Name: serverSoftware,
|
||||||
|
Version: softwareVer,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r nodeInfoResolver) IsOpenRegistration() (bool, error) {
|
||||||
|
return !r.cfg.App.Private, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r nodeInfoResolver) Usage() (nodeinfo.Usage, error) {
|
||||||
|
var collCount, postCount, activeHalfYear, activeMonth int
|
||||||
|
err := r.db.QueryRow(`SELECT COUNT(*) FROM collections`).Scan(&collCount)
|
||||||
|
if err != nil {
|
||||||
|
collCount = 0
|
||||||
|
}
|
||||||
|
err = r.db.QueryRow(`SELECT COUNT(*) FROM posts`).Scan(&postCount)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to fetch post counts: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.cfg.App.PublicStats {
|
||||||
|
// Display bi-yearly / monthly stats
|
||||||
|
err = r.db.QueryRow(fmt.Sprintf(`SELECT COUNT(*) FROM (
|
||||||
|
SELECT DISTINCT collection_id
|
||||||
|
FROM posts
|
||||||
|
INNER JOIN collections c
|
||||||
|
ON collection_id = c.id
|
||||||
|
WHERE collection_id IS NOT NULL
|
||||||
|
AND updated > DATE_SUB(NOW(), INTERVAL 6 MONTH)) co`, CollPublic)).Scan(&activeHalfYear)
|
||||||
|
|
||||||
|
err = r.db.QueryRow(fmt.Sprintf(`SELECT COUNT(*) FROM (
|
||||||
|
SELECT DISTINCT collection_id
|
||||||
|
FROM posts
|
||||||
|
INNER JOIN FROM collections c
|
||||||
|
ON collection_id = c.id
|
||||||
|
WHERE collection_id IS NOT NULL
|
||||||
|
AND updated > DATE_SUB(NOW(), INTERVAL 1 MONTH)) co`, CollPublic)).Scan(&activeMonth)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeinfo.Usage{
|
||||||
|
Users: nodeinfo.UsageUsers{
|
||||||
|
Total: collCount,
|
||||||
|
ActiveHalfYear: activeHalfYear,
|
||||||
|
ActiveMonth: activeMonth,
|
||||||
|
},
|
||||||
|
LocalPosts: postCount,
|
||||||
|
}, nil
|
||||||
|
}
|
10
routes.go
10
routes.go
|
@ -2,8 +2,10 @@ package writefreely
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/writeas/go-nodeinfo"
|
||||||
"github.com/writeas/web-core/log"
|
"github.com/writeas/web-core/log"
|
||||||
"github.com/writeas/writefreely/config"
|
"github.com/writeas/writefreely/config"
|
||||||
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,4 +30,12 @@ func initRoutes(handler *Handler, r *mux.Router, cfg *config.Config, db *datasto
|
||||||
|
|
||||||
// Primary app routes
|
// Primary app routes
|
||||||
log.Info("Adding %s routes (multi-user)...", hostSubroute)
|
log.Info("Adding %s routes (multi-user)...", hostSubroute)
|
||||||
|
write := r.Host(hostSubroute).Subrouter()
|
||||||
|
|
||||||
|
// Federation endpoints
|
||||||
|
// nodeinfo
|
||||||
|
niCfg := nodeInfoConfig(cfg)
|
||||||
|
ni := nodeinfo.NewService(*niCfg, nodeInfoResolver{cfg, db})
|
||||||
|
write.HandleFunc(nodeinfo.NodeInfoPath, handler.LogHandlerFunc(http.HandlerFunc(ni.NodeInfoDiscover)))
|
||||||
|
write.HandleFunc(niCfg.InfoURL, handler.LogHandlerFunc(http.HandlerFunc(ni.NodeInfo)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue