aboutsummaryrefslogtreecommitdiff
path: root/cmd/asbestos
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2025-01-11 15:14:44 -0500
committerXe Iaso <me@xeiaso.net>2025-01-11 15:14:44 -0500
commit231202b2d3bfdda154b68983f6f712bfc1f50b3a (patch)
treeb47d51735eeff35bab9945fb4067397afe5918a4 /cmd/asbestos
parent174c080d1d65701e02cdb3249ef6d36139d9c2e8 (diff)
downloadx-231202b2d3bfdda154b68983f6f712bfc1f50b3a.tar.xz
x-231202b2d3bfdda154b68983f6f712bfc1f50b3a.zip
cmd: add stickers
Signed-off-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'cmd/asbestos')
-rw-r--r--cmd/asbestos/html.templ114
-rw-r--r--cmd/asbestos/html_templ.go403
-rw-r--r--cmd/asbestos/main.go100
3 files changed, 617 insertions, 0 deletions
diff --git a/cmd/asbestos/html.templ b/cmd/asbestos/html.templ
new file mode 100644
index 0000000..ae57782
--- /dev/null
+++ b/cmd/asbestos/html.templ
@@ -0,0 +1,114 @@
+package main
+
+import (
+ "within.website/x/htmx"
+ "within.website/x/xess"
+)
+
+templ NotFound() {
+ <p>The URL you requested could not be found. Please check your URL and hang up to try your call again.</p>
+}
+
+templ allClear() {
+ <p>Your data was not found in the dataset. No action is required on your part.</p>
+}
+
+templ Error(why string) {
+ <p>Oopsie whoopsie uwu we made a fucky-wucky! A widdle fucko boingo! The code monkeys at our headquarters are working VEWY HARD to fix this!</p>
+ <p>Reason: { why }</p>
+}
+
+templ Index() {
+ <p>TODO placeholder</p>
+ <input
+ style="display: block"
+ class="form-control"
+ type="search"
+ name="search"
+ placeholder="Begin Typing To Search Users..."
+ hx-post="/search"
+ hx-trigger="input changed delay:500ms, search"
+ hx-target="#search-results"
+ hx-indicator=".htmx-indicator"
+ hx-swap="innerHTML"
+ />
+ <br/>
+ <div id="search-results"></div>
+}
+
+templ headArea() {
+ @htmx.Use()
+ <style>
+ .no-copy {
+ -webkit-user-select: none; /* Safari */
+ -moz-user-select: none; /* Firefox */
+ -ms-user-select: none; /* Internet Explorer/Edge */
+ user-select: none; /* Non-prefixed version, currently supported by Chrome, Opera and Edge */
+ }
+ </style>
+}
+
+templ footer() {
+ <p>
+ A product of <a href="https://techaro.lol">Techaro</a>
+ <a href="https://bsky.app/profile/techaro.lol">
+ { "@techaro.lol" }
+ </a>, the only ethical AI company
+ </p>
+}
+
+templ Layout(title string, body templ.Component) {
+ @xess.Base(
+ title,
+ headArea(),
+ nil,
+ body,
+ footer(),
+ )
+}
+
+templ searchPage(authorDID string, posts []Post) {
+ <table>
+ <thead>
+ <tr>
+ <th>Created at</th>
+ <th>Text</th>
+ <th>Link</th>
+ </tr>
+ </thead>
+ <tbody>
+ for _, post := range posts {
+ <tr>
+ <td>{ post.CreatedAt }</td>
+ <td>{ post.Text }</td>
+ <td><a href={ templ.SafeURL(post.BlueskyURL) }>🔗</a></td>
+ </tr>
+ }
+ </tbody>
+ </table>
+ <div id="dmca-notice">
+ <p>Since your data is in this dataset, here's what you can do about it:</p>
+ <p>Compose an email to <code>dmca@huggingface.co</code> with the subject line <code>DMCA Takedown Request</code> and something like the following body (rephrase this in your own words):</p>
+ <blockquote class="no-copy">
+ Hello,
+ <br/>
+ <br/>
+ I am writing to you to inform you that my data is present in the dataset <a href="https://huggingface.co/datasets/bluesky-community/one-million-bluesky-posts">bluesky-community/one-million-bluesky-posts</a> and I did not consent to it being included. I would like to request that you remove my data from the dataset.
+ <br/>
+ <br/>
+ You can identify my data by searching for the following DID in the <code>author_did</code> column: <code>{ authorDID }</code>
+ <br/>
+ <br/>
+ Thank you for your attention and patience in this matter.
+ <br/>
+ <br/>
+ Sincerely,
+ <br/>
+ <br/>
+ { "(Your Name here)" }, { "(Your Email here)" }
+ <br/>
+ { "(identified as" } { authorDID }{ ")" }
+ </blockquote>
+ <p>For more information, please refer to the <a href="https://huggingface.co/datasets/bluesky-community/one-million-bluesky-posts/discussions/12">dataset page</a>.</p>
+ </div>
+}
diff --git a/cmd/asbestos/html_templ.go b/cmd/asbestos/html_templ.go
new file mode 100644
index 0000000..7ac5c03
--- /dev/null
+++ b/cmd/asbestos/html_templ.go
@@ -0,0 +1,403 @@
+// Code generated by templ - DO NOT EDIT.
+
+// templ: version: v0.2.793
+package main
+
+//lint:file-ignore SA4006 This context is only used if a nested component is present.
+
+import "github.com/a-h/templ"
+import templruntime "github.com/a-h/templ/runtime"
+
+import (
+ "within.website/x/htmx"
+ "within.website/x/xess"
+)
+
+func NotFound() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var1 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var1 == nil {
+ templ_7745c5c3_Var1 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>The URL you requested could not be found. Please check your URL and hang up to try your call again.</p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func allClear() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var2 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var2 == nil {
+ templ_7745c5c3_Var2 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>Your data was not found in the dataset. No action is required on your part.</p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func Error(why string) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var3 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var3 == nil {
+ templ_7745c5c3_Var3 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>Oopsie whoopsie uwu we made a fucky-wucky! A widdle fucko boingo! The code monkeys at our headquarters are working VEWY HARD to fix this!</p><p>Reason: ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var4 string
+ templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(why)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 18, Col: 17}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func Index() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var5 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var5 == nil {
+ templ_7745c5c3_Var5 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>TODO placeholder</p><input style=\"display: block\" class=\"form-control\" type=\"search\" name=\"search\" placeholder=\"Begin Typing To Search Users...\" hx-post=\"/search\" hx-trigger=\"input changed delay:500ms, search\" hx-target=\"#search-results\" hx-indicator=\".htmx-indicator\" hx-swap=\"innerHTML\"><br><div id=\"search-results\"></div>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func headArea() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var6 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var6 == nil {
+ templ_7745c5c3_Var6 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = htmx.Use().Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<style>\n .no-copy {\n -webkit-user-select: none; /* Safari */\n -moz-user-select: none; /* Firefox */\n -ms-user-select: none; /* Internet Explorer/Edge */\n user-select: none; /* Non-prefixed version, currently supported by Chrome, Opera and Edge */\n }\n </style>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func footer() templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var7 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var7 == nil {
+ templ_7745c5c3_Var7 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p>A product of <a href=\"https://techaro.lol\">Techaro</a> <a href=\"https://bsky.app/profile/techaro.lol\">")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var8 string
+ templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs("@techaro.lol")
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 55, Col: 19}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>, the only ethical AI company</p>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func Layout(title string, body templ.Component) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var9 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var9 == nil {
+ templ_7745c5c3_Var9 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ templ_7745c5c3_Err = xess.Base(
+ title,
+ headArea(),
+ nil,
+ body,
+ footer(),
+ ).Render(ctx, templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+func searchPage(authorDID string, posts []Post) templ.Component {
+ return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
+ templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
+ if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
+ return templ_7745c5c3_CtxErr
+ }
+ templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
+ if !templ_7745c5c3_IsBuffer {
+ defer func() {
+ templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
+ if templ_7745c5c3_Err == nil {
+ templ_7745c5c3_Err = templ_7745c5c3_BufErr
+ }
+ }()
+ }
+ ctx = templ.InitializeContext(ctx)
+ templ_7745c5c3_Var10 := templ.GetChildren(ctx)
+ if templ_7745c5c3_Var10 == nil {
+ templ_7745c5c3_Var10 = templ.NopComponent
+ }
+ ctx = templ.ClearChildren(ctx)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<table><thead><tr><th>Created at</th><th>Text</th><th>Link</th></tr></thead> <tbody>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ for _, post := range posts {
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var11 string
+ templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(post.CreatedAt)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 82, Col: 25}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var12 string
+ templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(post.Text)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 83, Col: 20}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td><a href=\"")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var13 templ.SafeURL = templ.SafeURL(post.BlueskyURL)
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var13)))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">🔗</a></td></tr>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tbody></table><div id=\"dmca-notice\"><p>Since your data is in this dataset, here's what you can do about it:</p><p>Compose an email to <code>dmca@huggingface.co</code> with the subject line <code>DMCA Takedown Request</code> and something like the following body (rephrase this in your own words):</p><blockquote class=\"no-copy\">Hello,<br><br>I am writing to you to inform you that my data is present in the dataset <a href=\"https://huggingface.co/datasets/bluesky-community/one-million-bluesky-posts\">bluesky-community/one-million-bluesky-posts</a> and I did not consent to it being included. I would like to request that you remove my data from the dataset.<br><br>You can identify my data by searching for the following DID in the <code>author_did</code> column: <code>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var14 string
+ templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(authorDID)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 99, Col: 119}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</code><br><br>Thank you for your attention and patience in this matter.<br><br>Sincerely,<br><br>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var15 string
+ templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs("(Your Name here)")
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 108, Col: 23}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(", ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var16 string
+ templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs("(Your Email here)")
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 108, Col: 48}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<br>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var17 string
+ templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs("(identified as")
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 110, Col: 21}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var18 string
+ templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.JoinStringErrs(authorDID)
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 110, Col: 35}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var18))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ var templ_7745c5c3_Var19 string
+ templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(")")
+ if templ_7745c5c3_Err != nil {
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `html.templ`, Line: 110, Col: 42}
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</blockquote><p>For more information, please refer to the <a href=\"https://huggingface.co/datasets/bluesky-community/one-million-bluesky-posts/discussions/12\">dataset page</a>.</p></div>")
+ if templ_7745c5c3_Err != nil {
+ return templ_7745c5c3_Err
+ }
+ return templ_7745c5c3_Err
+ })
+}
+
+var _ = templruntime.GeneratedTemplate
diff --git a/cmd/asbestos/main.go b/cmd/asbestos/main.go
new file mode 100644
index 0000000..9ab1f8e
--- /dev/null
+++ b/cmd/asbestos/main.go
@@ -0,0 +1,100 @@
+package main
+
+import (
+ "database/sql"
+ "flag"
+ "fmt"
+ "log"
+ "log/slog"
+ "net/http"
+
+ "github.com/a-h/templ"
+ _ "github.com/mattn/go-sqlite3"
+ "within.website/x/htmx"
+ "within.website/x/internal"
+ "within.website/x/xess"
+)
+
+//go:generate go run github.com/a-h/templ/cmd/templ@latest generate
+
+var (
+ bind = flag.String("bind", ":8069", "http port to bind on")
+ dbURL = flag.String("database-url", "", "path to sqlite database")
+)
+
+func main() {
+ internal.HandleStartup()
+
+ slog.Info("opening database", "database_url", *dbURL)
+ db, err := sql.Open("sqlite3", *dbURL)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+
+ s := &Server{db: db}
+
+ mux := http.NewServeMux()
+ xess.Mount(mux)
+ htmx.Mount(mux)
+
+ mux.Handle("/{$}", templ.Handler(
+ Layout("Asbestos", Index()),
+ ))
+
+ mux.HandleFunc("POST /search", s.searchHTMXPage)
+
+ fmt.Printf("http://localhost%s\n", *bind)
+ log.Fatal(http.ListenAndServe(*bind, mux))
+}
+
+type Server struct {
+ db *sql.DB
+}
+
+type Post struct {
+ ID int
+ Text string
+ CreatedAt string
+ Author string
+ URI string
+ HasImages bool
+ ReplyTo sql.NullString
+ BlueskyURL string
+}
+
+func (s *Server) getPostsByAuthor(author string) ([]Post, error) {
+ rows, err := s.db.Query("SELECT id, text, created_at, author, uri, has_images, reply_to, bluesky_url FROM posts WHERE author = ?", author)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ var posts []Post
+ for rows.Next() {
+ var post Post
+ if err := rows.Scan(&post.ID, &post.Text, &post.CreatedAt, &post.Author, &post.URI, &post.HasImages, &post.ReplyTo, &post.BlueskyURL); err != nil {
+ return nil, err
+ }
+ posts = append(posts, post)
+ }
+ return posts, nil
+}
+
+func (s *Server) searchHTMXPage(w http.ResponseWriter, r *http.Request) {
+ query := r.FormValue("search")
+
+ posts, err := s.getPostsByAuthor(query)
+ if err != nil {
+ slog.Error("can't find posts", "author", query, "err", err)
+ templ.Handler(Error(err.Error())).ServeHTTP(w, r)
+ return
+ }
+
+ if len(posts) == 0 {
+ templ.Handler(allClear()).ServeHTTP(w, r)
+ return
+ }
+
+ templ.Handler(searchPage(query, posts)).ServeHTTPStreamed(w, r)
+}