So this was merged:
Try opening this note on https://nostter.app/ then clicking on
- wss://algo.utxo.one
- wss://catstrr.swarmstr.com
- wss://pyramid.fiatjaf.com
- wss://yabu.me
- wss://questions.swarmstr.com
- wss://labour.fiatjaf.com
Different locations and ips each time depending nodes it connects to.
Try to, microapps for different things, also the idea is for frens to get onboarded to nostr. Which reminds me onosendai and fanfares.io should be in there too.
Yeah that's my deck π the idea is from webcore.live but wanted straight easier management. I find the N fallback funnier and don't want an api.

nostr:naddr1qqjrxvf3x3jnve3k943nzepk956xzen994sngve495ukvdpk8qmkxcecx43x2q3qeaz6dwsnvwkha5sn5puwwyxjgy26uusundrm684lg3vw4ma5c2jsxpqqqpmxw7m6kla
Second. They are already in gallery if shared. The ui would be good to have quote in note from that but amethyst is not there yet. So you just put the note id like this
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.
```
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
// Function to sign, parse, and upload a media file async function signAndUploadMedia(filePath: string, uploadedFiles: Set
// 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://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
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:
Catstr is very popular in the hosehold, also the mandalorian π€£ then quoting the note id the gif is in from the gallery in a note, reply etc. If you already have a gif folder, that goes up easy. Or scraping tenor etc for old movies gifs and so on.
Autoupload them to blossoms for the kids so they can send whatever they like to amethyst's gallery. Then note id etc.
https://video.nostr.build/94e07f0010d96c85d033e11b6cfa92ff82aa33769d9a089f3ce007be4454267f.mp4
Adding image support to https://nostrava.xyz
All images are currently being uploaded to the #blossom server backing the app. Soon users will be able to choose whichever blossom compatible server they wish.


#running #moving #nostrava #activities
Mmm iris.to is becoming a goto client. Need cashu zaps.

How it looks like on podverse:

https://video.nostr.build/649a7a9ab3b25620debd34c4613587281d7bb223ea6c291c309f0c4abda89407.mp4
Me, playing with enhanced rss to listen to frens pubs from the podcasts apps and zap them from there(pulls the lud16).
Some podcast apps are... that is not just for e mail, bitch. Catch the f up.
Starting with basics #onosendai
CATSTRR - a nostr relay that only accepts notes with cat pictures πΈ
wss://catstrr.swarmstr.com
Powered by khatru framework by nostr:nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8g2lcy6q
Uses facebook/detr-resnet-50 for object detection.
Feedback/suggestions (future relay ideas) appreciated.

nostr:note1htdjk2ghh0c77zep0gelsmvr32vlce32453ed5f8n0dfv6aewa4s6jg376



