fix: adapt upstream commands to relay client
This commit is contained in:
+6
-26
@@ -42,19 +42,9 @@ export function registerFollowCommands(program: Command, ctx: CliContext): void
|
|||||||
.action(async (usernameOrId: string) => {
|
.action(async (usernameOrId: string) => {
|
||||||
const opts = program.opts();
|
const opts = program.opts();
|
||||||
const timeoutMs = ctx.resolveTimeoutFromOptions(opts);
|
const timeoutMs = ctx.resolveTimeoutFromOptions(opts);
|
||||||
|
const relayBaseUrl = ctx.resolveRelayBaseUrlFromOptions(opts);
|
||||||
const { cookies, warnings } = await ctx.resolveCredentialsFromOptions(opts);
|
const profileName = ctx.resolveProfileNameFromOptions(opts);
|
||||||
|
const client = new TwitterClient({ relayBaseUrl, profileName, timeoutMs });
|
||||||
for (const warning of warnings) {
|
|
||||||
console.error(`${ctx.p('warn')}${warning}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cookies.authToken || !cookies.ct0) {
|
|
||||||
console.error(`${ctx.p('err')}Missing required credentials`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const client = new TwitterClient({ cookies, timeoutMs });
|
|
||||||
|
|
||||||
const resolved = await resolveUserId(client, usernameOrId, ctx);
|
const resolved = await resolveUserId(client, usernameOrId, ctx);
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
@@ -81,19 +71,9 @@ export function registerFollowCommands(program: Command, ctx: CliContext): void
|
|||||||
.action(async (usernameOrId: string) => {
|
.action(async (usernameOrId: string) => {
|
||||||
const opts = program.opts();
|
const opts = program.opts();
|
||||||
const timeoutMs = ctx.resolveTimeoutFromOptions(opts);
|
const timeoutMs = ctx.resolveTimeoutFromOptions(opts);
|
||||||
|
const relayBaseUrl = ctx.resolveRelayBaseUrlFromOptions(opts);
|
||||||
const { cookies, warnings } = await ctx.resolveCredentialsFromOptions(opts);
|
const profileName = ctx.resolveProfileNameFromOptions(opts);
|
||||||
|
const client = new TwitterClient({ relayBaseUrl, profileName, timeoutMs });
|
||||||
for (const warning of warnings) {
|
|
||||||
console.error(`${ctx.p('warn')}${warning}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cookies.authToken || !cookies.ct0) {
|
|
||||||
console.error(`${ctx.p('err')}Missing required credentials`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const client = new TwitterClient({ cookies, timeoutMs });
|
|
||||||
|
|
||||||
const resolved = await resolveUserId(client, usernameOrId, ctx);
|
const resolved = await resolveUserId(client, usernameOrId, ctx);
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
|
|||||||
+3
-63
@@ -317,18 +317,9 @@ export function registerUserCommands(program: Command, ctx: CliContext): void {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { cookies, warnings } = await ctx.resolveCredentialsFromOptions(opts);
|
const relayBaseUrl = ctx.resolveRelayBaseUrlFromOptions(opts);
|
||||||
|
const profileName = ctx.resolveProfileNameFromOptions(opts);
|
||||||
for (const warning of warnings) {
|
const client = new TwitterClient({ relayBaseUrl, profileName, timeoutMs });
|
||||||
console.error(`${ctx.p('warn')}${warning}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cookies.authToken || !cookies.ct0) {
|
|
||||||
console.error(`${ctx.p('err')}Missing required credentials`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const client = new TwitterClient({ cookies, timeoutMs });
|
|
||||||
const result = await client.getUserAboutAccount(normalizedHandle);
|
const result = await client.getUserAboutAccount(normalizedHandle);
|
||||||
|
|
||||||
if (result.success && result.aboutProfile) {
|
if (result.success && result.aboutProfile) {
|
||||||
@@ -344,55 +335,4 @@ export function registerUserCommands(program: Command, ctx: CliContext): void {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
|
||||||
.command('about')
|
|
||||||
.description('Get account origin and location information for a user')
|
|
||||||
.argument('<username>', 'Twitter username (with or without @)')
|
|
||||||
.option('--json', 'Output as JSON')
|
|
||||||
.action(async (username: string, cmdOpts: { json?: boolean }) => {
|
|
||||||
const opts = program.opts();
|
|
||||||
const timeoutMs = ctx.resolveTimeoutFromOptions(opts);
|
|
||||||
|
|
||||||
const { cookies, warnings } = await ctx.resolveCredentialsFromOptions(opts);
|
|
||||||
|
|
||||||
for (const warning of warnings) {
|
|
||||||
console.error(`${ctx.p('warn')}${warning}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cookies.authToken || !cookies.ct0) {
|
|
||||||
console.error(`${ctx.p('err')}Missing required credentials`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const client = new TwitterClient({ cookies, timeoutMs });
|
|
||||||
const result = await client.getUserAboutAccount(username);
|
|
||||||
|
|
||||||
if (result.success && result.aboutProfile) {
|
|
||||||
if (cmdOpts.json) {
|
|
||||||
console.log(JSON.stringify(result.aboutProfile, null, 2));
|
|
||||||
} else {
|
|
||||||
const profile = result.aboutProfile;
|
|
||||||
console.log(`${ctx.p('info')}Account information for @${username}:`);
|
|
||||||
if (profile.accountBasedIn) {
|
|
||||||
console.log(` Account based in: ${profile.accountBasedIn}`);
|
|
||||||
}
|
|
||||||
if (profile.createdCountryAccurate !== undefined) {
|
|
||||||
console.log(` Creation country accurate: ${profile.createdCountryAccurate ? 'Yes' : 'No'}`);
|
|
||||||
}
|
|
||||||
if (profile.locationAccurate !== undefined) {
|
|
||||||
console.log(` Location accurate: ${profile.locationAccurate ? 'Yes' : 'No'}`);
|
|
||||||
}
|
|
||||||
if (profile.source) {
|
|
||||||
console.log(`${ctx.l('source')}${profile.source}`);
|
|
||||||
}
|
|
||||||
if (profile.learnMoreUrl) {
|
|
||||||
console.log(` Learn more: ${profile.learnMoreUrl}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.error(`${ctx.p('err')}Failed to fetch account information: ${result.error ?? 'Unknown error'}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export function withFollow<TBase extends AbstractConstructor<TwitterClientBase>>
|
|||||||
const response = await this.fetchWithTimeout(url, {
|
const response = await this.fetchWithTimeout(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
...this.getBaseHeaders(),
|
...this.getHeaders(),
|
||||||
'content-type': 'application/x-www-form-urlencoded',
|
'content-type': 'application/x-www-form-urlencoded',
|
||||||
},
|
},
|
||||||
body: params.toString(),
|
body: params.toString(),
|
||||||
|
|||||||
@@ -6,10 +6,8 @@ import { TwitterClient } from '../src/lib/twitter-client.js';
|
|||||||
|
|
||||||
const baseCtx = {
|
const baseCtx = {
|
||||||
resolveTimeoutFromOptions: () => undefined,
|
resolveTimeoutFromOptions: () => undefined,
|
||||||
resolveCredentialsFromOptions: async () => ({
|
resolveRelayBaseUrlFromOptions: () => 'http://relay.test',
|
||||||
cookies: { authToken: 'auth', ct0: 'ct0', cookieHeader: 'auth=auth; ct0=ct0' },
|
resolveProfileNameFromOptions: () => undefined,
|
||||||
warnings: [],
|
|
||||||
}),
|
|
||||||
p: () => '',
|
p: () => '',
|
||||||
} as unknown as CliContext;
|
} as unknown as CliContext;
|
||||||
|
|
||||||
|
|||||||
@@ -6,10 +6,8 @@ import { TwitterClient } from '../src/lib/twitter-client.js';
|
|||||||
|
|
||||||
const baseCtx = {
|
const baseCtx = {
|
||||||
resolveTimeoutFromOptions: () => undefined,
|
resolveTimeoutFromOptions: () => undefined,
|
||||||
resolveCredentialsFromOptions: async () => ({
|
resolveRelayBaseUrlFromOptions: () => 'http://relay.test',
|
||||||
cookies: { authToken: 'auth', ct0: 'ct0', cookieHeader: 'auth=auth; ct0=ct0' },
|
resolveProfileNameFromOptions: () => undefined,
|
||||||
warnings: [],
|
|
||||||
}),
|
|
||||||
p: () => '',
|
p: () => '',
|
||||||
l: () => '',
|
l: () => '',
|
||||||
printTweets: () => undefined,
|
printTweets: () => undefined,
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import { spawn } from 'node:child_process';
|
|||||||
import { existsSync } from 'node:fs';
|
import { existsSync } from 'node:fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { beforeAll, describe, expect, it } from 'vitest';
|
import { beforeAll, describe, expect, it } from 'vitest';
|
||||||
import { resolveCredentials } from '../../src/lib/cookies.js';
|
|
||||||
import { TwitterClient } from '../../src/lib/twitter-client.js';
|
|
||||||
|
|
||||||
type RunResult = { exitCode: number; stdout: string; stderr: string; signal: NodeJS.Signals | null };
|
type RunResult = { exitCode: number; stdout: string; stderr: string; signal: NodeJS.Signals | null };
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import { spawn } from 'node:child_process';
|
|||||||
import { existsSync } from 'node:fs';
|
import { existsSync } from 'node:fs';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { beforeAll, describe, expect, it } from 'vitest';
|
import { beforeAll, describe, expect, it } from 'vitest';
|
||||||
import { resolveCredentials } from '../../src/lib/cookies.js';
|
|
||||||
import { TwitterClient } from '../../src/lib/twitter-client.js';
|
|
||||||
|
|
||||||
type RunResult = { exitCode: number; stdout: string; stderr: string; signal: NodeJS.Signals | null };
|
type RunResult = { exitCode: number; stdout: string; stderr: string; signal: NodeJS.Signals | null };
|
||||||
|
|
||||||
|
|||||||
@@ -202,18 +202,19 @@ describe('TwitterClient getUserAboutAccount', () => {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
const client = new TwitterClient({ cookies: validCookies });
|
const client = new TwitterClient({ relayBaseUrl: 'http://relay.test', profileName: 'test-profile' });
|
||||||
await client.getUserAboutAccount('testuser');
|
await client.getUserAboutAccount('testuser');
|
||||||
|
|
||||||
expect(mockFetch).toHaveBeenCalledTimes(1);
|
expect(mockFetch).toHaveBeenCalledTimes(1);
|
||||||
const [url, options] = mockFetch.mock.calls[0] as [string, RequestInit];
|
const [url, options] = mockFetch.mock.calls[0] as [string, RequestInit];
|
||||||
|
|
||||||
|
expect(url).toContain('http://relay.test/i/api/graphql/');
|
||||||
expect(url).toContain('/AboutAccountQuery?');
|
expect(url).toContain('/AboutAccountQuery?');
|
||||||
expect(url).toContain('variables=');
|
expect(url).toContain('variables=');
|
||||||
expect(url).toContain('testuser');
|
expect(url).toContain('testuser');
|
||||||
expect(options.method).toBe('GET');
|
expect(options.method).toBe('GET');
|
||||||
expect(options.headers).toMatchObject({
|
expect(options.headers).toMatchObject({
|
||||||
'x-csrf-token': 'test_ct0_token',
|
'x-profile-name': 'test-profile',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user