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