diff --git a/cmd/tumblr-import/tumblr-import.py b/cmd/tumblr-import/tumblr-import.py index 1e64eda..1d1bd1f 100644 --- a/cmd/tumblr-import/tumblr-import.py +++ b/cmd/tumblr-import/tumblr-import.py @@ -50,7 +50,7 @@ def main(tumblr, root, scheme): } log.info("Blog title: %s", SiteSettings["site"]["title"]) log.info("Description: %s", SiteSettings["site"]["description"]) - write_db(root, "app/settings", SiteSettings) + # write_db(root, "app/settings", SiteSettings) posts_total = r["posts-total"] # n log.info("Total Posts: %d", posts_total) @@ -63,6 +63,9 @@ def main(tumblr, root, scheme): POST_ID = 0 + # Unique Tumblr post IDs so no duplicates. + tumblr_posts = set() + while posts_start >= 0: log.info("GET PAGE start=%d num=%d\n", posts_start, per_page) r = api_get(API_ROOT, start=posts_start, num=per_page) @@ -80,6 +83,10 @@ def main(tumblr, root, scheme): timestamp = datetime.fromtimestamp(post["unix-timestamp"]) timestamp = timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") + if post["id"] in tumblr_posts: + continue + tumblr_posts.add(post["id"]) + slug = post.get("slug") if not slug: slug = re.sub(r'.*{}/'.format(tumblr), '', post.get("url-with-slug")) @@ -209,12 +216,15 @@ def _download_images(root, images): for i, url in enumerate(images): log.info("DOWNLOAD: %s", url) + filename = url.rsplit("/", 1)[-1] + filename = "static/photos/"+filename + if os.path.isfile(os.path.join(root, filename)): + result.append("/"+filename) + continue + r = requests.get(url) if r.ok: - filename = "static/photos/"+filename - if os.path.isfile(os.path.join(root, filename)): - continue with open(os.path.join(root, filename), "wb") as fh: fh.write(r.content) result.append("/"+filename) diff --git a/internal/controllers/contact/contact.go b/internal/controllers/contact/contact.go index 12aedf8..57fe0dd 100644 --- a/internal/controllers/contact/contact.go +++ b/internal/controllers/contact/contact.go @@ -10,16 +10,24 @@ import ( "github.com/gorilla/mux" "github.com/kirsle/blog/internal/forms" + "github.com/kirsle/blog/internal/log" "github.com/kirsle/blog/internal/mail" "github.com/kirsle/blog/internal/markdown" - "github.com/kirsle/blog/models/settings" "github.com/kirsle/blog/internal/render" "github.com/kirsle/blog/internal/responses" + "github.com/kirsle/blog/models/settings" ) // Register attaches the contact URL to the app. func Register(r *mux.Router) { r.HandleFunc("/contact", func(w http.ResponseWriter, r *http.Request) { + // Allow ?next= to redirect to other local pages. + nextURL := r.FormValue("next") + if nextURL != "" && nextURL[0] != '/' { + log.Error("/contact?next=: URL must be a local page beginning with /") + nextURL = "" + } + form := &forms.Contact{} v := map[string]interface{}{ "Form": form, @@ -42,6 +50,15 @@ func Register(r *mux.Router) { if r.Method == http.MethodPost { form.ParseForm(r) if err = form.Validate(); err != nil { + // If they're not from the /contact front-end, redirect them + // with the flash. + if len(nextURL) > 0 { + responses.FlashAndRedirect(w, r, nextURL, err.Error()) + return + } + + // Otherwise flash and let the /contact page render to retain + // their form fields so far. responses.Flash(w, r, err.Error()) } else { go mail.SendEmail(mail.Email{ @@ -72,7 +89,13 @@ func Register(r *mux.Router) { )) fh.Close() } - responses.FlashAndRedirect(w, r, "/contact", "Your message has been sent.") + + if len(nextURL) > 0 { + responses.FlashAndRedirect(w, r, nextURL, "Your message has been sent.") + } else { + responses.FlashAndRedirect(w, r, "/contact", "Your message has been sent.") + } + return } } diff --git a/internal/controllers/posts/feeds.go b/internal/controllers/posts/feeds.go index 093528e..2b3bbac 100644 --- a/internal/controllers/posts/feeds.go +++ b/internal/controllers/posts/feeds.go @@ -6,10 +6,10 @@ import ( "time" "github.com/gorilla/feeds" + "github.com/kirsle/blog/internal/responses" "github.com/kirsle/blog/models/posts" "github.com/kirsle/blog/models/settings" "github.com/kirsle/blog/models/users" - "github.com/kirsle/blog/internal/responses" ) func feedHandler(w http.ResponseWriter, r *http.Request) { @@ -46,7 +46,7 @@ func feedHandler(w http.ResponseWriter, r *http.Request) { Description: post.Body + suffix, Created: p.Created, }) - if i >= 5 { + if i == 9 { // 10 -1 break } } diff --git a/internal/controllers/posts/index.go b/internal/controllers/posts/index.go index 5b79547..1148f61 100644 --- a/internal/controllers/posts/index.go +++ b/internal/controllers/posts/index.go @@ -8,11 +8,11 @@ import ( "strconv" "github.com/kirsle/blog/internal/log" + "github.com/kirsle/blog/internal/render" + "github.com/kirsle/blog/internal/types" "github.com/kirsle/blog/models/comments" "github.com/kirsle/blog/models/posts" "github.com/kirsle/blog/models/users" - "github.com/kirsle/blog/internal/render" - "github.com/kirsle/blog/internal/types" ) // partialIndex renders and returns the blog index partial. @@ -28,10 +28,16 @@ func partialIndex(r *http.Request, tag, privacy string) template.HTML { if page <= 0 { page = 1 } - perPage := 5 // TODO: configurable + perPage := 10 // TODO: configurable offset := (page - 1) * perPage stop := offset + perPage + // Calculate page total. + var pages = int(len(pool) / perPage) + if pages == 0 { + pages = 1 + } + // Handle pagination. var previousPage, nextPage int if page > 1 { @@ -48,7 +54,7 @@ func partialIndex(r *http.Request, tag, privacy string) template.HTML { var view []PostMeta for i := offset; i < stop; i++ { if i >= len(pool) { - continue + break } post, err := posts.Load(pool[i].ID) if err != nil { @@ -81,6 +87,8 @@ func partialIndex(r *http.Request, tag, privacy string) template.HTML { v := map[string]interface{}{ "PreviousPage": previousPage, "NextPage": nextPage, + "Page": page, + "Pages": pages, "View": view, } render.Template(&output, r, "blog/index.partial", v) diff --git a/internal/render/templates.go b/internal/render/templates.go index 12de0a4..0da1af7 100644 --- a/internal/render/templates.go +++ b/internal/render/templates.go @@ -10,10 +10,10 @@ import ( "github.com/kirsle/blog/internal/log" "github.com/kirsle/blog/internal/middleware" "github.com/kirsle/blog/internal/middleware/auth" - "github.com/kirsle/blog/models/settings" - "github.com/kirsle/blog/models/users" "github.com/kirsle/blog/internal/sessions" "github.com/kirsle/blog/internal/types" + "github.com/kirsle/blog/models/settings" + "github.com/kirsle/blog/models/users" ) // Vars is an interface to implement by the templates to pass their own custom @@ -23,6 +23,7 @@ type vars struct { // Global, "constant" template variables. SetupNeeded bool Title string + Description string Path string TemplatePath string // actual template file on disk LoggedIn bool @@ -62,6 +63,7 @@ func Template(w io.Writer, r *http.Request, path string, data interface{}) error Request: r, RequestTime: r.Context().Value(types.StartTimeKey).(time.Time), Title: s.Site.Title, + Description: s.Site.Description, Path: r.URL.Path, Data: data, diff --git a/root/.layout.gohtml b/root/.layout.gohtml index 6490a3a..3db8d91 100644 --- a/root/.layout.gohtml +++ b/root/.layout.gohtml @@ -50,7 +50,7 @@

{{ .Title }}

-

Just another web blog.

+

{{ .Description }}

diff --git a/root/admin/settings.gohtml b/root/admin/settings.gohtml index 9a7e951..5d2973b 100644 --- a/root/admin/settings.gohtml +++ b/root/admin/settings.gohtml @@ -1,169 +1,173 @@ {{ define "title" }}Website Settings{{ end }} {{ define "content" }} -
- +
+
+ + -{{ with .Data.s }} -

The Basics

+ {{ with .Data.s }} +

The Basics

-
- - -
+
+ + +
-
- - -
+
+ + +
-
- - For getting notifications about comments, etc. - -
+
+ + For getting notifications about comments, etc. + +
-
- - - The base absolute URL to your website. This is used to generate - emails such as comment notifications. If not provided, these - emails will not be sent. - - -
+
+ + + The base absolute URL to your website. This is used to generate + emails such as comment notifications. If not provided, these + emails will not be sent. + + +
-

Redis Cache

+

Redis Cache

-

- Using a Redis cache can - boost the performance of the JSON database by caching documents in - memory instead of always reading from disk. -

+

+ Using a Redis cache can + boost the performance of the JSON database by caching documents in + memory instead of always reading from disk. +

-
- -
-
- - -
-
- - -
-
- - 0-15 - -
-
- - (optional) - -
+
+ +
+
+ + +
+
+ + +
+
+ + 0-15 + +
+
+ + (optional) + +
-

Email Settings

+

Email Settings

-
- -
-
- - -
-
- - -
-
- - -
-
- - (optional) - -
-
- - (optional) - -
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + (optional) + +
+
+ + (optional) + +
-
- - Cancel +
+ + Cancel +
+ {{ end }} + +
-{{ end }} - - +
{{ end }}