Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add GitHub Skyline plugin
  • Loading branch information
lowlighter committed Feb 19, 2021
commit d2635dda25d97ce59b47383eacd41146de6bfe20
163 changes: 80 additions & 83 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
"express": "^4.17.1",
"express-rate-limit": "^5.2.6",
"faker": "^5.4.0",
"gifencoder": "^2.0.1",
"image-to-base64": "^2.1.1",
"js-yaml": "^4.0.0",
"memory-cache": "^0.2.0",
"png-js": "^1.0.0",
"prismjs": "^1.23.0",
"puppeteer": "^7.1.0",
"simple-git": "^2.35.0",
Expand Down
33 changes: 33 additions & 0 deletions source/app/metrics/utils.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//Imports
import fs from "fs/promises"
import fss from "fs"
import os from "os"
import paths from "path"
import url from "url"
Expand All @@ -10,7 +11,10 @@
import imgb64 from "image-to-base64"
import git from "simple-git"
import twemojis from "twemoji-parser"
import GIFEncoder from "gifencoder"
import PNG from "png-js"

//Exports
export {fs, os, paths, url, util, processes, axios, puppeteer, imgb64, git}

/**Returns module __dirname */
Expand Down Expand Up @@ -189,3 +193,32 @@
export async function wait(seconds) {
await new Promise(solve => setTimeout(solve, seconds*1000)) //eslint-disable-line no-promise-executor-return
}

/**Create gif from puppeteer browser */
export async function puppeteergif({page, width, height, frames, x = 0, y = 0, repeat = true, delay = 150, quality = 10}) {
//Create temporary stream
const path = paths.join(os.tmpdir(), `${Math.round(Math.random()*1000000000)}.gif`)
console.debug(`metrics/puppeteergif > set write stream to "${path}"`)
if (fss.existsSync(path))
await fs.unlink(path)
//Create encoder
const encoder = new GIFEncoder(width, height)
encoder.createWriteStream().pipe(fss.createWriteStream(path))
encoder.start()
encoder.setRepeat(repeat ? 0 : -1)
encoder.setDelay(delay)
encoder.setQuality(quality)
//Register frames
for (let i = 0; i < frames; i++) {
const buffer = new PNG(await page.screenshot({clip:{width, height, x, y}}))
encoder.addFrame(await new Promise(solve => buffer.decode(pixels => solve(pixels)))) //eslint-disable-line no-promise-executor-return
if (frames%10 === 0)
console.debug(`metrics/puppeteergif > processed ${i}/${frames} frames`)
}
console.debug(`metrics/puppeteergif > processed ${frames}/${frames} frames`)
//Close encoder and convert to base64
encoder.finish()
const result = await fs.readFile(path, "base64")
await fs.unlink(path)
return result
}
26 changes: 26 additions & 0 deletions source/plugins/skyline/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
### 🌇 GitHub Skyline 3D calendar

⚠️ This plugin significantly increase file size, prefer using it as standalone.

The *skyline* plugin lets you display your 3D commits calendar from [skyline.github.com](https://skyline.github.com/).

<table>
<td align="center">
<img src="https://github.com/lowlighter/lowlighter/blob/master/metrics.plugin.skyline.svg">
<img width="900" height="1" alt="">
</td>
</table>

This uses puppeteer to generate a GIF image of rendered animation.

#### ℹ️ Examples workflows

[➡️ Available options for this plugin](metadata.yml)

```yaml
- uses: lowlighter/metrics@latest
with:
# ... other options
plugin_skyline: yes
plugin_skyline_year: 0 # Set to 0 to display current year
```
49 changes: 49 additions & 0 deletions source/plugins/skyline/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//Setup
export default async function({login, q, imports, data, account}, {enabled = false} = {}) {
//Plugin execution
try {
//Check if plugin is enabled and requirements are met
if ((!enabled)||(!q.skyline))
return null

//Load inputs
let {year} = imports.metadata.plugins.skyline.inputs({data, account, q})
if (Number.isNaN(year)) {
year = new Date().getFullYear()
console.debug(`metrics/compute/${login}/plugins > skyline > year set to ${year}`)
}
const width = 454
const height = 284

//Start puppeteer and navigate to skyline.github.com
console.debug(`metrics/compute/${login}/plugins > skyline > starting browser`)
const browser = await imports.puppeteer.launch({headless:true, executablePath:process.env.PUPPETEER_BROWSER_PATH, args:["--no-sandbox", "--disable-extensions", "--disable-setuid-sandbox", "--disable-dev-shm-usage"]})
console.debug(`metrics/compute/${login}/plugins > skyline > started ${await browser.version()}`)
const page = await browser.newPage()
await page.setViewport({width, height})

//Load page
console.debug(`metrics/compute/${login}/plugins > skyline > loading skyline.github.com/${login}/${year}`)
await page.goto(`https://skyline.github.com/${login}/${year}`, {timeout:90*1000})
console.debug(`metrics/compute/${login}/plugins > skyline > waiting for initial render`)
const frame = page.mainFrame()
await page.waitForFunction('[...document.querySelectorAll("span")].map(span => span.innerText).includes("Download STL file")', {timeout:90*1000})
await frame.evaluate(() => [...document.querySelectorAll("button, footer, a")].map(element => element.remove()))

//Generate gif
console.debug(`metrics/compute/${login}/plugins > skyline > generating gif image`)
const image = await imports.puppeteergif({page, width, height, frames:106})

//Close puppeteer
await browser.close()

//Results
return {image}
}
//Handle errors
catch (error) {
throw {error:{message:"An error occured", instance:error}}
}
}


19 changes: 19 additions & 0 deletions source/plugins/skyline/metadata.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: "🌇 GitHub Skyline 3D calendar"
cost: N/A
categorie: github
supports:
- user
inputs:

# Enable or disable plugin
plugin_skyline:
description: Display GitHub Skyline 3D calendar
type: boolean
default: no

# Displayed year
plugin_skyline_year:
description: Displayed year
type: number
default: "current-year"
min: 2008
8 changes: 8 additions & 0 deletions source/plugins/skyline/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
- name: Skyline plugin (default)
uses: lowlighter/metrics@latest
with:
token: NOT_NEEDED
plugin_skyline: yes
timeout: 1800000
modes:
- action
3 changes: 2 additions & 1 deletion source/templates/classic/partials/_.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
"people",
"activity",
"anilist",
"wakatime"
"wakatime",
"skyline"
]
20 changes: 20 additions & 0 deletions source/templates/classic/partials/skyline.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<% if (plugins.skyline) { %>
<section>
<h2 class="field">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg>
GitHub Skyline
</h2>
<div class="row">
<section>
<% if (plugins.skyline.error) { %>
<div class="field error">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M2.343 13.657A8 8 0 1113.657 2.343 8 8 0 012.343 13.657zM6.03 4.97a.75.75 0 00-1.06 1.06L6.94 8 4.97 9.97a.75.75 0 101.06 1.06L8 9.06l1.97 1.97a.75.75 0 101.06-1.06L9.06 8l1.97-1.97a.75.75 0 10-1.06-1.06L8 6.94 6.03 4.97z"></path></svg>
<%= plugins.skyline.error.message %>
</div>
<% } else { %>
<img class="skyline" src="data:image/gif;base64,<%= plugins.skyline.image %>" width="480" height="300" alt=""/>
<% } %>
</section>
</div>
</section>
<% } %>
8 changes: 8 additions & 0 deletions source/templates/classic/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,14 @@
margin: 0 13px 2px;
}

/* Skyline */
img.skyline {
margin: 2px 13px 6px;
border-radius: 5px;
width: 454px;
height: 284px;
}

/* Fade animation */
.af {
opacity: 0;
Expand Down