Browse Source

template simplification

master
Christian Müller 8 years ago
parent
commit
586e6ca1e4
  1. 11
      assets/templates/note.html
  2. 10
      assets/templates/stats.html
  3. 5
      render.go
  4. 30
      server.go
  5. 22
      storage.go
  6. 4
      test/main.go

11
assets/templates/note.html

@ -9,10 +9,19 @@
<script src='/note.js'></script> <script src='/note.js'></script>
</head> </head>
<body> <body>
{{if .Fraud}}
{{.Ads}} {{.Ads}}
<input type="hidden" id="encoded" value="{{.Encoded}}" />
<article></article>
<script>
document.getElementsByTagName("article")[0].innerHTML =
decodeURIComponent(escape(window.atob(document.getElementById("encoded").value)));
</script>
{{else}}
<article> <article>
{{.Content}} {{.Content}}
</article> </article>
{{end}}
<footer> <footer>
<a href="/">&#8962; notehub</a> &middot; <a href="/">&#8962; notehub</a> &middot;
{{if .ID}} {{if .ID}}
@ -21,7 +30,7 @@
<a href="/{{.ID}}/export">export</a> &middot; <a href="/{{.ID}}/export">export</a> &middot;
<a href="javascript:void(0)" onclick="report({{.ID}})">report abuse</a> &middot; <a href="javascript:void(0)" onclick="report({{.ID}})">report abuse</a> &middot;
{{end}} {{end}}
<a href="/TOS.md">terms of service</a> <a href="/TOS.md">tos</a>
</footer> </footer>
</body> </body>
</html> </html>

10
assets/templates/stats.html

@ -1,10 +0,0 @@
{{define "Stats"}}
<h2>Statistics</h2>
<table>
<tr><td>Published</td><td>{{.Published.Format "Jan 02, 2006 15:04:05 UTC"}}</td></tr>
{{if not .Edited.IsZero}}
<tr><td>Edited</td><td>{{.Edited.Format "Jan 02, 2006 15:04:05 UTC"}}</td></tr>
{{end}}
<tr><td>Views</td><td>{{.Views}}</td></tr>
</table>
{{end}}

5
render.go

@ -1,6 +1,7 @@
package main package main
import ( import (
"encoding/base64"
"errors" "errors"
"html/template" "html/template"
"io/ioutil" "io/ioutil"
@ -25,7 +26,6 @@ var (
rexpNewLine = regexp.MustCompile("[\n\r]") rexpNewLine = regexp.MustCompile("[\n\r]")
rexpNonAlphaNum = regexp.MustCompile("[`~!@#$%^&*_|+=?;:'\",.<>{}\\/]") rexpNonAlphaNum = regexp.MustCompile("[`~!@#$%^&*_|+=?;:'\",.<>{}\\/]")
rexpNoScriptIframe = regexp.MustCompile("(<.*?script.*?>.*?<.*?/.*?script.*?>|<.*?iframe.*?>|</.*?iframe.*?>)") rexpNoScriptIframe = regexp.MustCompile("(<.*?script.*?>.*?<.*?/.*?script.*?>|<.*?iframe.*?>|</.*?iframe.*?>)")
rexpLink = regexp.MustCompile("(ht|f)tps?://[^\\s]+")
errorUnathorised = errors.New("password is wrong") errorUnathorised = errors.New("password is wrong")
errorBadRequest = errors.New("password is empty") errorBadRequest = errors.New("password is empty")
@ -40,6 +40,9 @@ func (n *Note) prepare() {
n.Text = rexpNoScriptIframe.ReplaceAllString(n.Text, "") n.Text = rexpNoScriptIframe.ReplaceAllString(n.Text, "")
n.Title = strings.TrimSpace(rexpNonAlphaNum.ReplaceAllString(fstLine[:maxLength], "")) n.Title = strings.TrimSpace(rexpNonAlphaNum.ReplaceAllString(fstLine[:maxLength], ""))
n.Content = mdTmplHTML([]byte(n.Text)) n.Content = mdTmplHTML([]byte(n.Text))
if n.Fraud() {
n.Encoded = base64.StdEncoding.EncodeToString([]byte(n.Content))
}
} }
var mdRenderer = markdown.New(markdown.HTML(true)) var mdRenderer = markdown.New(markdown.HTML(true))

30
server.go

@ -1,8 +1,8 @@
package main package main
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt"
"html/template" "html/template"
"io" "io"
"io/ioutil" "io/ioutil"
@ -19,8 +19,6 @@ import (
"github.com/labstack/gommon/log" "github.com/labstack/gommon/log"
) )
const fraudThreshold = 7
var TEST_MODE = false var TEST_MODE = false
type Template struct{ templates *template.Template } type Template struct{ templates *template.Template }
@ -41,14 +39,14 @@ func main() {
TEST_MODE = os.Getenv("TEST_MODE") != "" TEST_MODE = os.Getenv("TEST_MODE") != ""
var ads []byte
adsFName := os.Getenv("ADS") adsFName := os.Getenv("ADS")
var ads template.HTML
if adsFName != "" { if adsFName != "" {
var err error data, err := ioutil.ReadFile(adsFName)
ads, err = ioutil.ReadFile(adsFName)
if err != nil { if err != nil {
e.Logger.Errorf("couldn't read file %s: %v", adsFName, err) e.Logger.Errorf("couldn't read file %s: %v", adsFName, err)
} }
ads = mdTmplHTML(data)
} }
go flushStatsLoop(e.Logger, db) go flushStatsLoop(e.Logger, db)
@ -79,11 +77,8 @@ func main() {
return c.String(code, statuses[code]) return c.String(code, statuses[code])
} }
defer incViews(n, db) defer incViews(n, db)
fraud := n.fraudelent() n.Ads = ads
if fraud { c.Logger().Debugf("/%s delivered (fraud: %t)", id, n.Fraud())
n.Ads = mdTmplHTML(ads)
}
c.Logger().Debugf("/%s delivered (fraud: %t)", id, fraud)
return c.Render(code, "Note", n) return c.Render(code, "Note", n)
}) })
@ -93,7 +88,7 @@ func main() {
var content string var content string
if code == http.StatusOK { if code == http.StatusOK {
defer incViews(n, db) defer incViews(n, db)
if n.fraudelent() { if n.Fraud() {
code = http.StatusForbidden code = http.StatusForbidden
content = statuses[code] content = statuses[code]
c.Logger().Warnf("/%s/export failed (code: %d)", id, code) c.Logger().Warnf("/%s/export failed (code: %d)", id, code)
@ -112,12 +107,11 @@ func main() {
c.Logger().Errorf("/%s/stats failed (code: %d)", id, code) c.Logger().Errorf("/%s/stats failed (code: %d)", id, code)
return c.String(code, statuses[code]) return c.String(code, statuses[code])
} }
n.prepare() stats := fmt.Sprintf("Published: %s\n Views: %d", n.Published, n.Views)
buf := bytes.NewBuffer([]byte{}) if !n.Edited.IsZero() {
e.Renderer.Render(buf, "Stats", n, c) stats = fmt.Sprintf("Published: %s\n Edited: %s\n Views: %d", n.Published, n.Edited, n.Views)
n.Content = template.HTML(buf.String()) }
c.Logger().Debugf("/%s/stats delivered", id) return c.String(code, stats)
return c.Render(code, "Note", n)
}) })
e.GET("/:id/edit", func(c echo.Context) error { e.GET("/:id/edit", func(c echo.Context) error {

22
storage.go

@ -21,18 +21,24 @@ func init() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
} }
const idLength = 5 const (
idLength = 5
fraudThreshold = 7
)
var rexpNoteID = regexp.MustCompile("[a-z0-9]+") var (
rexpNoteID = regexp.MustCompile("[a-z0-9]+")
rexpLink = regexp.MustCompile("(ht|f)tps?://[^\\s]+")
)
type Note struct { type Note struct {
ID, Title, Text, Password, DeprecatedPassword string ID, Title, Text, Password, DeprecatedPassword, Encoded string
Published, Edited time.Time Published, Edited time.Time
Views int Views int
Content, Ads template.HTML Content, Ads template.HTML
} }
func (n *Note) fraudelent() bool { func (n *Note) Fraud() bool {
res := rexpLink.FindAllString(n.Text, -1) res := rexpLink.FindAllString(n.Text, -1)
if len(res) < 3 { if len(res) < 3 {
return false return false
@ -40,7 +46,7 @@ func (n *Note) fraudelent() bool {
stripped := rexpLink.ReplaceAllString(n.Text, "") stripped := rexpLink.ReplaceAllString(n.Text, "")
l1 := len(n.Text) l1 := len(n.Text)
l2 := len(stripped) l2 := len(stripped)
return n.Views > 100 && return n.Views > 30 &&
int(math.Ceil(100*float64(l1-l2)/float64(l1))) > fraudThreshold int(math.Ceil(100*float64(l1-l2)/float64(l1))) > fraudThreshold
} }

4
test/main.go

@ -135,7 +135,7 @@ func main() {
Get(service + "/" + id + "/stats"). Get(service + "/" + id + "/stats").
Send(). Send().
ExpectStatus(200). ExpectStatus(200).
ExpectContent("<tr><td>Views</td><td>4</td></tr>"). ExpectContent("Views: 4").
ExpectContent("Published") ExpectContent("Published")
frisby.Create("Test edit page of new note"). frisby.Create("Test edit page of new note").
@ -310,7 +310,7 @@ func main() {
Get(service + "/" + id + "/stats"). Get(service + "/" + id + "/stats").
Send(). Send().
ExpectStatus(200). ExpectStatus(200).
ExpectContent("<tr><td>Views</td><td>102</td></tr>"). ExpectContent("Views: 102").
ExpectContent("Published") ExpectContent("Published")
frisby.Create("Test export of fraudulent note"). frisby.Create("Test export of fraudulent note").

Loading…
Cancel
Save