Gonna be honest, guys, I don't think I know what an interface is

This commit is contained in:
Seednode 2023-09-12 20:56:39 -05:00
parent 62a8bde8ea
commit c77a151a24
8 changed files with 262 additions and 227 deletions

View File

@ -12,7 +12,7 @@ import (
) )
const ( const (
ReleaseVersion string = "0.73.1" ReleaseVersion string = "0.74.0"
) )
var ( var (

View File

@ -313,27 +313,27 @@ func ServePage(args []string) error {
formats := &types.Types{ formats := &types.Types{
Extensions: make(map[string]string), Extensions: make(map[string]string),
MimeTypes: make(map[string]*types.Type), MimeTypes: make(map[string]types.Type),
} }
if Audio || All { if Audio || All {
formats.Add(types.RegisterAudio()) formats.Add(types.Audio{})
} }
if Flash || All { if Flash || All {
formats.Add(types.RegisterFlash()) formats.Add(types.Flash{})
} }
if Images || All { if Images || All {
formats.Add(types.RegisterImages()) formats.Add(types.Images{})
} }
if Text || All { if Text || All {
formats.Add(types.RegisterText()) formats.Add(types.Text{})
} }
if Videos || All { if Videos || All {
formats.Add(types.RegisterVideos()) formats.Add(types.Video{})
} }
paths, err := normalizePaths(args, formats) paths, err := normalizePaths(args, formats)

View File

@ -9,41 +9,48 @@ import (
"strings" "strings"
) )
func RegisterAudio() *Type { type Audio struct{}
return &Type{
Css: func() string {
var css strings.Builder
css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) func (t Audio) Css() string {
css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) var css strings.Builder
return css.String() css.WriteString(`html,body{margin:0;padding:0;height:100%;}`)
}, css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`)
Title: func(queryParams, fileUri, filePath, fileName, mime string) string {
return fmt.Sprintf(`<title>%s</title>`, fileName) return css.String()
}, }
Body: func(queryParams, fileUri, filePath, fileName, mime string) string {
return fmt.Sprintf(`<a href="/%s"><audio controls autoplay loop preload="auto"><source src="%s" type="%s" alt="Roulette selected: %s">Your browser does not support the audio tag.</audio></a>`, func (t Audio) Title(queryParams, fileUri, filePath, fileName, mime string) string {
queryParams, return fmt.Sprintf(`<title>%s</title>`, fileName)
fileUri, }
mime,
fileName) func (t Audio) Body(queryParams, fileUri, filePath, fileName, mime string) string {
}, return fmt.Sprintf(`<a href="/%s"><audio controls autoplay loop preload="auto"><source src="%s" type="%s" alt="Roulette selected: %s">Your browser does not support the audio tag.</audio></a>`,
Extensions: map[string]string{ queryParams,
`.mp3`: `audio/mpeg`, fileUri,
`.ogg`: `audio/ogg`, mime,
`.oga`: `audio/ogg`, fileName)
}, }
MimeTypes: []string{
`application/ogg`, func (t Audio) Extensions() map[string]string {
`audio/mp3`, return map[string]string{
`audio/mpeg`, `.mp3`: `audio/mpeg`,
`audio/mpeg3`, `.ogg`: `audio/ogg`,
`audio/ogg`, `.oga`: `audio/ogg`,
`audio/x-mpeg-3`,
},
Validate: func(filePath string) bool {
return true
},
} }
} }
func (t Audio) MimeTypes() []string {
return []string{
`application/ogg`,
`audio/mp3`,
`audio/mpeg`,
`audio/mpeg3`,
`audio/ogg`,
`audio/x-mpeg-3`,
}
}
func (t Audio) Validate(filePath string) bool {
return true
}

View File

@ -9,35 +9,42 @@ import (
"strings" "strings"
) )
func RegisterFlash() *Type { type Flash struct{}
return &Type{
Css: func() string {
var css strings.Builder
css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) func (t Flash) Css() string {
css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) var css strings.Builder
return css.String() css.WriteString(`html,body{margin:0;padding:0;height:100%;}`)
}, css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`)
Title: func(queryParams, fileUri, filePath, fileName, mime string) string {
return fmt.Sprintf(`<title>%s</title>`, fileName)
},
Body: func(queryParams, fileUri, filePath, fileName, mime string) string {
var html strings.Builder
html.WriteString(fmt.Sprintf(`<script src="https://unpkg.com/@ruffle-rs/ruffle"></script><script>window.RufflePlayer.config = {autoplay:"on"};</script><embed src="%s"></embed>`, fileUri)) return css.String()
html.WriteString(fmt.Sprintf(`<br /><button onclick="window.location.href = '/%s';">Next</button>`, queryParams)) }
return html.String() func (t Flash) Title(queryParams, fileUri, filePath, fileName, mime string) string {
}, return fmt.Sprintf(`<title>%s</title>`, fileName)
Extensions: map[string]string{ }
`.swf`: `application/x-shockwave-flash`,
}, func (t Flash) Body(queryParams, fileUri, filePath, fileName, mime string) string {
MimeTypes: []string{ var html strings.Builder
`application/x-shockwave-flash`,
}, html.WriteString(fmt.Sprintf(`<script src="https://unpkg.com/@ruffle-rs/ruffle"></script><script>window.RufflePlayer.config = {autoplay:"on"};</script><embed src="%s"></embed>`, fileUri))
Validate: func(filePath string) bool { html.WriteString(fmt.Sprintf(`<br /><button onclick="window.location.href = '/%s';">Next</button>`, queryParams))
return true
}, return html.String()
}
func (t Flash) Extensions() map[string]string {
return map[string]string{
`.swf`: `application/x-shockwave-flash`,
} }
} }
func (t Flash) MimeTypes() []string {
return []string{
`application/x-shockwave-flash`,
}
}
func (t Flash) Validate(filePath string) bool {
return true
}

View File

@ -23,71 +23,78 @@ type Dimensions struct {
Height int Height int
} }
func RegisterImages() *Type { type Images struct{}
return &Type{
Css: func() string {
var css strings.Builder
css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) func (t Images) Css() string {
css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) var css strings.Builder
css.WriteString(`img{margin:auto;display:block;max-width:97%;max-height:97%;`)
css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}`)
return css.String() css.WriteString(`html,body{margin:0;padding:0;height:100%;}`)
}, css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`)
Title: func(queryParams, fileUri, filePath, fileName, mime string) string { css.WriteString(`img{margin:auto;display:block;max-width:97%;max-height:97%;`)
dimensions, err := ImageDimensions(filePath) css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}`)
if err != nil {
fmt.Println(err)
}
return fmt.Sprintf(`<title>%s (%dx%d)</title>`, return css.String()
fileName, }
dimensions.Width,
dimensions.Height)
},
Body: func(queryParams, fileUri, filePath, fileName, mime string) string {
dimensions, err := ImageDimensions(filePath)
if err != nil {
fmt.Println(err)
}
return fmt.Sprintf(`<a href="/%s"><img src="%s" width="%d" height="%d" type="%s" alt="Roulette selected: %s"></a>`, func (t Images) Title(queryParams, fileUri, filePath, fileName, mime string) string {
queryParams, dimensions, err := ImageDimensions(filePath)
fileUri, if err != nil {
dimensions.Width, fmt.Println(err)
dimensions.Height,
mime,
fileName)
},
Extensions: map[string]string{
`.apng`: `image/apng`,
`.avif`: `image/avif`,
`.bmp`: `image/bmp`,
`.gif`: `image/gif`,
`.jpg`: `image/jpeg`,
`.jpeg`: `image/jpeg`,
`.jfif`: `image/jpeg`,
`.pjp`: `image/jpeg`,
`.pjpeg`: `image/jpeg`,
`.png`: `image/png`,
`.svg`: `image/svg+xml`,
`.webp`: `image/webp`,
},
MimeTypes: []string{
`image/apng`,
`image/avif`,
`image/bmp`,
`image/gif`,
`image/jpeg`,
`image/png`,
`image/svg+xml`,
`image/webp`,
},
Validate: func(filePath string) bool {
return true
},
} }
return fmt.Sprintf(`<title>%s (%dx%d)</title>`,
fileName,
dimensions.Width,
dimensions.Height)
}
func (t Images) Body(queryParams, fileUri, filePath, fileName, mime string) string {
dimensions, err := ImageDimensions(filePath)
if err != nil {
fmt.Println(err)
}
return fmt.Sprintf(`<a href="/%s"><img src="%s" width="%d" height="%d" type="%s" alt="Roulette selected: %s"></a>`,
queryParams,
fileUri,
dimensions.Width,
dimensions.Height,
mime,
fileName)
}
func (t Images) Extensions() map[string]string {
return map[string]string{
`.apng`: `image/apng`,
`.avif`: `image/avif`,
`.bmp`: `image/bmp`,
`.gif`: `image/gif`,
`.jpg`: `image/jpeg`,
`.jpeg`: `image/jpeg`,
`.jfif`: `image/jpeg`,
`.pjp`: `image/jpeg`,
`.pjpeg`: `image/jpeg`,
`.png`: `image/png`,
`.svg`: `image/svg+xml`,
`.webp`: `image/webp`,
}
}
func (t Images) MimeTypes() []string {
return []string{
`image/apng`,
`image/avif`,
`image/bmp`,
`image/gif`,
`image/jpeg`,
`image/png`,
`image/svg+xml`,
`image/webp`,
}
}
func (t Images) Validate(filePath string) bool {
return true
} }
func ImageDimensions(path string) (*Dimensions, error) { func ImageDimensions(path string) (*Dimensions, error) {

View File

@ -12,64 +12,71 @@ import (
"unicode/utf8" "unicode/utf8"
) )
func RegisterText() *Type { type Text struct{}
return &Type{
Css: func() string {
var css strings.Builder
css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) func (t Text) Css() string {
css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;overflow:hidden;}`) var css strings.Builder
css.WriteString(`textarea{border:none;caret-color:transparent;outline:none;margin:.5rem;`)
css.WriteString(`height:99%;width:99%;white-space:pre;overflow:auto;}`)
return css.String() css.WriteString(`html,body{margin:0;padding:0;height:100%;}`)
}, css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;overflow:hidden;}`)
Title: func(queryParams, fileUri, filePath, fileName, mime string) string { css.WriteString(`textarea{border:none;caret-color:transparent;outline:none;margin:.5rem;`)
return fmt.Sprintf(`<title>%s</title>`, fileName) css.WriteString(`height:99%;width:99%;white-space:pre;overflow:auto;}`)
},
Body: func(queryParams, fileUri, filePath, fileName, mime string) string {
body, err := os.ReadFile(filePath)
if err != nil {
body = []byte{}
}
return fmt.Sprintf(`<a href="/%s"><textarea autofocus readonly>%s</textarea></a>`, return css.String()
queryParams, }
body)
},
Extensions: map[string]string{
`.css`: `text/css`,
`.csv`: `text/csv`,
`.html`: `text/html`,
`.js`: `text/javascript`,
`.json`: `application/json`,
`.md`: `text/markdown`,
`.txt`: `text/plain`,
`.xml`: `application/xml`,
},
MimeTypes: []string{
`application/json`,
`application/xml`,
`text/css`,
`text/csv`,
`text/javascript`,
`text/plain`,
`text/plain; charset=utf-8`,
},
Validate: func(path string) bool {
file, err := os.Open(path)
switch {
case errors.Is(err, os.ErrNotExist):
return false
case err != nil:
return false
}
defer file.Close()
head := make([]byte, 512) func (t Text) Title(queryParams, fileUri, filePath, fileName, mime string) string {
file.Read(head) return fmt.Sprintf(`<title>%s</title>`, fileName)
}
return utf8.Valid(head) func (t Text) Body(queryParams, fileUri, filePath, fileName, mime string) string {
}, body, err := os.ReadFile(filePath)
if err != nil {
body = []byte{}
}
return fmt.Sprintf(`<a href="/%s"><textarea autofocus readonly>%s</textarea></a>`,
queryParams,
body)
}
func (t Text) Extensions() map[string]string {
return map[string]string{
`.css`: `text/css`,
`.csv`: `text/csv`,
`.html`: `text/html`,
`.js`: `text/javascript`,
`.json`: `application/json`,
`.md`: `text/markdown`,
`.txt`: `text/plain`,
`.xml`: `application/xml`,
} }
} }
func (t Text) MimeTypes() []string {
return []string{
`application/json`,
`application/xml`,
`text/css`,
`text/csv`,
`text/javascript`,
`text/plain`,
`text/plain; charset=utf-8`,
}
}
func (t Text) Validate(filePath string) bool {
file, err := os.Open(filePath)
switch {
case errors.Is(err, os.ErrNotExist):
return false
case err != nil:
return false
}
defer file.Close()
head := make([]byte, 512)
file.Read(head)
return utf8.Valid(head)
}

View File

@ -11,29 +11,29 @@ import (
"path/filepath" "path/filepath"
) )
type Type struct { type Type interface {
Css func() string Css() string
Title func(queryParams, fileUri, filePath, fileName, mime string) string Title(queryParams, fileUri, filePath, fileName, mime string) string
Body func(queryParams, fileUri, filePath, fileName, mime string) string Body(queryParams, fileUri, filePath, fileName, mime string) string
Extensions map[string]string Extensions() map[string]string
MimeTypes []string MimeTypes() []string
Validate func(filePath string) bool Validate(filePath string) bool
} }
type Types struct { type Types struct {
Extensions map[string]string Extensions map[string]string
MimeTypes map[string]*Type MimeTypes map[string]Type
} }
func (s *Types) Add(t *Type) { func (s *Types) Add(t Type) {
for k, v := range t.Extensions { for k, v := range t.Extensions() {
_, exists := s.Extensions[k] _, exists := s.Extensions[k]
if !exists { if !exists {
s.Extensions[k] = v s.Extensions[k] = v
} }
} }
for _, v := range t.MimeTypes { for _, v := range t.MimeTypes() {
_, exists := s.Extensions[v] _, exists := s.Extensions[v]
if !exists { if !exists {
s.MimeTypes[v] = t s.MimeTypes[v] = t
@ -41,7 +41,7 @@ func (s *Types) Add(t *Type) {
} }
} }
func FileType(path string, registeredFormats *Types) (bool, *Type, string, error) { func FileType(path string, registeredFormats *Types) (bool, Type, string, error) {
file, err := os.Open(path) file, err := os.Open(path)
switch { switch {
case errors.Is(err, os.ErrNotExist): case errors.Is(err, os.ErrNotExist):

View File

@ -9,41 +9,48 @@ import (
"strings" "strings"
) )
func RegisterVideos() *Type { type Video struct{}
return &Type{
Css: func() string {
var css strings.Builder
css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) func (t Video) Css() string {
css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) var css strings.Builder
css.WriteString(`video{margin:auto;display:block;max-width:97%;max-height:97%;`)
css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}`)
return css.String() css.WriteString(`html,body{margin:0;padding:0;height:100%;}`)
}, css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`)
Title: func(queryParams, fileUri, filePath, fileName, mime string) string { css.WriteString(`video{margin:auto;display:block;max-width:97%;max-height:97%;`)
return fmt.Sprintf(`<title>%s</title>`, fileName) css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}`)
},
Body: func(queryParams, fileUri, filePath, fileName, mime string) string { return css.String()
return fmt.Sprintf(`<a href="/%s"><video controls autoplay loop preload="auto"><source src="%s" type="%s" alt="Roulette selected: %s">Your browser does not support the video tag.</video></a>`, }
queryParams,
fileUri, func (t Video) Title(queryParams, fileUri, filePath, fileName, mime string) string {
mime, return fmt.Sprintf(`<title>%s</title>`, fileName)
fileName) }
},
Extensions: map[string]string{ func (t Video) Body(queryParams, fileUri, filePath, fileName, mime string) string {
`.mp4`: `video/mp4`, return fmt.Sprintf(`<a href="/%s"><video controls autoplay loop preload="auto"><source src="%s" type="%s" alt="Roulette selected: %s">Your browser does not support the video tag.</video></a>`,
`.ogm`: `video/ogg`, queryParams,
`.ogv`: `video/ogg`, fileUri,
`.webm`: `video/webm`, mime,
}, fileName)
MimeTypes: []string{ }
`video/mp4`,
`video/ogg`, func (t Video) Extensions() map[string]string {
`video/webm`, return map[string]string{
}, `.mp4`: `video/mp4`,
Validate: func(filePath string) bool { `.ogm`: `video/ogg`,
return true `.ogv`: `video/ogg`,
}, `.webm`: `video/webm`,
} }
} }
func (t Video) MimeTypes() []string {
return []string{
`video/mp4`,
`video/ogg`,
`video/webm`,
}
}
func (t Video) Validate(filePath string) bool {
return true
}