├── .eslintrc.json
├── public
├── favicon.ico
└── vercel.svg
├── postcss.config.js
├── .idea
├── .gitignore
├── vcs.xml
├── prettier.xml
├── discord.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── modules.xml
└── server-count.iml
├── next.config.js
├── pages
├── _app.js
├── api
│ ├── login.js
│ └── cb.js
├── cb.jsx
├── Components
│ └── Footer.jsx
└── index.js
├── README.md
├── tailwind.config.js
├── styles
├── globals.css
└── Home.module.css
├── .gitignore
└── package.json
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flowergardn/server-counter/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | }
5 |
6 | module.exports = nextConfig
7 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import '../styles/globals.css'
2 |
3 | function MyApp({ Component, pageProps }) {
4 | return
5 | }
6 |
7 | export default MyApp
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # server-count
2 |
3 | My friend was trying to come up with a way to get the count of all your servers on Discord, so i decided to just ease his process to make 100x easier :)
4 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/prettier.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: [
3 | "./pages/**/*.{js,ts,jsx,tsx}",
4 | "./components/**/*.{js,ts,jsx,tsx}",
5 | ],
6 | theme: {
7 | extend: {},
8 | },
9 | plugins: [],
10 | }
11 |
--------------------------------------------------------------------------------
/.idea/discord.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/pages/api/login.js:
--------------------------------------------------------------------------------
1 | export default async function handler(req, res) {
2 | res.redirect(
3 | "https://discord.com/api/oauth2/authorize?client_id=969790016496746516&redirect_uri=https%3A%2F%2Fserver-counter.vercel.app%2Fcb&response_type=token&scope=identify%20guilds"
4 | );
5 | }
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/pages/cb.jsx:
--------------------------------------------------------------------------------
1 | import { useRouter } from 'next/router'
2 | import { useEffect } from 'react'
3 |
4 | export default function Callback() {
5 | const router = useRouter()
6 |
7 | useEffect(() => {
8 | const querySplit = router.asPath.split('&')
9 | const access_token = querySplit[1].split('=')[1]
10 | window.location.href = `/api/cb?token=${access_token}`
11 | }, [])
12 |
13 | return <>>
14 | }
15 |
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | html,
6 | body {
7 | padding: 0;
8 | margin: 0;
9 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
10 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
11 | background-color: #0F172A;
12 | }
13 |
14 | a {
15 | color: inherit;
16 | text-decoration: none;
17 | }
18 |
19 | * {
20 | box-sizing: border-box;
21 | }
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 | .pnpm-debug.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
--------------------------------------------------------------------------------
/.idea/server-count.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/pages/api/cb.js:
--------------------------------------------------------------------------------
1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction
2 |
3 | import axios from 'axios'
4 | import { serialize } from 'cookie'
5 |
6 | export default async function handler(req, res) {
7 | const { token: discordToken } = req.query
8 |
9 | // If no token was passed through, send a 400 status code
10 | if (!discordToken)
11 | res.status(400).json({ success: false, err: `Malformed token` })
12 |
13 | res.setHeader(
14 | 'Set-Cookie',
15 | serialize('token', discordToken, { path: '/', maxAge: 60 * 60 * 24 * 7 })
16 | )
17 |
18 | res.redirect('/')
19 | }
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "server-count",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "axios": "^0.27.2",
13 | "cookie": "^0.5.0",
14 | "js-cookie": "^3.0.1",
15 | "next": "12.1.5",
16 | "react": "18.1.0",
17 | "react-dom": "18.1.0"
18 | },
19 | "devDependencies": {
20 | "autoprefixer": "^10.4.5",
21 | "eslint": "8.14.0",
22 | "eslint-config-next": "12.1.5",
23 | "postcss": "^8.4.13",
24 | "prettier": "^2.6.2",
25 | "tailwindcss": "^3.0.24"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pages/Components/Footer.jsx:
--------------------------------------------------------------------------------
1 | export default function Footer() {
2 | return (
3 |
28 | );
29 | }
30 |
--------------------------------------------------------------------------------
/styles/Home.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | padding: 0 2rem;
3 | }
4 |
5 | .main {
6 | min-height: 100vh;
7 | padding: 4rem 0;
8 | flex: 1;
9 | display: flex;
10 | flex-direction: column;
11 | justify-content: center;
12 | align-items: center;
13 | }
14 |
15 | .footer {
16 | display: flex;
17 | flex: 1;
18 | padding: 2rem 0;
19 | border-top: 1px solid #eaeaea;
20 | justify-content: center;
21 | align-items: center;
22 | }
23 |
24 | .footer a {
25 | display: flex;
26 | justify-content: center;
27 | align-items: center;
28 | flex-grow: 1;
29 | }
30 |
31 | .title a {
32 | color: #0070f3;
33 | text-decoration: none;
34 | }
35 |
36 | .title a:hover,
37 | .title a:focus,
38 | .title a:active {
39 | text-decoration: underline;
40 | }
41 |
42 | .title {
43 | margin: 0;
44 | line-height: 1.15;
45 | font-size: 4rem;
46 | }
47 |
48 | .title,
49 | .description {
50 | text-align: center;
51 | }
52 |
53 | .description {
54 | margin: 4rem 0;
55 | line-height: 1.5;
56 | font-size: 1.5rem;
57 | }
58 |
59 | .code {
60 | background: #fafafa;
61 | border-radius: 5px;
62 | padding: 0.75rem;
63 | font-size: 1.1rem;
64 | font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
65 | Bitstream Vera Sans Mono, Courier New, monospace;
66 | }
67 |
68 | .grid {
69 | display: flex;
70 | align-items: center;
71 | justify-content: center;
72 | flex-wrap: wrap;
73 | max-width: 800px;
74 | }
75 |
76 | .card {
77 | margin: 1rem;
78 | padding: 1.5rem;
79 | text-align: left;
80 | color: inherit;
81 | text-decoration: none;
82 | border: 1px solid #eaeaea;
83 | border-radius: 10px;
84 | transition: color 0.15s ease, border-color 0.15s ease;
85 | max-width: 300px;
86 | }
87 |
88 | .card:hover,
89 | .card:focus,
90 | .card:active {
91 | color: #0070f3;
92 | border-color: #0070f3;
93 | }
94 |
95 | .card h2 {
96 | margin: 0 0 1rem 0;
97 | font-size: 1.5rem;
98 | }
99 |
100 | .card p {
101 | margin: 0;
102 | font-size: 1.25rem;
103 | line-height: 1.5;
104 | }
105 |
106 | .logo {
107 | height: 1em;
108 | margin-left: 0.5rem;
109 | }
110 |
111 | @media (max-width: 600px) {
112 | .grid {
113 | width: 100%;
114 | flex-direction: column;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import Cookies from "js-cookie";
2 | import { useEffect, useState } from "react";
3 | import axios from "axios";
4 | import Head from "next/head";
5 | import Footer from "./Components/Footer";
6 |
7 | export default function Home() {
8 | const [token, setToken] = useState("");
9 | const [servers, setServers] = useState([]);
10 |
11 | useEffect(() => {
12 | const _token = Cookies.get("token");
13 | if (_token && _token.length > 5) {
14 | setToken(Cookies.get("token"));
15 | (async () => {
16 | if (!localStorage.getItem("servers")) {
17 | console.log(
18 | `Calling Discord API with the token: ${Cookies.get("token")}`
19 | );
20 | let discordInfo;
21 | try {
22 | discordInfo = (
23 | await axios.get(`https://discord.com/api/users/@me/guilds`, {
24 | // We specify the access token in the headers, to tell Discord that we want this specific users' information.
25 | headers: { Authorization: `Bearer ${Cookies.get("token")}` },
26 | })
27 | ).data;
28 | } catch (err) {
29 | console.error(err);
30 | }
31 | setServers(discordInfo);
32 | } else setServers(JSON.parse(localStorage.getItem("servers")));
33 | })();
34 | }
35 | }, []);
36 |
37 | useEffect(() => {
38 | if (servers && servers.length !== 0) {
39 | localStorage.setItem("servers", JSON.stringify(servers, null, 4));
40 | }
41 | }, [servers]);
42 |
43 | function Page(props) {
44 | return (
45 | <>
46 |
47 |
{props.children}
48 |
49 | >
50 | );
51 | }
52 |
53 | function loggedIn() {
54 | return (
55 |
56 |
57 | You are in {servers.length} servers!
58 |
59 |
60 | );
61 | }
62 |
63 | function loggedOut() {
64 | return (
65 |
66 |
67 | You are currently not logged in
68 |
69 |
70 | Click{" "}
71 |
75 | here
76 | {" "}
77 | to login with Discord
78 |
79 |
80 | );
81 | }
82 |
83 | return (
84 | <>
85 |
86 |
90 |
91 |
92 |
93 |
94 |
98 | Server counter
99 |
100 | {token === "" ? loggedOut() : loggedIn()}
101 |
102 | >
103 | );
104 | }
105 |
--------------------------------------------------------------------------------