Ver a proveniência

Add ability to publish pages publicly

T235
tags/v1.0
Matt Baer há 8 anos
ascendente
cometimento
2f64bcc808
5 ficheiros alterados com 111 adições e 4 eliminações
  1. +1
    -0
      README.md
  2. +3
    -2
      app.go
  3. +2
    -0
      config.go
  4. +102
    -1
      construction.go
  5. +3
    -1
      templates/editor.html

+ 1
- 0
README.md Ver ficheiro

@@ -51,6 +51,7 @@ DB_USER=dbuser DB_PASSWORD=pass DB_DB=htmlhouse PRIVATE_KEY=keys/dev PUBLIC_KEY=
| `PUBLIC_KEY` | Generated public key | None. **Required** |
| `PORT` | Port to run app on | `8080` |
| `STATIC_DIR` | Relative dir where static files are stored | `static` |
| `AUTO_APPROVE` | Automatically approves public posts | false |

### Notes



+ 3
- 2
app.go Ver ficheiro

@@ -68,6 +68,7 @@ func (app *app) initRouter() {
type EditorPage struct {
ID string
Content string
Public bool
}

func getEditor(app *app, w http.ResponseWriter, r *http.Request) error {
@@ -80,7 +81,7 @@ func getEditor(app *app, w http.ResponseWriter, r *http.Request) error {
fmt.Printf("\n%s\n", err)
defaultPage = []byte("<!DOCTYPE html>\n<html>\n</html>")
}
app.templates["editor"].ExecuteTemplate(w, "editor", &EditorPage{"", string(defaultPage)})
app.templates["editor"].ExecuteTemplate(w, "editor", &EditorPage{"", string(defaultPage), false})

return nil
}
@@ -90,7 +91,7 @@ func getEditor(app *app, w http.ResponseWriter, r *http.Request) error {
return err
}

app.templates["editor"].ExecuteTemplate(w, "editor", &EditorPage{house, html})
app.templates["editor"].ExecuteTemplate(w, "editor", &EditorPage{house, html, isHousePublic(app, house)})
return nil
}



+ 2
- 0
config.go Ver ficheiro

@@ -16,6 +16,8 @@ type config struct {
PublicKey string `env:"key=PUBLIC_KEY require=true"`

ServerPort int `env:"key=PORT default=8080"`

AutoApprove bool `env:"key=AUTO_APPROVE default=false"`
}

func newConfig() (*config, error) {


+ 102
- 1
construction.go Ver ficheiro

@@ -1,11 +1,14 @@
package htmlhouse

import (
"bytes"
"database/sql"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"time"

@@ -20,6 +23,7 @@ func createHouse(app *app, w http.ResponseWriter, r *http.Request) error {
if strings.TrimSpace(html) == "" {
return impart.HTTPError{http.StatusBadRequest, "Supply something to publish."}
}
public := r.FormValue("public") == "true"

houseID := store.GenerateFriendlyRandomString(8)

@@ -34,9 +38,82 @@ func createHouse(app *app, w http.ResponseWriter, r *http.Request) error {

resUser := newSessionInfo(houseID)

if public {
go addPublicAccess(app, r.Host, houseID, html)
}

return impart.WriteSuccess(w, resUser, http.StatusCreated)
}

func validTitle(title string) bool {
return title != "" && strings.TrimSpace(title) != "HTMLhouse"
}

func removePublicAccess(app *app, houseID string) error {
_, err := app.db.Exec("DELETE FROM publichouses WHERE house_id = ?", houseID)
if err != nil {
return err
}

return nil
}

func addPublicAccess(app *app, host, houseID, html string) error {
// Parse title of page
title := titleReg.FindStringSubmatch(html)[1]
if !validTitle(title) {
// <title/> was invalid, so look for an <h1/>
header := headerReg.FindStringSubmatch(html)[1]
if validTitle(header) {
// <h1/> was valid, so use that instead of <title/>
title = header
}
}
title = strings.TrimSpace(title)

// Get thumbnail
data := url.Values{}
data.Set("url", fmt.Sprintf("%s/%s.html", host, houseID))

u, err := url.ParseRequestURI("http://peeper.html.house")
u.Path = "/"
urlStr := fmt.Sprintf("%v", u)

client := &http.Client{}
r, err := http.NewRequest("POST", urlStr, bytes.NewBufferString(data.Encode()))
if err != nil {
fmt.Printf("Error creating request: %v", err)
}
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

var thumbURL string
resp, err := client.Do(r)
if err != nil {
fmt.Printf("Error requesting thumbnail: %v", err)
return impart.HTTPError{http.StatusInternalServerError, "Couldn't generate thumbnail"}
} else {
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
if resp.StatusCode == http.StatusOK {
thumbURL = string(body)
}
}

// Add to public houses table
approved := sql.NullInt64{Valid: false}
if app.cfg.AutoApprove {
approved.Int64 = 1
approved.Valid = true
}
_, err = app.db.Exec("INSERT INTO publichouses (house_id, title, thumb_url, added, updated, approved) VALUES (?, ?, ?, NOW(), NOW(), ?) ON DUPLICATE KEY UPDATE title = ?, updated = NOW()", houseID, title, thumbURL, approved, title)
if err != nil {
return err
}

return nil
}

func renovateHouse(app *app, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
houseID := vars["house"]
@@ -44,6 +121,7 @@ func renovateHouse(app *app, w http.ResponseWriter, r *http.Request) error {
if strings.TrimSpace(html) == "" {
return impart.HTTPError{http.StatusBadRequest, "Supply something to publish."}
}
public := r.FormValue("public") == "true"

authHouseID, err := app.session.readToken(r)
if err != nil {
@@ -65,6 +143,12 @@ func renovateHouse(app *app, w http.ResponseWriter, r *http.Request) error {

resUser := newSessionInfo(houseID)

if public {
go addPublicAccess(app, r.Host, houseID, html)
} else {
go removePublicAccess(app, houseID)
}

return impart.WriteSuccess(w, resUser, http.StatusOK)
}

@@ -97,8 +181,11 @@ func getHouseHTML(app *app, houseID string) (string, error) {
return html, nil
}

// regular expressions for extracting data
var (
htmlReg = regexp.MustCompile("<html( ?.*)>")
htmlReg = regexp.MustCompile("<html( ?.*)>")
titleReg = regexp.MustCompile("<title>(.+)</title>")
headerReg = regexp.MustCompile("<h1>(.+)</h1>")
)

func getHouse(app *app, w http.ResponseWriter, r *http.Request) error {
@@ -220,3 +307,17 @@ func getPublicHouses(app *app) (*[]PublicHouse, error) {

return &houses, nil
}

func isHousePublic(app *app, houseID string) bool {
var dummy int64
err := app.db.QueryRow("SELECT 1 FROM publichouses WHERE house_id = ?", houseID).Scan(&dummy)
switch {
case err == sql.ErrNoRows:
return false
case err != nil:
fmt.Printf("Couldn't fetch: %v\n", err)
return false
}

return true
}

+ 3
- 1
templates/editor.html Ver ficheiro

@@ -37,6 +37,7 @@
</nav>
{{if .ID}}<a href="/{{.ID}}.html">view</a>{{end}}
<a id="publish" href="#">{{if .ID}}update{{else}}publish{{end}}</a>
<input type="checkbox" name="public" id="public"{{if .Public}} checked="checked"{{end}} /><label for="public">public</label>
</header>

<pre id="editor">{{.Content}}</pre>
@@ -51,6 +52,7 @@
<script>
var publishing = false;
var $publishBtn = $("#publish");
var $publicCheck = document.getElementById("public");
{{if .ID}}{{else}}var orig = "{{.Content}}";
$publishBtn.addClass("no");{{end}}

@@ -114,7 +116,7 @@ $publishBtn.on('click', function(e) {
beforeSend: function (request) {
request.setRequestHeader("Authorization", token);
},{{end}}
data: {html: editor.getSession().getValue()},
data: {html: editor.getSession().getValue(), public: $publicCheck.checked ? "true" : ""},
success: function(data, status, xhr) {
publishing = false;
{{if .ID}}if (data.meta.code == 200) { {{else}}if (data.meta.code == 201) {


Carregando…
Cancelar
Guardar