carom-link 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,233 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>carom — Dashboard</title>
7
+ <meta name="description" content="Link redirect server with bot and automated traffic protection">
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
11
+ <link rel="stylesheet" href="style.css">
12
+ </head>
13
+ <body>
14
+ <div class="app">
15
+ <!-- Header -->
16
+ <header class="header">
17
+ <div class="header-left">
18
+ <div class="logo">
19
+ <span class="logo-icon">🛡</span>
20
+ <span class="logo-text">carom</span>
21
+ </div>
22
+ </div>
23
+ <div class="header-right">
24
+ <div class="api-key-group">
25
+ <input type="password" id="apiKeyInput" placeholder="API Key" class="input-sm" autocomplete="off">
26
+ <button id="apiKeyToggle" class="btn-ghost" title="Toggle visibility">👁</button>
27
+ </div>
28
+ <div class="status-badge" id="statusBadge">
29
+ <span class="status-dot"></span>
30
+ <span class="status-text">Connecting...</span>
31
+ </div>
32
+ </div>
33
+ </header>
34
+
35
+ <!-- Navigation -->
36
+ <nav class="nav">
37
+ <button class="nav-btn active" data-tab="links">Links</button>
38
+ <button class="nav-btn" data-tab="create">Create Link</button>
39
+ <button class="nav-btn" data-tab="botpage">Bot Page</button>
40
+ <button class="nav-btn" data-tab="rules">Detection Rules</button>
41
+ <button class="nav-btn" data-tab="test">UA Tester</button>
42
+ </nav>
43
+
44
+ <!-- Main Content -->
45
+ <main class="main">
46
+ <!-- Links Tab -->
47
+ <section class="tab-content active" id="tab-links">
48
+ <div class="section-header">
49
+ <h1>Your Links</h1>
50
+ <div class="section-actions">
51
+ <button class="btn-secondary" id="refreshLinks">↻ Refresh</button>
52
+ </div>
53
+ </div>
54
+ <div class="table-container">
55
+ <table class="data-table" id="linksTable">
56
+ <thead>
57
+ <tr>
58
+ <th>Slug</th>
59
+ <th>Destination</th>
60
+ <th>Human</th>
61
+ <th>Bot</th>
62
+ <th>Created</th>
63
+ <th>Status</th>
64
+ <th>Actions</th>
65
+ </tr>
66
+ </thead>
67
+ <tbody id="linksBody">
68
+ <tr><td colspan="7" class="empty-state">Loading links...</td></tr>
69
+ </tbody>
70
+ </table>
71
+ </div>
72
+ </section>
73
+
74
+ <!-- Create Link Tab -->
75
+ <section class="tab-content" id="tab-create">
76
+ <div class="section-header">
77
+ <h1>Create New Link</h1>
78
+ </div>
79
+ <form id="createForm" class="form-card">
80
+ <div class="form-group">
81
+ <label for="urlInput">Destination URL</label>
82
+ <input type="url" id="urlInput" placeholder="https://example.com/your-page" required class="input-lg">
83
+ </div>
84
+ <div class="form-row">
85
+ <div class="form-group">
86
+ <label for="slugInput">Custom Slug <span class="optional">(optional)</span></label>
87
+ <input type="text" id="slugInput" placeholder="my-custom-slug" pattern="[a-zA-Z0-9_-]+" class="input-lg">
88
+ </div>
89
+ <div class="form-group">
90
+ <label for="expiresInput">Expires <span class="optional">(optional)</span></label>
91
+ <input type="datetime-local" id="expiresInput" class="input-lg">
92
+ </div>
93
+ </div>
94
+ <button type="submit" class="btn-primary" id="createBtn">Create Short Link</button>
95
+ <div id="createResult" class="result-card hidden">
96
+ <div class="result-label">Your short link:</div>
97
+ <div class="result-url" id="resultUrl"></div>
98
+ <button type="button" class="btn-ghost" id="copyBtn">📋 Copy</button>
99
+ </div>
100
+ </form>
101
+ </section>
102
+
103
+ <!-- Rules Tab -->
104
+ <section class="tab-content" id="tab-rules">
105
+ <div class="section-header">
106
+ <h1>Detection Rules</h1>
107
+ <div class="section-actions">
108
+ <button class="btn-secondary" id="refreshRules">↻ Refresh</button>
109
+ </div>
110
+ </div>
111
+ <form id="addRuleForm" class="form-card compact">
112
+ <div class="form-row">
113
+ <div class="form-group">
114
+ <label for="ruleType">Type</label>
115
+ <select id="ruleType" class="input-lg">
116
+ <option value="ua_pattern">UA Pattern</option>
117
+ <option value="ip_range">IP Range</option>
118
+ <option value="asn">ASN</option>
119
+ </select>
120
+ </div>
121
+ <div class="form-group flex-grow">
122
+ <label for="rulePattern">Pattern</label>
123
+ <input type="text" id="rulePattern" placeholder="e.g., CarrierIQ" required class="input-lg">
124
+ </div>
125
+ <div class="form-group">
126
+ <label for="ruleWeight">Weight</label>
127
+ <input type="number" id="ruleWeight" value="30" min="1" max="100" class="input-lg">
128
+ </div>
129
+ <div class="form-group" style="align-self: flex-end;">
130
+ <button type="submit" class="btn-primary">+ Add Rule</button>
131
+ </div>
132
+ </div>
133
+ </form>
134
+ <div class="table-container">
135
+ <table class="data-table" id="rulesTable">
136
+ <thead>
137
+ <tr>
138
+ <th>ID</th>
139
+ <th>Type</th>
140
+ <th>Pattern</th>
141
+ <th>Weight</th>
142
+ <th>Created</th>
143
+ <th>Actions</th>
144
+ </tr>
145
+ </thead>
146
+ <tbody id="rulesBody">
147
+ <tr><td colspan="6" class="empty-state">Loading rules...</td></tr>
148
+ </tbody>
149
+ </table>
150
+ </div>
151
+ </section>
152
+
153
+ <!-- Bot Page Tab -->
154
+ <section class="tab-content" id="tab-botpage">
155
+ <div class="section-header">
156
+ <h1>Bot Page Editor</h1>
157
+ </div>
158
+ <p class="section-description">Customize the page that bots and automated scanners see instead of your real destination. This page is served to any traffic classified as non-human.</p>
159
+ <div class="botpage-layout">
160
+ <form id="botPageForm" class="form-card">
161
+ <div class="form-group">
162
+ <label for="bpBrand">Brand Name</label>
163
+ <input type="text" id="bpBrand" placeholder="YourCompany" class="input-lg">
164
+ <span class="input-hint">Displayed as the page header and in the footer copyright</span>
165
+ </div>
166
+ <div class="form-group">
167
+ <label for="bpTitle">Page Title</label>
168
+ <input type="text" id="bpTitle" placeholder="Welcome" class="input-lg">
169
+ <span class="input-hint">Appears in the browser tab and Open Graph meta tags</span>
170
+ </div>
171
+ <div class="form-group">
172
+ <label for="bpDescription">Page Description</label>
173
+ <textarea id="bpDescription" placeholder="Visit our website for more information." rows="3" class="input-lg"></textarea>
174
+ <span class="input-hint">The main body text on the page and OG/Twitter card description</span>
175
+ </div>
176
+ <div class="form-actions">
177
+ <button type="submit" class="btn-primary" id="saveBotPage">💾 Save Changes</button>
178
+ <button type="button" class="btn-secondary" id="refreshPreview">↻ Refresh Preview</button>
179
+ </div>
180
+ <div id="botPageStatus" class="result-card hidden"></div>
181
+ </form>
182
+ <div class="preview-panel">
183
+ <div class="preview-header">
184
+ <span class="preview-badge">🛡 Live Preview — What bots see</span>
185
+ </div>
186
+ <div class="preview-frame-wrapper">
187
+ <iframe id="botPagePreview" class="preview-frame" sandbox="allow-same-origin"></iframe>
188
+ </div>
189
+ </div>
190
+ </div>
191
+ </section>
192
+
193
+ <!-- Rules Tab -->
194
+
195
+ <!-- UA Tester Tab -->
196
+ <section class="tab-content" id="tab-test">
197
+ <div class="section-header">
198
+ <h1>User-Agent Tester</h1>
199
+ </div>
200
+ <form id="testForm" class="form-card">
201
+ <div class="form-group">
202
+ <label for="testUa">User-Agent String</label>
203
+ <input type="text" id="testUa" placeholder='Mozilla/5.0 (compatible; Googlebot/2.1)' required class="input-lg mono">
204
+ </div>
205
+ <button type="submit" class="btn-primary">Test Against Rules</button>
206
+ <div id="testResult" class="result-card hidden">
207
+ <div class="test-result-header">
208
+ <span class="test-classification" id="testClassification"></span>
209
+ <span class="test-score" id="testScore"></span>
210
+ </div>
211
+ <div class="test-signals" id="testSignals"></div>
212
+ </div>
213
+ </form>
214
+ </section>
215
+ </main>
216
+
217
+ <!-- Link Detail Modal -->
218
+ <div class="modal-overlay hidden" id="statsModal">
219
+ <div class="modal">
220
+ <div class="modal-header">
221
+ <h2 id="statsTitle">Link Stats</h2>
222
+ <button class="btn-ghost modal-close" id="closeStats">✕</button>
223
+ </div>
224
+ <div class="modal-body" id="statsBody">
225
+ Loading...
226
+ </div>
227
+ </div>
228
+ </div>
229
+ </div>
230
+
231
+ <script src="app.js"></script>
232
+ </body>
233
+ </html>