Browse Source

Checkpoint

master
Tim Schuster 1 year ago
parent
commit
4ebae6cb4f
Signed by: Tim Schuster <mail@timschuster.info> GPG Key ID: F9E27097EFB77F61

+ 2
- 1
.gitignore View File

@@ -1,3 +1,4 @@
1 1
 /microblog.db
2 2
 /vendor
3
-/Gopkg.lock
3
+/Gopkg.lock
4
+/config.secl

+ 4
- 0
Gopkg.toml View File

@@ -76,3 +76,7 @@
76 76
 [[constraint]]
77 77
   name = "mvdan.cc/xurls"
78 78
   version = "1.1.0"
79
+
80
+[[constraint]]
81
+  name = "github.com/russross/blackfriday"
82
+  version = "2.0.0"

+ 44
- 27
cmd/microblog/main.go View File

@@ -7,9 +7,9 @@ import (
7 7
 	"github.com/sirupsen/logrus"
8 8
 	"go.rls.moe/webapps/microblog/config"
9 9
 	"go.rls.moe/webapps/microblog/model"
10
-	"go.rls.moe/webapps/microblog/plugins"
11 10
 	"go.rls.moe/webapps/microblog/router"
12
-	"go.rls.moe/webapps/microblog/util/tmpl"
11
+	"go.rls.moe/webapps/microblog/router/common"
12
+	"go.rls.moe/webapps/microblog/router/nativeapi"
13 13
 	"go.rls.moe/webapps/microblog/util/mail"
14 14
 )
15 15
 
@@ -44,16 +44,8 @@ func main() {
44 44
 	e.Pre(
45 45
 		middleware.RemoveTrailingSlash(),
46 46
 	)
47
-	e.Use(
48
-		middleware.RequestID(),
49
-		middleware.LoggerWithConfig(middleware.LoggerConfig{
50
-			Format: "method=${method}, uri=${uri}, path=${path}, status=${status}\n",
51
-		}),
52
-		middleware.Recover(),
53
-		middleware.BodyLimit("10M"),
54
-		router.CtxMiddleware(db, mailIO, conf),
55
-	)
56
-	newRenderer, err := tmpl.NewTemplateRenderer("resources/*.html", conf, func(t *tmpl.TemplateRenderer) error {
47
+
48
+	newRenderer, err := common.NewTemplateRenderer("resources/*.html", conf, func(t *common.TemplateRenderer) error {
57 49
 		t.AddFunc("url", router.BuildUrl)
58 50
 		return nil
59 51
 	})
@@ -64,19 +56,55 @@ func main() {
64 56
 		e.Renderer = newRenderer
65 57
 		e.HTTPErrorHandler = newRenderer.ErrRender
66 58
 	}
67
-	e.GET("/login", router.LoginForm)
68
-	e.POST("/login", router.LoginPost)
69 59
 
60
+	e.Use(
61
+		middleware.RequestID(),
62
+		middleware.LoggerWithConfig(middleware.LoggerConfig{
63
+			Format: "method=${method}, uri=${uri}, path=${path}, status=${status}\n",
64
+		}),
65
+		middleware.Recover(),
66
+		middleware.BodyLimit("10M"),
67
+		common.CtxMiddleware(db, mailIO, newRenderer, conf),
68
+	)
69
+
70
+	setupMainPages(e)
71
+	setupAdminPanel(e)
72
+	setupWebmention(e)
73
+	setupMicropubEndpoint(e)
74
+	setupNativeApi(e)
75
+
76
+	e.Debug = false
77
+	e.Logger.SetLevel(log2.DEBUG)
78
+	log.Fatal(e.Start(conf.ServeOn))
79
+}
80
+
81
+func setupNativeApi(e *echo.Echo) {
82
+	nativeApi := e.Group("/microblog")
83
+	nativeApi.POST("/comment", nativeapi.PostComment)
84
+}
85
+
86
+func setupWebmention(e *echo.Echo) {
87
+	e.GET("/@mp/webmention", router.WebmentionEndpoint)
88
+}
89
+
90
+func setupMicropubEndpoint(e *echo.Echo) {
70 91
 	e.Any("/@mp", router.MicropubEndpoint)
71 92
 	e.POST("/@mp/media", router.MicropubMedia)
72 93
 	e.GET("/@mp/auth", router.OAuthAuthEndpoint)
73 94
 	e.POST("/@mp/auth", router.OAuthAuthEndpoint)
74 95
 	e.POST("/@mp/token", router.OAuthAccess)
96
+}
75 97
 
76
-	e.GET("/@:user", router.UserProfile)
77
-
98
+func setupAdminPanel(e *echo.Echo) {
78 99
 	e.GET("/admin", router.AdminPanel)
79 100
 	e.POST("/admin", router.AdminAction)
101
+}
102
+
103
+func setupMainPages(e *echo.Echo) {
104
+	e.GET("/login", router.LoginForm)
105
+	e.POST("/login", router.LoginPost)
106
+
107
+	e.GET("/@:user", router.UserProfile)
80 108
 
81 109
 	e.GET("/@:user/:post", router.GetBlogPost)
82 110
 	e.GET("/@:user/:post/:slug", router.GetBlogPostSlugged)
@@ -86,15 +114,4 @@ func main() {
86 114
 	e.GET("/media/:file", router.Media)
87 115
 
88 116
 	e.GET("/", router.IndexShowcase)
89
-
90
-	e.GET("/@mp/webmention", router.WebmentionEndpoint)
91
-
92
-	if err := plugins.Startup(conf); err != nil {
93
-		log.WithError(err).Fatal("Could not start plugins")
94
-		return
95
-	}
96
-
97
-	e.Debug = false
98
-	e.Logger.SetLevel(log2.DEBUG)
99
-	log.Fatal(e.Start(conf.ServeOn))
100 117
 }

+ 0
- 5
cmd/microblog/plugins.go View File

@@ -1,5 +0,0 @@
1
-package main
2
-
3
-import (
4
-	_ "go.rls.moe/webapps/microblog/plugins/archive-is"
5
-)

+ 0
- 5
config.secl View File

@@ -1,5 +0,0 @@
1
-pages: (
2
-    show-header: true
3
-    showcase: "@tscs37"
4
-    pagelimit: 10
5
-)

+ 0
- 2
config/config.go View File

@@ -15,7 +15,6 @@ type Config struct {
15 15
 	Crypto        Crypto     `secl:"crypto"`
16 16
 	Session       Session    `secl:"session"`
17 17
 	NoCache       bool       `secl:"no-cache"`
18
-	NoMinify      bool       `secl:"no-minify"`
19 18
 	Pages         Pages      `secl:"pages"`
20 19
 	Plugins       Plugins    `secl:"plugins"`
21 20
 	SMTP          SMTPConfig `secl:"smtp"`
@@ -62,7 +61,6 @@ const DefaultConfig = `
62 61
 		uri: microblog.db
63 62
 	)
64 63
 	no-cache: yes
65
-	no-minify: yes
66 64
 	session: (
67 65
 		lifetime-days: 120
68 66
 		secret: randstr128

+ 10
- 1
model/comments.go View File

@@ -1,6 +1,9 @@
1 1
 package model
2 2
 
3
-import "time"
3
+import (
4
+	"time"
5
+	"errors"
6
+)
4 7
 
5 8
 type Comment struct {
6 9
 	ID           IDType `gorm:"primary_key"`
@@ -13,3 +16,9 @@ type Comment struct {
13 16
 	Post         Post
14 17
 	Body         string
15 18
 }
19
+
20
+func (c *Comment) BeforeSave() error {
21
+	if len(c.Body) < 10 {
22
+		return errors.New("Must be 10 characters long")
23
+	}
24
+}

+ 4
- 0
model/post.go View File

@@ -60,6 +60,10 @@ func (p *Post) BeforeSave() error {
60 60
 		}
61 61
 		p.InReplyToTitle = doc.Find("title").First().Text()
62 62
 	}
63
+	if p.HTMLContent == "" && p.Content != "" {
64
+		p.HTMLContent = util.RenderToHTML(p.Content)
65
+	}
66
+	p.HTMLContent = util.NormalHTML(p.HTMLContent)
63 67
 	return err
64 68
 }
65 69
 

+ 0
- 71
plugins/archive-is/plugin.go View File

@@ -1,71 +0,0 @@
1
-package archiveis
2
-
3
-import (
4
-	"go.rls.moe/webapps/microblog/model"
5
-	"go.rls.moe/webapps/microblog/plugins"
6
-	"go.rls.moe/webapps/microblog/router"
7
-	"net/http"
8
-	"time"
9
-	"net/url"
10
-	"go.rls.moe/webapps/microblog/config"
11
-)
12
-
13
-func init() {
14
-	plugins.Plugins = append(plugins.Plugins,WebArchivePlugin{})
15
-}
16
-
17
-type WebArchivePlugin struct {}
18
-
19
-func (WebArchivePlugin) PluginName() string {
20
-	return "Archive-Is-Syndication"
21
-}
22
-
23
-func (WebArchivePlugin) Start(config *config.Config) error {
24
-	if !config.Plugins.EnableArchiveIs {
25
-		return nil
26
-	}
27
-	router.SyndicationRegistry = append(
28
-		router.SyndicationRegistry,
29
-		router.SyndicationTarget{
30
-			Name: "archive.is",
31
-			UID: "https://archive.fo/",
32
-			Service: &router.SyndicationService{
33
-				Name: "archive.is",
34
-				URL: "https://archive.fo/",
35
-				Photo: "https://archive.fo/favicon.ico",
36
-			},
37
-		},
38
-	)
39
-	return nil
40
-}
41
-
42
-func (WebArchivePlugin) PreCreatePost(c *router.Context, post *model.Post) error {
43
-	client := http.DefaultClient
44
-	client.Timeout = 120 * time.Second
45
-	archiveUrl := url.URL{}
46
-	archiveUrl.Scheme = "https"
47
-	archiveUrl.Host = "archive.today"
48
-	query := archiveUrl.Query()
49
-	query.Set("run", "1")
50
-	postUrl, err := router.BuildUrl(c, *post)
51
-	if err != nil {
52
-		return err
53
-	}
54
-	query.Set("url", postUrl)
55
-	archiveUrl.RawQuery = query.Encode()
56
-	resp, err := client.Get(archiveUrl.String())
57
-	if err != nil {
58
-		return err
59
-	}
60
-	defer resp.Body.Close()
61
-	loc := resp.Request.URL
62
-	post.AlternateURLs = append(post.AlternateURLs, model.AlternateURLs{
63
-		URL: loc.String(),
64
-		Name: "archive.is",
65
-	})
66
-	return nil
67
-}
68
-
69
-func (WebArchivePlugin) PostCreatePost(c *router.Context, post *model.Post) {
70
-	return
71
-}

+ 0
- 8
plugins/iface.go View File

@@ -1,8 +0,0 @@
1
-package plugins
2
-
3
-import "go.rls.moe/webapps/microblog/config"
4
-
5
-type Plugin interface {
6
-	PluginName() string
7
-	Start(config *config.Config) error
8
-}

+ 0
- 17
plugins/registry.go View File

@@ -1,17 +0,0 @@
1
-package plugins
2
-
3
-import (
4
-	"github.com/pkg/errors"
5
-	"go.rls.moe/webapps/microblog/config"
6
-)
7
-
8
-var Plugins = []Plugin{}
9
-
10
-func Startup(config *config.Config) error {
11
-	for k := range Plugins {
12
-		if err := Plugins[k].Start(config); err != nil {
13
-			return errors.Wrap(err, "Could not start plugin " + Plugins[k].PluginName())
14
-		}
15
-	}
16
-	return nil
17
-}

+ 8
- 0
resources/_cmtbox.tmpl.html View File

@@ -0,0 +1,8 @@
1
+<div class="commentbox">
2
+    <form method="POST" action="/microblog/comment">
3
+        <input type="hidden" name="post" value="{{.}}">
4
+        <textarea name="comment" placeholder="Enter your comment" required>
5
+        </textarea>
6
+        <input type="submit" value="Comment">
7
+    </form>
8
+</div>

+ 10
- 0
resources/_pstbox.tmpl.html View File

@@ -0,0 +1,10 @@
1
+<div class="postbox">
2
+    <form method="POST" action="/microblog/post" enctype="multipart/form-data">
3
+        <input type="text" name="title" required>
4
+        <textarea name="comment" placeholder="Enter your blog post content" required>
5
+        </textarea>
6
+        <input type="file" name="photo" placeholder="Attach file">
7
+        <input type="text" name="categories" placeholder="Enter categories seperated with a comma">
8
+        <input type="submit" value="Create Blogpost">
9
+    </form>
10
+</div>

+ 0
- 3
resources/error.html View File

@@ -8,9 +8,6 @@
8 8
     <h1>{{.code}} - {{.plain}}</h1>
9 9
     {{ end }}
10 10
     {{ if .err }}
11
-    <div class="message">
12
-        {{.err.Error}}
13
-    </div>
14 11
     {{ end }}
15 12
 </div>
16 13
 

+ 3
- 0
resources/h_entry.html View File

@@ -75,4 +75,7 @@
75 75
         {{ joinElements .post.GetCategories ", " "<span class=\"p-category\">" "</span>" }}
76 76
     </div>
77 77
     {{ end }}
78
+    {{ if .allowReplies }}
79
+        {{ template "_cmtbox.tmpl.html" .post.ID }}
80
+    {{ end }}
78 81
 </article>

+ 5
- 4
router/admin.go View File

@@ -6,6 +6,7 @@ import (
6 6
 	"github.com/labstack/echo"
7 7
 	"github.com/pkg/errors"
8 8
 	"go.rls.moe/webapps/microblog/model"
9
+	"go.rls.moe/webapps/microblog/router/common"
9 10
 )
10 11
 
11 12
 type adminPanelAction struct {
@@ -17,12 +18,12 @@ type adminPanelAction struct {
17 18
 }
18 19
 
19 20
 func AdminPanel(c echo.Context) error {
20
-	cc := c.(*Context)
21
+	cc := c.(*common.Context)
21 22
 	if u, err := cc.GetUser(); err != nil || !u.Admin {
22 23
 		return &echo.HTTPError{
23 24
 			Code:    http.StatusForbidden,
24 25
 			Message: "Forbidden",
25
-			Inner:   err,
26
+			//TODO add inner error
26 27
 		}
27 28
 	} else {
28 29
 		return c.Render(http.StatusOK, "admin.html", map[string]interface{}{
@@ -34,12 +35,12 @@ func AdminPanel(c echo.Context) error {
34 35
 }
35 36
 
36 37
 func AdminAction(c echo.Context) error {
37
-	cc := c.(*Context)
38
+	cc := c.(*common.Context)
38 39
 	if u, err := cc.GetUser(); err != nil || !u.Admin {
39 40
 		return &echo.HTTPError{
40 41
 			Code:    http.StatusForbidden,
41 42
 			Message: "Forbidden",
42
-			Inner:   err,
43
+			//TODO add inner error
43 44
 		}
44 45
 	}
45 46
 	action := adminPanelAction{}

+ 2
- 1
router/blog.go View File

@@ -5,10 +5,11 @@ import (
5 5
 
6 6
 	"github.com/labstack/echo"
7 7
 	"go.rls.moe/webapps/microblog/model"
8
+	"go.rls.moe/webapps/microblog/router/common"
8 9
 )
9 10
 
10 11
 func GetBlogPost(c echo.Context) error {
11
-	cc := c.(*Context)
12
+	cc := c.(*common.Context)
12 13
 	post := model.Post{}
13 14
 	post.PublicRefID = cc.Param("post")
14 15
 	query := cc.DB.Preload("User").Preload("Categories").Preload("AlternateURLs").Where(&post)

router/csp.go → router/common/csp.go View File

@@ -1,4 +1,4 @@
1
-package router
1
+package common
2 2
 
3 3
 import (
4 4
 	"strings"

router/ctx.go → router/common/ctx.go View File

@@ -1,4 +1,4 @@
1
-package router
1
+package common
2 2
 
3 3
 import (
4 4
 	"net/http"
@@ -10,6 +10,7 @@ import (
10 10
 	"go.rls.moe/webapps/microblog/config"
11 11
 	"go.rls.moe/webapps/microblog/model"
12 12
 	"go.rls.moe/webapps/microblog/util/mail"
13
+	"time"
13 14
 )
14 15
 
15 16
 type Context struct {
@@ -19,6 +20,7 @@ type Context struct {
19 20
 	EmailIO         *mail.EMailIO
20 21
 	Session         model.Session
21 22
 	AccessToken     model.OAuthAccess
23
+	Renderer        *TemplateRenderer
22 24
 	HasSession      bool
23 25
 	HasAuth         bool
24 26
 	HasSeenAnyToken bool
@@ -38,14 +40,20 @@ func (c *Context) SetDB(db *model.DB) {
38 40
 	c.DB = db
39 41
 }
40 42
 
41
-func CtxMiddleware(db *model.DB, mailIO *mail.EMailIO, config *config.Config) echo.MiddlewareFunc {
43
+func CtxMiddleware(db *model.DB, mailIO *mail.EMailIO, renderer *TemplateRenderer, config *config.Config) echo.MiddlewareFunc {
42 44
 	return func(next echo.HandlerFunc) echo.HandlerFunc {
43 45
 		return func(c echo.Context) error {
46
+			defer func(start time.Time) {
47
+				c.Logger().Debugf("Request took %08.4f ms",
48
+					time.Now().Sub(start).Seconds() * 1000,
49
+				)
50
+			}(time.Now())
44 51
 			cc := &Context{
45 52
 				DB:         db,
46 53
 				Config:     config,
47 54
 				EmailIO:    mailIO,
48 55
 				HasSession: false,
56
+				Renderer:   renderer,
49 57
 			}
50 58
 			cc.Context = c
51 59
 			sessId, err := cc.Cookie("session")
@@ -134,19 +142,13 @@ func (cc *Context) GetUser() (model.User, error) {
134 142
 	}
135 143
 }
136 144
 
137
-func (cc *Context) GetRouteFromURL(url string) echo.Context {
138
-	return cc.GetRouteFromRequest("GET", url)
139
-}
140
-
141
-func (cc *Context) GetRouteFromRequest(method, url string) echo.Context {
142
-	cNew := new(Context)
143
-	cc.Echo().Router().Find(method, url, cNew)
144
-	return cNew
145
+func (cc *Context) Render(code int, name string, data interface{}) error {
146
+	return cc.Renderer.Render(cc.Response(), name, data, cc)
145 147
 }
146 148
 
147 149
 var postUrlRegex = regexp.MustCompile(`/([^/]*)/[^/]*$`)
148 150
 
149
-func getPostIDFromUrl(url string) (string, error) {
151
+func GetPostIDFromUrl(url string) (string, error) {
150 152
 	matches := postUrlRegex.FindAllStringSubmatch(url, 1)
151 153
 	if matches == nil || len(matches) == 0 {
152 154
 		return "", JSONError{

router/err.go → router/common/error.go View File

@@ -1,4 +1,4 @@
1
-package router
1
+package common
2 2
 
3 3
 import "fmt"
4 4
 

util/tmpl/helper.go → router/common/helper.go View File

@@ -1,16 +1,15 @@
1
-package tmpl
1
+package common
2 2
 
3 3
 import (
4 4
 	"errors"
5 5
 	"html/template"
6 6
 	"time"
7 7
 
8
+	"fmt"
8 9
 	humanize "github.com/dustin/go-humanize"
9 10
 	"github.com/labstack/echo"
10 11
 	"go.rls.moe/webapps/microblog/util"
11 12
 	"strings"
12
-	"fmt"
13
-	"go.rls.moe/webapps/microblog/router"
14 13
 )
15 14
 
16 15
 func intFormatTime(t time.Time, mode string) string {
@@ -61,7 +60,7 @@ func intJoin(stringSlice []string, sep, prefix, suffix string) template.HTML {
61 60
 }
62 61
 
63 62
 func intMakeCSP(c echo.Context) template.HTMLAttr {
64
-	cc, ok := c.(*router.Context)
63
+	cc, ok := c.(*Context)
65 64
 	if ok {
66 65
 		return template.HTMLAttr(fmt.Sprintf(`nonce="%s"`, cc.CSPNonce))
67 66
 	}
@@ -72,4 +71,4 @@ func intMakeCSP(c echo.Context) template.HTMLAttr {
72 71
 		return template.HTMLAttr(fmt.Sprintf(`nonce="%s"`, nonce))
73 72
 	}
74 73
 	return template.HTMLAttr("")
75
-}
74
+}

util/tmpl/tmpl.go → router/common/tmpl.go View File

@@ -1,4 +1,4 @@
1
-package tmpl
1
+package common
2 2
 
3 3
 import (
4 4
 	"bytes"
@@ -8,9 +8,7 @@ import (
8 8
 
9 9
 	"github.com/labstack/echo"
10 10
 	"go.rls.moe/webapps/microblog/config"
11
-	"go.rls.moe/webapps/microblog/router"
12 11
 	"go.rls.moe/webapps/microblog/util"
13
-	"go.rls.moe/webapps/microblog/util/minifier"
14 12
 )
15 13
 
16 14
 type TemplateRenderer struct {
@@ -26,7 +24,6 @@ func NewTemplateRenderer(glob string, config *config.Config, setupCallback func(
26 24
 		templates:    nil,
27 25
 		glob:         glob,
28 26
 		disableCache: config.NoCache,
29
-		enableMinify: !config.NoMinify,
30 27
 		customFuncs:  map[string]interface{}{},
31 28
 	}
32 29
 	t.AddFunc("formatTime", intFormatTime)
@@ -61,9 +58,6 @@ func (t *TemplateRenderer) AddFunc(name string, f interface{}) {
61 58
 }
62 59
 
63 60
 func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
64
-	if t.enableMinify {
65
-		w = minifier.MinifyHTMLWriter(w)
66
-	}
67 61
 	if t.disableCache {
68 62
 		err := t.init()
69 63
 		if err != nil {
@@ -86,33 +80,32 @@ func (t *TemplateRenderer) Render(w io.Writer, name string, data interface{}, c
86 80
 }
87 81
 
88 82
 func (t *TemplateRenderer) ErrRender(err error, ec echo.Context) {
89
-	c, ok := ec.(*router.Context)
83
+	c, ok := ec.(*Context)
90 84
 	if !ok {
91
-		c = &router.Context{Context: ec}
85
+		c = &Context{Context: ec}
92 86
 	}
93
-	if jErr, ok := err.(router.JSONError); ok {
87
+	c.Logger().Error(err)
88
+	if jErr, ok := err.(JSONError); ok {
94 89
 		if err := c.JSON(jErr.Code, jErr); err != nil {
95 90
 			c.Logger().Error(err)
96 91
 		}
97 92
 		return
98 93
 	}
99 94
 	var outBuf = bytes.NewBuffer([]byte{})
100
-	var out = minifier.MinifyHTMLWriter(outBuf)
101 95
 	params := map[string]interface{}{
102 96
 		"err": err,
103 97
 	}
104 98
 	if httpErr, ok := err.(*echo.HTTPError); ok {
105 99
 		params["plain"] = httpErr.Message
106
-		params["err"] = httpErr.Inner
107 100
 		params["code"] = httpErr.Code
108
-		if err := t.templates.ExecuteTemplate(out, "error.html", params); err != nil {
101
+		if err := t.templates.ExecuteTemplate(outBuf, "error.html", params); err != nil {
109 102
 			c.Logger().Error(err)
110 103
 		}
111 104
 		if err := c.HTML(httpErr.Code, outBuf.String()); err != nil {
112 105
 			c.Logger().Error(err)
113 106
 		}
114 107
 	} else {
115
-		if err := t.templates.ExecuteTemplate(out, "error.html", params); err != nil {
108
+		if err := t.templates.ExecuteTemplate(outBuf, "error.html", params); err != nil {
116 109
 			c.Logger().Error(err)
117 110
 		}
118 111
 		if err := c.HTML(http.StatusOK, outBuf.String()); err != nil {

+ 2
- 3
router/index.go View File

@@ -7,6 +7,7 @@ import (
7 7
 	"github.com/labstack/echo"
8 8
 	"go.rls.moe/webapps/microblog/model"
9 9
 	"go.rls.moe/webapps/microblog/util"
10
+	"go.rls.moe/webapps/microblog/router/common"
10 11
 )
11 12
 
12 13
 var (
@@ -15,14 +16,12 @@ var (
15 16
 )
16 17
 
17 18
 func IndexShowcase(c echo.Context) error {
18
-	cc := c.(*Context)
19
-	routeCC := cc.GetRouteFromURL(cc.Config.Pages.Showcase)
19
+	cc := c.(*common.Context)
20 20
 	isBlogSC := regexSCBlog.MatchString(cc.Config.Pages.Showcase)
21 21
 	isUserSC := regexSCUser.MatchString(cc.Config.Pages.Showcase)
22 22
 	if isBlogSC {
23 23
 		matches := regexSCBlog.FindAllStringSubmatch(cc.Config.Pages.Showcase, 1)
24 24
 		post := model.Post{PublicRefID: matches[0][2]}
25
-		post.PublicRefID = routeCC.Param("post")
26 25
 		if err := cc.DB.Where(&post).First(&post).Error; err != nil {
27 26
 			return err
28 27
 		} else {

+ 2
- 1
router/login.go View File

@@ -5,6 +5,7 @@ import (
5 5
 	"go.rls.moe/webapps/microblog/model"
6 6
 	"net/http"
7 7
 	"time"
8
+	"go.rls.moe/webapps/microblog/router/common"
8 9
 )
9 10
 
10 11
 func LoginForm(c echo.Context) error {
@@ -14,7 +15,7 @@ func LoginForm(c echo.Context) error {
14 15
 }
15 16
 
16 17
 func LoginPost(c echo.Context) error {
17
-	cc := c.(*Context)
18
+	cc := c.(*common.Context)
18 19
 	db := cc.GetDB()
19 20
 	user := model.User{}
20 21
 	email := cc.FormValue("email")

+ 13
- 12
router/micropub.go View File

@@ -11,10 +11,11 @@ import (
11 11
 	"go.rls.moe/webapps/microblog/model"
12 12
 	"go.rls.moe/webapps/microblog/model/microformats"
13 13
 	"go.rls.moe/webapps/microblog/util"
14
+	"go.rls.moe/webapps/microblog/router/common"
14 15
 )
15 16
 
16 17
 func MicropubEndpoint(c echo.Context) error {
17
-	cc := c.(*Context)
18
+	cc := c.(*common.Context)
18 19
 	cc.Logger().Debug("Entering MP Endpoint")
19 20
 	q := c.QueryParam("q")
20 21
 	if q == "config" {
@@ -40,9 +41,9 @@ func MicropubEndpoint(c echo.Context) error {
40 41
 				}
41 42
 				c.Request().Body.Close()
42 43
 				if err := json.Unmarshal(subData, sub); err != nil {
43
-					return JSONError{
44
+					return common.JSONError{
44 45
 						http.StatusBadRequest,
45
-						JErrInvalidRequest,
46
+						common.JErrInvalidRequest,
46 47
 						err.Error(),
47 48
 					}
48 49
 				}
@@ -63,9 +64,9 @@ func MicropubEndpoint(c echo.Context) error {
63 64
 					} else if action == "undelete" {
64 65
 						return MicropubUnDelete(cc)
65 66
 					} else {
66
-						return JSONError{
67
+						return common.JSONError{
67 68
 							http.StatusBadRequest,
68
-							JErrInvalidRequest,
69
+							common.JErrInvalidRequest,
69 70
 							"Action unknown",
70 71
 						}
71 72
 					}
@@ -82,15 +83,15 @@ func MicropubEndpoint(c echo.Context) error {
82 83
 			}
83 84
 		}
84 85
 	}
85
-	return JSONError{
86
+	return common.JSONError{
86 87
 		http.StatusBadRequest,
87
-		JErrInvalidRequest,
88
+		common.JErrInvalidRequest,
88 89
 		"Request was incomplete or invalid",
89 90
 	}
90 91
 }
91 92
 
92 93
 func MicropubConfig(c echo.Context) error {
93
-	cc := c.(*Context)
94
+	cc := c.(*common.Context)
94 95
 	if cc.HasAuth {
95 96
 		if cc.Can(model.ScopeMedia) || cc.Can(model.ScopeCreate) {
96 97
 			return c.JSON(http.StatusOK, map[string]interface{}{
@@ -98,16 +99,16 @@ func MicropubConfig(c echo.Context) error {
98 99
 				"syndicate-to":   SyndicationRegistry,
99 100
 			})
100 101
 		} else {
101
-			return JSONError{
102
+			return common.JSONError{
102 103
 				http.StatusUnauthorized,
103
-				JErrInsufficientScope,
104
+				common.JErrInsufficientScope,
104 105
 				"The current Access Token does not have the necessary scope to perform this action",
105 106
 			}
106 107
 		}
107 108
 	} else {
108
-		return JSONError{
109
+		return common.JSONError{
109 110
 			http.StatusUnauthorized,
110
-			JErrUnauthorized,
111
+			common.JErrUnauthorized,
111 112
 			"Access Token or Login invalid",
112 113
 		}
113 114
 	}

+ 7
- 21
router/mpcreate.go View File

@@ -5,17 +5,17 @@ import (
5 5
 
6 6
 	"go.rls.moe/webapps/microblog/model"
7 7
 	"go.rls.moe/webapps/microblog/model/microformats"
8
-	"go.rls.moe/webapps/microblog/plugins"
8
+	"go.rls.moe/webapps/microblog/router/common"
9 9
 	"go.rls.moe/webapps/microblog/util"
10 10
 	"go.rls.moe/webapps/microblog/util/webmention"
11 11
 )
12 12
 
13 13
 type CreatePostPlugin interface {
14
-	PreCreatePost(context *Context, post *model.Post) error
15
-	PostCreatePost(context *Context, post *model.Post)
14
+	PreCreatePost(context *common.Context, post *model.Post) error
15
+	PostCreatePost(context *common.Context, post *model.Post)
16 16
 }
17 17
 
18
-func MicropubCreateForm(c *Context) error {
18
+func MicropubCreateForm(c *common.Context) error {
19 19
 	c.Logger().Debug("Handling Form Submitted Content")
20 20
 	if c.FormValue("h") == "entry" {
21 21
 		categories, hasCategories := c.Request().Form["category[]"]
@@ -26,9 +26,9 @@ func MicropubCreateForm(c *Context) error {
26 26
 			Name:        c.FormValue("name"),
27 27
 		}
28 28
 		if !post.HasContent() {
29
-			return JSONError{
29
+			return common.JSONError{
30 30
 				http.StatusBadRequest,
31
-				JErrInvalidRequest,
31
+				common.JErrInvalidRequest,
32 32
 				"Content is mandatory",
33 33
 			}
34 34
 		}
@@ -68,13 +68,6 @@ func MicropubCreateForm(c *Context) error {
68 68
 		if err := c.DB.Create(&post).Error; err != nil {
69 69
 			return err
70 70
 		}
71
-		for k := range plugins.Plugins {
72
-			if plg, ok := plugins.Plugins[k].(CreatePostPlugin); ok {
73
-				if err := plg.PreCreatePost(c, &post); err != nil {
74
-					return err
75
-				}
76
-			}
77
-		}
78 71
 		if err := c.DB.Save(&post).Error; err != nil {
79 72
 			return err
80 73
 		}
@@ -106,7 +99,7 @@ func MicropubCreateForm(c *Context) error {
106 99
 	}
107 100
 }
108 101
 
109
-func MicropubJSONCreate(c *Context, submission *microformats.Submission) error {
102
+func MicropubJSONCreate(c *common.Context, submission *microformats.Submission) error {
110 103
 	c.Logger().Debug("Beginning Create Post")
111 104
 	data := submission.Data
112 105
 	post := model.Post{
@@ -140,13 +133,6 @@ func MicropubJSONCreate(c *Context, submission *microformats.Submission) error {
140 133
 	if err := c.DB.Create(&post).Error; err != nil {
141 134
 		return err
142 135
 	}
143
-	for k := range plugins.Plugins {
144
-		if plg, ok := plugins.Plugins[k].(CreatePostPlugin); ok {
145
-			if err := plg.PreCreatePost(c, &post); err != nil {
146
-				return err
147
-			}
148
-		}
149
-	}
150 136
 	if err := c.DB.Save(&post).Error; err != nil {
151 137
 		return err
152 138
 	}

+ 11
- 10
router/mpdelete.go View File

@@ -2,21 +2,22 @@ package router
2 2
 
3 3
 import (
4 4
 	"go.rls.moe/webapps/microblog/model"
5
-	"net/http"
6 5
 	"go.rls.moe/webapps/microblog/model/microformats"
6
+	"go.rls.moe/webapps/microblog/router/common"
7
+	"net/http"
7 8
 )
8 9
 
9
-func MicropubDelete(c *Context) error {
10
+func MicropubDelete(c *common.Context) error {
10 11
 	return MicropubDeleteID(c, c.FormValue("url"))
11 12
 }
12 13
 
13
-func MicropubJSONDelete(c *Context, submission *microformats.Submission) error {
14
+func MicropubJSONDelete(c *common.Context, submission *microformats.Submission) error {
14 15
 	return MicropubDeleteID(c, submission.URL)
15 16
 }
16 17
 
17
-func MicropubDeleteID(c *Context, postUrl string) error {
18
+func MicropubDeleteID(c *common.Context, postUrl string) error {
18 19
 	post := model.Post{}
19
-	postID, err := getPostIDFromUrl(postUrl)
20
+	postID, err := common.GetPostIDFromUrl(postUrl)
20 21
 	if err != nil {
21 22
 		return err
22 23
 	}
@@ -28,17 +29,17 @@ func MicropubDeleteID(c *Context, postUrl string) error {
28 29
 	return c.NoContent(http.StatusNoContent)
29 30
 }
30 31
 
31
-func MicropubUnDelete(c *Context) error {
32
+func MicropubUnDelete(c *common.Context) error {
32 33
 	return MicropubUnDeleteID(c, c.FormValue("url"))
33 34
 }
34 35
 
35
-func MicropubJSONUnDelete(c *Context, submission *microformats.Submission) error {
36
+func MicropubJSONUnDelete(c *common.Context, submission *microformats.Submission) error {
36 37
 	return MicropubUnDeleteID(c, submission.URL)
37 38
 }
38 39
 
39
-func MicropubUnDeleteID(c *Context, postUrl string) error {
40
+func MicropubUnDeleteID(c *common.Context, postUrl string) error {
40 41
 	post := model.Post{}
41
-	postID, err := getPostIDFromUrl(postUrl)
42
+	postID, err := common.GetPostIDFromUrl(postUrl)
42 43
 	if err != nil {
43 44
 		return err
44 45
 	}
@@ -52,4 +53,4 @@ func MicropubUnDeleteID(c *Context, postUrl string) error {
52 53
 		return err
53 54
 	}
54 55
 	return c.NoContent(http.StatusNoContent)
55
-}
56
+}

+ 16
- 15
router/mpmedia.go View File

@@ -9,6 +9,7 @@ import (
9 9
 	"net/http"
10 10
 	"path/filepath"
11 11
 	"strings"
12
+	"go.rls.moe/webapps/microblog/router/common"
12 13
 )
13 14
 
14 15
 func extInMime(ext, mimeType string) bool {
@@ -49,7 +50,7 @@ func MicropubMedia(c echo.Context) error {
49 50
 			"error_description": err.Error(),
50 51
 		})
51 52
 	}
52
-	cc := c.(*Context)
53
+	cc := c.(*common.Context)
53 54
 	media, err := CreateMedia(cc, file)
54 55
 	if err != nil {
55 56
 		return err
@@ -59,53 +60,53 @@ func MicropubMedia(c echo.Context) error {
59 60
 	return c.NoContent(http.StatusCreated)
60 61
 }
61 62
 
62
-func CreateMedia(c *Context, header *multipart.FileHeader) (model.Media, error) {
63
+func CreateMedia(c *common.Context, header *multipart.FileHeader) (model.Media, error) {
63 64
 	media := model.Media{}
64 65
 	media.MimeType = header.Header.Get("Content-Type")
65 66
 	if !isMediaMime(media.MimeType) {
66
-		return media, JSONError{
67
+		return media, common.JSONError{
67 68
 			http.StatusBadRequest,
68
-			JErrInvalidRequest,
69
+			common.JErrInvalidRequest,
69 70
 			"MIME Type " + media.MimeType + " is not permitted",
70 71
 		}
71 72
 	}
72 73
 	media.FileExtension = filepath.Ext(header.Filename)
73 74
 	if !extInMime(media.FileExtension, media.MimeType) {
74
-		return media, JSONError{
75
+		return media, common.JSONError{
75 76
 			http.StatusBadRequest,
76
-			JErrInvalidRequest,
77
+			common.JErrInvalidRequest,
77 78
 			"MIME Type " + media.MimeType + "does not allow extension " + media.FileExtension,
78 79
 		}
79 80
 	}
80 81
 	file, err := header.Open()
81 82
 	if err != nil {
82
-		return media, JSONError{
83
+		return media, common.JSONError{
83 84
 			http.StatusBadRequest,
84
-			JErrInvalidRequest,
85
+			common.JErrInvalidRequest,
85 86
 			err.Error(),
86 87
 		}
87 88
 	}
88 89
 	media.File = make([]byte, header.Size)
89 90
 	_, err = file.Read(media.File)
90 91
 	if err != nil {
91
-		return media, JSONError{
92
+		return media, common.JSONError{
92 93
 			http.StatusBadRequest,
93
-			JErrInvalidRequest,
94
+			common.JErrInvalidRequest,
94 95
 			err.Error(),
95 96
 		}
96 97
 	}
97 98
 	media.User, err = c.GetUser()
98 99
 	if err != nil {
99
-		return media, JSONError{
100
+		return media, common.JSONError{
100 101
 			http.StatusBadRequest,
101
-			JErrInvalidRequest,
102
+			common.JErrInvalidRequest,
102 103
 			err.Error(),
103 104
 		}
104 105
 	}
105 106
 	if err := c.DB.Create(&media).Error; err != nil {
106
-		return media, JSONError{
107
+		return media, common.JSONError{
107 108
 			http.StatusInternalServerError,
108
-			JErrInternal,
109
+			common.JErrInternal,
109 110
 			err.Error(),
110 111
 		}
111 112
 	}
@@ -113,7 +114,7 @@ func CreateMedia(c *Context, header *multipart.FileHeader) (model.Media, error)
113 114
 }
114 115
 
115 116
 func Media(c echo.Context) error {
116
-	cc := c.(*Context)
117
+	cc := c.(*common.Context)
117 118
 	media := model.Media{}
118 119
 	media.PublicRefID = cc.Param("file")
119 120
 	media.FileExtension = filepath.Ext(media.PublicRefID)

+ 3
- 2
router/mpsource.go View File

@@ -4,11 +4,12 @@ import (
4 4
 	"net/http"
5 5
 
6 6
 	"go.rls.moe/webapps/microblog/model"
7
+	"go.rls.moe/webapps/microblog/router/common"
7 8
 )
8 9
 
9
-func MicropubSource(c *Context) error {
10
+func MicropubSource(c *common.Context) error {
10 11
 	post := model.Post{}
11
-	postID, err := getPostIDFromUrl(c.QueryParam("url"))
12
+	postID, err := common.GetPostIDFromUrl(c.QueryParam("url"))
12 13
 	if err != nil {
13 14
 		return err
14 15
 	}

+ 3
- 2
router/mpupdate.go View File

@@ -5,10 +5,11 @@ import (
5 5
 
6 6
 	"go.rls.moe/webapps/microblog/model"
7 7
 	"go.rls.moe/webapps/microblog/model/microformats"
8
+	"go.rls.moe/webapps/microblog/router/common"
8 9
 )
9 10
 
10
-func MicropubJSONUpdate(c *Context, submission *microformats.Submission) error {
11
-	postID, err := getPostIDFromUrl(submission.URL)
11
+func MicropubJSONUpdate(c *common.Context, submission *microformats.Submission) error {
12
+	postID, err := common.GetPostIDFromUrl(submission.URL)
12 13
 	if err != nil {
13 14
 		return err
14 15
 	}

+ 34
- 0
router/nativeapi/comment.go View File

@@ -0,0 +1,34 @@
1
+package nativeapi
2
+
3
+import (
4
+	"github.com/labstack/echo"
5
+	"go.rls.moe/webapps/microblog/model"
6
+	"go.rls.moe/webapps/microblog/util"
7
+	"go.rls.moe/webapps/microblog/router/common"
8
+	"strings"
9
+	"errors"
10
+)
11
+
12
+func PostComment(c echo.Context) error {
13
+	cc := c.(*common.Context)
14
+	post := model.Post{
15
+		PublicRefID: cc.FormValue("post"),
16
+	}
17
+	if err := cc.DB.Where(post).First(&post).Error; err != nil {
18
+		return err
19
+	}
20
+	comment := model.Comment{
21
+		IsWebMention: false,
22
+		PostID: post.ID,
23
+		Post: post,
24
+		Body: cc.FormValue("comment"),
25
+	}
26
+	if strings.TrimSpace(comment.Body) == "" {
27
+		return errors.New("must not be empty comment")
28
+	}
29
+	comment.Body = util.RenderToHTML(comment.Body)
30
+	if err := cc.DB.Create(&comment).Error; err != nil {
31
+		return err
32
+	}
33
+	return nil
34
+}

+ 3
- 2
router/oauth.go View File

@@ -11,6 +11,7 @@ import (
11 11
 	"github.com/pkg/errors"
12 12
 	"go.rls.moe/webapps/microblog/model"
13 13
 	"go.rls.moe/webapps/microblog/util"
14
+	"go.rls.moe/webapps/microblog/router/common"
14 15
 )
15 16
 
16 17
 type oAuthAuthRequest struct {
@@ -55,7 +56,7 @@ func OAuthAuthEndpoint(c echo.Context) error {
55 56
 	if err := c.Bind(authRequest); err != nil {
56 57
 		return err
57 58
 	}
58
-	cc := c.(*Context)
59
+	cc := c.(*common.Context)
59 60
 	if cc.HasSession {
60 61
 		userMe, err := BuildUrl(cc, cc.Session.User)
61 62
 		if err != nil {
@@ -153,7 +154,7 @@ type oauthAccessRequest struct {
153 154
 }
154 155
 
155 156
 func OAuthAccess(c echo.Context) error {
156
-	cc := c.(*Context)
157
+	cc := c.(*common.Context)
157 158
 	if authHeader := c.Request().Header.Get("Authorization"); authHeader != "" {
158 159
 		if !strings.HasPrefix(authHeader, "Bearer ") {
159 160
 			return errors.New("Authentication only allows Bearer Tokens")

+ 5
- 2
router/syndication.go View File

@@ -1,6 +1,9 @@
1 1
 package router
2 2
 
3
-import "net/http"
3
+import (
4
+	"net/http"
5
+	"go.rls.moe/webapps/microblog/router/common"
6
+)
4 7
 
5 8
 type SyndicationTarget struct {
6 9
 	UID     string              `json:"uid"`
@@ -23,7 +26,7 @@ type SyndicationUser struct {
23 26
 
24 27
 var SyndicationRegistry = []SyndicationTarget{}
25 28
 
26
-func MicropubSyndication(c *Context) error {
29
+func MicropubSyndication(c *common.Context) error {
27 30
 	return c.JSON(http.StatusOK, map[string][]SyndicationTarget{
28 31
 		"syndicate-to": SyndicationRegistry,
29 32
 	})

+ 2
- 1
router/user.go View File

@@ -7,10 +7,11 @@ import (
7 7
 	"github.com/labstack/echo"
8 8
 	"go.rls.moe/webapps/microblog/model"
9 9
 	"go.rls.moe/webapps/microblog/util"
10
+	"go.rls.moe/webapps/microblog/router/common"
10 11
 )
11 12
 
12 13
 func UserProfile(c echo.Context) error {
13
-	cc := c.(*Context)
14
+	cc := c.(*common.Context)
14 15
 	userId := c.Param("user")
15 16
 	profileUser := model.User{}
16 17
 	if userId == "@me" {

+ 3
- 2
router/webmention.go View File

@@ -6,10 +6,11 @@ import (
6 6
 	"net/http"
7 7
 	"go.rls.moe/webapps/microblog/model"
8 8
 	"github.com/jinzhu/gorm"
9
+	"go.rls.moe/webapps/microblog/router/common"
9 10
 )
10 11
 
11 12
 func WebmentionEndpoint(c echo.Context) error {
12
-	cc := c.(*Context)
13
+	cc := c.(*common.Context)
13 14
 	source := c.FormValue("source")
14 15
 	target := c.FormValue("target")
15 16
 	db := cc.DB
@@ -19,7 +20,7 @@ func WebmentionEndpoint(c echo.Context) error {
19 20
 			log.Error(log)
20 21
 			return
21 22
 		}
22
-		postId, err := getPostIDFromUrl(target)
23
+		postId, err := common.GetPostIDFromUrl(target)
23 24
 		if err != nil {
24 25
 			log.Error(log)
25 26
 			return

+ 0
- 27
util/minifier/minify.go View File

@@ -1,27 +0,0 @@
1
-package minifier
2
-
3
-import (
4
-	"io"
5
-
6
-	"github.com/tdewolff/minify"
7
-	"github.com/tdewolff/minify/css"
8
-	"github.com/tdewolff/minify/html"
9
-	"github.com/tdewolff/minify/js"
10
-)
11
-
12
-var minifier *minify.M
13
-
14
-func init() {
15
-	minifier = minify.New()
16
-	minifier.Add("text/html", html.DefaultMinifier)
17
-	minifier.Add("text/css", css.DefaultMinifier)
18
-	minifier.Add("text/javascript", js.DefaultMinifier)
19
-}
20
-
21
-func MinifyHTML(out io.Writer, in io.Reader) error {
22
-	return minifier.Minify("text/html", out, in)
23
-}
24
-
25
-func MinifyHTMLWriter(out io.Writer) io.Writer {
26
-	return minifier.Writer("text/html", out)
27
-}

+ 22
- 4
util/util.go View File

@@ -18,6 +18,7 @@ import (
18 18
 	"mvdan.cc/xurls"
19 19
 	"github.com/PuerkitoBio/goquery"
20 20
 	"bytes"
21
+	"github.com/russross/blackfriday"
21 22
 )
22 23
 
23 24
 func MakeRandomString(bytes int) (string, error) {
@@ -90,7 +91,7 @@ func CurrentPage(c echo.Context) int {
90 91
 }
91 92
 
92 93
 func FindURLsInText(text string) []string {
93
-	return xurls.Strict().FindAllString(text, -1)
94
+	return xurls.Strict.FindAllString(text, -1)
94 95
 }
95 96
 
96 97
 func FindURLsInHTML(html string) ([]string, error) {
@@ -99,7 +100,7 @@ func FindURLsInHTML(html string) ([]string, error) {
99 100
 	if err != nil {
100 101
 		return nil, err
101 102
 	}
102
-	doc.Find("[href]").Each(func (i int, s *goquery.Selection)  {
103
+	doc.Find("[href]").Each(func(i int, s *goquery.Selection) {
103 104
 		url, ok := s.Attr("href")
104 105
 		if ok {
105 106
 			out = append(out, url)
@@ -109,7 +110,7 @@ func FindURLsInHTML(html string) ([]string, error) {
109 110
 }
110 111
 
111 112
 func ComparableURL(url2 *url.URL) (*url.URL, error) {
112
-	cleanUrl,err := url.Parse(url2.String())
113
+	cleanUrl, err := url.Parse(url2.String())
113 114
 	if err != nil {
114 115
 		return nil, err
115 116
 	}
@@ -117,4 +118,21 @@ func ComparableURL(url2 *url.URL) (*url.URL, error) {
117 118
 	cleanUrl.Fragment = ""
118 119
 	cleanUrl.User = nil
119 120
 	return cleanUrl, nil
120
-}
121
+}
122
+
123
+func RenderToHTML(s string) string {
124
+	htmlRenderer := blackfriday.NewHTMLRenderer(blackfriday.HTMLRendererParameters{
125
+		Flags: blackfriday.CommonHTMLFlags |
126
+			blackfriday.Safelink |
127
+			blackfriday.FootnoteReturnLinks |
128
+			blackfriday.NoreferrerLinks |
129
+			blackfriday.NofollowLinks,
130
+	})
131
+	s = string(blackfriday.Run(
132
+		[]byte(s),
133
+		blackfriday.WithExtensions(blackfriday.CommonExtensions),
134
+		blackfriday.WithRenderer(htmlRenderer),
135
+	))
136
+	s = NormalHTML(s)
137
+	return s
138
+}

+ 3
- 1
util/webmention/send.go View File

@@ -10,8 +10,10 @@ import (
10 10
 	"mvdan.cc/xurls"
11 11
 )
12 12
 
13
+// SendWebmentionPlain
14
+// deprecated
13 15
 func SendWebmentionPlain(source, body string) error {
14
-	return sendWebmentions(source, xurls.Strict().FindAllString(body, -1))
16
+	return sendWebmentions(source, xurls.Strict.FindAllString(body, -1))
15 17
 }
16 18
 
17 19
 func SendWebmentionHTML(source, body string) error {

Loading…
Cancel
Save