all repos — honk @ 270c3980a18b8833d2b48b9d80943d9f47082dbf

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	"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	flagIsUntagged = 8
 98)
 99
100func (honk *Honk) IsAcked() bool {
101	return honk.Flags&flagIsAcked != 0
102}
103
104func (honk *Honk) IsBonked() bool {
105	return honk.Flags&flagIsBonked != 0
106}
107
108func (honk *Honk) IsSaved() bool {
109	return honk.Flags&flagIsSaved != 0
110}
111
112func (honk *Honk) IsUntagged() bool {
113	return honk.Flags&flagIsUntagged != 0
114}
115
116type Donk struct {
117	FileID int64
118	XID    string
119	Name   string
120	Desc   string
121	URL    string
122	Media  string
123	Local  bool
124}
125
126type Place struct {
127	Name      string
128	Latitude  float64
129	Longitude float64
130	Url       string
131}
132
133type Duration int64
134
135func (d Duration) String() string {
136	s := time.Duration(d).String()
137	if strings.HasSuffix(s, "m0s") {
138		s = s[:len(s)-2]
139	}
140	if strings.HasSuffix(s, "h0m") {
141		s = s[:len(s)-2]
142	}
143	return s
144}
145
146func parseDuration(s string) time.Duration {
147	didx := strings.IndexByte(s, 'd')
148	if didx != -1 {
149		days, _ := strconv.ParseInt(s[:didx], 10, 0)
150		dur, _ := time.ParseDuration(s[didx:])
151		return dur + 24*time.Hour*time.Duration(days)
152	}
153	dur, _ := time.ParseDuration(s)
154	return dur
155}
156
157type Time struct {
158	StartTime time.Time
159	EndTime   time.Time
160	Duration  Duration
161}
162
163type Honker struct {
164	ID     int64
165	UserID int64
166	Name   string
167	XID    string
168	Handle string
169	Flavor string
170	Combos []string
171}
172
173type SomeThing struct {
174	What  int
175	XID   string
176	Owner string
177	Name  string
178}
179
180const (
181	SomeNothing int = iota
182	SomeActor
183	SomeCollection
184)
185
186var serverName string
187var dataDir = "."
188var viewDir = "."
189var iconName = "icon.png"
190var serverMsg template.HTML
191var aboutMsg template.HTML
192var loginMsg template.HTML
193
194func ElaborateUnitTests() {
195}
196
197func main() {
198	flag.StringVar(&dataDir, "datadir", dataDir, "data directory")
199	flag.StringVar(&viewDir, "viewdir", viewDir, "view directory")
200	flag.Parse()
201	args := flag.Args()
202	cmd := "run"
203	if len(args) > 0 {
204		cmd = args[0]
205	}
206	switch cmd {
207	case "init":
208		initdb()
209	case "upgrade":
210		upgradedb()
211	}
212	db := opendatabase()
213	dbversion := 0
214	getconfig("dbversion", &dbversion)
215	if dbversion != myVersion {
216		log.Fatal("incorrect database version. run upgrade.")
217	}
218	getconfig("servermsg", &serverMsg)
219	getconfig("aboutmsg", &aboutMsg)
220	getconfig("loginmsg", &loginMsg)
221	getconfig("servername", &serverName)
222	getconfig("usersep", &userSep)
223	getconfig("honksep", &honkSep)
224	prepareStatements(db)
225	switch cmd {
226	case "admin":
227		adminscreen()
228	case "debug":
229		if len(args) != 2 {
230			log.Fatal("need an argument: debug (on|off)")
231		}
232		switch args[1] {
233		case "on":
234			updateconfig("debug", 1)
235		case "off":
236			updateconfig("debug", 0)
237		default:
238			log.Fatal("argument must be on or off")
239		}
240	case "adduser":
241		adduser()
242	case "chpass":
243		chpass()
244	case "cleanup":
245		arg := "30"
246		if len(args) > 1 {
247			arg = args[1]
248		}
249		cleanupdb(arg)
250	case "ping":
251		if len(args) < 3 {
252			fmt.Printf("usage: honk ping from to\n")
253			return
254		}
255		name := args[1]
256		targ := args[2]
257		user, err := butwhatabout(name)
258		if err != nil {
259			log.Printf("unknown user")
260			return
261		}
262		ping(user, targ)
263	case "run":
264		serve()
265	case "test":
266		ElaborateUnitTests()
267	default:
268		log.Fatal("unknown command")
269	}
270}