all repos — honk @ a936f884ba29801e5b6599392191e60daba9e2c1

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	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 iconName = "icon.png"
188var serverMsg template.HTML
189var aboutMsg template.HTML
190var loginMsg template.HTML
191
192func ElaborateUnitTests() {
193}
194
195func main() {
196	cmd := "run"
197	if len(os.Args) > 1 {
198		cmd = os.Args[1]
199	}
200	switch cmd {
201	case "init":
202		initdb()
203	case "upgrade":
204		upgradedb()
205	}
206	db := opendatabase()
207	dbversion := 0
208	getconfig("dbversion", &dbversion)
209	if dbversion != myVersion {
210		log.Fatal("incorrect database version. run upgrade.")
211	}
212	getconfig("servermsg", &serverMsg)
213	getconfig("aboutmsg", &aboutMsg)
214	getconfig("loginmsg", &loginMsg)
215	getconfig("servername", &serverName)
216	getconfig("usersep", &userSep)
217	getconfig("honksep", &honkSep)
218	prepareStatements(db)
219	switch cmd {
220	case "admin":
221		adminscreen()
222	case "debug":
223		if len(os.Args) != 3 {
224			log.Fatal("need an argument: debug (on|off)")
225		}
226		switch os.Args[2] {
227		case "on":
228			updateconfig("debug", 1)
229		case "off":
230			updateconfig("debug", 0)
231		default:
232			log.Fatal("argument must be on or off")
233		}
234	case "adduser":
235		adduser()
236	case "chpass":
237		chpass()
238	case "cleanup":
239		arg := "30"
240		if len(os.Args) > 2 {
241			arg = os.Args[2]
242		}
243		cleanupdb(arg)
244	case "ping":
245		if len(os.Args) < 4 {
246			fmt.Printf("usage: honk ping from to\n")
247			return
248		}
249		name := os.Args[2]
250		targ := os.Args[3]
251		user, err := butwhatabout(name)
252		if err != nil {
253			log.Printf("unknown user")
254			return
255		}
256		ping(user, targ)
257	case "run":
258		serve()
259	case "test":
260		ElaborateUnitTests()
261	default:
262		log.Fatal("unknown command")
263	}
264}