master
yutent 2023-06-07 19:01:53 +08:00
commit a00d013597
7 changed files with 196 additions and 0 deletions

16
.gitignore vendored Normal file
View File

@ -0,0 +1,16 @@
.Spotlight-V100
.Trashes
.DS_Store
.AppleDouble
.LSOverride
._*
.idea
.vscode
*.env
node_modules/
data/logs/
data/ssl/
public/upload/
package-lock.json

16
app.dev.yaml Normal file
View File

@ -0,0 +1,16 @@
script: node ./app.js
cwd: ./
watch: true
name: stats:23333
ignore_watch: [data, public, package.json, package-lock.json, node_modules, .git, .gitignore, app.dev.yaml, app.yaml]
exec_mode: fork
error_file: ./data/logs/error.log
out_file: ./data/logs/out.log
merge_logs: true
min_uptime: 60s
max_restarts: 1
max_memory_restart: 300M
env:
NODE_ENV: development

32
app.js Normal file
View File

@ -0,0 +1,32 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2023/06/07 18:01:50
*/
import Five from '@gm5/core'
import fs from 'iofs'
const app = new Five()
if (fs.isfile('./config.env')) {
//
fs.cat('./config.env')
.toString()
.split('\n')
.forEach(it => {
let tmp = it.trim()
if (tmp) {
tmp = tmp.split(': ')
process.env[tmp[0]] = tmp[1]
}
})
}
app.set({
token: process.env.GITHUB_TOKEN
})
app.preload('./apps/')
app.listen(23333)

16
app.yaml Normal file
View File

@ -0,0 +1,16 @@
script: node ./app.js
cwd: ./
watch: true
name: stats:23333
ignore_watch: [data, public, package.json, package-lock.json, node_modules, .git, .gitignore, app.dev.yaml, app.yaml]
exec_mode: fork
error_file: ./data/logs/error.log
out_file: ./data/logs/out.log
merge_logs: true
min_uptime: 60s
max_restarts: 1
max_memory_restart: 300M
env:
NODE_ENV: production

74
apps/api.js Normal file
View File

@ -0,0 +1,74 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2023/06/07 18:06:57
*/
import Controller from '@gm5/controller'
import { render } from '../lib/svg.js'
export default class Github extends Controller {
__main__() {
//
}
async toplangsAction() {
let { username, count = 6 } = this.request.get()
let token = this.context.get('token')
let { data } = await fetch('https://api.github.com/graphql', {
headers: {
Authorization: 'Bearer ' + token,
'Content-Type': 'application/json'
},
method: 'post',
body: JSON.stringify({
query: `
query {
repositoryOwner(login: "${username}") {
repositories(ownerAffiliations: [OWNER, ORGANIZATION_MEMBER], isFork: false, first: 100){
nodes {
name
languages(first: 10) {
edges {
size
node {
color
name
}
}
}
}
}
}
}
`
})
}).then(r => r.json())
let { nodes } = data.repositoryOwner.repositories
let dict = {}
let langs = []
nodes.forEach(it => {
for (let lang of it.languages.edges) {
if (dict[lang.node.name]) {
dict[lang.node.name].size += lang.size
} else {
dict[lang.node.name] = { size: lang.size, color: lang.node.color }
}
}
})
for (let k in dict) {
langs.push({ name: k, size: dict[k].size, color: dict[k].color })
}
langs.sort((a, b) => b.size - a.size)
this.response.set('Content-Type', 'image/svg+xml')
this.response.end(render({}))
// this.response.send(200, { langs: langs.slice(0, count) })
}
}

35
lib/svg.js Normal file
View File

@ -0,0 +1,35 @@
/**
* {}
* @author yutent<yutent.io@gmail.com>
* @date 2023/06/07 18:41:20
*/
function html(strs, ...vals) {
let output = ''
for (let it of strs) {
output += it + (vals.shift() || '')
}
return output
}
export function render({ title = 'Most Used Languages' }) {
return html`
<svg
width="600"
height="400"
viewBox="0 0 600 400"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<style>
.header {
font: bold 20px 'Segoe UI', Ubuntu, Sans-Serif;
fill: #64b5f6;
}
</style>
<g transform="translate(24, 32)">
<text class="header">${title}</text>
</g>
</svg>
`
}

7
package.json Normal file
View File

@ -0,0 +1,7 @@
{
"name": "github-stats",
"type": "module",
"dependencies": {
"@gm5/core": "^1.1.5"
}
}