summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-10-06 22:15:22 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-10-06 22:15:22 -0700
commit65b1ed1ff56e4d795c67d4d0b31634decec7767b (patch)
tree40fb48480c7d9273e084ad317378d5cd7384c44f
parentc5a5b24cf6370ab549c033b20ad0389ec3ce8ec1 (diff)
downloadroseh.moe-65b1ed1ff56e4d795c67d4d0b31634decec7767b.tar.zst
Add uploader tool
-rw-r--r--internal/wordlist/wordlist.go11
-rw-r--r--internal/wordlist/wordlist.txt (renamed from wordlist.txt)0
-rw-r--r--roseh.moe.go18
-rw-r--r--tools/hole/hole.go91
4 files changed, 112 insertions, 8 deletions
diff --git a/internal/wordlist/wordlist.go b/internal/wordlist/wordlist.go
new file mode 100644
index 0000000..de929bc
--- /dev/null
+++ b/internal/wordlist/wordlist.go
@@ -0,0 +1,11 @@
+package wordlist
+
+import (
+ _ "embed"
+ "strings"
+)
+
+//go:embed wordlist.txt
+var wordList string
+
+var Words = strings.Split(strings.TrimSuffix(wordList, "\n"), "\n")
diff --git a/wordlist.txt b/internal/wordlist/wordlist.txt
index 5e304ce..5e304ce 100644
--- a/wordlist.txt
+++ b/internal/wordlist/wordlist.txt
diff --git a/roseh.moe.go b/roseh.moe.go
index 9b5c1a6..140b1de 100644
--- a/roseh.moe.go
+++ b/roseh.moe.go
@@ -20,6 +20,8 @@ import (
"strings"
"sync"
"time"
+
+ "gitlab.com/rhogenson/roseh.moe/internal/wordlist"
)
var (
@@ -119,10 +121,6 @@ func favicon(w http.ResponseWriter, r *http.Request) {
}
var (
- //go:embed wordlist.txt
- wordListString string
- wordList = strings.Split(strings.TrimSuffix(wordListString, "\n"), "\n")
-
//go:embed templates/wormhole.html.template
wormholeTemplateString string
wormholeTemplate = template.Must(template.Must(outlineTemplate.Clone()).New("body").Parse(wormholeTemplateString)).Lookup("outline")
@@ -133,15 +131,19 @@ type wormholeTemplateArgs struct {
Hole string
}
-func wormhole(w http.ResponseWriter, r *http.Request) {
+func makeHole() string {
const nWords = 10
buf := make([]byte, 2*nWords)
rand.Read(buf)
words := make([]string, nWords)
for i := range words {
- words[i] = wordList[binary.NativeEndian.Uint16(buf[2*i:])&0x1fff]
+ words[i] = wordlist.Words[binary.NativeEndian.Uint16(buf[2*i:])&0x1fff]
}
- if err := wormholeTemplate.Execute(w, wormholeTemplateArgs{Self: *selfURL, Hole: strings.Join(words, "-")}); err != nil {
+ return strings.Join(words, "-")
+}
+
+func wormhole(w http.ResponseWriter, r *http.Request) {
+ if err := wormholeTemplate.Execute(w, wormholeTemplateArgs{Self: *selfURL, Hole: makeHole()}); err != nil {
log.Printf("Warning: wormhole: %s", err)
}
}
@@ -160,7 +162,7 @@ var wormholeNotify = make(map[string]chan struct{})
func wormholeSend(w http.ResponseWriter, r *http.Request) {
reader, err := r.MultipartReader()
if err != nil {
- http.Error(w, "not a multipart/form-data request", http.StatusBadRequest)
+ http.Error(w, fmt.Sprintf("Not a multipart/form-data request: %s", err), http.StatusBadRequest)
return
}
for {
diff --git a/tools/hole/hole.go b/tools/hole/hole.go
new file mode 100644
index 0000000..d701c40
--- /dev/null
+++ b/tools/hole/hole.go
@@ -0,0 +1,91 @@
+package main
+
+import (
+ "crypto/rand"
+ "encoding/binary"
+ "flag"
+ "fmt"
+ "io"
+ "mime/multipart"
+ "net/http"
+ "os"
+ "strings"
+
+ "gitlab.com/rhogenson/roseh.moe/internal/wordlist"
+)
+
+var url = flag.String("url", "https://roseh.moe", "server URL")
+
+func makeHole() string {
+ const nWords = 10
+ buf := make([]byte, 2*nWords)
+ rand.Read(buf)
+ words := make([]string, nWords)
+ for i := range words {
+ words[i] = wordlist.Words[binary.NativeEndian.Uint16(buf[2*i:])&0x1fff]
+ }
+ return strings.Join(words, "-")
+}
+
+func hole() error {
+ args := flag.Args()
+ if len(args) != 1 {
+ return fmt.Errorf("usage error")
+ }
+ fileName := args[0]
+ f, err := os.Open(fileName)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+ hole := makeHole()
+ fmt.Println(*url + "/wormhole/" + hole)
+ resp, err := http.Get(*url + "/wormhole/" + hole + "/ready")
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("%s", resp.Status)
+ }
+ if _, err := io.Copy(io.Discard, resp.Body); err != nil {
+ return err
+ }
+ pipeReader, pipeWriter := io.Pipe()
+ multipartWriter := multipart.NewWriter(pipeWriter)
+ go func() {
+ defer pipeWriter.Close()
+ part, err := multipartWriter.CreateFormFile("file", fileName)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return
+ }
+ if _, err := io.Copy(part, f); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return
+ }
+ if err := multipartWriter.Close(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ return
+ }
+ }()
+ resp, err = http.Post(*url+"/wormhole/"+hole, multipartWriter.FormDataContentType(), pipeReader)
+ if err != nil {
+ return fmt.Errorf("upload: %s", err)
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ return fmt.Errorf("%s", resp.Status)
+ }
+ io.Copy(os.Stderr, resp.Body)
+ fmt.Fprintln(os.Stderr)
+ return nil
+}
+
+func main() {
+ flag.Parse()
+ if err := hole(); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ os.Exit(1)
+ }
+}