Browse Source

Checkpoint

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

+ 2
- 1
.gitignore View File

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

+ 1
- 0
cmd/microblog/.gitignore View File

@@ -0,0 +1 @@
1
+/microblog

+ 8
- 7
cmd/microblog/main.go View File

@@ -3,19 +3,20 @@ package main
3 3
 import (
4 4
 	"github.com/labstack/echo"
5 5
 	"github.com/labstack/echo/middleware"
6
-	log2 "github.com/labstack/gommon/log"
7 6
 	"github.com/sirupsen/logrus"
8 7
 	"go.rls.moe/webapps/microblog/config"
9 8
 	"go.rls.moe/webapps/microblog/model"
10 9
 	"go.rls.moe/webapps/microblog/router"
11 10
 	"go.rls.moe/webapps/microblog/router/common"
12 11
 	"go.rls.moe/webapps/microblog/router/nativeapi"
12
+	"go.rls.moe/webapps/microblog/util/logadapter"
13 13
 	"go.rls.moe/webapps/microblog/util/mail"
14 14
 )
15 15
 
16 16
 func main() {
17 17
 	conf, err := config.LoadConfig()
18 18
 	log := logrus.New()
19
+	log.Formatter = &logrus.TextFormatter{ForceColors: true}
19 20
 	if err != nil {
20 21
 		log.WithError(err).Fatal("Cannot open configuration")
21 22
 		return
@@ -27,7 +28,7 @@ func main() {
27 28
 	}
28 29
 	log.SetLevel(lvl)
29 30
 	log.Debug(conf.ServeOn)
30
-	db, err := model.OpenDB(conf)
31
+	db, err := model.OpenDB(conf, log)
31 32
 	if err != nil {
32 33
 		log.WithError(err).Fatal("Could not open DB connection")
33 34
 		return
@@ -45,8 +46,11 @@ func main() {
45 46
 		middleware.RemoveTrailingSlash(),
46 47
 	)
47 48
 
49
+	e.Logger = logadapter.NewLogrusAdapter(log)
50
+
48 51
 	newRenderer, err := common.NewTemplateRenderer("resources/*.html", conf, func(t *common.TemplateRenderer) error {
49 52
 		t.AddFunc("url", router.BuildUrl)
53
+		t.AddFunc("shortUrl", router.BuildShortUrl)
50 54
 		return nil
51 55
 	})
52 56
 	if err != nil {
@@ -59,9 +63,6 @@ func main() {
59 63
 
60 64
 	e.Use(
61 65
 		middleware.RequestID(),
62
-		middleware.LoggerWithConfig(middleware.LoggerConfig{
63
-			Format: "method=${method}, uri=${uri}, path=${path}, status=${status}\n",
64
-		}),
65 66
 		middleware.Recover(),
66 67
 		middleware.BodyLimit("10M"),
67 68
 		common.CtxMiddleware(db, mailIO, newRenderer, conf),
@@ -73,14 +74,14 @@ func main() {
73 74
 	setupMicropubEndpoint(e)
74 75
 	setupNativeApi(e)
75 76
 
76
-	e.Debug = false
77
-	e.Logger.SetLevel(log2.DEBUG)
77
+	e.Debug = true
78 78
 	log.Fatal(e.Start(conf.ServeOn))
79 79
 }
80 80
 
81 81
 func setupNativeApi(e *echo.Echo) {
82 82
 	nativeApi := e.Group("/microblog")
83 83
 	nativeApi.POST("/comment", nativeapi.PostComment)
84
+	nativeApi.POST("/post", nativeapi.PostEntry)
84 85
 }
85 86
 
86 87
 func setupWebmention(e *echo.Echo) {

+ 26
- 11
model/comments.go View File

@@ -1,24 +1,39 @@
1 1
 package model
2 2
 
3 3
 import (
4
-	"time"
5 4
 	"errors"
5
+	"time"
6
+)
7
+
8
+const (
9
+	CommentTypeNormal     = "comment"
10
+	CommentTypeWebmention = "webmention"
6 11
 )
7 12
 
8 13
 type Comment struct {
9
-	ID           IDType `gorm:"primary_key"`
10
-	CreatedAt    time.Time
11
-	UpdatedAt    time.Time
12
-	DeletedAt    *time.Time
13
-	IsWebMention bool
14
-	SourceURL    string // either the source post or the profile URL / email in URL form
15
-	PostID       IDType
16
-	Post         Post
17
-	Body         string
14
+	ID         IDType `gorm:"primary_key"`
15
+	CreatedAt  time.Time
16
+	UpdatedAt  time.Time
17
+	DeletedAt  *time.Time
18
+	Type       string
19
+	SourceURL  string // either the source post or the profile URL / email in URL form
20
+	AuthorName string
21
+	AuthorLink string
22
+	PostID     IDType
23
+	Post       Post
24
+	Body       string
18 25
 }
19 26
 
20 27
 func (c *Comment) BeforeSave() error {
21 28
 	if len(c.Body) < 10 {
22 29
 		return errors.New("Must be 10 characters long")
23 30
 	}
24
-}
31
+	return nil
32
+}
33
+
34
+func (c *Comment) Edited() bool {
35
+	if c.CreatedAt.Add(2 * 60 * time.Second).Before(c.UpdatedAt) {
36
+		return true
37
+	}
38
+	return false
39
+}

+ 21
- 0
model/comments_test.go View File

@@ -0,0 +1,21 @@
1
+package model
2
+
3
+import (
4
+	"testing"
5
+	"time"
6
+
7
+	"github.com/stretchr/testify/assert"
8
+)
9
+
10
+func TestComment_Edited(t *testing.T) {
11
+	a := assert.New(t)
12
+	c := Comment{
13
+		CreatedAt: time.Date(1990, 10, 10, 20, 20, 20, 20, time.UTC),
14
+		UpdatedAt: time.Date(1990, 10, 10, 20, 20, 20, 20, time.UTC),
15
+	}
16
+	a.False(c.Edited())
17
+	c.UpdatedAt = time.Date(1990, 10, 10, 20, 22, 20, 20, time.UTC)
18
+	a.False(c.Edited())
19
+	c.UpdatedAt = time.Date(1990, 10, 10, 20, 22, 20, 21, time.UTC)
20
+	a.True(c.Edited())
21
+}

+ 9
- 1
model/db.go View File

@@ -5,19 +5,26 @@ import (
5 5
 	_ "github.com/jinzhu/gorm/dialects/mysql"
6 6
 	_ "github.com/jinzhu/gorm/dialects/postgres"
7 7
 	_ "github.com/jinzhu/gorm/dialects/sqlite"
8
+	"github.com/sirupsen/logrus"
8 9
 	"go.rls.moe/webapps/microblog/config"
10
+	"go.rls.moe/webapps/microblog/util/logadapter"
9 11
 )
10 12
 
11 13
 type IDType = uint64
12 14
 
13 15
 type DB = gorm.DB
14 16
 
15
-func OpenDB(config *config.Config) (*DB, error) {
17
+type ContextableItem interface {
18
+	SetDB(*DB)
19
+}
20
+
21
+func OpenDB(config *config.Config, log *logrus.Logger) (*DB, error) {
16 22
 	db, err := gorm.Open(config.DatabaseType, config.DatabaseURI)
17 23
 	if err != nil {
18 24
 		return nil, err
19 25
 	}
20 26
 	db.LogMode(true)
27
+	db.SetLogger(logadapter.RedirectPrintToDebug{log.WithField("source", "db")})
21 28
 	u := &User{
22 29
 		Username: "admin",
23 30
 		EMail:    "root@localhost",
@@ -40,6 +47,7 @@ func OpenDB(config *config.Config) (*DB, error) {
40 47
 	db.AutoMigrate(&OAuthAccess{})
41 48
 	db.AutoMigrate(&Media{})
42 49
 	db.AutoMigrate(&AlternateURLs{})
50
+	db.AutoMigrate(&Comment{})
43 51
 	errs := db.GetErrors()
44 52
 	for err := range errs {
45 53
 		if errs[err] != nil {

+ 19
- 0
model/post.go View File

@@ -8,6 +8,8 @@ import (
8 8
 	"go.rls.moe/webapps/microblog/util"
9 9
 )
10 10
 
11
+var _ ContextableItem = &Post{}
12
+
11 13
 type Post struct {
12 14
 	ID            IDType `gorm:"primary_key"`
13 15
 	CreatedAt     time.Time
@@ -30,6 +32,11 @@ type Post struct {
30 32
 	Photo          string
31 33
 	PhotoAlt       string
32 34
 	Comments       []Comment
35
+	db             *DB
36
+}
37
+
38
+func (p *Post) SetDB(db *DB) {
39
+	p.db = db
33 40
 }
34 41
 
35 42
 func (p Post) GetTitle() (out string) {
@@ -99,3 +106,15 @@ func (p Post) GetCategories() (out []string) {
99 106
 	}
100 107
 	return out
101 108
 }
109
+
110
+func (p Post) GetResponses() ([]Comment, error) {
111
+	db := p.db
112
+	out := []Comment{}
113
+	if err := db.
114
+		Where(Comment{PostID: p.ID}).
115
+		Order("created_at DESC").
116
+		Limit(100).Find(&out).Error; err != nil {
117
+		return nil, err
118
+	}
119
+	return out, nil
120
+}

+ 1
- 1
model/session.go View File

@@ -21,7 +21,7 @@ func (s *Session) BeforeCreate() error {
21 21
 
22 22
 func (s *Session) Expired(config *config.Config) bool {
23 23
 	ttl := s.CreatedAt.Add(time.Hour * 24 * time.Duration(config.Session.Lifetime))
24
-	if ttl.After(time.Now()) {
24
+	if !ttl.After(time.Now()) {
25 25
 		return true
26 26
 	}
27 27
 	return false

BIN
resources/.sass-cache/e04010402c656d5a0b88f9c1a11d13fee34ef76b/style.scssc View File


+ 2
- 2
resources/_base.tmpl.html View File

@@ -4,10 +4,10 @@
4 4
     {{ if .title }}<title>{{.title}}</title>{{ end }}
5 5
     {{ if not .no_canonical }}
6 6
     {{ if .post }}
7
-    <link rel="canonical" href="{{url .context .post}}">
7
+    <link rel="canonical" href="{{shortUrl .context .post }}">
8 8
     {{ end }}
9 9
     {{ if .user }}
10
-    <link rel="canonical" href="{{url .context .user}}">
10
+    <link rel="canonical" href="{{shortUrl .context .user }}">
11 11
     {{ end }}
12 12
     {{ end }}
13 13
     <link rel="stylesheet" {{makeCSPAttr .context}} href="{{.baseUrl}}/style.css">

+ 24
- 0
resources/_cmt.tmpl.html View File

@@ -0,0 +1,24 @@
1
+<div class="comment">
2
+    <div class="author">
3
+        <a href="{{ .AuthorLink }}">{{ .AuthorName }}</a>
4
+        {{ if eq .Type "comment" }}
5
+        commented
6
+        {{end}}
7
+        {{ if eq .Type "webmention" }}
8
+        <a href="{{.SourceURL}}">mentioned</a>
9
+        {{end}}
10
+        {{ $t := formatTime .CreatedAt "iso8906" }}
11
+        {{ $th := formatTime .CreatedAt "human" }}
12
+        <time class="dt-published" datetime="{{ $t }}" title="{{ $t }}">{{$th}}</time>
13
+        {{ if .Edited }}
14
+        {{ $t := formatTime .UpdateAt "iso8906" }}
15
+        {{ $th := formatTime .UpdatedAt "human" }}
16
+        (edited
17
+        <time class="dt-published" datetime="{{ $t }}" title="{{ $t }}">{{$th}}</time>)
18
+        {{ end }}
19
+        :
20
+    </div>
21
+    <div class="commentbody">
22
+        {{ safeHtml .Body}}
23
+    </div>
24
+</div>

+ 3
- 2
resources/_cmtbox.tmpl.html View File

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

+ 32
- 7
resources/_pstbox.tmpl.html View File

@@ -1,10 +1,35 @@
1
-<div class="postbox">
1
+<div class="form postbox">
2 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">
3
+        <label>
4
+            <span>Title</span>
5
+            <input
6
+                    type="text"
7
+                    size="60"
8
+                    name="title"
9
+                    placeholder="Post Title (optional)">
10
+        </label>
11
+        <label>
12
+            <textarea
13
+                    name="content"
14
+                    placeholder="Enter your blog post content"
15
+                    required></textarea>
16
+        </label>
17
+        <label>
18
+            <span>Photo</span>
19
+            <input
20
+                    type="file"
21
+                    name="photo">
22
+        </label>
23
+        <label>
24
+            <span>Categories</span>
25
+            <input
26
+                    type="text"
27
+                    name="categories"
28
+                    size="60"
29
+                    placeholder="Enter categories seperated with a comma (optional)">
30
+        </label>
31
+        <label class="submit">
32
+            <input type="submit" value="Create Blogpost">
33
+        </label>
9 34
     </form>
10 35
 </div>

+ 13
- 1
resources/h_entry.html View File

@@ -75,7 +75,19 @@
75 75
         {{ joinElements .post.GetCategories ", " "<span class=\"p-category\">" "</span>" }}
76 76
     </div>
77 77
     {{ end }}
78
+    {{ if or .allowReplies .comments }}
79
+    <hr>
80
+    {{ end }}
78 81
     {{ if .allowReplies }}
79
-        {{ template "_cmtbox.tmpl.html" .post.ID }}
82
+        {{ template "_cmtbox.tmpl.html" .post.PublicRefID }}
83
+    {{ end }}
84
+    {{ if .comments }}
85
+    <div class="responses">
86
+        <span class="response_count">{{ len .comments }} comments</span>
87
+        {{ range .comments }}
88
+        <hr>
89
+            {{ template "_cmt.tmpl.html" . }}
90
+        {{ end }}
91
+    </div>
80 92
     {{ end }}
81 93
 </article>

+ 62
- 0
resources/style.css View File

@@ -78,4 +78,66 @@ blockquote {
78 78
     padding: 0 2em 0 2em;
79 79
     width: 33%; }
80 80
 
81
+.form {
82
+  box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2);
83
+  padding: 1em;
84
+  overflow: auto; }
85
+  .form label {
86
+    display: block;
87
+    clear: both; }
88
+    .form label > * {
89
+      margin-top: 5px;
90
+      margin-bottom: 5px; }
91
+    .form label span {
92
+      float: left; }
93
+    .form label input, .form label textarea {
94
+      float: right; }
95
+    .form label textarea {
96
+      width: 100%;
97
+      height: 20em; }
98
+    .form label input[type=submit] {
99
+      display: block;
100
+      width: 20em;
101
+      float: none;
102
+      margin-right: auto;
103
+      margin-left: auto;
104
+      left: 0;
105
+      right: 0; }
106
+  .form label.submit {
107
+    padding-top: 7px;
108
+    overflow: auto; }
109
+
110
+input[type=submit] {
111
+  padding: 3px;
112
+  font-size: 14pt; }
113
+
114
+ol {
115
+  padding-left: 0; }
116
+
117
+.comment {
118
+  padding-top: 1em;
119
+  /*box-shadow: 1px 1px 4px rgba(0,0,0,0.2);*/ }
120
+
121
+.commentbox .textarea-wrapper {
122
+  margin-top: 2em;
123
+  width: 100%;
124
+  height: 5em;
125
+  padding-bottom: 8px; }
126
+  .commentbox .textarea-wrapper textarea {
127
+    -webkit-box-sizing: border-box;
128
+    -moz-box-sizing: border-box;
129
+    box-sizing: border-box;
130
+    width: 100%;
131
+    height: 100%;
132
+    display: block;
133
+    resize: none; }
134
+.commentbox input[type=submit] {
135
+  width: 20em;
136
+  left: 0;
137
+  right: 0;
138
+  margin: auto; }
139
+
140
+.responses {
141
+  margin-top: 1em; }
142
+
81 143
 /*# sourceMappingURL=style.css.map */

+ 1
- 1
resources/style.css.map View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
 "version": 3,
3
-"mappings": "AAAA,IAAK;EACH,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,UAAU;EACvB,SAAK;IACH,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE,GAAG;IACZ,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;;AAIf,WAAY;EACV,MAAM,EAAE,aAAa;EACrB,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,KAAK,EAAE,IAAI;EAET,oBAAI;IACF,UAAU,EAAE,GAAG;EAEjB,sBAAM;IACJ,OAAO,EAAE,YAAY;IACrB,KAAK,EAAE,IAAI;IACX,4BAAM;MACJ,KAAK,EAAE,IAAI;MACX,KAAK,EAAE,KAAK;MACZ,KAAK,EAAE,IAAI;MACX,SAAS,EAAE,IAAI;EAGnB,uBAAO;IACL,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;;AAMnB,cAAG;EACD,eAAe,EAAE,IAAI;;AAIzB,QAAS;EACP,UAAU,EAAE,8BAA2B;EACvC,OAAO,EAAE,GAAG;EACZ,aAAa,EAAE,GAAG;EAClB,UAAE;IACA,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,CAAC;EAElB,iBAAS;IACP,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,aAAa;IACrB,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;EAEV,mBAAW;IACT,OAAO,EAAE,GAAG;EAEd,4CAA0B;IACxB,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,GAAG;IACd,oEAAY;MACV,UAAU,EAAE,MAAM;;AAQxB,WAAY;EACV,UAAU,EAAE,8BAA8B;EAC1C,OAAO,EAAE,WAAW;EACpB,MAAM,EAAE,GAAG;;AAGb,YAAa;EACX,eAAe,EAAE,IAAI;EACrB,KAAK,EAAE,IAAI;;AAGb,UAAW;EACT,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,aAAa;EACtB,WAAW,EAAE,cAAc;;AAG7B,UAAW;EACT,OAAO,EAAE,KAAK;EACd,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;EAKlB,cAAc,EAAE,GAAG;EAJnB,YAAE;IACA,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,GAAG",
3
+"mappings": "AAAA,IAAK;EACH,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,IAAI;EACf,WAAW,EAAE,UAAU;EACvB,SAAK;IACH,MAAM,EAAE,aAAa;IACrB,OAAO,EAAE,GAAG;IACZ,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;;AAIf,WAAY;EACV,MAAM,EAAE,aAAa;EACrB,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,KAAK,EAAE,IAAI;EAET,oBAAI;IACF,UAAU,EAAE,GAAG;EAEjB,sBAAM;IACJ,OAAO,EAAE,YAAY;IACrB,KAAK,EAAE,IAAI;IACX,4BAAM;MACJ,KAAK,EAAE,IAAI;MACX,KAAK,EAAE,KAAK;MACZ,KAAK,EAAE,IAAI;MACX,SAAS,EAAE,IAAI;EAGnB,uBAAO;IACL,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;;AAMnB,cAAG;EACD,eAAe,EAAE,IAAI;;AAIzB,QAAS;EACP,UAAU,EAAE,8BAA8B;EAC1C,OAAO,EAAE,GAAG;EACZ,aAAa,EAAE,GAAG;EAClB,UAAE;IACA,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,CAAC;EAElB,iBAAS;IACP,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,aAAa;IACrB,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;EAEV,mBAAW;IACT,OAAO,EAAE,GAAG;EAEd,4CAA2B;IACzB,UAAU,EAAE,GAAG;IACf,SAAS,EAAE,GAAG;IACd,oEAAY;MACV,UAAU,EAAE,MAAM;;AAQxB,WAAY;EACV,UAAU,EAAE,8BAA8B;EAC1C,OAAO,EAAE,WAAW;EACpB,MAAM,EAAE,GAAG;;AAGb,YAAa;EACX,eAAe,EAAE,IAAI;EACrB,KAAK,EAAE,IAAI;;AAGb,UAAW;EACT,MAAM,EAAE,CAAC;EACT,OAAO,EAAE,aAAa;EACtB,WAAW,EAAE,cAAc;;AAG7B,UAAW;EACT,OAAO,EAAE,KAAK;EACd,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,MAAM;EAKlB,cAAc,EAAE,GAAG;EAJnB,YAAE;IACA,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,GAAG;;AAKd,KAAM;EACJ,UAAU,EAAE,8BAA8B;EAC1C,OAAO,EAAE,GAAG;EACZ,QAAQ,EAAE,IAAI;EACd,WAAM;IACJ,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAI;IACX,eAAI;MACF,UAAU,EAAE,GAAG;MACf,aAAa,EAAE,GAAG;IAEpB,gBAAK;MACH,KAAK,EAAE,IAAI;IAEb,uCAAgB;MACd,KAAK,EAAE,KAAK;IAEd,oBAAS;MACP,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;IAEd,8BAAmB;MACjB,OAAO,EAAE,KAAK;MACd,KAAK,EAAE,IAAI;MACX,KAAK,EAAE,IAAI;MACX,YAAY,EAAE,IAAI;MAClB,WAAW,EAAE,IAAI;MACjB,IAAI,EAAE,CAAC;MACP,KAAK,EAAE,CAAC;EAGZ,kBAAa;IACX,WAAW,EAAE,GAAG;IAChB,QAAQ,EAAE,IAAI;;AAIlB,kBAAmB;EACjB,OAAO,EAAE,GAAG;EACZ,SAAS,EAAE,IAAI;;AAGjB,EAAG;EACD,YAAY,EAAE,CAAC;;AAGjB,QAAS;EACL,WAAW,EAAE,GAAG;EAChB,4CAA4C;;AAI9C,6BAAkB;EAChB,UAAU,EAAE,GAAG;EACf,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,GAAG;EACX,cAAc,EAAE,GAAG;EACnB,sCAAS;IACP,kBAAkB,EAAE,UAAU;IAC9B,eAAe,EAAE,UAAU;IAC3B,UAAU,EAAE,UAAU;IACtB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,IAAI;AAGhB,8BAAmB;EACjB,KAAK,EAAE,IAAI;EACX,IAAI,EAAE,CAAC;EACP,KAAK,EAAE,CAAC;EACR,MAAM,EAAE,IAAI;;AAIhB,UAAW;EACT,UAAU,EAAE,GAAG",
4 4
 "sources": ["style.scss"],
5 5
 "names": [],
6 6
 "file": "style.css"

+ 82
- 3
resources/style.scss View File

@@ -46,7 +46,7 @@ html {
46 46
 }
47 47
 
48 48
 .h-entry {
49
-  box-shadow: 1px 1px 4px rgba(0,0,0,0.2);
49
+  box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2);
50 50
   padding: 4px;
51 51
   margin-bottom: 1em;
52 52
   * {
@@ -64,13 +64,13 @@ html {
64 64
   .e-content {
65 65
     padding: 4px;
66 66
   }
67
-  .categories,.syndications {
67
+  .categories, .syndications {
68 68
     margin-top: 1em;
69 69
     font-size: 8pt;
70 70
     .p-category {
71 71
       font-style: italic;
72 72
     }
73
-    .u-syndication{
73
+    .u-syndication {
74 74
 
75 75
     }
76 76
   }
@@ -102,4 +102,83 @@ blockquote {
102 102
     width: 33%;
103 103
   }
104 104
   padding-bottom: 2em;
105
+}
106
+
107
+.form {
108
+  box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2);
109
+  padding: 1em;
110
+  overflow: auto;
111
+  label {
112
+    display: block;
113
+    clear: both;
114
+    > * {
115
+      margin-top: 5px;
116
+      margin-bottom: 5px;
117
+    }
118
+    span {
119
+      float: left;
120
+    }
121
+    input, textarea {
122
+      float: right;
123
+    }
124
+    textarea {
125
+      width: 100%;
126
+      height: 20em;
127
+    }
128
+    input[type=submit] {
129
+      display: block;
130
+      width: 20em;
131
+      float: none;
132
+      margin-right: auto;
133
+      margin-left: auto;
134
+      left: 0;
135
+      right: 0;
136
+    }
137
+  }
138
+  label.submit {
139
+    padding-top: 7px;
140
+    overflow: auto;
141
+  }
142
+}
143
+
144
+input[type=submit] {
145
+  padding: 3px;
146
+  font-size: 14pt;
147
+}
148
+
149
+ol {
150
+  padding-left: 0;
151
+}
152
+
153
+.comment {
154
+    padding-top: 1em;
155
+    /*box-shadow: 1px 1px 4px rgba(0,0,0,0.2);*/
156
+}
157
+
158
+.commentbox {
159
+  .textarea-wrapper {
160
+    margin-top: 2em;
161
+    width: 100%;
162
+    height: 5em;
163
+    padding-bottom: 8px;
164
+    textarea {
165
+      -webkit-box-sizing: border-box;
166
+      -moz-box-sizing: border-box;
167
+      box-sizing: border-box;
168
+      width: 100%;
169
+      height: 100%;
170
+      display: block;
171
+      resize: none;
172
+    }
173
+  }
174
+  input[type=submit] {
175
+    width: 20em;
176
+    left: 0;
177
+    right: 0;
178
+    margin: auto;
179
+  }
180
+}
181
+
182
+.responses {
183
+  margin-top: 1em;
105 184
 }

+ 4
- 0
resources/user.html View File

@@ -5,6 +5,10 @@
5 5
         <a class="p-author h-card" href="{{url .context .user}}">@{{.user.Username}}</a>
6 6
     </h1>
7 7
 
8
+    {{ if .context.LoggedIn }}
9
+    {{ template "_pstbox.tmpl.html" }}
10
+    {{ end }}
11
+
8 12
     {{ if gt (len .posts) 0 }}
9 13
     {{ template "paginator.html" (withContext .context "items" (len .posts) "pageSize" .pageSize "page" .page) }}
10 14
     <div class="user-posts">

+ 10
- 3
router/blog.go View File

@@ -28,14 +28,21 @@ func GetBlogPost(c echo.Context) error {
28 28
 				Slug:        "deleted",
29 29
 			}
30 30
 			return c.Render(http.StatusOK, "blog.html", map[string]interface{}{
31
-				"post": grave,
31
+				"post":  grave,
32 32
 				"title": "[Deleted]",
33 33
 			})
34 34
 		}
35 35
 	}
36
+	post.SetDB(cc.DB)
37
+	comments, err := post.GetResponses()
38
+	if err != nil {
39
+		return err
40
+	}
36 41
 	return c.Render(http.StatusOK, "blog.html", map[string]interface{}{
37
-		"post": post,
38
-		"title": post.GetTitle(),
42
+		"post":         post,
43
+		"title":        post.GetTitle(),
44
+		"comments":     comments,
45
+		"allowReplies": cc.LoggedIn(),
39 46
 	})
40 47
 }
41 48
 

+ 31
- 1
router/common/ctx.go View File

@@ -7,8 +7,10 @@ import (
7 7
 	"regexp"
8 8
 
9 9
 	"github.com/labstack/echo"
10
+	"github.com/sirupsen/logrus"
10 11
 	"go.rls.moe/webapps/microblog/config"
11 12
 	"go.rls.moe/webapps/microblog/model"
13
+	"go.rls.moe/webapps/microblog/util/logadapter"
12 14
 	"go.rls.moe/webapps/microblog/util/mail"
13 15
 	"time"
14 16
 )
@@ -32,6 +34,10 @@ func (c *Context) GetDB() *model.DB {
32 34
 	return c.DB
33 35
 }
34 36
 
37
+func (c *Context) Logrus() *logrus.Entry {
38
+	return c.Logger().(*logadapter.LogrusToEcho).GetLogrus()
39
+}
40
+
35 41
 func (c *Context) AddWorker(f func()) {
36 42
 	c.PostRunWorkers = append(c.PostRunWorkers, f)
37 43
 }
@@ -40,12 +46,29 @@ func (c *Context) SetDB(db *model.DB) {
40 46
 	c.DB = db
41 47
 }
42 48
 
49
+func (c *Context) LoggedIn() bool {
50
+	c.Logger().Debug("Checking for Session")
51
+	if c.Session.SessionID == "" {
52
+		c.Logger().Debug("Session is not set")
53
+		return false
54
+	}
55
+	if c.Session.Expired(c.Config) {
56
+		c.Logger().Debug("Session is expired")
57
+		return false
58
+	}
59
+	return true
60
+}
61
+
62
+func (c *Context) RequestID() string {
63
+	return c.Response().Header().Get(echo.HeaderXRequestID)
64
+}
65
+
43 66
 func CtxMiddleware(db *model.DB, mailIO *mail.EMailIO, renderer *TemplateRenderer, config *config.Config) echo.MiddlewareFunc {
44 67
 	return func(next echo.HandlerFunc) echo.HandlerFunc {
45 68
 		return func(c echo.Context) error {
46 69
 			defer func(start time.Time) {
47 70
 				c.Logger().Debugf("Request took %08.4f ms",
48
-					time.Now().Sub(start).Seconds() * 1000,
71
+					time.Now().Sub(start).Seconds()*1000,
49 72
 				)
50 73
 			}(time.Now())
51 74
 			cc := &Context{
@@ -56,6 +79,13 @@ func CtxMiddleware(db *model.DB, mailIO *mail.EMailIO, renderer *TemplateRendere
56 79
 				Renderer:   renderer,
57 80
 			}
58 81
 			cc.Context = c
82
+			cc.Logrus().WithField("request-id", cc.RequestID()).Debug("Received new Request")
83
+			defer cc.Logrus().WithFields(logrus.Fields{
84
+				"method": cc.Request().Method,
85
+				"path":   cc.Path(),
86
+				"uri":    cc.Request().RequestURI,
87
+				"status": cc.Response().Status,
88
+			}).Debug("Processed Request")
59 89
 			sessId, err := cc.Cookie("session")
60 90
 			if err == nil {
61 91
 				sess := model.Session{SessionID: sessId.Value}

+ 1
- 1
router/index.go View File

@@ -6,8 +6,8 @@ import (
6 6
 
7 7
 	"github.com/labstack/echo"
8 8
 	"go.rls.moe/webapps/microblog/model"
9
-	"go.rls.moe/webapps/microblog/util"
10 9
 	"go.rls.moe/webapps/microblog/router/common"
10
+	"go.rls.moe/webapps/microblog/util"
11 11
 )
12 12
 
13 13
 var (

+ 1
- 1
router/login.go View File

@@ -3,9 +3,9 @@ package router
3 3
 import (
4 4
 	"github.com/labstack/echo"
5 5
 	"go.rls.moe/webapps/microblog/model"
6
+	"go.rls.moe/webapps/microblog/router/common"
6 7
 	"net/http"
7 8
 	"time"
8
-	"go.rls.moe/webapps/microblog/router/common"
9 9
 )
10 10
 
11 11
 func LoginForm(c echo.Context) error {

+ 1
- 1
router/micropub.go View File

@@ -10,8 +10,8 @@ import (
10 10
 	"github.com/labstack/echo"
11 11
 	"go.rls.moe/webapps/microblog/model"
12 12
 	"go.rls.moe/webapps/microblog/model/microformats"
13
-	"go.rls.moe/webapps/microblog/util"
14 13
 	"go.rls.moe/webapps/microblog/router/common"
14
+	"go.rls.moe/webapps/microblog/util"
15 15
 )
16 16
 
17 17
 func MicropubEndpoint(c echo.Context) error {

+ 1
- 1
router/mpmedia.go View File

@@ -3,13 +3,13 @@ package router
3 3
 import (
4 4
 	"github.com/labstack/echo"
5 5
 	"go.rls.moe/webapps/microblog/model"
6
+	"go.rls.moe/webapps/microblog/router/common"
6 7
 	"go.rls.moe/webapps/microblog/util"
7 8
 	"mime"
8 9
 	"mime/multipart"
9 10
 	"net/http"
10 11
 	"path/filepath"
11 12
 	"strings"
12
-	"go.rls.moe/webapps/microblog/router/common"
13 13
 )
14 14
 
15 15
 func extInMime(ext, mimeType string) bool {

+ 24
- 8
router/nativeapi/comment.go View File

@@ -1,27 +1,39 @@
1 1
 package nativeapi
2 2
 
3 3
 import (
4
+	"errors"
4 5
 	"github.com/labstack/echo"
5 6
 	"go.rls.moe/webapps/microblog/model"
6
-	"go.rls.moe/webapps/microblog/util"
7
+	"go.rls.moe/webapps/microblog/router"
7 8
 	"go.rls.moe/webapps/microblog/router/common"
9
+	"go.rls.moe/webapps/microblog/util"
10
+	"net/http"
8 11
 	"strings"
9
-	"errors"
10 12
 )
11 13
 
12 14
 func PostComment(c echo.Context) error {
13 15
 	cc := c.(*common.Context)
16
+	if !cc.LoggedIn() {
17
+		return errors.New("Must be logged in")
18
+	}
14 19
 	post := model.Post{
15 20
 		PublicRefID: cc.FormValue("post"),
16 21
 	}
17 22
 	if err := cc.DB.Where(post).First(&post).Error; err != nil {
18 23
 		return err
19 24
 	}
25
+	profileUrl, err := router.BuildUrl(cc, cc.Session.User)
26
+	if err != nil {
27
+		return err
28
+	}
20 29
 	comment := model.Comment{
21
-		IsWebMention: false,
22
-		PostID: post.ID,
23
-		Post: post,
24
-		Body: cc.FormValue("comment"),
30
+		Type:       model.CommentTypeNormal,
31
+		PostID:     post.ID,
32
+		Post:       post,
33
+		Body:       cc.FormValue("comment"),
34
+		SourceURL:  profileUrl,
35
+		AuthorName: cc.Session.User.Username,
36
+		AuthorLink: profileUrl,
25 37
 	}
26 38
 	if strings.TrimSpace(comment.Body) == "" {
27 39
 		return errors.New("must not be empty comment")
@@ -30,5 +42,9 @@ func PostComment(c echo.Context) error {
30 42
 	if err := cc.DB.Create(&comment).Error; err != nil {
31 43
 		return err
32 44
 	}
33
-	return nil
34
-}
45
+	url, err := router.BuildUrl(cc, post)
46
+	if err != nil {
47
+		return err
48
+	}
49
+	return cc.Redirect(http.StatusSeeOther, url)
50
+}

+ 43
- 0
router/nativeapi/post.go View File

@@ -0,0 +1,43 @@
1
+package nativeapi
2
+
3
+import (
4
+	"errors"
5
+	"net/http"
6
+
7
+	"github.com/labstack/echo"
8
+	"go.rls.moe/webapps/microblog/model"
9
+	"go.rls.moe/webapps/microblog/router"
10
+	"go.rls.moe/webapps/microblog/router/common"
11
+	"go.rls.moe/webapps/microblog/util"
12
+	"go.rls.moe/webapps/microblog/util/webmention"
13
+)
14
+
15
+func PostEntry(c echo.Context) error {
16
+	cc := c.(*common.Context)
17
+	if !cc.LoggedIn() {
18
+		return errors.New("Must be logged in")
19
+	}
20
+	post := model.Post{
21
+		Content: cc.FormValue("content"),
22
+		User:    cc.Session.User,
23
+		Name:    cc.FormValue("title"),
24
+	}
25
+	post.HTMLContent = util.RenderToHTML(post.Content)
26
+	if err := cc.DB.Create(&post).Error; err != nil {
27
+		return err
28
+	}
29
+	postUrl, err := router.BuildUrl(cc, post)
30
+	if err != nil {
31
+		return errors.New("Could not build Post URL")
32
+	}
33
+	cc.AddWorker(webmentionWorker(post, postUrl, c.Logger()))
34
+	return cc.Redirect(http.StatusSeeOther, postUrl)
35
+}
36
+
37
+func webmentionWorker(post model.Post, postUrl string, logger echo.Logger) func() {
38
+	return func() {
39
+		if err := webmention.SendWebmentionHTML(postUrl, post.HTMLContent); err != nil {
40
+			logger.Error(err)
41
+		}
42
+	}
43
+}

+ 1
- 1
router/oauth.go View File

@@ -10,8 +10,8 @@ import (
10 10
 	"github.com/labstack/echo"
11 11
 	"github.com/pkg/errors"
12 12
 	"go.rls.moe/webapps/microblog/model"
13
-	"go.rls.moe/webapps/microblog/util"
14 13
 	"go.rls.moe/webapps/microblog/router/common"
14
+	"go.rls.moe/webapps/microblog/util"
15 15
 )
16 16
 
17 17
 type oAuthAuthRequest struct {

+ 1
- 1
router/syndication.go View File

@@ -1,8 +1,8 @@
1 1
 package router
2 2
 
3 3
 import (
4
-	"net/http"
5 4
 	"go.rls.moe/webapps/microblog/router/common"
5
+	"net/http"
6 6
 )
7 7
 
8 8
 type SyndicationTarget struct {

+ 14
- 5
router/url.go View File

@@ -2,23 +2,32 @@ package router
2 2
 
3 3
 import (
4 4
 	"github.com/labstack/echo"
5
-	"go.rls.moe/webapps/microblog/model"
6 5
 	"github.com/pkg/errors"
6
+	"go.rls.moe/webapps/microblog/model"
7 7
 )
8
+
9
+func BuildShortUrl(c echo.Context, modelI interface{}) (string, error) {
10
+	return intBuildUrl(c, modelI, true)
11
+}
12
+
8 13
 func BuildUrl(c echo.Context, modelI interface{}) (string, error) {
9
-	return intBuildUrl(c, modelI)
14
+	return intBuildUrl(c, modelI, false)
10 15
 }
11 16
 
12
-func intBuildUrl(c echo.Context, modelI interface{}) (string, error) {
17
+func intBuildUrl(c echo.Context, modelI interface{}, shortUrl bool) (string, error) {
13 18
 	base := "https://" + c.Request().Host
14 19
 	switch data := modelI.(type) {
15 20
 	case model.User:
16 21
 		return base + c.Echo().URL(UserProfile, data.Username), nil
17 22
 	case model.Post:
18
-		return base + c.Echo().URL(GetBlogPostSlugged, data.User.Username, data.PublicRefID, data.Slug), nil
23
+		if !shortUrl {
24
+			return base + c.Echo().URL(GetBlogPostSlugged, data.User.Username, data.PublicRefID, data.Slug), nil
25
+		} else {
26
+			return base + c.Echo().URL(GetBlogPost, data.User.Username, data.PublicRefID, data.Slug), nil
27
+		}
19 28
 	case model.Media:
20 29
 		return base + c.Echo().URL(Media, data.PublicRefID+data.FileExtension), nil
21 30
 	default:
22 31
 		return "", errors.New("Unknown URL Model")
23 32
 	}
24
-}
33
+}

+ 1
- 1
router/user.go View File

@@ -6,8 +6,8 @@ import (
6 6
 
7 7
 	"github.com/labstack/echo"
8 8
 	"go.rls.moe/webapps/microblog/model"
9
-	"go.rls.moe/webapps/microblog/util"
10 9
 	"go.rls.moe/webapps/microblog/router/common"
10
+	"go.rls.moe/webapps/microblog/util"
11 11
 )
12 12
 
13 13
 func UserProfile(c echo.Context) error {

+ 9
- 9
router/webmention.go View File

@@ -1,12 +1,12 @@
1 1
 package router
2 2
 
3 3
 import (
4
+	"github.com/jinzhu/gorm"
4 5
 	"github.com/labstack/echo"
5
-	"go.rls.moe/webapps/microblog/util/webmention"
6
-	"net/http"
7 6
 	"go.rls.moe/webapps/microblog/model"
8
-	"github.com/jinzhu/gorm"
9 7
 	"go.rls.moe/webapps/microblog/router/common"
8
+	"go.rls.moe/webapps/microblog/util/webmention"
9
+	"net/http"
10 10
 )
11 11
 
12 12
 func WebmentionEndpoint(c echo.Context) error {
@@ -25,12 +25,12 @@ func WebmentionEndpoint(c echo.Context) error {
25 25
 			log.Error(log)
26 26
 			return
27 27
 		}
28
-		post := model.Post{PublicRefID:postId}
28
+		post := model.Post{PublicRefID: postId}
29 29
 		if err := db.Preload("Comments").Where(&post).First(&post).Error; err != nil {
30 30
 			log.Error(err)
31 31
 			return
32 32
 		}
33
-		comment := model.Comment{PostID:post.ID, SourceURL: source}
33
+		comment := model.Comment{PostID: post.ID, SourceURL: source}
34 34
 		if err := db.Where(&comment).First(&comment).Error; err != nil && err != gorm.ErrRecordNotFound {
35 35
 			log.Error(err)
36 36
 			return
@@ -48,12 +48,12 @@ func WebmentionEndpoint(c echo.Context) error {
48 48
 			return
49 49
 		}
50 50
 		db.Model(&post).Association("Comments").Append(&model.Comment{
51
-			IsWebMention: true,
51
+			Type:      model.CommentTypeWebmention,
52 52
 			SourceURL: source,
53
-			PostID: post.ID,
54
-			Body: body,
53
+			PostID:    post.ID,
54
+			Body:      body,
55 55
 		})
56 56
 	}
57 57
 	cc.AddWorker(worker)
58 58
 	return c.NoContent(http.StatusAccepted)
59
-}
59
+}

+ 11
- 0
util/logadapter/debug.go View File

@@ -0,0 +1,11 @@
1
+package logadapter
2
+
3
+import "github.com/sirupsen/logrus"
4
+
5
+type RedirectPrintToDebug struct {
6
+	Entry *logrus.Entry
7
+}
8
+
9
+func (r RedirectPrintToDebug) Print(v ...interface{}) {
10
+	r.Entry.Debug(v...)
11
+}

+ 182
- 0
util/logadapter/echo.go View File

@@ -0,0 +1,182 @@
1
+package logadapter
2
+
3
+import (
4
+	"io"
5
+
6
+	"github.com/labstack/echo"
7
+	"github.com/labstack/gommon/log"
8
+	"github.com/sirupsen/logrus"
9
+)
10
+
11
+const jsonEntryStub = "JSON Log Entry"
12
+
13
+var _ echo.Logger = &LogrusToEcho{}
14
+
15
+type LogrusToEcho struct {
16
+	log    *logrus.Logger
17
+	prefix string
18
+}
19
+
20
+func NewLogrusAdapter(e *logrus.Logger) *LogrusToEcho {
21
+	return &LogrusToEcho{log: e}
22
+}
23
+
24
+func (l *LogrusToEcho) Output() io.Writer {
25
+	return l.log.Out
26
+}
27
+
28
+func (l *LogrusToEcho) SetOutput(w io.Writer) {
29
+	l.log.Out = w
30
+}
31
+
32
+func (l *LogrusToEcho) GetLogrus() *logrus.Entry {
33
+	return l.log.WithField("source", "request_handler")
34
+}
35
+
36
+func (l *LogrusToEcho) Prefix() string {
37
+	return l.prefix
38
+}
39
+
40
+func (l *LogrusToEcho) SetPrefix(p string) {
41
+	l.prefix = p
42
+}
43
+
44
+func (l *LogrusToEcho) Level() log.Lvl {
45
+	switch l.getLogger().Level {
46
+	case logrus.DebugLevel:
47
+		return log.DEBUG
48
+	case logrus.InfoLevel:
49
+		return log.INFO
50
+	case logrus.WarnLevel:
51
+		return log.WARN
52
+	case logrus.ErrorLevel:
53
+		return log.ERROR
54
+	case logrus.PanicLevel:
55
+		return log.OFF
56
+	default:
57
+		return log.DEBUG
58
+	}
59
+}
60
+
61
+func (l *LogrusToEcho) SetLevel(v log.Lvl) {
62
+	switch v {
63
+	case log.DEBUG:
64
+		l.log.SetLevel(logrus.DebugLevel)
65
+	case log.INFO:
66
+		l.log.SetLevel(logrus.InfoLevel)
67
+	case log.WARN:
68
+		l.log.SetLevel(logrus.WarnLevel)
69
+	case log.ERROR:
70
+		l.log.SetLevel(logrus.ErrorLevel)
71
+	case log.OFF:
72
+		l.log.SetLevel(logrus.PanicLevel)
73
+	default:
74
+		l.log.SetLevel(logrus.DebugLevel)
75
+	}
76
+}
77
+
78
+func (l *LogrusToEcho) jsonToFields(j log.JSON) *logrus.Entry {
79
+	entry := l.getLogger().WithField("type", "json")
80
+	for k := range j {
81
+		entry = entry.WithField(k, j[k])
82
+	}
83
+	return entry
84
+}
85
+
86
+func (l *LogrusToEcho) coldStop() {
87
+	panic("Cold Stop")
88
+}
89
+
90
+func (l *LogrusToEcho) getLogger() *logrus.Entry {
91
+	return l.log.WithField("source", "http_framework")
92
+}
93
+
94
+func (l *LogrusToEcho) Print(i ...interface{}) {
95
+	l.getLogger().Print(i...)
96
+}
97
+
98
+func (l *LogrusToEcho) Printf(format string, args ...interface{}) {
99
+	l.getLogger().Printf(format, args...)
100
+}
101
+
102
+func (l *LogrusToEcho) Printj(j log.JSON) {
103
+	l.jsonToFields(j).WithField("source", "request_handler").Printf(jsonEntryStub)
104
+}
105
+
106
+func (l *LogrusToEcho) Debug(i ...interface{}) {
107
+	l.getLogger().WithField("source", "request_handler").Debug(i...)
108
+}
109
+
110
+func (l *LogrusToEcho) Debugf(format string, args ...interface{}) {
111
+	l.getLogger().WithField("source", "request_handler").Debugf(format, args...)
112
+}
113
+
114
+func (l *LogrusToEcho) Debugj(j log.JSON) {
115
+	l.jsonToFields(j).Debug(jsonEntryStub)
116
+}
117
+
118
+func (l *LogrusToEcho) Info(i ...interface{}) {
119
+	l.getLogger().Info(i...)
120
+}
121
+
122
+func (l *LogrusToEcho) Infof(format string, args ...interface{}) {
123
+	l.getLogger().Debugf(format, args...)
124
+}
125
+
126
+func (l *LogrusToEcho) Infoj(j log.JSON) {
127
+	l.jsonToFields(j).Info(jsonEntryStub)
128
+}
129
+
130
+func (l *LogrusToEcho) Warn(i ...interface{}) {
131
+	l.getLogger().Warn(i...)
132
+}
133
+
134
+func (l *LogrusToEcho) Warnf(format string, args ...interface{}) {
135
+	l.getLogger().Warnf(format, args...)
136
+}
137
+
138
+func (l *LogrusToEcho) Warnj(j log.JSON) {
139
+	l.jsonToFields(j).Warn(jsonEntryStub)
140
+}
141
+
142
+func (l *LogrusToEcho) Error(i ...interface{}) {
143
+	l.getLogger().Error(i...)
144
+}
145
+
146
+func (l *LogrusToEcho) Errorf(format string, args ...interface{}) {
147
+	l.getLogger().Errorf(format, args...)
148
+}
149
+
150
+func (l *LogrusToEcho) Errorj(j log.JSON) {
151
+	l.jsonToFields(j).Error(jsonEntryStub)
152
+}
153
+
154
+func (l *LogrusToEcho) Fatal(i ...interface{}) {
155
+	l.getLogger().Fatal(i...)
156
+	l.coldStop()
157
+}
158
+
159
+func (l *LogrusToEcho) Fatalj(j log.JSON) {
160
+	l.jsonToFields(j).Fatal(jsonEntryStub)
161
+	l.coldStop()
162
+}
163
+
164
+func (l *LogrusToEcho) Fatalf(format string, args ...interface{}) {
165
+	l.getLogger().Fatalf(format, args...)
166
+	l.coldStop()
167
+}
168
+
169
+func (l *LogrusToEcho) Panic(i ...interface{}) {
170
+	l.getLogger().Panic(i...)
171
+	l.coldStop()
172
+}
173
+
174
+func (l *LogrusToEcho) Panicj(j log.JSON) {
175
+	l.jsonToFields(j).Panic(jsonEntryStub)
176
+	l.coldStop()
177
+}
178
+
179
+func (l *LogrusToEcho) Panicf(format string, args ...interface{}) {
180
+	l.getLogger().Panicf(format, args...)
181
+	l.coldStop()
182
+}

+ 1
- 1
util/mail/send.go View File

@@ -14,7 +14,7 @@ import (
14 14
 type EMailIO struct {
15 15
 	config    config.SMTPConfig
16 16
 	templates *template.Template
17
-	glob string
17
+	glob      string
18 18
 }
19 19
 
20 20
 func NewEMailIO(glob string, config *config.Config) (*EMailIO, error) {

+ 3
- 3
util/util.go View File

@@ -9,16 +9,16 @@ import (
9 9
 	"strconv"
10 10
 	"strings"
11 11
 
12
+	"bytes"
13
+	"github.com/PuerkitoBio/goquery"
12 14
 	"github.com/jinzhu/gorm"
13 15
 	"github.com/labstack/echo"
14 16
 	"github.com/microcosm-cc/bluemonday"
17
+	"github.com/russross/blackfriday"
15 18
 	"golang.org/x/text/runes"
16 19
 	"golang.org/x/text/transform"
17 20
 	"golang.org/x/text/unicode/norm"
18 21
 	"mvdan.cc/xurls"
19
-	"github.com/PuerkitoBio/goquery"
20
-	"bytes"
21
-	"github.com/russross/blackfriday"
22 22
 )
23 23
 
24 24
 func MakeRandomString(bytes int) (string, error) {

+ 2
- 2
util/webmention/discovery_test.go View File

@@ -1,10 +1,10 @@
1 1
 package webmention
2 2
 
3 3
 import (
4
-	"testing"
5 4
 	"github.com/stretchr/testify/assert"
6 5
 	"go.rls.moe/webapps/microblog/util"
7 6
 	"strings"
7
+	"testing"
8 8
 )
9 9
 
10 10
 var testContent = `<a href="https://webmention.rocks/test/1">Test 1</a>
@@ -82,4 +82,4 @@ func TestFindEndpoint(t *testing.T) {
82 82
 		return
83 83
 	}
84 84
 	assert.True(strings.HasPrefix(endpoint, "https://webmention.rocks/test/23/page/webmention-endpoint/"), "Redirect Test has appropriate Prefix")
85
-}
85
+}

+ 1
- 1
util/webmention/getbody.go View File

@@ -2,4 +2,4 @@ package webmention
2 2
 
3 3
 func GetBody(url string) (string, error) {
4 4
 	return "", nil
5
-}
5
+}

+ 3
- 3
util/webmention/verify.go View File

@@ -2,9 +2,9 @@ package webmention
2 2
 
3 3
 import (
4 4
 	"github.com/PuerkitoBio/goquery"
5
-	"net/url"
6
-	"go.rls.moe/webapps/microblog/util"
7 5
 	"github.com/pkg/errors"
6
+	"go.rls.moe/webapps/microblog/util"
7
+	"net/url"
8 8
 )
9 9
 
10 10
 func VerifySource(source, target string) error {
@@ -41,4 +41,4 @@ func VerifySource(source, target string) error {
41 41
 		return errors.New("URL Target not found in Source")
42 42
 	}
43 43
 	return nil
44
-}
44
+}

+ 2
- 2
version.go View File

@@ -1,6 +1,6 @@
1 1
 package microblog
2 2
 
3 3
 const (
4
-	ProductName = `microblog`
4
+	ProductName    = `microblog`
5 5
 	ProductVersion = `v0.1-indev`
6
-)
6
+)

Loading…
Cancel
Save