Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 2022 march Twitter API v2 update #254

Merged
merged 8 commits into from
Apr 7, 2022
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
130 changes: 130 additions & 0 deletions doc/v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ This is a comprehensive guide of all methods available for the Twitter API v2 on
* [Get users that retweeted a specific tweet](#Getusersthatretweetedaspecifictweet)
* [Retweet a tweet](#Retweetatweet)
* [Unretweet a tweet](#Unretweetatweet)
* [List quoted replies of a tweet](#Listquotedrepliesofatweet)
* [Bookmarks](#Bookmarks)
* [Bookmark a tweet](#Bookmarkatweet)
* [Remove bookmark](#Removebookmark)
* [List bookmarks](#Listbookmarks)
* [Users](#Users)
* [Logged user](#Loggeduser)
* [Single user](#Singleuser)
Expand Down Expand Up @@ -77,6 +82,7 @@ This is a comprehensive guide of all methods available for the Twitter API v2 on
* [Spaces by ID](#SpacesbyID)
* [Spaces by their creator ID](#SpacesbytheircreatorID)
* [Search spaces](#Searchspaces)
* [Space buyers](#Spacebuyers)
* [Batch compliance](#Batchcompliance)
* [Get a single compliance job](#Getasinglecompliancejob)
* [Search compliance jobs](#Searchcompliancejobs)
Expand Down Expand Up @@ -106,6 +112,9 @@ Get to know how [paginators work here](./paginators.md).
- `query: string`
- `options?: Tweetv2SearchParams`

or
- `options?: Tweetv2SearchParams`
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Not super clear

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I should add a line break between first options and or


**Returns**: `TweetSearchRecentV2Paginator`

**Example**
Expand Down Expand Up @@ -509,6 +518,105 @@ Remove a retweet of a single tweet.
await client.v2.unretweet('12', '20');
```

### <a name='Listquotedrepliesofatweet'></a>List quoted replies of a tweet

List quoted replies of a tweets using a tweet paginator.

**Method**: `.quotes()`

**Endpoint**: `tweets/:id/quote_tweets (GET)`

**Right level**: `Read-only`

**Arguments**:
- `tweetId: string`: Tweet ID
- `options: TweetV2PaginableTimelineParams`: Tweet meta options

**Returns**: `QuotedTweetsTimelineV2Paginator`: A tweet paginator

**Example**
```ts
const quotes = await client.v2.quotes({ expansions: ['author_id'], 'user.fields': ['username', 'url'] })

for await (const quote of quotes) {
const quotedTweetAuthor = bookmarks.includes.author(quote)

if (quotedTweetAuthor) {
console.log('Quote answer tweet', quote.id, 'has been made by', quotedTweetAuthor.username)
}
}
```

## <a name='Bookmarks'></a>Bookmarks

### <a name='Bookmarkatweet'></a>Bookmark a tweet

Add tweet as bookmark.

**Method**: `.bookmark()`

**Endpoint**: `users/:id/bookmarks (POST)`

**Right level**: `Read-write`

**Arguments**:
- `tweetId: string`: Tweet to bookmark

**Returns**: `TweetV2BookmarkResult`

**Example**
```ts
await client.v2.bookmark('20')
```

### <a name='Removebookmark'></a>Remove bookmark

Remove a bookmark by tweet ID.

**Method**: `.deleteBookmark()`

**Endpoint**: `users/:id/bookmarks/:tweet_id (DELETE)`

**Right level**: `Read-write`

**Arguments**:
- `tweetId: string`: Tweet to unbookmark

**Returns**: `TweetV2BookmarkResult`

**Example**
```ts
await client.v2.deleteBookmark('20')
```

### <a name='Listbookmarks'></a>List bookmarks

List bookmarked tweets using a tweet paginator.

**Method**: `.bookmarks()`

**Endpoint**: `users/:id/bookmarks (GET)`

**Right level**: `Read-only`

**Arguments**:
- `options: TweetV2PaginableTimelineParams`: Tweet meta options

**Returns**: `TweetBookmarksTimelineV2Paginator`: A tweet paginator

**Example**
```ts
const bookmarks = await client.v2.bookmarks({ expansions: ['referenced_tweets.id'] })

for await (const bookmark of bookmarks) {
const quotedTweet = bookmarks.includes.quote(bookmark)

if (quotedTweet) {
console.log('Bookmarked tweet', bookmark.id, 'is a quote of', quotedTweet.id)
}
}
```

## <a name='Users'></a>Users

### <a name='Loggeduser'></a>Logged user
Expand Down Expand Up @@ -1279,6 +1387,28 @@ const { data: spaces } = await client.v2.searchSpaces({ query: 'Node JS', state:
console.log(spaces) // SpaceV2[] - Found live spaces talking about NodeJS!
```

### <a name='Spacebuyers'></a>Space buyers

Get buyers of your space by its ID.

**Method**: `.spaceBuyers()`

**Endpoint**: `spaces/:id/buyers`

**Right level**: `Read-only`

**Arguments**:
- `spaceId: string`
- `options?: SpaceV2BuyersParams`

**Returns**: `SpaceV2BuyersResult`

**Example**
```ts
const { data: users } = await client.v2.spaceBuyers('space-id')
// users is a UserV2[]
```

## <a name='Batchcompliance'></a>Batch compliance

### <a name='Getasinglecompliancejob'></a>Get a single compliance job
Expand Down
8 changes: 8 additions & 0 deletions src/paginators/tweet.paginator.v1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ abstract class TweetTimelineV1Paginator<
TParams extends TweetV1TimelineParams,
TShared = any,
> extends TwitterPaginator<TResult, TParams, TweetV1, TShared> {
protected hasFinishedFetch = false;

protected refreshInstanceFromResult(response: TwitterResponse<TResult>, isNextPage: true) {
const result = response.data;
this._rateLimit = response.rateLimit!;

if (isNextPage) {
this._realData.push(...result);
// HINT: This is an approximation, as "end" of pagination cannot be safely determined without cursors.
this.hasFinishedFetch = result.length === 0;
}
}

Expand Down Expand Up @@ -54,6 +58,10 @@ abstract class TweetTimelineV1Paginator<
get tweets() {
return this._realData;
}

get done() {
return super.done || this.hasFinishedFetch;
}
}

// Timelines
Expand Down
24 changes: 20 additions & 4 deletions src/paginators/tweet.paginator.v2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
TweetV2,
Tweetv2TimelineResult,
TweetV2TimelineParams,
TweetV2UserTimelineResult,
TweetV2PaginableTimelineResult,
TweetV2UserTimelineParams,
Tweetv2ListResult,
TweetV2PaginableListParams,
Expand Down Expand Up @@ -118,7 +118,7 @@ abstract class TweetTimelineV2Paginator<

/** A generic PreviousableTwitterPaginator able to consume TweetV2 timelines with pagination_tokens. */
abstract class TweetPaginableTimelineV2Paginator<
TResult extends TweetV2UserTimelineResult,
TResult extends TweetV2PaginableTimelineResult,
TParams extends TweetV2PaginableTimelineParams,
TShared = any,
> extends TimelineV2Paginator<TResult, TParams, TweetV2, TShared> {
Expand Down Expand Up @@ -163,24 +163,40 @@ export class TweetSearchAllV2Paginator extends TweetTimelineV2Paginator<Tweetv2S
protected _endpoint = 'tweets/search/all';
}

export class QuotedTweetsTimelineV2Paginator
extends TweetPaginableTimelineV2Paginator<TweetV2PaginableTimelineResult, TweetV2PaginableTimelineParams, { id: string }>
{
protected _endpoint = 'tweets/:id/quote_tweets';
}

// -----------------
// - User timeline -
// -----------------

type TUserTimelinePaginatorShared = { id: string };

export class TweetUserTimelineV2Paginator
extends TweetPaginableTimelineV2Paginator<TweetV2UserTimelineResult, TweetV2UserTimelineParams, TUserTimelinePaginatorShared>
extends TweetPaginableTimelineV2Paginator<TweetV2PaginableTimelineResult, TweetV2UserTimelineParams, TUserTimelinePaginatorShared>
{
protected _endpoint = 'users/:id/tweets';
}

export class TweetUserMentionTimelineV2Paginator
extends TweetPaginableTimelineV2Paginator<TweetV2UserTimelineResult, TweetV2PaginableTimelineParams, TUserTimelinePaginatorShared>
extends TweetPaginableTimelineV2Paginator<TweetV2PaginableTimelineResult, TweetV2PaginableTimelineParams, TUserTimelinePaginatorShared>
{
protected _endpoint = 'users/:id/mentions';
}

// -------------
// - Bookmarks -
// -------------

export class TweetBookmarksTimelineV2Paginator
extends TweetPaginableTimelineV2Paginator<TweetV2PaginableTimelineResult, TweetV2PaginableTimelineParams, { id: string }>
{
protected _endpoint = 'users/:id/bookmarks';
}

// ---------------------------------------------------------------------------------
// - Tweet lists (consume tweets with pagination tokens instead of since/until id) -
// ---------------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/types/auth.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TypeOrArrayOf } from './shared.types';

export type TOAuth2Scope = 'tweet.read' | 'tweet.write' | 'tweet.moderate.write' | 'users.read' | 'follows.read' | 'follows.write'
| 'offline.access' | 'space.read' | 'mute.read' | 'mute.write' | 'like.read' | 'like.write' | 'list.read' | 'list.write'
| 'block.read' | 'block.write';
| 'block.read' | 'block.write' | 'bookmark.read' | 'bookmark.write';

export interface BuildOAuth2RequestLinkArgs {
scope?: TypeOrArrayOf<TOAuth2Scope> | TypeOrArrayOf<string>;
Expand Down
9 changes: 7 additions & 2 deletions src/types/v2/spaces.v2.types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { TypeOrArrayOf } from '../shared.types';
import type { DataMetaAndIncludeV2, DataV2 } from './shared.v2.types';
import type { TTweetv2UserField } from './tweet.v2.types';
import type { UserV2 } from './user.v2.types';
import type { UsersV2Params, UsersV2Result, UserV2 } from './user.v2.types';

export interface SpaceV2FieldsParams {
expansions: TypeOrArrayOf<TSpaceV2Expansion> | string;
Expand All @@ -12,7 +12,7 @@ export interface SpaceV2FieldsParams {
export type TSpaceV2Expansion = 'invited_user_ids' | 'speaker_ids' | 'creator_id' | 'host_ids';
export type TSpaceV2SpaceField = 'host_ids' | 'created_at' | 'creator_id' | 'id' | 'lang'
| 'invited_user_ids' | 'participant_count' | 'speaker_ids' | 'started_at' | 'state' | 'title'
| 'updated_at' | 'scheduled_start' | 'is_ticketed';
| 'updated_at' | 'scheduled_start' | 'is_ticketed' | 'topic_ids' | 'ended_at';
export type TSpaceV2State = 'live' | 'scheduled';

// - Requests -
Expand All @@ -27,12 +27,15 @@ export interface SpaceV2SearchParams extends Partial<SpaceV2FieldsParams> {
max_results?: number;
}

export interface SpaceV2BuyersParams extends Partial<UsersV2Params> {}

// - Responses -

type SpaceV2Includes = { users?: UserV2[] };

export type SpaceV2SingleResult = DataV2<SpaceV2>;
export type SpaceV2LookupResult = DataMetaAndIncludeV2<SpaceV2[], { result_count: number }, SpaceV2Includes>;
export type SpaceV2BuyersResult = UsersV2Result;

// - Entities -

Expand All @@ -51,4 +54,6 @@ export interface SpaceV2 {
title?: string;
creator_id?: string;
updated_at?: string;
topic_ids?: string[];
ended_at?: string;
}
7 changes: 6 additions & 1 deletion src/types/v2/tweet.v2.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ export type Tweetv2ListResult = DataMetaAndIncludeV2<TweetV2[], {
}, ApiV2Includes>;

export type Tweetv2SearchResult = Tweetv2TimelineResult;
export type TweetV2UserTimelineResult = Tweetv2TimelineResult & MetaV2<{ previous_token?: string }>;
export type TweetV2PaginableTimelineResult = Tweetv2TimelineResult & MetaV2<{ previous_token?: string }>;;
export type TweetV2UserTimelineResult = TweetV2PaginableTimelineResult;

export type TweetV2LookupResult = DataAndIncludeV2<TweetV2[], ApiV2Includes>;
export type TweetV2SingleResult = DataAndIncludeV2<TweetV2, ApiV2Includes>;
Expand Down Expand Up @@ -143,6 +144,10 @@ export type TweetV2RetweetResult = DataV2<{ retweeted: boolean }>;

export type TweetV2RetweetedByResult = TweetV2LikedByResult;

// -- Bookmarks

export type TweetV2BookmarkResult = DataV2<{ bookmarked: boolean }>;

/// Tweets

export type TweetV2DeleteTweetResult = DataV2<{ deleted: boolean }>;
Expand Down
Loading