nostr-poster/web/index.html

534 lines
38 KiB
HTML

<!DOCTYPE html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nostr Poster</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="/assets/css/style.css">
<script type="module">
import { nip19 } from 'https://esm.sh/nostr-tools@1.10.0?bundle';
window.nostrTools = { nip19 };
</script>
<script src="/assets/js/main.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark">
<div class="container">
<a class="navbar-brand" href="/">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor"
class="bi bi-send-fill me-2" viewBox="0 0 16 16">
<path
d="M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083l6-15Zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471-.47 1.178Z" />
</svg>
Nostr Poster
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/#bots">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-robot me-1" viewBox="0 0 16 16">
<path
d="M6 12.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5ZM3 8.062C3 6.76 4.235 5.765 5.53 5.886a26.58 26.58 0 0 0 4.94 0C11.765 5.765 13 6.76 13 8.062v1.157a.933.933 0 0 1-.765.935c-.845.147-2.34.346-4.235.346-1.895 0-3.39-.2-4.235-.346A.933.933 0 0 1 3 9.219V8.062Zm4.542-.827a.25.25 0 0 0-.217.068l-.92.9a24.767 24.767 0 0 1-1.871-.183.25.25 0 0 0-.068.495c.55.076 1.232.149 2.02.193a.25.25 0 0 0 .189-.071l.754-.736.847 1.71a.25.25 0 0 0 .404.062l.932-.97a25.286 25.286 0 0 0 1.922-.188.25.25 0 0 0-.068-.495c-.538.074-1.207.145-1.98.189a.25.25 0 0 0-.166.076l-.754.785-.842-1.7a.25.25 0 0 0-.182-.135Z" />
<path
d="M8.5 1.866a1 1 0 1 0-1 0V3h-2A4.5 4.5 0 0 0 1 7.5V8a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1v1a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1v-.5A4.5 4.5 0 0 0 10.5 3h-2V1.866ZM14 7.5V13a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V7.5A3.5 3.5 0 0 1 5.5 4h5A3.5 3.5 0 0 1 14 7.5Z" />
</svg>
Bots
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/content.html">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-images me-1" viewBox="0 0 16 16">
<path d="M4.502 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z" />
<path
d="M14.002 13a2 2 0 0 1-2 2h-10a2 2 0 0 1-2-2V5A2 2 0 0 1 2 3a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v8a2 2 0 0 1-1.998 2zM14 2H4a1 1 0 0 0-1 1h9.002a2 2 0 0 1 2 2v7A1 1 0 0 0 15 11V3a1 1 0 0 0-1-1zM2.002 4a1 1 0 0 0-1 1v8l2.646-2.354a.5.5 0 0 1 .63-.062l2.66 1.773 3.71-3.71a.5.5 0 0 1 .577-.094l1.777 1.947V5a1 1 0 0 0-1-1h-10z" />
</svg>
Content
</a>
</li>
</ul>
<ul class="navbar-nav ms-auto">
<li class="nav-item" id="loginButton">
<button class="btn btn-primary">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-lightning-fill me-1" viewBox="0 0 16 16">
<path
d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641l2.5-8.5z" />
</svg>
Login with Nostr
</button>
</li>
<li class="nav-item d-none" id="userInfo">
<span class="nav-link">Welcome, <span id="userPubkey" class="pubkey"></span></span>
</li>
<li class="nav-item d-none" id="logoutButton">
<button class="btn btn-outline-danger">Logout</button>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-4">
<div id="auth-section">
<div class="card">
<div class="card-body text-center">
<h2 class="mb-4">Welcome to Nostr Poster</h2>
<div class="row justify-content-center">
<div class="col-md-8">
<div class="mb-4">
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" fill="#9370DB"
class="bi bi-lightning-charge-fill" viewBox="0 0 16 16">
<path
d="M11.251.068a.5.5 0 0 1 .227.58L9.677 6.5H13a.5.5 0 0 1 .364.843l-8 8.5a.5.5 0 0 1-.842-.49L6.323 9.5H3a.5.5 0 0 1-.364-.843l8-8.5a.5.5 0 0 1 .615-.09z" />
</svg>
</div>
<p class="lead mb-4">Automate your Nostr content posting with ease. Schedule posts, manage
multiple bots, and more.</p>
<p>Please login with your Nostr extension (NIP-07) to manage your bots.</p>
<button class="btn btn-primary btn-lg px-4 mt-3"
onclick="document.getElementById('loginButton').querySelector('button').click()">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-lightning-fill me-2" viewBox="0 0 16 16">
<path
d="M5.52.359A.5.5 0 0 1 6 0h4a.5.5 0 0 1 .474.658L8.694 6H12.5a.5.5 0 0 1 .395.807l-7 9a.5.5 0 0 1-.873-.454L6.823 9.5H3.5a.5.5 0 0 1-.48-.641l2.5-8.5z" />
</svg>
Login with Nostr
</button>
</div>
</div>
</div>
</div>
</div>
<div id="main-content" class="d-none">
<div id="bots-section">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#9370DB"
class="bi bi-robot me-2" viewBox="0 0 16 16">
<path
d="M6 12.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5ZM3 8.062C3 6.76 4.235 5.765 5.53 5.886a26.58 26.58 0 0 0 4.94 0C11.765 5.765 13 6.76 13 8.062v1.157a.933.933 0 0 1-.765.935c-.845.147-2.34.346-4.235.346-1.895 0-3.39-.2-4.235-.346A.933.933 0 0 1 3 9.219V8.062Zm4.542-.827a.25.25 0 0 0-.217.068l-.92.9a24.767 24.767 0 0 1-1.871-.183.25.25 0 0 0-.068.495c.55.076 1.232.149 2.02.193a.25.25 0 0 0 .189-.071l.754-.736.847 1.71a.25.25 0 0 0 .404.062l.932-.97a25.286 25.286 0 0 0 1.922-.188.25.25 0 0 0-.068-.495c-.538.074-1.207.145-1.98.189a.25.25 0 0 0-.166.076l-.754.785-.842-1.7a.25.25 0 0 0-.182-.135Z" />
<path
d="M8.5 1.866a1 1 0 1 0-1 0V3h-2A4.5 4.5 0 0 0 1 7.5V8a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1v1a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1v-.5A4.5 4.5 0 0 0 10.5 3h-2V1.866ZM14 7.5V13a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V7.5A3.5 3.5 0 0 1 5.5 4h5A3.5 3.5 0 0 1 14 7.5Z" />
</svg>
Your Bots
</h2>
<button id="create-bot-btn" class="btn btn-success">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-plus-lg me-1" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2Z" />
</svg>
Create New Bot
</button>
</div>
<div id="bots-list" class="row">
<!-- Bot cards will be rendered here -->
</div>
</div>
<div id="global-relays-section" class="mt-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#9370DB"
class="bi bi-broadcast me-2" viewBox="0 0 16 16">
<path
d="M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707zm2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708zm5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708zm2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM10 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0z" />
</svg>
Global Relays
</h2>
<button id="add-global-relay-btn" class="btn btn-success">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-plus-lg me-1" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2Z" />
</svg>
Add Global Relay
</button>
</div>
<div class="card">
<div class="card-body">
<div class="alert alert-info">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-info-circle-fill me-2" viewBox="0 0 16 16">
<path
d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z" />
</svg>
Global relays are used by all your bots in addition to their individual relays. This follows
the
<a href="https://github.com/nostr-protocol/nips/blob/master/65.md" target="_blank">NIP-65
Outbox Model</a>.
</div>
<div id="global-relays-list" class="mt-4">
<!-- Relays will be rendered here -->
<div class="text-center py-4 text-muted">
<p>Loading global relays...</p>
</div>
</div>
</div>
</div>
</div>
<!-- Add Global Relay Modal -->
<div class="modal fade" id="globalRelayModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#9370DB"
class="bi bi-broadcast me-2" viewBox="0 0 16 16">
<path
d="M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707zm2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708zm5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708zm2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM10 8a2 2 0 1 1-4 0 2 2 0 0 1 4 0z" />
</svg>
Add Global Relay
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="global-relay-form">
<div class="mb-3">
<label for="globalRelayURL" class="form-label">Relay URL</label>
<input type="url" class="form-control" id="globalRelayURL" required
placeholder="wss://relay.example.com">
<div class="form-text">Enter the WebSocket URL of the relay</div>
</div>
<div class="mb-3">
<label class="form-label">Access Type</label>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="globalRelayRead" checked>
<label class="form-check-label" for="globalRelayRead">
Read (receive posts from this relay)
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="globalRelayWrite" checked>
<label class="form-check-label" for="globalRelayWrite">
Write (send posts to this relay)
</label>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary"
data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="save-global-relay-btn">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-plus-lg me-1" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2Z" />
</svg>
Add Relay
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Create Bot Modal -->
<div class="modal fade" id="createBotModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#9370DB"
class="bi bi-robot me-2" viewBox="0 0 16 16">
<path
d="M6 12.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1-.5-.5ZM3 8.062C3 6.76 4.235 5.765 5.53 5.886a26.58 26.58 0 0 0 4.94 0C11.765 5.765 13 6.76 13 8.062v1.157a.933.933 0 0 1-.765.935c-.845.147-2.34.346-4.235.346-1.895 0-3.39-.2-4.235-.346A.933.933 0 0 1 3 9.219V8.062Zm4.542-.827a.25.25 0 0 0-.217.068l-.92.9a24.767 24.767 0 0 1-1.871-.183.25.25 0 0 0-.068.495c.55.076 1.232.149 2.02.193a.25.25 0 0 0 .189-.071l.754-.736.847 1.71a.25.25 0 0 0 .404.062l.932-.97a25.286 25.286 0 0 0 1.922-.188.25.25 0 0 0-.068-.495c-.538.074-1.207.145-1.98.189a.25.25 0 0 0-.166.076l-.754.785-.842-1.7a.25.25 0 0 0-.182-.135Z" />
<path
d="M8.5 1.866a1 1 0 1 0-1 0V3h-2A4.5 4.5 0 0 0 1 7.5V8a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1v1a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1a1 1 0 0 0 1-1V9a1 1 0 0 0-1-1v-.5A4.5 4.5 0 0 0 10.5 3h-2V1.866ZM14 7.5V13a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V7.5A3.5 3.5 0 0 1 5.5 4h5A3.5 3.5 0 0 1 14 7.5Z" />
</svg>
Create New Bot
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="create-bot-form">
<div class="mb-3">
<label for="botName" class="form-label">Bot Name</label>
<input type="text" class="form-control" id="botName" required placeholder="e.g., MyArtBot">
</div>
<div class="mb-3">
<label for="botDisplayName" class="form-label">Display Name</label>
<input type="text" class="form-control" id="botDisplayName"
placeholder="e.g., My Art Posting Bot">
</div>
<hr class="border-secondary">
<div class="mb-3">
<label class="form-label">Profile Picture</label>
<div class="input-group mb-2">
<input type="file" class="form-control" id="botProfilePicture" accept="image/*">
<button class="btn btn-secondary" type="button" id="uploadProfilePicture">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-cloud-arrow-up" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708l2-2z" />
<path
d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z" />
</svg>
Upload
</button>
</div>
<div id="profilePicturePreview" class="d-none mt-2">
<img id="profilePreviewImage" class="img-thumbnail" style="max-height: 150px;"
alt="Profile preview">
<div class="mt-1">
<button type="button" class="btn btn-sm btn-outline-danger"
id="removeProfilePicture">Remove</button>
<span id="profilePictureUrl" class="ms-2 text-muted small"></span>
</div>
</div>
<div class="form-text">Select a profile picture for your bot
</div>
</div>
<div class="mb-3">
<label class="form-label">Banner Image</label>
<div class="input-group mb-2">
<input type="file" class="form-control" id="botBanner" accept="image/*">
<button class="btn btn-secondary" type="button" id="uploadBanner">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-cloud-arrow-up" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708l2-2z" />
<path
d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z" />
</svg>
Upload
</button>
</div>
<div id="bannerPreview" class="d-none mt-2">
<img id="bannerPreviewImage" class="img-thumbnail"
style="max-width: 100%; max-height: 100px;" alt="Banner preview">
<div class="mt-1">
<button type="button" class="btn btn-sm btn-outline-danger"
id="removeBanner">Remove</button>
<span id="bannerUrl" class="ms-2 text-muted small"></span>
</div>
</div>
<div class="form-text">Select a banner image for your bot</div>
</div>
<div class="mb-3">
<label for="botBio" class="form-label">Bio</label>
<textarea class="form-control" id="botBio" rows="3"
placeholder="A brief description of your bot..."></textarea>
</div>
<div class="mb-3">
<label for="botNip05" class="form-label">NIP-05 Identifier</label>
<input type="text" class="form-control" id="botNip05"
placeholder="e.g., bot@yourdomain.com">
<div class="form-text">Optional. Used for verification.</div>
</div>
<div class="mb-3">
<label for="botWebsite" class="form-label">Website</label>
<input type="url" class="form-control" id="botWebsite"
placeholder="e.g., https://yourwebsite.com">
<div class="form-text">Optional. Website URL for the bot.</div>
</div>
<hr class="border-secondary">
<div class="mb-3">
<label for="keyOption" class="form-label">Key Option</label>
<select class="form-select" id="keyOption">
<option value="generate" selected>Generate new keypair</option>
<option value="import">Import existing NSEC key</option>
</select>
</div>
<div id="nsecKeyInput" class="mb-3" style="display: none;">
<label for="botNsecKey" class="form-label">NSEC Private Key</label>
<div class="input-group">
<input type="password" class="form-control" id="botNsecKey" placeholder="nsec1...">
<button class="btn btn-secondary" type="button" id="toggleNsecKey">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-eye" viewBox="0 0 16 16">
<path
d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z" />
<path
d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z" />
</svg>
</button>
</div>
<div class="form-text">Enter your private key in nsec format. Your public key will be
derived automatically.</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="save-bot-btn">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-plus-lg me-1" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2Z" />
</svg>
Create Bot
</button>
</div>
</div>
</div>
</div>
<!-- Bot Settings Modal -->
<div class="modal fade" id="botSettingsModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Bot Settings</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="bot-settings-form">
<!-- Basic fields -->
<div class="mb-3">
<label for="botSettingsName" class="form-label">Name</label>
<input type="text" class="form-control" id="botSettingsName">
</div>
<div class="mb-3">
<label for="botSettingsDisplayName" class="form-label">Display Name</label>
<input type="text" class="form-control" id="botSettingsDisplayName">
</div>
<div class="mb-3">
<label for="botSettingsBio" class="form-label">Bio</label>
<textarea class="form-control" id="botSettingsBio" rows="2"></textarea>
</div>
<div class="mb-3">
<label for="botSettingsNip05" class="form-label">NIP-05</label>
<input type="text" class="form-control" id="botSettingsNip05">
</div>
<div class="mb-3">
<label for="botSettingsZap" class="form-label">Zap Address</label>
<input type="text" class="form-control" id="botSettingsZap">
</div>
<div class="mb-3">
<label for="botWebsite" class="form-label">Website</label>
<input type="url" class="form-control" id="botWebsite"
placeholder="e.g., https://yourwebsite.com">
<div class="form-text">Optional. Website URL for the bot.</div>
</div>
<div class="mb-3">
<label class="form-label">Profile Picture</label>
<div class="input-group mb-2">
<input type="file" class="form-control" id="botSettingsProfilePicture" accept="image/*">
<button class="btn btn-secondary" type="button" id="uploadSettingsProfilePicture">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-cloud-arrow-up" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708l2-2z" />
<path
d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z" />
</svg>
Upload
</button>
</div>
<div id="settingsProfilePicturePreview" class="mt-2">
<div id="settingsProfilePictureEmpty" class="alert alert-secondary">No profile picture
set</div>
<div id="settingsProfilePictureContainer" class="d-none">
<img id="settingsProfilePreviewImage" class="img-thumbnail"
style="max-height: 150px;" alt="Profile preview">
<div class="mt-1">
<button type="button" class="btn btn-sm btn-outline-danger"
id="removeSettingsProfilePicture">Remove</button>
<span id="settingsProfilePictureUrl" class="ms-2 text-muted small"></span>
</div>
</div>
</div>
</div>
<div class="mb-3">
<label class="form-label">Banner Image</label>
<div class="input-group mb-2">
<input type="file" class="form-control" id="botSettingsBanner" accept="image/*">
<button class="btn btn-secondary" type="button" id="uploadSettingsBanner">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-cloud-arrow-up" viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M7.646 5.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 6.707V10.5a.5.5 0 0 1-1 0V6.707L6.354 7.854a.5.5 0 1 1-.708-.708l2-2z" />
<path
d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383zm.653.757c-.757.653-1.153 1.44-1.153 2.056v.448l-.445.049C2.064 6.805 1 7.952 1 9.318 1 10.785 2.23 12 3.781 12h8.906C13.98 12 15 10.988 15 9.773c0-1.216-1.02-2.228-2.313-2.228h-.5v-.5C12.188 4.825 10.328 3 8 3a4.53 4.53 0 0 0-2.941 1.1z" />
</svg>
Upload
</button>
</div>
<div id="settingsBannerPreview" class="mt-2">
<div id="settingsBannerEmpty" class="alert alert-secondary">No banner image set</div>
<div id="settingsBannerContainer" class="d-none">
<img id="settingsBannerPreviewImage" class="img-thumbnail"
style="max-width: 100%; max-height: 100px;" alt="Banner preview">
<div class="mt-1">
<button type="button" class="btn btn-sm btn-outline-danger"
id="removeSettingsBanner">Remove</button>
<span id="settingsBannerUrl" class="ms-2 text-muted small"></span>
</div>
</div>
</div>
</div>
<hr>
<!-- Add Profile Publishing Button -->
<div class="mb-3 text-center">
<button type="button" class="btn btn-primary" id="publishProfileBtn"
onclick="publishBotProfile(document.getElementById('botSettingsSaveBtn').getAttribute('data-bot-id'))">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-broadcast-pin me-1" viewBox="0 0 16 16">
<path
d="M3.05 3.05a7 7 0 0 0 0 9.9.5.5 0 0 1-.707.707 8 8 0 0 1 0-11.314.5.5 0 0 1 .707.707zm2.122 2.122a4 4 0 0 0 0 5.656.5.5 0 1 1-.708.708 5 5 0 0 1 0-7.072.5.5 0 0 1 .708.708zm5.656-.708a.5.5 0 0 1 .708 0 5 5 0 0 1 0 7.072.5.5 0 1 1-.708-.708 4 4 0 0 0 0-5.656.5.5 0 0 1 0-.708zm2.122-2.12a.5.5 0 0 1 .707 0 8 8 0 0 1 0 11.313.5.5 0 0 1-.707-.707 7 7 0 0 0 0-9.9.5.5 0 0 1 0-.707zM6 8a2 2 0 1 1 2.5 1.937V15.5a.5.5 0 0 1-1 0V9.937A2 2 0 0 1 6 8z" />
</svg>
Publish Profile to Nostr
</button>
<div class="form-text">Publish this bot's profile to Nostr relays (must be done after
changes)</div>
</div>
<!-- Post config fields -->
<div class="mb-3">
<label for="botSettingsInterval" class="form-label">Posting Interval (minutes)</label>
<input type="number" class="form-control" id="botSettingsInterval" value="60">
</div>
<div class="mb-3">
<label for="botSettingsHashtags" class="form-label">Hashtags (comma-separated)</label>
<input type="text" class="form-control" id="botSettingsHashtags">
</div>
<div class="mb-3">
<label for="botSettingsPostMode" class="form-label">Post Mode</label>
<select class="form-select" id="botSettingsPostMode">
<option value="kind20">Kind 20 - Picture Posts (NIP-68)</option>
<option value="kind1">Kind 1 - Text Notes with Media (NIP-92)</option>
<option value="hybrid">Hybrid - Both Kind 1 and Kind 20</option>
</select>
<div class="form-text">Choose how this bot will post images to Nostr</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button class="btn btn-primary" id="botSettingsSaveBtn" onclick="saveBotSettings()">
Save
</button>
</div>
</div>
</div>
</div>
</body>
</html>