Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/clis/reddit/comment.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page, kwargs) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required');

await page.goto('https://www.reddit.com');

Expand Down
3 changes: 2 additions & 1 deletion src/clis/reddit/save.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page, kwargs) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required');

await page.goto('https://www.reddit.com');

Expand Down
8 changes: 6 additions & 2 deletions src/clis/reddit/saved.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AuthRequiredError, CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand All @@ -12,7 +13,7 @@ cli({
],
columns: ['title', 'subreddit', 'score', 'comments', 'url'],
func: async (page, kwargs) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required');

await page.goto('https://www.reddit.com');

Expand Down Expand Up @@ -41,7 +42,10 @@ cli({
}
})()`);

if (result?.error) throw new Error(result.error);
if (result?.error) {
if (String(result.error).includes('Not logged in')) throw new AuthRequiredError('reddit.com', result.error);
throw new CommandExecutionError(result.error);
}
return (result || []).slice(0, kwargs.limit);
}
});
3 changes: 2 additions & 1 deletion src/clis/reddit/subscribe.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page, kwargs) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required');

await page.goto('https://www.reddit.com');

Expand Down
3 changes: 2 additions & 1 deletion src/clis/reddit/upvote.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page, kwargs) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required');

await page.goto('https://www.reddit.com');

Expand Down
8 changes: 6 additions & 2 deletions src/clis/reddit/upvoted.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AuthRequiredError, CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand All @@ -12,7 +13,7 @@ cli({
],
columns: ['title', 'subreddit', 'score', 'comments', 'url'],
func: async (page, kwargs) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required');

await page.goto('https://www.reddit.com');

Expand Down Expand Up @@ -41,7 +42,10 @@ cli({
}
})()`);

if (result?.error) throw new Error(result.error);
if (result?.error) {
if (String(result.error).includes('Not logged in')) throw new AuthRequiredError('reddit.com', result.error);
throw new CommandExecutionError(result.error);
}
return (result || []).slice(0, kwargs.limit);
}
});
5 changes: 3 additions & 2 deletions src/clis/substack/search.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

type SubstackPostResult = {
Expand Down Expand Up @@ -32,7 +33,7 @@ async function searchPosts(keyword: string, limit: number): Promise<SubstackPost
url.searchParams.set('includePlatformResults', 'true');

const resp = await fetch(url, { headers: headers() });
if (!resp.ok) throw new Error(`Substack post search failed: HTTP ${resp.status}`);
if (!resp.ok) throw new CommandExecutionError(`Substack post search failed: HTTP ${resp.status}`);

const data = await resp.json() as { results?: any[] };
const results = Array.isArray(data?.results) ? data.results : [];
Expand All @@ -52,7 +53,7 @@ async function searchPublications(keyword: string, limit: number): Promise<Subst
url.searchParams.set('page', '0');

const resp = await fetch(url, { headers: headers() });
if (!resp.ok) throw new Error(`Substack publication search failed: HTTP ${resp.status}`);
if (!resp.ok) throw new CommandExecutionError(`Substack publication search failed: HTTP ${resp.status}`);

const data = await resp.json() as { results?: any[] };
const results = Array.isArray(data?.results) ? data.results : [];
Expand Down
5 changes: 3 additions & 2 deletions src/clis/substack/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import type { IPage } from '../../types.js';

export function buildSubstackBrowseUrl(category?: string): string {
Expand All @@ -7,7 +8,7 @@ export function buildSubstackBrowseUrl(category?: string): string {
}

export async function loadSubstackFeed(page: IPage, url: string, limit: number): Promise<any[]> {
if (!page) throw new Error('Requires browser session');
if (!page) throw new CommandExecutionError('Browser session required for substack feed');
await page.goto(url);
await page.wait(5);
const data = await page.evaluate(`
Expand Down Expand Up @@ -76,7 +77,7 @@ export async function loadSubstackFeed(page: IPage, url: string, limit: number):
}

export async function loadSubstackArchive(page: IPage, baseUrl: string, limit: number): Promise<any[]> {
if (!page) throw new Error('Requires browser session');
if (!page) throw new CommandExecutionError('Browser session required for substack archive');
await page.goto(`${baseUrl}/archive`);
await page.wait(5);
const data = await page.evaluate(`
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/accept.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand All @@ -15,7 +16,7 @@ cli({
],
columns: ['index', 'status', 'user', 'message'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter accept');

const keywords: string[] = kwargs.query.split(',').map((k: string) => k.trim()).filter(Boolean);
const maxAccepts: number = kwargs.max ?? 20;
Expand Down
4 changes: 3 additions & 1 deletion src/clis/twitter/article.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AuthRequiredError, CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand Down Expand Up @@ -153,7 +154,8 @@ cli({
`);

if (result?.error) {
throw new Error(result.error + (result.hint ? ` (${result.hint})` : ''));
if (String(result.error).includes('No ct0 cookie')) throw new AuthRequiredError('x.com', result.error);
throw new CommandExecutionError(result.error + (result.hint ? ` (${result.hint})` : ''));
}

return result || [];
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/block.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter block');
const username = kwargs.username.replace(/^@/, '');

await page.goto(`https://x.com/${username}`);
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/bookmark.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter bookmark');

await page.goto(kwargs.url);
await page.wait(5);
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/follow.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter follow');
const username = kwargs.username.replace(/^@/, '');

await page.goto(`https://x.com/${username}`);
Expand Down
5 changes: 3 additions & 2 deletions src/clis/twitter/followers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AuthRequiredError, SelectorError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand Down Expand Up @@ -26,7 +27,7 @@ cli({
}`);

if (!href) {
throw new Error('Could not find logged-in user profile link. Are you logged in?');
throw new AuthRequiredError('x.com', 'Could not find logged-in user profile link. Are you logged in?');
}
targetUser = href.replace('/', '');
}
Expand Down Expand Up @@ -55,7 +56,7 @@ cli({
return false;
}`);
if (!clicked) {
throw new Error('Could not find followers link on profile page. Twitter may have changed the layout.');
throw new SelectorError('Twitter followers link', 'Twitter may have changed the layout.');
}
await page.wait(5);

Expand Down
5 changes: 3 additions & 2 deletions src/clis/twitter/following.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AuthRequiredError, SelectorError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand Down Expand Up @@ -26,7 +27,7 @@ cli({
}`);

if (!href) {
throw new Error('Could not find logged-in user profile link. Are you logged in?');
throw new AuthRequiredError('x.com', 'Could not find logged-in user profile link. Are you logged in?');
}
targetUser = href.replace('/', '');
}
Expand All @@ -48,7 +49,7 @@ cli({
return false;
}`);
if (!clicked) {
throw new Error('Could not find following link on profile page. Twitter may have changed the layout.');
throw new SelectorError('Twitter following link', 'Twitter may have changed the layout.');
}
await page.wait(5);

Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/hide-reply.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter hide-reply');

await page.goto(kwargs.url);
await page.wait(5);
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/like.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter like');

await page.goto(kwargs.url);
await page.wait(5); // Wait for tweet to load completely
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/notifications.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand Down Expand Up @@ -29,7 +30,7 @@ cli({
// Verify SPA navigation succeeded
const currentUrl = await page.evaluate('() => window.location.pathname');
if (currentUrl !== '/notifications') {
throw new Error('SPA navigation to notifications failed. Twitter may have changed its routing.');
throw new CommandExecutionError('SPA navigation to notifications failed. Twitter may have changed its routing.');
}

// 4. Scroll to trigger pagination
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/post.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { cli, Strategy } from '../../registry.js';
import { CommandExecutionError } from '../../errors.js';
import type { IPage } from '../../types.js';

cli({
Expand All @@ -13,7 +14,7 @@ cli({
],
columns: ['status', 'message', 'text'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter post');

// 1. Navigate directly to the compose tweet modal
await page.goto('https://x.com/compose/tweet');
Expand Down
6 changes: 4 additions & 2 deletions src/clis/twitter/profile.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AuthRequiredError, CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';

cli({
Expand All @@ -22,7 +23,7 @@ cli({
const link = document.querySelector('a[data-testid="AppTabBar_Profile_Link"]');
return link ? link.getAttribute('href') : null;
}`);
if (!href) throw new Error('Could not detect logged-in user. Are you logged in?');
if (!href) throw new AuthRequiredError('x.com', 'Could not detect logged-in user. Are you logged in?');
username = href.replace('/', '');
}

Expand Down Expand Up @@ -121,7 +122,8 @@ cli({
`);

if (result?.error) {
throw new Error(result.error + (result.hint ? ` (${result.hint})` : ''));
if (String(result.error).includes('No ct0 cookie')) throw new AuthRequiredError('x.com', result.error);
throw new CommandExecutionError(result.error + (result.hint ? ` (${result.hint})` : ''));
}

return result || [];
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/reply-dm.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand All @@ -16,7 +17,7 @@ cli({
],
columns: ['index', 'status', 'user', 'message'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter reply-dm');

const messageText: string = kwargs.text;
const maxSend: number = kwargs.max ?? 20;
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/reply.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand All @@ -14,7 +15,7 @@ cli({
],
columns: ['status', 'message', 'text'],
func: async (page: IPage | null, kwargs: any) => {
if (!page) throw new Error('Requires browser');
if (!page) throw new CommandExecutionError('Browser session required for twitter reply');

// 1. Navigate to the tweet page
await page.goto(kwargs.url);
Expand Down
3 changes: 2 additions & 1 deletion src/clis/twitter/search.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { CommandExecutionError } from '../../errors.js';
import { cli, Strategy } from '../../registry.js';
import type { IPage } from '../../types.js';

Expand Down Expand Up @@ -31,7 +32,7 @@ async function navigateToSearch(page: Pick<IPage, 'evaluate' | 'wait'>, query: s
}
}

throw new Error(
throw new CommandExecutionError(
`SPA navigation to /search failed. Final path: ${lastPath || '(empty)'}. Twitter may have changed its routing.`,
);
}
Expand Down
Loading
Loading