all repos — honk @ 8ec0cf92e22ef73c76d48f48b890f30ec04eb377

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	"flag"
 21	"fmt"
 22	"html/template"
 23	"log"
 24	notrand "math/rand"
 25	"os"
 26	"strconv"
 27	"strings"
 28	"time"
 29)
 30
 31var honkVersion = "honk 0.8.0-dev"
 32
 33func init() {
 34	notrand.Seed(time.Now().Unix())
 35}
 36
 37type WhatAbout struct {
 38	ID      int64
 39	Name    string
 40	Display string
 41	About   string
 42	Key     string
 43	URL     string
 44	Options UserOptions
 45	SecKey  *rsa.PrivateKey
 46}
 47
 48type UserOptions struct {
 49	SkinnyCSS bool `json:",omitempty"`
 50}
 51
 52type KeyInfo struct {
 53	keyname string
 54	seckey  *rsa.PrivateKey
 55}
 56
 57const serverUID int64 = -2
 58
 59type Honk struct {
 60	ID       int64
 61	UserID   int64
 62	Username string
 63	What     string
 64	Honker   string
 65	Handle   string
 66	Oonker   string
 67	Oondle   string
 68	XID      string
 69	RID      string
 70	Date     time.Time
 71	URL      string
 72	Noise    string
 73	Precis   string
 74	Format   string
 75	Convoy   string
 76	Audience []string
 77	Public   bool
 78	Whofore  int64
 79	Replies  []*Honk
 80	Flags    int64
 81	HTPrecis template.HTML
 82	HTML     template.HTML
 83	Style    string
 84	Open     string
 85	Donks    []*Donk
 86	Onts     []string
 87	Place    *Place
 88	Time     *Time
 89}
 90
 91type OldRevision struct {
 92	Precis string
 93	Noise  string
 94}
 95
 96const (
 97	flagIsAcked    = 1
 98	flagIsBonked   = 2
 99	flagIsSaved    = 4
100	flagIsUntagged = 8
101)
102
103func (honk *Honk) IsAcked() bool {
104	return honk.Flags&flagIsAcked != 0
105}
106
107func (honk *Honk) IsBonked() bool {
108	return honk.Flags&flagIsBonked != 0
109}
110
111func (honk *Honk) IsSaved() bool {
112	return honk.Flags&flagIsSaved != 0
113}
114
115func (honk *Honk) IsUntagged() bool {
116	return honk.Flags&flagIsUntagged != 0
117}
118
119type Donk struct {
120	FileID int64
121	XID    string
122	Name   string
123	Desc   string
124	URL    string
125	Media  string
126	Local  bool
127}
128
129type Place struct {
130	Name      string
131	Latitude  float64
132	Longitude float64
133	Url       string
134}
135
136type Duration int64
137
138func (d Duration) String() string {
139	s := time.Duration(d).String()
140	if strings.HasSuffix(s, "m0s") {
141		s = s[:len(s)-2]
142	}
143	if strings.HasSuffix(s, "h0m") {
144		s = s[:len(s)-2]
145	}
146	return s
147}
148
149func parseDuration(s string) time.Duration {
150	didx := strings.IndexByte(s, 'd')
151	if didx != -1 {
152		days, _ := strconv.ParseInt(s[:didx], 10, 0)
153		dur, _ := time.ParseDuration(s[didx:])
154		return dur + 24*time.Hour*time.Duration(days)
155	}
156	dur, _ := time.ParseDuration(s)
157	return dur
158}
159
160type Time struct {
161	StartTime time.Time
162	EndTime   time.Time
163	Duration  Duration
164}
165
166type Honker struct {
167	ID     int64
168	UserID int64
169	Name   string
170	XID    string
171	Handle string
172	Flavor string
173	Combos []string
174}
175
176type SomeThing struct {
177	What  int
178	XID   string
179	Owner string
180	Name  string
181}
182
183const (
184	SomeNothing int = iota
185	SomeActor
186	SomeCollection
187)
188
189var serverName string
190var dataDir = "."
191var viewDir = "."
192var iconName = "icon.png"
193var serverMsg template.HTML
194var aboutMsg template.HTML
195var loginMsg template.HTML
196
197func ElaborateUnitTests() {
198}
199
200func main() {
201	flag.StringVar(&dataDir, "datadir", dataDir, "data directory")
202	flag.StringVar(&viewDir, "viewdir", viewDir, "view directory")
203	flag.Parse()
204	args := flag.Args()
205	cmd := "run"
206	if len(args) > 0 {
207		cmd = args[0]
208	}
209	switch cmd {
210	case "init":
211		initdb()
212	case "upgrade":
213		upgradedb()
214	case "version":
215		fmt.Println(honkVersion)
216		os.Exit(0)
217	}
218	db := opendatabase()
219	dbversion := 0
220	getconfig("dbversion", &dbversion)
221	if dbversion != myVersion {
222		log.Fatal("incorrect database version. run upgrade.")
223	}
224	getconfig("servermsg", &serverMsg)
225	getconfig("aboutmsg", &aboutMsg)
226	getconfig("loginmsg", &loginMsg)
227	getconfig("servername", &serverName)
228	getconfig("usersep", &userSep)
229	getconfig("honksep", &honkSep)
230	prepareStatements(db)
231	switch cmd {
232	case "admin":
233		adminscreen()
234	case "debug":
235		if len(args) != 2 {
236			log.Fatal("need an argument: debug (on|off)")
237		}
238		switch args[1] {
239		case "on":
240			updateconfig("debug", 1)
241		case "off":
242			updateconfig("debug", 0)
243		default:
244			log.Fatal("argument must be on or off")
245		}
246	case "adduser":
247		adduser()
248	case "chpass":
249		chpass()
250	case "cleanup":
251		arg := "30"
252		if len(args) > 1 {
253			arg = args[1]
254		}
255		cleanupdb(arg)
256	case "ping":
257		if len(args) < 3 {
258			fmt.Printf("usage: honk ping from to\n")
259			return
260		}
261		name := args[1]
262		targ := args[2]
263		user, err := butwhatabout(name)
264		if err != nil {
265			log.Printf("unknown user")
266			return
267		}
268		ping(user, targ)
269	case "run":
270		serve()
271	case "test":
272		ElaborateUnitTests()
273	default:
274		log.Fatal("unknown command")
275	}
276}