# Nostr Post Scheduler & Private Message API A Node.js API for scheduling Nostr posts and sending private messages using the Nostr protocol. ## Features - Schedule public Nostr posts (kind: 1) at a future time - Reschedule or cancel scheduled posts - Send encrypted private messages (kind: 4) - Auto-managing the database, including table creation and indexing - Efficient background job processing to send scheduled posts just-in-time - API key authentication for secure access - Swagger UI documentation available at `/docs` for easy API exploration ## Technology Stack - **Programming Language**: JavaScript (Node.js) - **Framework**: Express.js - **Database**: SQLite (default) or PostgreSQL/MySQL (via .env configuration) - **Queue System**: Background tasks with node-cron - **Security**: API key authentication, proper key handling, and rate limiting - **Documentation**: Swagger UI (`/docs`) and Redoc (`/redoc`) - **Nostr Libraries**: Nostr-NDK and nostr-tools ## Getting Started ### Prerequisites - Node.js (v14 or higher) - npm or yarn ### Installation 1. Clone the repository: ```bash git clone https://github.com/yourusername/nostr-scheduler-api.git cd nostr-scheduler-api ``` 2. Install dependencies: ```bash npm install ``` 3. Create a `.env` file based on the `.env.example`: ```bash cp .env.example .env ``` 4. Edit the `.env` file with your configuration: ```bash cp .env.example .env ``` 5. Start the server: ```bash npm start ``` For development with auto-reload: ```bash npm run dev ``` ## API Documentation Once the server is running, you can access the API documentation at: - Swagger UI: http://localhost:3000/docs ## API Endpoints ### Schedule a Nostr Post - **Method**: POST `/schedule/post` - **Description**: Schedules a new Nostr post at a future time. - **Request Parameters**: - `content`: Content of the Nostr post - Either `timestamp` (Unix format) or both `date` (DD/MM/YY or DD/MM/YYYY) and `hour` (HH:MM or HHMM) - Optional `relays` (otherwise defaults from .env) ### Reschedule a Nostr Post - **Method**: PATCH `/schedule/post/{post_id}` - **Description**: Updates the scheduled time of an existing post. - **Request Parameters**: - `post_id`: ID of the post to reschedule - Either new `timestamp` or new `date` + `hour` ### Retrieve a Scheduled Post - **Method**: GET `/schedule/post/{post_id}` - **Description**: Returns details of a scheduled post. ### Delete a Scheduled Post - **Method**: DELETE `/schedule/post/{post_id}` - **Description**: Cancels a scheduled post before it is sent. ### List All Scheduled Posts - **Method**: GET `/schedule/posts` - **Description**: Returns all pending scheduled posts. ### Send a Private Message - **Method**: POST `/messages/send` - **Description**: Immediately sends an encrypted private message. - **Request Parameters**: - `recipient_pubkey`: Public key of the recipient - `content`: Message content - Optional `relays` (otherwise defaults from .env) ### Retrieve Sent Messages - **Method**: GET `/messages/sent` - **Description**: Returns a history of sent private messages. ### Webhook for External Triggers - **Method**: POST `/webhook/trigger` - **Description**: Allows an external service to trigger a scheduled post immediately. - **Request Parameters**: - `post_id`: ID of the post to send immediately ## Authentication & Security All API requests require an Admin API Key in the request headers: - Header: `Authorization: Bearer ` - If missing or incorrect, the API returns 401 Unauthorized. Private Key Handling: - The private key (in nsec or hex format) is stored in .env and never in the database. - It is only loaded when necessary for signing events. Rate Limiting: - Prevents spam and excessive API usage. - Limited to X requests per minute (configurable). ## Database Schema ### Table: scheduled_posts | Column | Type | Description | |-----------|---------|---------------------------------------| | id | INTEGER | Unique ID of the scheduled post (PK) | | content | TEXT | The content of the scheduled note | | timestamp | INTEGER | Auto-saved Unix timestamp | | date | TEXT | Human-readable date (YYYY-MM-DD) | | hour | TEXT | Human-readable time (HH:MM) | | relays | TEXT | Comma-separated list of relays | | status | TEXT | "pending", "sent", or "failed" | | created_at| INTEGER | Creation timestamp | | updated_at| INTEGER | Last update timestamp | ### Table: sent_messages | Column | Type | Description | |-----------------|---------|---------------------------------------| | id | INTEGER | Unique ID of the message (PK) | | recipient_pubkey| TEXT | The recipient's public key | | message | TEXT | The message content | | timestamp | INTEGER | Unix timestamp of when it was sent | | relays | TEXT | Comma-separated list of relays | | event_id | TEXT | Event ID of the sent message | | created_at | INTEGER | Creation timestamp | ## License This project is licensed under the MIT License - see the LICENSE file for details.