Gen References
This commit is contained in:
parent
fd5cf554b4
commit
37bebe271e
|
@ -1 +1,61 @@
|
|||
package citing
|
||||
|
||||
import (
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"git.openprivacy.ca/sarah/kdb/fetch"
|
||||
"github.com/nickng/bibtex"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ExtractPDF(extract string) (string,string,string,*bibtex.BibEntry) {
|
||||
log.Infof("Extracting..." + extract)
|
||||
parts := strings.Split(extract,";")
|
||||
if len(parts) >= 3 {
|
||||
args := strings.Split(parts[1], ":")
|
||||
|
||||
src := strings.Join(parts[2:], ":")
|
||||
id := sha512.Sum512([]byte(src))
|
||||
fetch.Fetch(src, hex.EncodeToString(id[:]))
|
||||
cachepath := path.Join("cache/", hex.EncodeToString(id[:]))
|
||||
args = append(args, "-singlefile", "-png", cachepath, "tmp")
|
||||
subProcess := exec.Command("pdftoppm", args...)
|
||||
log.Infof("Running.. %v", subProcess.Args, subProcess.String())
|
||||
err := subProcess.Run()
|
||||
output, _ := subProcess.CombinedOutput()
|
||||
log.Infof("Success: %v %v", output, err)
|
||||
data, _ := ioutil.ReadFile("tmp.png")
|
||||
link := hex.EncodeToString([]byte(extract))
|
||||
log.Infof("Extracted; %v", link)
|
||||
bt := FindReference(src)
|
||||
title := "From " + src
|
||||
if bt != nil {
|
||||
title = bt.Fields["title"].String() + " by " + bt.Fields["author"].String() + " (" + bt.Fields["year"] .String()+ ")"
|
||||
}
|
||||
return title,link, "<img class=\"source\" id=\"" + link + "\" src=\"data:image/png;base64, " + base64.StdEncoding.EncodeToString(data) + "\"/>",bt
|
||||
}
|
||||
|
||||
return "","","",nil
|
||||
}
|
||||
|
||||
func FindReference(url string) *bibtex.BibEntry{
|
||||
file,err := os.Open("./data/references.kdb")
|
||||
if err == nil {
|
||||
bt,err := bibtex.Parse(file)
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
}
|
||||
for _,e := range bt.Entries {
|
||||
if e.Fields["url"].String() == url {
|
||||
return e
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ category: typeof:synchronization
|
|||
|
||||
There are multiple approaches to the sync, from sutble adjustments to complete resets. The very simplified model involves having each node maintain an excitement level which builds over time, and once it reaches a given threshold causes the node to flash (and reset the level). If a node is nearby a neighbour that flashes, the flash causes the node to also fire (and reset the excitement level). This slowly moves the nodes closer together over time.
|
||||
|
||||
Original simplified model proposed by Richmod in 1930
|
||||
Original simplified model proposed by Richmond in 1930
|
||||
|
||||
source: Richmond, Carl A. "Fireflies flashing in unison." Science 71.1847 (1930): 537-538. cite;-f:1;https://zero.sci-hub.se/2227/40b764e0b2b3a5c769160823430c5ca4/richmond1930.pdf
|
||||
|
||||
|
|
|
@ -1 +1,49 @@
|
|||
package fetch
|
||||
|
||||
import (
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"golang.org/x/net/proxy"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
func makeTorifiedClient() *http.Client {
|
||||
torDialer, err := proxy.SOCKS5("tcp", "127.0.0.1:9050", nil, proxy.Direct)
|
||||
if err != nil {
|
||||
//log.Fatalf("Could not connect to Tor Proxy: %v", err)
|
||||
}
|
||||
transportConfig := &http.Transport{
|
||||
Dial: torDialer.Dial,
|
||||
}
|
||||
client := new(http.Client)
|
||||
client.Transport = transportConfig
|
||||
client.CheckRedirect = func(r *http.Request, via []*http.Request) error {
|
||||
r.URL.Opaque = r.URL.Path
|
||||
return nil
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func Fetch(url string, cacheid string) []byte {
|
||||
log.Infof("Fetching..." + url)
|
||||
cachepath := path.Join("cache/", cacheid)
|
||||
if _, err := os.Stat(cachepath); !os.IsNotExist(err) {
|
||||
data,_ := ioutil.ReadFile(cachepath)
|
||||
return data
|
||||
}
|
||||
|
||||
client := makeTorifiedClient()
|
||||
resp,err:= client.Get(url)
|
||||
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
data, _ := ioutil.ReadAll(resp.Body)
|
||||
ioutil.WriteFile(cachepath, data, 0640)
|
||||
return data
|
||||
}
|
||||
log.Errorf("Error fetching: %v", err)
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
|
||||
|
|
30
kdb.go
30
kdb.go
|
@ -4,9 +4,11 @@ import (
|
|||
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.openprivacy.ca/sarah/kdb/citing"
|
||||
"github.com/nickng/bibtex"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -21,9 +23,10 @@ type Page struct {
|
|||
Body template.HTML
|
||||
BodyOrig string
|
||||
Concept template.HTML
|
||||
References map[string]*bibtex.BibEntry
|
||||
}
|
||||
|
||||
var templates = template.Must(template.ParseFiles("templates/edit.html", "templates/view.html"))
|
||||
var templates = template.Must(template.ParseFiles("templates/view.html"))
|
||||
|
||||
func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
|
||||
err := templates.ExecuteTemplate(w, tmpl+".html", p)
|
||||
|
@ -67,13 +70,24 @@ func loadPage(title string) (*Page, error) {
|
|||
concept := template.HTML(construct_graph(title))
|
||||
|
||||
linked := make(map[string]bool)
|
||||
references := make(map[string]*bibtex.BibEntry)
|
||||
for _, word := range strings.Fields(body) {
|
||||
if !linked[normalize(word)] {
|
||||
if hasPage(word) {
|
||||
body = strings.ReplaceAll(body, word, fmt.Sprintf("<a href='/view/%v/'>%v</a>", normalize(word), normalize(word)))
|
||||
}
|
||||
if strings.HasPrefix(word,"cite;") {
|
||||
log.Infof("Extracting Citation")
|
||||
cite,link,img,rec := citing.ExtractPDF(word)
|
||||
if rec != nil {
|
||||
if references[rec.CiteName] == nil {
|
||||
references[rec.CiteName] = rec
|
||||
}
|
||||
}
|
||||
body = strings.ReplaceAll(body, word, fmt.Sprintf("<a title=\"%v\" href=\"javascript:showsource('%v')\">[X]</a>%v",cite,link,img))
|
||||
}
|
||||
if strings.HasPrefix(word, "http") {
|
||||
body = strings.ReplaceAll(body, word, fmt.Sprintf("<a href='%v'>%v</a>", word, word))
|
||||
body = strings.ReplaceAll(body, word, fmt.Sprintf("<a onmouseover=\"javascript:showsource('%v')\" href='%v'></a>", word, word, word))
|
||||
}
|
||||
if strings.HasPrefix(word, "data:image/png;base64,") {
|
||||
body = strings.ReplaceAll(body, word, fmt.Sprintf("<img width=75%% height=75%% src='%v'/>", word))
|
||||
|
@ -82,7 +96,7 @@ func loadPage(title string) (*Page, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return &Page{Title: title, Body: template.HTML(body), BodyOrig: string(bodyb), Concept: concept}, nil
|
||||
return &Page{Title: title, Body: template.HTML(body), BodyOrig: string(bodyb), Concept: concept, References:references}, nil
|
||||
}
|
||||
|
||||
func normalize(word string) string {
|
||||
|
@ -157,10 +171,9 @@ func construct_graph(word string) string {
|
|||
}
|
||||
|
||||
func construct_graph_sub(graph string, word string, seen map[string]bool, depth int) string {
|
||||
if depth >= 0 {
|
||||
} else {
|
||||
|
||||
if depth < 0 {
|
||||
return graph
|
||||
//4b3557
|
||||
}
|
||||
links := get_links(normalize(word))
|
||||
if !seen[normalize(word)] {
|
||||
|
@ -237,8 +250,9 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func main() {
|
||||
log.SetLevel(log.LevelInfo)
|
||||
http.HandleFunc("/", indexHandler)
|
||||
http.HandleFunc("/view/", viewHandler)
|
||||
http.HandleFunc("/save/", saveHandler)
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
log.Errorln(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>{{.Title}} - SigilKDB</title>
|
||||
<style>
|
||||
body {
|
||||
width:75%;
|
||||
margin:100px auto;
|
||||
font-family: Chilanka;
|
||||
overflow: visible;
|
||||
|
||||
}
|
||||
textarea
|
||||
{
|
||||
|
@ -13,21 +14,58 @@
|
|||
}
|
||||
|
||||
.conceptgraph {
|
||||
float:right;
|
||||
float:right;
|
||||
}
|
||||
|
||||
.sourceframe {
|
||||
position:absolute;
|
||||
bottom:0px;
|
||||
right:0px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.source {
|
||||
width:40%;
|
||||
display:none;
|
||||
}
|
||||
|
||||
</style>
|
||||
<script>
|
||||
function showsource(x) {
|
||||
if (document.getElementById(x).style.display != "block") {
|
||||
document.getElementById(x).style.display = "block"
|
||||
} else {
|
||||
document.getElementById(x).style.display = "none"
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{.Title}}</h1>
|
||||
<div class=".conceptgraph">{{.Concept}}</div>
|
||||
<div style="white-space:pre-line" >{{.Body}}</div>
|
||||
<br/><br/><br/><br/>
|
||||
<hr/>
|
||||
<h1>Editing {{.Title}}</h1>
|
||||
<div style="white-space:pre-line" >{{.Body}}
|
||||
|
||||
{{ $length := len .References }}
|
||||
{{ if gt $length 0 }}
|
||||
<h3> References </h3>
|
||||
{{ range $key, $value := .References }}
|
||||
<li><strong><a href="{{index $value.Fields "url"}}">{{ $key }}</a></strong>: {{index $value.Fields "author"}} {{index $value.Fields "title"}} {{index $value.Fields "year"}}</li>
|
||||
{{ end }}
|
||||
{{end}}
|
||||
|
||||
<br/><br/><br/><br/>
|
||||
<hr/>
|
||||
<h1>Editing {{.Title}}</h1>
|
||||
|
||||
<form style="width:100%;" action="/save/{{.Title}}" method="POST">
|
||||
<div ><textarea name="body" rows="20" cols="80">{{printf "%s" .BodyOrig}}</textarea></div>
|
||||
<div><input type="submit" value="Save"></div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<form style="width:100%;" action="/save/{{.Title}}" method="POST">
|
||||
<div ><textarea name="body" rows="20" cols="80">{{printf "%s" .BodyOrig}}</textarea></div>
|
||||
<div><input type="submit" value="Save"></div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue