aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client.go52
-rw-r--r--database.go66
-rw-r--r--databaseschema.psql8
-rw-r--r--main.go26
-rw-r--r--static/index.html40
-rw-r--r--static/nadmin.html8
-rw-r--r--static/news.html32
7 files changed, 219 insertions, 13 deletions
diff --git a/client.go b/client.go
index 6e185cc..be79cdd 100644
--- a/client.go
+++ b/client.go
@@ -8,6 +8,7 @@ import "strings"
import "strconv"
import "sort"
import "regexp"
+import "time"
var Key *string = new(string)
@@ -35,8 +36,7 @@ type Board struct{
type PageData struct {
Title string
- Message string
- MessageHTML template.HTML
+ PreferredUsername string
Board Board
Pages []int
CurrentPage int
@@ -48,6 +48,8 @@ type PageData struct {
Instance Actor
InstanceIndex []ObjectBase
ReturnTo string
+ NewsItems []NewsItem
+ BoardRemainer []int
}
type AdminPage struct {
@@ -74,15 +76,22 @@ type Removed struct {
Board string
}
+
+type NewsItem struct {
+ Title string
+ Content string
+ Time int
+}
+
func IndexGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
- t := template.Must(template.ParseFiles("./static/main.html", "./static/index.html"))
+ t := template.Must(template.New("").Funcs(template.FuncMap{"mod": func(i, j int) bool { return i%j == 0 }, "unixtoreadable": func(u int) string { return time.Unix(int64(u), 0).Format("Jan 02, 2006") }}).ParseFiles("./static/main.html", "./static/index.html"))
actor := GetActorFromDB(db, Domain)
var data PageData
data.Title = "Welcome to " + actor.PreferredUsername
- data.Message = actor.PreferredUsername + " is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code here https://github.com/FChannel0"
- data.MessageHTML = template.HTML(actor.PreferredUsername + " is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code here <a href='https://github.com/FChannel0'>https://github.com/FChannel0</a>")
+
+ data.PreferredUsername = actor.PreferredUsername
data.Boards = Boards
data.Board.Name = ""
data.Key = *Key
@@ -91,11 +100,42 @@ func IndexGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
data.Board.Actor = actor
data.Board.Post.Actor = actor.Id
data.Board.Restricted = actor.Restricted
+ data.BoardRemainer = make([]int, (len(data.Boards) % 3)+1)
data.InstanceIndex = GetCollectionFromReq("https://fchan.xyz/followers").Items
+ data.NewsItems = getNewsFromDB(db)
+ t.ExecuteTemplate(w, "layout", data)
+}
+func NewsGet(w http.ResponseWriter, r *http.Request, db *sql.DB, timestamp int) {
+ t := template.Must(template.New("").Funcs(template.FuncMap{"unixtoreadable": func(u int) string { return time.Unix(int64(u), 0).Format("Jan 02, 2006") }}).ParseFiles("./static/main.html", "./static/news.html"))
+
+ actor := GetActorFromDB(db, Domain)
+
+ var data PageData
+ data.PreferredUsername = actor.PreferredUsername
+ data.Boards = Boards
+ data.Board.Name = ""
+ data.Key = *Key
+ data.Board.Domain = Domain
+ data.Board.ModCred, _ = GetPasswordFromSession(r)
+ data.Board.Actor = actor
+ data.Board.Post.Actor = actor.Id
+ data.Board.Restricted = actor.Restricted
+ data.NewsItems = []NewsItem{NewsItem{}}
+
+ var err error
+ data.NewsItems[0], err = getNewsItemFromDB(db, timestamp)
- t.ExecuteTemplate(w, "layout", data)
+ if err != nil {
+ w.WriteHeader(http.StatusForbidden)
+ w.Write([]byte("404 no path"))
+ return
+ }
+
+ data.Title = actor.PreferredUsername + ": " + data.NewsItems[0].Title
+
+ t.ExecuteTemplate(w, "layout", data)
}
func OutboxGet(w http.ResponseWriter, r *http.Request, db *sql.DB, collection Collection){
diff --git a/database.go b/database.go
index 9d5d721..037fde2 100644
--- a/database.go
+++ b/database.go
@@ -7,11 +7,12 @@ import "time"
import "os"
import "strings"
import "sort"
+import "container/list"
func GetActorFromDB(db *sql.DB, id string) Actor {
- var nActor Actor
+ var nActor Actor
- query :=`select type, id, name, preferedusername, inbox, outbox, following, followers, restricted, summary, publickeypem from actor where id=$1`
+ query :=`select type, id, name, preferedusername, inbox, outbox, following, followers, restricted, summary, publickeypem from actor where id=$1`
rows, err := db.Query(query, id)
@@ -1488,3 +1489,64 @@ func MarkObjectSensitive(db *sql.DB, id string, sensitive bool) {
CheckError(err, "error updating sensitive object in cacheactivitystream")
}
+
+func getNewsFromDB(db *sql.DB) []NewsItem {
+ news := list.New()
+ query :=`select title, content, time from newsItem order by time desc`
+
+ rows, err := db.Query(query)
+
+ if CheckError(err, "could not get news from db query") != nil {
+ return make([]NewsItem, 0)
+ }
+
+ defer rows.Close()
+ for rows.Next() {
+ n := NewsItem{}
+ err = rows.Scan(&n.Title, &n.Content, &n.Time)
+ if CheckError(err, "error scanning news from db") != nil {
+ return make([]NewsItem, 0)
+ }
+ news.PushBack(n)
+ }
+
+ anews := make([]NewsItem, news.Len())
+
+ i:=0
+ for e := news.Front(); e != nil; e = e.Next() {
+ assert := e.Value.(NewsItem)
+ anews[i] = assert
+ i++
+ }
+
+ return anews
+}
+
+func getNewsItemFromDB(db *sql.DB, timestamp int) (NewsItem, error) {
+ var news NewsItem
+ query := `select title, content, time from newsItem where time=$1 limit 1`
+
+ rows, err := db.Query(query, timestamp)
+
+ if err != nil {
+ return news, err
+ }
+
+ defer rows.Close()
+ rows.Next()
+ err = rows.Scan(&news.Title, &news.Content, &news.Time)
+
+ if err != nil {
+ return news, err
+ }
+
+ return news, nil
+}
+
+func WriteNewsToDB(db *sql.DB, news NewsItem) {
+ query := `insert into newsItem (title, content, time) values ($1, $2, $3)`
+
+ _, err := db.Exec(query, news.Title, news.Content, time.Now().Unix())
+
+ CheckError(err, "error writing news item")
+}
diff --git a/databaseschema.psql b/databaseschema.psql
index e12813e..43767f3 100644
--- a/databaseschema.psql
+++ b/databaseschema.psql
@@ -216,7 +216,13 @@ owner varchar(100),
file varchar(100)
);
+CREATE TABLE IF NOT EXISTS newsItem(
+title text,
+content text,
+time bigint
+);
+
ALTER TABLE actor ADD COLUMN IF NOT EXISTS publicKeyPem varchar(100) default '';
ALTER TABLE activitystream ADD COLUMN IF NOT EXISTS sensitive boolean default false;
-ALTER TABLE cacheactivitystream ADD COLUMN IF NOT EXISTS sensitive boolean default false; \ No newline at end of file
+ALTER TABLE cacheactivitystream ADD COLUMN IF NOT EXISTS sensitive boolean default false;
diff --git a/main.go b/main.go
index 2874396..69e8902 100644
--- a/main.go
+++ b/main.go
@@ -290,6 +290,21 @@ func main() {
w.WriteHeader(http.StatusForbidden)
w.Write([]byte("404 no path"))
})
+
+ http.HandleFunc("/news/", func(w http.ResponseWriter, r *http.Request){
+ timestamp := r.URL.Path[6:]
+ if timestamp[len(timestamp)-1:] == "/" {
+ timestamp = timestamp[:len(timestamp)-1]
+ }
+
+ ts, err := strconv.Atoi(timestamp)
+ if err != nil {
+ w.WriteHeader(http.StatusForbidden)
+ w.Write([]byte("404 no path"))
+ } else {
+ NewsGet(w, r, db, ts)
+ }
+ })
http.HandleFunc("/post", func(w http.ResponseWriter, r *http.Request){
@@ -602,6 +617,17 @@ func main() {
MakeActivityRequestOutbox(db, newActorActivity)
http.Redirect(w, r, "/" + *Key, http.StatusSeeOther)
})
+
+ http.HandleFunc("/" + *Key + "/postnews", func(w http.ResponseWriter, r *http.Request) {
+ var newsitem NewsItem
+
+ newsitem.Title = r.FormValue("title")
+ newsitem.Content = r.FormValue("summary")
+
+ WriteNewsToDB(db, newsitem)
+
+ http.Redirect(w, r, "/", http.StatusSeeOther)
+ })
http.HandleFunc("/verify", func(w http.ResponseWriter, r *http.Request){
if(r.Method == "POST") {
diff --git a/static/index.html b/static/index.html
index ab0bea0..518c012 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1,6 +1,6 @@
{{ define "header" }}
<title>{{ .Title }}</title>
-<meta name="description" content="{{ .Message }}">
+<meta name="description" content="{{ .PreferredUsername }} is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code here: https://github.com/FChannel0.">
<meta property="og:locale" content="en_US" />
<meta property="og:type" content="website" />
@@ -8,10 +8,10 @@
<meta property="og:site_name" content="{{ .Board.Actor.PreferredUsername }}" />
<meta property="og:title" content="{{ .Title }}">
-<meta property="og:description" content="{{ .Message }}">
+<meta property="og:description" content="{{ .PreferredUsername }} is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code here: https://github.com/FChannel0.">
<meta name="twitter:title" content="{{ .Title }}">
-<meta name="twitter:description" content="{{ .Message }}">
+<meta name="twitter:description" content="{{ .PreferredUsername }} is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code here: https://github.com/FChannel0.">
<meta name="twitter:card" content="summary_large_image">
{{ end }}
@@ -20,7 +20,39 @@
{{ define "content" }}
<div style="text-align: center; max-width: 800px; margin: 0 auto;">
<h1>{{ .Title }}</h1>
- <p style="text-align: justify">{{.MessageHTML}}</p>
+ <p style="text-align: justify">{{ .PreferredUsername }} is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code <a href="https://github.com/FChannel0">here</a>.</p>
+
+ <div style="margin-top:50px;">
+
+ <div style="display: grid;border-right: 2px solid #820404">
+ <div style="display: inline-grid;grid-column: 1 / 4;border-bottom: 2px solid #820404;border-left: 2px solid #820404;border-top: 2px solid #820404;"><span style="font-size: 1.5em;font-weight: bold;">Local boards</span></div>
+ {{ range .Boards }}
+ <div style="whitespace: nowrap;display: inline-grid;text-align: left;padding: 5px;border-bottom: 2px solid #820404;border-left: 2px solid #820404;"><a href="{{.Location}}">{{.Name}} - {{.PrefName}}</a></div>
+ {{ end }}
+ {{ range .BoardRemainer }}
+ <div style="whitespace: nowrap;display: inline-grid;text-align: left;padding: 5px;border-bottom: 2px solid #820404;border-left: 2px solid #820404;"></div>
+ {{ end }}
+ </div>
+
+ </div>
+
+ <div style="margin-top:50px;">
+ <table align="center" style="text-align: left;">
+ <th>
+ <tr>{{ .PreferredUsername }} news</tr>
+ </th>
+
+ {{ range $i, $e := .NewsItems }}
+ <tr>
+ <td><a href="/news/{{.Time}}">{{unixtoreadable $e.Time}} - {{$e.Title}}</a>
+ {{ if eq $i 0 }}
+ <br><p>{{$e.Content}}</p>
+ {{ end }}
+ </td>
+ </tr>
+ {{ end }}
+ </table>
+ </div>
<div style="margin-top:50px;">
<table align="center" style="text-align: left;">
diff --git a/static/nadmin.html b/static/nadmin.html
index 984eb76..877e1e5 100644
--- a/static/nadmin.html
+++ b/static/nadmin.html
@@ -17,6 +17,14 @@
<option value="False">False</option>
</select>
</form>
+
+ <h3>Post News</h3>
+ <form id="news" action="/{{ .Key }}/postnews" method="post" enctype="application/x-www-form-urlencoded">
+ <label>Title:</label><br>
+ <input type="text" name="title" placeholder="{{.Actor}} was created!" required><input type="submit" value="Post"><br>
+ <label>Content:</label><br>
+ <textarea name="summary" rows="8" cols="50"></textarea><br>
+ </form>
<ul style="display: inline-block; padding: 0;">
<li style="display: inline-block;"><a href="#following">Subscribed</a></li>
diff --git a/static/news.html b/static/news.html
new file mode 100644
index 0000000..757c420
--- /dev/null
+++ b/static/news.html
@@ -0,0 +1,32 @@
+{{ define "header" }}
+<title>{{ .Title }}</title>
+<meta name="description" content="{{ .PreferredUsername }} is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code here: https://github.com/FChannel0.">
+
+<meta property="og:locale" content="en_US" />
+<meta property="og:type" content="website" />
+<meta property="og:url" content="{{ .Board.Domain }}">
+<meta property="og:site_name" content="{{ .Board.Actor.PreferredUsername }}" />
+
+<meta property="og:title" content="{{ .Title }}">
+<meta property="og:description" content="{{ .PreferredUsername }} is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code here: https://github.com/FChannel0.">
+
+<meta name="twitter:title" content="{{ .Title }}">
+<meta name="twitter:description" content="{{ .PreferredUsername }} is a federated image board based on activitypub. The current version of the code running the server is still a work in progress, expect a bumpy ride for the time being. Get the server code here: https://github.com/FChannel0.">
+<meta name="twitter:card" content="summary_large_image">
+
+{{ end }}
+
+{{ define "top" }}{{ end }}
+{{ define "content" }}
+<div style="text-align: left; max-width: 800px; margin: 0 auto;">
+
+ {{ range .NewsItems }}
+ <p><h1>{{unixtoreadable .Time}} - {{.Title}}</h1><br>{{.Content}}</p>
+ {{ end }}
+
+</div>
+{{ end }}
+{{ define "bottom" }}{{ end }}
+
+{{ define "script" }}
+{{ end }}