chore(release): 0.5.0
This commit is contained in:
@@ -4,8 +4,13 @@ import { type OperationName, QUERY_IDS, TARGET_QUERY_ID_OPERATIONS } from './twi
|
||||
import type { CurrentUserResult, TwitterClientOptions } from './twitter-client-types.js';
|
||||
import { normalizeQuoteDepth } from './twitter-client-utils.js';
|
||||
|
||||
export type Constructor<T = object> = new (...args: unknown[]) => T;
|
||||
export type AbstractConstructor<T = object> = abstract new (...args: unknown[]) => T;
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TS mixin base constructor requirement.
|
||||
export type Constructor<T = object> = new (...args: any[]) => T;
|
||||
// biome-ignore lint/suspicious/noExplicitAny: TS mixin base constructor requirement.
|
||||
export type AbstractConstructor<T = object> = abstract new (...args: any[]) => T;
|
||||
export type Mixin<TBase extends AbstractConstructor<TwitterClientBase>, TAdded> = abstract new (
|
||||
...args: ConstructorParameters<TBase>
|
||||
) => TwitterClientBase & TAdded;
|
||||
|
||||
export abstract class TwitterClientBase {
|
||||
protected authToken: string;
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
import type { AbstractConstructor, TwitterClientBase } from './twitter-client-base.js';
|
||||
import type { AbstractConstructor, Mixin, TwitterClientBase } from './twitter-client-base.js';
|
||||
import { TWITTER_MEDIA_METADATA_URL, TWITTER_UPLOAD_URL } from './twitter-client-constants.js';
|
||||
import type { UploadMediaResult } from './twitter-client-types.js';
|
||||
|
||||
export function withMedia<TBase extends AbstractConstructor<TwitterClientBase>>(Base: TBase) {
|
||||
return class extends Base {
|
||||
export interface TwitterClientMediaMethods {
|
||||
uploadMedia(input: { data: Uint8Array; mimeType: string; alt?: string }): Promise<UploadMediaResult>;
|
||||
}
|
||||
|
||||
export function withMedia<TBase extends AbstractConstructor<TwitterClientBase>>(
|
||||
Base: TBase,
|
||||
): Mixin<TBase, TwitterClientMediaMethods> {
|
||||
abstract class TwitterClientMedia extends Base {
|
||||
// biome-ignore lint/complexity/noUselessConstructor lint/suspicious/noExplicitAny: TS mixin constructor requirement.
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
private mediaCategoryForMime(mimeType: string): string | null {
|
||||
if (mimeType.startsWith('image/')) {
|
||||
if (mimeType === 'image/gif') {
|
||||
@@ -162,5 +173,7 @@ export function withMedia<TBase extends AbstractConstructor<TwitterClientBase>>(
|
||||
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return TwitterClientMedia;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,22 @@
|
||||
import type { AbstractConstructor, TwitterClientBase } from './twitter-client-base.js';
|
||||
import type { AbstractConstructor, Mixin, TwitterClientBase } from './twitter-client-base.js';
|
||||
import { TWITTER_API_BASE, TWITTER_GRAPHQL_POST_URL, TWITTER_STATUS_UPDATE_URL } from './twitter-client-constants.js';
|
||||
import { buildTweetCreateFeatures } from './twitter-client-features.js';
|
||||
import type { CreateTweetResponse, TweetResult } from './twitter-client-types.js';
|
||||
|
||||
export function withPosting<TBase extends AbstractConstructor<TwitterClientBase>>(Base: TBase) {
|
||||
return class extends Base {
|
||||
export interface TwitterClientPostingMethods {
|
||||
tweet(text: string, mediaIds?: string[]): Promise<TweetResult>;
|
||||
reply(text: string, replyToTweetId: string, mediaIds?: string[]): Promise<TweetResult>;
|
||||
}
|
||||
|
||||
export function withPosting<TBase extends AbstractConstructor<TwitterClientBase>>(
|
||||
Base: TBase,
|
||||
): Mixin<TBase, TwitterClientPostingMethods> {
|
||||
abstract class TwitterClientPosting extends Base {
|
||||
// biome-ignore lint/complexity/noUselessConstructor lint/suspicious/noExplicitAny: TS mixin constructor requirement.
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post a new tweet
|
||||
*/
|
||||
@@ -269,5 +281,7 @@ export function withPosting<TBase extends AbstractConstructor<TwitterClientBase>
|
||||
error: `${this.formatErrors(errors)} | fallback: ${fallback.error ?? 'Unknown error'}`,
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return TwitterClientPosting;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
import type { AbstractConstructor, TwitterClientBase } from './twitter-client-base.js';
|
||||
import type { AbstractConstructor, Mixin, TwitterClientBase } from './twitter-client-base.js';
|
||||
import { TWITTER_API_BASE } from './twitter-client-constants.js';
|
||||
import { buildSearchFeatures } from './twitter-client-features.js';
|
||||
import type { SearchResult, TweetData } from './twitter-client-types.js';
|
||||
import { extractCursorFromInstructions, parseTweetsFromInstructions } from './twitter-client-utils.js';
|
||||
|
||||
export function withSearch<TBase extends AbstractConstructor<TwitterClientBase>>(Base: TBase) {
|
||||
return class extends Base {
|
||||
export interface TwitterClientSearchMethods {
|
||||
search(query: string, count?: number): Promise<SearchResult>;
|
||||
}
|
||||
|
||||
export function withSearch<TBase extends AbstractConstructor<TwitterClientBase>>(
|
||||
Base: TBase,
|
||||
): Mixin<TBase, TwitterClientSearchMethods> {
|
||||
abstract class TwitterClientSearch extends Base {
|
||||
// biome-ignore lint/complexity/noUselessConstructor lint/suspicious/noExplicitAny: TS mixin constructor requirement.
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for tweets matching a query
|
||||
*/
|
||||
@@ -156,5 +167,7 @@ export function withSearch<TBase extends AbstractConstructor<TwitterClientBase>>
|
||||
|
||||
return { success: true, tweets };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return TwitterClientSearch;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
import type { AbstractConstructor, TwitterClientBase } from './twitter-client-base.js';
|
||||
import type { AbstractConstructor, Mixin, TwitterClientBase } from './twitter-client-base.js';
|
||||
import { TWITTER_API_BASE } from './twitter-client-constants.js';
|
||||
import { buildBookmarksFeatures, buildLikesFeatures } from './twitter-client-features.js';
|
||||
import type { SearchResult } from './twitter-client-types.js';
|
||||
import type { GraphqlTweetResult, SearchResult } from './twitter-client-types.js';
|
||||
import { parseTweetsFromInstructions } from './twitter-client-utils.js';
|
||||
|
||||
export function withTimelines<TBase extends AbstractConstructor<TwitterClientBase>>(Base: TBase) {
|
||||
return class extends Base {
|
||||
export interface TwitterClientTimelineMethods {
|
||||
getBookmarks(count?: number): Promise<SearchResult>;
|
||||
getLikes(count?: number): Promise<SearchResult>;
|
||||
getBookmarkFolderTimeline(folderId: string, count?: number): Promise<SearchResult>;
|
||||
}
|
||||
|
||||
export function withTimelines<TBase extends AbstractConstructor<TwitterClientBase>>(
|
||||
Base: TBase,
|
||||
): Mixin<TBase, TwitterClientTimelineMethods> {
|
||||
abstract class TwitterClientTimelines extends Base {
|
||||
// biome-ignore lint/complexity/noUselessConstructor lint/suspicious/noExplicitAny: TS mixin constructor requirement.
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
private async getBookmarksQueryIds(): Promise<string[]> {
|
||||
const primary = await this.getQueryId('Bookmarks');
|
||||
return Array.from(new Set([primary, 'RV1g3b8n_SGOHwkqKYSCFw', 'tmd4ifV8RHltzn8ymGg1aw']));
|
||||
@@ -74,7 +87,7 @@ export function withTimelines<TBase extends AbstractConstructor<TwitterClientBas
|
||||
content?: {
|
||||
itemContent?: {
|
||||
tweet_results?: {
|
||||
result?: unknown;
|
||||
result?: GraphqlTweetResult;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -180,7 +193,7 @@ export function withTimelines<TBase extends AbstractConstructor<TwitterClientBas
|
||||
content?: {
|
||||
itemContent?: {
|
||||
tweet_results?: {
|
||||
result?: unknown;
|
||||
result?: GraphqlTweetResult;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -283,7 +296,7 @@ export function withTimelines<TBase extends AbstractConstructor<TwitterClientBas
|
||||
content?: {
|
||||
itemContent?: {
|
||||
tweet_results?: {
|
||||
result?: unknown;
|
||||
result?: GraphqlTweetResult;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -333,5 +346,7 @@ export function withTimelines<TBase extends AbstractConstructor<TwitterClientBas
|
||||
|
||||
return { success: false, error: firstAttempt.error };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return TwitterClientTimelines;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AbstractConstructor, TwitterClientBase } from './twitter-client-base.js';
|
||||
import type { AbstractConstructor, Mixin, TwitterClientBase } from './twitter-client-base.js';
|
||||
import { TWITTER_API_BASE } from './twitter-client-constants.js';
|
||||
import { buildArticleFeatures, buildArticleFieldToggles, buildTweetDetailFeatures } from './twitter-client-features.js';
|
||||
import type { GetTweetResult, GraphqlTweetResult, SearchResult } from './twitter-client-types.js';
|
||||
@@ -10,8 +10,21 @@ import {
|
||||
parseTweetsFromInstructions,
|
||||
} from './twitter-client-utils.js';
|
||||
|
||||
export function withTweetDetails<TBase extends AbstractConstructor<TwitterClientBase>>(Base: TBase) {
|
||||
return class extends Base {
|
||||
export interface TwitterClientTweetDetailMethods {
|
||||
getTweet(tweetId: string): Promise<GetTweetResult>;
|
||||
getReplies(tweetId: string): Promise<SearchResult>;
|
||||
getThread(tweetId: string): Promise<SearchResult>;
|
||||
}
|
||||
|
||||
export function withTweetDetails<TBase extends AbstractConstructor<TwitterClientBase>>(
|
||||
Base: TBase,
|
||||
): Mixin<TBase, TwitterClientTweetDetailMethods> {
|
||||
abstract class TwitterClientTweetDetails extends Base {
|
||||
// biome-ignore lint/complexity/noUselessConstructor lint/suspicious/noExplicitAny: TS mixin constructor requirement.
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
private async fetchUserArticlePlainText(
|
||||
userId: string,
|
||||
tweetId: string,
|
||||
@@ -318,5 +331,7 @@ export function withTweetDetails<TBase extends AbstractConstructor<TwitterClient
|
||||
|
||||
return { success: true, tweets: thread };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return TwitterClientTweetDetails;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AbstractConstructor, TwitterClientBase } from './twitter-client-base.js';
|
||||
import type { AbstractConstructor, Mixin, TwitterClientBase } from './twitter-client-base.js';
|
||||
import {
|
||||
SETTINGS_NAME_REGEX,
|
||||
SETTINGS_SCREEN_NAME_REGEX,
|
||||
@@ -9,8 +9,21 @@ import { buildFollowingFeatures } from './twitter-client-features.js';
|
||||
import type { CurrentUserResult, FollowingResult } from './twitter-client-types.js';
|
||||
import { parseUsersFromInstructions } from './twitter-client-utils.js';
|
||||
|
||||
export function withUsers<TBase extends AbstractConstructor<TwitterClientBase>>(Base: TBase) {
|
||||
return class extends Base {
|
||||
export interface TwitterClientUserMethods {
|
||||
getCurrentUser(): Promise<CurrentUserResult>;
|
||||
getFollowing(userId: string, count?: number): Promise<FollowingResult>;
|
||||
getFollowers(userId: string, count?: number): Promise<FollowingResult>;
|
||||
}
|
||||
|
||||
export function withUsers<TBase extends AbstractConstructor<TwitterClientBase>>(
|
||||
Base: TBase,
|
||||
): Mixin<TBase, TwitterClientUserMethods> {
|
||||
abstract class TwitterClientUsers extends Base {
|
||||
// biome-ignore lint/complexity/noUselessConstructor lint/suspicious/noExplicitAny: TS mixin constructor requirement.
|
||||
constructor(...args: any[]) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
private async getFollowingQueryIds(): Promise<string[]> {
|
||||
const primary = await this.getQueryId('Following');
|
||||
return Array.from(new Set([primary, 'BEkNpEt5pNETESoqMsTEGA']));
|
||||
@@ -326,5 +339,7 @@ export function withUsers<TBase extends AbstractConstructor<TwitterClientBase>>(
|
||||
|
||||
return { success: false, error: firstAttempt.error };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return TwitterClientUsers;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
import type { AbstractConstructor } from './twitter-client-base.js';
|
||||
import { TwitterClientBase } from './twitter-client-base.js';
|
||||
import { withMedia } from './twitter-client-media.js';
|
||||
import { withPosting } from './twitter-client-posting.js';
|
||||
import { withSearch } from './twitter-client-search.js';
|
||||
import { withTimelines } from './twitter-client-timelines.js';
|
||||
import { withTweetDetails } from './twitter-client-tweet-detail.js';
|
||||
import { withUsers } from './twitter-client-users.js';
|
||||
import { type TwitterClientMediaMethods, withMedia } from './twitter-client-media.js';
|
||||
import { type TwitterClientPostingMethods, withPosting } from './twitter-client-posting.js';
|
||||
import { type TwitterClientSearchMethods, withSearch } from './twitter-client-search.js';
|
||||
import { type TwitterClientTimelineMethods, withTimelines } from './twitter-client-timelines.js';
|
||||
import { type TwitterClientTweetDetailMethods, withTweetDetails } from './twitter-client-tweet-detail.js';
|
||||
import { type TwitterClientUserMethods, withUsers } from './twitter-client-users.js';
|
||||
|
||||
type TwitterClientInstance = TwitterClientBase &
|
||||
TwitterClientMediaMethods &
|
||||
TwitterClientPostingMethods &
|
||||
TwitterClientSearchMethods &
|
||||
TwitterClientTimelineMethods &
|
||||
TwitterClientTweetDetailMethods &
|
||||
TwitterClientUserMethods;
|
||||
|
||||
const MixedTwitterClient = withUsers(
|
||||
withTimelines(withSearch(withTweetDetails(withPosting(withMedia(TwitterClientBase))))),
|
||||
);
|
||||
) as AbstractConstructor<TwitterClientInstance>;
|
||||
|
||||
export class TwitterClient extends MixedTwitterClient {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user