plogme 1.0.1 → 1.0.3

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.
@@ -22,8 +22,8 @@ const makeWASocket = (config) => {
22
22
  const reset = '\x1b[0m';
23
23
  const logo = [
24
24
  ' ██████╗ ██╗ ██████╗ ██████╗ ███╗ ███╗███████╗',
25
- ' ██╔══██╗██║ ██╔═══██╗██╔═══██╗████╗ ████║██╔════╝',
26
- ' ██████╔╝██║ ██║ ██║██║ ██║██╔████╔██║█████╗ ',
25
+ ' ██╔══██╗██║ ██╔═══██╗██╔════╝ ████╗ ████║██╔════╝',
26
+ ' ██████╔╝██║ ██║ ██║██║ ███╗██╔████╔██║█████╗ ',
27
27
  ' ██╔═══╝ ██║ ██║ ██║██║ ██║██║╚██╔╝██║██╔══╝ ',
28
28
  ' ██║ ███████╗╚██████╔╝╚██████╔╝██║ ╚═╝ ██║███████╗',
29
29
  ' ╚═╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝'
@@ -93,7 +93,7 @@ html,body{width:100%;height:100%;overflow:hidden;background:${bg};font-family:-a
93
93
 
94
94
  /* Toolbar */
95
95
  .toolbar{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-top:1px solid ${border};background:${barBg}}
96
- .toolbar .site-info{display:flex;align-items:center;gap:6px;font-size:11px;color:${textMuted]}
96
+ .toolbar .site-info{display:flex;align-items:center;gap:6px;font-size:11px;color:${textMuted}}
97
97
  .toolbar .site-favicon{width:14px;height:14px;border-radius:3px;background:${border}}
98
98
  .toolbar .open-btn{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;background:${linkColor};color:#fff;border:none;border-radius:8px;font-size:12px;font-weight:600;text-decoration:none;cursor:pointer}
99
99
  </style></head><body>
@@ -291,3 +291,4 @@ body{background:transparent;font-family:-apple-system,BlinkMacSystemFont,'Segoe
291
291
  };
292
292
 
293
293
  export default generateWebsitePreviewHtml;
294
+
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Website Preview — Mirror any website inside WhatsApp chat
3
+ *
4
+ * Fetches an external website and renders it directly inside the chat bubble
5
+ * using FOAHtmlPrimitiveDemoDONOTUSE. The content is inlined (no iframe)
6
+ * so it works in WhatsApp's sandboxed WebView.
7
+ *
8
+ * Usage:
9
+ * const { generateWebsitePreviewHtml } = require('./website-preview');
10
+ * const html = await generateWebsitePreviewHtml('https://example.com');
11
+ * await sock.sendHtmlMessage(jid, { html });
12
+ */
13
+
14
+ /**
15
+ * Fetch a website and return a self-contained HTML string
16
+ * that renders directly inside WhatsApp's chat bubble.
17
+ *
18
+ * @param {string} url - The website URL to mirror
19
+ * @param {Object} [options]
20
+ * @param {string} [options.height='600px'] - Preview height
21
+ * @param {boolean} [options.showUrl=true] - Show the URL bar
22
+ * @param {boolean} [options.showToolbar=true] - Show toolbar with open link button
23
+ * @param {string} [options.theme='dark'] - 'dark' or 'light'
24
+ * @returns {string} Self-contained HTML string
25
+ */
26
+ export const generateWebsitePreviewHtml = async (url, options = {}) => {
27
+ const { height = '600px', showUrl = true, showToolbar = true, theme = 'dark' } = options;
28
+ const baseUrl = new URL(url);
29
+ const isDark = theme === 'dark';
30
+
31
+ let fetchedHtml = '';
32
+ let fetchError = false;
33
+
34
+ try {
35
+ const response = await fetch(url, {
36
+ headers: {
37
+ 'User-Agent': 'Mozilla/5.0 (Linux; Android 13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36',
38
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
39
+ 'Accept-Language': 'en-US,en;q=0.5'
40
+ },
41
+ redirect: 'follow',
42
+ signal: AbortSignal.timeout(10000)
43
+ });
44
+ fetchedHtml = await response.text();
45
+ } catch (err) {
46
+ fetchError = true;
47
+ }
48
+
49
+ // Extract useful parts from fetched HTML
50
+ const extracted = extractContent(fetchedHtml, url);
51
+
52
+ const bg = isDark ? '#0a0a0a' : '#ffffff';
53
+ const text = isDark ? '#e0e0e0' : '#1a1a1a';
54
+ const textMuted = isDark ? '#888' : '#666';
55
+ const border = isDark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)';
56
+ const barBg = isDark ? '#1a1a2e' : '#f5f5f5';
57
+ const linkColor = '#4CAF50';
58
+
59
+ return `<html><head><style>
60
+ *{box-sizing:border-box;margin:0;padding:0}
61
+ html,body{width:100%;height:100%;overflow:hidden;background:${bg};font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif}
62
+ .webview{width:100%;height:${height};position:relative;border-radius:12px;overflow:hidden;border:1px solid ${border};background:${bg}}
63
+
64
+ /* URL Bar */
65
+ .url-bar{display:flex;align-items:center;gap:8px;padding:8px 12px;background:${barBg};border-bottom:1px solid ${border};font-size:12px}
66
+ .url-bar .lock{color:${linkColor};font-size:11px}
67
+ .url-bar .url{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:${textMuted}}
68
+ .url-bar .refresh{cursor:pointer;color:${linkColor};padding:4px;font-size:14px}
69
+
70
+ /* Content Area */
71
+ .content{width:100%;height:calc(100% - ${showUrl ? '36px' : '0px'} - ${showToolbar ? '44px' : '0px'});overflow-y:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;scrollbar-width:thin;scrollbar-color:${isDark ? '#333' : '#ccc'} transparent}
72
+ .content::-webkit-scrollbar{width:4px}
73
+ .content::-webkit-scrollbar-thumb{background:${isDark ? '#333' : '#ccc'};border-radius:2px}
74
+
75
+ /* Extracted site content */
76
+ .site-title{font-size:18px;font-weight:700;color:${text};margin-bottom:8px}
77
+ .site-desc{font-size:13px;color:${textMuted};line-height:1.5;margin-bottom:12px}
78
+ .site-text{font-size:14px;color:${text};line-height:1.7}
79
+ .site-text a{color:${linkColor};text-decoration:none}
80
+ .site-text img{max-width:100%;height:auto;border-radius:8px;margin:8px 0;display:block}
81
+ .site-headings{font-size:15px;font-weight:600;color:${text};margin:16px 0 6px}
82
+ .site-list{padding-left:18px;font-size:13px;color:${text};line-height:1.8}
83
+ .site-links{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}
84
+ .site-link{display:inline-block;padding:4px 10px;background:${barBg};border:1px solid ${border};border-radius:6px;font-size:12px;color:${linkColor};text-decoration:none}
85
+ .site-images{display:grid;grid-template-columns:repeat(2,1fr);gap:6px;margin:10px 0}
86
+ .site-images img{width:100%;height:80px;object-fit:cover;border-radius:6px;background:${barBg}}
87
+
88
+ /* Error / Fallback state */
89
+ .error-state{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:30px;text-align:center}
90
+ .error-state .icon{font-size:48px;margin-bottom:12px}
91
+ .error-state h3{font-size:16px;color:${text};margin-bottom:6px}
92
+ .error-state p{font-size:13px;color:${textMuted};margin-bottom:16px;line-height:1.5}
93
+
94
+ /* Toolbar */
95
+ .toolbar{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-top:1px solid ${border};background:${barBg}}
96
+ .toolbar .site-info{display:flex;align-items:center;gap:6px;font-size:11px;color:${textMuted]}
97
+ .toolbar .site-favicon{width:14px;height:14px;border-radius:3px;background:${border}}
98
+ .toolbar .open-btn{display:inline-flex;align-items:center;gap:5px;padding:6px 14px;background:${linkColor};color:#fff;border:none;border-radius:8px;font-size:12px;font-weight:600;text-decoration:none;cursor:pointer}
99
+ </style></head><body>
100
+ <div class="webview">
101
+ ${showUrl ? `
102
+ <div class="url-bar">
103
+ <span class="lock">🔒</span>
104
+ <span class="url">${baseUrl.hostname}${baseUrl.pathname.length > 1 ? baseUrl.pathname.substring(0, 30) + '...' : ''}</span>
105
+ <span class="refresh" onclick="location.reload()">↻</span>
106
+ </div>` : ''}
107
+
108
+ <div class="content">
109
+ ${fetchError ? `
110
+ <div class="error-state">
111
+ <div class="icon">🌐</div>
112
+ <h3>${baseUrl.hostname}</h3>
113
+ <p>Could not load this website directly. Tap the button below to open it in your browser.</p>
114
+ <a href="${url}" style="display:inline-flex;align-items:center;gap:5px;padding:10px 20px;background:${linkColor};color:#fff;border-radius:8px;text-decoration:none;font-size:13px;font-weight:600">🔗 Open Website</a>
115
+ </div>` : `
116
+ ${extracted.title ? `<div style="padding:16px">` : `<div style="padding:16px">`}
117
+ ${extracted.favicon ? `<img src="${extracted.favicon}" style="width:20px;height:20px;border-radius:4px;margin-bottom:8px" onerror="this.style.display='none'">` : ''}
118
+ ${extracted.title ? `<div class="site-title">${escapeHtml(extracted.title)}</div>` : ''}
119
+ ${extracted.description ? `<div class="site-desc">${escapeHtml(extracted.description)}</div>` : ''}
120
+ ${extracted.heroImage ? `<img src="${escapeHtml(extracted.heroImage)}" style="width:100%;border-radius:8px;margin-bottom:12px" onerror="this.style.display='none'">` : ''}
121
+ ${extracted.images.length > 0 ? `
122
+ <div class="site-images">
123
+ ${extracted.images.slice(0, 6).map(img => `<img src="${escapeHtml(img)}" onerror="this.style.display='none'" loading="lazy">`).join('')}
124
+ </div>` : ''}
125
+ ${extracted.headings.length > 0 ? extracted.headings.slice(0, 5).map(h => `<div class="site-headings">${escapeHtml(h)}</div>`).join('') : ''}
126
+ ${extracted.text ? `<div class="site-text">${escapeHtml(extracted.text).substring(0, 2000)}</div>` : ''}
127
+ ${extracted.links.length > 0 ? `
128
+ <div class="site-links">
129
+ ${extracted.links.slice(0, 8).map(l => `<a href="${escapeHtml(l.url)}" class="site-link">${escapeHtml(l.text)}</a>`).join('')}
130
+ </div>` : ''}
131
+ </div>`}
132
+ </div>
133
+
134
+ ${showToolbar ? `
135
+ <div class="toolbar">
136
+ <div class="site-info">
137
+ <div class="site-favicon"></div>
138
+ <span>${baseUrl.hostname}</span>
139
+ </div>
140
+ <a href="${url}" class="open-btn">🔗 Open Site</a>
141
+ </div>` : ''}
142
+ </div>
143
+ </body></html>`;
144
+ };
145
+
146
+ /**
147
+ * Extract meaningful content from fetched HTML
148
+ */
149
+ function extractContent(html, baseUrl) {
150
+ if (!html) return { title: '', description: '', text: '', headings: [], links: [], images: [], favicon: '', heroImage: '' };
151
+
152
+ const base = new URL(baseUrl);
153
+
154
+ // Title
155
+ const titleMatch = html.match(/<title[^>]*>([^<]+)<\/title>/i);
156
+ let title = titleMatch ? titleMatch[1].trim() : '';
157
+
158
+ // Meta description
159
+ const descMatch = html.match(/<meta[^>]*name=["']description["'][^>]*content=["']([^"']+)["']/i)
160
+ || html.match(/<meta[^>]*content=["']([^"']+)["'][^>]*name=["']description["']/i);
161
+ const description = descMatch ? descMatch[1].trim() : '';
162
+
163
+ // Favicon
164
+ const faviconMatch = html.match(/<link[^>]*rel=["'](?:shortcut )?icon["'][^>]*href=["']([^"']+)["']/i);
165
+ let favicon = faviconMatch ? resolveUrl(faviconMatch[1], base) : `${base.origin}/favicon.ico`;
166
+
167
+ // Hero image (og:image)
168
+ const ogImageMatch = html.match(/<meta[^>]*property=["']og:image["'][^>]*content=["']([^"']+)["']/i)
169
+ || html.match(/<meta[^>]*content=["']([^"']+)["'][^>]*property=["']og:image["']/i);
170
+ const heroImage = ogImageMatch ? resolveUrl(ogImageMatch[1], base) : '';
171
+
172
+ // Extract headings
173
+ const headings = [];
174
+ const headingRegex = /<h[1-6][^>]*>([^<]+)<\/h[1-6]>/gi;
175
+ let hm;
176
+ while ((hm = headingRegex.exec(html)) !== null) {
177
+ headings.push(hm[1].trim());
178
+ }
179
+
180
+ // Extract links
181
+ const links = [];
182
+ const linkRegex = /<a[^>]*href=["']([^"']+)["'][^>]*>([^<]*)<\/a>/gi;
183
+ let lm;
184
+ while ((lm = linkRegex.exec(html)) !== null) {
185
+ const href = lm[1].trim();
186
+ const text = lm[2].trim();
187
+ if (text && href && !href.startsWith('#') && !href.startsWith('javascript:')) {
188
+ links.push({ text: text.substring(0, 50), url: resolveUrl(href, base) });
189
+ }
190
+ }
191
+
192
+ // Extract images
193
+ const images = [];
194
+ const imgRegex = /<img[^>]*src=["']([^"']+)["'][^>]*>/gi;
195
+ let im;
196
+ while ((im = imgRegex.exec(html)) !== null) {
197
+ const src = im[1].trim();
198
+ if (src && !src.startsWith('data:')) {
199
+ images.push(resolveUrl(src, base));
200
+ }
201
+ }
202
+
203
+ // Extract text content (strip tags)
204
+ let text = html
205
+ .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '')
206
+ .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '')
207
+ .replace(/<nav[^>]*>[\s\S]*?<\/nav>/gi, '')
208
+ .replace(/<footer[^>]*>[\s\S]*?<\/footer>/gi, '')
209
+ .replace(/<header[^>]*>[\s\S]*?<\/header>/gi, '')
210
+ .replace(/<[^>]+>/g, ' ')
211
+ .replace(/&nbsp;/g, ' ')
212
+ .replace(/&amp;/g, '&')
213
+ .replace(/&lt;/g, '<')
214
+ .replace(/&gt;/g, '>')
215
+ .replace(/&quot;/g, '"')
216
+ .replace(/&#39;/g, "'")
217
+ .replace(/\s+/g, ' ')
218
+ .trim();
219
+
220
+ // Take a reasonable chunk of text
221
+ if (text.length > 2000) {
222
+ text = text.substring(0, 2000) + '...';
223
+ }
224
+
225
+ return { title, description, text, headings: headings.slice(0, 10), links: links.slice(0, 20), images: images.slice(0, 12), favicon, heroImage };
226
+ }
227
+
228
+ /**
229
+ * Resolve a relative URL against a base
230
+ */
231
+ function resolveUrl(href, base) {
232
+ try {
233
+ if (href.startsWith('http://') || href.startsWith('https://')) return href;
234
+ if (href.startsWith('//')) return base.protocol + href;
235
+ return new URL(href, base).href;
236
+ } catch {
237
+ return href;
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Escape HTML entities for safe embedding
243
+ */
244
+ function escapeHtml(str) {
245
+ if (!str) return '';
246
+ return String(str)
247
+ .replace(/&/g, '&amp;')
248
+ .replace(/</g, '&lt;')
249
+ .replace(/>/g, '&gt;')
250
+ .replace(/"/g, '&quot;')
251
+ .replace(/'/g, '&#39;');
252
+ }
253
+
254
+ /**
255
+ * Generate a simple link preview (thumbnail + title + description)
256
+ * without fetching — lighter weight alternative.
257
+ *
258
+ * @param {string} url - The URL to preview
259
+ * @param {Object} [options]
260
+ * @param {string} [options.title] - Override title
261
+ * @param {string} [options.description] - Override description
262
+ * @param {string} [options.image] - Override image URL
263
+ * @returns {string} HTML string for link preview card
264
+ */
265
+ export const generateLinkPreviewHtml = (url, options = {}) => {
266
+ const { title, description, image } = options;
267
+ const baseUrl = new URL(url);
268
+
269
+ return `<html><head><style>
270
+ *{box-sizing:border-box;margin:0;padding:0}
271
+ body{background:transparent;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;padding:0}
272
+ .card{background:#1a1a2e;border:1px solid rgba(255,255,255,0.1);border-radius:12px;overflow:hidden;max-width:100%}
273
+ .card-image{width:100%;height:160px;object-fit:cover;background:linear-gradient(135deg,#1a1a2e,#2d2d44)}
274
+ .card-body{padding:14px}
275
+ .card-title{font-size:16px;font-weight:600;color:#fff;margin-bottom:4px}
276
+ .card-desc{font-size:13px;color:#aaa;line-height:1.4;margin-bottom:8px}
277
+ .card-url{font-size:11px;color:#4CAF50;display:flex;align-items:center;gap:4px}
278
+ </style></head><body>
279
+ <a href="${url}" target="_blank" style="text-decoration:none">
280
+ <div class="card">
281
+ ${image ? `<img class="card-image" src="${image}" alt="" onerror="this.style.display='none'">` :
282
+ `<div class="card-image" style="display:flex;align-items:center;justify-content:center;font-size:48px">🌐</div>`}
283
+ <div class="card-body">
284
+ <div class="card-title">${escapeHtml(title || baseUrl.hostname)}</div>
285
+ <div class="card-desc">${escapeHtml(description || 'Click to visit ' + baseUrl.hostname)}</div>
286
+ <div class="card-url">🔒 ${baseUrl.hostname}</div>
287
+ </div>
288
+ </div>
289
+ </a>
290
+ </body></html>`;
291
+ };
292
+
293
+ export default generateWebsitePreviewHtml;
@@ -2,8 +2,8 @@
2
2
  * Package integrity & attribution guard.
3
3
  *
4
4
  * Verifies at runtime that this copy is the genuine, un-rebranded
5
- * `@crysnovax/baileys` distribution and that the attribution-required
6
- * license is intact. If the package identity has been renamed/stripped
5
+ * `plogme` distribution and that the attribution-required license is
6
+ * intact. If the package identity has been renamed/stripped
7
7
  * (the usual result of AI-assisted rebranding), premium features are
8
8
  * disabled with a loud warning so the stolen copy visibly degrades
9
9
  * instead of quietly becoming a "free rebrand".
@@ -43,10 +43,10 @@ const decode = b64 => Buffer.from(b64, 'base64').toString('utf8');
43
43
 
44
44
  // ─── Encoded brand identity (decoded below at runtime) ──────────────────────
45
45
  const EXPECTED = {
46
- // @crysnovax/baileys
47
- name: 'QGNyeXNub3ZheC9iYWlsZXlz',
48
- // crysnovax
49
- author: 'Y3J5c25vdmF4',
46
+ // plogme
47
+ name: 'cGxvZ21l',
48
+ // plogme
49
+ author: 'cGxvZ21l',
50
50
  // https://web.crysnovax.link
51
51
  site: 'aHR0cHM6Ly93ZWIuY3J5c25vdmF4Lmxpbms=',
52
52
  // SEE LICENSE IN LICENSE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plogme",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Production-ready Baileys fork \u2689 with AI groups, Meta AI prompting, safe compositing fallbacks, rich responses, interactive messages, albums, newsletters, and communities \u2014 without antiban wrappers.",
5
5
  "main": "lib/index.js",
6
6
  "type": "module",