/ clis / discord-app / search.js
search.js
 1  import { cli, Strategy } from '@jackwener/opencli/registry';
 2  export const searchCommand = cli({
 3      site: 'discord-app',
 4      name: 'search',
 5      description: 'Search messages in the current Discord server/channel (Cmd+F)',
 6      domain: 'localhost',
 7      strategy: Strategy.UI,
 8      browser: true,
 9      args: [{ name: 'query', required: true, positional: true, help: 'Search query' }],
10      columns: ['Index', 'Author', 'Message'],
11      func: async (page, kwargs) => {
12          const query = kwargs.query;
13          // Open search with Cmd+F
14          const isMac = process.platform === 'darwin';
15          await page.pressKey(isMac ? 'Meta+F' : 'Control+F');
16          await page.wait(0.5);
17          // Type query into search box
18          await page.evaluate(`
19        (function(q) {
20          const input = document.querySelector('[aria-label*="Search"], [class*="searchBar"] input, [placeholder*="Search"]');
21          if (!input) throw new Error('Search input not found');
22          input.focus();
23          const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;
24          setter.call(input, q);
25          input.dispatchEvent(new Event('input', { bubbles: true }));
26        })(${JSON.stringify(query)})
27      `);
28          await page.pressKey('Enter');
29          await page.wait(2);
30          // Scrape search results
31          const results = await page.evaluate(`
32        (function() {
33          const items = [];
34          const resultNodes = document.querySelectorAll('[class*="searchResult_"], [id*="search-result"]');
35          
36          resultNodes.forEach((node, i) => {
37            const author = node.querySelector('[class*="username"]')?.textContent?.trim() || '—';
38            const content = node.querySelector('[id^="message-content-"], [class*="messageContent"]')?.textContent?.trim() || node.textContent?.trim();
39            items.push({
40              Index: i + 1,
41              Author: author,
42              Message: (content || '').substring(0, 200),
43            });
44          });
45          
46          return items;
47        })()
48      `);
49          // Close search
50          await page.pressKey('Escape');
51          if (results.length === 0) {
52              return [{ Index: 0, Author: 'System', Message: `No results for "${query}"` }];
53          }
54          return results;
55      },
56  });