all repos — honk @ e5cbd10ac388882962a35b34e11bb8cc33d12e4e

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