From 4e3848cadbb3fd89b94a7ef24838173939d198db Mon Sep 17 00:00:00 2001
From: knotteye <knotteye@airmail.cc>
Date: Thu, 1 Jul 2021 17:56:04 -0500
Subject: Add a list of local boards and server news

---
 client.go           | 13 +++++++++++--
 database.go         | 42 ++++++++++++++++++++++++++++++++++++++++--
 databaseschema.psql |  8 +++++++-
 main.go             | 11 +++++++++++
 static/index.html   | 28 ++++++++++++++++++++++++++++
 static/nadmin.html  |  8 ++++++++
 6 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/client.go b/client.go
index dd40f3d..fcb496b 100644
--- a/client.go
+++ b/client.go
@@ -47,6 +47,7 @@ type PageData struct {
 	Instance Actor
 	InstanceIndex []ObjectBase
 	ReturnTo string
+	NewsItems []NewsItem
 }
 
 type AdminPage struct {
@@ -73,8 +74,15 @@ 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 }}).ParseFiles("./static/main.html", "./static/index.html"))
 
 	actor := GetActorFromDB(db, Domain)
 
@@ -90,8 +98,9 @@ func IndexGet(w http.ResponseWriter, r *http.Request, db *sql.DB) {
 	data.Board.Post.Actor = actor.Id
 	data.Board.Restricted = actor.Restricted
 	data.InstanceIndex = GetCollectionFromReq("https://fchan.xyz/followers").Items
+	data.NewsItems = getNewsFromDB(db)
 
-	t.ExecuteTemplate(w, "layout",  data)	
+	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..5fcebf0 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,40 @@ 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)
+		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 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 972e69e..037f240 100644
--- a/main.go
+++ b/main.go
@@ -598,6 +598,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 19c5da2..de06c6c 100644
--- a/static/index.html
+++ b/static/index.html
@@ -22,6 +22,34 @@
   <h1>{{ .Title }}</h1>
   <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;">
+  <table align="center" style="text-align: left;">
+    <th>
+      <tr>Local boards</tr>
+    </th>
+
+    {{ range .Boards }}
+    <tr>
+      <td><a href="{{.Location}}">{{.Name}} - {{.PrefName}}</a></td>
+    </tr>
+    {{ end }}
+  </table>
+  </div>
+  
+  <div style="margin-top:50px;">
+  <table align="center" style="text-align: left;">
+    <th>
+      <tr>{{ .PreferredUsername }} news</tr>
+    </th>
+
+    {{ range .NewsItems }}
+    <tr>
+      <td><p><em><b>{{.Time}} - {{.Title}}</b></em><br>{{.Content}}</p></td>
+    </tr>
+    {{ end }}
+  </table>
+  </div>
+  
   <div style="margin-top:50px;">
   <table align="center" style="text-align: left;">
     <th>
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>
-- 
cgit v1.2.3