Add geotags, post to nostr
This commit is contained in:
parent
4e1c42f3a7
commit
950de7f769
3 changed files with 73 additions and 16 deletions
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"imports": {
|
"imports": {
|
||||||
"@nostrify/nostrify": "jsr:@nostrify/nostrify@^0.30.1",
|
"@nostrify/nostrify": "jsr:@nostrify/nostrify@^0.30.1",
|
||||||
|
"nostr-geotags": "npm:nostr-geotags@^0.7.1",
|
||||||
"nostr-tools": "npm:nostr-tools@^2.7.2"
|
"nostr-tools": "npm:nostr-tools@^2.7.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
deno.lock
17
deno.lock
|
@ -12,6 +12,7 @@
|
||||||
"npm:@scure/bip32@^1.4.0": "npm:@scure/bip32@1.4.0",
|
"npm:@scure/bip32@^1.4.0": "npm:@scure/bip32@1.4.0",
|
||||||
"npm:@scure/bip39@^1.3.0": "npm:@scure/bip39@1.3.0",
|
"npm:@scure/bip39@^1.3.0": "npm:@scure/bip39@1.3.0",
|
||||||
"npm:lru-cache@^10.2.0": "npm:lru-cache@10.4.3",
|
"npm:lru-cache@^10.2.0": "npm:lru-cache@10.4.3",
|
||||||
|
"npm:nostr-geotags@^0.7.1": "npm:nostr-geotags@0.7.1",
|
||||||
"npm:nostr-tools@^2.7.0": "npm:nostr-tools@2.7.2",
|
"npm:nostr-tools@^2.7.0": "npm:nostr-tools@2.7.2",
|
||||||
"npm:nostr-tools@^2.7.2": "npm:nostr-tools@2.7.2",
|
"npm:nostr-tools@^2.7.2": "npm:nostr-tools@2.7.2",
|
||||||
"npm:websocket-ts@^2.1.5": "npm:websocket-ts@2.1.5",
|
"npm:websocket-ts@^2.1.5": "npm:websocket-ts@2.1.5",
|
||||||
|
@ -122,10 +123,25 @@
|
||||||
"@scure/base": "@scure/base@1.1.7"
|
"@scure/base": "@scure/base@1.1.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"iso-3166@4.3.0": {
|
||||||
|
"integrity": "sha512-H4kM/sVbxTjSl9xnQCYOrNWdpN0R8Uz26j1BuXI9E6U+kw5wmd3HyPgr/v4+NCuvV/NcvwTfZxd5XZ4lPKvBNA==",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
"lru-cache@10.4.3": {
|
"lru-cache@10.4.3": {
|
||||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
||||||
"dependencies": {}
|
"dependencies": {}
|
||||||
},
|
},
|
||||||
|
"ngeohash@0.6.3": {
|
||||||
|
"integrity": "sha512-kltF0cOxgx1AbmVzKxYZaoB0aj7mOxZeHaerEtQV0YaqnkXNq26WWqMmJ6lTqShYxVRWZ/mwvvTrNeOwdslWiw==",
|
||||||
|
"dependencies": {}
|
||||||
|
},
|
||||||
|
"nostr-geotags@0.7.1": {
|
||||||
|
"integrity": "sha512-3xnmDUqTP7MzWLmaJvTgWYwlex3yYGmKi6qAEOHRrh+gZs26YEqECe5yalRH0i4rBZXNXDfkiZs/gvRts6eoAQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"iso-3166": "iso-3166@4.3.0",
|
||||||
|
"ngeohash": "ngeohash@0.6.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nostr-tools@2.7.2": {
|
"nostr-tools@2.7.2": {
|
||||||
"integrity": "sha512-Bq3Ug0SZFtgtL1+0wCnAe8AJtI7yx/00/a2nUug9SkhfOwlKS92Tef12iCK9FdwXw+oFZWMtRnSwcLayQso+xA==",
|
"integrity": "sha512-Bq3Ug0SZFtgtL1+0wCnAe8AJtI7yx/00/a2nUug9SkhfOwlKS92Tef12iCK9FdwXw+oFZWMtRnSwcLayQso+xA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -192,6 +208,7 @@
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"jsr:@nostrify/nostrify@^0.30.1",
|
"jsr:@nostrify/nostrify@^0.30.1",
|
||||||
|
"npm:nostr-geotags@^0.7.1",
|
||||||
"npm:nostr-tools@^2.7.2"
|
"npm:nostr-tools@^2.7.2"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
71
main.ts
71
main.ts
|
@ -10,6 +10,8 @@ import { BlossomUploader } from '@nostrify/nostrify/uploaders';
|
||||||
|
|
||||||
import * as nip19 from 'nostr-tools/nip19'
|
import * as nip19 from 'nostr-tools/nip19'
|
||||||
|
|
||||||
|
import ngeotags from 'nostr-geotags';
|
||||||
|
|
||||||
console.log("\nUse at your own risk!\n");
|
console.log("\nUse at your own risk!\n");
|
||||||
console.log("Considering trying it out with a throwaway nsec.");
|
console.log("Considering trying it out with a throwaway nsec.");
|
||||||
console.log("All data will be public. Anything you upload is hard to delete.\n");
|
console.log("All data will be public. Anything you upload is hard to delete.\n");
|
||||||
|
@ -24,14 +26,12 @@ for (const i in posts) {
|
||||||
const post = posts[i]
|
const post = posts[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("You can try one picture at a time, duplicates are skipped the next run.");
|
console.log("You can try one picture at a time");
|
||||||
|
const offset = Number(prompt("Skip how many posts?", 0));
|
||||||
const n = Number(prompt("How many do you want to upload?", posts.length));
|
const n = Number(prompt("How many do you want to upload?", posts.length - offset));
|
||||||
|
|
||||||
if (n == 0) { Deno.exit(0); }
|
if (n == 0) { Deno.exit(0); }
|
||||||
|
|
||||||
assert(n > 0);
|
assert(n > 0);
|
||||||
assert(n <= posts.length);
|
assert(n <= posts.length - offset);
|
||||||
|
|
||||||
const nsec_str = Deno.env.get("NSEC") || prompt("\nPlease enter your nsec:");
|
const nsec_str = Deno.env.get("NSEC") || prompt("\nPlease enter your nsec:");
|
||||||
|
|
||||||
|
@ -54,13 +54,11 @@ const relay = new NRelay1(relay_str);
|
||||||
|
|
||||||
console.log("\nAs a sanity check, here's your last message (if any):");
|
console.log("\nAs a sanity check, here's your last message (if any):");
|
||||||
|
|
||||||
for await (const msg of relay.req([{ kinds: [1], limit: 1, authors: [pubkey_hex] }])) {
|
for await (const msg of relay.req([{ kinds: [1], limit: 960, authors: [pubkey_hex] }])) {
|
||||||
if (msg[0] === 'EVENT') console.log(msg[2].content);
|
if (msg[0] === 'EVENT') console.log(msg[2].content);
|
||||||
if (msg[0] === 'EOSE') break;
|
if (msg[0] === 'EOSE') break;
|
||||||
}
|
}
|
||||||
|
|
||||||
await relay.close()
|
|
||||||
|
|
||||||
// TODO: suggest public (free or paid) Blossom servers, allow multiple
|
// TODO: suggest public (free or paid) Blossom servers, allow multiple
|
||||||
const blossom_url = Deno.env.get("BLOSSOM") || prompt("Enter Blossom server URL:", "https://blossom.primal.net/");
|
const blossom_url = Deno.env.get("BLOSSOM") || prompt("Enter Blossom server URL:", "https://blossom.primal.net/");
|
||||||
|
|
||||||
|
@ -75,6 +73,7 @@ let completed = 0;
|
||||||
let events = [];
|
let events = [];
|
||||||
|
|
||||||
for (const i in posts) {
|
for (const i in posts) {
|
||||||
|
if (i < offset) continue;
|
||||||
const post = posts[i]
|
const post = posts[i]
|
||||||
console.log(post);
|
console.log(post);
|
||||||
|
|
||||||
|
@ -91,6 +90,9 @@ for (const i in posts) {
|
||||||
message = post.title + "\n";
|
message = post.title + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Populated from the first media item with coordinates
|
||||||
|
let geotags;
|
||||||
|
|
||||||
let first = true;
|
let first = true;
|
||||||
for (const j in post.media) {
|
for (const j in post.media) {
|
||||||
const media = post.media[j];
|
const media = post.media[j];
|
||||||
|
@ -112,6 +114,12 @@ for (const i in posts) {
|
||||||
if (media.uri.slice(-5) == ".webp") {
|
if (media.uri.slice(-5) == ".webp") {
|
||||||
blob = new Blob([data], {type: 'image/webp'});
|
blob = new Blob([data], {type: 'image/webp'});
|
||||||
extension = ".webp"
|
extension = ".webp"
|
||||||
|
} else if (media.uri.slice(-4) == ".jpg") {
|
||||||
|
blob = new Blob([data], {type: 'image/jpeg'});
|
||||||
|
extension = ".jpg"
|
||||||
|
} else if (media.uri.slice(-4) == ".mp4") {
|
||||||
|
blob = new Blob([data], {type: 'video/mp4'});
|
||||||
|
extension = ".mp4"
|
||||||
} else if (!media.uri.includes(".")) {
|
} else if (!media.uri.includes(".")) {
|
||||||
// Assume it's an mp4 movie
|
// Assume it's an mp4 movie
|
||||||
blob = new Blob([data], {type: 'video/mp4'});
|
blob = new Blob([data], {type: 'video/mp4'});
|
||||||
|
@ -122,21 +130,49 @@ for (const i in posts) {
|
||||||
console.log(post);
|
console.log(post);
|
||||||
Deno.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
|
// TODO: if upload fails, log something useful
|
||||||
|
// * e.g. file size (might be over the upload limit)
|
||||||
const tags = await uploader.upload(blob);
|
const tags = await uploader.upload(blob);
|
||||||
|
|
||||||
if (extension == ".mp4") {
|
|
||||||
console.log(tags);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add URL to message (plus extension)
|
// add URL to message (plus extension)
|
||||||
message += tags[0][1] + extension
|
message += tags[0][1] + extension
|
||||||
|
|
||||||
// TODO: get city?
|
if (geotags == undefined && media.media_metadata && media.media_metadata.photo_metadata) {
|
||||||
|
const options = {
|
||||||
|
geohash: true,
|
||||||
|
gps: true,
|
||||||
|
city: false,
|
||||||
|
iso31662: false,
|
||||||
|
iso31662: false,
|
||||||
|
iso31663: false
|
||||||
|
};
|
||||||
|
|
||||||
|
let exif_data = media.media_metadata.photo_metadata.exif_data;
|
||||||
|
if (exif_data) {
|
||||||
|
for (const k in exif_data) {
|
||||||
|
const exif_item = exif_data[k];
|
||||||
|
if (exif_item.latitude != undefined && exif_item.latitude != undefined) {
|
||||||
|
geotags = ngeotags({
|
||||||
|
lat: exif_item.latitude,
|
||||||
|
lon: exif_item.longitude
|
||||||
|
}, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate Nostr event
|
// Generate Nostr event
|
||||||
const event = await signer.signEvent({ kind: 1, content: message, tags: [], created_at: created_at});
|
let event = {
|
||||||
|
kind: 1,
|
||||||
|
content: message,
|
||||||
|
tags: [],
|
||||||
|
created_at: created_at
|
||||||
|
}
|
||||||
|
if (geotags != undefined) {
|
||||||
|
event.tags = [...event.tags, ...geotags];
|
||||||
|
}
|
||||||
|
const signed_event = await signer.signEvent(event);
|
||||||
console.log(event);
|
console.log(event);
|
||||||
events.push(event);
|
events.push(event);
|
||||||
|
|
||||||
|
@ -147,7 +183,10 @@ for (const i in posts) {
|
||||||
alert("About to post to Nostr.");
|
alert("About to post to Nostr.");
|
||||||
|
|
||||||
for (const event in events) {
|
for (const event in events) {
|
||||||
await relay.event(event);
|
console.log(event);
|
||||||
|
console.log(await relay.event(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await relay.close()
|
||||||
|
|
||||||
console.log("Done!");
|
console.log("Done!");
|
||||||
|
|
Loading…
Reference in a new issue