~aw/fishbb

e4509dbfc7e7efdf2923699fd6a09558c7864141 — alex wennerberg 2 months ago 9eefc6e
very rudimentary search
9 files changed, 58 insertions(+), 13 deletions(-)

M TODO
M db.go
M post.go
M schema.sql
M views/search.html
A views/shortpost.html
M views/style.css
M views/thread.html
M web.go
M TODO => TODO +5 -7
@@ 7,13 7,6 @@ better error handling on login
better ux for account creation
move lock to right place
links on home and thread list should go to the post

NOTIFICATIONS:
- @mentions
- auto-hyperlink @mention maybe?

"shortpsot" list -> use summary code

Login/Reigster:
add a reply button that uses @mentions
finish up oauth integration


@@ 23,6 16,11 @@ Search
----- alpha waterline ----- (may push lower to get something more complete out)

# DEFINITELY
NOTIFICATIONS:
- @mentions
- auto-hyperlink @mention maybe?

"shortpsot" list -> use summary code
block renaming of form
IP blocking / other antispam
split out config management for admins

M db.go => db.go +6 -1
@@ 10,7 10,7 @@ import (
	_ "github.com/mattn/go-sqlite3"
)

var stmtGetForumID, stmtUpdateMe,
var stmtGetForumID, stmtUpdateMe, stmtSearchPosts,
	stmtEditPost, stmtGetPost, stmtGetPostSlug, stmtGetForum,
	stmtGetForumBySlug, stmtCreateUser, stmtGetForums, stmtUpdateForum,
	stmtGetUser, stmtGetUsers, stmtGetPostAuthorID, stmtDeletePost,


@@ 163,6 163,11 @@ func prepareStatements(db *sql.DB) {
		from posts 
		join users on posts.authorid = users.id 
		where threadid = ? limit ? offset ?`)
	stmtSearchPosts = prepare(db, `
	select posts.id, content, users.id, users.username, posts.created, posts.edited 
	from posts 
	join users on posts.authorid = users.id 
	where content like ?`)
	stmtGetPost = prepare(db, `
		select posts.id, content, users.id, users.username, posts.created, posts.edited 
		from posts 

M post.go => post.go +20 -1
@@ 33,7 33,7 @@ const previewLength = 10
func (p Post) Preview() string {
	text := html2text.HTML2Text(p.Content)
	if len(text) > previewLength-3 {
		return text[:previewLength] + "..."
		return text[:previewLength-3] + "..."
	}
	return text
}


@@ 68,6 68,25 @@ func getPostSlug(postid int) (string, error) {
	return url, nil
}

// TODO maybe consolidate with query builder
func searchPosts(q string) ([]Post, error) {
	var posts []Post
	rows, err := stmtSearchPosts.Query("%" + q + "%")
	if err != nil {
		return nil, err
	}
	for rows.Next() {
		var p Post
		err := rows.Scan(&p.ID, &p.Content, &p.Author.ID, &p.Author.Username, &p.Created, &p.Edited)
		fmt.Println(p)
		if err != nil {
			return nil, err
		}
		posts = append(posts, p)
	}
	return posts, nil
}

// page is 1-indexed
func getPosts(threadid, page int) []Post {
	var posts []Post

M schema.sql => schema.sql +5 -1
@@ 62,7 62,11 @@ create index idxposts_threadid on posts(threadid);

-- create table invitations ( );
-- create table reports
-- create table notifications
create table notifications (
  type text not null,
  message text, -- markdown
  created datetime default current_timestamp,
);

pragma journal_mode = wal;
pragma busy_timeout = 5000;

M views/search.html => views/search.html +5 -1
@@ 1,8 1,12 @@
{{ template "header.html" . }}
<div class="div-header">Posts that match "{{.Query}}"</div>
<div class="body-padded">
Search feature coming soon!
{{ range .Posts }}
<div class="shortpost">
	<img style="vertical-align:middle" src="/a?a={{.Author.Username}}" width=18>
	<a href="/user/{{.Author.ID}}">{{.Author.Username}}</a> <a href="#{{.ID}}" title="Link to this post">#</a> 
	{{ .Preview }}
</div>
{{ end }}
</div>
{{ template "footer.html" . }}

A views/shortpost.html => views/shortpost.html +1 -0
@@ 0,0 1,1 @@


M views/style.css => views/style.css +5 -0
@@ 269,3 269,8 @@ h1, h2, h3, h4, h5, h6 {
  text-overflow: ellipsis;
  vertical-align: top;
}

.shortpost {
  border-bottom: 1px solid var(--border);
  padding: 0.3rem;
}

M views/thread.html => views/thread.html +3 -1
@@ 15,7 15,9 @@
  <div class="post-meta">
	  <div>
  <img  style="vertical-align:middle" src="/a?a={{.Author.Username}}" width=18>
  <a href="/user/{{.Author.ID}}">{{.Author.Username}}</a> <a href="#{{.ID}}" title="Link to this post">#</a> <span class="text-alt" title="{{ .Created }}">{{ timeago .Created}}
	  <a href="/user/{{.Author.ID}}">{{.Author.Username}}</a> <a href="#{{.ID}}"
	  title="Link to this post">#</a> <span class="text-alt" title="{{ .Created
	  }}">{{ timeago .Created}}
	  {{ if .Edited }}<em>(edited {{timeago .Edited}})</em>{{end}}
</span>
	  </div>

M web.go => web.go +8 -1
@@ 482,7 482,14 @@ func doChangePassword(w http.ResponseWriter, r *http.Request) {

func searchPage(w http.ResponseWriter, r *http.Request) {
	tmpl := make(map[string]any)
	tmpl["Query"] = r.URL.Query().Get("q")
	q := r.URL.Query().Get("q")
	tmpl["Query"] = q
	posts, err := searchPosts(q)
	if err != nil {
		serverError(w, r, err)
		return
	}
	tmpl["Posts"] = posts
	serveHTML(w, r, "search", tmpl)
}