mirror of https://github.com/writeas/writefreely
This adds gopher support to WriteFreely -- both single- and multi-user instances. It is off by default, but can be enabled with the new `gopher_port` config value in the `[server]` section. When enabled, multi-user instances will show all public blogs at gopher://[host]:[gopher_port]/ -- otherwise, blogs are accessible at gopher://[host]:[gopher_port]/[blog]/ This is just a proof of concept for now. We still need to handle some edge cases and different configurations, like private instances. Ref T559pull/273/head
parent
fca864c94a
commit
6aa8de3a4b
@ -0,0 +1,146 @@ |
||||
/* |
||||
* Copyright © 2020 A Bunch Tell LLC. |
||||
* |
||||
* This file is part of WriteFreely. |
||||
* |
||||
* WriteFreely is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU Affero General Public License, included |
||||
* in the LICENSE file in this source code package. |
||||
*/ |
||||
|
||||
package writefreely |
||||
|
||||
import ( |
||||
"bytes" |
||||
"fmt" |
||||
"io" |
||||
"strings" |
||||
|
||||
"github.com/prologic/go-gopher" |
||||
"github.com/writeas/web-core/log" |
||||
) |
||||
|
||||
func initGopher(apper Apper) { |
||||
handler := NewWFHandler(apper) |
||||
|
||||
gopher.HandleFunc("/", handler.Gopher(handleGopher)) |
||||
log.Info("Serving on gopher://localhost:%d", apper.App().Config().Server.GopherPort) |
||||
gopher.ListenAndServe(fmt.Sprintf(":%d", apper.App().Config().Server.GopherPort), nil) |
||||
} |
||||
|
||||
func handleGopher(app *App, w gopher.ResponseWriter, r *gopher.Request) error { |
||||
parts := strings.Split(r.Selector, "/") |
||||
if app.cfg.App.SingleUser { |
||||
if parts[1] != "" { |
||||
return handleGopherCollectionPost(app, w, r) |
||||
} |
||||
return handleGopherCollection(app, w, r) |
||||
} |
||||
|
||||
// Show all public collections (a gopher Reader view, essentially)
|
||||
if len(parts) == 3 { |
||||
return handleGopherCollection(app, w, r) |
||||
} |
||||
|
||||
w.WriteInfo(fmt.Sprintf("Welcome to %s", app.cfg.App.SiteName)) |
||||
|
||||
colls, err := app.db.GetPublicCollections(app.cfg.App.Host) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
for _, c := range *colls { |
||||
w.WriteItem(&gopher.Item{ |
||||
Type: gopher.DIRECTORY, |
||||
Description: c.DisplayTitle(), |
||||
Selector: "/" + c.Alias + "/", |
||||
}) |
||||
} |
||||
return w.End() |
||||
} |
||||
|
||||
func handleGopherCollection(app *App, w gopher.ResponseWriter, r *gopher.Request) error { |
||||
var collAlias, slug string |
||||
var c *Collection |
||||
var err error |
||||
var baseSel = "/" |
||||
|
||||
parts := strings.Split(r.Selector, "/") |
||||
if app.cfg.App.SingleUser { |
||||
// sanity check
|
||||
slug = parts[1] |
||||
if slug != "" { |
||||
return handleGopherCollectionPost(app, w, r) |
||||
} |
||||
|
||||
c, err = app.db.GetCollectionByID(1) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} else { |
||||
collAlias = parts[1] |
||||
slug = parts[2] |
||||
if slug != "" { |
||||
return handleGopherCollectionPost(app, w, r) |
||||
} |
||||
|
||||
c, err = app.db.GetCollection(collAlias) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
baseSel = "/" + c.Alias + "/" |
||||
} |
||||
c.hostName = app.cfg.App.Host |
||||
|
||||
posts, err := app.db.GetPosts(app.cfg, c, 0, false, false, false) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
for _, p := range *posts { |
||||
w.WriteItem(&gopher.Item{ |
||||
Type: gopher.FILE, |
||||
Description: p.CreatedDate() + " - " + p.DisplayTitle(), |
||||
Selector: baseSel + p.Slug.String, |
||||
}) |
||||
} |
||||
return w.End() |
||||
} |
||||
|
||||
func handleGopherCollectionPost(app *App, w gopher.ResponseWriter, r *gopher.Request) error { |
||||
var collAlias, slug string |
||||
var c *Collection |
||||
var err error |
||||
|
||||
parts := strings.Split(r.Selector, "/") |
||||
if app.cfg.App.SingleUser { |
||||
slug = parts[1] |
||||
c, err = app.db.GetCollectionByID(1) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} else { |
||||
collAlias = parts[1] |
||||
slug = parts[2] |
||||
c, err = app.db.GetCollection(collAlias) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
} |
||||
c.hostName = app.cfg.App.Host |
||||
|
||||
p, err := app.db.GetPost(slug, c.ID) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
b := bytes.Buffer{} |
||||
if p.Title.String != "" { |
||||
b.WriteString(p.Title.String + "\n") |
||||
} |
||||
b.WriteString(p.DisplayDate + "\n\n") |
||||
b.WriteString(p.Content) |
||||
io.Copy(w, &b) |
||||
|
||||
return w.End() |
||||
} |
Loading…
Reference in new issue