all repos — honk @ adc6190ceb2c7314f59d982e92c6e9f3f0f72dc7

my fork of honk

honk.go (view raw)

  1//
  2// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
  3//
  4// Permission to use, copy, modify, and distribute this software for any
  5// purpose with or without fee is hereby granted, provided that the above
  6// copyright notice and this permission notice appear in all copies.
  7//
  8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 10// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 11// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 12// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 13// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 14// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 15
 16package main
 17
 18import (
 19	"crypto/rsa"
 20	"fmt"
 21	"html/template"
 22	"log"
 23	notrand "math/rand"
 24	"os"
 25	"strconv"
 26	"strings"
 27	"time"
 28)
 29
 30func init() {
 31	notrand.Seed(time.Now().Unix())
 32}
 33
 34type WhatAbout struct {
 35	ID      int64
 36	Name    string
 37	Display string
 38	About   string
 39	Key     string
 40	URL     string
 41	Options UserOptions
 42	SecKey  *rsa.PrivateKey
 43}
 44
 45type UserOptions struct {
 46	SkinnyCSS bool `json:",omitempty"`
 47}
 48
 49type KeyInfo struct {
 50	keyname string
 51	seckey  *rsa.PrivateKey
 52}
 53
 54const serverUID int64 = -2
 55
 56type Honk struct {
 57	ID       int64
 58	UserID   int64
 59	Username string
 60	What     string
 61	Honker   string
 62	Handle   string
 63	Oonker   string
 64	Oondle   string
 65	XID      string
 66	RID      string
 67	Date     time.Time
 68	URL      string
 69	Noise    string
 70	Precis   string
 71	Format   string
 72	Convoy   string
 73	Audience []string
 74	Public   bool
 75	Whofore  int64
 76	Replies  []*Honk
 77	Flags    int64
 78	HTPrecis template.HTML
 79	HTML     template.HTML
 80	Style    string
 81	Open     string
 82	Donks    []*Donk
 83	Onts     []string
 84	Place    *Place
 85	Time     *Time
 86}
 87
 88type OldRevision struct {
 89	Precis string
 90	Noise  string
 91}
 92
 93const (
 94	flagIsAcked  = 1
 95	flagIsBonked = 2
 96	flagIsSaved  = 4
 97)
 98
 99func (honk *Honk) IsAcked() bool {
100	return honk.Flags&flagIsAcked != 0
101}
102
103func (honk *Honk) IsBonked() bool {
104	return honk.Flags&flagIsBonked != 0
105}
106
107func (honk *Honk) IsSaved() bool {
108	return honk.Flags&flagIsSaved != 0
109}
110
111type Donk struct {
112	FileID int64
113	XID    string
114	Name   string
115	Desc   string
116	URL    string
117	Media  string
118	Local  bool
119}
120
121type Place struct {
122	Name      string
123	Latitude  float64
124	Longitude float64
125	Url       string
126}
127
128type Duration int64
129
130func (d Duration) String() string {
131	s := time.Duration(d).String()
132	if strings.HasSuffix(s, "m0s") {
133		s = s[:len(s)-2]
134	}
135	if strings.HasSuffix(s, "h0m") {
136		s = s[:len(s)-2]
137	}
138	return s
139}
140
141func parseDuration(s string) time.Duration {
142	didx := strings.IndexByte(s, 'd')
143	if didx != -1 {
144		days, _ := strconv.ParseInt(s[:didx], 10, 0)
145		dur, _ := time.ParseDuration(s[didx:])
146		return dur + 24*time.Hour*time.Duration(days)
147	}
148	dur, _ := time.ParseDuration(s)
149	return dur
150}
151
152type Time struct {
153	StartTime time.Time
154	EndTime   time.Time
155	Duration  Duration
156}
157
158type Honker struct {
159	ID     int64
160	UserID int64
161	Name   string
162	XID    string
163	Handle string
164	Flavor string
165	Combos []string
166}
167
168type SomeThing struct {
169	What  int
170	XID   string
171	Owner string
172	Name  string
173}
174
175const (
176	SomeNothing int = iota
177	SomeActor
178	SomeCollection
179)
180
181var serverName string
182var iconName = "icon.png"
183var serverMsg template.HTML
184var aboutMsg template.HTML
185var loginMsg template.HTML
186
187func ElaborateUnitTests() {
188}
189
190func main() {
191	cmd := "run"
192	if len(os.Args) > 1 {
193		cmd = os.Args[1]
194	}
195	switch cmd {
196	case "init":
197		initdb()
198	case "upgrade":
199		upgradedb()
200	}
201	db := opendatabase()
202	dbversion := 0
203	getconfig("dbversion", &dbversion)
204	if dbversion != myVersion {
205		log.Fatal("incorrect database version. run upgrade.")
206	}
207	getconfig("servermsg", &serverMsg)
208	getconfig("aboutmsg", &aboutMsg)
209	getconfig("loginmsg", &loginMsg)
210	getconfig("servername", &serverName)
211	getconfig("usersep", &userSep)
212	getconfig("honksep", &honkSep)
213	prepareStatements(db)
214	switch cmd {
215	case "admin":
216		adminscreen()
217	case "debug":
218		if len(os.Args) != 3 {
219			log.Fatal("need an argument: debug (on|off)")
220		}
221		switch os.Args[2] {
222		case "on":
223			updateconfig("debug", 1)
224		case "off":
225			updateconfig("debug", 0)
226		default:
227			log.Fatal("argument must be on or off")
228		}
229	case "adduser":
230		adduser()
231	case "chpass":
232		chpass()
233	case "cleanup":
234		arg := "30"
235		if len(os.Args) > 2 {
236			arg = os.Args[2]
237		}
238		cleanupdb(arg)
239	case "ping":
240		if len(os.Args) < 4 {
241			fmt.Printf("usage: honk ping from to\n")
242			return
243		}
244		name := os.Args[2]
245		targ := os.Args[3]
246		user, err := butwhatabout(name)
247		if err != nil {
248			log.Printf("unknown user")
249			return
250		}
251		ping(user, targ)
252	case "run":
253		serve()
254	case "test":
255		ElaborateUnitTests()
256	default:
257		log.Fatal("unknown command")
258	}
259}