minimal nip-96 file server behind tor
you can install this server on android phone, see below for instructions

upload
curl --socks5-hostname 127.0.0.1:9050 -X POST -H "Content-Type: multipart/form-data" -F "[email protected]" http://s6mn26rvxxoiezkh43e42on4nsnj2etpkvy7pjkj4rgpv7n5n4gjgqyd.onion/upload

app.js

const express = require('express')
const multer  = require('multer')
const crypto = require('crypto')
const fs = require('fs/promises')
const fs_ = require('fs')
const path = require('path')
const upload = multer({ dest: 'uploads/' })
const app = express();
const port = 8000
// change hostname / baseurl if you are not using default termux + tor setup
const hostname = fs_.readFileSync("/data/data/com.termux/files/usr/var/lib/tor/hidden_service/hostname", "utf-8")
const baseurl = "http://" + hostname

function not_found(res){
  res.send("404")
  res.status(404)
}

app.get('/.well-known/nostr/nip96.json', async (req, res) => {
  console.log("get /.well-known/nostr/nip96.json")
  res.send({
    "api_url": baseurl
  })
})

app.post('/', upload.single('file'), async (req, res, next) => {
  console.log("post /")

  const file = req.file

  if (!file) {
    const error = new Error('Please upload a file')
    error.httpStatusCode = 400
    return next(error)
  }

  console.log("upload", file.originalname)

  const fileBuffer = await fs.readFile(file.path);
  const hashSum = crypto.createHash('sha256')
  hashSum.update(fileBuffer)
  const hash = hashSum.digest('hex')
  const extension_match = file.originalname.match(/\.([a-z0-9]{1,4})$/)
  const extension = extension_match && extension_match[1] || null

  await fs.rename(file.path, "uploads/" + hash)

  await fs.writeFile("uploads/" + hash + ".json", JSON.stringify({
    originalname: file.originalname,
    mimetype: file.mimetype,
    extension: extension
  }))

  res.send(JSON.stringify({
    status: "success",
    message: "Upload successful",
    nip94_event: {
      tags: [
        ["url", baseurl + "/" + hash + "." + extension],
        ["ox", hash],
      ],
      content: ""
    }
  }))
})

app.get('/', async (req, res) => {
  console.log("get /")

  res.send(
    `<!DOCTYPE html>
    <html>
    <head>
      <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon"> 
    </head
    <body>
      <h1>nostr nip-96 filehosting</h1>
      <p>curl --socks5-hostname 127.0.0.1:9050 -X POST -H "Content-Type: multipart/form-data" -F "[email protected] " ` + baseurl + `</p>
      <p>
        <a href="/.well-known/nostr/nip96.json">/.well-known/nostr/nip96.json</a>
      </p>
    </body>
    </html>`
  )
})

app.get('/:hash', async (req, res) => {
  console.log("get", req.params.hash)
  const match = req.params.hash.match(/^([^.]+)(\.([a-z0-9]+)|)$/)
  const filename = "uploads/" + match[1] + ".json"

  if(!match || !await fs_.existsSync(filename)){
    return not_found(res)
  }

  try{
    const info = JSON.parse(await fs.readFile(filename))

    if(info.extension !== (match[3] || null)){
      return not_found(res)
    }

    res.set("Content-Type", info.mimetype)
    res.sendFile(path.join(__dirname, 'uploads/' + match[1]))
  }catch(e){
    console.log("info file does not exist for hash " + req.params.hash)
    return not_found(res)
  }
})

app.listen(port, () => {
  console.log('Server is listening on port ' + port)
  console.log("tor address is", baseurl)
})

install on android phone
you can install this server on android phone
first setup tor hidden service as instructed in this guide:
https://rentry.org/androidtor

after that:
create app.js with contents as above
pkg install nodejs
pkg install express
pkg install multer
node app.js

Edit

Pub: 02 Feb 2024 01:55 UTC

Edit: 02 Feb 2024 02:00 UTC

Views: 108