commit 12418b12ae7d6e565f21359426570278cec3f0fa
parent 6d52b2946655a5506db31e28fe93f1c5a19c5c58
Author: breadcat <breadcat@users.noreply.github.com>
Date: Mon, 22 Sep 2025 16:17:44 +0100
Raw URL copy/paste function
Diffstat:
2 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/main.go b/main.go
@@ -45,6 +45,8 @@ type TagDisplay struct {
type PageData struct {
Title string
Data interface{}
+ IP string
+ Port string
}
func main() {
@@ -351,6 +353,22 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, fmt.Sprintf("/file/%d", id), http.StatusSeeOther)
}
+// raw local IP for raw address
+func getLocalIP() (string, error) {
+ addrs, err := net.InterfaceAddrs()
+ if err != nil {
+ return "", err
+ }
+ for _, addr := range addrs {
+ if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
+ if ipnet.IP.To4() != nil {
+ return ipnet.IP.String(), nil
+ }
+ }
+ }
+ return "", fmt.Errorf("no connected network interface found")
+}
+
// Router for file operations, tag deletion, rename, and delete
func fileRouter(w http.ResponseWriter, r *http.Request) {
parts := strings.Split(r.URL.Path, "/")
@@ -552,13 +570,22 @@ func fileHandler(w http.ResponseWriter, r *http.Request) {
return
}
- pageData := PageData{
- Title: f.Filename,
- Data: struct {
- File File
- Categories []string
- }{f, cats},
- }
+ // IP and port for raw URL
+ ip, _ := getLocalIP()
+ port := strings.TrimPrefix(config.ServerPort, ":")
+ // Escape filename for copy/paste
+ escaped := url.PathEscape(f.Filename)
+
+ pageData := PageData{
+ Title: f.Filename,
+ Data: struct {
+ File File
+ Categories []string
+ EscapedFilename string
+ }{f, cats, escaped},
+ IP: ip,
+ Port: port,
+ }
tmpl.ExecuteTemplate(w, "file.html", pageData)
}
diff --git a/templates/file.html b/templates/file.html
@@ -1,5 +1,4 @@
{{template "_header" .}}
-File {{.Data.File.Filename}}
<h2>File: {{.Data.File.Filename}}</h2>
{{if hasAnySuffix .Data.File.Filename ".jpg" ".jpeg" ".png" ".gif" ".webp"}}
@@ -12,6 +11,46 @@ File {{.Data.File.Filename}}
<a href="/uploads/{{.Data.File.Filename}}">Download file</a><br>
{{end}}
+<h3>Raw URL</h3>
+<pre id="raw-url">http://{{.IP}}:{{.Port}}/uploads/{{.Data.EscapedFilename}}</pre>
+<button id="copy-btn" style="margin-top: 5px;">Copy to Clipboard</button>
+<span id="copy-status" style="margin-left: 10px;"></span>
+
+<script>
+document.getElementById("copy-btn").addEventListener("click", function() {
+ const text = document.getElementById("raw-url").textContent.trim();
+ const status = document.getElementById("copy-status");
+
+ // Fallback approach using a temporary textarea
+ const textarea = document.createElement("textarea");
+ textarea.value = text;
+ textarea.style.position = "fixed"; // prevent scrolling
+ textarea.style.left = "-9999px"; // off-screen
+ document.body.appendChild(textarea);
+ textarea.focus();
+ textarea.select();
+
+ let successful = false;
+ try {
+ successful = document.execCommand("copy");
+ } catch (err) {
+ successful = false;
+ }
+
+ document.body.removeChild(textarea);
+
+ if (successful) {
+ status.textContent = "✓ Copied!";
+ status.style.color = "green";
+ } else {
+ status.textContent = "✗ Copy failed";
+ status.style.color = "red";
+ }
+});
+</script>
+
+
+
<h3>File Actions</h3>
<form method="post" action="/file/{{.Data.File.ID}}/rename" style="display:inline-block; margin-right: 20px;">
New filename: <input type="text" name="newfilename" value="{{.Data.File.Filename}}" required style="width:300px"><br>