-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
453 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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":[]} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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' }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
Oops, something went wrong.