Skip to content

Commit

Permalink
Merge pull request #608 from Rishikant181/dev
Browse files Browse the repository at this point in the history
v4.1.0-alpha.1
  • Loading branch information
Rishikant181 authored Sep 5, 2024
2 parents 4164236 + 66d8208 commit a8d659b
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 47 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rettiwt-api",
"version": "4.1.0-alpha.0",
"version": "4.1.0-alpha.1",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"description": "An API for fetching data from TwitterAPI, without any rate limits!",
Expand Down
14 changes: 0 additions & 14 deletions src/commands/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,20 +126,6 @@ function createUserCommand(rettiwt: Rettiwt): Command {
}
});

// Notifications
user.command('notifications')
.description('Fetch you list of notifications')
.argument('[count]', 'The number of notifications to fetch')
.argument('[cursor]', 'The cursor to the batch of notifications to fetch')
.action(async (count?: string, cursor?: string) => {
try {
const notifications = await rettiwt.user.notifications(count ? parseInt(count) : undefined, cursor);
output(notifications);
} catch (error) {
output(error);
}
});

// Recommended
user.command('recommended')
.description('Fetch your recommended feed')
Expand Down
7 changes: 4 additions & 3 deletions src/models/data/CursoredData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class CursoredData<T extends Notification | Tweet | User> {
public list: T[] = [];

/** The cursor to the next batch of data. */
public next: Cursor;
public next: Cursor = new Cursor('');

/**
* @param response - The raw response.
Expand All @@ -29,13 +29,14 @@ export class CursoredData<T extends Notification | Tweet | User> {
public constructor(response: NonNullable<unknown>, type: EBaseType) {
if (type == EBaseType.TWEET) {
this.list = Tweet.list(response) as T[];
this.next = new Cursor(findByFilter<ICursor>(response, 'cursorType', 'Bottom')[0]?.value ?? '');
} else if (type == EBaseType.USER) {
this.list = User.list(response) as T[];
this.next = new Cursor(findByFilter<ICursor>(response, 'cursorType', 'Bottom')[0]?.value ?? '');
} else if (type == EBaseType.NOTIFICATION) {
this.list = Notification.list(response) as T[];
this.next = new Cursor(findByFilter<ICursor>(response, 'cursorType', 'Top')[0]?.value ?? '');
}

this.next = new Cursor(findByFilter<ICursor>(response, 'cursorType', 'Bottom')[0]?.value ?? '');
}
}

Expand Down
10 changes: 7 additions & 3 deletions src/services/public/TweetService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,17 +454,21 @@ export class TweetService extends FetcherService {
* // Creating a new Rettiwt instance using the given 'API_KEY'
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
*
* // Streaming all upcoming tweets from user 'user1'
* (async () => {
* // Creating a function that streams all new tweets from the user 'user1'
* async function streamTweets() {
* try {
* // Awaiting for the tweets returned by the AsyncGenerator returned by the method
* for await (const tweet of rettiwt.tweet.stream({ fromUsers: ['user1'] }, 1000)) {
* console.log(tweet.fullText);
* }
* }
* catch (err) {
* console.log(err);
* }
* })();
* }
*
* // Calling the function
* streamTweets();
* ```
*/
public async *stream(filter: TweetFilter, pollingInterval: number = 60000): AsyncGenerator<Tweet> {
Expand Down
81 changes: 55 additions & 26 deletions src/services/public/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,12 +394,11 @@ export class UserService extends FetcherService {
}

/**
* Get the list of notifications of the logged in user.
* Stream notifications of the logged in user in pseudo real-time.
*
* @param count - The number of notifications to fetch, must be \<= 40.
* @param cursor - The cursor to the batch of notifications to fetch
* @param pollingInterval - The interval in milliseconds to poll for new tweets. Default interval is 60000 ms.
*
* @returns The list of notifications of the target user.
* @returns An async generator that yields new notifications as they are received.
*
* @example
* ```
Expand All @@ -408,32 +407,62 @@ export class UserService extends FetcherService {
* // Creating a new Rettiwt instance using the given 'API_KEY'
* const rettiwt = new Rettiwt({ apiKey: API_KEY });
*
* // Fetching the recent 40 Notifications of the logged in user
* rettiwt.user.notifications(40)
* .then(res => {
* console.log(res);
* })
* .catch(err => {
* console.log(err);
* });
* // Creating a function that streams all new notifications
* async function streamNotifications() {
* try {
* // Awaiting for the notifications returned by the AsyncGenerator returned by the method
* for await (const notification of rettiwt.user.notifications(1000)) {
* console.log(notification.message);
* }
* }
* catch (err) {
* console.log(err);
* }
* }
*
* // Calling the function
* streamNotifications();
* ```
*/
public async notifications(count?: number, cursor?: string): Promise<CursoredData<Notification>> {
public async *notifications(pollingInterval: number = 60000): AsyncGenerator<Notification> {
const resource = EResourceType.USER_NOTIFICATIONS;

// Fetching raw list of notifications
const response = await this.request<IUserNotificationsResponse>(resource, {
count: count,
cursor: cursor,
});

// Deserializing response
const data = extractors[resource](response);

// Sorting the notifications by time, from recent to oldest
data.list.sort((a, b) => new Date(b.receivedAt).valueOf() - new Date(a.receivedAt).valueOf());

return data;
/** Whether it's the first batch of notifications or not. */
let first: boolean = true;

/** The cursor to the last notification received. */
let cursor: string | undefined = undefined;

while (true) {
// Pause execution for the specified polling interval before proceeding to the next iteration
await new Promise((resolve) => setTimeout(resolve, pollingInterval));

// Get the batch of notifications after the given cursor
const response = await this.request<IUserNotificationsResponse>(resource, {
count: 40,
cursor: cursor,
});

// Deserializing response
const notifications = extractors[resource](response);

// Sorting the notifications by time, from oldest to recent
notifications.list.sort((a, b) => new Date(a.receivedAt).valueOf() - new Date(b.receivedAt).valueOf());

// If not first batch, return new notifications
if (!first) {
// Yield the notifications
for (const notification of notifications.list) {
yield notification;
}
}
// Else do nothing, do nothing since first batch is notifications that have already been received
else {
first = false;
}

cursor = notifications.next.value;
}
}

/**
Expand Down

0 comments on commit a8d659b

Please sign in to comment.