all repos — honk @ caa15d152605dadcb21036f5d2251b69124ee7cc

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