mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-07 16:06:12 +02:00
Pulling avatar information of authors from discord (#19)
Pulling avatar information of authors from discord
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
users.json
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
<a href="https://discord.gg/programming">
|
<a href="https://discord.gg/programming">
|
||||||
<img src="https://img.shields.io/discord/244230771232079873?color=%23dc1529&label=The%20Programmers%20Hangout" />
|
<img src="https://img.shields.io/discord/244230771232079873?color=%23dc1529&label=The%20Programmers%20Hangout" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://discord.gg/programming">
|
<a href="https://discord.gg/programming">
|
||||||
<img src="https://cdn.discordapp.com/banners/244230771232079873/ab1a9d5657892f173d5dd752b21d318f.jpg?size=1024" />
|
<img src="https://cdn.discordapp.com/banners/244230771232079873/ab1a9d5657892f173d5dd752b21d318f.jpg?size=1024" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
# TPH Website
|
||||||
|
|
||||||
The official website for [The Programmer's Hangout](https://discord.gg/programming).
|
The official website for [The Programmer's Hangout](https://discord.gg/programming).
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
@@ -40,7 +42,7 @@ Gatsby will take care of most of this process by creating a new page and positio
|
|||||||
5. Run through the [setup steps](#setup) if possible to make sure your changes look ok.
|
5. Run through the [setup steps](#setup) if possible to make sure your changes look ok.
|
||||||
6. Create a pull request.
|
6. Create a pull request.
|
||||||
|
|
||||||
#### Frontmatter
|
#### Frontmatter
|
||||||
|
|
||||||
Frontmatter the optional metadata attached to every markdown file, like the list of authors or the creation date of the file. It is essentially just yaml syntax inside `---` delimiters within a markdown file. If you're not familiar with yaml you can find some refreshers [here](https://learnxinyminutes.com/docs/yaml/)
|
Frontmatter the optional metadata attached to every markdown file, like the list of authors or the creation date of the file. It is essentially just yaml syntax inside `---` delimiters within a markdown file. If you're not familiar with yaml you can find some refreshers [here](https://learnxinyminutes.com/docs/yaml/)
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ An example frontmatter might look like this
|
|||||||
```md
|
```md
|
||||||
---
|
---
|
||||||
authors:
|
authors:
|
||||||
- "@Xetera"
|
- "Xetera#0001"
|
||||||
title: "Working with Lists in Elixir"
|
title: "Working with Lists in Elixir"
|
||||||
created_at: 2020/01/30
|
created_at: 2020/01/30
|
||||||
external_resources:
|
external_resources:
|
||||||
@@ -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.
|
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
@@ -1,28 +1,40 @@
|
|||||||
const { graphql } = require("gatsby")
|
const { graphql } = require("gatsby")
|
||||||
const { createFilePath } = require("gatsby-source-filesystem")
|
const { createFilePath } = require("gatsby-source-filesystem")
|
||||||
|
const helper = require("./scripts/buildHelpers")
|
||||||
const path = require(`path`)
|
const path = require(`path`)
|
||||||
|
const fs = require("fs")
|
||||||
|
|
||||||
const usersEndpoint = id => `https://discordapp.com/api/guilds/${id}/members`
|
const requiredArticleFrontmatter = ["authors", "date"]
|
||||||
|
|
||||||
const fetchUsers = () => {
|
let users = []
|
||||||
// Fetch user data from discord using bot token here
|
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 createDocs = async ({ createPage, graphql }) => {
|
||||||
const languageDocs = path.resolve(`src/templates/languagePost.tsx`)
|
const languageDocs = path.resolve(`src/templates/languagePost.tsx`)
|
||||||
|
|
||||||
const result = await graphql(`
|
const result = await graphql(`
|
||||||
{
|
query FetchDocs {
|
||||||
allFile(filter: { sourceInstanceName: { eq: "docs" } }) {
|
allFile(filter: { sourceInstanceName: { eq: "docs" } }) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
relativePath
|
relativePath
|
||||||
childMarkdownRemark {
|
|
||||||
frontmatter {
|
|
||||||
author
|
|
||||||
date
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,11 +59,19 @@ const createDocs = async ({ createPage, graphql }) => {
|
|||||||
exports.onCreateNode = async ({ node, getNode, actions }) => {
|
exports.onCreateNode = async ({ node, getNode, actions }) => {
|
||||||
const { createPage, createNodeField } = actions
|
const { createPage, createNodeField } = actions
|
||||||
if (node.internal.type === "MarkdownRemark") {
|
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({
|
createNodeField({
|
||||||
node,
|
node,
|
||||||
name: "slug",
|
name: "authors",
|
||||||
value: slug,
|
value: authors,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+34
@@ -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": {
|
"dns-equal": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/lokijs/-/lokijs-1.5.7.tgz",
|
||||||
"integrity": "sha512-2SqUV6JH4f15Z5/7LVsyadSUwHhZppxhujgy/VhVqiRYMGt5oaocb7fV/3JGjHJ6rTuEIajnpTLGRz9cJW/c3g=="
|
"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": {
|
"longest": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
|
||||||
@@ -13580,6 +13604,11 @@
|
|||||||
"utila": "~0.4"
|
"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": {
|
"prismjs": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz",
|
"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": {
|
"socket.io": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz",
|
||||||
|
|||||||
+3
-1
@@ -8,6 +8,7 @@
|
|||||||
"@types/ramda": "^0.26.18",
|
"@types/ramda": "^0.26.18",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
"babel-plugin-styled-components": "^1.10.6",
|
"babel-plugin-styled-components": "^1.10.6",
|
||||||
|
"discord.js": "^11.5.1",
|
||||||
"gatsby": "^2.13.39",
|
"gatsby": "^2.13.39",
|
||||||
"gatsby-image": "^2.2.6",
|
"gatsby-image": "^2.2.6",
|
||||||
"gatsby-plugin-manifest": "^2.2.4",
|
"gatsby-plugin-manifest": "^2.2.4",
|
||||||
@@ -58,7 +59,8 @@
|
|||||||
"start": "npm run develop",
|
"start": "npm run develop",
|
||||||
"serve": "gatsby serve",
|
"serve": "gatsby serve",
|
||||||
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"",
|
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"",
|
||||||
"codegen": "graphql-codegen --config codegen.yml"
|
"codegen": "graphql-codegen --config codegen.yml",
|
||||||
|
"fetch-users": "node ./scripts/fetchUsers.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
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(hash) {
|
||||||
|
const avatar = 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(hash)
|
||||||
|
|
||||||
|
return {
|
||||||
|
name,
|
||||||
|
hash,
|
||||||
|
avatar,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resolveAuthors(users, authors) {
|
||||||
|
return authors.map(author => this.resolveAuthor(users, author))
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// 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)
|
||||||
|
return 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).on("finish", () => {
|
||||||
|
console.log("Finished writing list")
|
||||||
|
process.exit(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log("Attempting to log in...")
|
||||||
|
client.login(process.env.BOT_TOKEN)
|
||||||
@@ -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
|
||||||
@@ -45,7 +45,8 @@ const ALL_DOCS = graphql`
|
|||||||
relativePath
|
relativePath
|
||||||
childMarkdownRemark {
|
childMarkdownRemark {
|
||||||
frontmatter {
|
frontmatter {
|
||||||
author
|
authors
|
||||||
|
title
|
||||||
date
|
date
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
authors:
|
||||||
|
- "Xetera#0001"
|
||||||
|
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:
|
authors:
|
||||||
- "@veksen"
|
- "veksen#1060"
|
||||||
created_at: "2019/07/27"
|
created_at: "2019/07/27"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
authors:
|
authors:
|
||||||
- "@Xetera"
|
- "Xetera#0001"
|
||||||
created_at: 2019/07/26
|
created_at: 2019/07/26
|
||||||
updated_at: 2019/07/26
|
updated_at: 2019/07/26
|
||||||
title: Introduction to Promises
|
title: Introduction to Promises
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
authors:
|
authors:
|
||||||
- "@Xetera"
|
- "Xetera#0001"
|
||||||
created_at: "2019/07/26"
|
created_at: "2019/07/26"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
authors:
|
authors:
|
||||||
- "@supergrecko"
|
- "supergrecko#3434"
|
||||||
created_at: "2019/07/27"
|
created_at: "2019/07/27"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
---
|
---
|
||||||
author: "@Xetera"
|
authors:
|
||||||
|
- "Xetera#0001"
|
||||||
date: 2019/06/26
|
date: 2019/06/26
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,15 @@ export const query = graphql`
|
|||||||
file(relativePath: { eq: $file }) {
|
file(relativePath: { eq: $file }) {
|
||||||
post: childMarkdownRemark {
|
post: childMarkdownRemark {
|
||||||
html
|
html
|
||||||
|
fields {
|
||||||
|
authors {
|
||||||
|
name
|
||||||
|
hash
|
||||||
|
avatar
|
||||||
|
}
|
||||||
|
}
|
||||||
frontmatter {
|
frontmatter {
|
||||||
authors
|
date
|
||||||
title
|
title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user