Replying to Avatar ₿/🐈‍⬛

Yo, my favorite new blossom+deno to nostr shit is to scrape tenor #catstr gifs and 🌸 them up now that nostrcheck is in as well, thanks to nostr:nprofile1qqszv6q4uryjzr06xfxxew34wwc5hmjfmfpqn229d72gfegsdn2q3fgpz9mhxue69uhkummnw3ezuamfdejj7qg6waehxw309ahx7um5wgh8g6r9wdsk6etrv96zu6t09uqsuamnwvaz7tmwdaejumr0dshs9h69jx nostr:nprofile1qqsqgc0uhmxycvm5gwvn944c7yfxnnxm0nyh8tt62zhrvtd3xkj8fhgprdmhxue69uhkwmr9v9ek7mnpw3hhytnyv4mz7un9d3shjqgcwaehxw309ahx7umywf5hvefwv9c8qtmjv4kxz7gpzemhxue69uhhyetvv9ujumt0wd68ytnsw43z7s3al0v and the heads up of nostr:nprofile1qqsgdp0taan9xwxadyc79nxl8svanu895yr8eyv0ytnss8p9tru047qpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujuerpd46hxtnfduq3qamnwvaz7tmwdaehgu3wwa5kuegzls3js instagram script.

nostr:nevent1qqsq5t4scgw95pma9w0gk8tk0j5t07mu9lel3qv4ssa7p40a95gg5fgpzfmhxue69uhkummnw3ezumr49e4k2tczyz24gvcfdl9zy0ef4h749gxzmcr683fwk6q0ndxeadkydkged32quqcyqqqqqqg3phnsz

```

import { NSecSigner, NRelay1, NSchema as n } from '@nostrify/nostrify';

import { BlossomUploader } from '@nostrify/nostrify/uploaders'; import * as nip19 from 'nostr-tools/nip19'; // Helper function to convert a hex string to Uint8Array function hexToUint8Array(hex: string): Uint8Array { if (hex.length % 2 !== 0) { throw new Error("Hex string must have an even length"); } const array = new Uint8Array(hex.length / 2); for (let i = 0; i < hex.length; i += 2) { array[i / 2] = parseInt(hex.substr(i, 2), 16); } return array; } // Retrieve the secret key from an environment variable const hexSecretKey = Deno.env.get('SECRET_KEY_HEX');

if (!hexSecretKey) { throw new Error('Environment variable "SECRET_KEY_HEX" is not set.'); } const secretKey: Uint8Array = hexToUint8Array(hexSecretKey); // Initialize the signer with your secret key const signer = new NSecSigner(secretKey);

// Define the relay URLs

const relayUrls = [

'wss://nostr.mom', 'wss://nos.lol', 'wss://relay.primal.net', 'wss://e.nos.lol', 'wss://relay.nostr.band' ];

// Create an array of NRelay1 instances const relays = relayUrls.map(url => new NRelay1(url)); // Path to the JSON file that stores uploaded files

const uploadedFilesPath = './uploaded_files.json'; // Function to read uploaded files from JSON async function readUploadedFiles(): Promise> {

try { const data = await Deno.readTextFile(uploadedFilesPath); return new Set(JSON.parse(data)); } catch { return new Set();

} }

// Function to write uploaded files to JSON

async function writeUploadedFiles(uploadedFiles: Set) { await Deno.writeTextFile(uploadedFilesPath, JSON.stringify(Array.from(uploadedFiles))); }

// Function to sign, parse, and upload a media file async function signAndUploadMedia(filePath: string, uploadedFiles: Set) { try {

// Check if the file has already been uploaded if (uploadedFiles.has(filePath)) {

console.log(`File ${filePath} has already been uploaded. Skipping.`); return; }

// Get the public key from the signer const pubkey = await signer.getPublicKey();

// Initialize the uploader const uploader = new BlossomUploader({

servers: [ 'https://cdn.satellite.earth',

'https://nstore.nostrver.se',

'https://blossom.puhcho.me',

'https://blossom.primal.net', 'https://files.v0l.io/', 'https://cdn.nostrcheck.me' ],

signer: signer, // Use the signer for authentication

}); // Read the file const fileBuffer = await Deno.readFile(filePath);

const file = new File([fileBuffer], filePath.split('/').pop()!);

// Upload the file and get the tags const tags = await uploader.upload(file);

// Find the URL in the tags let fileUrl = 'Unknown URL';

for (const tag of tags) {

if (tag[0] === "url" && tag[1]) {

fileUrl = tag[1];

break; } } // Create event data

const eventData = { kind: 1,

content: `${fileUrl}`,

tags: tags, created_at: Math.floor(Date.now() / 1000), };

// Sign the event to get id and sig

const signedEvent = await signer.signEvent(eventData);

const completeEventData = {

...eventData, id: signedEvent.id, pubkey: pubkey, sig: signedEvent.sig,

};

// Parse and validate the complete event data using NSchema

const event = n.event().parse(completeEventData); console.log('Parsed and validated event:', event);

// Send the event to each relay for (const relay of relays) { console.log('Sending event to relay:', relay); console.log(await relay.event(event));

await relay.close(); } // Add the file to the uploaded files set and update the JSON file uploadedFiles.add(filePath); await writeUploadedFiles(uploadedFiles);

console.log("Done!");

} catch (error) {

console.error('Error signing and uploading media:', error);

} } // Function to select a random valid file from a folder

async function getRandomValidFileFromFolder(folderPath: string, uploadedFiles: Set): Promise { const validExtensions = ['jpg', 'mp4', 'webp', 'gif']; const files: string[] = []; for await (const dirEntry of Deno.readDir(folderPath)) { if (dirEntry.isFile) {

const extension = dirEntry.name.split('.').pop()?.toLowerCase(); if (extension && validExtensions.includes(extension)) { files.push(dirEntry.name); } }

} // Filter out files that have already been uploaded const unuploadedFiles = files.filter(file => !uploadedFiles.has(`${folderPath}/${file}`));

if (unuploadedFiles.length === 0) { console.error('No unuploaded valid files found. Please add new JPG, MP4, or WEBP files.');

return null; } const randomIndex = Math.floor(Math.random() * unuploadedFiles.length);

return `${folderPath}/${unuploadedFiles[randomIndex]}`;

}

// Example usage

const folderPath = Deno.env.get('MEDIA_FOLDER_PATH');

if (folderPath) { readUploadedFiles().then((uploadedFiles) => {

getRandomValidFileFromFolder(folderPath, uploadedFiles).then((randomFilePath) => { if (randomFilePath) {

signAndUploadMedia(randomFilePath, uploadedFiles);

}

});

});

} else {

console.error('Environment variable "MEDIA_FOLDER_PATH" is not set.');

}

```

Also puts amethyst gallery to good use:

https://v.nostr.build/ICPPrle8VODjFOPV.mp4

```

import { NSecSigner, NRelay1, NSchema as n } from '@nostrify/nostrify';

import { BlossomUploader } from '@nostrify/nostrify/uploaders';

import * as nip19 from 'nostr-tools/nip19';

// Helper function to convert a hex string to Uint8Array

function hexToUint8Array(hex: string): Uint8Array {

if (hex.length % 2 !== 0) {

throw new Error("Hex string must have an even length");

}

const array = new Uint8Array(hex.length / 2);

for (let i = 0; i < hex.length; i += 2) {

array[i / 2] = parseInt(hex.substr(i, 2), 16);

}

return array;

}

// Function to read uploaded files from JSON

async function readUploadedFiles(uploadedFilesPath: string): Promise> {

try {

const data = await Deno.readTextFile(uploadedFilesPath);

return new Set(JSON.parse(data));

} catch {

return new Set();

}

}

// Function to write uploaded files to JSON

async function writeUploadedFiles(uploadedFiles: Set, uploadedFilesPath: string) {

await Deno.writeTextFile(uploadedFilesPath, JSON.stringify(Array.from(uploadedFiles)));

}

// Function to append a URL to a text file

async function appendUrlToFile(fileUrl: string, urlFilePath: string) {

try {

await Deno.writeTextFile(urlFilePath, fileUrl + '\n', { append: true });

console.log(`Appended URL to file: ${fileUrl}`);

} catch (error) {

console.error('Error appending URL to file:', error);

}

}

// Function to sign, parse, and upload a media file

async function signAndUploadMedia(

filePath: string,

uploadedFiles: Set,

urlFilePath: string,

signer: NSecSigner,

relays: { relay: NRelay1; url: string }[]

) {

try {

// Check if the file has already been uploaded

if (uploadedFiles.has(filePath)) {

console.log(`File ${filePath} has already been uploaded. Skipping.`);

return;

}

// Get the public key from the signer

const pubkey = await signer.getPublicKey();

// Initialize the uploader

const uploader = new BlossomUploader({

servers: [

'https://cdn.satellite.earth',

'https://nstore.nostrver.se',

'https://blossom.puhcho.me',

'https://blossom.primal.net',

'https://cdn.nostrcheck.me'

],

signer: signer,

});

// Read the file

const fileBuffer = await Deno.readFile(filePath);

const file = new File([fileBuffer], filePath.split('/').pop()!);

// Upload the file and get the tags

const tags = await uploader.upload(file);

// Find the URL in the tags

let fileUrl = 'Unknown URL';

for (const tag of tags) {

if (tag[0] === "url" && tag[1]) {

fileUrl = tag[1];

break;

}

}

// Append the URL to the text file

await appendUrlToFile(fileUrl, urlFilePath);

// Create event data

const eventData = {

kind: 1,

content: `${fileUrl}`,

tags: tags,

created_at: Math.floor(Date.now() / 1000),

};

// Sign the event to get id and sig

const signedEvent = await signer.signEvent(eventData);

const completeEventData = {

...eventData,

id: signedEvent.id,

pubkey: pubkey,

sig: signedEvent.sig,

};

// Parse and validate the complete event data using NSchema

const event = n.event().parse(completeEventData);

console.log('Parsed and validated event:', event);

// Send the event to each relay

for (const { relay, url } of relays) {

try {

console.log(`Sending event to relay ${url}`);

await relay.event(event);

console.log(`Event sent successfully to ${url}`);

} catch (error) {

console.error(`Error sending event to relay ${url}:`, error);

} finally {

try {

await relay.close();

console.log(`Relay ${url} closed`);

} catch (closeError) {

console.error(`Error closing relay ${url}:`, closeError);

}

}

}

// Add the file to the uploaded files set and update the JSON file

uploadedFiles.add(filePath);

await writeUploadedFiles(uploadedFiles, './uploaded_files.json');

console.log("Done!");

} catch (error) {

console.error('Error signing and uploading media:', error);

}

}

// Function to select a random valid file from a folder

async function getRandomValidFileFromFolder(folderPath: string, uploadedFiles: Set): Promise {

const validExtensions = ['jpg', 'mp4', 'webp', 'gif'];

const files: string[] = [];

for await (const dirEntry of Deno.readDir(folderPath)) {

if (dirEntry.isFile) {

const extension = dirEntry.name.split('.').pop()?.toLowerCase();

if (extension && validExtensions.includes(extension)) {

files.push(dirEntry.name);

}

}

}

// Filter out files that have already been uploaded

const unuploadedFiles = files.filter(file => !uploadedFiles.has(`${folderPath}/${file}`));

if (unuploadedFiles.length === 0) {

console.log('All files have been uploaded. Selecting a random URL to publish.');

return null;

}

const randomIndex = Math.floor(Math.random() * unuploadedFiles.length);

return `${folderPath}/${unuploadedFiles[randomIndex]}`;

}

// Function to publish a Nostr event with a random URL

async function publishRandomUrlEvent(urlFilePath: string, signer: NSecSigner, relays: { relay: NRelay1; url: string }[]) {

try {

const urls = (await Deno.readTextFile(urlFilePath)).trim().split('\n');

if (urls.length === 0) {

console.error('No URLs found in the URL file.');

return;

}

const randomUrl = urls[Math.floor(Math.random() * urls.length)];

// Create event data

const eventData = {

kind: 1,

content: `${randomUrl}`,

tags: [],

created_at: Math.floor(Date.now() / 1000),

};

// Sign the event to get id and sig

const signedEvent = await signer.signEvent(eventData);

const completeEventData = {

...eventData,

id: signedEvent.id,

pubkey: await signer.getPublicKey(),

sig: signedEvent.sig,

};

// Parse and validate the complete event data using NSchema

const event = n.event().parse(completeEventData);

console.log('Parsed and validated event:', event);

for (const { relay, url } of relays) {

try {

console.log(`Sending event to relay ${url}`);

await relay.event(event);

console.log(`Event sent successfully to ${url}`);

} catch (error) {

console.error(`Error sending event to relay ${url}:`, error);

} finally {

try {

await relay.close();

console.log(`Relay ${url} closed`);

} catch (closeError) {

console.error(`Error closing relay ${url}:`, closeError);

}

}

}

console.log("Published random URL event successfully!");

} catch (error) {

console.error('Error publishing random URL event:', error);

}

}

// Main function to execute the script

async function main() {

const hexSecretKey = Deno.env.get('SECRET_KEY_HEX');

if (!hexSecretKey) {

console.error('Environment variable "SECRET_KEY_HEX" is not set.');

Deno.exit(1);

return;

}

const secretKey: Uint8Array = hexToUint8Array(hexSecretKey);

// Initialize the signer with your secret key

const signer = new NSecSigner(secretKey);

// Define the relay URLs

const relayUrls = [

'wss://nostr.mom',

'wss://nos.lol',

'wss://relay.primal.net',

'wss://e.nos.lol',

'wss://relay.damus.io',

'wss://nostr.lu.ke',

'wss://nostr.oxtr.dev',

'wss://relay.nostrcheck.me',

'wss://nostr.data.haus',

'wss://ditto.puhcho.me/relay',

'wss://offchain.pub',

'wss://strfry.iris.to'

];

// Create an array of NRelay1 instances with their URLs

const relays = relayUrls.map(url => ({ relay: new NRelay1(url), url }));

// Path to the JSON file that stores uploaded files

const uploadedFilesPath = './home/user/test_bloom/uploaded_files.json';

// Path to the text file that stores uploaded URLs

const urlFilePath = './home/user/test_bloom/uploaded_urls.txt';

// Example usage

const folderPath = Deno.env.get('MEDIA_FOLDER_PATH');

if (folderPath) {

try {

const uploadedFiles = await readUploadedFiles(uploadedFilesPath);

const randomFilePath = await getRandomValidFileFromFolder(folderPath, uploadedFiles);

if (randomFilePath) {

await signAndUploadMedia(randomFilePath, uploadedFiles, urlFilePath, signer, relays);

} else {

await publishRandomUrlEvent(urlFilePath, signer, relays);

}

} catch (error) {

console.error('Error during execution:', error);

} finally {

Deno.exit();

}

} else {

console.error('Environment variable "MEDIA_FOLDER_PATH" is not set.');

Deno.exit(1);

}

}

// Execute main function

main();

```

Better as it was uploading to just one blossom.

Reply to this note

Please Login to reply.

Discussion

No replies yet.