added user-fetching functionality on build

This commit is contained in:
Xetera
2019-07-29 04:12:04 -04:00
committed by Jean-Philippe Sirois
parent 1d93f4e160
commit 1b6525f4b4
15 changed files with 172 additions and 32 deletions
+2
View File
@@ -1,3 +1,5 @@
users.json
# Logs
logs
*.log
+2 -1
View File
@@ -6,6 +6,8 @@
<img src="https://cdn.discordapp.com/banners/244230771232079873/ab1a9d5657892f173d5dd752b21d318f.jpg?size=1024" />
</a>
# TPH Website
The official website for [The Programmer's Hangout](https://discord.gg/programming).
## Contributing
@@ -62,4 +64,3 @@ some content here
```
You can look at other resources like [this one](/src/content/docs/javascript/promises/intro.md) for reference when creating your own. We use [ISO8601](https://en.wikipedia.org/wiki/ISO_8601) as the date format to confuse both Americans and Europeans an equal amount.
+33 -13
View File
@@ -1,28 +1,40 @@
const { graphql } = require("gatsby")
const { createFilePath } = require("gatsby-source-filesystem")
const helper = require("./scripts/buildHelpers")
const path = require(`path`)
const fs = require("fs")
const usersEndpoint = id => `https://discordapp.com/api/guilds/${id}/members`
const requiredArticleFrontmatter = ["authors", "date"]
const fetchUsers = () => {
// Fetch user data from discord using bot token here
let users = []
try {
users = JSON.parse(fs.readFileSync("./users.json", "utf-8"))
console.log("(◕◡◕✿) Users list loaded!")
} catch (e) {
console.log("(◕‸ ◕✿) Users list not present, skipping user resolution...")
}
const validateResourceArticle = node => {
const missingField = requiredArticleFrontmatter.find(
required => node.frontmatter[required]
)
if (missingField) {
console.error(
`Article ${node.fileAbsolutePath} is missing field '${missingField}'`
)
process.exit(1)
}
}
const createDocs = async ({ createPage, graphql }) => {
const languageDocs = path.resolve(`src/templates/languagePost.tsx`)
const result = await graphql(`
{
query FetchDocs {
allFile(filter: { sourceInstanceName: { eq: "docs" } }) {
edges {
node {
relativePath
childMarkdownRemark {
frontmatter {
author
date
}
}
}
}
}
@@ -47,11 +59,19 @@ const createDocs = async ({ createPage, graphql }) => {
exports.onCreateNode = async ({ node, getNode, actions }) => {
const { createPage, createNodeField } = actions
if (node.internal.type === "MarkdownRemark") {
const slug = createFilePath({ node, getNode, basePath: "src/content/docs" })
const { frontmatter } = node
const isDoc = Boolean(!frontmatter.path)
if (!isDoc) {
return
}
const authors = helper.resolveAuthors(users, frontmatter.authors)
createNodeField({
node,
name: "slug",
value: slug,
name: "authors",
value: authors,
})
}
}
+34
View File
@@ -5323,6 +5323,25 @@
}
}
},
"discord.js": {
"version": "11.5.1",
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-11.5.1.tgz",
"integrity": "sha512-tGhV5xaZXE3Z+4uXJb3hYM6gQ1NmnSxp9PClcsSAYFVRzH6AJH74040mO3afPDMWEAlj8XsoPXXTJHTxesqcGw==",
"requires": {
"long": "^4.0.0",
"prism-media": "^0.0.3",
"snekfetch": "^3.6.4",
"tweetnacl": "^1.0.0",
"ws": "^6.0.0"
},
"dependencies": {
"tweetnacl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.1.tgz",
"integrity": "sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A=="
}
}
},
"dns-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
@@ -10942,6 +10961,11 @@
"resolved": "https://registry.npmjs.org/lokijs/-/lokijs-1.5.7.tgz",
"integrity": "sha512-2SqUV6JH4f15Z5/7LVsyadSUwHhZppxhujgy/VhVqiRYMGt5oaocb7fV/3JGjHJ6rTuEIajnpTLGRz9cJW/c3g=="
},
"long": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz",
"integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA=="
},
"longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@@ -13580,6 +13604,11 @@
"utila": "~0.4"
}
},
"prism-media": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-0.0.3.tgz",
"integrity": "sha512-c9KkNifSMU/iXT8FFTaBwBMr+rdVcN+H/uNv1o+CuFeTThNZNTOrQ+RgXA1yL/DeLk098duAeRPP3QNPNbhxYQ=="
},
"prismjs": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz",
@@ -15428,6 +15457,11 @@
}
}
},
"snekfetch": {
"version": "3.6.4",
"resolved": "https://registry.npmjs.org/snekfetch/-/snekfetch-3.6.4.tgz",
"integrity": "sha512-NjxjITIj04Ffqid5lqr7XdgwM7X61c/Dns073Ly170bPQHLm6jkmelye/eglS++1nfTWktpP6Y2bFXjdPlQqdw=="
},
"socket.io": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz",
+1
View File
@@ -8,6 +8,7 @@
"@types/ramda": "^0.26.18",
"axios": "^0.19.0",
"babel-plugin-styled-components": "^1.10.6",
"discord.js": "^11.5.1",
"gatsby": "^2.13.39",
"gatsby-image": "^2.2.6",
"gatsby-plugin-manifest": "^2.2.4",
+34
View File
@@ -0,0 +1,34 @@
const DEFAULT_AVATAR_MODULO = 5
module.exports = {
splitHash(identifier) {
const hashLocation = identifier.lastIndexOf("#")
if (hashLocation === -1) {
throw Error(`Invalid name format ${identifier}`)
}
const name = identifier.slice(0, hashLocation)
const hash = identifier.slice(hashLocation + 1)
return [name, hash]
},
getDefaultAvatar(name) {
const [_, hash] = this.splitHash(hashLocation)
const avatar = Number(hash) % DEFAULT_AVATAR_MODULO
return `https://cdn.discordapp.com/embed/avatars/${avatar}.png`
},
resolveAuthor(users, author) {
const target = users.find(user => user.identifier === author)
const [name, hash] = this.splitHash(author)
const avatar = target ? target.avatar : this.getDefaultAvatar(author)
return {
name,
hash,
avatar,
}
},
resolveAuthors(users, authors) {
return authors.map(author => this.resolveAuthor(users, author))
},
}
+42
View File
@@ -0,0 +1,42 @@
// This script will be ran periodically through CI
// don't touch it
const Discord = require("discord.js")
const fs = require("fs")
const { Readable, Writable } = require("stream")
const client = new Discord.Client()
const { BOT_TOKEN } = process.env
const TPH = "244230771232079873"
const DESTINATION = "./users.json"
if (!BOT_TOKEN) {
throw Error("Missing BOT_TOKEN environment variable")
}
const writeS = (content, dest) => {
const source = new Readable()
source.push(JSON.stringify(content))
source.push(null)
source.pipe(dest)
}
client.once("ready", async () => {
console.log("Bot ready, fetching user list...")
const tph = client.guilds.get(TPH)
if (!tph) {
throw Error("Bot is not in TPH, cannot fetch users")
}
const guild = await tph.fetchMembers()
const memberInfo = guild.members.map(member => ({
identifier: `${member.user.username}#${member.user.discriminator}`,
avatar: member.user.displayAvatarURL,
}))
const wrs = fs.createWriteStream(DESTINATION)
console.log(`Fetched ${memberInfo.length} users, writing to ${DESTINATION}`)
writeS(memberInfo, wrs)
process.exit(0)
})
console.log("Attempting to log in...")
client.login(process.env.BOT_TOKEN)
+14
View File
@@ -0,0 +1,14 @@
import React from "react"
function DiscordButton({
lined = false,
children,
}: React.PropsWithChildren<{ lined: boolean }>) {
return (
<button>
<div>{children}</div>
</button>
)
}
export default DiscordButton
+2 -1
View File
@@ -45,7 +45,8 @@ const ALL_DOCS = graphql`
relativePath
childMarkdownRemark {
frontmatter {
author
authors
title
date
}
}
@@ -1,10 +0,0 @@
---
authors:
- "@Xetera"
created_at: 2019/07/27
title: Callbacks
---
# Callbacks are everywhere
If you've been doing javascript for any amount of time you'll have noticed that callbacks appear in just about every single piece of code.
@@ -1,6 +1,6 @@
---
authors:
- "@veksen"
- "veksen#1060"
created_at: "2019/07/27"
---
@@ -1,6 +1,6 @@
---
authors:
- "@Xetera"
- "Xetera#0001"
created_at: 2019/07/26
updated_at: 2019/07/26
title: Introduction to Promises
@@ -1,6 +1,6 @@
---
authors:
- "@Xetera"
- "Xetera#0001"
created_at: "2019/07/26"
---
@@ -1,6 +1,6 @@
---
authors:
- "@supergrecko"
- "supergrecko#3434"
created_at: "2019/07/27"
---
+2 -1
View File
@@ -1,5 +1,6 @@
---
author: "@Xetera"
authors:
- "Xetera#0001"
date: 2019/06/26
---