Skip to content

Commit

Permalink
refactor(platforms): fixes bug with tweetDays provider
Browse files Browse the repository at this point in the history
  • Loading branch information
aminah-io committed Jul 15, 2023
1 parent 685ff1e commit 6d96c9f
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 42 deletions.
93 changes: 83 additions & 10 deletions platforms/src/Twitter/Providers/__tests__/twitterTweetDays.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,6 @@ describe("TwittewTweetDaysProvider", function () {

const MOCK_TWITTER_CLIENT = new Client({} as auth.OAuth2User);

const mockContext: ProviderContext = {
twitter: {
id: "123",
},
};

const mockPayload: RequestPayload = {
address: "0x0",
proofs: {
Expand All @@ -36,15 +30,80 @@ describe("TwittewTweetDaysProvider", function () {
const sessionKey = mockPayload.proofs.sessionKey;
const code = mockPayload.proofs.code;

it("handles valid tweet days count", async () => {
it("handles gte 30 days tweet count", async () => {
(getUserTweetTimeline as jest.MockedFunction<typeof getUserTweetTimeline>).mockImplementation(() => {
return Promise.resolve({
numberDaysTweeted: 35,
errors: undefined,
});
});

const mockContext: ProviderContext = {
twitter: {
id: "123",
numberDaysTweeted: 35,
errors: undefined,
},
};

const provider = new TwitterTweetDaysProvider({ threshold: "30" });
const result = await provider.verify(mockPayload, mockContext);

expect(getAuthClient).toBeCalledWith(sessionKey, code, mockContext);
expect(getAuthClient).toHaveBeenCalledTimes(1);
expect(getUserTweetTimeline).toHaveBeenCalledTimes(1);
expect(result).toEqual({
valid: true,
error: undefined,
record: { id: "123" },
});
});

it("handles gte 60 days tweet count", async () => {
(getUserTweetTimeline as jest.MockedFunction<typeof getUserTweetTimeline>).mockImplementation(() => {
return Promise.resolve({
numberDaysTweeted: 65,
errors: undefined,
});
});

const mockContext: ProviderContext = {
twitter: {
id: "123",
numberDaysTweeted: 65,
errors: undefined,
},
};

const provider = new TwitterTweetDaysProvider({ threshold: "60" });
const result = await provider.verify(mockPayload, mockContext);

expect(getAuthClient).toBeCalledWith(sessionKey, code, mockContext);
expect(getAuthClient).toHaveBeenCalledTimes(1);
expect(getUserTweetTimeline).toHaveBeenCalledTimes(1);
expect(result).toEqual({
valid: true,
error: undefined,
record: { id: "123" },
});
});

it("handles gte 120 days tweet count", async () => {
(getUserTweetTimeline as jest.MockedFunction<typeof getUserTweetTimeline>).mockImplementation(() => {
return Promise.resolve({
numberDaysTweeted: 120,
valid: true,
errors: undefined,
});
});

const mockContext: ProviderContext = {
twitter: {
id: "123",
numberDaysTweeted: 120,
errors: undefined,
},
};

const provider = new TwitterTweetDaysProvider({ threshold: "120" });
const result = await provider.verify(mockPayload, mockContext);

Expand All @@ -62,11 +121,18 @@ describe("TwittewTweetDaysProvider", function () {
(getUserTweetTimeline as jest.MockedFunction<typeof getUserTweetTimeline>).mockImplementation(() => {
return Promise.resolve({
numberDaysTweeted: 12,
valid: false,
errors: undefined,
});
});

const mockContext: ProviderContext = {
twitter: {
id: "123",
numberDaysTweeted: 12,
errors: undefined,
},
};

const provider = new TwitterTweetDaysProvider({ threshold: "120" });
const result = await provider.verify(mockPayload, mockContext);

Expand All @@ -84,11 +150,18 @@ describe("TwittewTweetDaysProvider", function () {
(getUserTweetTimeline as jest.MockedFunction<typeof getUserTweetTimeline>).mockImplementation(() => {
return Promise.resolve({
numberDaysTweeted: undefined,
valid: false,
errors: ["Errors"],
});
});

const mockContext: ProviderContext = {
twitter: {
id: "123",
numberDaysTweeted: 35,
errors: undefined,
},
};

const provider = new TwitterTweetDaysProvider({ threshold: "120" });
const result = await provider.verify(mockPayload, mockContext);

Expand Down
15 changes: 5 additions & 10 deletions platforms/src/Twitter/Providers/twitterTweetDays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import { TwitterContext, getAuthClient, getUserTweetTimeline, UserTweetTimeline
async function verifyTwitterTweetDays(
sessionKey: string,
code: string,
context: TwitterContext,
threshold: number
context: TwitterContext
): Promise<UserTweetTimeline> {
const twitterClient = await getAuthClient(sessionKey, code, context);
const data = await getUserTweetTimeline(context, twitterClient, threshold);
const data = await getUserTweetTimeline(context, twitterClient);
return data;
}

Expand All @@ -32,15 +31,11 @@ export class TwitterTweetDaysProvider implements Provider {
}

async verify(payload: RequestPayload, context: TwitterContext): Promise<VerifiedPayload> {
const twitterTweetData = await verifyTwitterTweetDays(
payload.proofs.sessionKey,
payload.proofs.code,
context,
parseInt(this._options.threshold)
);
const twitterTweetData = await verifyTwitterTweetDays(payload.proofs.sessionKey, payload.proofs.code, context);

const twitterUserId = context.twitter.id;
const valid = twitterTweetData.valid;
const numberDaysTweeted = context.twitter.numberDaysTweeted;
const valid = numberDaysTweeted >= parseInt(this._options.threshold);

return {
valid,
Expand Down
27 changes: 5 additions & 22 deletions platforms/src/Twitter/procedures/twitterOauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export type TwitterContext = ProviderContext & {
createdAt?: string;
id?: string;
numberDaysTweeted?: number;
valid?: boolean;
};
};

Expand All @@ -42,7 +41,6 @@ export type TwitterUserData = {
export type UserTweetTimeline = {
id?: string;
numberDaysTweeted?: number;
valid?: boolean;
errors?: string[];
};

Expand Down Expand Up @@ -138,13 +136,12 @@ export const getTwitterUserData = async (context: TwitterContext, twitterClient:

export const getUserTweetTimeline = async (
context: TwitterContext,
twitterClient: Client,
threshold: number
twitterClient: Client
): Promise<UserTweetTimeline> => {
const tweetDays: Set<string> = new Set();
let nextToken: string | undefined;
let apiCallCount = 0;
if (context.twitter.numberDaysTweeted === undefined || context.twitter.valid === false) {
if (context.twitter.numberDaysTweeted === undefined) {
try {
// return information about the (authenticated) requesting user
const userId = (await twitterClient.users.findMyUser()).data.id;
Expand All @@ -164,31 +161,18 @@ export const getUserTweetTimeline = async (
tweetDays.add(date);
}
nextToken = userTweetDaysResponse.meta.next_token;
// If user has already tweeted for more than the threshold distinct days, no need to continue
if (tweetDays.size >= threshold) {
context.twitter.id = userId;
context.twitter.numberDaysTweeted = tweetDays.size;
context.twitter.valid = true;
return {
id: userId,
numberDaysTweeted: tweetDays.size,
valid: true,
};
}

context.twitter.id = userId;
context.twitter.numberDaysTweeted = tweetDays.size;
// Respect rate limits by sleeping for a short time after each request
await new Promise((resolve) => setTimeout(resolve, 1000));
} while (nextToken && (apiCallCount <= 14 || tweetDays.size >= 120));
context.twitter.id = userId;
context.twitter.numberDaysTweeted = tweetDays.size;
context.twitter.valid = false;
return {
id: context.twitter.id,
numberDaysTweeted: context.twitter.numberDaysTweeted,
valid: context.twitter.valid,
};
} catch (_error) {
const error = _error as ProviderError;

if (error?.response?.status === 429) {
return {
errors: ["Error getting getting Twitter info", "Rate limit exceeded"],
Expand All @@ -202,6 +186,5 @@ export const getUserTweetTimeline = async (
return {
id: context.twitter.id,
numberDaysTweeted: context.twitter.numberDaysTweeted,
valid: context.twitter.valid,
};
};

0 comments on commit 6d96c9f

Please sign in to comment.