Strongly type everything
This commit is contained in:
parent
842a627cac
commit
fee3766c2b
18 changed files with 221 additions and 109 deletions
|
@ -1,5 +1,6 @@
|
|||
import { Handler } from '@netlify/functions'
|
||||
import fetch from "node-fetch"
|
||||
import { AnilistInfo } from '../../src/components/Anilist'
|
||||
|
||||
const handler: Handler = async (event, context) => {
|
||||
let anilist = await fetch("https://graphql.anilist.co", {
|
||||
|
@ -52,7 +53,7 @@ const handler: Handler = async (event, context) => {
|
|||
|
||||
let p_json = await anilist.json() as {[key: string]: any}
|
||||
let json = p_json.data.MediaList
|
||||
let anime = {
|
||||
let anime: AnilistInfo = {
|
||||
title: json.media.title.romaji,
|
||||
episodes: {
|
||||
watched: json.progress,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Handler } from '@netlify/functions'
|
||||
import { Octokit } from '@octokit/core'
|
||||
import { GithubInfo } from '../../src/components/Github'
|
||||
|
||||
const handler: Handler = async (event, context) => {
|
||||
let octokit = new Octokit({auth: process.env.API_GITHUB})
|
||||
|
@ -20,7 +21,7 @@ const handler: Handler = async (event, context) => {
|
|||
}
|
||||
}
|
||||
|
||||
let info = {
|
||||
let info: GithubInfo = {
|
||||
public: {
|
||||
repo: public_push.repo.name,
|
||||
date: public_push.created_at.substring(0, public_push.created_at.indexOf("T"))
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Handler } from '@netlify/functions'
|
||||
import fetch from "node-fetch"
|
||||
import { GitlabInfo } from '../../src/components/Gitlab'
|
||||
|
||||
const handler: Handler = async (event, context) => {
|
||||
let gitlab = await fetch("https://gitlab.com/api/v4/events?action=pushed", {
|
||||
|
@ -19,11 +20,13 @@ const handler: Handler = async (event, context) => {
|
|||
}
|
||||
|
||||
let json = await gitlab.json() as {[key: string]: any}
|
||||
let date = json[0].created_at.substring(0, json[0].created_at.indexOf("T"))
|
||||
let activity: GitlabInfo = {
|
||||
date: json[0].created_at.substring(0, json[0].created_at.indexOf("T"))
|
||||
}
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({date})
|
||||
body: JSON.stringify(activity)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { Handler } from '@netlify/functions'
|
||||
import { api } from "./shared/api"
|
||||
import { HacktheboxInfo } from '../../src/components/Hackthebox'
|
||||
|
||||
const handler: Handler = async (event, context) => {
|
||||
let hackthebox = await api<{
|
||||
let hackthebox: {profile: {activity: HacktheboxInfo[]}} = await api<{
|
||||
profile: {
|
||||
activity: {
|
||||
id: string
|
||||
|
@ -16,7 +17,7 @@ const handler: Handler = async (event, context) => {
|
|||
}>
|
||||
(`https://www.hackthebox.com/api/v4/profile/activity/1063999`)
|
||||
|
||||
let pwn = hackthebox.profile.activity.find((a) => a.object_type === "machine")
|
||||
let pwn = hackthebox.profile.activity.find((a: HacktheboxInfo) => a!.object_type === "machine")
|
||||
if (!pwn) {
|
||||
return {
|
||||
statusCode: 404,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Handler } from '@netlify/functions'
|
||||
import { API, APIError, User } from 'osu-api-v2-js'
|
||||
import { OsuInfo } from '../../src/components/Osu'
|
||||
|
||||
const handler: Handler = async (event, context) => {
|
||||
let api = await API.createAsync({id: 11451, secret: process.env.API_OSU!})
|
||||
|
@ -24,7 +25,7 @@ const handler: Handler = async (event, context) => {
|
|||
}
|
||||
}
|
||||
|
||||
let ranks = {
|
||||
let ranks: OsuInfo = {
|
||||
osu: [0,0],
|
||||
taiko: [0,0],
|
||||
fruits: [0,0],
|
||||
|
|
BIN
public/mode-fruits.png
Normal file
BIN
public/mode-fruits.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
public/mode-mania.png
Normal file
BIN
public/mode-mania.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
public/mode-osu.png
Normal file
BIN
public/mode-osu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
public/mode-taiko.png
Normal file
BIN
public/mode-taiko.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -50,7 +50,8 @@ body {
|
|||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
.info > * {
|
||||
padding: 3px 10px;
|
||||
margin: auto;
|
||||
.info canvas {
|
||||
height: 110px !important;
|
||||
width: 220px !important;
|
||||
margin: 0;
|
||||
}
|
||||
|
|
12
src/App.jsx
12
src/App.jsx
|
@ -3,11 +3,11 @@ import "./App.css";
|
|||
|
||||
import Lastfm from "./components/Lastfm";
|
||||
import Speedruncom from "./components/Speedruncom";
|
||||
import Hackthebox from "./components/hackthebox";
|
||||
import Github from "./components/github";
|
||||
import Gitlab from "./components/gitlab";
|
||||
import Osu from "./components/osu";
|
||||
import Anilist from "./components/anilist";
|
||||
import Hackthebox from "./components/Hackthebox";
|
||||
import Github from "./components/Github";
|
||||
import Gitlab from "./components/Gitlab";
|
||||
import Osu from "./components/Osu";
|
||||
import Anilist from "./components/Anilist";
|
||||
|
||||
function App() {
|
||||
return (
|
||||
|
@ -16,10 +16,10 @@ function App() {
|
|||
<div className="info_container">
|
||||
<Lastfm/>
|
||||
<Speedruncom/>
|
||||
<Osu/>
|
||||
{/* <Hackthebox/>
|
||||
<Github/>
|
||||
<Gitlab/>
|
||||
<Osu/>
|
||||
<Anilist/> */}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
export type AnilistInfo = {
|
||||
title: string
|
||||
episodes: {
|
||||
watched: number
|
||||
total: number
|
||||
},
|
||||
score: number
|
||||
startDate: string
|
||||
updateDate: string
|
||||
endDate: string
|
||||
cover: string
|
||||
} | undefined
|
||||
|
||||
export default function Anilist() {
|
||||
const [anilist, setAnilist] = useState({})
|
||||
const [anilist, setAnilist]: [AnilistInfo, React.Dispatch<React.SetStateAction<AnilistInfo>>] = useState()
|
||||
const getAnilist = async () => {
|
||||
const response = await fetch("/.netlify/functions/anilist").then(r => r.json())
|
||||
setAnilist(response)
|
||||
|
@ -11,7 +24,7 @@ export default function Anilist() {
|
|||
getAnilist()
|
||||
}, [])
|
||||
|
||||
if (anilist.title === undefined) {
|
||||
if (anilist === undefined) {
|
||||
return <></>
|
||||
}
|
||||
return (
|
|
@ -1,7 +1,17 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
export type GithubInfo = {
|
||||
public: {
|
||||
repo: string
|
||||
date: string
|
||||
}
|
||||
private: {
|
||||
date: string
|
||||
}
|
||||
} | undefined
|
||||
|
||||
export default function Github() {
|
||||
const [github, setGithub] = useState({})
|
||||
const [github, setGithub]: [GithubInfo, React.Dispatch<React.SetStateAction<GithubInfo>>] = useState()
|
||||
const getGithub = async () => {
|
||||
const response = await fetch("/.netlify/functions/github").then(r => r.json())
|
||||
setGithub(response)
|
||||
|
@ -11,7 +21,7 @@ export default function Github() {
|
|||
getGithub()
|
||||
}, [])
|
||||
|
||||
if (github.public === undefined || github.public.date === undefined) {
|
||||
if (github === undefined) {
|
||||
return <></>
|
||||
}
|
||||
return (
|
|
@ -1,7 +1,11 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
export type GitlabInfo = {
|
||||
date: string
|
||||
} | undefined
|
||||
|
||||
export default function Gitlab() {
|
||||
const [gitlab, setGitlab] = useState({})
|
||||
const [gitlab, setGitlab]: [GitlabInfo, React.Dispatch<React.SetStateAction<GitlabInfo>>] = useState()
|
||||
const getGitlab = async () => {
|
||||
const response = await fetch("/.netlify/functions/gitlab").then(r => r.json())
|
||||
setGitlab(response)
|
||||
|
@ -11,7 +15,7 @@ export default function Gitlab() {
|
|||
getGitlab()
|
||||
}, [])
|
||||
|
||||
if (gitlab.date === undefined) {
|
||||
if (gitlab === undefined) {
|
||||
return <></>
|
||||
}
|
||||
return (
|
|
@ -1,7 +1,16 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
export type HacktheboxInfo = {
|
||||
id: string
|
||||
date_diff: string
|
||||
object_type: string
|
||||
type: string
|
||||
name: string
|
||||
machine_avatar: string
|
||||
} | undefined
|
||||
|
||||
export default function Hackthebox() {
|
||||
const [hackthebox, setHackthebox] = useState({})
|
||||
const [hackthebox, setHackthebox]: [HacktheboxInfo, React.Dispatch<React.SetStateAction<HacktheboxInfo>>] = useState()
|
||||
const getHackthebox = async () => {
|
||||
const response = await fetch("/.netlify/functions/hackthebox").then(r => r.json())
|
||||
setHackthebox(response)
|
||||
|
@ -11,7 +20,7 @@ export default function Hackthebox() {
|
|||
getHackthebox()
|
||||
}, [])
|
||||
|
||||
if (hackthebox.name === undefined) {
|
||||
if (hackthebox === undefined) {
|
||||
return <></>
|
||||
}
|
||||
|
126
src/components/Osu.tsx
Normal file
126
src/components/Osu.tsx
Normal file
|
@ -0,0 +1,126 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
LineElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
} from 'chart.js';
|
||||
import { Line } from 'react-chartjs-2';
|
||||
import Info from "./structures/info";
|
||||
import "../style/osu.css"
|
||||
|
||||
export type OsuInfo = {
|
||||
osu: number[]
|
||||
taiko: number[]
|
||||
fruits: number[]
|
||||
mania: number[]
|
||||
} | undefined
|
||||
|
||||
ChartJS.register(
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
LineElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend
|
||||
);
|
||||
|
||||
export default function Osu() {
|
||||
const [osu, setOsu]: [OsuInfo, React.Dispatch<React.SetStateAction<OsuInfo>>] = useState()
|
||||
const getOsu = async () => {
|
||||
const response = await fetch("/.netlify/functions/osu").then(r => r.json())
|
||||
setOsu(response)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getOsu()
|
||||
}, [])
|
||||
|
||||
if (osu === undefined) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
function shapeData(ranks: number[]) {
|
||||
let labels = ranks.map((r, i) => `${i + 1} days ago`).reverse()
|
||||
return {
|
||||
labels,
|
||||
datasets: [{
|
||||
id: 1,
|
||||
label: "",
|
||||
data: ranks,
|
||||
borderColor: `rgb(
|
||||
${String(ranks[0]).slice(-2)},
|
||||
${String(ranks[ranks.length/2]).slice(-2)},
|
||||
${String(ranks[ranks.length-1]).slice(-2)}
|
||||
)`,
|
||||
tension: 0.5,
|
||||
fill: false,
|
||||
pointStyle: false as false
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
let options = {
|
||||
scales: {
|
||||
y: {
|
||||
reverse: true,
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Info
|
||||
title="osu!"
|
||||
link="https://osu.ppy.sh/users/7276846"
|
||||
description="Rhythm games"
|
||||
elements={[
|
||||
<div>
|
||||
<a href="https://osu.ppy.sh/users/7276846/osu" target="_blank" className="gamemode-title">
|
||||
<img src="mode-osu.png"></img>
|
||||
<h2><strong>osu!</strong></h2>
|
||||
</a>
|
||||
<div className="bg-white">
|
||||
<Line datasetIdKey="1" data={shapeData(osu.osu)} options={options}/>
|
||||
</div>
|
||||
</div>,
|
||||
<div className="mt-6">
|
||||
<a href="https://osu.ppy.sh/users/7276846/taiko" target="_blank" className="gamemode-title">
|
||||
<img src="mode-taiko.png"></img>
|
||||
<h2>osu!<strong>taiko</strong></h2>
|
||||
</a>
|
||||
<div className="bg-white">
|
||||
<Line datasetIdKey="1" data={shapeData(osu.taiko)} options={options}/>
|
||||
</div>
|
||||
</div>,
|
||||
<div className="mt-6">
|
||||
<a href="https://osu.ppy.sh/users/7276846/fruits" target="_blank" className="gamemode-title">
|
||||
<img src="mode-fruits.png"></img>
|
||||
<h2>osu!<strong>catch</strong></h2>
|
||||
</a>
|
||||
<div className="bg-white">
|
||||
<Line datasetIdKey="1" data={shapeData(osu.fruits)} options={options}/>
|
||||
</div>
|
||||
</div>,
|
||||
<div className="mt-6">
|
||||
<a href="https://osu.ppy.sh/users/7276846/mania" target="_blank" className="gamemode-title">
|
||||
<img src="mode-mania.png"></img>
|
||||
<h2>osu!<strong>mania</strong></h2>
|
||||
</a>
|
||||
<div className="bg-white">
|
||||
<Line datasetIdKey="1" data={shapeData(osu.mania)} options={options}/>
|
||||
</div>
|
||||
</div>
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
LineElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend,
|
||||
scales,
|
||||
} from 'chart.js';
|
||||
import { Line } from 'react-chartjs-2';
|
||||
|
||||
ChartJS.register(
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
LineElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend
|
||||
);
|
||||
|
||||
export default function Osu() {
|
||||
const [osu, setOsu] = useState({})
|
||||
const getOsu = async () => {
|
||||
const response = await fetch("/.netlify/functions/osu").then(r => r.json())
|
||||
setOsu(response)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getOsu()
|
||||
}, [])
|
||||
|
||||
if (osu.osu === undefined) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
function shapeData(ranks) {
|
||||
let labels = ranks.map((r, i) => `${i + 1} days ago`).reverse()
|
||||
return {
|
||||
labels,
|
||||
datasets: [{
|
||||
id: 1,
|
||||
label: "",
|
||||
data: ranks,
|
||||
borderColor: `rgb(
|
||||
${String(ranks[0]).slice(-2)},
|
||||
${String(ranks[ranks.length/2]).slice(-2)},
|
||||
${String(ranks[ranks.length-1]).slice(-2)}
|
||||
)`,
|
||||
tension: 0.5,
|
||||
fill: false,
|
||||
pointStyle: false
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
let options = {
|
||||
scales: {
|
||||
y: {
|
||||
reverse: true,
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div id="osu">
|
||||
<Line datasetIdKey="1" data={shapeData(osu.osu)} options={options}/>
|
||||
<Line datasetIdKey="1" data={shapeData(osu.taiko)} options={options}/>
|
||||
<Line datasetIdKey="1" data={shapeData(osu.fruits)} options={options}/>
|
||||
<Line datasetIdKey="1" data={shapeData(osu.mania)} options={options}/>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
.gamemode-title {
|
||||
display: flex;
|
||||
margin: auto;
|
||||
margin-bottom: 6px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.gamemode-title img {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.gamemode-title h2 {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
font-size: 24px;
|
||||
padding-bottom: 0.4rem;
|
||||
}
|
||||
|
||||
.gamemode-title > * {
|
||||
margin-left: 6px;
|
||||
margin-right: 6px;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue