all repos — honk @ 01cf685cacac303376bf0efcdaafb7e9e1702de2

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