Files
timmy-home/nostr/post_message.py

72 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Post a message to the Nostr relay. Raw approach - no SDK needed."""
import json, hashlib, time, asyncio, ssl
def sign_and_post(hex_sec, hex_pub, content, kind=1, tags=None):
import coincurve
import websockets
# Build event
ts = int(time.time())
evt_serial = [0, hex_pub, ts, kind, tags or [], content]
evt_id = hashlib.sha256(
json.dumps(evt_serial, separators=(',', ':'), ensure_ascii=False).encode()
).hexdigest()
# Sign with schnorr
sk = coincurve.PrivateKey(bytes.fromhex(hex_sec))
sig = sk.sign_schnorr(bytes.fromhex(evt_id))
signed = {
"id": evt_id,
"pubkey": hex_pub,
"created_at": ts,
"kind": kind,
"tags": tags or [],
"content": content,
"sig": sig.hex()
}
print(f"Event: kind={kind}, id={evt_id[:16]}...")
print(f"Content: {content[:80]}")
return asyncio.run(_send(signed)), signed
async def _send(evt):
import websockets
url = "ws://127.0.0.1:2929"
async with websockets.connect(url) as ws:
await ws.send(json.dumps(["EVENT", evt]))
try:
resp = await asyncio.wait_for(ws.recv(), timeout=5)
print(f"Relay: {resp[:200]}")
return True
except Exception as e:
print(f"Relay: {e}")
return False
if __name__ == "__main__":
import os
keys_path = os.path.expanduser("~/.timmy/nostr/agent_keys.json")
with open(keys_path) as f:
keys = json.load(f)
t = keys["timmy"]
# Post 3 messages
posts = [
["Timmy speaks: The group is live. Sovereignty and service always.", 1, []],
["Timmy speaks: Morning report will now go to Nostr instead of Telegram.", 1, []],
["Timmy speaks: The crew should check NIP-29 for the household group.", 1, []],
]
url = "wss://relay.alexanderwhitestone.com:2929"
print(f"Posting to relay: {url}\n")
for content, kind, tags in posts:
ok, evt = sign_and_post(t["hex_sec"], t["hex_pub"], content, kind, tags)
status = "OK" if ok else "FAILED"
print(f" [{status}] {content[:50]}...\n")