Skip to content

Commit

Permalink
✨ intermediate commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sksuryan committed Dec 24, 2021
1 parent a75eb13 commit a12021a
Show file tree
Hide file tree
Showing 13 changed files with 453 additions and 24 deletions.
1 change: 1 addition & 0 deletions assets/animations/loading.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"4.8.0","meta":{"g":"LottieFiles AE 1.0.0","a":"","k":"","d":"","tc":"#3250C3"},"fr":29.9700012207031,"ip":0,"op":150.000006109625,"w":3840,"h":2160,"nm":"Loading","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"center","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1920,1080,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[1256.807,1256.807],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":111,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.997614841835,0.997614841835,1],"ix":4},"o":{"a":0,"k":0,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-65.41,-19.459],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[16.318,16.157],"ix":3},"r":{"a":0,"k":-1651.434,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"round 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1920,1080,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[1256.807,1256.807],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.99816942402,0.99816942402,0.99816942402,1],"ix":4},"o":{"a":0,"k":40,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-65.41,-19.459],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":0,"s":[50.155,50.155]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":82,"s":[16.155,16.155]},{"t":150.000006109625,"s":[50.155,50.155]}],"ix":3},"r":{"a":0,"k":-1651.434,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"round 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1920,1080,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[1256.807,1256.807],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.99816942402,0.99816942402,0.99816942402,1],"ix":4},"o":{"a":0,"k":40,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-65.41,-19.459],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":0,"s":[67.797,67.797]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":40,"s":[17.797,17.797]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":109,"s":[51.797,51.797]},{"t":150.000006109625,"s":[67.797,67.797]}],"ix":3},"r":{"a":0,"k":-1651.434,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"round 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1920,1080,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[1256.807,1256.807],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.99816942402,0.99816942402,0.99816942402,1],"ix":4},"o":{"a":0,"k":40,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-65.41,-19.459],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":0,"s":[85.27,85.27]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":18,"s":[60.27,60.27]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":64,"s":[14.27,14.27]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":82,"s":[75.27,75.27]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":117,"s":[89.27,89.271]},{"t":150.000006109625,"s":[85.27,85.271]}],"ix":3},"r":{"a":0,"k":-1651.434,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"background","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[1920,1080,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[1256.807,1256.807],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.99816942402,0.99816942402,0.99816942402,1],"ix":4},"o":{"a":0,"k":40,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-65.41,-19.459],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":0,"s":[100,100]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":10,"s":[65,65]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":43,"s":[46,46]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":72,"s":[15,15]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":90,"s":[63,63]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":120,"s":[76,76]},{"t":150.000006109625,"s":[100,100]}],"ix":3},"r":{"a":0,"k":-1651.434,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900.000036657751,"st":0,"bm":0}],"markers":[]}
2 changes: 1 addition & 1 deletion components/LetsGo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const ArrowIcon: FC = () => (
<g id={styles.waveGroup}>
<path
id={styles.waves}
d='M128 140H0V42.6426C17.0667 42.6426 14.8372 11.8952 32.1939 12.0003C49.4413 12.1047 46.7526 42.5382 64 42.6426C81.3568 42.7477 78.8372 11.8952 96.1939 12.0003C113.441 12.1047 110.545 42.6426 128 42.6426V140Z'
d='M128 108.501H0V11.1435C17.0667 11.1435 14.8372 0.895728 32.1939 1.00082C49.4413 1.10526 46.7526 11.039 64 11.1435C81.3568 11.2486 78.8372 0.895698 96.1939 1.00079C113.441 1.10523 110.545 11.1435 128 11.1435V108.501Z'
fill='url(#waves-gradient)'
/>
</g>
Expand Down
31 changes: 31 additions & 0 deletions components/LoadingScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { FC } from 'react';
import Lottie, { Options } from 'react-lottie';

import styles from '../styles/LoadingScreen.module.scss';
import LoadingAnimation from '../assets/animations/loading.json';

const LoadingScreen: FC = () => {
const defaultOptions: Options = {
loop: true,
autoplay: true,
animationData: LoadingAnimation,
rendererSettings: {
preserveAspectRatio: 'xMidYMid slice',
},
};

return (
<div className={styles.container}>
<Lottie options={defaultOptions} width={168} height={168} />
<p>"hey cortana!"</p>
<p>"cue elevator music"</p>
<p>.</p>
<p>.</p>
<p>.</p>
<p>.</p>
<h3>uhh nevermind...</h3>
</div>
);
};

export default LoadingScreen;
7 changes: 7 additions & 0 deletions interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface TwitterBearerToken {
token_type: string;
expires_in: number;
access_token: string;
scope: string;
refresh_token?: string;
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
"lint": "next lint"
},
"dependencies": {
"@types/react-lottie": "^1.2.6",
"next": "12.0.7",
"react": "17.0.2",
"react-dom": "17.0.2",
"sass": "^1.45.0"
"react-lottie": "^1.2.3",
"sass": "^1.45.0",
"twitter-api-v2": "^1.8.0"
},
"devDependencies": {
"@types/node": "16.11.13",
Expand Down
13 changes: 0 additions & 13 deletions pages/api/hello.ts

This file was deleted.

127 changes: 127 additions & 0 deletions pages/api/letsgowrapped.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import TwitterApi, { TweetV2, TwitterApiReadOnly } from 'twitter-api-v2';
import { TwitterBearerToken } from '../../interfaces';

type Data = {
results?: any;
error?: string;
};

export default async function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
let twitterClient: TwitterApiReadOnly;

const token = JSON.parse(req.body) as TwitterBearerToken;

if (token.access_token) {
twitterClient = new TwitterApi(token.access_token).readOnly;

const user = await twitterClient.v2.userByUsername('_rvers', {
'user.fields': ['profile_image_url'],
});
const userID = user?.data?.id;

let tweetsPaginator = await twitterClient.v2.userTimeline(userID, {
max_results: 100,
start_time: '2021-01-01T00:00:00Z',
'tweet.fields': ['entities', 'text', 'attachments', 'public_metrics'],
exclude: 'retweets',
});
const tweets: TweetV2[] = tweetsPaginator.tweets;

while (!tweetsPaginator.done) {
tweetsPaginator = await tweetsPaginator.fetchNext();
tweets.concat(tweetsPaginator.tweets);
}

const favPeopleSet = new Set();

const overallStats = {
totalLikes: 0,
totalRetweets: 0,
};
const favPeopleObj: { [key: string]: number } = {};
let mostLikedTweet: { tweet: TweetV2; likes: number } | undefined;
const numberOfTweetsThisYear = tweets.length;

const reg =
'(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c\ude32-\ude3a]|[\ud83c\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])';

const emojiObject: { [key: string]: number } = {};

tweets.forEach((tweet) => {
tweet.entities?.mentions
? tweet.entities.mentions.forEach((user) => {
if (favPeopleSet.has(user.username)) {
favPeopleObj[user.username] += 1;
} else {
favPeopleObj[user.username] = 1;
favPeopleSet.add(user.username);
}
})
: [];

let likes = 0;

if (tweet.public_metrics) {
overallStats.totalLikes += tweet.public_metrics.like_count;
overallStats.totalRetweets += tweet.public_metrics.retweet_count;

likes = tweet.public_metrics.like_count;
}

const emojis = tweet.text.match(reg);
emojis?.forEach((elt) => {
if (emojiObject[elt]) {
emojiObject[elt] += 1;
} else {
emojiObject[elt] = 1;
}
});

if (!mostLikedTweet) {
mostLikedTweet = {
tweet,
likes,
};
} else if (mostLikedTweet.likes < likes) {
mostLikedTweet = {
tweet,
likes,
};
}
});

const numberOfPeopleInteractedWith = Object.keys(favPeopleObj).length;
const favObj = Object.keys(favPeopleObj)
.sort((a, b) => favPeopleObj[b] - favPeopleObj[a])
.slice(0, 6);

const topEmojis = Object.keys(emojiObject)
.sort((a, b) => emojiObject[b] - emojiObject[a])
.slice(0, 30);

const topFollowersProfile = await twitterClient.v2.usersByUsernames(
favObj,
{
'user.fields': ['profile_image_url'],
}
);

const results = {
user,
topEmojis,
overallStats,
mostLikedTweet,
topFollowersProfile,
numberOfTweetsThisYear,
numberOfPeopleInteractedWith,
};

res.status(200).json({ results });
} else {
res.status(500).json({ error: 'Internal Server Error' });
}
}
76 changes: 76 additions & 0 deletions pages/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import Head from 'next/head';
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { GetServerSideProps, GetServerSidePropsContext, NextPage } from 'next';

import { TwitterBearerToken } from '../interfaces';
import LoadingScreen from '../components/LoadingScreen';

const url = process.env.NODE_ENV
? 'http://localhost:3000'
: 'https://your_deployment.server.com';

interface PropType {
accessToken: TwitterBearerToken;
}

const Wrapped: NextPage<PropType> = (props: PropType) => {
const router = useRouter();

console.log(props);

useEffect(() => {
(async () => {
const results = await fetch(url + '/api/letsgowrapped', {
method: 'POST',
body: JSON.stringify(props.accessToken),
});

// router.push('/wrapped');
const data = await results.json();
console.log(data);
})();
}, []);

return (
<div>
<Head>
<title>Twitter Wrapped | Loading</title>
</Head>
<LoadingScreen />
</div>
);
};

export const getServerSideProps: GetServerSideProps = async (
ctx: GetServerSidePropsContext
) => {
let results = {};

if (typeof ctx.query.code === 'string' && process.env.CLIENT_ID) {
const base64Encoded = Buffer.from(
`${process.env.CLIENT_ID}:${process.env.CLIENT_SECRET}`
).toString('base64');

const res = await fetch('https://api.twitter.com/2/oauth2/token', {
method: 'POST',
headers: {
Authorization: `Basic ${base64Encoded}`,
},
body: new URLSearchParams({
code: ctx.query.code,
grant_type: 'authorization_code',
client_id: process.env.CLIENT_ID,
code_verifier: 'challenge',
redirect_uri: 'http://localhost:3000/loading',
}),
});

console.log(res.status);

results = (await res.json()) as TwitterBearerToken;
}
return { props: { accessToken: results } };
};

export default Wrapped;
Loading

0 comments on commit a12021a

Please sign in to comment.