switched tabs for spaces
This commit is contained in:
parent
1713893f02
commit
cdf89ace54
420
main.go
420
main.go
|
@ -1,257 +1,257 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"flag"
|
||||
"strings"
|
||||
"net/http"
|
||||
"io/ioutil"
|
||||
"html/template"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"fmt"
|
||||
"flag"
|
||||
"strings"
|
||||
"net/http"
|
||||
"io/ioutil"
|
||||
"html/template"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type Options struct {
|
||||
Port int
|
||||
Address string
|
||||
ArchivePath string
|
||||
Port int
|
||||
Address string
|
||||
ArchivePath string
|
||||
}
|
||||
|
||||
type PostsCache struct {
|
||||
Text string
|
||||
Indexes [][2]int
|
||||
Archive []interface{}
|
||||
Text string
|
||||
Indexes [][2]int
|
||||
Archive []interface{}
|
||||
}
|
||||
|
||||
type PostSummary struct {
|
||||
URL string
|
||||
Content string
|
||||
Datetime string
|
||||
URL string
|
||||
Content string
|
||||
Datetime string
|
||||
}
|
||||
|
||||
type Context struct {
|
||||
Name string
|
||||
Prompt string
|
||||
Posts []*PostSummary
|
||||
Count int
|
||||
Name string
|
||||
Prompt string
|
||||
Posts []*PostSummary
|
||||
Count int
|
||||
}
|
||||
|
||||
const APP_NAME = "manfred"
|
||||
const APP_NAME = "manfred"
|
||||
const BASE_TEMPLATE = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
width: 70%;
|
||||
margin: auto;
|
||||
}
|
||||
.prompt {
|
||||
width: 100%
|
||||
}
|
||||
.prompt h1 {
|
||||
text-align: center;
|
||||
}
|
||||
.result {
|
||||
text-align: justify;
|
||||
margin-top: 2em;
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
<meta charset="utf-8">
|
||||
<title>{{ .Name }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top">
|
||||
<div class="title">
|
||||
<h1>{{ .Name }} </h1>
|
||||
</div>
|
||||
</div>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
width: 70%;
|
||||
margin: auto;
|
||||
}
|
||||
.prompt {
|
||||
width: 100%
|
||||
}
|
||||
.prompt h1 {
|
||||
text-align: center;
|
||||
}
|
||||
.result {
|
||||
text-align: justify;
|
||||
margin-top: 2em;
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
<meta charset="utf-8">
|
||||
<title>{{ .Name }}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="top">
|
||||
<div class="title">
|
||||
<h1>{{ .Name }} </h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="prompt">
|
||||
<form action="/" method="post">
|
||||
<input type="text" placeholder="Plaintext.." name="prompt">
|
||||
<button type="submit">Search</button>
|
||||
</form>
|
||||
<p>Showing {{ .Count }} result(s) for "{{ .Prompt }}"</p>
|
||||
</div>
|
||||
<div class="prompt">
|
||||
<form action="/" method="post">
|
||||
<input type="text" placeholder="Plaintext.." name="prompt">
|
||||
<button type="submit">Search</button>
|
||||
</form>
|
||||
<p>Showing {{ .Count }} result(s) for "{{ .Prompt }}"</p>
|
||||
</div>
|
||||
|
||||
<div class="results">
|
||||
{{ range $p := .Posts }}
|
||||
<div class="result">
|
||||
<a href="{{ $p.URL }}">{{ $p.URL }}</a>
|
||||
<p>{{ $p.Datetime }}</p>
|
||||
{{ $p.Content }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</body>
|
||||
<div class="results">
|
||||
{{ range $p := .Posts }}
|
||||
<div class="result">
|
||||
<a href="{{ $p.URL }}">{{ $p.URL }}</a>
|
||||
<p>{{ $p.Datetime }}</p>
|
||||
{{ $p.Content }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
var cache *PostsCache = &PostsCache{}
|
||||
var options Options = Options{}
|
||||
var indexTemplate *template.Template = nil
|
||||
var cache *PostsCache = &PostsCache{}
|
||||
var options Options = Options{}
|
||||
var indexTemplate *template.Template = nil
|
||||
|
||||
func (c *PostsCache) LoadArchiveCache(path string) error {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
b, _ := ioutil.ReadAll(f)
|
||||
|
||||
a := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fi := a["orderedItems"].([]interface{})
|
||||
for _, e := range fi {
|
||||
ei, ok := e.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
eo, ok := ei["object"].(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
s, ok := eo["content"].(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
c.Archive = append(c.Archive, e)
|
||||
|
||||
tl := len(c.Text)
|
||||
|
||||
c.Indexes = append(c.Indexes, [2]int{tl, tl+ len(s)})
|
||||
c.Text += s
|
||||
}
|
||||
|
||||
return nil
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
b, _ := ioutil.ReadAll(f)
|
||||
|
||||
a := make(map[string]interface{})
|
||||
err = json.Unmarshal(b, &a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fi := a["orderedItems"].([]interface{})
|
||||
for _, e := range fi {
|
||||
ei, ok := e.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
eo, ok := ei["object"].(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
s, ok := eo["content"].(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
c.Archive = append(c.Archive, e)
|
||||
|
||||
tl := len(c.Text)
|
||||
|
||||
c.Indexes = append(c.Indexes, [2]int{tl, tl+ len(s)})
|
||||
c.Text += s
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *PostsCache) FindPostFromIndex(index int) int {
|
||||
a, b, m := 0, 0, 0
|
||||
a, b, m := 0, 0, 0
|
||||
|
||||
b = len(c.Indexes)-1
|
||||
for a <= b {
|
||||
m = a + (b - a)/2;
|
||||
if c.Indexes[m][0] <= index && index <= c.Indexes[m][1]{
|
||||
return m
|
||||
}
|
||||
|
||||
if c.Indexes[m][0] < index {
|
||||
a = m + 1
|
||||
} else {
|
||||
b = m - 1
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
b = len(c.Indexes)-1
|
||||
for a <= b {
|
||||
m = a + (b - a)/2;
|
||||
if c.Indexes[m][0] <= index && index <= c.Indexes[m][1]{
|
||||
return m
|
||||
}
|
||||
|
||||
if c.Indexes[m][0] < index {
|
||||
a = m + 1
|
||||
} else {
|
||||
b = m - 1
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
func (c *PostsCache) FindPosts(kw string) []int {
|
||||
r := []int{}
|
||||
|
||||
i, a, l := 0, 0, len(c.Text)
|
||||
for a < l {
|
||||
i = strings.Index(c.Text[a:], kw)
|
||||
if i < 0 {
|
||||
break;
|
||||
}
|
||||
a += i +1
|
||||
|
||||
p := c.FindPostFromIndex(a-1)
|
||||
if p < 0 {
|
||||
break
|
||||
}
|
||||
|
||||
fnd := false
|
||||
for _, ri := range r {
|
||||
if ri == p {
|
||||
fnd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if fnd {
|
||||
continue
|
||||
}
|
||||
r = append(r, p)
|
||||
}
|
||||
|
||||
return r
|
||||
r := []int{}
|
||||
|
||||
i, a, l := 0, 0, len(c.Text)
|
||||
for a < l {
|
||||
i = strings.Index(c.Text[a:], kw)
|
||||
if i < 0 {
|
||||
break;
|
||||
}
|
||||
a += i +1
|
||||
|
||||
p := c.FindPostFromIndex(a-1)
|
||||
if p < 0 {
|
||||
break
|
||||
}
|
||||
|
||||
fnd := false
|
||||
for _, ri := range r {
|
||||
if ri == p {
|
||||
fnd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if fnd {
|
||||
continue
|
||||
}
|
||||
r = append(r, p)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (c *PostsCache) GetPostSummary(p int) *PostSummary {
|
||||
ps := new(PostSummary)
|
||||
|
||||
if p < 0 || p >= len(c.Indexes) {
|
||||
return nil
|
||||
}
|
||||
|
||||
a := c.Archive[p].(map[string]interface{})
|
||||
obj := a["object"].(map[string]interface{})
|
||||
|
||||
ps.URL = obj["id"].(string)
|
||||
ps.Content = obj["content"].(string)
|
||||
ps.Datetime = a["published"].(string)
|
||||
|
||||
return ps
|
||||
ps := new(PostSummary)
|
||||
|
||||
if p < 0 || p >= len(c.Indexes) {
|
||||
return nil
|
||||
}
|
||||
|
||||
a := c.Archive[p].(map[string]interface{})
|
||||
obj := a["object"].(map[string]interface{})
|
||||
|
||||
ps.URL = obj["id"].(string)
|
||||
ps.Content = obj["content"].(string)
|
||||
ps.Datetime = a["published"].(string)
|
||||
|
||||
return ps
|
||||
}
|
||||
|
||||
func Index(w http.ResponseWriter, r * http.Request) {
|
||||
ctx := &Context{
|
||||
Name : APP_NAME,
|
||||
}
|
||||
ctx := &Context{
|
||||
Name : APP_NAME,
|
||||
}
|
||||
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
|
||||
ctx.Prompt = r.FormValue("prompt")
|
||||
px := cache.FindPosts(ctx.Prompt)
|
||||
for _, p := range px {
|
||||
ps := cache.GetPostSummary(p)
|
||||
if ps == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ctx.Posts = append(ctx.Posts, ps)
|
||||
}
|
||||
|
||||
ctx.Count = len(ctx.Posts)
|
||||
}
|
||||
|
||||
indexTemplate.Execute(w, ctx)
|
||||
if r.Method == "POST" {
|
||||
r.ParseForm()
|
||||
|
||||
ctx.Prompt = r.FormValue("prompt")
|
||||
px := cache.FindPosts(ctx.Prompt)
|
||||
for _, p := range px {
|
||||
ps := cache.GetPostSummary(p)
|
||||
if ps == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ctx.Posts = append(ctx.Posts, ps)
|
||||
}
|
||||
|
||||
ctx.Count = len(ctx.Posts)
|
||||
}
|
||||
|
||||
indexTemplate.Execute(w, ctx)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&options.Address, "a", "127.0.0.1", "Address the web server will be listening for")
|
||||
flag.StringVar(&options.ArchivePath, "o", "./outbox.json", "Path to outbox.json")
|
||||
flag.IntVar(&options.Port, "p", 8123, "Port the web server will be listening in")
|
||||
flag.StringVar(&options.Address, "a", "127.0.0.1", "Address the web server will be listening for")
|
||||
flag.StringVar(&options.ArchivePath, "o", "./outbox.json", "Path to outbox.json")
|
||||
flag.IntVar(&options.Port, "p", 8123, "Port the web server will be listening in")
|
||||
|
||||
flag.Parse()
|
||||
flag.Parse()
|
||||
|
||||
err := cache.LoadArchiveCache(options.ArchivePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cache.GetPostSummary(0)
|
||||
|
||||
indexTemplate, err = template.New("index").Parse(BASE_TEMPLATE)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
http.HandleFunc("/", Index)
|
||||
|
||||
uri := fmt.Sprintf("%s:%d", options.Address, options.Port)
|
||||
fmt.Println("listening to http://" + uri)
|
||||
panic(http.ListenAndServe(uri, nil))
|
||||
err := cache.LoadArchiveCache(options.ArchivePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cache.GetPostSummary(0)
|
||||
|
||||
indexTemplate, err = template.New("index").Parse(BASE_TEMPLATE)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
http.HandleFunc("/", Index)
|
||||
|
||||
uri := fmt.Sprintf("%s:%d", options.Address, options.Port)
|
||||
fmt.Println("listening to http://" + uri)
|
||||
panic(http.ListenAndServe(uri, nil))
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue