72 lines
2.1 KiB
Python
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")
|