Compare commits

..

19 Commits

Author SHA1 Message Date
Ted Unangst 887bf8e8a6 Added tag v1.0.0 for changeset b1e7ac92a58a 2023-08-09 21:14:17 -04:00
Ted Unangst f68e73937c 1.0.0 Happy Honker 2023-08-09 21:14:08 -04:00
Ted Unangst 448ae46efe time to commit to using the proper accept type 2023-08-09 16:16:11 -04:00
Ted Unangst 829c0af097 new sample colors 2023-08-09 15:44:54 -04:00
Ted Unangst ad8d72ce0d qotd 2023-08-08 16:17:47 -04:00
Ted Unangst fe783eda2a webs bump for html fix 2023-08-07 17:28:14 -04:00
Ted Unangst 24017928ab do not run honk as root 2023-08-07 13:58:24 -04:00
Ted Unangst 6b830f8fe5 update ignore file 2023-08-07 02:28:49 -04:00
Ted Unangst 6f4b325cf5 split main into a new file, add build info 2023-08-07 02:27:25 -04:00
Ted Unangst 93b30f305e rel alternative for user too 2023-08-06 04:08:06 -04:00
Ted Unangst 8f3e5229b2 stop fixing the width of the textarea 2023-08-06 03:14:12 -04:00
Ted Unangst d2f812058b repair loss of bonker information in last refactor 2023-08-06 03:04:37 -04:00
Ted Unangst 2514129b3a add a sample meme 2023-08-06 02:19:56 -04:00
Ted Unangst 656d4c99a5 if we don't get the bonk, nothing to do 2023-08-05 20:59:58 -04:00
Ted Unangst e7454cc9be m 2023-08-05 20:53:15 -04:00
Ted Unangst 6a5f4ba621 reject origin test in getjunk path to catch strays 2023-08-05 20:52:55 -04:00
Ted Unangst 2376371d76 update twitter import again, from tom 2023-08-04 13:08:15 -04:00
Ted Unangst 79756a6b0f don't report csp violations by default 2023-08-04 13:06:24 -04:00
Ted Unangst 9de375d169 unusued range var 2023-08-02 23:34:24 -04:00
19 changed files with 420 additions and 305 deletions

View File

@ -1,4 +1,9 @@
.*\.db
syntax: glob
.preflightcheck
*.db
*.db-shm
*.db-wal
memes
emus
honk
violations.json

View File

@ -38,3 +38,4 @@ bc1bcfb9c0cc86b3c63325b07e13a36b9d4500f0 v0.9.7
916cefdc24363b6e7e193dbde82632c17f58adfd v0.9.8
4b8cf31560b7d1e1696af109b158766c4ce823ab v0.9.9
d7c3a01e7aaef67c40920bbc4e8507350fc33e31 v0.9.91
b1e7ac92a58a7183310b1a5cca8222d65f242d81 v1.0.0

14
README
View File

@ -1,6 +1,6 @@
honk
-- features
## features
Take control of your honks and join the federation.
An ActivityPub server with minimal setup and support costs.
@ -17,7 +17,7 @@ The button to submit a new honk says "it's gonna be honked".
The honk mission is to work well if it's what you want.
This does not imply the goal is to be what you want.
-- build
## build
It should be sufficient to type make after unpacking a release.
You'll need a go compiler version 1.16 or later. And libsqlite3.
@ -26,7 +26,7 @@ Even on a fast machine, building from source can take several seconds.
Development sources: hg clone https://humungus.tedunangst.com/r/honk
-- setup
## setup
honk expects to be fronted by a TLS terminating reverse proxy.
@ -40,17 +40,17 @@ servername: (public DNS name: honk.example.com)
Then run honk.
./honk
-- upgrade
## upgrade
old-honk backup `date +backup-%F`
./honk upgrade
./honk
-- documentation
## documentation
There is a more complete incomplete manual. This is just the README.
-- guidelines
## guidelines
One honk per day, or call it an "eighth-tenth" honk.
If your honk frequency changes, so will the number of honks.
@ -67,6 +67,6 @@ It is considered rude to make noise in a place of business.
The honk may be made on public property only when the person doing
the honk has the permission of the owner of that property.
-- disclaimer
## disclaimer
Do not use honk to contact emergency services.

View File

@ -133,6 +133,9 @@ var flightdeck = gate.NewSerializer()
var signGets = true
func GetJunkTimeout(userid int64, url string, timeout time.Duration) (junk.Junk, error) {
if rejectorigin(userid, url, false) {
return nil, fmt.Errorf("rejected origin: %s", url)
}
client := http.DefaultClient
sign := func(req *http.Request) error {
var ki *KeyInfo
@ -147,7 +150,7 @@ func GetJunkTimeout(userid int64, url string, timeout time.Duration) (junk.Junk,
sign = nil
}
fn := func() (interface{}, error) {
at := thefakename
at := theonetruename
if strings.Contains(url, ".well-known/webfinger?resource") {
at = "application/jrd+json"
}
@ -490,7 +493,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
maxdepth := 10
currenttid := ""
goingup := 0
var xonkxonkfn func(junk.Junk, string, bool, bool) *Honk
var xonkxonkfn func(junk.Junk, string, bool, string) *Honk
qutify := func(user *WhatAbout, content string) string {
if depth >= maxdepth {
@ -522,7 +525,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
}
prevdepth := depth
depth = maxdepth
xonkxonkfn(j, originate(m), false, false)
xonkxonkfn(j, originate(m), false, "")
depth = prevdepth
}
}
@ -541,10 +544,10 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
ilog.Printf("error getting onemore: %s: %s", xid, err)
return
}
xonkxonkfn(obj, originate(xid), false, false)
xonkxonkfn(obj, originate(xid), false, "")
}
xonkxonkfn = func(item junk.Junk, origin string, isUpdate bool, isAnnounce bool) *Honk {
xonkxonkfn = func(item junk.Junk, origin string, isUpdate bool, bonker string) *Honk {
id, _ := item.GetString("id")
what := firstofmany(item, "type")
dt, ok := item.GetString("published")
@ -624,6 +627,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
if !isUpdate && !needbonkid(user, xid) {
return nil
}
bonker, _ = item.GetString("actor")
origin = originate(xid)
if ok && originate(id) == origin {
dlog.Printf("using object in announce for %s", xid)
@ -632,9 +636,10 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
obj, err = GetJunkHardMode(user.ID, xid)
if err != nil {
ilog.Printf("error getting bonk: %s: %s", xid, err)
return nil
}
}
return xonkxonkfn(obj, origin, isUpdate, true)
return xonkxonkfn(obj, origin, isUpdate, bonker)
case "Update":
isUpdate = true
fallthrough
@ -656,7 +661,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
ilog.Printf("no object for creation %s", id)
return nil
}
return xonkxonkfn(obj, origin, isUpdate, isAnnounce)
return xonkxonkfn(obj, origin, isUpdate, bonker)
case "Read":
xid, ok = item.GetString("object")
if ok {
@ -669,7 +674,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
ilog.Printf("error getting read: %s", err)
return nil
}
return xonkxonkfn(obj, originate(xid), false, false)
return xonkxonkfn(obj, originate(xid), false, "")
}
return nil
case "Add":
@ -685,7 +690,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
ilog.Printf("error getting add: %s", err)
return nil
}
return xonkxonkfn(obj, originate(xid), false, false)
return xonkxonkfn(obj, originate(xid), false, "")
}
return nil
case "Move":
@ -714,7 +719,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
obj = item
what = "event"
case "ChatMessage":
isAnnounce = false
bonker = ""
obj = item
what = "chonk"
default:
@ -722,7 +727,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
dumpactivity(item)
return nil
}
if isAnnounce {
if bonker != "" {
what = "bonk"
}
@ -755,7 +760,9 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
if xonk.Honker == "" {
xonk.Honker = extractattrto(obj)
}
xonk.Oonker = extractattrto(obj)
if bonker != "" {
xonk.Honker, xonk.Oonker = bonker, xonk.Honker
}
if xonk.Oonker == xonk.Honker {
xonk.Oonker = ""
}
@ -1125,7 +1132,7 @@ func xonksaver(user *WhatAbout, item junk.Junk, origin string) *Honk {
return &xonk
}
return xonkxonkfn(item, origin, false, false)
return xonkxonkfn(item, origin, false, "")
}
func dumpactivity(item junk.Junk) {

View File

@ -14,3 +14,38 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package main
import (
"io"
"net"
"time"
)
func qotd() {
var qotdaddr string
getconfig("qotdaddr", &qotdaddr)
if qotdaddr == "" {
return
}
s, err := net.Listen("tcp", ":8017")
if err != nil {
return
}
for {
c, err := s.Accept()
if err != nil {
time.Sleep(time.Second)
continue
}
honks := getpublichonks()
for _, honk := range honks {
if !firstclass(honk) {
continue
}
io.WriteString(c, honk.Noise)
io.WriteString(c, "\n")
break
}
c.Close()
}
}

View File

@ -1121,7 +1121,7 @@ func cleanupdb(arg string) {
if err != nil {
elog.Fatal(err)
}
for xid, _ := range filexids {
for xid := range filexids {
_, err = tx.Exec("delete from filedata where xid = ?", xid)
if err != nil {
elog.Fatal(err)

View File

@ -1,15 +1,19 @@
changelog
=== next
### 1.0.0 Happy Honker
+ A great big honk composition text box.
+ More reliable search.
+ Secret tags.
+ Mention links locally.
+ Mentions link locally.
+ ::: spoiler markdown
+ Fix the bonk and zonk crash.
+ New threaded display order.
+ Improved search.
@ -18,15 +22,19 @@ changelog
+ Import from instagram.
+ improve handling of some Page and Link objects
+ Improve handling of some Page and Link objects.
+ search can now load external posts
+ Other federation fixes.
=== 0.9.91 One More Time
+ Search can now load external posts.
+ Some hypercard opengraph markup for previews.
### 0.9.91 One More Time
+ Swallow a follow bug.
=== 0.9.9 Eat the Bugs
### 0.9.9 Eat the Bugs
+ Some fixes for image descriptions.
@ -58,7 +66,7 @@ changelog
+ Try to fix hoot again because Twitter did a Twitter.
=== 0.9.8 Tentative Tentacle
### 0.9.8 Tentative Tentacle
+ Switch database to WAL mode.
@ -88,7 +96,7 @@ changelog
+ Some improved html and markdown.
=== 0.9.7 Witless Weekender
### 0.9.7 Witless Weekender
+++ Word guessing game. Wonk wonk!
@ -104,7 +112,7 @@ changelog
+ Printing is prettier than ever before.
=== 0.9.6 Virile Vigorous and Potent
### 0.9.6 Virile Vigorous and Potent
+ A bug, a fix, a bug fix, a fix bug.
@ -120,17 +128,17 @@ changelog
+ Fix hoot to work with Twitter's latest crap.
=== 0.9.5 Emergency Ejection
### 0.9.5 Emergency Ejection
+ Fix honk init user creation.
=== 0.9.4 Collegiate Colloquialism
### 0.9.4 Collegiate Colloquialism
+ Add validation to some more user inputs to prevent mistakes.
+ Easier to use ping command.
=== 0.9.3 Notacanthous Nutshell
### 0.9.3 Notacanthous Nutshell
++ backup command.
@ -152,11 +160,11 @@ changelog
- Custom lingo for those who don't like honking.
=== 0.9.2 Malleable Maltote
### 0.9.2 Malleable Maltote
+ Fix compilation on mac.
=== 0.9.1 Late Stage Lusciousness
### 0.9.1 Late Stage Lusciousness
++ Boing boom tschak chonky chatter. Chat messages with Pleroma.
@ -176,7 +184,7 @@ changelog
+ A few API refinements and additions.
=== 0.9.0 Monitor vs Merrimack
### 0.9.0 Monitor vs Merrimack
--- Add Reactions.
@ -194,7 +202,7 @@ changelog
+ Maybe possible to use @user@example.com wihtout subdomain.
=== 0.8.6 Sartorial Headpiece
### 0.8.6 Sartorial Headpiece
++ Import command now supports the elephant in the room.
@ -220,7 +228,7 @@ changelog
+ More flexible meme names.
=== 0.8.5 Turnkey Blaster
### 0.8.5 Turnkey Blaster
+ Codenames in changelog.
@ -240,17 +248,17 @@ changelog
+ Can never seem to version the changelog correctly.
=== 0.8.4
### 0.8.4
+ Fix bug preventing import of keys
+ Option to switch map links to Apple.
=== 0.8.3
### 0.8.3
- mistag.
=== 0.8.2 Game Warden
### 0.8.2 Game Warden
++ Import command to preserve those embarssassing old posts from Twitter.
@ -266,7 +274,7 @@ changelog
+ "Bug" fixes.
=== 0.8.1
### 0.8.1
++ Make it easier to upgrade by decoupling data dir from ".".
@ -278,7 +286,7 @@ changelog
Syntax highlighting for code blocks.
Something resembling an actual manual.
=== 0.8.0 Ordinary Octology
### 0.8.0 Ordinary Octology
+++ Add Honk Filtering and Censorship System (HFCS).
@ -333,7 +341,7 @@ changelog
- Sometimes the cached state of the @me feed becomes unsynced.
Acked status may display incorrectly.
=== 0.7.7 More 7 Than Ever
### 0.7.7 More 7 Than Ever
+ Add another retry to workaround pixelfed's general unreliability.
@ -345,11 +353,11 @@ changelog
+ Increase max thread retrieval depth to 10.
=== 0.7.6
### 0.7.6
+ Fix a bug where upgrades would not complete in one step.
=== 0.7.5
### 0.7.5
+ Fix a bug (introdcued 0.7.4) preventing new user creation from working.
@ -361,7 +369,7 @@ changelog
+ What may be considered UI improvements.
=== 0.7.4
### 0.7.4
+ Ever more bug fixes.
@ -377,19 +385,19 @@ changelog
+ webp image transcoding.
=== 0.7.3
### 0.7.3
+ Better fedicompat so bonks are visible to pleroma followers.
=== 0.7.2
### 0.7.2
+ Add the funzone. Minor other UI tweaks.
=== 0.7.1
### 0.7.1
+ Fix bug preventing unfollow from working.
=== 0.7.0 Father Mother Maiden Crone Honker Bonker Zonker
### 0.7.0 Father Mother Maiden Crone Honker Bonker Zonker
+++ Auto fetching and inlining of hoots.
@ -419,12 +427,12 @@ changelog
+ Add max-width for video tag.
=== 0.6.0 Sixy Delights
### 0.6.0 Sixy Delights
Most records from this time of primitive development have been lost.
=== 0.5.0 Halfway to Heaven
### 0.5.0 Halfway to Heaven
=== 0.4.0 Fore Score
### 0.4.0 Fore Score
=== 0.3.0 Valorous Varaha
### 0.3.0 Valorous Varaha

View File

@ -266,10 +266,10 @@ honk-v98> ./honk -datadir ../honkdata admin
honk-v98> date; ./honk -log honk.log -datadir ../honkdata
.Ed
.Pp
The views directory includes a sample pleroma.css to change color scheme.
The views directory includes a sample mastodon.css to change color scheme.
.Bd -literal -offset indent
honk-v98> mkdir ../honkdata/views
honk-v98> cp views/pleroma.css ../honkdata/views/local.css
honk-v98> cp views/mastodon.css ../honkdata/views/local.css
.Ed
.Pp
Upgrade to the next version.

2
go.mod
View File

@ -9,5 +9,5 @@ require (
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
humungus.tedunangst.com/r/go-sqlite3 v1.1.3
humungus.tedunangst.com/r/webs v0.6.67
humungus.tedunangst.com/r/webs v0.6.68
)

4
go.sum
View File

@ -25,5 +25,5 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
humungus.tedunangst.com/r/go-sqlite3 v1.1.3 h1:G2N4wzDS0NbuvrZtQJhh4F+3X+s7BF8b9ga8k38geUI=
humungus.tedunangst.com/r/go-sqlite3 v1.1.3/go.mod h1:FtEEmQM7U2Ey1TuEEOyY1BmphTZnmiEjPsNLEAkpf/M=
humungus.tedunangst.com/r/webs v0.6.67 h1:OO5UkQa+bHeiIrZ5IGR9JGtgGPsKsYlRJEVk1bSt+Qo=
humungus.tedunangst.com/r/webs v0.6.67/go.mod h1:03R0N9BcT49HB4TDd1YmarpbiPvPzVDm74Mk4h1hYPc=
humungus.tedunangst.com/r/webs v0.6.68 h1:veKjASf1krPf4o3O7hMRsNvE4+Z6LzXVso/qMccZntk=
humungus.tedunangst.com/r/webs v0.6.68/go.mod h1:03R0N9BcT49HB4TDd1YmarpbiPvPzVDm74Mk4h1hYPc=

228
honk.go
View File

@ -16,27 +16,14 @@
package main
import (
"flag"
"fmt"
"html/template"
golog "log"
"log/syslog"
notrand "math/rand"
"os"
"strconv"
"strings"
"time"
"humungus.tedunangst.com/r/webs/httpsig"
"humungus.tedunangst.com/r/webs/log"
)
var softwareVersion = "develop"
func init() {
notrand.Seed(time.Now().Unix())
}
type WhatAbout struct {
ID int64
Name string
@ -277,218 +264,3 @@ const (
SomeActor
SomeCollection
)
var serverName string
var serverPrefix string
var masqName string
var dataDir = "."
var viewDir = "."
var iconName = "icon.png"
var serverMsg template.HTML
var aboutMsg template.HTML
var loginMsg template.HTML
func ElaborateUnitTests() {
}
func unplugserver(hostname string) {
db := opendatabase()
xid := fmt.Sprintf("%%https://%s/%%", hostname)
db.Exec("delete from honkers where xid like ? and flavor = 'dub'", xid)
db.Exec("delete from doovers where rcpt like ?", xid)
}
func reexecArgs(cmd string) []string {
args := []string{"-datadir", dataDir}
args = append(args, log.Args()...)
args = append(args, cmd)
return args
}
var elog, ilog, dlog *golog.Logger
func main() {
flag.StringVar(&dataDir, "datadir", dataDir, "data directory")
flag.StringVar(&viewDir, "viewdir", viewDir, "view directory")
flag.Parse()
log.Init(log.Options{Progname: "honk", Facility: syslog.LOG_UUCP})
elog = log.E
ilog = log.I
dlog = log.D
args := flag.Args()
cmd := "run"
if len(args) > 0 {
cmd = args[0]
}
switch cmd {
case "init":
initdb()
case "upgrade":
upgradedb()
case "version":
fmt.Println(softwareVersion)
os.Exit(0)
}
db := opendatabase()
dbversion := 0
getconfig("dbversion", &dbversion)
if dbversion != myVersion {
elog.Fatal("incorrect database version. run upgrade.")
}
getconfig("servermsg", &serverMsg)
getconfig("aboutmsg", &aboutMsg)
getconfig("loginmsg", &loginMsg)
getconfig("servername", &serverName)
getconfig("masqname", &masqName)
if masqName == "" {
masqName = serverName
}
serverPrefix = fmt.Sprintf("https://%s/", serverName)
getconfig("usersep", &userSep)
getconfig("honksep", &honkSep)
getconfig("devel", &develMode)
getconfig("fasttimeout", &fastTimeout)
getconfig("slowtimeout", &slowTimeout)
getconfig("signgets", &signGets)
prepareStatements(db)
switch cmd {
case "admin":
adminscreen()
case "import":
if len(args) != 4 {
elog.Fatal("import username mastodon|twitter srcdir")
}
importMain(args[1], args[2], args[3])
case "devel":
if len(args) != 2 {
elog.Fatal("need an argument: devel (on|off)")
}
switch args[1] {
case "on":
setconfig("devel", 1)
case "off":
setconfig("devel", 0)
default:
elog.Fatal("argument must be on or off")
}
case "setconfig":
if len(args) != 3 {
elog.Fatal("need an argument: setconfig key val")
}
var val interface{}
var err error
if val, err = strconv.Atoi(args[2]); err != nil {
val = args[2]
}
setconfig(args[1], val)
case "adduser":
adduser()
case "deluser":
if len(args) < 2 {
fmt.Printf("usage: honk deluser username\n")
return
}
deluser(args[1])
case "chpass":
if len(args) < 2 {
fmt.Printf("usage: honk chpass username\n")
return
}
chpass(args[1])
case "follow":
if len(args) < 3 {
fmt.Printf("usage: honk follow username url\n")
return
}
user, err := butwhatabout(args[1])
if err != nil {
fmt.Printf("user not found\n")
return
}
var meta HonkerMeta
mj, _ := jsonify(&meta)
honkerid, err := savehonker(user, args[2], "", "presub", "", mj)
if err != nil {
fmt.Printf("had some trouble with that: %s\n", err)
return
}
followyou(user, honkerid, true)
case "unfollow":
if len(args) < 3 {
fmt.Printf("usage: honk unfollow username url\n")
return
}
user, err := butwhatabout(args[1])
if err != nil {
fmt.Printf("user not found\n")
return
}
row := db.QueryRow("select honkerid from honkers where xid = ? and userid = ? and flavor in ('sub')", args[2], user.ID)
var honkerid int64
err = row.Scan(&honkerid)
if err != nil {
fmt.Printf("sorry couldn't find them\n")
return
}
unfollowyou(user, honkerid, true)
case "sendmsg":
if len(args) < 4 {
fmt.Printf("usage: honk send username filename rcpt\n")
return
}
user, err := butwhatabout(args[1])
if err != nil {
fmt.Printf("user not found\n")
return
}
data, err := os.ReadFile(args[2])
if err != nil {
fmt.Printf("can't read file\n")
return
}
deliverate(user.ID, args[3], data)
case "cleanup":
arg := "30"
if len(args) > 1 {
arg = args[1]
}
cleanupdb(arg)
case "unplug":
if len(args) < 2 {
fmt.Printf("usage: honk unplug servername\n")
return
}
name := args[1]
unplugserver(name)
case "backup":
if len(args) < 2 {
fmt.Printf("usage: honk backup dirname\n")
return
}
name := args[1]
svalbard(name)
case "ping":
if len(args) < 3 {
fmt.Printf("usage: honk ping (from username) (to username or url)\n")
return
}
name := args[1]
targ := args[2]
user, err := butwhatabout(name)
if err != nil {
elog.Printf("unknown user")
return
}
ping(user, targ)
case "run":
serve()
case "backend":
backendServer()
case "test":
ElaborateUnitTests()
default:
elog.Fatal("unknown command")
}
}

View File

@ -338,7 +338,7 @@ func importTwitter(username, source string) {
}
var tweets []*Tweet
fd, err := os.Open(source + "/tweet.js")
fd, err := os.Open(source + "/tweets.js")
if err != nil {
elog.Fatal(err)
}
@ -375,11 +375,6 @@ func importTwitter(username, source string) {
continue
}
if t.Tweet.FavoriteCount == "0" || t.Tweet.FavoriteCount == "" {
log.Printf("skipping, unworthy tweet")
continue
}
what := "honk"
noise := ""
if parent := tweetmap[t.Tweet.InReplyToStatusID]; parent != nil {

255
main.go Normal file
View File

@ -0,0 +1,255 @@
//
// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package main
import (
"flag"
"fmt"
"html/template"
golog "log"
"log/syslog"
notrand "math/rand"
"os"
"strconv"
"time"
"humungus.tedunangst.com/r/webs/log"
)
var softwareVersion = "develop"
func init() {
notrand.Seed(time.Now().Unix())
}
var serverName string
var serverPrefix string
var masqName string
var dataDir = "."
var viewDir = "."
var iconName = "icon.png"
var serverMsg template.HTML
var aboutMsg template.HTML
var loginMsg template.HTML
func ElaborateUnitTests() {
}
func unplugserver(hostname string) {
db := opendatabase()
xid := fmt.Sprintf("%%https://%s/%%", hostname)
db.Exec("delete from honkers where xid like ? and flavor = 'dub'", xid)
db.Exec("delete from doovers where rcpt like ?", xid)
}
func reexecArgs(cmd string) []string {
args := []string{"-datadir", dataDir}
args = append(args, log.Args()...)
args = append(args, cmd)
return args
}
var elog, ilog, dlog *golog.Logger
func main() {
flag.StringVar(&dataDir, "datadir", dataDir, "data directory")
flag.StringVar(&viewDir, "viewdir", viewDir, "view directory")
flag.Parse()
log.Init(log.Options{Progname: "honk", Facility: syslog.LOG_UUCP})
elog = log.E
ilog = log.I
dlog = log.D
if os.Geteuid() == 0 {
elog.Fatalf("do not run honk as root")
}
args := flag.Args()
cmd := "run"
if len(args) > 0 {
cmd = args[0]
}
switch cmd {
case "init":
initdb()
case "upgrade":
upgradedb()
case "version":
fmt.Println(softwareVersion)
os.Exit(0)
}
db := opendatabase()
dbversion := 0
getconfig("dbversion", &dbversion)
if dbversion != myVersion {
elog.Fatal("incorrect database version. run upgrade.")
}
getconfig("servermsg", &serverMsg)
getconfig("aboutmsg", &aboutMsg)
getconfig("loginmsg", &loginMsg)
getconfig("servername", &serverName)
getconfig("masqname", &masqName)
if masqName == "" {
masqName = serverName
}
serverPrefix = fmt.Sprintf("https://%s/", serverName)
getconfig("usersep", &userSep)
getconfig("honksep", &honkSep)
getconfig("devel", &develMode)
getconfig("fasttimeout", &fastTimeout)
getconfig("slowtimeout", &slowTimeout)
getconfig("signgets", &signGets)
prepareStatements(db)
switch cmd {
case "admin":
adminscreen()
case "import":
if len(args) != 4 {
elog.Fatal("import username mastodon|twitter srcdir")
}
importMain(args[1], args[2], args[3])
case "devel":
if len(args) != 2 {
elog.Fatal("need an argument: devel (on|off)")
}
switch args[1] {
case "on":
setconfig("devel", 1)
case "off":
setconfig("devel", 0)
default:
elog.Fatal("argument must be on or off")
}
case "setconfig":
if len(args) != 3 {
elog.Fatal("need an argument: setconfig key val")
}
var val interface{}
var err error
if val, err = strconv.Atoi(args[2]); err != nil {
val = args[2]
}
setconfig(args[1], val)
case "adduser":
adduser()
case "deluser":
if len(args) < 2 {
fmt.Printf("usage: honk deluser username\n")
return
}
deluser(args[1])
case "chpass":
if len(args) < 2 {
fmt.Printf("usage: honk chpass username\n")
return
}
chpass(args[1])
case "follow":
if len(args) < 3 {
fmt.Printf("usage: honk follow username url\n")
return
}
user, err := butwhatabout(args[1])
if err != nil {
fmt.Printf("user not found\n")
return
}
var meta HonkerMeta
mj, _ := jsonify(&meta)
honkerid, err := savehonker(user, args[2], "", "presub", "", mj)
if err != nil {
fmt.Printf("had some trouble with that: %s\n", err)
return
}
followyou(user, honkerid, true)
case "unfollow":
if len(args) < 3 {
fmt.Printf("usage: honk unfollow username url\n")
return
}
user, err := butwhatabout(args[1])
if err != nil {
fmt.Printf("user not found\n")
return
}
row := db.QueryRow("select honkerid from honkers where xid = ? and userid = ? and flavor in ('sub')", args[2], user.ID)
var honkerid int64
err = row.Scan(&honkerid)
if err != nil {
fmt.Printf("sorry couldn't find them\n")
return
}
unfollowyou(user, honkerid, true)
case "sendmsg":
if len(args) < 4 {
fmt.Printf("usage: honk send username filename rcpt\n")
return
}
user, err := butwhatabout(args[1])
if err != nil {
fmt.Printf("user not found\n")
return
}
data, err := os.ReadFile(args[2])
if err != nil {
fmt.Printf("can't read file\n")
return
}
deliverate(user.ID, args[3], data)
case "cleanup":
arg := "30"
if len(args) > 1 {
arg = args[1]
}
cleanupdb(arg)
case "unplug":
if len(args) < 2 {
fmt.Printf("usage: honk unplug servername\n")
return
}
name := args[1]
unplugserver(name)
case "backup":
if len(args) < 2 {
fmt.Printf("usage: honk backup dirname\n")
return
}
name := args[1]
svalbard(name)
case "ping":
if len(args) < 3 {
fmt.Printf("usage: honk ping (from username) (to username or url)\n")
return
}
name := args[1]
targ := args[2]
user, err := butwhatabout(name)
if err != nil {
elog.Printf("unknown user")
return
}
ping(user, targ)
case "run":
serve()
case "backend":
backendServer()
case "test":
ElaborateUnitTests()
default:
elog.Fatal("unknown command")
}
}

BIN
memes/twowires.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -16,10 +16,38 @@
package main
import (
"runtime/debug"
"syscall"
"time"
)
func init() {
if softwareVersion != "develop" {
return
}
bi, ok := debug.ReadBuildInfo()
if !ok {
return
}
var vcs, rev, mod string
for _, bs := range bi.Settings {
if bs.Key == "vcs" {
vcs = "/" + bs.Value
}
if bs.Key == "vcs.revision" {
rev = bs.Value
if len(rev) > 12 {
rev = rev[:12]
}
rev = "-" + rev
}
if bs.Key == "vcs.modified" && bs.Value == "true" {
mod = "+"
}
}
softwareVersion += vcs + rev + mod
}
type Sensors struct {
Memory float64
Uptime float64

7
views/mastodon.css Normal file
View File

@ -0,0 +1,7 @@
html {
--bg-page: #353a49;
--bg-dark: #393f4f;
--fg: #fff;
--hl: #6364ff;
--fg-subtle: #606984
}

View File

@ -1,7 +0,0 @@
html {
--bg-page: #1b2735;
--bg-dark: #121a24;
--fg: #b9b9ba;
--hl: #d8a070;
--fg-subtle: rgba(185, 185, 186, 0.5);
}

View File

@ -146,7 +146,7 @@ textarea {
font-size: 1em;
background: var(--bg-page);
color: var(--fg);
width: 600px;
width: 100%;
height: 4em;
margin-bottom: 0.5em;
box-sizing: border-box;

13
web.go
View File

@ -602,7 +602,7 @@ func xzone(w http.ResponseWriter, r *http.Request) {
honkers = append(honkers, Honker{XID: xid})
}
rows.Close()
for i, _ := range honkers {
for i := range honkers {
_, honkers[i].Handle = handles(honkers[i].XID)
}
templinfo := getInfo(r)
@ -733,6 +733,7 @@ func showuser(w http.ResponseWriter, r *http.Request) {
templinfo["Name"] = user.Name
templinfo["WhatAbout"] = user.HTAbout
templinfo["ServerMessage"] = ""
templinfo["APAltLink"] = templates.Sprintf("<link href='%s' rel='alternate' type='application/activity+json'>", user.URL)
if u != nil {
templinfo["HonkCSRF"] = login.GetCSRF("honkhonk", r)
}
@ -2560,6 +2561,9 @@ func apihandler(w http.ResponseWriter, r *http.Request) {
}
func fiveoh(w http.ResponseWriter, r *http.Request) {
if !develMode {
return
}
fd, err := os.OpenFile("violations.json", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
elog.Printf("error opening violations! %s", err)
@ -2606,7 +2610,11 @@ func bgmonitor() {
func addcspheaders(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Security-Policy", "default-src 'none'; script-src 'self'; connect-src 'self'; style-src 'self'; img-src 'self'; media-src 'self'; report-uri /csp-violation")
policy := "default-src 'none'; script-src 'self'; connect-src 'self'; style-src 'self'; img-src 'self'; media-src 'self'"
if develMode {
policy += "; report-uri /csp-violation"
}
w.Header().Set("Content-Security-Policy", policy)
next.ServeHTTP(w, r)
})
}
@ -2648,6 +2656,7 @@ func serve() {
go redeliverator()
go tracker()
go bgmonitor()
go qotd()
loadLingo()
emuinit()