mirror of
https://github.com/nbd-wtf/go-nostr.git
synced 2025-03-17 13:22:56 +01:00
NIP-96 sign payload, content field for file caption (#148)
* content in upload response for file caption as in NIP-94, optional signing of file payload in NIP-98 header * Content in NIP-94 as well
This commit is contained in:
parent
0b2b69529b
commit
c8c295f839
@ -51,6 +51,7 @@ type FileMetadata struct {
|
|||||||
TorrentInfoHash string
|
TorrentInfoHash string
|
||||||
Blurhash string
|
Blurhash string
|
||||||
Thumb string
|
Thumb string
|
||||||
|
Content string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fm FileMetadata) IsVideo() bool { return strings.Split(fm.M, "/")[0] == "video" }
|
func (fm FileMetadata) IsVideo() bool { return strings.Split(fm.M, "/")[0] == "video" }
|
||||||
|
@ -3,9 +3,12 @@ package nip96
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash"
|
||||||
"io"
|
"io"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -26,6 +29,7 @@ func Upload(ctx context.Context, req UploadRequest) (*UploadResponse, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var requestBody bytes.Buffer
|
var requestBody bytes.Buffer
|
||||||
|
fileHash := sha256.New()
|
||||||
writer := multipart.NewWriter(&requestBody)
|
writer := multipart.NewWriter(&requestBody)
|
||||||
{
|
{
|
||||||
// Add the file
|
// Add the file
|
||||||
@ -33,7 +37,7 @@ func Upload(ctx context.Context, req UploadRequest) (*UploadResponse, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("multipartWriter.CreateFormFile: %w", err)
|
return nil, fmt.Errorf("multipartWriter.CreateFormFile: %w", err)
|
||||||
}
|
}
|
||||||
if _, err := io.Copy(fileWriter, req.File); err != nil {
|
if _, err := io.Copy(fileWriter, io.TeeReader(req.File, fileHash)); err != nil {
|
||||||
return nil, fmt.Errorf("io.Copy: %w", err)
|
return nil, fmt.Errorf("io.Copy: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +65,10 @@ func Upload(ctx context.Context, req UploadRequest) (*UploadResponse, error) {
|
|||||||
uploadReq.Header.Set("Content-Type", writer.FormDataContentType())
|
uploadReq.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
|
|
||||||
if req.SK != "" {
|
if req.SK != "" {
|
||||||
auth, err := generateAuthHeader(req.SK, req.Host)
|
if !req.SignPayload {
|
||||||
|
fileHash = nil
|
||||||
|
}
|
||||||
|
auth, err := generateAuthHeader(req.SK, req.Host, fileHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("generateAuthHeader: %w", err)
|
return nil, fmt.Errorf("generateAuthHeader: %w", err)
|
||||||
}
|
}
|
||||||
@ -99,7 +106,7 @@ func Upload(ctx context.Context, req UploadRequest) (*UploadResponse, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateAuthHeader(sk, host string) (string, error) {
|
func generateAuthHeader(sk, host string, fileHash hash.Hash) (string, error) {
|
||||||
pk, err := nostr.GetPublicKey(sk)
|
pk, err := nostr.GetPublicKey(sk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("nostr.GetPublicKey: %w", err)
|
return "", fmt.Errorf("nostr.GetPublicKey: %w", err)
|
||||||
@ -114,6 +121,9 @@ func generateAuthHeader(sk, host string) (string, error) {
|
|||||||
nostr.Tag{"method", "POST"},
|
nostr.Tag{"method", "POST"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if fileHash != nil {
|
||||||
|
event.Tags = append(event.Tags, nostr.Tag{"payload", hex.EncodeToString(fileHash.Sum(nil))})
|
||||||
|
}
|
||||||
event.Sign(sk)
|
event.Sign(sk)
|
||||||
|
|
||||||
b, err := json.Marshal(event)
|
b, err := json.Marshal(event)
|
||||||
|
@ -22,6 +22,7 @@ func TestUpload(t *testing.T) {
|
|||||||
//Host: "https://nostrcheck.me/api/v2/media",
|
//Host: "https://nostrcheck.me/api/v2/media",
|
||||||
//Host: "https://nostrage.com/api/v2/media",
|
//Host: "https://nostrage.com/api/v2/media",
|
||||||
SK: nostr.GeneratePrivateKey(),
|
SK: nostr.GeneratePrivateKey(),
|
||||||
|
SignPayload: true,
|
||||||
File: img,
|
File: img,
|
||||||
Filename: "ostrich.png",
|
Filename: "ostrich.png",
|
||||||
Caption: "nostr ostrich",
|
Caption: "nostr ostrich",
|
||||||
|
@ -16,6 +16,9 @@ type UploadRequest struct {
|
|||||||
// SK is a private key used to sign the NIP-98 Auth header. If not set
|
// SK is a private key used to sign the NIP-98 Auth header. If not set
|
||||||
// the auth header will not be included in the upload.
|
// the auth header will not be included in the upload.
|
||||||
SK string
|
SK string
|
||||||
|
// Optional signing of payload (file) as described in NIP-98, if enabled
|
||||||
|
// includes `payload` tag with file's sha256 in signed event / auth header.
|
||||||
|
SignPayload bool
|
||||||
|
|
||||||
// File is the file to upload.
|
// File is the file to upload.
|
||||||
File io.Reader
|
File io.Reader
|
||||||
@ -64,6 +67,7 @@ type UploadResponse struct {
|
|||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
ProcessingURL string `json:"processing_url"`
|
ProcessingURL string `json:"processing_url"`
|
||||||
Nip94Event struct {
|
Nip94Event struct {
|
||||||
Tags nostr.Tags `json:"tags"`
|
Tags nostr.Tags `json:"tags"`
|
||||||
|
Content string `json:"content"`
|
||||||
} `json:"nip94_event"`
|
} `json:"nip94_event"`
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user