Use twitter safe relay
CI / test (pull_request) Has been cancelled

This commit is contained in:
2026-06-24 03:39:34 +09:00
parent b771e827aa
commit 1f6e228272
66 changed files with 597 additions and 1720 deletions
+7 -62
View File
@@ -4,7 +4,6 @@ import { join } from 'node:path';
import type { Command } from 'commander';
import JSON5 from 'json5';
import kleur from 'kleur';
import { type CookieSource, resolveCredentials } from '../lib/cookies.js';
import { extractTweetId } from '../lib/extract-tweet-id.js';
import {
hyperlink,
@@ -17,10 +16,7 @@ import {
import type { TweetData } from '../lib/twitter-client.js';
export type BirdConfig = {
chromeProfile?: string;
firefoxProfile?: string;
cookieSource?: CookieSource | CookieSource[];
cookieTimeoutMs?: number;
relayBaseUrl?: string;
timeoutMs?: number;
quoteDepth?: number;
};
@@ -48,7 +44,7 @@ export type CliContext = {
applyOutputFromCommand: (command: Command) => void;
resolveTimeoutFromOptions: (options: { timeout?: string | number }) => number | undefined;
resolveQuoteDepthFromOptions: (options: { quoteDepth?: string | number }) => number | undefined;
resolveCredentialsFromOptions: (opts: CredentialsOptions) => ReturnType<typeof resolveCredentials>;
resolveRelayBaseUrlFromOptions: (opts: RelayOptions) => string | undefined;
loadMedia: (opts: { media: string[]; alts: string[] }) => MediaSpec[];
printTweets: (tweets: TweetData[], opts?: { json?: boolean; emptyMessage?: string; showSeparator?: boolean }) => void;
printTweetsResult: (
@@ -65,38 +61,6 @@ export type CliContext = {
extractTweetId: (tweetIdOrUrl: string) => string;
};
const COOKIE_SOURCES: CookieSource[] = ['safari', 'chrome', 'firefox'];
function parseCookieSource(value: string): CookieSource {
const normalized = value.trim().toLowerCase();
if (normalized === 'safari' || normalized === 'chrome' || normalized === 'firefox') {
return normalized;
}
throw new Error(`Invalid --cookie-source "${value}". Allowed: safari, chrome, firefox.`);
}
export const collectCookieSource = (value: string, previous: CookieSource[] = []): CookieSource[] => {
previous.push(parseCookieSource(value));
return previous;
};
function resolveCookieSourceOrder(input: unknown): CookieSource[] | undefined {
if (typeof input === 'string') {
return [parseCookieSource(input)];
}
if (Array.isArray(input)) {
const result: CookieSource[] = [];
for (const entry of input) {
if (typeof entry !== 'string') {
continue;
}
result.push(parseCookieSource(entry));
}
return result.length > 0 ? result : undefined;
}
return undefined;
}
function resolveTimeoutMs(...values: Array<string | number | undefined | null>): number | undefined {
for (const value of values) {
if (value === undefined || value === null || value === '') {
@@ -170,13 +134,8 @@ function loadConfig(warn: (message: string) => void): BirdConfig {
};
}
type CredentialsOptions = {
authToken?: string;
ct0?: string;
chromeProfile?: string;
firefoxProfile?: string;
cookieSource?: CookieSource[];
cookieTimeout?: string | number;
type RelayOptions = {
relayBaseUrl?: string;
};
export function createCliContext(normalizedArgs: string[], env: NodeJS.ProcessEnv = process.env): CliContext {
@@ -268,26 +227,12 @@ export function createCliContext(normalizedArgs: string[], env: NodeJS.ProcessEn
return resolveTimeoutMs(options.timeout, config.timeoutMs, env.BIRD_TIMEOUT_MS);
}
function resolveCookieTimeoutFromOptions(options: { cookieTimeout?: string | number }): number | undefined {
return resolveTimeoutMs(options.cookieTimeout, config.cookieTimeoutMs, env.BIRD_COOKIE_TIMEOUT_MS);
}
function resolveQuoteDepthFromOptions(options: { quoteDepth?: string | number }): number | undefined {
return resolveQuoteDepth(options.quoteDepth, config.quoteDepth, env.BIRD_QUOTE_DEPTH);
}
function resolveCredentialsFromOptions(opts: CredentialsOptions): ReturnType<typeof resolveCredentials> {
const cookieSource = opts.cookieSource?.length
? opts.cookieSource
: (resolveCookieSourceOrder(config.cookieSource) ?? COOKIE_SOURCES);
return resolveCredentials({
authToken: opts.authToken,
ct0: opts.ct0,
cookieSource,
chromeProfile: opts.chromeProfile || config.chromeProfile,
firefoxProfile: opts.firefoxProfile || config.firefoxProfile,
cookieTimeoutMs: resolveCookieTimeoutFromOptions(opts),
});
function resolveRelayBaseUrlFromOptions(opts: RelayOptions): string | undefined {
return opts.relayBaseUrl || config.relayBaseUrl || env.TWITTER_RELAY_BASE_URL;
}
function loadMedia(opts: { media: string[]; alts: string[] }): MediaSpec[] {
@@ -422,7 +367,7 @@ export function createCliContext(normalizedArgs: string[], env: NodeJS.ProcessEn
applyOutputFromCommand,
resolveTimeoutFromOptions,
resolveQuoteDepthFromOptions,
resolveCredentialsFromOptions,
resolveRelayBaseUrlFromOptions,
loadMedia,
printTweets,
printTweetsResult,