tcp.ac/common.go

208 lines
3.8 KiB
Go
Raw Permalink Normal View History

package main
import (
2022-07-14 07:50:26 +00:00
"git.tcp.direct/kayos/common/hash"
2022-12-18 10:54:32 +00:00
"git.tcp.direct/kayos/common/pool"
valid "github.com/asaskevich/govalidator"
"github.com/gin-gonic/gin"
2022-01-21 12:58:22 +00:00
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
2022-07-08 20:23:20 +00:00
2022-07-18 10:41:29 +00:00
"github.com/json-iterator/go"
2022-07-08 20:23:20 +00:00
"git.tcp.direct/tcp.direct/tcp.ac/config"
)
2022-07-18 10:41:29 +00:00
var json = jsoniter.ConfigCompatibleWithStandardLibrary
2022-12-18 10:54:32 +00:00
var str = pool.NewStringFactory()
2022-01-21 12:58:22 +00:00
type EntryType uint8
const (
Image EntryType = iota
Text
URL
// Custom is for user uploads of arbitrary formats.
Custom
)
type UserID uint64
2022-07-18 10:41:29 +00:00
// Entry FIXME: not currently used
2022-01-21 12:58:22 +00:00
type Entry interface {
TypeCode() string
UID() string
DelKey() string
OwnerID() uint64
Private() bool
2022-07-14 07:50:26 +00:00
Sum() []byte
Bytes() []byte
2022-01-21 12:58:22 +00:00
}
type Post struct {
2022-01-21 12:58:22 +00:00
entryType EntryType
2022-07-14 07:50:26 +00:00
b2sum []byte
data []byte
2022-01-21 12:58:22 +00:00
owner UserID
uid, key string
priv bool
log *zerolog.Logger
}
2022-07-14 07:50:26 +00:00
func (p *Post) setLogger() {
pl := log.Logger.With().Str("caller", p.TypeCode(true)+":"+p.UID()).
Bool("private", p.priv).Logger()
p.log = &pl
}
2022-07-18 10:41:29 +00:00
func newPost(entryType EntryType, data []byte, priv bool) *Post {
2022-07-14 07:50:26 +00:00
p := &Post{
2022-07-18 10:41:29 +00:00
entryType: entryType,
2022-07-14 07:50:26 +00:00
priv: priv,
data: data,
}
p.setLogger()
return p
}
2022-07-18 10:41:29 +00:00
func typeToString(t EntryType, long bool) string {
2022-12-18 10:54:32 +00:00
s := str.Get()
defer str.MustPut(s)
2022-07-18 10:41:29 +00:00
switch t {
2022-01-21 12:58:22 +00:00
case Image:
2022-12-18 10:54:32 +00:00
s.WriteString("i")
2022-07-14 07:50:26 +00:00
if long {
s.WriteString("mg")
2022-07-14 07:50:26 +00:00
}
2022-01-21 12:58:22 +00:00
case Text:
2022-12-18 10:54:32 +00:00
s.WriteString("t")
2022-07-14 07:50:26 +00:00
if long {
2022-12-18 10:54:32 +00:00
s.WriteString("xt")
2022-07-14 07:50:26 +00:00
}
2022-01-21 12:58:22 +00:00
case URL:
2022-12-18 10:54:32 +00:00
s.WriteString("u")
2022-07-14 07:50:26 +00:00
if long {
2022-12-18 10:54:32 +00:00
s.WriteString("rl")
2022-07-18 10:41:29 +00:00
}
case Custom:
2022-12-18 10:54:32 +00:00
s.WriteString("e")
2022-07-18 10:41:29 +00:00
if long {
2022-12-18 10:54:32 +00:00
s.WriteString("tc")
2022-07-14 07:50:26 +00:00
}
2022-01-21 12:58:22 +00:00
default:
2022-07-18 10:41:29 +00:00
panic("unknown entry type")
2022-01-21 12:58:22 +00:00
}
2022-12-18 10:54:32 +00:00
return s.String()
2022-07-18 10:41:29 +00:00
}
func (p *Post) TypeCode(long bool) (code string) {
return typeToString(p.entryType, long)
2022-01-21 12:58:22 +00:00
}
func (p *Post) UID() string {
return p.uid
}
func (p *Post) DelKey() string {
return p.key
}
func (p *Post) Private() bool {
return p.priv
}
2022-07-14 07:50:26 +00:00
func (p *Post) Log() *zerolog.Logger {
2022-01-21 12:58:22 +00:00
if p.log != nil {
return p.log
}
2022-07-14 07:50:26 +00:00
p.setLogger()
2022-01-21 12:58:22 +00:00
return p.log
}
func validateKey(rKey string) bool {
2022-07-08 20:23:20 +00:00
if len(rKey) != config.DeleteKeySize || !valid.IsAlphanumeric(rKey) {
return false
}
return true
}
2022-12-18 10:54:32 +00:00
type Response struct {
View string `json:"view,omitempty"`
Delete string `json:"delete,omitempty"`
Error string `json:"error,omitempty"`
}
2022-01-21 12:58:22 +00:00
2022-12-18 10:54:32 +00:00
func (p *Post) viewURL() string {
s := str.Get()
defer str.MustPut(s)
s.WriteString(config.BaseURL)
s.WriteString(p.TypeCode(false))
s.WriteString("/")
s.WriteString(p.UID())
return s.String()
}
2022-01-21 12:58:22 +00:00
2022-12-18 10:54:32 +00:00
func (p *Post) delURL() string {
if p.key == "" {
return ""
}
2022-12-18 10:54:32 +00:00
s := str.Get()
defer str.MustPut(s)
s.WriteString(config.BaseURL)
s.WriteString("d/")
s.WriteString(p.TypeCode(false))
s.WriteString("/")
s.WriteString(p.DelKey())
return s.String()
}
2022-12-18 10:54:32 +00:00
func (p *Post) String() string {
resp := new(Response)
resp.View = p.viewURL()
resp.Delete = p.delURL()
str, _ := json.MarshalToString(resp)
return str
}
2022-12-18 10:54:32 +00:00
func (p *Post) NewPostResponse(responder any) {
view := p.viewURL()
log.Info().
2022-07-14 07:50:26 +00:00
Str("type", p.TypeCode(false)).
2022-01-21 12:58:22 +00:00
Str("uid", p.UID()).Str("key", p.DelKey()).
2022-12-18 10:54:32 +00:00
Bool("private", p.Private()).Msgf("success: %s", view)
2022-07-14 07:50:26 +00:00
urlString := p.TypeCode(true)
delString := "del"
2022-12-18 10:54:32 +00:00
// for backwards compatibility with image scripts.
2022-07-14 07:50:26 +00:00
if p.TypeCode(false) == "i" {
urlString = "Imgurl"
delString = "ToDelete"
}
if cg, ginok := responder.(*gin.Context); ginok {
2022-12-18 10:54:32 +00:00
cg.JSON(201, gin.H{urlString: view, delString: p.delURL()})
2022-07-14 07:50:26 +00:00
}
2022-07-18 10:41:29 +00:00
if ct, tdok := responder.(*textValidator); tdok {
2022-12-18 10:54:32 +00:00
js, err := json.Marshal(gin.H{urlString: view, delString: p.delURL()})
2022-07-18 10:41:29 +00:00
if err != nil {
log.Error().Interface("post", p).
Err(err).Msg("json marshal failed")
2022-12-18 10:54:32 +00:00
ct.out = []byte("{\"error\":\"internal server error\"}")
2022-07-18 10:41:29 +00:00
}
ct.out = js
}
return
}
2022-07-14 07:50:26 +00:00
func (p *Post) Sum() []byte {
if p.b2sum == nil && p.data != nil {
p.b2sum = hash.Sum(hash.TypeBlake2b, p.data)
}
return p.b2sum
}
func (p *Post) Bytes() []byte {
return p.data
}