2019-09-10 20:43:34 +02:00
//
// Copyright (c) 2019 Ted Unangst <tedu@tedunangst.com>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package main
import (
2019-10-02 23:27:29 +02:00
"bytes"
2020-09-30 21:20:40 +02:00
"crypto/sha512"
2019-09-10 20:43:34 +02:00
"database/sql"
2022-05-31 08:32:22 +02:00
_ "embed"
2022-05-31 09:06:09 +02:00
"encoding/json"
2019-09-10 20:43:34 +02:00
"fmt"
2020-09-26 01:02:26 +02:00
"html/template"
2019-10-11 02:37:03 +02:00
"sort"
2019-09-10 20:43:34 +02:00
"strconv"
"strings"
2021-02-10 00:48:36 +01:00
"sync"
2019-09-10 20:43:34 +02:00
"time"
2019-10-13 01:25:23 +02:00
"humungus.tedunangst.com/r/webs/cache"
2019-10-25 23:31:48 +02:00
"humungus.tedunangst.com/r/webs/httpsig"
2019-09-10 20:43:34 +02:00
"humungus.tedunangst.com/r/webs/login"
2020-09-26 01:02:26 +02:00
"humungus.tedunangst.com/r/webs/mz"
2019-09-10 20:43:34 +02:00
)
2022-05-31 08:32:22 +02:00
//go:embed schema.sql
var sqlSchema string
2019-10-26 00:46:27 +02:00
func userfromrow ( row * sql . Row ) ( * WhatAbout , error ) {
2019-10-07 21:47:37 +02:00
user := new ( WhatAbout )
2019-10-26 00:46:27 +02:00
var seckey , options string
err := row . Scan ( & user . ID , & user . Name , & user . Display , & user . About , & user . Key , & seckey , & options )
if err == nil {
user . SecKey , _ , err = httpsig . DecodeKey ( seckey )
}
if err != nil {
return nil , err
}
if user . ID > 0 {
user . URL = fmt . Sprintf ( "https://%s/%s/%s" , serverName , userSep , user . Name )
2019-10-29 06:00:38 +01:00
err = unjsonify ( options , & user . Options )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error processing user options: %s" , err )
2019-10-29 06:00:38 +01:00
}
2019-10-26 00:46:27 +02:00
} else {
user . URL = fmt . Sprintf ( "https://%s/%s" , serverName , user . Name )
}
2020-01-24 00:08:15 +01:00
if user . Options . Reaction == "" {
2020-02-07 17:57:00 +01:00
user . Options . R eaction = "none"
2020-01-24 00:08:15 +01:00
}
2020-09-26 01:02:26 +02:00
2019-10-26 00:46:27 +02:00
return user , nil
}
var somenamedusers = cache . New ( cache . Options { Filler : func ( name string ) ( * WhatAbout , bool ) {
row := stmtUserByName . QueryRow ( name )
user , err := userfromrow ( row )
2019-10-07 21:29:34 +02:00
if err != nil {
return nil , false
}
2022-05-20 21:50:33 +02:00
var marker mz . Marker
marker . HashLinker = ontoreplacer
marker . AtLinker = attoreplacer
user . HTAbout = template . HTML ( marker . Mark ( user . About ) )
user . Onts = marker . HashTags
2019-10-07 21:29:34 +02:00
return user , true
} } )
2019-10-26 00:46:27 +02:00
var somenumberedusers = cache . New ( cache . Options { Filler : func ( userid int64 ) ( * WhatAbout , bool ) {
row := stmtUserByNumber . QueryRow ( userid )
user , err := userfromrow ( row )
if err != nil {
return nil , false
}
2022-05-20 21:50:33 +02:00
// don't touch attoreplacer, which introduces a loop
// finger -> getjunk -> keys -> users
2019-10-26 00:46:27 +02:00
return user , true
} } )
2019-10-25 23:31:48 +02:00
func getserveruser ( ) * WhatAbout {
2019-10-26 00:46:27 +02:00
var user * WhatAbout
ok := somenumberedusers . Get ( serverUID , & user )
if ! ok {
2022-02-06 06:42:13 +01:00
elog . Panicf ( "lost server user" )
2019-10-25 23:31:48 +02:00
}
2019-10-26 00:46:27 +02:00
return user
2019-10-25 23:31:48 +02:00
}
2019-10-07 21:29:34 +02:00
func butwhatabout ( name string ) ( * WhatAbout , error ) {
var user * WhatAbout
2019-10-26 00:46:27 +02:00
ok := somenamedusers . Get ( name , & user )
2019-10-07 21:29:34 +02:00
if ! ok {
return nil , fmt . Errorf ( "no user: %s" , name )
}
return user , nil
2019-09-10 20:43:34 +02:00
}
2019-10-16 05:27:30 +02:00
var honkerinvalidator cache . Invalidator
2019-09-10 20:43:34 +02:00
func gethonkers ( userid int64 ) [ ] * Honker {
rows , err := stmtHonkers . Query ( userid )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error querying honkers: %s" , err )
2019-09-10 20:43:34 +02:00
return nil
}
defer rows . Close ( )
var honkers [ ] * Honker
for rows . Next ( ) {
2019-10-21 07:29:39 +02:00
h := new ( Honker )
2019-12-03 00:26:29 +01:00
var combos , meta string
err = rows . Scan ( & h . ID , & h . UserID , & h . Name , & h . XID , & h . Flavor , & combos , & meta )
if err == nil {
err = unjsonify ( meta , & h . Meta )
}
2019-09-10 20:43:34 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning honker: %s" , err )
2019-12-03 00:26:29 +01:00
continue
2019-09-10 20:43:34 +02:00
}
2019-12-03 00:26:29 +01:00
h . Combos = strings . Split ( strings . TrimSpace ( combos ) , " " )
2019-10-21 07:29:39 +02:00
honkers = append ( honkers , h )
2019-09-10 20:43:34 +02:00
}
return honkers
}
func getdubs ( userid int64 ) [ ] * Honker {
rows , err := stmtDubbers . Query ( userid )
2019-10-26 02:31:07 +02:00
return dubsfromrows ( rows , err )
}
func getnameddubs ( userid int64 , name string ) [ ] * Honker {
rows , err := stmtNamedDubbers . Query ( userid , name )
return dubsfromrows ( rows , err )
}
func dubsfromrows ( rows * sql . Rows , err error ) [ ] * Honker {
2019-09-10 20:43:34 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error querying dubs: %s" , err )
2019-09-10 20:43:34 +02:00
return nil
}
defer rows . Close ( )
var honkers [ ] * Honker
for rows . Next ( ) {
2019-10-21 07:29:39 +02:00
h := new ( Honker )
err = rows . Scan ( & h . ID , & h . UserID , & h . Name , & h . XID , & h . Flavor )
2019-09-10 20:43:34 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning honker: %s" , err )
2019-09-10 20:43:34 +02:00
return nil
}
2019-10-21 07:29:39 +02:00
honkers = append ( honkers , h )
2019-09-10 20:43:34 +02:00
}
return honkers
}
func allusers ( ) [ ] login . UserInfo {
var users [ ] login . UserInfo
2019-10-25 23:31:48 +02:00
rows , _ := opendatabase ( ) . Query ( "select userid, username from users where userid > 0" )
2019-09-10 20:43:34 +02:00
defer rows . Close ( )
for rows . Next ( ) {
var u login . UserInfo
rows . Scan ( & u . UserID , & u . Username )
users = append ( users , u )
}
return users
}
2019-09-16 22:46:14 +02:00
func getxonk ( userid int64 , xid string ) * Honk {
row := stmtOneXonk . QueryRow ( userid , xid )
2019-09-16 22:51:47 +02:00
return scanhonk ( row )
2019-09-16 22:46:14 +02:00
}
2019-09-10 20:43:34 +02:00
func getbonk ( userid int64 , xid string ) * Honk {
row := stmtOneBonk . QueryRow ( userid , xid )
2019-09-16 22:51:47 +02:00
return scanhonk ( row )
2019-09-10 20:43:34 +02:00
}
func getpublichonks ( ) [ ] * Honk {
2022-04-12 20:40:17 +02:00
dt := time . Now ( ) . Add ( - 7 * 24 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
2019-11-13 07:01:34 +01:00
rows , err := stmtPublicHonks . Query ( dt , 100 )
2019-09-10 20:43:34 +02:00
return getsomehonks ( rows , err )
}
2019-10-11 02:37:03 +02:00
func geteventhonks ( userid int64 ) [ ] * Honk {
2019-11-12 07:43:16 +01:00
rows , err := stmtEventHonks . Query ( userid , 25 )
2019-10-11 02:37:03 +02:00
honks := getsomehonks ( rows , err )
sort . Slice ( honks , func ( i , j int ) bool {
var t1 , t2 time . Time
if honks [ i ] . Time == nil {
t1 = honks [ i ] . Date
} else {
t1 = honks [ i ] . Time . StartTime
}
if honks [ j ] . Time == nil {
t2 = honks [ j ] . Date
} else {
t2 = honks [ j ] . Time . StartTime
}
return t1 . After ( t2 )
} )
now := time . Now ( ) . Add ( - 24 * time . Hour )
for i , h := range honks {
2019-12-16 23:36:04 +01:00
t := h . Date
if tm := h . Time ; tm != nil {
t = tm . StartTime
}
if t . Before ( now ) {
2019-10-11 02:37:03 +02:00
honks = honks [ : i ]
break
}
}
reversehonks ( honks )
return honks
}
2019-10-20 20:36:55 +02:00
func gethonksbyuser ( name string , includeprivate bool , wanted int64 ) [ ] * Honk {
2022-04-12 20:40:17 +02:00
dt := time . Now ( ) . Add ( - 7 * 24 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
2019-11-13 07:01:34 +01:00
limit := 50
2019-09-10 20:43:34 +02:00
whofore := 2
if includeprivate {
whofore = 3
}
2019-11-12 07:43:16 +01:00
rows , err := stmtUserHonks . Query ( wanted , whofore , name , dt , limit )
2019-09-10 20:43:34 +02:00
return getsomehonks ( rows , err )
}
2019-10-20 20:36:55 +02:00
func gethonksforuser ( userid int64 , wanted int64 ) [ ] * Honk {
2022-04-12 20:40:17 +02:00
dt := time . Now ( ) . Add ( - 7 * 24 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
2019-10-20 20:36:55 +02:00
rows , err := stmtHonksForUser . Query ( wanted , userid , dt , userid , userid )
2019-09-10 20:43:34 +02:00
return getsomehonks ( rows , err )
}
2019-10-20 20:36:55 +02:00
func gethonksforuserfirstclass ( userid int64 , wanted int64 ) [ ] * Honk {
2022-04-12 20:40:17 +02:00
dt := time . Now ( ) . Add ( - 7 * 24 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
2019-10-20 20:36:55 +02:00
rows , err := stmtHonksForUserFirstClass . Query ( wanted , userid , dt , userid , userid )
2019-09-26 17:28:05 +02:00
return getsomehonks ( rows , err )
}
2019-10-30 05:20:41 +01:00
2019-10-20 20:36:55 +02:00
func gethonksforme ( userid int64 , wanted int64 ) [ ] * Honk {
2022-04-12 20:40:17 +02:00
dt := time . Now ( ) . Add ( - 7 * 24 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
2019-10-20 20:36:55 +02:00
rows , err := stmtHonksForMe . Query ( wanted , userid , dt , userid )
2019-11-03 18:54:38 +01:00
return getsomehonks ( rows , err )
2019-09-10 20:43:34 +02:00
}
2020-07-20 00:51:02 +02:00
func gethonksfromlongago ( userid int64 , wanted int64 ) [ ] * Honk {
2022-04-12 20:40:17 +02:00
now := time . Now ( )
2022-02-11 02:30:39 +01:00
var honks [ ] * Honk
for i := 1 ; i <= 3 ; i ++ {
dt := time . Date ( now . Year ( ) - i , now . Month ( ) , now . Day ( ) , now . Hour ( ) , now . Minute ( ) ,
now . Second ( ) , 0 , now . Location ( ) )
2022-04-12 20:40:17 +02:00
dt1 := dt . Add ( - 36 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
dt2 := dt . Add ( 12 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
2022-02-11 02:30:39 +01:00
rows , err := stmtHonksFromLongAgo . Query ( wanted , userid , dt1 , dt2 , userid )
honks = append ( honks , getsomehonks ( rows , err ) ... )
}
return honks
2020-07-20 00:51:02 +02:00
}
2019-10-20 20:36:55 +02:00
func getsavedhonks ( userid int64 , wanted int64 ) [ ] * Honk {
rows , err := stmtHonksISaved . Query ( wanted , userid )
2019-10-11 22:03:17 +02:00
return getsomehonks ( rows , err )
}
2019-10-20 20:36:55 +02:00
func gethonksbyhonker ( userid int64 , honker string , wanted int64 ) [ ] * Honk {
rows , err := stmtHonksByHonker . Query ( wanted , userid , honker , userid )
2019-09-10 20:43:34 +02:00
return getsomehonks ( rows , err )
}
2019-10-20 20:36:55 +02:00
func gethonksbyxonker ( userid int64 , xonker string , wanted int64 ) [ ] * Honk {
rows , err := stmtHonksByXonker . Query ( wanted , userid , xonker , xonker , userid )
2019-09-10 20:43:34 +02:00
return getsomehonks ( rows , err )
}
2019-10-20 20:36:55 +02:00
func gethonksbycombo ( userid int64 , combo string , wanted int64 ) [ ] * Honk {
2019-09-10 20:43:34 +02:00
combo = "% " + combo + " %"
2019-10-30 05:02:23 +01:00
rows , err := stmtHonksByCombo . Query ( wanted , userid , userid , combo , userid , wanted , userid , combo , userid )
2019-09-10 20:43:34 +02:00
return getsomehonks ( rows , err )
}
2019-10-20 20:36:55 +02:00
func gethonksbyconvoy ( userid int64 , convoy string , wanted int64 ) [ ] * Honk {
rows , err := stmtHonksByConvoy . Query ( wanted , userid , userid , convoy )
2019-09-10 20:43:34 +02:00
honks := getsomehonks ( rows , err )
return honks
}
2019-10-20 20:36:55 +02:00
func gethonksbysearch ( userid int64 , q string , wanted int64 ) [ ] * Honk {
2020-01-12 09:43:45 +01:00
var queries [ ] string
var params [ ] interface { }
queries = append ( queries , "honks.honkid > ?" )
params = append ( params , wanted )
queries = append ( queries , "honks.userid = ?" )
params = append ( params , userid )
2019-10-16 05:27:30 +02:00
terms := strings . Split ( q , " " )
for _ , t := range terms {
2020-07-07 22:53:30 +02:00
if t == "" {
continue
}
2020-01-12 09:43:45 +01:00
negate := " "
if t [ 0 ] == '-' {
t = t [ 1 : ]
negate = " not "
}
if t == "" {
continue
}
2019-10-16 05:27:30 +02:00
if strings . HasPrefix ( t , "site:" ) {
2020-01-12 09:43:45 +01:00
site := t [ 5 : ]
2019-10-16 05:27:30 +02:00
site = "%" + site + "%"
2020-01-12 09:43:45 +01:00
queries = append ( queries , "xid" + negate + "like ?" )
params = append ( params , site )
2019-10-16 05:27:30 +02:00
continue
}
if strings . HasPrefix ( t , "honker:" ) {
2020-01-12 09:43:45 +01:00
honker := t [ 7 : ]
2019-10-16 05:27:30 +02:00
xid := fullname ( honker , userid )
if xid != "" {
honker = xid
}
2020-01-12 09:43:45 +01:00
queries = append ( queries , negate + "(honks.honker = ? or honks.oonker = ?)" )
params = append ( params , honker )
params = append ( params , honker )
2019-10-16 05:27:30 +02:00
continue
}
2020-01-12 09:43:45 +01:00
t = "%" + t + "%"
queries = append ( queries , "noise" + negate + "like ?" )
params = append ( params , t )
2019-11-28 08:14:07 +01:00
}
2020-01-12 09:43:45 +01:00
selecthonks := "select honks.honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, format, convoy, whofore, flags from honks join users on honks.userid = users.userid "
where := "where " + strings . Join ( queries , " and " )
butnotthose := " and convoy not in (select name from zonkers where userid = ? and wherefore = 'zonvoy' order by zonkerid desc limit 100)"
limit := " order by honks.honkid desc limit 250"
params = append ( params , userid )
rows , err := opendatabase ( ) . Query ( selecthonks + where + butnotthose + limit , params ... )
2019-09-10 20:43:34 +02:00
honks := getsomehonks ( rows , err )
return honks
}
2019-10-20 20:36:55 +02:00
func gethonksbyontology ( userid int64 , name string , wanted int64 ) [ ] * Honk {
rows , err := stmtHonksByOntology . Query ( wanted , name , userid , userid )
2019-09-10 20:43:34 +02:00
honks := getsomehonks ( rows , err )
return honks
}
2019-10-08 06:58:42 +02:00
func reversehonks ( honks [ ] * Honk ) {
for i , j := 0 , len ( honks ) - 1 ; i < j ; i , j = i + 1 , j - 1 {
honks [ i ] , honks [ j ] = honks [ j ] , honks [ i ]
}
}
2019-09-10 20:43:34 +02:00
func getsomehonks ( rows * sql . Rows , err error ) [ ] * Honk {
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error querying honks: %s" , err )
2019-09-10 20:43:34 +02:00
return nil
}
defer rows . Close ( )
var honks [ ] * Honk
for rows . Next ( ) {
2019-09-16 22:51:47 +02:00
h := scanhonk ( rows )
if h != nil {
honks = append ( honks , h )
2019-09-10 20:43:34 +02:00
}
}
rows . Close ( )
donksforhonks ( honks )
return honks
}
2019-09-16 22:51:47 +02:00
type RowLike interface {
Scan ( dest ... interface { } ) error
}
func scanhonk ( row RowLike ) * Honk {
h := new ( Honk )
2019-09-22 23:00:14 +02:00
var dt , aud string
2019-09-16 22:51:47 +02:00
err := row . Scan ( & h . ID , & h . UserID , & h . Username , & h . What , & h . Honker , & h . Oonker , & h . XID , & h . RID ,
2019-09-22 23:00:14 +02:00
& dt , & h . URL , & aud , & h . Noise , & h . Precis , & h . Format , & h . Convoy , & h . Whofore , & h . Flags )
2019-09-16 22:51:47 +02:00
if err != nil {
if err != sql . ErrNoRows {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning honk: %s" , err )
2019-09-16 22:51:47 +02:00
}
return nil
}
h . Date , _ = time . Parse ( dbtimeformat , dt )
h . Audience = strings . Split ( aud , " " )
2019-10-30 08:39:56 +01:00
h . Public = loudandproud ( h . Audience )
2019-09-16 22:51:47 +02:00
return h
}
2019-09-10 20:43:34 +02:00
func donksforhonks ( honks [ ] * Honk ) {
db := opendatabase ( )
var ids [ ] string
hmap := make ( map [ int64 ] * Honk )
for _ , h := range honks {
ids = append ( ids , fmt . Sprintf ( "%d" , h . ID ) )
hmap [ h . ID ] = h
}
2019-10-30 08:36:28 +01:00
idset := strings . Join ( ids , "," )
2019-09-22 23:00:14 +02:00
// grab donks
2019-10-30 08:36:28 +01:00
q := fmt . Sprintf ( "select honkid, donks.fileid, xid, name, description, url, media, local from donks join filemeta on donks.fileid = filemeta.fileid where honkid in (%s)" , idset )
2019-09-10 20:43:34 +02:00
rows , err := db . Query ( q )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error querying donks: %s" , err )
2019-09-10 20:43:34 +02:00
return
}
defer rows . Close ( )
for rows . Next ( ) {
var hid int64
2019-10-21 07:29:39 +02:00
d := new ( Donk )
2019-09-10 20:43:34 +02:00
err = rows . Scan ( & hid , & d . FileID , & d . XID , & d . Name , & d . Desc , & d . URL , & d . Media , & d . Local )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning donk: %s" , err )
2019-09-10 20:43:34 +02:00
continue
}
2020-10-01 19:18:05 +02:00
d . External = ! strings . HasPrefix ( d . URL , serverPrefix )
2019-09-10 20:43:34 +02:00
h := hmap [ hid ]
2019-10-21 07:29:39 +02:00
h . Donks = append ( h . Donks , d )
2019-09-10 20:43:34 +02:00
}
2019-09-22 23:00:14 +02:00
rows . Close ( )
// grab onts
2019-10-30 08:36:28 +01:00
q = fmt . Sprintf ( "select honkid, ontology from onts where honkid in (%s)" , idset )
2019-09-22 23:00:14 +02:00
rows , err = db . Query ( q )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error querying onts: %s" , err )
2019-09-22 23:00:14 +02:00
return
}
defer rows . Close ( )
for rows . Next ( ) {
var hid int64
var o string
err = rows . Scan ( & hid , & o )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning donk: %s" , err )
2019-09-22 23:00:14 +02:00
continue
}
h := hmap [ hid ]
h . Onts = append ( h . Onts , o )
}
rows . Close ( )
2019-10-30 08:36:28 +01:00
2019-10-02 23:10:01 +02:00
// grab meta
2019-10-30 08:36:28 +01:00
q = fmt . Sprintf ( "select honkid, genus, json from honkmeta where honkid in (%s)" , idset )
2019-09-28 06:12:50 +02:00
rows , err = db . Query ( q )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error querying honkmeta: %s" , err )
2019-09-28 06:12:50 +02:00
return
}
defer rows . Close ( )
for rows . Next ( ) {
var hid int64
2019-10-02 23:10:01 +02:00
var genus , j string
err = rows . Scan ( & hid , & genus , & j )
2019-09-28 06:12:50 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning honkmeta: %s" , err )
2019-09-28 06:12:50 +02:00
continue
}
h := hmap [ hid ]
2019-10-02 23:10:01 +02:00
switch genus {
case "place" :
p := new ( Place )
err = unjsonify ( j , p )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error parsing place: %s" , err )
2019-10-02 23:10:01 +02:00
continue
}
h . Place = p
2019-10-03 00:20:14 +02:00
case "time" :
t := new ( Time )
err = unjsonify ( j , t )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error parsing time: %s" , err )
2019-10-03 00:20:14 +02:00
continue
}
h . Time = t
2019-11-27 20:36:29 +01:00
case "mentions" :
err = unjsonify ( j , & h . Mentions )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error parsing mentions: %s" , err )
2019-11-27 20:36:29 +01:00
continue
}
2021-02-09 15:00:08 +01:00
case "badonks" :
err = unjsonify ( j , & h . Badonks )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error parsing badonks: %s" , err )
2021-02-09 15:00:08 +01:00
continue
}
2022-02-09 23:11:55 +01:00
case "wonkles" :
h . Wonkles = j
2022-02-12 20:58:57 +01:00
case "guesses" :
h . Guesses = template . HTML ( j )
2019-10-02 23:10:01 +02:00
case "oldrev" :
default :
2022-02-06 06:42:13 +01:00
elog . Printf ( "unknown meta genus: %s" , genus )
2019-10-02 23:10:01 +02:00
}
2019-09-28 06:12:50 +02:00
}
rows . Close ( )
2019-09-10 20:43:34 +02:00
}
2020-05-15 05:54:29 +02:00
func donksforchonks ( chonks [ ] * Chonk ) {
db := opendatabase ( )
var ids [ ] string
chmap := make ( map [ int64 ] * Chonk )
for _ , ch := range chonks {
ids = append ( ids , fmt . Sprintf ( "%d" , ch . ID ) )
chmap [ ch . ID ] = ch
}
idset := strings . Join ( ids , "," )
// grab donks
q := fmt . Sprintf ( "select chonkid, donks.fileid, xid, name, description, url, media, local from donks join filemeta on donks.fileid = filemeta.fileid where chonkid in (%s)" , idset )
rows , err := db . Query ( q )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error querying donks: %s" , err )
2020-05-15 05:54:29 +02:00
return
}
defer rows . Close ( )
for rows . Next ( ) {
var chid int64
d := new ( Donk )
err = rows . Scan ( & chid , & d . FileID , & d . XID , & d . Name , & d . Desc , & d . URL , & d . Media , & d . Local )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning donk: %s" , err )
2020-05-15 05:54:29 +02:00
continue
}
ch := chmap [ chid ]
ch . Donks = append ( ch . Donks , d )
}
}
2020-09-30 17:35:18 +02:00
func savefile ( name string , desc string , url string , media string , local bool , data [ ] byte ) ( int64 , error ) {
fileid , _ , err := savefileandxid ( name , desc , url , media , local , data )
return fileid , err
}
2020-09-30 21:20:40 +02:00
func hashfiledata ( data [ ] byte ) string {
h := sha512 . New512_256 ( )
h . Write ( data )
return fmt . Sprintf ( "%x" , h . Sum ( nil ) )
}
2020-09-30 17:35:18 +02:00
func savefileandxid ( name string , desc string , url string , media string , local bool , data [ ] byte ) ( int64 , string , error ) {
2020-09-30 21:20:40 +02:00
var xid string
if local {
hash := hashfiledata ( data )
row := stmtCheckFileData . QueryRow ( hash )
err := row . Scan ( & xid )
if err == sql . ErrNoRows {
xid = xfiltrate ( )
switch media {
case "image/png" :
xid += ".png"
case "image/jpeg" :
xid += ".jpg"
case "application/pdf" :
xid += ".pdf"
case "text/plain" :
xid += ".txt"
}
_ , err = stmtSaveFileData . Exec ( xid , media , hash , data )
if err != nil {
return 0 , "" , err
}
} else if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error checking file hash: %s" , err )
2020-09-30 21:20:40 +02:00
return 0 , "" , err
}
if url == "" {
url = fmt . Sprintf ( "https://%s/d/%s" , serverName , xid )
}
2020-09-30 17:35:18 +02:00
}
2019-09-30 03:40:37 +02:00
res , err := stmtSaveFile . Exec ( xid , name , desc , url , media , local )
if err != nil {
2020-09-30 17:35:18 +02:00
return 0 , "" , err
2019-09-30 03:40:37 +02:00
}
fileid , _ := res . LastInsertId ( )
2020-09-30 17:35:18 +02:00
return fileid , xid , nil
2019-09-30 03:40:37 +02:00
}
2019-10-03 05:02:01 +02:00
func finddonk ( url string ) * Donk {
donk := new ( Donk )
row := stmtFindFile . QueryRow ( url )
err := row . Scan ( & donk . FileID , & donk . XID )
if err == nil {
return donk
}
if err != sql . ErrNoRows {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error finding file: %s" , err )
2019-10-03 05:02:01 +02:00
}
return nil
}
2020-05-13 23:15:29 +02:00
func savechonk ( ch * Chonk ) error {
dt := ch . Date . UTC ( ) . Format ( dbtimeformat )
2020-05-15 05:51:42 +02:00
db := opendatabase ( )
tx , err := db . Begin ( )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "can't begin tx: %s" , err )
2020-05-15 05:51:42 +02:00
return err
}
res , err := tx . Stmt ( stmtSaveChonk ) . Exec ( ch . UserID , ch . XID , ch . Who , ch . Target , dt , ch . Noise , ch . Format )
2020-05-13 23:15:29 +02:00
if err == nil {
ch . ID , _ = res . LastInsertId ( )
2020-05-15 05:51:42 +02:00
for _ , d := range ch . Donks {
_ , err := tx . Stmt ( stmtSaveDonk ) . Exec ( - 1 , ch . ID , d . FileID )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error saving donk: %s" , err )
2020-05-15 05:51:42 +02:00
break
}
}
2022-02-05 22:53:19 +01:00
chatplusone ( tx , ch . UserID )
2020-05-15 05:51:42 +02:00
err = tx . Commit ( )
} else {
tx . Rollback ( )
2020-05-13 23:15:29 +02:00
}
return err
}
2022-02-05 22:53:19 +01:00
func chatplusone ( tx * sql . Tx , userid int64 ) {
2021-12-27 05:19:04 +01:00
var user * WhatAbout
ok := somenumberedusers . Get ( userid , & user )
if ! ok {
return
}
options := user . Options
2022-02-05 22:53:19 +01:00
options . ChatCount += 1
2021-12-27 05:19:04 +01:00
j , err := jsonify ( options )
if err == nil {
2022-02-05 22:53:19 +01:00
_ , err = tx . Exec ( "update users set options = ? where username = ?" , j , user . Name )
2021-12-27 05:19:04 +01:00
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error plussing chat: %s" , err )
2021-12-27 05:19:04 +01:00
}
somenamedusers . Clear ( user . Name )
somenumberedusers . Clear ( user . ID )
}
func chatnewnone ( userid int64 ) {
var user * WhatAbout
ok := somenumberedusers . Get ( userid , & user )
2022-02-05 22:53:19 +01:00
if ! ok || user . Options . ChatCount == 0 {
2021-12-27 05:19:04 +01:00
return
}
options := user . Options
2022-02-05 22:53:19 +01:00
options . ChatCount = 0
2021-12-27 05:19:04 +01:00
j , err := jsonify ( options )
if err == nil {
db := opendatabase ( )
_ , err = db . Exec ( "update users set options = ? where username = ?" , j , user . Name )
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error noneing chat: %s" , err )
2021-12-27 05:19:04 +01:00
}
somenamedusers . Clear ( user . Name )
somenumberedusers . Clear ( user . ID )
}
2022-02-05 22:53:19 +01:00
func meplusone ( tx * sql . Tx , userid int64 ) {
var user * WhatAbout
ok := somenumberedusers . Get ( userid , & user )
if ! ok {
return
}
options := user . Options
options . MeCount += 1
j , err := jsonify ( options )
if err == nil {
_ , err = tx . Exec ( "update users set options = ? where username = ?" , j , user . Name )
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error plussing me: %s" , err )
2022-02-05 22:53:19 +01:00
}
somenamedusers . Clear ( user . Name )
somenumberedusers . Clear ( user . ID )
}
func menewnone ( userid int64 ) {
var user * WhatAbout
ok := somenumberedusers . Get ( userid , & user )
if ! ok || user . Options . MeCount == 0 {
return
}
options := user . Options
options . MeCount = 0
j , err := jsonify ( options )
if err == nil {
db := opendatabase ( )
_ , err = db . Exec ( "update users set options = ? where username = ?" , j , user . Name )
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error noneing me: %s" , err )
2022-02-05 22:53:19 +01:00
}
somenamedusers . Clear ( user . Name )
somenumberedusers . Clear ( user . ID )
}
2020-05-24 01:17:30 +02:00
func loadchatter ( userid int64 ) [ ] * Chatter {
2020-05-24 01:05:23 +02:00
duedt := time . Now ( ) . Add ( - 3 * 24 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
rows , err := stmtLoadChonks . Query ( userid , duedt )
2020-05-13 23:15:29 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error loading chonks: %s" , err )
2020-05-13 23:15:29 +02:00
return nil
}
defer rows . Close ( )
chonks := make ( map [ string ] [ ] * Chonk )
2020-05-15 06:18:50 +02:00
var allchonks [ ] * Chonk
2020-05-13 23:15:29 +02:00
for rows . Next ( ) {
ch := new ( Chonk )
var dt string
err = rows . Scan ( & ch . ID , & ch . UserID , & ch . XID , & ch . Who , & ch . Target , & dt , & ch . Noise , & ch . Format )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning chonk: %s" , err )
2020-05-13 23:15:29 +02:00
continue
}
ch . Date , _ = time . Parse ( dbtimeformat , dt )
chonks [ ch . Target ] = append ( chonks [ ch . Target ] , ch )
2020-05-15 06:18:50 +02:00
allchonks = append ( allchonks , ch )
2020-05-13 23:15:29 +02:00
}
2020-05-15 06:18:50 +02:00
donksforchonks ( allchonks )
2020-05-24 01:17:30 +02:00
rows . Close ( )
rows , err = stmtGetChatters . Query ( userid )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error getting chatters: %s" , err )
2020-05-24 01:17:30 +02:00
return nil
}
for rows . Next ( ) {
var target string
err = rows . Scan ( & target )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error scanning chatter: %s" , target )
2020-05-24 01:17:30 +02:00
continue
}
if _ , ok := chonks [ target ] ; ! ok {
chonks [ target ] = [ ] * Chonk { }
}
}
var chatter [ ] * Chatter
for target , chonks := range chonks {
chatter = append ( chatter , & Chatter {
Target : target ,
Chonks : chonks ,
} )
}
2020-05-24 01:32:32 +02:00
sort . Slice ( chatter , func ( i , j int ) bool {
a , b := chatter [ i ] , chatter [ j ]
if len ( a . Chonks ) == 0 || len ( b . Chonks ) == 0 {
if len ( a . Chonks ) == len ( b . Chonks ) {
return a . Target < b . Target
}
return len ( a . Chonks ) > len ( b . Chonks )
}
return a . Chonks [ len ( a . Chonks ) - 1 ] . Date . After ( b . Chonks [ len ( b . Chonks ) - 1 ] . Date )
} )
2020-05-24 01:17:30 +02:00
return chatter
2020-05-13 23:15:29 +02:00
}
2019-09-11 22:20:22 +02:00
func savehonk ( h * Honk ) error {
dt := h . Date . UTC ( ) . Format ( dbtimeformat )
aud := strings . Join ( h . Audience , " " )
2019-10-08 07:23:54 +02:00
db := opendatabase ( )
tx , err := db . Begin ( )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "can't begin tx: %s" , err )
2019-10-08 07:23:54 +02:00
return err
}
res , err := tx . Stmt ( stmtSaveHonk ) . Exec ( h . UserID , h . What , h . Honker , h . XID , h . RID , dt , h . URL ,
2019-09-11 22:20:22 +02:00
aud , h . Noise , h . Convoy , h . Whofore , h . Format , h . Precis ,
2019-09-22 23:00:14 +02:00
h . Oonker , h . Flags )
2019-10-08 07:23:54 +02:00
if err == nil {
h . ID , _ = res . LastInsertId ( )
err = saveextras ( tx , h )
}
if err == nil {
2022-02-05 22:53:19 +01:00
if h . Whofore == 1 {
meplusone ( tx , h . UserID )
}
2019-10-08 07:23:54 +02:00
err = tx . Commit ( )
} else {
tx . Rollback ( )
}
2019-09-11 22:20:22 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error saving honk: %s" , err )
2019-10-08 07:23:54 +02:00
}
2019-11-12 07:09:08 +01:00
honkhonkline ( )
2019-10-08 07:23:54 +02:00
return err
}
func updatehonk ( h * Honk ) error {
old := getxonk ( h . UserID , h . XID )
oldrev := OldRevision { Precis : old . Precis , Noise : old . Noise }
dt := h . Date . UTC ( ) . Format ( dbtimeformat )
db := opendatabase ( )
tx , err := db . Begin ( )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "can't begin tx: %s" , err )
2019-10-08 07:23:54 +02:00
return err
}
2019-11-27 20:22:20 +01:00
err = deleteextras ( tx , h . ID , false )
2019-10-08 07:23:54 +02:00
if err == nil {
2019-11-20 17:35:34 +01:00
_ , err = tx . Stmt ( stmtUpdateHonk ) . Exec ( h . Precis , h . Noise , h . Format , h . Whofore , dt , h . ID )
2019-10-08 07:23:54 +02:00
}
if err == nil {
err = saveextras ( tx , h )
}
if err == nil {
var j string
j , err = jsonify ( & oldrev )
if err == nil {
_ , err = tx . Stmt ( stmtSaveMeta ) . Exec ( old . ID , "oldrev" , j )
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error saving oldrev: %s" , err )
2019-10-08 07:23:54 +02:00
}
}
if err == nil {
err = tx . Commit ( )
} else {
tx . Rollback ( )
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error updating honk %d: %s" , h . ID , err )
2019-10-08 07:23:54 +02:00
}
return err
}
func deletehonk ( honkid int64 ) error {
db := opendatabase ( )
tx , err := db . Begin ( )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "can't begin tx: %s" , err )
2019-09-11 22:20:22 +02:00
return err
}
2019-10-08 07:23:54 +02:00
2019-11-27 20:22:20 +01:00
err = deleteextras ( tx , honkid , true )
2019-10-08 07:23:54 +02:00
if err == nil {
_ , err = tx . Stmt ( stmtDeleteHonk ) . Exec ( honkid )
}
if err == nil {
err = tx . Commit ( )
} else {
tx . Rollback ( )
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error deleting honk %d: %s" , honkid , err )
2019-10-08 07:23:54 +02:00
}
2019-09-17 00:00:13 +02:00
return err
}
2019-10-08 07:23:54 +02:00
func saveextras ( tx * sql . Tx , h * Honk ) error {
2019-09-11 22:20:22 +02:00
for _ , d := range h . Donks {
2020-05-15 05:51:42 +02:00
_ , err := tx . Stmt ( stmtSaveDonk ) . Exec ( h . ID , - 1 , d . FileID )
2019-09-11 22:20:22 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error saving donk: %s" , err )
2019-09-11 22:20:22 +02:00
return err
}
}
for _ , o := range h . Onts {
2019-10-08 07:23:54 +02:00
_ , err := tx . Stmt ( stmtSaveOnt ) . Exec ( strings . ToLower ( o ) , h . ID )
2019-09-11 22:20:22 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error saving ont: %s" , err )
2019-09-11 22:20:22 +02:00
return err
}
}
2019-09-29 22:07:35 +02:00
if p := h . Place ; p != nil {
2019-10-02 23:10:01 +02:00
j , err := jsonify ( p )
2019-10-03 00:20:14 +02:00
if err == nil {
2019-10-08 07:23:54 +02:00
_ , err = tx . Stmt ( stmtSaveMeta ) . Exec ( h . ID , "place" , j )
2019-10-02 23:10:01 +02:00
}
2019-09-28 06:12:50 +02:00
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error saving place: %s" , err )
2019-09-28 06:12:50 +02:00
return err
}
}
2019-10-03 00:20:14 +02:00
if t := h . Time ; t != nil {
j , err := jsonify ( t )
if err == nil {
2019-10-08 07:23:54 +02:00
_ , err = tx . Stmt ( stmtSaveMeta ) . Exec ( h . ID , "time" , j )
2019-10-02 23:29:02 +02:00
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error saving time: %s" , err )
2019-11-27 20:36:29 +01:00
return err
}
}
if m := h . Mentions ; len ( m ) > 0 {
j , err := jsonify ( m )
if err == nil {
_ , err = tx . Stmt ( stmtSaveMeta ) . Exec ( h . ID , "mentions" , j )
}
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Printf ( "error saving mentions: %s" , err )
2019-10-02 23:29:02 +02:00
return err
}
}
2022-02-09 23:11:55 +01:00
if w := h . Wonkles ; w != "" {
_ , err := tx . Stmt ( stmtSaveMeta ) . Exec ( h . ID , "wonkles" , w )
if err != nil {
elog . Printf ( "error saving wonkles: %s" , err )
return err
}
}
2022-02-12 20:58:57 +01:00
if g := h . Guesses ; g != "" {
_ , err := tx . Stmt ( stmtSaveMeta ) . Exec ( h . ID , "guesses" , g )
if err != nil {
elog . Printf ( "error saving guesses: %s" , err )
return err
}
}
2019-09-11 22:20:22 +02:00
return nil
}
2021-02-10 00:48:36 +01:00
var baxonker sync . Mutex
2021-02-09 14:18:22 +01:00
func addreaction ( user * WhatAbout , xid string , who , react string ) {
2021-02-10 00:48:36 +01:00
baxonker . Lock ( )
defer baxonker . Unlock ( )
2021-02-09 14:18:22 +01:00
h := getxonk ( user . ID , xid )
if h == nil {
return
}
h . Badonks = append ( h . Badonks , Badonk { Who : who , What : react } )
j , _ := jsonify ( h . Badonks )
db := opendatabase ( )
tx , _ := db . Begin ( )
_ , _ = tx . Stmt ( stmtDeleteOneMeta ) . Exec ( h . ID , "badonks" )
_ , _ = tx . Stmt ( stmtSaveMeta ) . Exec ( h . ID , "badonks" , j )
tx . Commit ( )
}
2019-11-27 20:22:20 +01:00
func deleteextras ( tx * sql . Tx , honkid int64 , everything bool ) error {
2019-10-08 07:23:54 +02:00
_ , err := tx . Stmt ( stmtDeleteDonks ) . Exec ( honkid )
2019-09-16 23:00:50 +02:00
if err != nil {
2019-10-08 07:23:54 +02:00
return err
2019-09-16 23:00:50 +02:00
}
2019-10-08 07:23:54 +02:00
_ , err = tx . Stmt ( stmtDeleteOnts ) . Exec ( honkid )
2019-09-28 06:12:50 +02:00
if err != nil {
2019-10-08 07:23:54 +02:00
return err
2019-10-07 04:53:58 +02:00
}
2019-11-27 20:22:20 +01:00
if everything {
_ , err = tx . Stmt ( stmtDeleteAllMeta ) . Exec ( honkid )
} else {
_ , err = tx . Stmt ( stmtDeleteSomeMeta ) . Exec ( honkid )
}
2019-09-16 23:00:50 +02:00
if err != nil {
2019-10-08 07:23:54 +02:00
return err
2019-09-16 23:00:50 +02:00
}
2019-10-08 07:23:54 +02:00
return nil
2019-09-16 23:00:50 +02:00
}
2019-10-02 23:10:01 +02:00
func jsonify ( what interface { } ) ( string , error ) {
var buf bytes . Buffer
e := json . NewEncoder ( & buf )
e . SetEscapeHTML ( false )
e . SetIndent ( "" , "" )
err := e . Encode ( what )
return buf . String ( ) , err
}
func unjsonify ( s string , dest interface { } ) error {
d := json . NewDecoder ( strings . NewReader ( s ) )
err := d . Decode ( dest )
return err
}
2022-02-09 23:11:55 +01:00
func getxonker ( what , flav string ) string {
var res string
row := stmtGetXonker . QueryRow ( what , flav )
row . Scan ( & res )
return res
}
func savexonker ( what , value , flav , when string ) {
stmtSaveXonker . Exec ( what , value , flav , when )
}
2022-04-28 21:38:51 +02:00
func savehonker ( user * WhatAbout , url , name , flavor , combos , mj string ) error {
var owner string
if url [ 0 ] == '#' {
flavor = "peep"
if name == "" {
name = url [ 1 : ]
}
owner = url
} else {
info , err := investigate ( url )
if err != nil {
ilog . Printf ( "failed to investigate honker: %s" , err )
return err
}
url = info . XID
if name == "" {
name = info . Name
}
owner = info . Owner
}
var x string
db := opendatabase ( )
row := db . QueryRow ( "select xid from honkers where xid = ? and userid = ? and flavor in ('sub', 'unsub', 'peep')" , url , user . ID )
err := row . Scan ( & x )
if err != sql . ErrNoRows {
if err != nil {
elog . Printf ( "honker scan err: %s" , err )
} else {
err = fmt . Errorf ( "it seems you are already subscribed to them" )
}
return err
}
res , err := stmtSaveHonker . Exec ( user . ID , name , url , flavor , combos , owner , mj )
if err != nil {
elog . Print ( err )
return err
}
honkerid , _ := res . LastInsertId ( )
if flavor == "presub" {
followyou ( user , honkerid )
}
return nil
}
2019-09-10 20:43:34 +02:00
func cleanupdb ( arg string ) {
db := opendatabase ( )
days , err := strconv . Atoi ( arg )
2019-09-30 22:43:51 +02:00
var sqlargs [ ] interface { }
var where string
2019-09-10 20:43:34 +02:00
if err != nil {
honker := arg
2022-04-12 20:40:17 +02:00
expdate := time . Now ( ) . Add ( - 3 * 24 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
2019-10-11 22:03:17 +02:00
where = "dt < ? and honker = ?"
2019-09-30 22:43:51 +02:00
sqlargs = append ( sqlargs , expdate )
sqlargs = append ( sqlargs , honker )
2019-09-10 20:43:34 +02:00
} else {
2022-04-12 20:40:17 +02:00
expdate := time . Now ( ) . Add ( - time . Duration ( days ) * 24 * time . Hour ) . UTC ( ) . Format ( dbtimeformat )
2019-10-11 22:03:17 +02:00
where = "dt < ? and convoy not in (select convoy from honks where flags & 4 or whofore = 2 or whofore = 3)"
2019-09-30 22:43:51 +02:00
sqlargs = append ( sqlargs , expdate )
2019-09-10 20:43:34 +02:00
}
2019-10-11 22:03:17 +02:00
doordie ( db , "delete from honks where flags & 4 = 0 and whofore = 0 and " + where , sqlargs ... )
2020-05-15 05:51:42 +02:00
doordie ( db , "delete from donks where honkid > 0 and honkid not in (select honkid from honks)" )
2019-09-30 22:43:51 +02:00
doordie ( db , "delete from onts where honkid not in (select honkid from honks)" )
2019-10-02 23:10:01 +02:00
doordie ( db , "delete from honkmeta where honkid not in (select honkid from honks)" )
2019-09-30 22:43:51 +02:00
2019-09-30 03:40:37 +02:00
doordie ( db , "delete from filemeta where fileid not in (select fileid from donks)" )
2019-09-10 20:43:34 +02:00
for _ , u := range allusers ( ) {
doordie ( db , "delete from zonkers where userid = ? and wherefore = 'zonvoy' and zonkerid < (select zonkerid from zonkers where userid = ? and wherefore = 'zonvoy' order by zonkerid desc limit 1 offset 200)" , u . UserID , u . UserID )
}
2019-09-30 22:43:51 +02:00
filexids := make ( map [ string ] bool )
blobdb := openblobdb ( )
rows , err := blobdb . Query ( "select xid from filedata" )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Fatal ( err )
2019-09-30 22:43:51 +02:00
}
for rows . Next ( ) {
var xid string
err = rows . Scan ( & xid )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Fatal ( err )
2019-09-30 22:43:51 +02:00
}
filexids [ xid ] = true
}
rows . Close ( )
rows , err = db . Query ( "select xid from filemeta" )
for rows . Next ( ) {
var xid string
err = rows . Scan ( & xid )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Fatal ( err )
2019-09-30 22:43:51 +02:00
}
delete ( filexids , xid )
}
rows . Close ( )
tx , err := blobdb . Begin ( )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Fatal ( err )
2019-09-30 22:43:51 +02:00
}
for xid , _ := range filexids {
_ , err = tx . Exec ( "delete from filedata where xid = ?" , xid )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Fatal ( err )
2019-09-30 22:43:51 +02:00
}
}
err = tx . Commit ( )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Fatal ( err )
2019-09-30 22:43:51 +02:00
}
2019-09-10 20:43:34 +02:00
}
2019-10-26 02:31:07 +02:00
var stmtHonkers , stmtDubbers , stmtNamedDubbers , stmtSaveHonker , stmtUpdateFlavor , stmtUpdateHonker * sql . Stmt
2020-11-26 04:03:46 +01:00
var stmtDeleteHonker * sql . Stmt
2019-10-07 21:22:10 +02:00
var stmtAnyXonk , stmtOneXonk , stmtPublicHonks , stmtUserHonks , stmtHonksByCombo , stmtHonksByConvoy * sql . Stmt
2019-09-10 20:43:34 +02:00
var stmtHonksByOntology , stmtHonksForUser , stmtHonksForMe , stmtSaveDub , stmtHonksByXonker * sql . Stmt
2020-07-20 00:51:02 +02:00
var stmtHonksFromLongAgo * sql . Stmt
2020-01-12 09:43:45 +01:00
var stmtHonksByHonker , stmtSaveHonk , stmtUserByName , stmtUserByNumber * sql . Stmt
2019-10-11 02:37:03 +02:00
var stmtEventHonks , stmtOneBonk , stmtFindZonk , stmtFindXonk , stmtSaveDonk * sql . Stmt
2019-09-30 03:40:37 +02:00
var stmtFindFile , stmtGetFileData , stmtSaveFileData , stmtSaveFile * sql . Stmt
2020-09-30 21:20:40 +02:00
var stmtCheckFileData * sql . Stmt
2019-09-10 20:43:34 +02:00
var stmtAddDoover , stmtGetDoovers , stmtLoadDoover , stmtZapDoover , stmtOneHonker * sql . Stmt
2019-10-30 00:14:41 +01:00
var stmtUntagged , stmtDeleteHonk , stmtDeleteDonks , stmtDeleteOnts , stmtSaveZonker * sql . Stmt
2022-05-05 20:55:32 +02:00
var stmtGetZonkers , stmtRecentHonkers , stmtGetXonker , stmtSaveXonker , stmtDeleteXonker , stmtDeleteOldXonkers * sql . Stmt
2019-10-13 07:58:01 +02:00
var stmtAllOnts , stmtSaveOnt , stmtUpdateFlags , stmtClearFlags * sql . Stmt
2019-11-27 20:22:20 +01:00
var stmtHonksForUserFirstClass * sql . Stmt
2021-02-09 14:18:22 +01:00
var stmtSaveMeta , stmtDeleteAllMeta , stmtDeleteOneMeta , stmtDeleteSomeMeta , stmtUpdateHonk * sql . Stmt
2019-10-11 22:03:17 +02:00
var stmtHonksISaved , stmtGetFilters , stmtSaveFilter , stmtDeleteFilter * sql . Stmt
2019-11-26 06:29:31 +01:00
var stmtGetTracks * sql . Stmt
2020-05-24 01:17:30 +02:00
var stmtSaveChonk , stmtLoadChonks , stmtGetChatters * sql . Stmt
2019-09-10 20:43:34 +02:00
func preparetodie ( db * sql . DB , s string ) * sql . Stmt {
stmt , err := db . Prepare ( s )
if err != nil {
2022-02-06 06:42:13 +01:00
elog . Fatalf ( "error %s: %s" , err , s )
2019-09-10 20:43:34 +02:00
}
return stmt
}
func prepareStatements ( db * sql . DB ) {
2019-12-03 00:26:29 +01:00
stmtHonkers = preparetodie ( db , "select honkerid, userid, name, xid, flavor, combos, meta from honkers where userid = ? and (flavor = 'presub' or flavor = 'sub' or flavor = 'peep' or flavor = 'unsub') order by name" )
2020-09-02 22:31:02 +02:00
stmtSaveHonker = preparetodie ( db , "insert into honkers (userid, name, xid, flavor, combos, owner, meta, folxid) values (?, ?, ?, ?, ?, ?, ?, '')" )
2020-09-14 20:59:45 +02:00
stmtUpdateFlavor = preparetodie ( db , "update honkers set flavor = ?, folxid = ? where userid = ? and name = ? and xid = ? and flavor = ?" )
2019-12-03 00:26:29 +01:00
stmtUpdateHonker = preparetodie ( db , "update honkers set name = ?, combos = ?, meta = ? where honkerid = ? and userid = ?" )
2020-11-26 04:03:46 +01:00
stmtDeleteHonker = preparetodie ( db , "delete from honkers where honkerid = ?" )
2019-09-10 20:43:34 +02:00
stmtOneHonker = preparetodie ( db , "select xid from honkers where name = ? and userid = ?" )
stmtDubbers = preparetodie ( db , "select honkerid, userid, name, xid, flavor from honkers where userid = ? and flavor = 'dub'" )
2019-10-26 02:31:07 +02:00
stmtNamedDubbers = preparetodie ( db , "select honkerid, userid, name, xid, flavor from honkers where userid = ? and name = ? and flavor = 'dub'" )
2019-09-10 20:43:34 +02:00
2019-09-22 23:00:14 +02:00
selecthonks := "select honks.honkid, honks.userid, username, what, honker, oonker, honks.xid, rid, dt, url, audience, noise, precis, format, convoy, whofore, flags from honks join users on honks.userid = users.userid "
2019-09-10 20:43:34 +02:00
limit := " order by honks.honkid desc limit 250"
2019-11-12 07:43:16 +01:00
smalllimit := " order by honks.honkid desc limit ?"
2019-09-10 20:43:34 +02:00
butnotthose := " and convoy not in (select name from zonkers where userid = ? and wherefore = 'zonvoy' order by zonkerid desc limit 100)"
stmtOneXonk = preparetodie ( db , selecthonks + "where honks.userid = ? and xid = ?" )
2019-10-07 21:22:10 +02:00
stmtAnyXonk = preparetodie ( db , selecthonks + "where xid = ? order by honks.honkid asc" )
2019-09-10 20:43:34 +02:00
stmtOneBonk = preparetodie ( db , selecthonks + "where honks.userid = ? and xid = ? and what = 'bonk' and whofore = 2" )
2019-11-12 07:43:16 +01:00
stmtPublicHonks = preparetodie ( db , selecthonks + "where whofore = 2 and dt > ?" + smalllimit )
stmtEventHonks = preparetodie ( db , selecthonks + "where (whofore = 2 or honks.userid = ?) and what = 'event'" + smalllimit )
stmtUserHonks = preparetodie ( db , selecthonks + "where honks.honkid > ? and (whofore = 2 or whofore = ?) and username = ? and dt > ?" + smalllimit )
2019-10-11 17:03:29 +02:00
myhonkers := " and honker in (select xid from honkers where userid = ? and (flavor = 'sub' or flavor = 'peep' or flavor = 'presub') and combos not like '% - %')"
2019-10-20 20:36:55 +02:00
stmtHonksForUser = preparetodie ( db , selecthonks + "where honks.honkid > ? and honks.userid = ? and dt > ?" + myhonkers + butnotthose + limit )
stmtHonksForUserFirstClass = preparetodie ( db , selecthonks + "where honks.honkid > ? and honks.userid = ? and dt > ? and (what <> 'tonk')" + myhonkers + butnotthose + limit )
stmtHonksForMe = preparetodie ( db , selecthonks + "where honks.honkid > ? and honks.userid = ? and dt > ? and whofore = 1" + butnotthose + limit )
2020-07-20 00:57:53 +02:00
stmtHonksFromLongAgo = preparetodie ( db , selecthonks + "where honks.honkid > ? and honks.userid = ? and dt > ? and dt < ? and whofore = 2" + butnotthose + limit )
2019-10-20 20:36:55 +02:00
stmtHonksISaved = preparetodie ( db , selecthonks + "where honks.honkid > ? and honks.userid = ? and flags & 4 order by honks.honkid desc" )
stmtHonksByHonker = preparetodie ( db , selecthonks + "join honkers on (honkers.xid = honks.honker or honkers.xid = honks.oonker) where honks.honkid > ? and honks.userid = ? and honkers.name = ?" + butnotthose + limit )
stmtHonksByXonker = preparetodie ( db , selecthonks + " where honks.honkid > ? and honks.userid = ? and (honker = ? or oonker = ?)" + butnotthose + limit )
2019-10-30 05:02:23 +01:00
stmtHonksByCombo = preparetodie ( db , selecthonks + " where honks.honkid > ? and honks.userid = ? and honks.honker in (select xid from honkers where honkers.userid = ? and honkers.combos like ?) " + butnotthose + " union " + selecthonks + "join onts on honks.honkid = onts.honkid where honks.honkid > ? and honks.userid = ? and onts.ontology in (select xid from honkers where combos like ?)" + butnotthose + limit )
2019-10-20 20:36:55 +02:00
stmtHonksByConvoy = preparetodie ( db , selecthonks + "where honks.honkid > ? and (honks.userid = ? or (? = -1 and whofore = 2)) and convoy = ?" + limit )
stmtHonksByOntology = preparetodie ( db , selecthonks + "join onts on honks.honkid = onts.honkid where honks.honkid > ? and onts.ontology = ? and (honks.userid = ? or (? = -1 and honks.whofore = 2))" + limit )
2019-09-10 20:43:34 +02:00
2019-10-02 23:10:01 +02:00
stmtSaveMeta = preparetodie ( db , "insert into honkmeta (honkid, genus, json) values (?, ?, ?)" )
2019-11-27 20:22:20 +01:00
stmtDeleteAllMeta = preparetodie ( db , "delete from honkmeta where honkid = ?" )
stmtDeleteSomeMeta = preparetodie ( db , "delete from honkmeta where honkid = ? and genus not in ('oldrev')" )
2021-02-09 14:18:22 +01:00
stmtDeleteOneMeta = preparetodie ( db , "delete from honkmeta where honkid = ? and genus = ?" )
2019-09-22 23:00:14 +02:00
stmtSaveHonk = preparetodie ( db , "insert into honks (userid, what, honker, xid, rid, dt, url, audience, noise, convoy, whofore, format, precis, oonker, flags) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" )
2019-09-16 23:00:50 +02:00
stmtDeleteHonk = preparetodie ( db , "delete from honks where honkid = ?" )
2019-11-20 17:35:34 +01:00
stmtUpdateHonk = preparetodie ( db , "update honks set precis = ?, noise = ?, format = ?, whofore = ?, dt = ? where honkid = ?" )
2019-09-16 23:00:50 +02:00
stmtSaveOnt = preparetodie ( db , "insert into onts (ontology, honkid) values (?, ?)" )
stmtDeleteOnts = preparetodie ( db , "delete from onts where honkid = ?" )
2020-05-15 05:51:42 +02:00
stmtSaveDonk = preparetodie ( db , "insert into donks (honkid, chonkid, fileid) values (?, ?, ?)" )
2019-09-16 23:00:50 +02:00
stmtDeleteDonks = preparetodie ( db , "delete from donks where honkid = ?" )
2019-09-30 03:40:37 +02:00
stmtSaveFile = preparetodie ( db , "insert into filemeta (xid, name, description, url, media, local) values (?, ?, ?, ?, ?, ?)" )
2019-09-30 22:43:51 +02:00
blobdb := openblobdb ( )
2020-09-30 21:20:40 +02:00
stmtSaveFileData = preparetodie ( blobdb , "insert into filedata (xid, media, hash, content) values (?, ?, ?, ?)" )
stmtCheckFileData = preparetodie ( blobdb , "select xid from filedata where hash = ?" )
2019-09-30 03:40:37 +02:00
stmtGetFileData = preparetodie ( blobdb , "select media, content from filedata where xid = ?" )
2019-09-10 20:43:34 +02:00
stmtFindXonk = preparetodie ( db , "select honkid from honks where userid = ? and xid = ?" )
2019-10-03 05:02:01 +02:00
stmtFindFile = preparetodie ( db , "select fileid, xid from filemeta where url = ? and local = 1" )
2019-10-26 00:46:27 +02:00
stmtUserByName = preparetodie ( db , "select userid, username, displayname, about, pubkey, seckey, options from users where username = ? and userid > 0" )
stmtUserByNumber = preparetodie ( db , "select userid, username, displayname, about, pubkey, seckey, options from users where userid = ?" )
2020-09-14 20:59:45 +02:00
stmtSaveDub = preparetodie ( db , "insert into honkers (userid, name, xid, flavor, combos, owner, meta, folxid) values (?, ?, ?, ?, '', '', '', ?)" )
2019-10-26 00:46:27 +02:00
stmtAddDoover = preparetodie ( db , "insert into doovers (dt, tries, userid, rcpt, msg) values (?, ?, ?, ?, ?)" )
2019-09-10 20:43:34 +02:00
stmtGetDoovers = preparetodie ( db , "select dooverid, dt from doovers" )
2019-10-26 00:46:27 +02:00
stmtLoadDoover = preparetodie ( db , "select tries, userid, rcpt, msg from doovers where dooverid = ?" )
2019-09-10 20:43:34 +02:00
stmtZapDoover = preparetodie ( db , "delete from doovers where dooverid = ?" )
2019-10-30 00:23:07 +01:00
stmtUntagged = preparetodie ( db , "select xid, rid, flags from (select honkid, xid, rid, flags from honks where userid = ? order by honkid desc limit 10000) order by honkid asc" )
2019-09-10 20:43:34 +02:00
stmtFindZonk = preparetodie ( db , "select zonkerid from zonkers where userid = ? and name = ? and wherefore = 'zonk'" )
stmtGetZonkers = preparetodie ( db , "select zonkerid, name, wherefore from zonkers where userid = ? and wherefore <> 'zonk'" )
stmtSaveZonker = preparetodie ( db , "insert into zonkers (userid, name, wherefore) values (?, ?, ?)" )
stmtGetXonker = preparetodie ( db , "select info from xonkers where name = ? and flavor = ?" )
2019-11-25 21:50:17 +01:00
stmtSaveXonker = preparetodie ( db , "insert into xonkers (name, info, flavor, dt) values (?, ?, ?, ?)" )
stmtDeleteXonker = preparetodie ( db , "delete from xonkers where name = ? and flavor = ? and dt < ?" )
2022-05-05 20:55:32 +02:00
stmtDeleteOldXonkers = preparetodie ( db , "delete from xonkers where flavor = ? and dt < ?" )
2019-09-10 20:43:34 +02:00
stmtRecentHonkers = preparetodie ( db , "select distinct(honker) from honks where userid = ? and honker not in (select xid from honkers where userid = ? and flavor = 'sub') order by honkid desc limit 100" )
stmtUpdateFlags = preparetodie ( db , "update honks set flags = flags | ? where honkid = ?" )
stmtClearFlags = preparetodie ( db , "update honks set flags = flags & ~ ? where honkid = ?" )
2019-10-13 07:58:01 +02:00
stmtAllOnts = preparetodie ( db , "select ontology, count(ontology) from onts join honks on onts.honkid = honks.honkid where (honks.userid = ? or honks.whofore = 2) group by ontology" )
2019-10-04 22:30:33 +02:00
stmtGetFilters = preparetodie ( db , "select hfcsid, json from hfcs where userid = ?" )
2019-10-07 02:26:21 +02:00
stmtSaveFilter = preparetodie ( db , "insert into hfcs (userid, json) values (?, ?)" )
stmtDeleteFilter = preparetodie ( db , "delete from hfcs where userid = ? and hfcsid = ?" )
2019-11-26 06:29:31 +01:00
stmtGetTracks = preparetodie ( db , "select fetches from tracks where xid = ?" )
2020-05-13 23:15:29 +02:00
stmtSaveChonk = preparetodie ( db , "insert into chonks (userid, xid, who, target, dt, noise, format) values (?, ?, ?, ?, ?, ?, ?)" )
2020-05-24 01:05:23 +02:00
stmtLoadChonks = preparetodie ( db , "select chonkid, userid, xid, who, target, dt, noise, format from chonks where userid = ? and dt > ? order by chonkid asc" )
2020-05-24 01:17:30 +02:00
stmtGetChatters = preparetodie ( db , "select distinct(target) from chonks where userid = ?" )
2019-09-10 20:43:34 +02:00
}