├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ └── config.yml ├── actions │ ├── ghcr-clean │ │ ├── delete_ghcr_dangling_images.sh │ │ └── delete_workflows.sh │ └── spelling │ │ ├── README.md │ │ ├── advice.md │ │ ├── allow.txt │ │ ├── candidate.patterns │ │ ├── excludes.txt │ │ ├── expect.txt │ │ ├── line_forbidden.patterns │ │ ├── patterns.txt │ │ └── reject.txt ├── architecture.svg ├── config │ ├── codeql.yml │ ├── dprint.json │ └── label.yml ├── dependabot.yml ├── pull_request_template.md ├── readme │ ├── imgs │ │ ├── about_metrics_are_html.png │ │ ├── about_metrics_marker.png │ │ ├── example_action_update.dark.png │ │ ├── example_action_update.light.png │ │ ├── example_github_profile.dark.png │ │ ├── example_github_profile.light.png │ │ ├── features_embed.gif │ │ ├── features_insights.gif │ │ ├── plugin_16personalities_profile.png │ │ ├── plugin_achievements_ranks.png │ │ ├── plugin_chess_lichess_token_0.png │ │ ├── plugin_chess_lichess_token_1.png │ │ ├── plugin_chess_lichess_token_2.png │ │ ├── plugin_music_playlist_apple.png │ │ ├── plugin_music_playlist_spotify.png │ │ ├── plugin_music_recent_spotify_token_0.png │ │ ├── plugin_music_recent_spotify_token_1.png │ │ ├── plugin_music_recent_spotify_token_2.png │ │ ├── plugin_music_recent_youtube_cookie_1.png │ │ ├── plugin_music_recent_youtube_cookie_2.png │ │ ├── plugin_projects_create.png │ │ ├── plugin_projects_repositories.png │ │ ├── plugin_projects_setup.png │ │ ├── plugin_projects_track_progress.png │ │ ├── plugin_splatoon_auth.png │ │ ├── plugin_splatoon_script.png │ │ ├── plugin_splatoon_statink.png │ │ ├── plugin_stackoverflow_user_id.png │ │ ├── plugin_steam_userid.png │ │ ├── plugin_steam_webtoken.png │ │ ├── plugin_stock_token.png │ │ ├── plugin_tweets_secrets.png │ │ ├── plugin_wakatime_token.png │ │ ├── setup_personal_repository.dark.png │ │ ├── setup_personal_repository.light.png │ │ ├── setup_personal_token.dark.png │ │ ├── setup_personal_token.light.png │ │ ├── setup_private_contributions.dark.png │ │ ├── setup_private_contributions.light.png │ │ ├── setup_public_membership_org.dark.png │ │ ├── setup_public_membership_org.light.png │ │ ├── setup_repository_secret.dark.png │ │ ├── setup_repository_secret.light.png │ │ ├── setup_selfhosted_create.dark.png │ │ ├── setup_selfhosted_create.light.png │ │ ├── setup_shared.dark.png │ │ ├── setup_shared.light.png │ │ ├── setup_token_org_read_scope.dark.png │ │ ├── setup_token_org_read_scope.light.png │ │ ├── setup_token_repo_scope.dark.png │ │ ├── setup_token_repo_scope.light.png │ │ ├── setup_workflow_permissions.dark.png │ │ └── setup_workflow_permissions.light.png │ └── partials │ │ ├── documentation │ │ ├── compatibility.md │ │ ├── contributing.md │ │ ├── inspirations.md │ │ ├── organizations.md │ │ ├── selfhosted.md │ │ ├── setup.md │ │ └── setup │ │ │ ├── action.md │ │ │ ├── docker.md │ │ │ ├── local.md │ │ │ ├── shared.md │ │ │ └── web.md │ │ ├── license.md │ │ └── templated │ │ ├── README.md │ │ ├── compatibility.md │ │ ├── documentation.md │ │ ├── introduction.md │ │ ├── plugins.community.md │ │ ├── plugins.md │ │ └── templates.md ├── scripts │ ├── build.mjs │ ├── files │ │ └── examples.yml │ ├── markdown_example.mjs │ ├── presets_examples.mjs │ ├── preview.mjs │ ├── quickstart │ │ ├── index.mjs │ │ ├── plugin │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ │ └── template │ │ │ ├── README.md │ │ │ ├── image.svg │ │ │ ├── metadata.yml │ │ │ └── partials │ │ │ ├── _.json │ │ │ └── hello.ejs │ └── release.mjs └── workflows │ ├── branches.yml │ ├── ci.yml │ ├── clean.yml │ ├── examples.presets.yml │ ├── examples.yml │ ├── label.yml │ ├── spelling.yml │ ├── stale.yml │ ├── test.presets.yml │ └── test.yml ├── .gitignore ├── ARCHITECTURE.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── README.md ├── SECURITY.md ├── action.yml ├── package-lock.json ├── package.json ├── settings.example.json ├── source ├── .eslintrc.yml ├── app │ ├── action │ │ ├── action.yml │ │ ├── index.mjs │ │ └── run.sh │ ├── metrics │ │ ├── index.mjs │ │ ├── metadata.mjs │ │ ├── presets.mjs │ │ ├── setup.mjs │ │ └── utils.mjs │ └── web │ │ ├── index.mjs │ │ ├── instance.mjs │ │ ├── settings.example.json │ │ └── statics │ │ ├── app.js │ │ ├── embed │ │ ├── app.js │ │ ├── app.placeholder.js │ │ ├── index.html │ │ └── placeholders │ │ │ ├── isocalendar.full-year.svg │ │ │ ├── isocalendar.half-year.svg │ │ │ ├── lines.history.svg │ │ │ ├── screenshot.png │ │ │ ├── skyline.png │ │ │ ├── stargazers.worldmap.svg │ │ │ └── stock.svg │ │ ├── favicon.png │ │ ├── index.html │ │ ├── insights │ │ ├── index.html │ │ ├── script.js │ │ └── style.css │ │ ├── oauth │ │ ├── index.html │ │ ├── redirect.html │ │ └── script.js │ │ ├── opengraph.png │ │ ├── style.css │ │ └── style.vars.css ├── plugins │ ├── README.md │ ├── achievements │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── list │ │ │ ├── index.mjs │ │ │ ├── organizations.mjs │ │ │ └── users.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── achievements.graphql │ │ │ ├── metrics.graphql │ │ │ ├── octocat.graphql │ │ │ ├── organizations.graphql │ │ │ ├── ranking.graphql │ │ │ └── total.graphql │ ├── activity │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── anilist │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── characters.graphql │ │ │ ├── favorites.graphql │ │ │ ├── medias.graphql │ │ │ └── statistics.graphql │ ├── base │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── calendar.graphql │ │ │ ├── contributions.graphql │ │ │ ├── field.graphql │ │ │ ├── field.repositories.graphql │ │ │ ├── organization.graphql │ │ │ ├── organization.x.graphql │ │ │ ├── repositories.graphql │ │ │ ├── repository.graphql │ │ │ ├── user.graphql │ │ │ └── user.x.graphql │ ├── calendar │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ └── calendar.graphql │ ├── code │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── community │ │ ├── 16personalities │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ │ ├── README.md │ │ ├── chess │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ │ ├── crypto │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ │ ├── fortune │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ │ ├── nightscout │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ │ ├── poopmap │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ │ ├── screenshot │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ │ ├── splatoon │ │ │ ├── README.md │ │ │ ├── assets.mjs │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ ├── metadata.yml │ │ │ ├── s3si │ │ │ │ ├── .gitignore │ │ │ │ ├── LICENSE.md │ │ │ │ ├── index.ts │ │ │ │ └── mocks │ │ │ │ │ ├── u_coop.json │ │ │ │ │ ├── u_summary.json │ │ │ │ │ └── u_vs.json │ │ │ └── token.ts │ │ └── stock │ │ │ ├── README.md │ │ │ ├── examples.yml │ │ │ ├── index.mjs │ │ │ └── metadata.yml │ ├── contributors │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ └── commit.graphql │ ├── core │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── discussions │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── categories.graphql │ │ │ ├── comments.graphql │ │ │ └── statistics.graphql │ ├── followup │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── repository.collaborators.graphql │ │ │ ├── repository.graphql │ │ │ └── user.graphql │ ├── gists │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ └── gists.graphql │ ├── habits │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── introduction │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── organization.graphql │ │ │ ├── repository.graphql │ │ │ └── user.graphql │ ├── isocalendar │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ └── calendar.graphql │ ├── languages │ │ ├── README.md │ │ ├── analyzer │ │ │ ├── analyzer.mjs │ │ │ ├── cli.mjs │ │ │ ├── indepth.mjs │ │ │ └── recent.mjs │ │ ├── analyzers.mjs │ │ ├── colorsets.json │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── leetcode │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── languages.graphql │ │ │ ├── problems.graphql │ │ │ ├── recent.graphql │ │ │ └── skills.graphql │ ├── licenses │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── licenses.graphql │ │ │ └── repository.graphql │ ├── lines │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── music │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── notable │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── commits.graphql │ │ │ ├── contributions.graphql │ │ │ └── issues.graphql │ ├── pagespeed │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── people │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── people.graphql │ │ │ ├── repository.graphql │ │ │ └── sponsors.graphql │ ├── posts │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ └── hashnode.graphql │ ├── projects │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── repository.graphql │ │ │ ├── repository.legacy.graphql │ │ │ ├── user.graphql │ │ │ └── user.legacy.graphql │ ├── reactions │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ └── reactions.graphql │ ├── repositories │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── pinned.graphql │ │ │ ├── random.graphql │ │ │ ├── repository.graphql │ │ │ └── starred.graphql │ ├── rss │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── skyline │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── sponsors │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── active.graphql │ │ │ ├── all.graphql │ │ │ └── description.graphql │ ├── sponsorships │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ ├── all.graphql │ │ │ └── sponsorships.graphql │ ├── stackoverflow │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── stargazers │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ ├── queries │ │ │ └── stargazers.graphql │ │ └── worldmap │ │ │ ├── atlas │ │ │ ├── 50m_countries.geojson │ │ │ └── LICENSE.md │ │ │ └── index.mjs │ ├── starlists │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── stars │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ ├── metadata.yml │ │ └── queries │ │ │ └── stars.graphql │ ├── steam │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── support │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── topics │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── traffic │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ ├── tweets │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml │ └── wakatime │ │ ├── README.md │ │ ├── examples.yml │ │ ├── index.mjs │ │ └── metadata.yml └── templates │ ├── README.md │ ├── classic │ ├── README.md │ ├── examples.yml │ ├── fonts.css │ ├── image.svg │ ├── metadata.yml │ ├── partials │ │ ├── 16personalities.ejs │ │ ├── _.json │ │ ├── achievements.ejs │ │ ├── activity.ejs │ │ ├── anilist.ejs │ │ ├── base.activity+community.ejs │ │ ├── base.header.ejs │ │ ├── base.repositories.ejs │ │ ├── calendar.ejs │ │ ├── chess.ejs │ │ ├── code.ejs │ │ ├── crypto.ejs │ │ ├── discussions.ejs │ │ ├── followup.ejs │ │ ├── fortune.ejs │ │ ├── gists.ejs │ │ ├── habits.ejs │ │ ├── introduction.ejs │ │ ├── isocalendar.ejs │ │ ├── languages.ejs │ │ ├── leetcode.ejs │ │ ├── lines.ejs │ │ ├── music.ejs │ │ ├── nightscout.ejs │ │ ├── notable.ejs │ │ ├── pagespeed.ejs │ │ ├── people.ejs │ │ ├── poopmap.ejs │ │ ├── posts.ejs │ │ ├── projects.ejs │ │ ├── reactions.ejs │ │ ├── repositories.ejs │ │ ├── rss.ejs │ │ ├── screenshot.ejs │ │ ├── skyline.ejs │ │ ├── splatoon.ejs │ │ ├── sponsors.ejs │ │ ├── sponsorships.ejs │ │ ├── stackoverflow.ejs │ │ ├── stargazers.ejs │ │ ├── starlists.ejs │ │ ├── stars.ejs │ │ ├── steam.ejs │ │ ├── stock.ejs │ │ ├── support.ejs │ │ ├── topics.ejs │ │ ├── traffic.ejs │ │ ├── tweets.ejs │ │ └── wakatime.ejs │ ├── style.css │ └── template.mjs │ ├── community │ ├── README.md │ ├── examples.yml │ └── metadata.yml │ ├── markdown │ ├── README.md │ ├── example.md │ ├── example.pdf.md │ ├── examples.yml │ ├── image.svg │ ├── metadata.yml │ ├── partials │ │ ├── _.json │ │ ├── activity.ejs │ │ ├── posts.ejs │ │ ├── rss.ejs │ │ ├── topics.ejs │ │ └── tweets.ejs │ └── template.mjs │ ├── repository │ ├── README.md │ ├── examples.yml │ ├── image.svg │ ├── metadata.yml │ ├── partials │ │ ├── _.json │ │ ├── activity.ejs │ │ ├── base.header.ejs │ │ ├── contributors.ejs │ │ ├── crypto.ejs │ │ ├── followup.ejs │ │ ├── introduction.ejs │ │ ├── languages.ejs │ │ ├── licenses.ejs │ │ ├── lines.ejs │ │ ├── pagespeed.ejs │ │ ├── people.ejs │ │ ├── posts.ejs │ │ ├── projects.ejs │ │ ├── rss.ejs │ │ ├── screenshot.ejs │ │ ├── sponsors.ejs │ │ ├── stargazers.ejs │ │ ├── stock.ejs │ │ └── traffic.ejs │ └── template.mjs │ └── terminal │ ├── README.md │ ├── examples.yml │ ├── fonts.css │ ├── image.svg │ ├── metadata.yml │ ├── partials │ ├── _.json │ ├── base.activity+community.ejs │ ├── base.header.ejs │ ├── base.repositories.ejs │ ├── gists.ejs │ ├── isocalendar.ejs │ ├── languages.ejs │ ├── lines.ejs │ ├── pagespeed.ejs │ ├── screenshot.ejs │ └── traffic.ejs │ ├── style.css │ └── template.mjs ├── tests ├── cases │ ├── 16personalities.plugin.yml │ ├── achievements.plugin.yml │ ├── activity.plugin.yml │ ├── anilist.plugin.yml │ ├── base.plugin.yml │ ├── calendar.plugin.yml │ ├── chess.plugin.yml │ ├── classic.template.yml │ ├── code.plugin.yml │ ├── community.template.yml │ ├── contributors.plugin.yml │ ├── core.plugin.yml │ ├── crypto.plugin.yml │ ├── discussions.plugin.yml │ ├── followup.plugin.yml │ ├── fortune.plugin.yml │ ├── gists.plugin.yml │ ├── habits.plugin.yml │ ├── introduction.plugin.yml │ ├── isocalendar.plugin.yml │ ├── languages.plugin.yml │ ├── leetcode.plugin.yml │ ├── licenses.plugin.yml │ ├── lines.plugin.yml │ ├── markdown.template.yml │ ├── music.plugin.yml │ ├── nightscout.plugin.yml │ ├── notable.plugin.yml │ ├── pagespeed.plugin.yml │ ├── people.plugin.yml │ ├── poopmap.plugin.yml │ ├── posts.plugin.yml │ ├── projects.plugin.yml │ ├── reactions.plugin.yml │ ├── repositories.plugin.yml │ ├── repository.template.yml │ ├── rss.plugin.yml │ ├── screenshot.plugin.yml │ ├── skyline.plugin.yml │ ├── splatoon.plugin.yml │ ├── sponsors.plugin.yml │ ├── sponsorships.plugin.yml │ ├── stackoverflow.plugin.yml │ ├── stargazers.plugin.yml │ ├── starlists.plugin.yml │ ├── stars.plugin.yml │ ├── steam.plugin.yml │ ├── stock.plugin.yml │ ├── support.plugin.yml │ ├── terminal.template.yml │ ├── topics.plugin.yml │ ├── traffic.plugin.yml │ ├── tweets.plugin.yml │ └── wakatime.plugin.yml ├── ci.test.js ├── metrics.test.js ├── mocks │ ├── .eslintrc.yml │ ├── api │ │ ├── axios │ │ │ ├── get │ │ │ │ ├── lastfm.mjs │ │ │ │ ├── lichess.mjs │ │ │ │ ├── nightscout.mjs │ │ │ │ ├── pagespeed.mjs │ │ │ │ ├── poopmap.mjs │ │ │ │ ├── spotify.mjs │ │ │ │ ├── stackoverflow.mjs │ │ │ │ ├── steam.mjs │ │ │ │ ├── twitter.mjs │ │ │ │ ├── wakatime.mjs │ │ │ │ └── yahoo.mjs │ │ │ └── post │ │ │ │ ├── anilist.mjs │ │ │ │ ├── hashnode.mjs │ │ │ │ ├── leetcode.mjs │ │ │ │ ├── spotify.mjs │ │ │ │ └── youtubemusic.mjs │ │ └── github │ │ │ ├── graphql │ │ │ ├── achievements.default.mjs │ │ │ ├── achievements.metrics.mjs │ │ │ ├── achievements.octocat.mjs │ │ │ ├── achievements.organizations.mjs │ │ │ ├── achievements.ranking.mjs │ │ │ ├── achievements.total.mjs │ │ │ ├── base.calendar.mjs │ │ │ ├── base.contributions.mjs │ │ │ ├── base.field.mjs │ │ │ ├── base.field.repositories.mjs │ │ │ ├── base.repositories.mjs │ │ │ ├── base.repository.mjs │ │ │ ├── base.user.mjs │ │ │ ├── calendar.default.mjs │ │ │ ├── contributors.commit.mjs │ │ │ ├── discussions.categories.mjs │ │ │ ├── discussions.comments.mjs │ │ │ ├── discussions.statistics.mjs │ │ │ ├── followup.repository.collaborators.mjs │ │ │ ├── followup.repository.mjs │ │ │ ├── followup.user.mjs │ │ │ ├── gists.default.mjs │ │ │ ├── introduction.organization.mjs │ │ │ ├── introduction.repository.mjs │ │ │ ├── introduction.user.mjs │ │ │ ├── isocalendar.calendar.mjs │ │ │ ├── licenses.default.mjs │ │ │ ├── licenses.repository.mjs │ │ │ ├── notable.contributions.mjs │ │ │ ├── notable.issues.mjs │ │ │ ├── people.default.mjs │ │ │ ├── people.repository.mjs │ │ │ ├── people.sponsors.mjs │ │ │ ├── projects.repository.legacy.mjs │ │ │ ├── projects.repository.mjs │ │ │ ├── projects.user.legacy.mjs │ │ │ ├── projects.user.mjs │ │ │ ├── reactions.default.mjs │ │ │ ├── repositories.pinned.mjs │ │ │ ├── repositories.random.mjs │ │ │ ├── repositories.repository.mjs │ │ │ ├── repositories.starred.mjs │ │ │ ├── sponsors.active.mjs │ │ │ ├── sponsors.all.mjs │ │ │ ├── sponsors.description.mjs │ │ │ ├── sponsorships.all.mjs │ │ │ ├── sponsorships.default.mjs │ │ │ ├── stargazers.default.mjs │ │ │ └── stars.default.mjs │ │ │ └── rest │ │ │ ├── activity │ │ │ ├── listEventsForAuthenticatedUser.mjs │ │ │ └── listRepoEvents.mjs │ │ │ ├── emojis │ │ │ └── get.mjs │ │ │ ├── rateLimit │ │ │ └── get.mjs │ │ │ ├── repos │ │ │ ├── get.mjs │ │ │ ├── getContributorsStats.mjs │ │ │ ├── getViews.mjs │ │ │ ├── listCommits.mjs │ │ │ └── listContributors.mjs │ │ │ ├── request.mjs │ │ │ └── users │ │ │ ├── getByUsername.mjs │ │ │ └── listGpgKeysForUser.mjs │ └── index.mjs ├── presets.test.js └── secrets.json └── vercel.json /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.{js,mjs}] 2 | charset = utf-8 3 | indent_style = space 4 | indent_size = 2 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Vendored files 5 | source/templates/** linguist-vendored 6 | source/app/web/statics/style.vars.css linguist-vendored 7 | 8 | # Hidden files 9 | .github/** -linguist-detectable 10 | 11 | # Documentation 12 | ARCHITECTURE.md linguist-documentation 13 | CODE_OF_CONDUCT.md linguist-documentation 14 | CONTRIBUTING.md linguist-documentation 15 | LICENSE.md linguist-documentation 16 | SECURITY.md linguist-documentation 17 | README.md linguist-documentation 18 | 19 | # Generated files 20 | source/plugins/README.md linguist-generated 21 | source/plugins/community/README.md linguist-generated 22 | source/templates/README.md linguist-generated 23 | action.yml linguist-generated 24 | settings.example.json linguist-generated 25 | tests/cases/* linguist-generated 26 | package-lock.json linguist-generated 27 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | github: lowlighter 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 🙏 Request help with setup or report a possible issue 4 | url: https://github.com/lowlighter/metrics/discussions/new?category=q-a 5 | about: Post here when having trouble with setup or configuration 6 | - name: 💡 Suggest new features 7 | url: https://github.com/lowlighter/metrics/discussions/new?category=ideas 8 | about: Submit ideas to help us improve 9 | - name: 💬 Start a discussion 10 | url: https://github.com/lowlighter/metrics/discussions/new?category=general 11 | about: Ask other questions related to this project here -------------------------------------------------------------------------------- /.github/actions/ghcr-clean/delete_ghcr_dangling_images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # Simple script to remove dangling images from GHCR 5 | # You need to be logged to 'gh' first. 6 | 7 | # package_name syntax. i.e: jellyfin-vue 8 | owner="$1" 9 | container="$2" 10 | temp_file="ghcr_prune.ids" 11 | rm -rf $temp_file 12 | 13 | echo "Fetching dangling images from GHCR..." 14 | gh api /users/${owner}/packages/container/${container}/versions --paginate > $temp_file 15 | 16 | ids_to_delete=$(cat "$temp_file" | jq -r '.[] | select(.metadata.container.tags==[]) | .id') 17 | 18 | if [ "${ids_to_delete}" = "" ] 19 | then 20 | echo "There are no dangling images to remove for this package" 21 | exit 0 22 | fi 23 | 24 | echo -e "\nDeleting dangling images..." 25 | while read -r line; do 26 | id="$line" 27 | echo "Processing image $id" 28 | ## Workaround for https://github.com/cli/cli/issues/4286 and https://github.com/cli/cli/issues/3937 29 | set +e 30 | echo -n | gh api --method DELETE /users/${owner}/packages/container/${container}/versions/${id} --input - 31 | test $? -eq 0 && echo Dangling image with ID $id deleted successfully 32 | set -e 33 | done <<< $ids_to_delete 34 | 35 | rm -rf $temp_file 36 | echo -e "\nAll the dangling images have been removed successfully" 37 | exit 0 38 | -------------------------------------------------------------------------------- /.github/actions/spelling/advice.md: -------------------------------------------------------------------------------- 1 | 2 |
If the flagged items are false positives 3 | 4 | If items relate to a ... 5 | * binary file (or some other file you wouldn't want to check at all). 6 | 7 | Please add a file path to the `excludes.txt` file matching the containing file. 8 | 9 | File paths are Perl 5 Regular Expressions - you can [test]( 10 | https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files. 11 | 12 | `^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md]( 13 | ../tree/HEAD/README.md) (on whichever branch you're using). 14 | 15 | * well-formed pattern. 16 | 17 | If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it, 18 | try adding it to the `patterns.txt` file. 19 | 20 | Patterns are Perl 5 Regular Expressions - you can [test]( 21 | https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines. 22 | 23 | Note that patterns can't match multiline strings. 24 | 25 |
26 | -------------------------------------------------------------------------------- /.github/actions/spelling/allow.txt: -------------------------------------------------------------------------------- 1 | appid 2 | apikey 3 | apiname 4 | appdetails 5 | appids 6 | appinfo 7 | deno 8 | Flickr 9 | gpgarmor 10 | github 11 | githubassets 12 | https 13 | IPlayer 14 | ISteam 15 | joinmastodon 16 | leetcode 17 | MBTI 18 | Nie 19 | npx 20 | personaname 21 | pgn 22 | playerstats 23 | rbga 24 | rtime 25 | scm 26 | shas 27 | splatoon 28 | Splatnet 29 | ssh 30 | statink 31 | STATINK 32 | steamcommunity 33 | steamid 34 | steamids 35 | steampowered 36 | tdatum 37 | timecreated 38 | tspan 39 | ubuntu 40 | unlocktime 41 | userid 42 | xticked 43 | xticks 44 | yargsparser 45 | yticked 46 | webtoken 47 | -------------------------------------------------------------------------------- /.github/actions/spelling/candidate.patterns: -------------------------------------------------------------------------------- 1 | # Apple music 2 | \bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+ 3 | # Spotify 4 | \bopen\.spotify\.com/embed/playlist/\w+ 5 | -------------------------------------------------------------------------------- /.github/actions/spelling/line_forbidden.patterns: -------------------------------------------------------------------------------- 1 | # reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere 2 | # \bm_data\b 3 | 4 | # s.b. GitHub 5 | \bGithub\b 6 | 7 | # s.b. GitLab 8 | \bGitlab\b 9 | 10 | # s.b. JavaScript 11 | \bJavascript\b 12 | 13 | # s.b. Microsoft 14 | \bMicroSoft\b 15 | 16 | # s.b. another 17 | \ban[- ]other\b 18 | 19 | # s.b. greater than 20 | \bgreater then\b 21 | 22 | # s.b. less than 23 | \bless then\b 24 | 25 | # s.b. otherwise 26 | \bother[- ]wise\b 27 | 28 | # s.b. nonexistent 29 | \bnon existing\b 30 | \b[Nn]o[nt][- ]existent\b 31 | 32 | # s.b. preexisting 33 | [Pp]re-existing 34 | 35 | # s.b. preempt 36 | [Pp]re-empt\b 37 | 38 | # s.b. preemptively 39 | [Pp]re-emptively 40 | 41 | # s.b. reentrancy 42 | [Rr]e-entrancy 43 | 44 | # s.b. reentrant 45 | [Rr]e-entrant 46 | 47 | # Reject duplicate words 48 | \s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s 49 | -------------------------------------------------------------------------------- /.github/actions/spelling/reject.txt: -------------------------------------------------------------------------------- 1 | ^attache$ 2 | benefitting 3 | occurences? 4 | ^dependan.* 5 | ^oer$ 6 | Sorce 7 | ^[Ss]pae.* 8 | ^untill$ 9 | ^untilling$ 10 | ^wether.* 11 | -------------------------------------------------------------------------------- /.github/config/codeql.yml: -------------------------------------------------------------------------------- 1 | name: CodeQL config 2 | queries: 3 | - uses: security-and-quality 4 | paths-ignore: 5 | - copyrighted/** 6 | - .github/scripts/quickstart/** 7 | - source/plugins/community/splatoon/s3si/** -------------------------------------------------------------------------------- /.github/config/dprint.json: -------------------------------------------------------------------------------- 1 | { 2 | "incremental": true, 3 | "indentWidth": 2, 4 | "typescript": { 5 | "lineWidth": 360, 6 | "semiColons": "asi", 7 | "quoteStyle": "preferDouble", 8 | "useBraces": "preferNone", 9 | "singleBodyPosition": "nextLine", 10 | "arrowFunction.useParentheses": "preferNone", 11 | "commentLine.forceSpaceAfterSlashes": false, 12 | "taggedTemplate.spaceBeforeLiteral": false, 13 | "nextControlFlowPosition": "nextLine", 14 | "spaceSurroundingProperties": false 15 | }, 16 | "includes": ["**/*.{js,mjs}"], 17 | "excludes": [ 18 | "node_modules/**/*", 19 | ".github/scripts/quickstart/**/*" 20 | ], 21 | "plugins": [ 22 | "https://plugins.dprint.dev/typescript-0.83.0.wasm" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | open-pull-requests-limit: 0 # Will not be managed by npm anymore in v4 5 | labels: 6 | - 📦 dependencies 7 | directory: / 8 | schedule: 9 | interval: weekly 10 | pull-request-branch-name: 11 | separator: "-" 12 | reviewers: 13 | - lowlighter 14 | commit-message: 15 | prefix: "chore(deps)" 16 | ignore: 17 | - dependency-name: "*" 18 | update-types: 19 | - version-update:semver-patch 20 | - dependency-name: vue-prism-component 21 | versions: 22 | - 2.0.0 23 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /.github/readme/imgs/about_metrics_are_html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/about_metrics_are_html.png -------------------------------------------------------------------------------- /.github/readme/imgs/about_metrics_marker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/about_metrics_marker.png -------------------------------------------------------------------------------- /.github/readme/imgs/example_action_update.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/example_action_update.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/example_action_update.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/example_action_update.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/example_github_profile.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/example_github_profile.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/example_github_profile.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/example_github_profile.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/features_embed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/features_embed.gif -------------------------------------------------------------------------------- /.github/readme/imgs/features_insights.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/features_insights.gif -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_16personalities_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_16personalities_profile.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_achievements_ranks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_achievements_ranks.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_chess_lichess_token_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_chess_lichess_token_0.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_chess_lichess_token_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_chess_lichess_token_1.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_chess_lichess_token_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_chess_lichess_token_2.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_music_playlist_apple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_music_playlist_apple.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_music_playlist_spotify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_music_playlist_spotify.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_music_recent_spotify_token_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_music_recent_spotify_token_0.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_music_recent_spotify_token_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_music_recent_spotify_token_1.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_music_recent_spotify_token_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_music_recent_spotify_token_2.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_music_recent_youtube_cookie_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_music_recent_youtube_cookie_1.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_music_recent_youtube_cookie_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_music_recent_youtube_cookie_2.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_projects_create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_projects_create.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_projects_repositories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_projects_repositories.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_projects_setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_projects_setup.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_projects_track_progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_projects_track_progress.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_splatoon_auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_splatoon_auth.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_splatoon_script.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_splatoon_script.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_splatoon_statink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_splatoon_statink.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_stackoverflow_user_id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_stackoverflow_user_id.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_steam_userid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_steam_userid.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_steam_webtoken.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_steam_webtoken.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_stock_token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_stock_token.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_tweets_secrets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_tweets_secrets.png -------------------------------------------------------------------------------- /.github/readme/imgs/plugin_wakatime_token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/plugin_wakatime_token.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_personal_repository.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_personal_repository.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_personal_repository.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_personal_repository.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_personal_token.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_personal_token.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_personal_token.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_personal_token.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_private_contributions.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_private_contributions.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_private_contributions.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_private_contributions.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_public_membership_org.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_public_membership_org.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_public_membership_org.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_public_membership_org.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_repository_secret.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_repository_secret.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_repository_secret.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_repository_secret.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_selfhosted_create.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_selfhosted_create.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_selfhosted_create.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_selfhosted_create.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_shared.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_shared.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_shared.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_shared.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_token_org_read_scope.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_token_org_read_scope.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_token_org_read_scope.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_token_org_read_scope.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_token_repo_scope.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_token_repo_scope.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_token_repo_scope.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_token_repo_scope.light.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_workflow_permissions.dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_workflow_permissions.dark.png -------------------------------------------------------------------------------- /.github/readme/imgs/setup_workflow_permissions.light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/.github/readme/imgs/setup_workflow_permissions.light.png -------------------------------------------------------------------------------- /.github/readme/partials/documentation/contributing.md: -------------------------------------------------------------------------------- 1 | ## 💪 Contributing 2 | 3 | If you are interested in contributing, the following resources may interest you: 4 | 5 | * [💪 Contribution guide](/CONTRIBUTING.md) 6 | * [🧬 Architecture](/ARCHITECTURE.md) 7 | * [📜 License](/LICENSE) 8 | * **:octocat: GitHub resources** 9 | * [📖 GitHub GraphQL API](https://docs.github.com/en/graphql) 10 | * [📖 GitHub GraphQL Explorer](https://docs.github.com/en/free-pro-team@latest/graphql/overview/explorer) 11 | * [📖 GitHub Rest API](https://docs.github.com/en/rest) 12 | * [📖 GitHub Octicons](https://github.com/primer/octicons) 13 | 14 | Use [`💬 discussions`](https://github.com/lowlighter/metrics/discussions) for feedback, new features suggestions, bugs reports or to request help for installation. 15 | -------------------------------------------------------------------------------- /.github/readme/partials/documentation/inspirations.md: -------------------------------------------------------------------------------- 1 | # ✨ Inspirations 2 | 3 | * [anuraghazra/github-readme-stats](https://github.com/anuraghazra/github-readme-stats) 4 | * [jstrieb/github-stats](https://github.com/jstrieb/github-stats) 5 | * [ankurparihar/readme-pagespeed-insights](https://github.com/ankurparihar/readme-pagespeed-insights) 6 | * [jasonlong/isometric-contributions](https://github.com/jasonlong/isometric-contributions) 7 | * [jamesgeorge007/github-activity-readme](https://github.com/jamesgeorge007/github-activity-readme) 8 | * [vvo/sourcekarma](https://github.com/vvo/sourcekarma) 9 | * [ryo-ma/github-profile-trophy](https://github.com/ryo-ma/github-profile-trophy) 10 | * [teoxoy/profile-readme-stats](https://github.com/teoxoy/profile-readme-stats) 11 | * [dyatko/worldstar](https://github.com/dyatko/worldstar) -------------------------------------------------------------------------------- /.github/readme/partials/documentation/setup/docker.md: -------------------------------------------------------------------------------- 1 | # 🐳 Using command line with docker (~2 min) 2 | 3 | ## 0️ Prepare your machine 4 | 5 | A machine with a recent version of [docker](https://www.docker.com/) is required. 6 | 7 | ## 1️ Run docker image 8 | 9 | The command to use is similar to the following: 10 | ```shell 11 | docker run --rm --env INPUT_TOKEN=**** --env INPUT_USER=user --volume=/tmp:/renders ghcr.io/lowlighter/metrics:latest 12 | ``` 13 | 14 | To pass parameters, pass environment variable with the same name as the corresponding action option but in uppercase and prefixed with `INPUT_`. 15 | 16 | Generated files will be created in the mounted `/renders` directory. 17 | 18 | > 💡 When running *metrics* with docker, [`output_action`](/source/plugins/core/README.md#-configuring-output-action) will automatically default to `none` instead. To use a different output action, both `GITHUB_REPOSITORY` (notice the absence of `INPUT_` prefix) and `INPUT_COMMITTER_TOKEN` (with sufficient permissions) environment variables must be set. 19 | -------------------------------------------------------------------------------- /.github/readme/partials/license.md: -------------------------------------------------------------------------------- 1 | ## 📜 License 2 | 3 | ``` 4 | MIT License 5 | Copyright (c) 2020-present lowlighter 6 | ``` 7 | 8 | ![Sponsors](https://github.com/lowlighter/metrics/blob/examples/metrics.sponsors.svg) 9 | -------------------------------------------------------------------------------- /.github/readme/partials/templated/README.md: -------------------------------------------------------------------------------- 1 | # 📊 Metrics [](https://www.producthunt.com/posts/github-metrics?utm_source=badge-featured&utm_medium=badge&utm_source=badge-github-metrics) 2 | 3 | [![Continuous integration](https://github.com/lowlighter/metrics/actions/workflows/ci.yml/badge.svg)](https://github.com/lowlighter/metrics/actions/workflows/ci.yml) 4 | 5 | <% for (const partial of ["templated/introduction", "templated/documentation", "license"]) { -%> 6 | <%- await include(`/partials/${partial}.md`) %> 7 | <% } %> 8 | -------------------------------------------------------------------------------- /.github/readme/partials/templated/documentation.md: -------------------------------------------------------------------------------- 1 | # 📚 Documentation 2 | 3 | <% if (/[.]0-beta$/.test(packaged.version)) { %> 4 | > *⚠️ This is the documentation of **v<%= packaged.version.replace(/[.]0-beta$/, "") %>-beta** (`@master`/`@main` branches) which includes [unreleased features](https://github.com/lowlighter/metrics/compare/latest...master) planned for next release. See documentation for current released version [**v<%= (Number(packaged.version.replace(/[.]0-beta$/, ""))-0.01).toFixed(2).replace(/[.]0/, ".") %>** (`@latest` branch) here](https://github.com/lowlighter/metrics/blob/latest/README.md).* 5 | <% } %> 6 | 7 | <% for (const partial of ["documentation/setup", "templated/templates", "templated/plugins", "documentation/contributing"]) { %> 8 | <%- await include(`/partials/${partial}.md`) -%> 9 | <% } %> 10 | -------------------------------------------------------------------------------- /.github/readme/partials/templated/templates.md: -------------------------------------------------------------------------------- 1 | ## 🖼️ Templates 2 | 3 | Templates lets you change general appearance of rendered metrics. 4 | 5 | <% for (const [template, {name}] of Object.entries(templates).filter(([key, value]) => value)) { %> 6 | * [<%- name %> `<%= template %>`](/source/templates/<%= template %>/README.md)<%# -%> 7 | <% } %> 8 | -------------------------------------------------------------------------------- /.github/scripts/markdown_example.mjs: -------------------------------------------------------------------------------- 1 | //Imports 2 | import puppeteer from "puppeteer" 3 | 4 | //Setup browser 5 | const browser = await puppeteer.launch({ 6 | headless: "new", 7 | executablePath: process.env.PUPPETEER_BROWSER_PATH, 8 | args: ["--no-sandbox", "--disable-extensions", "--disable-setuid-sandbox", "--disable-dev-shm-usage"], 9 | ignoreDefaultArgs: ["--disable-extensions"], 10 | }) 11 | const page = await browser.newPage() 12 | 13 | //Select markdown example and take screenshot 14 | await page.setViewport({width: 600, height: 600}) 15 | await page.goto("https://github.com/lowlighter/metrics/blob/examples/metrics.markdown.md") 16 | await page.waitForSelector("article.markdown-body") 17 | await new Promise(solve => setTimeout(solve, 4000)) 18 | const clip = await page.evaluate(() => { 19 | const {x, y, width, height} = document.querySelector("article.markdown-body").getBoundingClientRect() 20 | return {x, y, width, height} 21 | }) 22 | await page.screenshot({type: "png", path: "/tmp/metrics.markdown.png", clip, omitBackground: true}) 23 | await browser.close() 24 | -------------------------------------------------------------------------------- /.github/scripts/quickstart/plugin/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## ➡️ Available options 5 | 6 | 7 | 8 | 9 | ## ℹ️ Examples workflows 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.github/scripts/quickstart/plugin/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Example 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.<%= name %>.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_<%= name %>: yes 8 | prod: 9 | skip: true 10 | -------------------------------------------------------------------------------- /.github/scripts/quickstart/plugin/index.mjs: -------------------------------------------------------------------------------- 1 | //Setup 2 | export default async function({login, q, imports, data, computed, rest, graphql, queries, account}, {enabled = false, extras = false} = {}) { 3 | //Plugin execution 4 | try { 5 | //Check if plugin is enabled and requirements are met 6 | if ((!q.<%= name %>) || (!imports.metadata.plugins.<%= name %>.enabled(enabled, {extras}))) 7 | return null 8 | //Results 9 | return {} 10 | } 11 | //Handle errors 12 | catch (error) { 13 | throw imports.format.error(error) 14 | } 15 | } -------------------------------------------------------------------------------- /.github/scripts/quickstart/plugin/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 🧩 <%= `${name.charAt(0).toLocaleUpperCase()}${name.substring(1)}` %> 2 | category: community 3 | description: | 4 | Short description 5 | examples: 6 | default: https://via.placeholder.com/468x60?text=No%20preview%20available 7 | authors: 8 | - octocat 9 | supports: 10 | - user 11 | - organization 12 | - repository 13 | scopes: [] 14 | inputs: 15 | 16 | plugin_<%= name %>: 17 | description: | 18 | Enable <%= name %> plugin 19 | type: boolean 20 | default: no 21 | -------------------------------------------------------------------------------- /.github/scripts/quickstart/template/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## ℹ️ Examples workflows 5 | 6 | 7 | -------------------------------------------------------------------------------- /.github/scripts/quickstart/template/image.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | <%% for (const partial of [...partials]) { %> 10 | <%%- await include(`partials/${partial}.ejs`) %> 11 | <%% } %> 12 | 13 |
14 |
15 |
16 | 17 |
-------------------------------------------------------------------------------- /.github/scripts/quickstart/template/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 🖼️ Template name 2 | extends: classic 3 | description: | 4 | Short description 5 | examples: 6 | default: https://via.placeholder.com/468x60?text=No%20preview%20available 7 | authors: 8 | - octocat 9 | supports: 10 | - user 11 | - organization 12 | - repository 13 | formats: 14 | - svg 15 | - png 16 | - jpeg 17 | - json 18 | - markdown 19 | - markdown-pdf 20 | -------------------------------------------------------------------------------- /.github/scripts/quickstart/template/partials/_.json: -------------------------------------------------------------------------------- 1 | [ 2 | "hello" 3 | ] -------------------------------------------------------------------------------- /.github/workflows/branches.yml: -------------------------------------------------------------------------------- 1 | name: Check automated branches 2 | 3 | on: 4 | pull_request_target: 5 | branches: 6 | - main 7 | - latest 8 | - examples 9 | 10 | jobs: 11 | notice: 12 | name: Notice for automated branches 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Comment on pull request 16 | uses: actions/github-script@v6 17 | with: 18 | script: | 19 | const {issue:{number:issue_number}, repo:{owner, repo}} = context 20 | github.rest.issues.createComment({issue_number, owner, repo, body:[ 21 | "Hello there 👋!", 22 | "", 23 | "It seems you have opened a pull request on either `main`, `latest` or `examples`.", 24 | "These branches are fully-automated and do not accept human contributions.", 25 | "", 26 | "* To contribute to *metrics* code, open a pull request to `master` branch", 27 | "* To contribute to *metrics* presets, open a pull request to `presets` branch", 28 | "", 29 | "Thanks for your cooperation 🦾!" 30 | ].join("\n")}) 31 | - name: Change base branch 32 | run: exit 1 33 | -------------------------------------------------------------------------------- /.github/workflows/clean.yml: -------------------------------------------------------------------------------- 1 | name: Clean untagged docker images 2 | 3 | on: 4 | release: 5 | types: 6 | - published 7 | workflow_dispatch: 8 | 9 | jobs: 10 | clean: 11 | name: Clean untagged docker images 12 | runs-on: ubuntu-latest 13 | continue-on-error: true 14 | steps: 15 | - name: Checkout repository 16 | uses: actions/checkout@v3 17 | - name: Run script 18 | run: ./delete_ghcr_dangling_images.sh lowlighter metrics 19 | working-directory: .github/actions/ghcr-clean 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GHCR_BOT_TOKEN }} 22 | -------------------------------------------------------------------------------- /.github/workflows/examples.presets.yml: -------------------------------------------------------------------------------- 1 | name: Publish examples (presets) 2 | on: 3 | schedule: 4 | - cron: "0 16 1/2 * *" 5 | workflow_dispatch: 6 | workflow_call: 7 | jobs: 8 | examples: 9 | runs-on: ubuntu-latest 10 | if: "github.repository == 'lowlighter/metrics'" 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 0 16 | - name: Setup NodeJS 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: 20 20 | - name: Setup metrics 21 | run: npm ci 22 | - name: Publish presets examples 23 | run: npm run presets -- publish 24 | env: 25 | GITHUB_TOKEN: ${{ github.token }} 26 | 27 | 28 | -------------------------------------------------------------------------------- /.github/workflows/label.yml: -------------------------------------------------------------------------------- 1 | name: Label issue and pull requests 2 | 3 | on: pull_request_target 4 | 5 | jobs: 6 | label: 7 | name: Label issue and pull requests 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/labeler@v4 11 | with: 12 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 13 | configuration-path: .github/config/label.yml 14 | sync-labels: yes 15 | -------------------------------------------------------------------------------- /.github/workflows/test.presets.yml: -------------------------------------------------------------------------------- 1 | name: Test (presets) 2 | 3 | on: 4 | pull_request: 5 | branches: [ presets ] 6 | workflow_call: 7 | inputs: 8 | ref: 9 | type: string 10 | repo: 11 | type: string 12 | jobs: 13 | 14 | test: 15 | name: Test 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout repository 19 | uses: actions/checkout@v3 20 | with: 21 | fetch-depth: 0 22 | ref: master 23 | - name: Setup NodeJS 24 | uses: actions/setup-node@v3 25 | with: 26 | node-version: 20 27 | - name: Setup metrics 28 | run: npm ci 29 | - name: Run tests 30 | run: npm run test-presets 31 | env: 32 | HEAD_REF: ${{ inputs.ref }} 33 | REPO: ${{ inputs.repo }} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-present lowlighter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ### 📝 Reporting a Vulnerability 2 | 3 | To report a vulnerability, simply open an [issue](https://github.com/lowlighter/metrics/issues). 4 | We'll try to patch it quickly. 5 | -------------------------------------------------------------------------------- /source/app/web/index.mjs: -------------------------------------------------------------------------------- 1 | import app from "./instance.mjs" 2 | ;(async function() { 3 | await app({sandbox: process.env.SANDBOX}) 4 | })() 5 | -------------------------------------------------------------------------------- /source/app/web/statics/embed/placeholders/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/source/app/web/statics/embed/placeholders/screenshot.png -------------------------------------------------------------------------------- /source/app/web/statics/embed/placeholders/skyline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/source/app/web/statics/embed/placeholders/skyline.png -------------------------------------------------------------------------------- /source/app/web/statics/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/source/app/web/statics/favicon.png -------------------------------------------------------------------------------- /source/app/web/statics/oauth/redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Metrics 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Redirecting... 14 | 25 | 26 | -------------------------------------------------------------------------------- /source/app/web/statics/opengraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/source/app/web/statics/opengraph.png -------------------------------------------------------------------------------- /source/plugins/achievements/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Detailed display 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.achievements.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_achievements: yes 8 | plugin_achievements_only: sponsor, maintainer, octonaut 9 | test: 10 | timeout: 1800000 11 | 12 | - name: Compact display 13 | uses: lowlighter/metrics@latest 14 | with: 15 | filename: metrics.plugin.achievements.compact.svg 16 | token: ${{ secrets.METRICS_TOKEN }} 17 | base: "" 18 | plugin_achievements: yes 19 | plugin_achievements_only: polyglot, stargazer, sponsor, deployer, member, maintainer, developer, scripter, packager, explorer, infographile, manager 20 | plugin_achievements_display: compact 21 | plugin_achievements_threshold: X 22 | test: 23 | timeout: 1800000 -------------------------------------------------------------------------------- /source/plugins/achievements/list/index.mjs: -------------------------------------------------------------------------------- 1 | //Exports 2 | export { default as organization } from "./organizations.mjs" 3 | export { default as user } from "./users.mjs" 4 | -------------------------------------------------------------------------------- /source/plugins/achievements/queries/metrics.graphql: -------------------------------------------------------------------------------- 1 | query AchievementsMetrics { 2 | repository(owner: "lowlighter", name: "metrics") { 3 | viewerHasStarred 4 | } 5 | viewer { 6 | login 7 | } 8 | } -------------------------------------------------------------------------------- /source/plugins/achievements/queries/octocat.graphql: -------------------------------------------------------------------------------- 1 | query AchievementsOctocat { 2 | user(login: "octocat") { 3 | viewerIsFollowing 4 | } 5 | viewer { 6 | login 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /source/plugins/achievements/queries/organizations.graphql: -------------------------------------------------------------------------------- 1 | query AchievementsOrganizations { 2 | organization(login: "$login") { 3 | repositories(first: 1, privacy: PUBLIC, affiliations: OWNER, orderBy: {field: CREATED_AT, direction: ASC}) { 4 | nodes { 5 | createdAt 6 | nameWithOwner 7 | } 8 | totalCount 9 | } 10 | forks:repositories(first: 1, privacy: PUBLIC, isFork: true, orderBy: {field: CREATED_AT, direction: ASC}) { 11 | nodes { 12 | createdAt 13 | nameWithOwner 14 | } 15 | totalCount 16 | } 17 | popular:repositories(first:1, orderBy: {field: STARGAZERS, direction: DESC}) { 18 | nodes { 19 | stargazers { 20 | totalCount 21 | } 22 | } 23 | } 24 | projects(first: 1, orderBy: {field: CREATED_AT, direction: ASC}) { 25 | totalCount 26 | } 27 | packages(first: 1, orderBy: {direction: ASC, field: CREATED_AT}) { 28 | totalCount 29 | } 30 | membersWithRole { 31 | totalCount 32 | } 33 | sponsorshipsAsSponsor { 34 | totalCount 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /source/plugins/achievements/queries/ranking.graphql: -------------------------------------------------------------------------------- 1 | query AchievementsRanking { 2 | repo_rank:search(query: "stars:>$stars", type: REPOSITORY, first: 0) { 3 | repositoryCount 4 | } 5 | user_rank:search(query: "followers:>$followers", type: USER, first: 0) { 6 | userCount 7 | } 8 | forks_rank:search(query: "forks:>$forks", type: REPOSITORY, first: 0) { 9 | repositoryCount 10 | } 11 | created_rank:search(query: "repos:>$created", type: USER, first: 0) { 12 | userCount 13 | } 14 | } -------------------------------------------------------------------------------- /source/plugins/achievements/queries/total.graphql: -------------------------------------------------------------------------------- 1 | query AchievementsTotal { 2 | issues:search(query: "created:>1970", type: ISSUE) { 3 | count:issueCount 4 | } 5 | repositories:search(query: "created:>1970", type: REPOSITORY) { 6 | count:repositoryCount 7 | } 8 | users:search(query: "created:>1970", type: USER) { 9 | count:userCount 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /source/plugins/activity/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Recent activity 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.activity.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_activity: yes 8 | plugin_activity_limit: 5 9 | plugin_activity_days: 0 10 | plugin_activity_filter: issue, pr, release, fork, review, ref/create 11 | -------------------------------------------------------------------------------- /source/plugins/anilist/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Favorites anime and currently watching 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.anilist.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_anilist: yes 8 | plugin_anilist_medias: anime 9 | plugin_anilist_sections: favorites, watching 10 | plugin_anilist_limit: 1 11 | 12 | - name: Favorites manga and currently reading 13 | uses: lowlighter/metrics@latest 14 | with: 15 | filename: metrics.plugin.anilist.manga.svg 16 | token: NOT_NEEDED 17 | base: "" 18 | plugin_anilist: yes 19 | plugin_anilist_medias: manga 20 | plugin_anilist_sections: favorites, reading 21 | plugin_anilist_limit: 1 22 | 23 | - name: Favorites characters 24 | uses: lowlighter/metrics@latest 25 | with: 26 | filename: metrics.plugin.anilist.characters.svg 27 | token: NOT_NEEDED 28 | base: "" 29 | plugin_anilist: yes 30 | plugin_anilist_sections: characters 31 | plugin_anilist_limit_characters: 22 32 | -------------------------------------------------------------------------------- /source/plugins/anilist/queries/characters.graphql: -------------------------------------------------------------------------------- 1 | query FavoritesCharacters ($name: String, $page:Int) { 2 | User(name: $name) { 3 | favourites { 4 | characters(page: $page) { 5 | nodes { 6 | name { 7 | full 8 | native 9 | } 10 | image { 11 | medium 12 | } 13 | } 14 | pageInfo { 15 | currentPage 16 | hasNextPage 17 | } 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /source/plugins/anilist/queries/favorites.graphql: -------------------------------------------------------------------------------- 1 | query Favorites ($name: String, $page:Int) { 2 | User(name: $name) { 3 | favourites { 4 | $type(page: $page) { 5 | nodes { 6 | title { 7 | romaji 8 | english 9 | native 10 | } 11 | description 12 | type 13 | status(version: 2) 14 | episodes 15 | volumes 16 | chapters 17 | averageScore 18 | countryOfOrigin 19 | genres 20 | coverImage { 21 | medium 22 | } 23 | startDate { 24 | year 25 | } 26 | } 27 | pageInfo { 28 | currentPage 29 | hasNextPage 30 | } 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /source/plugins/anilist/queries/medias.graphql: -------------------------------------------------------------------------------- 1 | query Medias ($name: String, $type: MediaType) { 2 | MediaListCollection(userName: $name, type: $type) { 3 | lists { 4 | name 5 | isCustomList 6 | entries { 7 | ...mediaListEntry 8 | } 9 | } 10 | } 11 | } 12 | 13 | fragment mediaListEntry on MediaList { 14 | status 15 | progress 16 | progressVolumes 17 | score 18 | startedAt { 19 | year 20 | month 21 | day 22 | } 23 | completedAt { 24 | year 25 | month 26 | day 27 | } 28 | media { 29 | title { 30 | romaji 31 | english 32 | native 33 | } 34 | description 35 | type 36 | status(version: 2) 37 | episodes 38 | volumes 39 | chapters 40 | averageScore 41 | countryOfOrigin 42 | genres 43 | coverImage { 44 | medium 45 | } 46 | startDate { 47 | year 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /source/plugins/anilist/queries/statistics.graphql: -------------------------------------------------------------------------------- 1 | query Statistics ($name: String) { 2 | User(name: $name) { 3 | id 4 | name 5 | about 6 | statistics { 7 | anime { 8 | count 9 | minutesWatched 10 | episodesWatched 11 | genres(limit: 4) { 12 | genre 13 | } 14 | } 15 | manga { 16 | count 17 | chaptersRead 18 | volumesRead 19 | genres(limit: 4) { 20 | genre 21 | } 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /source/plugins/base/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Default metrics 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.base.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: header, activity, community, repositories, metadata 7 | -------------------------------------------------------------------------------- /source/plugins/base/queries/calendar.graphql: -------------------------------------------------------------------------------- 1 | query BaseCalendar { 2 | user(login: "$login") { 3 | calendar:contributionsCollection(from: "$calendar.from", to: "$calendar.to") { 4 | contributionCalendar { 5 | weeks { 6 | contributionDays { 7 | color 8 | } 9 | } 10 | } 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /source/plugins/base/queries/contributions.graphql: -------------------------------------------------------------------------------- 1 | query BaseContributions { 2 | user(login: "$login") { 3 | contributionsCollection$range { 4 | $field 5 | } 6 | } 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /source/plugins/base/queries/field.graphql: -------------------------------------------------------------------------------- 1 | query BaseField { 2 | $account(login: "$login") { 3 | $field { 4 | totalCount 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /source/plugins/base/queries/field.repositories.graphql: -------------------------------------------------------------------------------- 1 | query BaseFieldRepositories{ 2 | $account(login: "$login") { 3 | repositories(last: 0 $affiliations) { 4 | $field 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /source/plugins/base/queries/organization.graphql: -------------------------------------------------------------------------------- 1 | query BaseOrganization { 2 | organization(login: "$login") { 3 | databaseId 4 | name 5 | login 6 | location 7 | createdAt 8 | avatarUrl 9 | websiteUrl 10 | isVerified 11 | twitterUsername 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /source/plugins/base/queries/organization.x.graphql: -------------------------------------------------------------------------------- 1 | query BaseOrganizationX { 2 | organization(login: "$login") { 3 | packages { 4 | totalCount 5 | } 6 | sponsorshipsAsSponsor { 7 | totalCount 8 | } 9 | sponsorshipsAsMaintainer { 10 | totalCount 11 | } 12 | membersWithRole { 13 | totalCount 14 | } 15 | repositories(last: 0 $affiliations) { 16 | totalCount 17 | totalDiskUsage 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /source/plugins/base/queries/repository.graphql: -------------------------------------------------------------------------------- 1 | query BaseRepository { 2 | $account(login: "$login") { 3 | repository(name: "$repo") { 4 | name 5 | createdAt 6 | diskUsage 7 | homepageUrl 8 | owner { 9 | login 10 | } 11 | isFork 12 | forkCount 13 | watchers { 14 | totalCount 15 | } 16 | stargazers { 17 | totalCount 18 | } 19 | releases { 20 | totalCount 21 | } 22 | deployments { 23 | totalCount 24 | } 25 | environments { 26 | totalCount 27 | } 28 | languages(first: 8) { 29 | edges { 30 | size 31 | node { 32 | color 33 | name 34 | } 35 | } 36 | } 37 | licenseInfo { 38 | name 39 | spdxId 40 | } 41 | issues_open: issues(states: OPEN) { 42 | totalCount 43 | } 44 | issues_closed: issues(states: CLOSED) { 45 | totalCount 46 | } 47 | pr_open: pullRequests(states: OPEN) { 48 | totalCount 49 | } 50 | pr_closed: pullRequests(states: CLOSED) { 51 | totalCount 52 | } 53 | pr_merged: pullRequests(states: MERGED) { 54 | totalCount 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /source/plugins/base/queries/user.graphql: -------------------------------------------------------------------------------- 1 | query BaseUser { 2 | user(login: "$login") { 3 | databaseId 4 | name 5 | login 6 | location 7 | createdAt 8 | avatarUrl 9 | websiteUrl 10 | twitterUsername 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/plugins/calendar/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Current year calendar 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.calendar.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_calendar: yes 8 | 9 | - name: Full history calendar 10 | uses: lowlighter/metrics@latest 11 | with: 12 | filename: metrics.plugin.calendar.full.svg 13 | token: ${{ secrets.METRICS_TOKEN }} 14 | base: "" 15 | plugin_calendar: yes 16 | plugin_calendar_limit: 0 17 | -------------------------------------------------------------------------------- /source/plugins/calendar/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 📆 Commit calendar 2 | category: github 3 | description: | 4 | This plugin can display commit calendar across several years. 5 | examples: 6 | current year: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.calendar.svg 7 | +full history: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.calendar.full.svg 8 | index: 17 9 | supports: 10 | - user 11 | scopes: 12 | - public_access 13 | inputs: 14 | 15 | plugin_calendar: 16 | description: | 17 | Enable calendar plugin 18 | type: boolean 19 | default: no 20 | 21 | plugin_calendar_limit: 22 | description: | 23 | Years to display 24 | 25 | This option has different behaviours depending on its value: 26 | - `n > 0` will display the last `n` years, relative to current year 27 | - `n == 0` will display all years starting from GitHub account registration date 28 | - `n < 0` will display all years plus `n` additional years, relative to GitHub account registration date 29 | - Use this when there are commits pushed before GitHub registration 30 | type: number 31 | default: 1 32 | zero: disable -------------------------------------------------------------------------------- /source/plugins/calendar/queries/calendar.graphql: -------------------------------------------------------------------------------- 1 | query CalendarDefault { 2 | user(login: "$login") { 3 | calendar:contributionsCollection(from: "$from", to: "$to") { 4 | contributionCalendar { 5 | weeks { 6 | contributionDays { 7 | contributionCount 8 | color 9 | date 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /source/plugins/code/examples.yml: -------------------------------------------------------------------------------- 1 | - name: JavaScript or TypeScript snippet of the day 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.code.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_code: yes 8 | plugin_code_languages: javascript, typescript 9 | plugin_code_load: 400 -------------------------------------------------------------------------------- /source/plugins/community/16personalities/examples.yml: -------------------------------------------------------------------------------- 1 | - name: MBTI Personality profile 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.16personalities.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_16personalities: yes 8 | plugin_16personalities_url: ${{ secrets.SIXTEEN_PERSONALITIES_URL }} 9 | plugin_16personalities_sections: personality, traits 10 | plugin_16personalities_scores: no 11 | -------------------------------------------------------------------------------- /source/plugins/community/chess/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Last chess game from lichess.org 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.chess.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_chess: yes 8 | plugin_chess_token: ${{ secrets.CHESS_TOKEN }} 9 | plugin_chess_platform: lichess.org 10 | 11 | -------------------------------------------------------------------------------- /source/plugins/community/crypto/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Crypto Metrics 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.crypto.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_crypto: yes 8 | plugin_crypto_id: bitcoin 9 | plugin_crypto_vs_currency: usd 10 | plugin_crypto_days: 1 11 | plugin_crypto_precision: 2 12 | prod: 13 | skip: true 14 | test: 15 | skip: true -------------------------------------------------------------------------------- /source/plugins/community/fortune/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Fortune 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.fortune.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_fortune: yes 8 | -------------------------------------------------------------------------------- /source/plugins/community/fortune/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 🥠 Fortune 2 | category: community 3 | description: | 4 | This plugins displays a random fortune message 5 | examples: 6 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.fortune.svg 7 | authors: 8 | - lowlighter 9 | supports: 10 | - user 11 | scopes: [] 12 | inputs: 13 | 14 | plugin_fortune: 15 | description: | 16 | Enable fortune plugin 17 | type: boolean 18 | default: no 19 | -------------------------------------------------------------------------------- /source/plugins/community/nightscout/examples.yml: -------------------------------------------------------------------------------- 1 | - uses: lowlighter/metrics@latest 2 | with: 3 | token: NOT_NEEDED 4 | plugin_nightscout: yes 5 | plugin_nightscout_url: ${{ secrets.NIGHTSCOUT_URL }} 6 | prod: 7 | skip: true -------------------------------------------------------------------------------- /source/plugins/community/poopmap/examples.yml: -------------------------------------------------------------------------------- 1 | - uses: lowlighter/metrics@latest 2 | with: 3 | token: NOT_NEEDED 4 | plugin_poopmap_token: ${{ secrets.POOPMAP_TOKEN }} 5 | plugin_poopmap: yes 6 | prod: 7 | skip: true -------------------------------------------------------------------------------- /source/plugins/community/poopmap/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 💩 PoopMap plugin 2 | category: community 3 | description: | 4 | This plugin displays statistics from a [PoopMap](https://poopmap.net) account. 5 | disclaimer: | 6 | This plugin is not affiliated, associated, authorized, endorsed by, or in any way officially connected with [PoopMap](https://poopmap.net). 7 | All product and company names are trademarks™ or registered® trademarks of their respective holders. 8 | examples: 9 | default: https://github.com/matievisthekat/matievisthekat/blob/master/metrics.plugin.poopmap.svg 10 | authors: 11 | - matievisthekat 12 | supports: 13 | - user 14 | scopes: [] 15 | inputs: 16 | 17 | plugin_poopmap: 18 | description: | 19 | Enable poopmap plugin 20 | type: boolean 21 | default: no 22 | 23 | plugin_poopmap_token: 24 | description: | 25 | PoopMap API token 26 | type: token 27 | default: "" 28 | 29 | plugin_poopmap_days: 30 | description: | 31 | Time range 32 | type: number 33 | values: 34 | - 7 35 | - 30 36 | - 180 37 | - 365 38 | default: 7 39 | -------------------------------------------------------------------------------- /source/plugins/community/screenshot/examples.yml: -------------------------------------------------------------------------------- 1 | - name: XKCD of the day 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.screenshot.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_screenshot: yes 8 | plugin_screenshot_title: XKCD of the day 9 | plugin_screenshot_url: https://xkcd.com 10 | plugin_screenshot_selector: "#comic img" 11 | test: 12 | timeout: 1800000 13 | modes: 14 | - action -------------------------------------------------------------------------------- /source/plugins/community/splatoon/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Splatnet data 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.splatoon.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_splatoon: yes 8 | plugin_splatoon_token: ${{ secrets.SPLATOON_TOKEN }} 9 | test: 10 | skip: true 11 | prod: 12 | skip: true 13 | 14 | - name: Splatnet data with stat.ink integration 15 | uses: lowlighter/metrics@latest 16 | with: 17 | filename: metrics.plugin.splatoon.svg 18 | token: NOT_NEEDED 19 | base: "" 20 | plugin_splatoon: yes 21 | plugin_splatoon_token: ${{ secrets.SPLATOON_TOKEN }} 22 | plugin_splatoon_statink: yes 23 | plugin_splatoon_statink_token: ${{ secrets.SPLATOON_STATINK_TOKEN }} 24 | extras_css: | 25 | h2 { display: none !important; } 26 | test: 27 | skip: true 28 | prod: 29 | skip: true -------------------------------------------------------------------------------- /source/plugins/community/splatoon/s3si/.gitignore: -------------------------------------------------------------------------------- 1 | cache 2 | export 3 | profile.json -------------------------------------------------------------------------------- /source/plugins/community/stock/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Stock prices from Tesla 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.stock.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_stock: yes 8 | plugin_stock_token: ${{ secrets.STOCK_TOKEN }} 9 | plugin_stock_symbol: TSLA 10 | -------------------------------------------------------------------------------- /source/plugins/contributors/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Contributors with contributions count 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.contributors.contributions.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | template: repository 8 | repo: metrics 9 | plugin_contributors: yes 10 | plugin_contributors_contributions: yes 11 | 12 | - name: Contributors by categories 13 | uses: lowlighter/metrics@latest 14 | with: 15 | filename: metrics.plugin.contributors.categories.svg 16 | token: ${{ secrets.METRICS_TOKEN }} 17 | base: "" 18 | template: repository 19 | repo: metrics 20 | plugin_contributors: yes 21 | plugin_contributors_sections: categories 22 | plugin_contributors_categories: | 23 | { 24 | "🧩 Plugins / 🖼️ templates":["source/plugins/**", "source/templates/**"], 25 | "📚 Documentation":["README.md", "**/README.md", "**/metadata.yml"], 26 | "💻 Code (other)":["source/**", "Dockerfile"] 27 | } 28 | -------------------------------------------------------------------------------- /source/plugins/contributors/queries/commit.graphql: -------------------------------------------------------------------------------- 1 | query ContributorsCommit { 2 | repository(owner: "$owner" name: "$repo") { 3 | object(expression: "$expression") { 4 | ... on Commit { 5 | oid 6 | abbreviatedOid 7 | messageHeadline 8 | committedDate 9 | } 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /source/plugins/discussions/examples.yml: -------------------------------------------------------------------------------- 1 | - name: GitHub Discussions 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.discussions.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_discussions: yes 8 | plugin_discussions_categories_limit: 8 9 | -------------------------------------------------------------------------------- /source/plugins/discussions/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 💬 Discussions 2 | category: github 3 | description: | 4 | This plugin displays GitHub discussions stats. 5 | examples: 6 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.discussions.svg 7 | index: 15 8 | supports: 9 | - user 10 | scopes: 11 | - public_access 12 | inputs: 13 | 14 | plugin_discussions: 15 | description: | 16 | Enable discussions plugin 17 | type: boolean 18 | default: no 19 | 20 | plugin_discussions_categories: 21 | description: | 22 | Discussion categories 23 | type: boolean 24 | default: yes 25 | 26 | plugin_discussions_categories_limit: 27 | description: | 28 | Display limit (categories) 29 | 30 | Note that categories are sorted from highest to lowest count 31 | type: number 32 | default: 0 33 | zero: disable -------------------------------------------------------------------------------- /source/plugins/discussions/queries/categories.graphql: -------------------------------------------------------------------------------- 1 | query DiscussionsCategories { 2 | user(login: "$login") { 3 | repositoryDiscussions($after first: 100, orderBy: {field: CREATED_AT, direction: DESC}) { 4 | edges { 5 | cursor 6 | } 7 | nodes { 8 | upvoteCount 9 | category { 10 | emoji 11 | name 12 | } 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /source/plugins/discussions/queries/comments.graphql: -------------------------------------------------------------------------------- 1 | query DiscussionsComments { 2 | user(login: "$login") { 3 | repositoryDiscussionComments($after first: 100) { 4 | edges { 5 | cursor 6 | } 7 | nodes { 8 | upvoteCount 9 | } 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /source/plugins/discussions/queries/statistics.graphql: -------------------------------------------------------------------------------- 1 | query DiscussionsStatistics { 2 | user(login: "$login") { 3 | started: repositoryDiscussions { 4 | totalCount 5 | } 6 | comments: repositoryDiscussionComments { 7 | totalCount 8 | } 9 | answers: repositoryDiscussionComments(onlyAnswers: true) { 10 | totalCount 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /source/plugins/followup/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Opened on user's repositories 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.followup.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_followup: yes 8 | 9 | - name: Opened by user 10 | uses: lowlighter/metrics@latest 11 | with: 12 | filename: metrics.plugin.followup.user.svg 13 | token: ${{ secrets.METRICS_TOKEN }} 14 | base: "" 15 | plugin_followup: yes 16 | plugin_followup_sections: user 17 | 18 | - name: Indepth analysis 19 | uses: lowlighter/metrics@latest 20 | with: 21 | filename: metrics.plugin.followup.indepth.svg 22 | token: ${{ secrets.METRICS_TOKEN }} 23 | base: "" 24 | plugin_followup: yes 25 | plugin_followup_indepth: yes 26 | 27 | - name: Exclude Archived 28 | uses: lowlighter/metrics@latest 29 | with: 30 | filename: metrics.plugin.followup.archived.svg 31 | token: ${{ secrets.METRICS_TOKEN }} 32 | base: "" 33 | plugin_followup: yes 34 | plugin_followup_archived: no 35 | prod: 36 | skip: true -------------------------------------------------------------------------------- /source/plugins/followup/queries/repository.collaborators.graphql: -------------------------------------------------------------------------------- 1 | query FollowupRepositoryCollaborators { 2 | repository(name: "$repo", owner: "$owner") { 3 | collaborators { 4 | nodes { 5 | login 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/plugins/followup/queries/repository.graphql: -------------------------------------------------------------------------------- 1 | query FollowupRepository { 2 | issues_open:search(query: "repo:$owner/$repo is:issue $collaborators is:open", type: ISSUE, first: 0) { 3 | issueCount 4 | } 5 | issues_drafts:search(query: "repo:$owner/$repo is:issue $collaborators draft:true", type: ISSUE, first: 0) { 6 | issueCount 7 | } 8 | issues_skipped:search(query: "repo:$owner/$repo is:issue $collaborators is:closed label:wontfix,duplicate", type: ISSUE, first: 0) { 9 | issueCount 10 | } 11 | issues_closed:search(query: "repo:$owner/$repo is:issue $collaborators is:closed", type: ISSUE, first: 0) { 12 | issueCount 13 | } 14 | pr_open:search(query: "repo:$owner/$repo is:pr $collaborators is:open draft:false", type: ISSUE, first: 0) { 15 | issueCount 16 | } 17 | pr_drafts:search(query: "repo:$owner/$repo is:pr $collaborators draft:true", type: ISSUE, first: 0) { 18 | issueCount 19 | } 20 | pr_closed:search(query: "repo:$owner/$repo is:pr $collaborators is:unmerged is:closed draft:false", type: ISSUE, first: 0) { 21 | issueCount 22 | } 23 | pr_merged:search(query: "repo:$owner/$repo is:pr $collaborators is:merged", type: ISSUE, first: 0) { 24 | issueCount 25 | } 26 | } -------------------------------------------------------------------------------- /source/plugins/followup/queries/user.graphql: -------------------------------------------------------------------------------- 1 | query FollowupUser { 2 | issues_open:search(query: "is:issue author:$login is:open $archived", type: ISSUE, first: 0) { 3 | issueCount 4 | } 5 | issues_drafts:search(query: "is:issue author:$login draft:true $archived", type: ISSUE, first: 0) { 6 | issueCount 7 | } 8 | issues_skipped:search(query: "is:issue author:$login is:closed label:wontfix,duplicate $archived", type: ISSUE, first: 0) { 9 | issueCount 10 | } 11 | issues_closed:search(query: "is:issue author:$login is:closed $archived", type: ISSUE, first: 0) { 12 | issueCount 13 | } 14 | pr_open:search(query: "is:pr author:$login is:open draft:false $archived", type: ISSUE, first: 0) { 15 | issueCount 16 | } 17 | pr_drafts:search(query: "is:pr author:$login draft:true $archived", type: ISSUE, first: 0) { 18 | issueCount 19 | } 20 | pr_closed:search(query: "is:pr author:$login is:unmerged is:closed draft:false $archived", type: ISSUE, first: 0) { 21 | issueCount 22 | } 23 | pr_merged:search(query: "is:pr author:$login is:merged $archived", type: ISSUE, first: 0) { 24 | issueCount 25 | } 26 | } -------------------------------------------------------------------------------- /source/plugins/gists/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Gists 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.gists.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_gists: yes 8 | -------------------------------------------------------------------------------- /source/plugins/gists/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 🎫 Gists 2 | category: github 3 | description: | 4 | This plugin displays [gists](https://gist.github.com) stats. 5 | examples: 6 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.gists.svg 7 | index: 24 8 | supports: 9 | - user 10 | scopes: 11 | - public_access 12 | inputs: 13 | 14 | plugin_gists: 15 | description: | 16 | Enable gists plugin 17 | type: boolean 18 | default: no 19 | -------------------------------------------------------------------------------- /source/plugins/gists/queries/gists.graphql: -------------------------------------------------------------------------------- 1 | query GistsDefault { 2 | user(login: "$login") { 3 | gists($after first: 100, orderBy: {field: UPDATED_AT, direction: DESC}) { 4 | edges { 5 | cursor 6 | } 7 | totalCount 8 | nodes { 9 | stargazerCount 10 | isFork 11 | forks { 12 | totalCount 13 | } 14 | files { 15 | name 16 | } 17 | comments { 18 | totalCount 19 | } 20 | } 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /source/plugins/habits/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Mildly interesting facts 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.habits.facts.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_habits: yes 8 | plugin_habits_facts: yes 9 | plugin_habits_charts: no 10 | config_timezone: Europe/Paris 11 | 12 | - name: Recent activity charts 13 | uses: lowlighter/metrics@latest 14 | with: 15 | filename: metrics.plugin.habits.charts.svg 16 | token: ${{ secrets.METRICS_TOKEN }} 17 | base: "" 18 | plugin_habits: yes 19 | plugin_habits_facts: no 20 | plugin_habits_charts: yes 21 | config_timezone: Europe/Paris -------------------------------------------------------------------------------- /source/plugins/introduction/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Organization introduction 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.introduction.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | user: github 7 | base: header 8 | plugin_introduction: yes 9 | prod: 10 | with: 11 | token: ${{ secrets.METRICS_TOKEN_WITH_SCOPES }} 12 | 13 | - name: Repository introduction 14 | uses: lowlighter/metrics@latest 15 | with: 16 | filename: metrics.plugin.introduction.repository.svg 17 | token: ${{ secrets.METRICS_TOKEN }} 18 | template: repository 19 | repo: metrics 20 | base: header 21 | plugin_introduction: yes 22 | -------------------------------------------------------------------------------- /source/plugins/introduction/metadata.yml: -------------------------------------------------------------------------------- 1 | name: "🙋 Introduction" 2 | category: github 3 | description: | 4 | This plugin displays account bio or organization/repository description. 5 | 6 | Since account bio is already displayed on account profile, this plugin is mostly intended for external usage. 7 | examples: 8 | +for a user or an organization: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.introduction.svg 9 | for a repository: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.introduction.repository.svg 10 | index: 26 11 | supports: 12 | - user 13 | - organization 14 | - repository 15 | scopes: 16 | - public_access 17 | inputs: 18 | 19 | plugin_introduction: 20 | description: | 21 | Enable introduction plugin 22 | type: boolean 23 | default: no 24 | 25 | plugin_introduction_title: 26 | description: | 27 | Section title 28 | type: boolean 29 | default: yes 30 | -------------------------------------------------------------------------------- /source/plugins/introduction/queries/organization.graphql: -------------------------------------------------------------------------------- 1 | query IntroductionOrganization { 2 | organization(login: "$login") { 3 | description 4 | } 5 | } -------------------------------------------------------------------------------- /source/plugins/introduction/queries/repository.graphql: -------------------------------------------------------------------------------- 1 | query IntroductionRepository { 2 | repository(name: "$repo", owner: "$owner") { 3 | description 4 | } 5 | } -------------------------------------------------------------------------------- /source/plugins/introduction/queries/user.graphql: -------------------------------------------------------------------------------- 1 | query IntroductionUser { 2 | user(login: "$login") { 3 | bio 4 | } 5 | } -------------------------------------------------------------------------------- /source/plugins/isocalendar/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Half-year calendar 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.isocalendar.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_isocalendar: yes 8 | 9 | - name: Full-year calendar 10 | uses: lowlighter/metrics@latest 11 | with: 12 | filename: metrics.plugin.isocalendar.fullyear.svg 13 | token: ${{ secrets.METRICS_TOKEN }} 14 | base: "" 15 | plugin_isocalendar: yes 16 | plugin_isocalendar_duration: full-year 17 | -------------------------------------------------------------------------------- /source/plugins/isocalendar/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 📅 Isometric commit calendar 2 | category: github 3 | description: | 4 | This plugin displays an isometric view of a user commit calendar along with a few additional statistics like current streak and average number of commit per day. 5 | examples: 6 | +full year calendar: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.isocalendar.fullyear.svg 7 | half year calendar: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.isocalendar.svg 8 | index: 0 9 | supports: 10 | - user 11 | scopes: 12 | - public_access 13 | inputs: 14 | 15 | plugin_isocalendar: 16 | description: | 17 | Enable isocalendar plugin 18 | type: boolean 19 | default: no 20 | 21 | plugin_isocalendar_duration: 22 | description: | 23 | Time range 24 | 25 | - `half-year`: 180 days 26 | - `full-year`: 1 year 27 | type: string 28 | default: half-year 29 | values: 30 | - half-year 31 | - full-year -------------------------------------------------------------------------------- /source/plugins/isocalendar/queries/calendar.graphql: -------------------------------------------------------------------------------- 1 | query IsocalendarCalendar { 2 | user(login: "$login") { 3 | calendar:contributionsCollection(from: "$from", to: "$to") { 4 | contributionCalendar { 5 | weeks { 6 | contributionDays { 7 | contributionCount 8 | color 9 | date 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /source/plugins/languages/analyzers.mjs: -------------------------------------------------------------------------------- 1 | //Imports 2 | import { cli } from "./analyzer/cli.mjs" 3 | import { IndepthAnalyzer } from "./analyzer/indepth.mjs" 4 | import { RecentAnalyzer } from "./analyzer/recent.mjs" 5 | 6 | /**Indepth analyzer */ 7 | export async function indepth({login, data, imports, rest, context, repositories}, {skipped, categories, timeout}) { 8 | return new IndepthAnalyzer(login, {shell: imports, uid: data.user.databaseId, skipped, authoring: data.shared["commits.authoring"], timeout, rest, context, categories}).run({repositories}) 9 | } 10 | 11 | /**Recent languages activity */ 12 | export async function recent({login, data, imports, rest, context, account}, {skipped = [], categories, days = 0, load = 0, timeout}) { 13 | return new RecentAnalyzer(login, {shell: imports, uid: data.user.databaseId, skipped, authoring: data.shared["commits.authoring"], timeout, account, rest, context, days, categories, load}).run() 14 | } 15 | 16 | //import.meta.main 17 | if (/languages.analyzers.mjs$/.test(process.argv[1])) { 18 | ;(async () => { 19 | console.log(await cli()) 20 | process.exit(0) 21 | })() 22 | } 23 | -------------------------------------------------------------------------------- /source/plugins/languages/colorsets.json: -------------------------------------------------------------------------------- 1 | { 2 | "rainbow":["0:#ff0000", "1:#ffa500", "2:#ffff00", "3:#008000", "4:#0000ff", "5:#4b0082", "6:#ee82ee", "7:#162221"], 3 | "complementary":["0:#ff0000", "1:#008000", "2:#ffa500", "3:#0000ff", "4:#ffff00", "5:#4b0082", "6:#162221", "7:#ee82ee"] 4 | } -------------------------------------------------------------------------------- /source/plugins/leetcode/examples.yml: -------------------------------------------------------------------------------- 1 | - name: LeetCode 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.leetcode.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_leetcode: yes 8 | plugin_leetcode_sections: solved, skills, recent 9 | -------------------------------------------------------------------------------- /source/plugins/leetcode/queries/languages.graphql: -------------------------------------------------------------------------------- 1 | query Languages ($username: String!) { 2 | matchedUser(username: $username) { 3 | languageProblemCount { 4 | languageName 5 | problemsSolved 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /source/plugins/leetcode/queries/problems.graphql: -------------------------------------------------------------------------------- 1 | query Problems ($username: String!) { 2 | allQuestionsCount { 3 | difficulty 4 | count 5 | } 6 | matchedUser(username: $username) { 7 | problemsSolvedBeatsStats { 8 | difficulty 9 | percentage 10 | } 11 | submitStatsGlobal { 12 | acSubmissionNum { 13 | difficulty 14 | count 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /source/plugins/leetcode/queries/recent.graphql: -------------------------------------------------------------------------------- 1 | query Recent ($username: String!, $limit: Int!) { 2 | recentAcSubmissionList(username: $username, limit: $limit) { 3 | id 4 | title 5 | titleSlug 6 | timestamp 7 | } 8 | } -------------------------------------------------------------------------------- /source/plugins/leetcode/queries/skills.graphql: -------------------------------------------------------------------------------- 1 | query Skills ($username: String!) { 2 | matchedUser(username: $username) { 3 | tagProblemCounts { 4 | advanced { 5 | tagName 6 | problemsSolved 7 | } 8 | intermediate { 9 | tagName 10 | problemsSolved 11 | } 12 | fundamental { 13 | tagName 14 | problemsSolved 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /source/plugins/licenses/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Licenses and permissions 2 | with: 3 | filename: metrics.plugin.licenses.svg 4 | token: ${{ secrets.METRICS_TOKEN }} 5 | base: "" 6 | template: repository 7 | repo: metrics 8 | plugin_licenses: yes 9 | plugin_licenses_setup: "bash -c '[[ -f package.json ]] && npm ci || true'" 10 | test: 11 | timeout: 1800000 12 | modes: 13 | - action 14 | 15 | - name: Licenses with open-source ratio graphs 16 | uses: lowlighter/metrics@latest 17 | with: 18 | filename: metrics.plugin.licenses.ratio.svg 19 | token: ${{ secrets.METRICS_TOKEN }} 20 | base: "" 21 | template: repository 22 | repo: metrics 23 | plugin_licenses: yes 24 | plugin_licenses_setup: "bash -c '[[ -f package.json ]] && npm ci || true'" 25 | plugin_licenses_legal: no 26 | plugin_licenses_ratio: yes 27 | test: 28 | skip: true -------------------------------------------------------------------------------- /source/plugins/licenses/queries/licenses.graphql: -------------------------------------------------------------------------------- 1 | query LicensesDefault { 2 | licenses { 3 | spdxId 4 | name 5 | nickname 6 | key 7 | limitations { 8 | key 9 | label 10 | } 11 | conditions { 12 | key 13 | label 14 | } 15 | permissions { 16 | key 17 | label 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /source/plugins/licenses/queries/repository.graphql: -------------------------------------------------------------------------------- 1 | query LicensesRepository { 2 | $account(login: "$owner") { 3 | repository(name: "$name") { 4 | licenseInfo { 5 | spdxId 6 | name 7 | nickname 8 | key 9 | } 10 | url 11 | databaseId 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /source/plugins/lines/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Compact display in base plugin 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.lines.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: repositories 7 | plugin_lines: yes 8 | plugin_lines_delay: 30 9 | 10 | - name: Repositories and diff history 11 | uses: lowlighter/metrics@latest 12 | with: 13 | filename: metrics.plugin.lines.history.svg 14 | token: ${{ secrets.METRICS_TOKEN }} 15 | base: "" 16 | plugin_lines: yes 17 | plugin_lines_delay: 30 18 | plugin_lines_sections: repositories, history 19 | plugin_lines_repositories_limit: 2 20 | plugin_lines_history_limit: 1 21 | repositories_skipped: | 22 | @use.patterns 23 | */* 24 | +lowlighter/metrics 25 | -------------------------------------------------------------------------------- /source/plugins/notable/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Contributions 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.notable.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_notable: yes 8 | 9 | - name: Indepth analysis 10 | uses: lowlighter/metrics@latest 11 | with: 12 | filename: metrics.plugin.notable.indepth.svg 13 | token: ${{ secrets.METRICS_TOKEN }} 14 | base: "" 15 | plugin_notable: yes 16 | plugin_notable_indepth: yes 17 | plugin_notable_repositories: yes 18 | -------------------------------------------------------------------------------- /source/plugins/notable/queries/commits.graphql: -------------------------------------------------------------------------------- 1 | { 2 | repository(owner: "$owner", name: "$repo") { 3 | ...RepoFragment 4 | } 5 | } 6 | 7 | fragment RepoFragment on Repository { 8 | name 9 | defaultBranchRef { 10 | name 11 | target { 12 | ... on Commit { 13 | id 14 | history(first: 0) { 15 | totalCount 16 | } 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /source/plugins/notable/queries/contributions.graphql: -------------------------------------------------------------------------------- 1 | query NotableContributions { 2 | user(login: "$login") { 3 | repositoriesContributedTo($after first: $repositories, contributionTypes: [$types], includeUserRepositories: $self, orderBy: { field: STARGAZERS, direction: DESC }) { 4 | edges { 5 | cursor 6 | node { 7 | isInOrganization 8 | owner { 9 | login 10 | avatarUrl 11 | } 12 | nameWithOwner 13 | watchers { 14 | totalCount 15 | } 16 | forks { 17 | totalCount 18 | } 19 | stargazers { 20 | totalCount 21 | } 22 | issues { 23 | totalCount 24 | } 25 | pullRequests { 26 | totalCount 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /source/plugins/notable/queries/issues.graphql: -------------------------------------------------------------------------------- 1 | query NotableIssues { 2 | user(login: "$login") { 3 | $type($after first: 100, orderBy: {field: CREATED_AT, direction: DESC}) { 4 | totalCount 5 | edges { 6 | cursor 7 | node { 8 | repository { 9 | nameWithOwner 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /source/plugins/people/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Followers 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.people.followers.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_people: yes 8 | plugin_people_types: followers 9 | 10 | - name: Contributors and sponsors 11 | uses: lowlighter/metrics@latest 12 | with: 13 | filename: metrics.plugin.people.repository.svg 14 | token: ${{ secrets.METRICS_TOKEN }} 15 | base: "" 16 | template: repository 17 | repo: metrics 18 | plugin_people: yes 19 | plugin_people_types: contributors, stargazers, watchers, sponsors 20 | -------------------------------------------------------------------------------- /source/plugins/people/queries/people.graphql: -------------------------------------------------------------------------------- 1 | query PeopleDefault { 2 | $account(login: "$login") { 3 | login 4 | $type($after first: 100) { 5 | edges { 6 | cursor 7 | node { 8 | login 9 | avatarUrl(size: $size) 10 | } 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /source/plugins/people/queries/repository.graphql: -------------------------------------------------------------------------------- 1 | query PeopleRepository { 2 | $account(login: "$login") { 3 | repository(name: "$repository") { 4 | $type($after first: 100) { 5 | edges { 6 | cursor 7 | node { 8 | login 9 | avatarUrl(size: $size) 10 | } 11 | } 12 | } 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /source/plugins/people/queries/sponsors.graphql: -------------------------------------------------------------------------------- 1 | query PeopleSponsors { 2 | $account(login: "$login") { 3 | login 4 | $type($after first: 100) { 5 | edges { 6 | cursor 7 | node { 8 | $target { 9 | ... on User { 10 | login 11 | avatarUrl(size: $size) 12 | } 13 | } 14 | } 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /source/plugins/posts/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Recent posts 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.posts.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_posts: yes 8 | plugin_posts_source: dev.to 9 | 10 | - name: Recent posts with descriptions and cover images 11 | uses: lowlighter/metrics@latest 12 | with: 13 | filename: metrics.plugin.posts.full.svg 14 | token: NOT_NEEDED 15 | base: "" 16 | plugin_posts: yes 17 | plugin_posts_source: dev.to 18 | plugin_posts_limit: 2 19 | plugin_posts_descriptions: yes 20 | plugin_posts_covers: yes 21 | -------------------------------------------------------------------------------- /source/plugins/posts/queries/hashnode.graphql: -------------------------------------------------------------------------------- 1 | query PostsHashnode { 2 | user(username: "$user"){ 3 | publication{ 4 | posts(page: 0) { 5 | slug 6 | title 7 | brief 8 | coverImage 9 | dateAdded 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /source/plugins/projects/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Project from a repository 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.projects.svg 5 | token: ${{ secrets.METRICS_TOKEN_WITH_SCOPES }} 6 | base: "" 7 | plugin_projects: yes 8 | plugin_projects_repositories: lowlighter/metrics/projects/1 9 | plugin_projects_descriptions: yes 10 | -------------------------------------------------------------------------------- /source/plugins/projects/queries/repository.graphql: -------------------------------------------------------------------------------- 1 | query ProjectsRepository { 2 | $account(login: "$user") { 3 | repository(name: "$repository") { 4 | projectV2(number: $id) { 5 | name: title 6 | body: shortDescription 7 | updatedAt 8 | items(first: 4, orderBy: {field: POSITION, direction: ASC}) { 9 | totalCount 10 | nodes { 11 | type 12 | isArchived 13 | fieldValues(last: 100) { 14 | nodes { 15 | ... on ProjectV2ItemFieldTextValue { 16 | text 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /source/plugins/projects/queries/repository.legacy.graphql: -------------------------------------------------------------------------------- 1 | query ProjectsRepositoryLegacy { 2 | $account(login: "$user") { 3 | repository(name: "$repository") { 4 | project(number: $id) { 5 | name 6 | body 7 | updatedAt 8 | progress { 9 | doneCount 10 | inProgressCount 11 | todoCount 12 | enabled 13 | } 14 | } 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /source/plugins/projects/queries/user.graphql: -------------------------------------------------------------------------------- 1 | query ProjectsUser { 2 | $account(login: "$login") { 3 | projectsV2(last: $limit, orderBy: {field: UPDATED_AT, direction: DESC}) { 4 | totalCount 5 | nodes { 6 | name: title 7 | body: shortDescription 8 | updatedAt 9 | items(first: 4, orderBy: {field: POSITION, direction: ASC}) { 10 | totalCount 11 | nodes { 12 | type 13 | isArchived 14 | fieldValues(last: 100) { 15 | nodes { 16 | ... on ProjectV2ItemFieldTextValue { 17 | text 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /source/plugins/projects/queries/user.legacy.graphql: -------------------------------------------------------------------------------- 1 | query ProjectsUserLegacy { 2 | $account(login: "$login") { 3 | projects(last: $limit, states: OPEN, orderBy: {field: UPDATED_AT, direction: DESC}) { 4 | totalCount 5 | nodes { 6 | name 7 | body 8 | updatedAt 9 | progress { 10 | doneCount 11 | inProgressCount 12 | todoCount 13 | enabled 14 | } 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /source/plugins/reactions/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Comment reactions 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.reactions.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_reactions: yes 8 | plugin_reactions_limit: 100 9 | plugin_reactions_details: percentage 10 | 11 | -------------------------------------------------------------------------------- /source/plugins/reactions/queries/reactions.graphql: -------------------------------------------------------------------------------- 1 | query ReactionsDefault { 2 | user(login: "$login") { 3 | login 4 | $type($before last: 50) { 5 | edges { 6 | cursor 7 | node { 8 | createdAt 9 | reactions(last: 100, orderBy: {field: CREATED_AT, direction: DESC}) { 10 | nodes { 11 | content 12 | user { 13 | login 14 | } 15 | } 16 | } 17 | } 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/plugins/repositories/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Featured repositories 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.repositories.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_repositories: yes 8 | plugin_repositories_featured: lowlighter/metrics 9 | 10 | - name: Pinned repositories 11 | uses: lowlighter/metrics@latest 12 | with: 13 | filename: metrics.plugin.repositories.pinned.svg 14 | token: ${{ secrets.METRICS_TOKEN }} 15 | base: "" 16 | plugin_repositories: yes 17 | plugin_repositories_pinned: 2 18 | -------------------------------------------------------------------------------- /source/plugins/repositories/queries/pinned.graphql: -------------------------------------------------------------------------------- 1 | query RepositoriesPinned { 2 | user(login: "$login") { 3 | pinnedItems(types: REPOSITORY, first: $limit) { 4 | edges { 5 | node { 6 | ... on Repository { 7 | createdAt 8 | description 9 | forkCount 10 | isFork 11 | issues { 12 | totalCount 13 | } 14 | nameWithOwner 15 | openGraphImageUrl 16 | licenseInfo { 17 | nickname 18 | spdxId 19 | name 20 | } 21 | pullRequests { 22 | totalCount 23 | } 24 | stargazerCount 25 | primaryLanguage { 26 | color 27 | name 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /source/plugins/repositories/queries/random.graphql: -------------------------------------------------------------------------------- 1 | query RepositoriesRandom { 2 | user(login: "$login") { 3 | repositories( 4 | orderBy: {field: UPDATED_AT, direction: DESC} 5 | first: 100 6 | privacy: PUBLIC 7 | $affiliations 8 | $forks 9 | ) { 10 | nodes { 11 | nameWithOwner 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /source/plugins/repositories/queries/repository.graphql: -------------------------------------------------------------------------------- 1 | query RepositoriesRepository { 2 | repository(owner: "$owner", name: "$name") { 3 | createdAt 4 | description 5 | forkCount 6 | isFork 7 | issues { 8 | totalCount 9 | } 10 | nameWithOwner 11 | openGraphImageUrl 12 | licenseInfo { 13 | nickname 14 | spdxId 15 | name 16 | } 17 | pullRequests { 18 | totalCount 19 | } 20 | stargazerCount 21 | primaryLanguage { 22 | color 23 | name 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /source/plugins/repositories/queries/starred.graphql: -------------------------------------------------------------------------------- 1 | query RepositoriesStarred { 2 | user(login: "$login") { 3 | repositories( 4 | orderBy: {field: STARGAZERS, direction: DESC} 5 | first: $limit 6 | privacy: PUBLIC 7 | $affiliations 8 | $forks 9 | ) { 10 | nodes { 11 | nameWithOwner 12 | } 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /source/plugins/rss/examples.yml: -------------------------------------------------------------------------------- 1 | - name: News from hackernews 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.rss.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_rss: yes 8 | plugin_rss_source: https://news.ycombinator.com/rss 9 | plugin_rss_limit: 4 10 | -------------------------------------------------------------------------------- /source/plugins/rss/index.mjs: -------------------------------------------------------------------------------- 1 | //Imports 2 | import rss from "rss-parser" 3 | 4 | //Setup 5 | export default async function({login, q, imports, data, account}, {enabled = false, extras = false} = {}) { 6 | //Plugin execution 7 | try { 8 | //Check if plugin is enabled and requirements are met 9 | if ((!q.rss) || (!imports.metadata.plugins.rss.enabled(enabled, {extras}))) 10 | return null 11 | 12 | //Load inputs 13 | let {source, limit} = imports.metadata.plugins.rss.inputs({data, account, q}) 14 | if (!source) 15 | throw {error: {message: "RSS feed URL is not set"}} 16 | 17 | //Load rss feed 18 | const {title, description, link, items} = await (new rss()).parseURL(source) //eslint-disable-line new-cap 19 | const feed = items.map(({title, link, isoDate: date}) => ({title, link, date: new Date(date)})) 20 | 21 | //Limit feed 22 | if (limit > 0) { 23 | console.debug(`metrics/compute/${login}/plugins > rss > keeping only ${limit} items`) 24 | feed.splice(limit) 25 | } 26 | 27 | //Results 28 | return {source: title, description, link, feed} 29 | } 30 | //Handle errors 31 | catch (error) { 32 | throw imports.format.error(error) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /source/plugins/rss/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 🗼 Rss feed 2 | category: social 3 | description: | 4 | This plugin displays news from a given RSS feed. 5 | examples: 6 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.rss.svg 7 | index: 7 8 | supports: 9 | - user 10 | - organization 11 | - repository 12 | scopes: [] 13 | inputs: 14 | 15 | plugin_rss: 16 | description: | 17 | Enable rss plugin 18 | type: boolean 19 | default: no 20 | 21 | plugin_rss_source: 22 | description: | 23 | RSS feed source 24 | type: string 25 | default: "" 26 | example: https://news.ycombinator.com/rss 27 | 28 | plugin_rss_limit: 29 | description: | 30 | Display limit 31 | type: number 32 | default: 4 33 | min: 0 34 | max: 30 35 | zero: disable -------------------------------------------------------------------------------- /source/plugins/sponsors/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Sponsors goal 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.sponsors.svg 5 | token: ${{ secrets.METRICS_TOKEN_PERSONAL }} 6 | base: "" 7 | plugin_sponsors: yes 8 | plugin_sponsors_sections: goal, list 9 | plugin_sponsors_past: yes 10 | 11 | - name: Sponsors introduction 12 | uses: lowlighter/metrics@latest 13 | with: 14 | filename: metrics.plugin.sponsors.full.svg 15 | token: ${{ secrets.METRICS_TOKEN_WITH_SCOPES }} 16 | base: "" 17 | plugin_sponsors: yes 18 | -------------------------------------------------------------------------------- /source/plugins/sponsors/queries/active.graphql: -------------------------------------------------------------------------------- 1 | query SponsorsActive { 2 | $account(login: "$login") { 3 | sponsorshipsAsMaintainer($after first: 100) { 4 | edges { 5 | cursor 6 | } 7 | nodes { 8 | privacyLevel 9 | sponsorEntity { 10 | ... on User { 11 | login 12 | avatarUrl(size: $size) 13 | } 14 | ... on Organization { 15 | login 16 | avatarUrl(size: $size) 17 | url 18 | } 19 | } 20 | tier { 21 | monthlyPriceInDollars 22 | } 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /source/plugins/sponsors/queries/all.graphql: -------------------------------------------------------------------------------- 1 | query SponsorsAll { 2 | $account(login: "$login") { 3 | sponsorsActivities($after first: 100, period: ALL) { 4 | edges { 5 | cursor 6 | } 7 | nodes { 8 | sponsor { 9 | ... on User { 10 | avatarUrl(size: $size) 11 | login 12 | } 13 | ... on Organization { 14 | login 15 | avatarUrl(size: $size) 16 | url 17 | } 18 | } 19 | sponsorsTier { 20 | monthlyPriceInDollars 21 | } 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /source/plugins/sponsors/queries/description.graphql: -------------------------------------------------------------------------------- 1 | query SponsorsDescription { 2 | $account(login: "$login") { 3 | sponsorsListing { 4 | fullDescription 5 | activeGoal { 6 | percentComplete 7 | title 8 | description 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/plugins/sponsorships/examples.yml: -------------------------------------------------------------------------------- 1 | - name: 💝 GitHub Sponsorships 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.sponsorships.svg 5 | token: ${{ secrets.METRICS_TOKEN_PERSONAL }} 6 | base: "" 7 | plugin_sponsorships: yes 8 | -------------------------------------------------------------------------------- /source/plugins/sponsorships/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 💝 GitHub Sponsorships 2 | category: github 3 | description: | 4 | This plugin displays sponsorships funded through [GitHub sponsors](https://github.com/sponsors/). 5 | examples: 6 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.sponsorships.svg 7 | index: 12 8 | supports: 9 | - user 10 | - organization 11 | scopes: 12 | - read:user 13 | - read:org 14 | inputs: 15 | 16 | plugin_sponsorships: 17 | description: | 18 | Enable sponsorships plugin 19 | type: boolean 20 | default: no 21 | 22 | plugin_sponsorships_sections: 23 | description: | 24 | Displayed sections 25 | 26 | - `amount`: display total amount sponsored 27 | - `sponsorships`: display GitHub sponsorships 28 | type: array 29 | format: comma-separated 30 | default: amount, sponsorships 31 | example: amount, sponsorships 32 | values: 33 | - amount 34 | - sponsorships 35 | 36 | plugin_sponsorships_size: 37 | description: | 38 | Profile picture display size 39 | type: number 40 | default: 24 41 | min: 8 42 | max: 64 -------------------------------------------------------------------------------- /source/plugins/sponsorships/queries/all.graphql: -------------------------------------------------------------------------------- 1 | query SponsorshipsAll { 2 | $account(login: "$login") { 3 | sponsorshipsAsSponsor($after first: 100, activeOnly: false, orderBy: {field: CREATED_AT, direction: DESC}) { 4 | edges { 5 | cursor 6 | } 7 | nodes { 8 | createdAt 9 | isActive 10 | isOneTimePayment 11 | tier { 12 | name 13 | } 14 | privacyLevel 15 | sponsorable { 16 | ... on User { 17 | avatarUrl(size: $size) 18 | login 19 | } 20 | ... on Organization { 21 | login 22 | avatarUrl(size: $size) 23 | url 24 | } 25 | } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /source/plugins/sponsorships/queries/sponsorships.graphql: -------------------------------------------------------------------------------- 1 | query SponsorshipsDefault { 2 | $account(login: "$login") { 3 | totalSponsorshipAmountAsSponsorInCents 4 | sponsorshipsAsSponsor(first: 1, activeOnly: false, orderBy: {field: CREATED_AT, direction: ASC}) { 5 | nodes { 6 | createdAt 7 | } 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /source/plugins/stackoverflow/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Top answers from stackoverflow 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.stackoverflow.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_stackoverflow: yes 8 | plugin_stackoverflow_user: 1 9 | plugin_stackoverflow_sections: answers-top 10 | plugin_stackoverflow_limit: 2 11 | -------------------------------------------------------------------------------- /source/plugins/stargazers/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Using classic charts 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.stargazers.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_stargazers: yes 8 | 9 | - name: Using graph charts 10 | uses: lowlighter/metrics@latest 11 | with: 12 | filename: metrics.plugin.stargazers.graph.svg 13 | token: ${{ secrets.METRICS_TOKEN }} 14 | base: "" 15 | plugin_stargazers: yes 16 | plugin_stargazers_charts_type: graph 17 | 18 | - name: With worldmap 19 | uses: lowlighter/metrics@latest 20 | with: 21 | filename: metrics.plugin.stargazers.worldmap.svg 22 | token: ${{ secrets.METRICS_TOKEN }} 23 | base: "" 24 | plugin_stargazers: yes 25 | plugin_stargazers_charts: no 26 | plugin_stargazers_worldmap: yes 27 | plugin_stargazers_worldmap_token: ${{ secrets.GOOGLE_MAP_TOKEN }} 28 | plugin_stargazers_worldmap_sample: 200 -------------------------------------------------------------------------------- /source/plugins/stargazers/queries/stargazers.graphql: -------------------------------------------------------------------------------- 1 | query StargazersDefault { 2 | repository(name: "$repository", owner: "$login") { 3 | stargazers($after first: 100, orderBy: {field: STARRED_AT, direction: ASC}) { 4 | edges { 5 | starredAt 6 | cursor 7 | $location 8 | } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /source/plugins/stargazers/worldmap/atlas/LICENSE.md: -------------------------------------------------------------------------------- 1 | See license at [npmjs.com/package/visionscarto-world-atlas](https://www.npmjs.com/package/visionscarto-world-atlas) -------------------------------------------------------------------------------- /source/plugins/starlists/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Featured star list 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.starlists.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_starlists: yes 8 | plugin_starlists_limit_repositories: 2 9 | plugin_starlists_only: TC39 10 | test: 11 | timeout: 1800000 12 | 13 | - name: Featured star list languages 14 | uses: lowlighter/metrics@latest 15 | with: 16 | filename: metrics.plugin.starlists.languages.svg 17 | token: NOT_NEEDED 18 | base: "" 19 | plugin_starlists: yes 20 | plugin_starlists_languages: yes 21 | plugin_starlists_limit_languages: 8 22 | plugin_starlists_limit_repositories: 0 23 | plugin_starlists_only: Awesome 24 | test: 25 | timeout: 1800000 26 | -------------------------------------------------------------------------------- /source/plugins/stars/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Recently starred 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.stars.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: "" 7 | plugin_stars: yes 8 | plugin_stars_limit: 3 9 | -------------------------------------------------------------------------------- /source/plugins/stars/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 🌟 Recently starred repositories 2 | category: github 3 | description: | 4 | This plugin displays recently starred repositories. 5 | examples: 6 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.stars.svg 7 | index: 5 8 | supports: 9 | - user 10 | scopes: 11 | - public_access 12 | inputs: 13 | 14 | plugin_stars: 15 | description: | 16 | Enable stars plugin 17 | type: boolean 18 | default: no 19 | 20 | plugin_stars_limit: 21 | description: | 22 | Display limit 23 | type: number 24 | default: 4 25 | min: 1 26 | max: 100 -------------------------------------------------------------------------------- /source/plugins/stars/queries/stars.graphql: -------------------------------------------------------------------------------- 1 | query StarsDefault { 2 | user(login: "$login") { 3 | starredRepositories(first: $limit, orderBy: {field: STARRED_AT, direction: DESC}) { 4 | edges { 5 | starredAt 6 | node { 7 | description 8 | forkCount 9 | isFork 10 | issues { 11 | totalCount 12 | } 13 | nameWithOwner 14 | openGraphImageUrl 15 | licenseInfo { 16 | nickname 17 | spdxId 18 | name 19 | } 20 | pullRequests { 21 | totalCount 22 | } 23 | stargazerCount 24 | primaryLanguage { 25 | color 26 | name 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /source/plugins/steam/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Recently played games 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.steam.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_steam_token: ${{ secrets.STEAM_TOKEN }} 8 | plugin_steam: yes 9 | plugin_steam_user: "0" 10 | plugin_steam_sections: recently-played 11 | plugin_steam_achievements_limit: 0 12 | prod: 13 | # ⚠️ Using mocked data for privacy reasons 14 | with: 15 | plugin_steam_token: MOCKED_TOKEN 16 | use_mocked_data: yes 17 | 18 | - name: Profile and detailed game history 19 | uses: lowlighter/metrics@latest 20 | with: 21 | filename: metrics.plugin.steam.full.svg 22 | token: NOT_NEEDED 23 | base: "" 24 | plugin_steam_token: ${{ secrets.STEAM_TOKEN }} 25 | plugin_steam: yes 26 | plugin_steam_user: "0" 27 | prod: 28 | # ⚠️ Using mocked data for privacy reasons 29 | with: 30 | plugin_steam_token: MOCKED_TOKEN 31 | use_mocked_data: yes -------------------------------------------------------------------------------- /source/plugins/support/examples.yml: -------------------------------------------------------------------------------- 1 | - name: GitHub Community Support 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.support.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_support: yes 8 | prod: 9 | skip: true 10 | test: 11 | skip: true -------------------------------------------------------------------------------- /source/plugins/support/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 💭 GitHub Community Support 2 | category: github 3 | description: | 4 | This plugin displays statistics from a [GitHub Support Community](https://github.community/) account. 5 | deprecation: | 6 | GitHub Support Community has been moved to [GitHub Discussions](https://github.blog/2022-07-26-launching-github-community-powered-by-github-discussions). 7 | examples: 8 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.support.svg 9 | supports: 10 | - user 11 | scopes: [] 12 | inputs: 13 | 14 | plugin_support: 15 | description: | 16 | Enable support plugin 17 | type: boolean 18 | default: no 19 | extras: 20 | - metrics.run.puppeteer.scrapping -------------------------------------------------------------------------------- /source/plugins/topics/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Labels 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.topics.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_topics: yes 8 | plugin_topics_limit: 12 9 | 10 | - name: Icons 11 | uses: lowlighter/metrics@latest 12 | with: 13 | filename: metrics.plugin.topics.icons.svg 14 | token: NOT_NEEDED 15 | base: "" 16 | plugin_topics: yes 17 | plugin_topics_limit: 0 18 | plugin_topics_mode: icons 19 | -------------------------------------------------------------------------------- /source/plugins/traffic/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Repositories traffic 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.traffic.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: repositories 7 | plugin_traffic: yes 8 | prod: 9 | with: 10 | token: ${{ secrets.METRICS_TOKEN_WITH_SCOPES }} -------------------------------------------------------------------------------- /source/plugins/traffic/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 🧮 Repositories traffic 2 | category: github 3 | description: | 4 | This plugin displays the number of page views across affiliated repositories. 5 | examples: 6 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.plugin.traffic.svg 7 | index: 22 8 | supports: 9 | - user 10 | - organization 11 | - repository 12 | scopes: 13 | - repo 14 | inputs: 15 | 16 | plugin_traffic: 17 | description: | 18 | Enable traffic plugin 19 | type: boolean 20 | default: no 21 | 22 | plugin_traffic_skipped: 23 | description: | 24 | Skipped repositories 25 | type: array 26 | format: 27 | - newline-separated 28 | - comma-separated 29 | default: "" 30 | example: my-repo-1, my-repo-2, owner/repo-3, ... 31 | inherits: repositories_skipped 32 | -------------------------------------------------------------------------------- /source/plugins/tweets/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Latest tweets 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.tweets.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_tweets: yes 8 | plugin_tweets_token: ${{ secrets.TWITTER_TOKEN }} 9 | plugin_tweets_user: github 10 | prod: 11 | skip: true 12 | test: 13 | skip: true 14 | 15 | - name: Latest tweets including attachments 16 | uses: lowlighter/metrics@latest 17 | with: 18 | filename: metrics.plugin.tweets.attachments.svg 19 | token: NOT_NEEDED 20 | base: "" 21 | plugin_tweets: yes 22 | plugin_tweets_token: ${{ secrets.TWITTER_TOKEN }} 23 | plugin_tweets_attachments: yes 24 | plugin_tweets_user: github 25 | plugin_tweets_limit: 1 26 | prod: 27 | skip: true 28 | test: 29 | skip: true 30 | -------------------------------------------------------------------------------- /source/plugins/wakatime/examples.yml: -------------------------------------------------------------------------------- 1 | - name: WakaTime 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.plugin.wakatime.svg 5 | token: NOT_NEEDED 6 | base: "" 7 | plugin_wakatime: yes 8 | plugin_wakatime_sections: time, projects, projects-graphs, languages, languages-graphs, editors, os 9 | plugin_wakatime_token: ${{ secrets.WAKATIME_TOKEN }} 10 | prod: 11 | # ⚠️ Using mocked data because I don't really use WakaTime 12 | with: 13 | plugin_wakatime_token: MOCKED_TOKEN 14 | use_mocked_data: yes -------------------------------------------------------------------------------- /source/templates/README.md: -------------------------------------------------------------------------------- 1 | ## 🖼️ Templates 2 | 3 | Templates lets you change general appearance of rendered metrics. 4 | 5 | 6 | * [📗 Classic template `classic`](/source/templates/classic/README.md) 7 | * [📘 Repository template `repository`](/source/templates/repository/README.md) 8 | * [📙 Terminal template `terminal`](/source/templates/terminal/README.md) 9 | * [📒 Markdown template `markdown`](/source/templates/markdown/README.md) 10 | * [📕 Community templates `community`](/source/templates/community/README.md) 11 | -------------------------------------------------------------------------------- /source/templates/classic/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Example 2 | uses: lowlighter/metrics@latest 3 | with: 4 | filename: metrics.classic.svg 5 | token: ${{ secrets.METRICS_TOKEN }} 6 | base: header, repositories 7 | plugin_lines: yes 8 | -------------------------------------------------------------------------------- /source/templates/classic/fonts.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowlighter/metrics/366f8b9dfe3a59656c67d5dcad9950f59c9bc96d/source/templates/classic/fonts.css -------------------------------------------------------------------------------- /source/templates/classic/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 📗 Classic template 2 | description: | 3 | A template mimicking GitHub visual identity. 4 | This is also the default template. 5 | examples: 6 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.classic.svg 7 | index: 0 8 | supports: 9 | - user 10 | - organization 11 | formats: 12 | - svg 13 | - png 14 | - jpeg 15 | - json 16 | -------------------------------------------------------------------------------- /source/templates/classic/partials/_.json: -------------------------------------------------------------------------------- 1 | [ 2 | "base.header", 3 | "introduction", 4 | "base.activity+community", 5 | "base.repositories", 6 | "lines", 7 | "followup", 8 | "discussions", 9 | "languages", 10 | "notable", 11 | "projects", 12 | "repositories", 13 | "gists", 14 | "pagespeed", 15 | "habits", 16 | "topics", 17 | "music", 18 | "nightscout", 19 | "posts", 20 | "rss", 21 | "tweets", 22 | "isocalendar", 23 | "calendar", 24 | "stars", 25 | "starlists", 26 | "stargazers", 27 | "people", 28 | "activity", 29 | "reactions", 30 | "anilist", 31 | "wakatime", 32 | "skyline", 33 | "support", 34 | "stackoverflow", 35 | "leetcode", 36 | "crypto", 37 | "stock", 38 | "achievements", 39 | "screenshot", 40 | "code", 41 | "chess", 42 | "sponsors", 43 | "sponsorships", 44 | "poopmap", 45 | "16personalities", 46 | "fortune", 47 | "splatoon", 48 | "steam" 49 | ] 50 | -------------------------------------------------------------------------------- /source/templates/classic/partials/traffic.ejs: -------------------------------------------------------------------------------- 1 | <%# Included in base.repositories.ejs %> -------------------------------------------------------------------------------- /source/templates/classic/template.mjs: -------------------------------------------------------------------------------- 1 | /**Template processor */ 2 | export default async function(_, __, {imports}) { 3 | //Core 4 | await imports.plugins.core(...arguments) 5 | } 6 | -------------------------------------------------------------------------------- /source/templates/community/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Using a community template 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: ${{ secrets.METRICS_TOKEN }} 5 | template: "@classic" 6 | setup_community_templates: "lowlighter/metrics@master:classic" 7 | test: 8 | modes: 9 | - action 10 | 11 | - name: Using a trusted community template 12 | uses: lowlighter/metrics@latest 13 | with: 14 | token: ${{ secrets.METRICS_TOKEN }} 15 | template: "@terminal" 16 | setup_community_templates: "lowlighter/metrics@master:terminal+trust" 17 | test: 18 | modes: 19 | - action 20 | -------------------------------------------------------------------------------- /source/templates/community/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 📕 Community templates 2 | description: | 3 | A template mimicking GitHub visual identity. 4 | This is also the default template. 5 | -------------------------------------------------------------------------------- /source/templates/markdown/example.pdf.md: -------------------------------------------------------------------------------- 1 | # 📒 Markdown template example (pdf) 2 | 3 | See [rendering of this file here](https://github.com/lowlighter/metrics/blob/examples/metrics.markdown.pdf) and [original template source here](https://github.com/lowlighter/metrics/blob/master/source/templates/markdown/example.pdf.md). 4 | 5 | ## 🧩 Plugins 6 | 7 | All markdown features are supported, meaning that both markdown plugins and SVG renders can be used. 8 | 9 | <%- await include(`partials/rss.ejs`) %> 10 | 11 | <%- await embed(`example-isocalendar-pdf`, {isocalendar:true}) %> 12 | -------------------------------------------------------------------------------- /source/templates/markdown/image.svg: -------------------------------------------------------------------------------- 1 | You did not provide a valid "markdown" query parameter, which is required to use this template. -------------------------------------------------------------------------------- /source/templates/markdown/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 📒 Markdown template 2 | description: | 3 | A template capable of rendering markdown from a given template file. 4 | examples: 5 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.markdown.png 6 | index: 3 7 | supports: 8 | - user 9 | - organization 10 | - repository 11 | formats: 12 | - markdown 13 | - markdown-pdf 14 | - json 15 | -------------------------------------------------------------------------------- /source/templates/markdown/partials/_.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /source/templates/markdown/partials/posts.ejs: -------------------------------------------------------------------------------- 1 | <%_ if (plugins.posts) { _%> 2 | **[✒️ Recent posts from <%= plugins.posts?.source %>](<%= plugins.posts?.link %>)** 3 | <%_ if (plugins.posts.error) { _%> 4 | <%= plugins.posts.error.message _%> 5 | <%_ } else if ((plugins.posts.list.length)&&(plugins.posts.descriptions)||(plugins.posts.covers)) { _%> 6 | <%_ for (const {title, date, link, description = "", image} of plugins.posts.list) { _%> 7 | 8 | 9 | <%_ if (plugins.posts.covers) { _%> 10 | 13 | <%_ } _%> 14 | 17 | 18 | 19 | 24 | 25 |
11 | 12 | 15 | <%= title.trim() %> 16 |
20 | <%= description %> 21 |
22 | Published on <%= f.date(new Date(date), {date:true, timeZone:config.timezone?.name}) %> 23 |
26 | <%_ } _%> 27 | <%_ } else if (plugins.posts.list.length) { _%> 28 | <%_ for (const {title, date, link} of plugins.posts.list) { _%> 29 | * [<%= title.trim() %>](<%= link %>) 30 | * *Published on <%= f.date(new Date(date), {date:true, timeZone:config.timezone?.name}) %>* 31 | <%_ } _%> 32 | <%_ } else { _%> 33 | No recent posts 34 | <%_ } _%> 35 | <%_ } _%> 36 | -------------------------------------------------------------------------------- /source/templates/markdown/partials/rss.ejs: -------------------------------------------------------------------------------- 1 | <%_ if (plugins.rss) { _%> 2 | **[🗼 Rss feed from <%= plugins.rss?.source %>](<%= plugins.rss?.link %>)** 3 | <%_ if (plugins.rss.error) { _%> 4 | <%= plugins.rss.error.message _%> 5 | <%_ } else if (plugins.rss.feed.length) { _%> 6 | <%_ for (const {title, link, date} of plugins.rss.feed) { _%> 7 | * [<%= title %>](<%= link %>) 8 | * *Published on <%= f.date(new Date(date), {date:true}) %>* 9 | <%_ } _%> 10 | <%_ } else { _%> 11 | Empty RSS feed 12 | <%_ } _%> 13 | <%_ } _%> 14 | -------------------------------------------------------------------------------- /source/templates/markdown/partials/topics.ejs: -------------------------------------------------------------------------------- 1 | <%_ if (plugins.topics) { _%> 2 | **[📌 <%= {starred:"Starred topics", mastered:"Mastered technologies and topics"}[plugins.topics.mode] %>](https://github.com/<%= user.login %>?tab=stars)** 3 | 4 | <%_ if (plugins.topics.error) { _%> 5 | <%= plugins.topics.error.message _%> 6 | <%_ } else if (plugins.topics.list.length) { _%> 7 | <%_ for (const {name, icon24} of plugins.topics.list.slice(0, plugins.topics.list.length-1)) { _%> 8 | [![](https://img.shields.io/static/v1?style=flat&label=&message=<%= encodeURIComponent(name) %>&color=222&logo=<%= icon24 %>)](https://github.com/topics/<%= name.toLocaleLowerCase().replace(/\+/g, "plus").replace(/#/g, "sharp").replace(/\./g, "").replace(/ /g, "-") %>) 9 | <%_ } _%> 10 | 11 | [<%= plugins.topics.list[plugins.topics.list.length-1].name %>](https://github.com/<%= user.login %>?tab=stars) 12 | <%_ } else { _%> 13 | No starred topics 14 | <%_ } _%> 15 | <%_ } _%> -------------------------------------------------------------------------------- /source/templates/markdown/partials/tweets.ejs: -------------------------------------------------------------------------------- 1 | <%_ if (plugins.tweets) { _%> 2 | **[🐤 Latest tweets from @<%= plugins.tweets.username %>](https://twitter.com/<%= plugins.tweets.username %>)** 3 | <%_ if (plugins.tweets.error) { _%> 4 | <%= plugins.tweets.error.message _%> 5 | <%_ } else if (plugins.tweets.list.length) { _%> 6 | <%_ for (const {text, createdAt, attachments} of plugins.tweets.list) { _%> 7 | > <%- text %> 8 | <%_ if (attachments) { _%> 9 | <%_ for (const {image, title, description, website} of attachments) { _%> 10 | > 11 | > <%= title %> 12 | <%_ } _%> 13 | <%_ } _%> 14 | > 15 | > *<%= createdAt %>* 16 | 17 | <%_ } _%> 18 | <%_ } else { _%> 19 | No recent tweets 20 | <%_ } _%> 21 | <%_ } _%> -------------------------------------------------------------------------------- /source/templates/repository/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Example 2 | uses: lowlighter/metrics@latest 3 | with: 4 | template: repository 5 | filename: metrics.repository.svg 6 | token: ${{ secrets.METRICS_TOKEN_WITH_SCOPES }} 7 | user: lowlighter 8 | repo: metrics 9 | plugin_lines: yes 10 | plugin_followup: yes 11 | plugin_projects: yes 12 | plugin_projects_repositories: lowlighter/metrics/projects/1 -------------------------------------------------------------------------------- /source/templates/repository/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 📘 Repository template 2 | description: | 3 | A template mimicking GitHub visual identity and specially crafted for repositories. 4 | examples: 5 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.repository.svg 6 | index: 1 7 | supports: 8 | - repository 9 | formats: 10 | - svg 11 | - png 12 | - jpeg 13 | - json 14 | -------------------------------------------------------------------------------- /source/templates/repository/partials/_.json: -------------------------------------------------------------------------------- 1 | [ 2 | "base.header", 3 | "introduction", 4 | "followup", 5 | "languages", 6 | "projects", 7 | "pagespeed", 8 | "stargazers", 9 | "people", 10 | "activity", 11 | "posts", 12 | "rss", 13 | "screenshot", 14 | "stock", 15 | "crypto", 16 | "contributors", 17 | "sponsors", 18 | "licenses" 19 | ] -------------------------------------------------------------------------------- /source/templates/repository/partials/lines.ejs: -------------------------------------------------------------------------------- 1 | <%# Included in base.repositories.ejs %> -------------------------------------------------------------------------------- /source/templates/repository/partials/traffic.ejs: -------------------------------------------------------------------------------- 1 | <%# Included in base.repositories.ejs %> -------------------------------------------------------------------------------- /source/templates/terminal/examples.yml: -------------------------------------------------------------------------------- 1 | - name: Example 2 | uses: lowlighter/metrics@latest 3 | with: 4 | template: terminal 5 | filename: metrics.terminal.svg 6 | token: ${{ secrets.METRICS_TOKEN }} 7 | base: header, metadata 8 | -------------------------------------------------------------------------------- /source/templates/terminal/metadata.yml: -------------------------------------------------------------------------------- 1 | name: 📙 Terminal template 2 | description: | 3 | A template mimicking a SSH session. 4 | examples: 5 | default: https://github.com/lowlighter/metrics/blob/examples/metrics.terminal.svg 6 | index: 2 7 | supports: 8 | - user 9 | - organization 10 | formats: 11 | - svg 12 | - png 13 | - jpeg 14 | - json 15 | -------------------------------------------------------------------------------- /source/templates/terminal/partials/_.json: -------------------------------------------------------------------------------- 1 | [ 2 | "base.header", 3 | "base.activity+community", 4 | "base.repositories", 5 | "gists", 6 | "languages", 7 | "pagespeed", 8 | "isocalendar", 9 | "screenshot" 10 | ] -------------------------------------------------------------------------------- /source/templates/terminal/partials/base.header.ejs: -------------------------------------------------------------------------------- 1 | <% if ((account === "user")&&(base.header)) { %> 2 |
<%- meta.$ %> whoami
<%# -%> 3 |
<%# -%> 4 | <%= user.name || user.login %> registered=<%= computed.registration.match(/^.+? [ymd]/)?.[0].replace(/ /g, "") %>, uid=<%= `${user.databaseId}`.substr(-4) %>, gid=<%= user.organizations.totalCount %> 5 | contributed to <%= user.repositoriesContributedTo.totalCount %> repositor<%= s(user.repositoriesContributedTo.totalCount, "y") %> <% for (const [x, {color}] of Object.entries(computed.calendar)) { -%>#<% } %> 6 | followed by <%= user.followers.totalCount %> user<%= s(user.followers.totalCount) %> 7 |
<% } else if ((account === "organization")&&(base.header)) { %><%# -%> 8 |
<%- meta.$ %> whoami
<%# -%> 9 |
<%# -%> 10 | <%= user.name || user.login %> registered=<%= computed.registration.match(/^.+? [ymd]/)?.[0].replace(/ /g, "") %>, uid=0, gid=<%= `${user.databaseId}`.substr(-4) %> 11 | organization with <%= user.membersWithRole.totalCount %> member<%= s(user.membersWithRole.totalCount) %> 12 |
<% } -%> -------------------------------------------------------------------------------- /source/templates/terminal/partials/gists.ejs: -------------------------------------------------------------------------------- 1 | <% if (plugins.gists) { %> 2 |
<%- meta.$ %> ls -lh github/gists
<%# -%> 3 |
<%# -%> 4 | Total <%= plugins.gists.totalCount %> gist<%= s(plugins.gists.totalCount) %> 5 | -r-- <%= `${plugins.gists.stargazers}`.padStart(5) %> stargazer<%= s(plugins.gists.stargazers) %> 6 | -r-- <%= `${plugins.gists.forks}`.padStart(5) %> fork<%= s(plugins.gists.forks) %> 7 |
<% } -%> -------------------------------------------------------------------------------- /source/templates/terminal/partials/isocalendar.ejs: -------------------------------------------------------------------------------- 1 | <% if (plugins.isocalendar) { %> 2 |
<%- meta.$ %> ncal -MB<%= {"half-year":5, "full-year":11}[plugins.isocalendar.duration] %>
<%# -%> 3 |
<%# -%>
<%- plugins.isocalendar.svg %>
4 | <%= `${plugins.isocalendar.streak.current}`.padStart(5) %> consecutive day<%= s(plugins.isocalendar.streak.current) %> with commits 5 | <%= `~${plugins.isocalendar.average}`.padStart(5) %> commits per day in average 6 |
7 | <% } %> 8 | -------------------------------------------------------------------------------- /source/templates/terminal/partials/languages.ejs: -------------------------------------------------------------------------------- 1 | <% if (plugins.languages) { %> 2 |
<%- meta.$ %> locale
<%# -%> 3 |
<%# -%> 4 | <% if (plugins.languages.error) { -%> 5 | <%= plugins.languages.error.message %><%# -%> 6 | <% } else { for (const {name, value} of plugins.languages.favorites) { -%> 7 | <%= name.toLocaleUpperCase().padEnd(12) %> [<%= "#".repeat(Math.ceil(100*value/5)).padEnd(20) %>] <%= (100*value).toFixed(2).padEnd(5) %>% 8 | <% }} -%> 9 |
<% } -%> -------------------------------------------------------------------------------- /source/templates/terminal/partials/lines.ejs: -------------------------------------------------------------------------------- 1 | <%# Included in base.repositories.ejs %> -------------------------------------------------------------------------------- /source/templates/terminal/partials/screenshot.ejs: -------------------------------------------------------------------------------- 1 | <% if (plugins.screenshot) { %> 2 |
<%- meta.$ %> wget <%= plugins.screenshot.url %>
<%# -%> 3 |
<%# -%>
4 | <% } %> 5 | -------------------------------------------------------------------------------- /source/templates/terminal/partials/traffic.ejs: -------------------------------------------------------------------------------- 1 | <%# Included in base.repositories.ejs %> -------------------------------------------------------------------------------- /source/templates/terminal/template.mjs: -------------------------------------------------------------------------------- 1 | /**Template processor */ 2 | export default async function({q}, _, {imports}) { 3 | //Core 4 | await imports.plugins.core(...arguments) 5 | //Disable optimization to keep white-spaces 6 | q.raw = true 7 | } 8 | -------------------------------------------------------------------------------- /tests/cases/16personalities.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🧠 16personalities - MBTI Personality profile 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_16personalities: 'yes' 6 | plugin_16personalities_url: https://www.16personalities.com/profiles/b7d9f29453ea5 7 | plugin_16personalities_sections: personality, traits 8 | plugin_16personalities_scores: 'no' 9 | use_mocked_data: 'yes' 10 | verify: 'yes' 11 | -------------------------------------------------------------------------------- /tests/cases/achievements.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🏆 Achievements - Detailed display 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_achievements: 'yes' 6 | plugin_achievements_only: sponsor, maintainer, octonaut 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | timeout: 1800000 10 | - name: 🏆 Achievements - Compact display 11 | uses: lowlighter/metrics@latest 12 | with: 13 | token: MOCKED_TOKEN 14 | plugin_achievements: 'yes' 15 | plugin_achievements_only: >- 16 | polyglot, stargazer, sponsor, deployer, member, maintainer, developer, 17 | scripter, packager, explorer, infographile, manager 18 | plugin_achievements_display: compact 19 | plugin_achievements_threshold: X 20 | use_mocked_data: 'yes' 21 | verify: 'yes' 22 | timeout: 1800000 23 | -------------------------------------------------------------------------------- /tests/cases/activity.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 📰 Recent activity - Recent activity 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_activity: 'yes' 6 | plugin_activity_limit: 5 7 | plugin_activity_days: 0 8 | plugin_activity_filter: issue, pr, release, fork, review, ref/create 9 | use_mocked_data: 'yes' 10 | verify: 'yes' 11 | -------------------------------------------------------------------------------- /tests/cases/anilist.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: >- 2 | 🌸 Anilist watch list and reading list - Favorites anime and currently 3 | watching 4 | uses: lowlighter/metrics@latest 5 | with: 6 | token: NOT_NEEDED 7 | plugin_anilist: 'yes' 8 | plugin_anilist_medias: anime 9 | plugin_anilist_sections: favorites, watching 10 | plugin_anilist_limit: 1 11 | use_mocked_data: 'yes' 12 | verify: 'yes' 13 | - name: >- 14 | 🌸 Anilist watch list and reading list - Favorites manga and currently 15 | reading 16 | uses: lowlighter/metrics@latest 17 | with: 18 | token: NOT_NEEDED 19 | plugin_anilist: 'yes' 20 | plugin_anilist_medias: manga 21 | plugin_anilist_sections: favorites, reading 22 | plugin_anilist_limit: 1 23 | use_mocked_data: 'yes' 24 | verify: 'yes' 25 | - name: 🌸 Anilist watch list and reading list - Favorites characters 26 | uses: lowlighter/metrics@latest 27 | with: 28 | token: NOT_NEEDED 29 | plugin_anilist: 'yes' 30 | plugin_anilist_sections: characters 31 | plugin_anilist_limit_characters: 22 32 | use_mocked_data: 'yes' 33 | verify: 'yes' 34 | -------------------------------------------------------------------------------- /tests/cases/base.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🗃️ Base content - Default metrics 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | base: header, activity, community, repositories, metadata 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | -------------------------------------------------------------------------------- /tests/cases/calendar.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 📆 Commit calendar - Current year calendar 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_calendar: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | - name: 📆 Commit calendar - Full history calendar 9 | uses: lowlighter/metrics@latest 10 | with: 11 | token: MOCKED_TOKEN 12 | plugin_calendar: 'yes' 13 | plugin_calendar_limit: 0 14 | use_mocked_data: 'yes' 15 | verify: 'yes' 16 | -------------------------------------------------------------------------------- /tests/cases/chess.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: ♟️ Chess - Last chess game from lichess.org 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_chess: 'yes' 6 | plugin_chess_token: MOCKED_TOKEN 7 | plugin_chess_platform: lichess.org 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | -------------------------------------------------------------------------------- /tests/cases/classic.template.yml: -------------------------------------------------------------------------------- 1 | - name: 📗 Classic template - Example 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | base: header, repositories 6 | plugin_lines: yes 7 | use_mocked_data: yes 8 | verify: yes 9 | -------------------------------------------------------------------------------- /tests/cases/code.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: ♐ Random code snippet - JavaScript or TypeScript snippet of the day 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_code: 'yes' 6 | plugin_code_languages: javascript, typescript 7 | plugin_code_load: 400 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | -------------------------------------------------------------------------------- /tests/cases/community.template.yml: -------------------------------------------------------------------------------- 1 | - name: 📕 Community templates - Using a community template 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | template: "@classic" 6 | setup_community_templates: lowlighter/metrics@master:classic 7 | use_mocked_data: yes 8 | verify: yes 9 | modes: 10 | - action 11 | - name: 📕 Community templates - Using a trusted community template 12 | uses: lowlighter/metrics@latest 13 | with: 14 | token: MOCKED_TOKEN 15 | template: "@terminal" 16 | setup_community_templates: lowlighter/metrics@master:terminal+trust 17 | use_mocked_data: yes 18 | verify: yes 19 | modes: 20 | - action 21 | -------------------------------------------------------------------------------- /tests/cases/contributors.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🏅 Repository contributors - Contributors with contributions count 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | template: repository 6 | repo: metrics 7 | plugin_contributors: 'yes' 8 | plugin_contributors_contributions: 'yes' 9 | use_mocked_data: 'yes' 10 | verify: 'yes' 11 | - name: 🏅 Repository contributors - Contributors by categories 12 | uses: lowlighter/metrics@latest 13 | with: 14 | token: MOCKED_TOKEN 15 | template: repository 16 | repo: metrics 17 | plugin_contributors: 'yes' 18 | plugin_contributors_sections: categories 19 | plugin_contributors_categories: | 20 | { 21 | "🧩 Plugins / 🖼️ templates":["source/plugins/**", "source/templates/**"], 22 | "📚 Documentation":["README.md", "**/README.md", "**/metadata.yml"], 23 | "💻 Code (other)":["source/**", "Dockerfile"] 24 | } 25 | use_mocked_data: 'yes' 26 | verify: 'yes' 27 | -------------------------------------------------------------------------------- /tests/cases/crypto.plugin.yml: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /tests/cases/discussions.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 💬 Discussions - GitHub Discussions 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_discussions: 'yes' 6 | plugin_discussions_categories_limit: 8 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | -------------------------------------------------------------------------------- /tests/cases/followup.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🎟️ Follow-up of issues and pull requests - Opened on user's repositories 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_followup: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | - name: 🎟️ Follow-up of issues and pull requests - Opened by user 9 | uses: lowlighter/metrics@latest 10 | with: 11 | token: MOCKED_TOKEN 12 | plugin_followup: 'yes' 13 | plugin_followup_sections: user 14 | use_mocked_data: 'yes' 15 | verify: 'yes' 16 | - name: 🎟️ Follow-up of issues and pull requests - Indepth analysis 17 | uses: lowlighter/metrics@latest 18 | with: 19 | token: MOCKED_TOKEN 20 | plugin_followup: 'yes' 21 | plugin_followup_indepth: 'yes' 22 | use_mocked_data: 'yes' 23 | verify: 'yes' 24 | - name: 🎟️ Follow-up of issues and pull requests - Exclude Archived 25 | uses: lowlighter/metrics@latest 26 | with: 27 | token: MOCKED_TOKEN 28 | plugin_followup: 'yes' 29 | plugin_followup_archived: 'no' 30 | use_mocked_data: 'yes' 31 | verify: 'yes' 32 | -------------------------------------------------------------------------------- /tests/cases/fortune.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🥠 Fortune - Fortune 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_fortune: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | -------------------------------------------------------------------------------- /tests/cases/gists.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🎫 Gists - Gists 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_gists: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | -------------------------------------------------------------------------------- /tests/cases/habits.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 💡 Coding habits and activity - Mildly interesting facts 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_habits: 'yes' 6 | plugin_habits_facts: 'yes' 7 | plugin_habits_charts: 'no' 8 | config_timezone: Europe/Paris 9 | use_mocked_data: 'yes' 10 | verify: 'yes' 11 | - name: 💡 Coding habits and activity - Recent activity charts 12 | uses: lowlighter/metrics@latest 13 | with: 14 | token: MOCKED_TOKEN 15 | plugin_habits: 'yes' 16 | plugin_habits_facts: 'no' 17 | plugin_habits_charts: 'yes' 18 | config_timezone: Europe/Paris 19 | use_mocked_data: 'yes' 20 | verify: 'yes' 21 | -------------------------------------------------------------------------------- /tests/cases/introduction.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🙋 Introduction - Organization introduction 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | user: github 6 | base: header 7 | plugin_introduction: 'yes' 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | - name: 🙋 Introduction - Repository introduction 11 | uses: lowlighter/metrics@latest 12 | with: 13 | token: MOCKED_TOKEN 14 | template: repository 15 | repo: metrics 16 | base: header 17 | plugin_introduction: 'yes' 18 | use_mocked_data: 'yes' 19 | verify: 'yes' 20 | -------------------------------------------------------------------------------- /tests/cases/isocalendar.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 📅 Isometric commit calendar - Half-year calendar 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_isocalendar: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | - name: 📅 Isometric commit calendar - Full-year calendar 9 | uses: lowlighter/metrics@latest 10 | with: 11 | token: MOCKED_TOKEN 12 | plugin_isocalendar: 'yes' 13 | plugin_isocalendar_duration: full-year 14 | use_mocked_data: 'yes' 15 | verify: 'yes' 16 | -------------------------------------------------------------------------------- /tests/cases/leetcode.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🗳️ Leetcode - LeetCode 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_leetcode: 'yes' 6 | plugin_leetcode_sections: solved, skills, recent 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | -------------------------------------------------------------------------------- /tests/cases/licenses.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 📜 Repository licenses - Licenses and permissions 2 | with: 3 | token: MOCKED_TOKEN 4 | template: repository 5 | repo: metrics 6 | plugin_licenses: 'yes' 7 | plugin_licenses_setup: bash -c '[[ -f package.json ]] && npm ci || true' 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | timeout: 1800000 11 | modes: 12 | - action 13 | -------------------------------------------------------------------------------- /tests/cases/lines.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 👨‍💻 Lines of code changed - Compact display in base plugin 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | base: repositories 6 | plugin_lines: 'yes' 7 | plugin_lines_delay: 30 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | - name: 👨‍💻 Lines of code changed - Repositories and diff history 11 | uses: lowlighter/metrics@latest 12 | with: 13 | token: MOCKED_TOKEN 14 | plugin_lines: 'yes' 15 | plugin_lines_delay: 30 16 | plugin_lines_sections: repositories, history 17 | plugin_lines_repositories_limit: 2 18 | plugin_lines_history_limit: 1 19 | repositories_skipped: | 20 | @use.patterns 21 | */* 22 | +lowlighter/metrics 23 | use_mocked_data: 'yes' 24 | verify: 'yes' 25 | -------------------------------------------------------------------------------- /tests/cases/nightscout.plugin.yml: -------------------------------------------------------------------------------- 1 | - uses: lowlighter/metrics@latest 2 | with: 3 | token: NOT_NEEDED 4 | plugin_nightscout: 'yes' 5 | plugin_nightscout_url: https://testapp.herokuapp.com/ 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | name: 💉 Nightscout - (unnamed) 9 | -------------------------------------------------------------------------------- /tests/cases/notable.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🎩 Notable contributions - Contributions 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_notable: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | - name: 🎩 Notable contributions - Indepth analysis 9 | uses: lowlighter/metrics@latest 10 | with: 11 | token: MOCKED_TOKEN 12 | plugin_notable: 'yes' 13 | plugin_notable_indepth: 'yes' 14 | plugin_notable_repositories: 'yes' 15 | use_mocked_data: 'yes' 16 | verify: 'yes' 17 | -------------------------------------------------------------------------------- /tests/cases/people.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🧑‍🤝‍🧑 People - Followers 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_people: 'yes' 6 | plugin_people_types: followers 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | - name: 🧑‍🤝‍🧑 People - Contributors and sponsors 10 | uses: lowlighter/metrics@latest 11 | with: 12 | token: MOCKED_TOKEN 13 | template: repository 14 | repo: metrics 15 | plugin_people: 'yes' 16 | plugin_people_types: contributors, stargazers, watchers, sponsors 17 | use_mocked_data: 'yes' 18 | verify: 'yes' 19 | -------------------------------------------------------------------------------- /tests/cases/poopmap.plugin.yml: -------------------------------------------------------------------------------- 1 | - uses: lowlighter/metrics@latest 2 | with: 3 | token: NOT_NEEDED 4 | plugin_poopmap_token: MOCKED_TOKEN 5 | plugin_poopmap: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | name: 💩 PoopMap plugin - (unnamed) 9 | -------------------------------------------------------------------------------- /tests/cases/posts.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: ✒️ Recent posts - Recent posts 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_posts: 'yes' 6 | plugin_posts_source: dev.to 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | - name: ✒️ Recent posts - Recent posts with descriptions and cover images 10 | uses: lowlighter/metrics@latest 11 | with: 12 | token: NOT_NEEDED 13 | plugin_posts: 'yes' 14 | plugin_posts_source: dev.to 15 | plugin_posts_limit: 2 16 | plugin_posts_descriptions: 'yes' 17 | plugin_posts_covers: 'yes' 18 | use_mocked_data: 'yes' 19 | verify: 'yes' 20 | -------------------------------------------------------------------------------- /tests/cases/projects.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🗂️ GitHub projects - Project from a repository 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_projects: 'yes' 6 | plugin_projects_repositories: lowlighter/metrics/projects/1 7 | plugin_projects_descriptions: 'yes' 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | -------------------------------------------------------------------------------- /tests/cases/reactions.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🎭 Comment reactions - Comment reactions 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_reactions: 'yes' 6 | plugin_reactions_limit: 100 7 | plugin_reactions_details: percentage 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | -------------------------------------------------------------------------------- /tests/cases/repositories.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 📓 Featured repositories - Featured repositories 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_repositories: 'yes' 6 | plugin_repositories_featured: lowlighter/metrics 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | - name: 📓 Featured repositories - Pinned repositories 10 | uses: lowlighter/metrics@latest 11 | with: 12 | token: MOCKED_TOKEN 13 | plugin_repositories: 'yes' 14 | plugin_repositories_pinned: 2 15 | use_mocked_data: 'yes' 16 | verify: 'yes' 17 | -------------------------------------------------------------------------------- /tests/cases/repository.template.yml: -------------------------------------------------------------------------------- 1 | - name: 📘 Repository template - Example 2 | uses: lowlighter/metrics@latest 3 | with: 4 | template: repository 5 | token: MOCKED_TOKEN 6 | user: lowlighter 7 | repo: metrics 8 | plugin_lines: yes 9 | plugin_followup: yes 10 | plugin_projects: yes 11 | plugin_projects_repositories: lowlighter/metrics/projects/1 12 | use_mocked_data: yes 13 | verify: yes 14 | -------------------------------------------------------------------------------- /tests/cases/rss.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🗼 Rss feed - News from hackernews 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_rss: 'yes' 6 | plugin_rss_source: https://news.ycombinator.com/rss 7 | plugin_rss_limit: 4 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | -------------------------------------------------------------------------------- /tests/cases/screenshot.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 📸 Website screenshot - XKCD of the day 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_screenshot: 'yes' 6 | plugin_screenshot_title: XKCD of the day 7 | plugin_screenshot_url: https://xkcd.com 8 | plugin_screenshot_selector: '#comic img' 9 | use_mocked_data: 'yes' 10 | verify: 'yes' 11 | timeout: 1800000 12 | modes: 13 | - action 14 | -------------------------------------------------------------------------------- /tests/cases/skyline.plugin.yml: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /tests/cases/splatoon.plugin.yml: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /tests/cases/sponsors.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 💕 GitHub Sponsors - Sponsors goal 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_sponsors: 'yes' 6 | plugin_sponsors_sections: goal, list 7 | plugin_sponsors_past: 'yes' 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | - name: 💕 GitHub Sponsors - Sponsors introduction 11 | uses: lowlighter/metrics@latest 12 | with: 13 | token: MOCKED_TOKEN 14 | plugin_sponsors: 'yes' 15 | use_mocked_data: 'yes' 16 | verify: 'yes' 17 | -------------------------------------------------------------------------------- /tests/cases/sponsorships.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 💝 GitHub Sponsorships - 💝 GitHub Sponsorships 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_sponsorships: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | -------------------------------------------------------------------------------- /tests/cases/stackoverflow.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🗨️ Stack Overflow - Top answers from stackoverflow 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_stackoverflow: 'yes' 6 | plugin_stackoverflow_user: 1 7 | plugin_stackoverflow_sections: answers-top 8 | plugin_stackoverflow_limit: 2 9 | use_mocked_data: 'yes' 10 | verify: 'yes' 11 | -------------------------------------------------------------------------------- /tests/cases/stargazers.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: ✨ Stargazers - Using classic charts 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_stargazers: 'yes' 6 | use_mocked_data: 'yes' 7 | verify: 'yes' 8 | - name: ✨ Stargazers - Using graph charts 9 | uses: lowlighter/metrics@latest 10 | with: 11 | token: MOCKED_TOKEN 12 | plugin_stargazers: 'yes' 13 | plugin_stargazers_charts_type: graph 14 | use_mocked_data: 'yes' 15 | verify: 'yes' 16 | - name: ✨ Stargazers - With worldmap 17 | uses: lowlighter/metrics@latest 18 | with: 19 | token: MOCKED_TOKEN 20 | plugin_stargazers: 'yes' 21 | plugin_stargazers_charts: 'no' 22 | plugin_stargazers_worldmap: 'yes' 23 | plugin_stargazers_worldmap_token: MOCKED_TOKEN 24 | plugin_stargazers_worldmap_sample: 200 25 | use_mocked_data: 'yes' 26 | verify: 'yes' 27 | -------------------------------------------------------------------------------- /tests/cases/starlists.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 💫 Star lists - Featured star list 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_starlists: 'yes' 6 | plugin_starlists_limit_repositories: 2 7 | plugin_starlists_only: TC39 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | timeout: 1800000 11 | - name: 💫 Star lists - Featured star list languages 12 | uses: lowlighter/metrics@latest 13 | with: 14 | token: NOT_NEEDED 15 | plugin_starlists: 'yes' 16 | plugin_starlists_languages: 'yes' 17 | plugin_starlists_limit_languages: 8 18 | plugin_starlists_limit_repositories: 0 19 | plugin_starlists_only: Awesome 20 | use_mocked_data: 'yes' 21 | verify: 'yes' 22 | timeout: 1800000 23 | -------------------------------------------------------------------------------- /tests/cases/stars.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🌟 Recently starred repositories - Recently starred 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | plugin_stars: 'yes' 6 | plugin_stars_limit: 3 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | -------------------------------------------------------------------------------- /tests/cases/steam.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🕹️ Steam - Recently played games 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_steam_token: MOCKED_TOKEN 6 | plugin_steam: 'yes' 7 | plugin_steam_user: '0' 8 | plugin_steam_sections: recently-played 9 | plugin_steam_achievements_limit: 0 10 | use_mocked_data: 'yes' 11 | verify: 'yes' 12 | - name: 🕹️ Steam - Profile and detailed game history 13 | uses: lowlighter/metrics@latest 14 | with: 15 | token: NOT_NEEDED 16 | plugin_steam_token: MOCKED_TOKEN 17 | plugin_steam: 'yes' 18 | plugin_steam_user: '0' 19 | use_mocked_data: 'yes' 20 | verify: 'yes' 21 | -------------------------------------------------------------------------------- /tests/cases/stock.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 💹 Stock prices - Stock prices from Tesla 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_stock: 'yes' 6 | plugin_stock_token: MOCKED_TOKEN 7 | plugin_stock_symbol: TSLA 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | -------------------------------------------------------------------------------- /tests/cases/support.plugin.yml: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /tests/cases/terminal.template.yml: -------------------------------------------------------------------------------- 1 | - name: 📙 Terminal template - Example 2 | uses: lowlighter/metrics@latest 3 | with: 4 | template: terminal 5 | token: MOCKED_TOKEN 6 | base: header, metadata 7 | use_mocked_data: yes 8 | verify: yes 9 | -------------------------------------------------------------------------------- /tests/cases/topics.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 📌 Starred topics - Labels 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_topics: 'yes' 6 | plugin_topics_limit: 12 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | - name: 📌 Starred topics - Icons 10 | uses: lowlighter/metrics@latest 11 | with: 12 | token: NOT_NEEDED 13 | plugin_topics: 'yes' 14 | plugin_topics_limit: 0 15 | plugin_topics_mode: icons 16 | use_mocked_data: 'yes' 17 | verify: 'yes' 18 | -------------------------------------------------------------------------------- /tests/cases/traffic.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: 🧮 Repositories traffic - Repositories traffic 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: MOCKED_TOKEN 5 | base: repositories 6 | plugin_traffic: 'yes' 7 | use_mocked_data: 'yes' 8 | verify: 'yes' 9 | -------------------------------------------------------------------------------- /tests/cases/tweets.plugin.yml: -------------------------------------------------------------------------------- 1 | [] 2 | -------------------------------------------------------------------------------- /tests/cases/wakatime.plugin.yml: -------------------------------------------------------------------------------- 1 | - name: ⏰ WakaTime - WakaTime 2 | uses: lowlighter/metrics@latest 3 | with: 4 | token: NOT_NEEDED 5 | plugin_wakatime: 'yes' 6 | plugin_wakatime_sections: time, projects, projects-graphs, languages, languages-graphs, editors, os 7 | plugin_wakatime_token: MOCKED_TOKEN 8 | use_mocked_data: 'yes' 9 | verify: 'yes' 10 | -------------------------------------------------------------------------------- /tests/mocks/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | # Overrides enforced rules for mocks 2 | rules: 3 | max-params: off 4 | no-unused-vars: off -------------------------------------------------------------------------------- /tests/mocks/api/axios/get/lichess.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, url, options, login = faker.internet.userName()}) { 3 | //Wakatime api 4 | if (/^https:..lichess.org.api.games.user.*$/.test(url)) { 5 | console.debug(`metrics/compute/mocks > mocking lichess api result > ${url}`) 6 | return ({ 7 | status: 200, 8 | data: ` 9 | [Event "It (cat.17)"] 10 | [Site "Wijk aan Zee (Netherlands)"] 11 | [Date "1999.??.??"] 12 | [Round "?"] 13 | [White "Garry Kasparov"] 14 | [Black "Veselin Topalov"] 15 | [Result "1-0"] 16 | 17 | 1. e4 d6 2. d4 Nf6 3. Nc3 g6 4. Be3 Bg7 5. Qd2 c6 6. f3 b5 7. Nge2 Nbd7 8. Bh6 18 | Bxh6 9. Qxh6 Bb7 10. a3 e5 11. O-O-O Qe7 12. Kb1 a6 13. Nc1 O-O-O 14. Nb3 exd4 19 | 15. Rxd4 c5 16. Rd1 Nb6 17. g3 Kb8 18. Na5 Ba8 19. Bh3 d5 20. Qf4+ Ka7 21. Rhe1 20 | d4 22. Nd5 Nbxd5 23. exd5 Qd6 24. Rxd4 cxd4 25. Re7+ Kb6 26. Qxd4+ Kxa5 27. b4+ 21 | Ka4 28. Qc3 Qxd5 29. Ra7 Bb7 30. Rxb7 Qc4 31. Qxf6 Kxa3 32. Qxa6+ Kxb4 33. c3+ 22 | Kxc3 34. Qa1+ Kd2 35. Qb2+ Kd1 36. Bf1 Rd2 37. Rd7 Rxd7 38. Bxc4 bxc4 39. Qxh8 23 | Rd3 40. Qa8 c3 41. Qa4+ Ke1 42. f4 f5 43. Kc1 Rd2 44. Qa7 1-0`.trim(), 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/mocks/api/axios/get/nightscout.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, url}) { 3 | //Last.fm api 4 | if (/^https:..testapp.herokuapp.com.*$/.test(url)) { 5 | //Get Nightscout Data 6 | console.debug(`metrics/compute/mocks > mocking nightscout api result > ${url}`) 7 | const lastInterval = Math.floor(new Date() / 300000) * 300000 8 | return ({ 9 | status: 200, 10 | data: new Array(12).fill(null).map(_ => ({ 11 | _id: faker.git.commitSha().substring(0, 23), 12 | device: "xDrip-DexcomG5", 13 | date: lastInterval, 14 | dateString: new Date(lastInterval).toISOString(), 15 | sgv: faker.number.int({min: 40, max: 400}), 16 | delta: faker.number.int({min: -10, max: 10}), 17 | direction: faker.helpers.arrayElement(["SingleUp", "DoubleUp", "FortyFiveUp", "Flat", "FortyFiveDown", "SingleDown", "DoubleDown"]), 18 | type: "sgv", 19 | filtered: 0, 20 | unfiltered: 0, 21 | rssi: 100, 22 | noise: 1, 23 | sysTime: new Date(lastInterval).toISOString(), 24 | utcOffset: faker.number.int({min: -12, max: 14}) * 60, 25 | })), 26 | }) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/mocks/api/axios/get/poopmap.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, url, options, login = faker.internet.userName()}) { 3 | //Wakatime api 4 | if (/^https:..api.poopmap.net.*$/.test(url)) { 5 | //Get user profile 6 | if (/public_links\/MOCKED_TOKEN/.test(url)) { 7 | console.debug(`metrics/compute/mocks > mocking poopmap api result > ${url}`) 8 | return ({ 9 | status: 200, 10 | data: { 11 | poops: new Array(12 + faker.number.int(6)).fill(null).map(_ => ({ 12 | id: 79744699, 13 | latitude: faker.location.latitude(), 14 | longitude: faker.location.longitude(), 15 | created_at: faker.date.past().toISOString(), 16 | note: "", 17 | place: "", 18 | rating: faker.number.int(5), 19 | followers_count: faker.number.int(100), 20 | comments_count: faker.number.int(12), 21 | })), 22 | }, 23 | }) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/mocks/api/axios/post/hashnode.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, url, body, login = faker.internet.userName()}) { 3 | if (/^https:..api.hashnode.com.*$/.test(url)) { 4 | console.debug(`metrics/compute/mocks > mocking hashnode result > ${url}`) 5 | return ({ 6 | status: 200, 7 | data: { 8 | data: { 9 | user: { 10 | publication: { 11 | posts: new Array(30).fill(null).map(_ => ({ 12 | title: faker.lorem.sentence(), 13 | brief: faker.lorem.paragraph(), 14 | coverImage: null, 15 | dateAdded: faker.date.recent(), 16 | })), 17 | }, 18 | }, 19 | }, 20 | }, 21 | }) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/mocks/api/axios/post/spotify.mjs: -------------------------------------------------------------------------------- 1 | //Imports 2 | import urls from "url" 3 | 4 | /**Mocked data */ 5 | export default function({faker, url, body, login = faker.internet.userName()}) { 6 | if (/^https:..accounts.spotify.com.api.token.*$/.test(url)) { 7 | //Access token generator 8 | const params = new urls.URLSearchParams(body) 9 | if ((params.get("grant_type") === "refresh_token") && (params.get("client_id") === "MOCKED_CLIENT_ID") && (params.get("client_secret") === "MOCKED_CLIENT_SECRET") && (params.get("refresh_token") === "MOCKED_REFRESH_TOKEN")) { 10 | console.debug(`metrics/compute/mocks > mocking spotify api result > ${url}`) 11 | return ({ 12 | status: 200, 13 | data: { 14 | access_token: "MOCKED_TOKEN_ACCESS", 15 | token_type: "Bearer", 16 | expires_in: 3600, 17 | scope: "user-read-recently-played user-read-private", 18 | }, 19 | }) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/achievements.metrics.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > achievements/metrics") 4 | return ({ 5 | repository: {viewerHasStarred: faker.datatype.boolean()}, 6 | viewer: {login}, 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/achievements.octocat.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > achievements/octocat") 4 | return ({ 5 | user: {viewerIsFollowing: faker.datatype.boolean()}, 6 | viewer: {login}, 7 | }) 8 | } 9 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/achievements.organizations.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > achievements/organizations") 4 | return ({ 5 | organization: { 6 | repositories: { 7 | nodes: [ 8 | { 9 | createdAt: faker.date.recent(), 10 | nameWithOwner: `${faker.internet.userName()}/${faker.lorem.slug()}`, 11 | }, 12 | ], 13 | totalCount: faker.number.int(100), 14 | }, 15 | forks: { 16 | nodes: [ 17 | { 18 | createdAt: faker.date.recent(), 19 | nameWithOwner: `${faker.internet.userName()}/${faker.lorem.slug()}`, 20 | }, 21 | ], 22 | totalCount: faker.number.int(100), 23 | }, 24 | popular: { 25 | nodes: [{stargazers: {totalCount: faker.number.int(50000)}}], 26 | }, 27 | projects: {totalCount: faker.number.int(100)}, 28 | packages: {totalCount: faker.number.int(100)}, 29 | membersWithRole: {totalCount: faker.number.int(100)}, 30 | sponsorshipsAsSponsor: {totalCount: faker.number.int(100)}, 31 | }, 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/achievements.ranking.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > achievements/ranking") 4 | return ({ 5 | repo_rank: {repositoryCount: faker.number.int(100000)}, 6 | forks_rank: {repositoryCount: faker.number.int(100000)}, 7 | created_rank: {userCount: faker.number.int(100000)}, 8 | user_rank: {userCount: faker.number.int(100000)}, 9 | repo_total: {repositoryCount: faker.number.int(100000)}, 10 | user_total: {userCount: faker.number.int(100000)}, 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/achievements.total.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > achievements/total") 4 | return ({ 5 | repositories: {count: faker.number.int(100000)}, 6 | issues: {count: faker.number.int(100000)}, 7 | users: {count: faker.number.int(100000)}, 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/base.contributions.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > base/user") 4 | return ({ 5 | user: { 6 | contributionsCollection: { 7 | totalRepositoriesWithContributedCommits: faker.number.int(100), 8 | totalCommitContributions: faker.number.int(10000), 9 | restrictedContributionsCount: faker.number.int(10000), 10 | totalIssueContributions: faker.number.int(100), 11 | totalPullRequestContributions: faker.number.int(1000), 12 | totalPullRequestReviewContributions: faker.number.int(1000), 13 | }, 14 | }, 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/base.field.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > base/user") 4 | return ({ 5 | user: { 6 | packages: {totalCount: faker.number.int(10)}, 7 | starredRepositories: {totalCount: faker.number.int(1000)}, 8 | watching: {totalCount: faker.number.int(100)}, 9 | sponsorshipsAsSponsor: {totalCount: faker.number.int(10)}, 10 | sponsorshipsAsMaintainer: {totalCount: faker.number.int(10)}, 11 | repositoriesContributedTo: {totalCount: faker.number.int(100)}, 12 | followers: {totalCount: faker.number.int(1000)}, 13 | following: {totalCount: faker.number.int(1000)}, 14 | issueComments: {totalCount: faker.number.int(1000)}, 15 | organizations: {totalCount: faker.number.int(10)}, 16 | }, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/base.field.repositories.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > base/user") 4 | return ({ 5 | user: { 6 | repositories: {totalCount: faker.number.int(100), totalDiskUsage: faker.number.int(100000)}, 7 | }, 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/base.user.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > base/user") 4 | return ({ 5 | user: { 6 | databaseId: faker.number.int(10000000), 7 | name: faker.person.fullName(), 8 | login, 9 | createdAt: `${faker.date.past({years: 10})}`, 10 | avatarUrl: faker.image.urlLoremFlickr({category: "people"}), 11 | websiteUrl: faker.internet.url(), 12 | twitterUsername: login, 13 | }, 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/calendar.default.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > calendar/default") 4 | //Generate calendar 5 | const date = new Date(query.match(/from: "(?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z)"/)?.groups?.date) 6 | const to = new Date(query.match(/to: "(?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z)"/)?.groups?.date) 7 | const weeks = [] 8 | let contributionDays = [] 9 | for (; date <= to; date.setDate(date.getDate() + 1)) { 10 | //Create new week on sunday 11 | if (date.getDay() === 0) { 12 | weeks.push({contributionDays}) 13 | contributionDays = [] 14 | } 15 | //Random contributions 16 | const contributionCount = Math.min(10, Math.max(0, faker.number.int(14) - 4)) 17 | contributionDays.push({ 18 | contributionCount, 19 | color: ["#ebedf0", "#9be9a8", "#40c463", "#30a14e", "#216e39"][Math.ceil(contributionCount / 10 / 0.25)], 20 | date: date.toISOString().substring(0, 10), 21 | }) 22 | } 23 | return ({ 24 | user: { 25 | calendar: { 26 | contributionCalendar: { 27 | weeks, 28 | }, 29 | }, 30 | }, 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/contributors.commit.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > contributors/commit") 4 | return ({ 5 | repository: { 6 | object: { 7 | oid: "MOCKED_SHA", 8 | abbreviatedOid: "MOCKED_SHA", 9 | messageHeadline: faker.lorem.sentence(), 10 | committedDate: faker.date.recent(), 11 | }, 12 | }, 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/discussions.categories.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > discussions/categories") 4 | return /after: "MOCKED_CURSOR"/m.test(query) 5 | ? ({ 6 | user: { 7 | repositoryDiscussions: { 8 | edges: [], 9 | nodes: [], 10 | }, 11 | }, 12 | }) 13 | : ({ 14 | user: { 15 | repositoryDiscussions: { 16 | edges: new Array(100).fill(null).map(_ => ({cursor: "MOCKED_CURSOR"})), 17 | nodes: new Array(100).fill(null).map(_ => ({ 18 | category: { 19 | emoji: faker.helpers.arrayElement([":chart_with_upwards_trend:", ":chart_with_downwards_trend:", ":bar_char:"]), 20 | name: faker.lorem.slug(), 21 | }, 22 | })), 23 | }, 24 | }, 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/discussions.comments.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > discussions/comments") 4 | return /after: "MOCKED_CURSOR"/m.test(query) 5 | ? ({ 6 | user: { 7 | repositoryDiscussionsComments: { 8 | edges: [], 9 | nodes: [], 10 | }, 11 | }, 12 | }) 13 | : ({ 14 | user: { 15 | repositoryDiscussionsComments: { 16 | edges: new Array(100).fill(null).map(_ => ({cursor: "MOCKED_CURSOR"})), 17 | nodes: new Array(100).fill(null).map(_ => ({upvoteCount: faker.number.int(10)})), 18 | }, 19 | }, 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/discussions.statistics.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > discussions/statistics") 4 | return ({ 5 | user: { 6 | started: {totalCount: faker.number.int(1000)}, 7 | comments: {totalCount: faker.number.int(1000)}, 8 | answers: {totalCount: faker.number.int(1000)}, 9 | }, 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/followup.repository.collaborators.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > followup/repository/collaborators") 4 | return ({ 5 | repository: { 6 | collaborators: { 7 | nodes: ["github-user"], 8 | }, 9 | }, 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/followup.repository.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > followup/repository") 4 | return ({ 5 | issues_open: {issueCount: faker.number.int(100)}, 6 | issues_drafts: {issueCount: faker.number.int(100)}, 7 | issues_skipped: {issueCount: faker.number.int(100)}, 8 | issues_closed: {issueCount: faker.number.int(100)}, 9 | pr_open: {issueCount: faker.number.int(100)}, 10 | pr_drafts: {issueCount: faker.number.int(100)}, 11 | pr_closed: {issueCount: faker.number.int(100)}, 12 | pr_merged: {issueCount: faker.number.int(100)}, 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/followup.user.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > followup/user") 4 | return ({ 5 | issues_open: {issueCount: faker.number.int(100)}, 6 | issues_drafts: {issueCount: faker.number.int(100)}, 7 | issues_skipped: {issueCount: faker.number.int(100)}, 8 | issues_closed: {issueCount: faker.number.int(100)}, 9 | pr_open: {issueCount: faker.number.int(100)}, 10 | pr_drafts: {issueCount: faker.number.int(100)}, 11 | pr_closed: {issueCount: faker.number.int(100)}, 12 | pr_merged: {issueCount: faker.number.int(100)}, 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/introduction.organization.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > introduction/organization") 4 | return ({ 5 | organization: { 6 | description: faker.lorem.sentences(), 7 | }, 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/introduction.repository.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > introduction/repository") 4 | return ({ 5 | repository: { 6 | description: faker.lorem.sentences(), 7 | }, 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/introduction.user.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > introduction/user") 4 | return ({ 5 | user: { 6 | bio: faker.lorem.sentences(), 7 | }, 8 | }) 9 | } 10 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/isocalendar.calendar.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > isocalendar/calendar") 4 | //Generate calendar 5 | const date = new Date(query.match(/from: "(?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z)"/)?.groups?.date) 6 | const to = new Date(query.match(/to: "(?\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z)"/)?.groups?.date) 7 | const weeks = [] 8 | let contributionDays = [] 9 | for (; date <= to; date.setDate(date.getDate() + 1)) { 10 | //Create new week on sunday 11 | if (date.getDay() === 0) { 12 | weeks.push({contributionDays}) 13 | contributionDays = [] 14 | } 15 | //Random contributions 16 | const contributionCount = Math.min(10, Math.max(0, faker.number.int(14) - 4)) 17 | contributionDays.push({ 18 | contributionCount, 19 | color: ["#ebedf0", "#9be9a8", "#40c463", "#30a14e", "#216e39"][Math.ceil(contributionCount / 10 / 0.25)], 20 | date: date.toISOString().substring(0, 10), 21 | }) 22 | } 23 | return ({ 24 | user: { 25 | calendar: { 26 | contributionCalendar: { 27 | weeks, 28 | }, 29 | }, 30 | }, 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/licenses.repository.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > licenses/repository") 4 | return ({ 5 | user: { 6 | repository: { 7 | licenseInfo: {spdxId: "MIT", name: "MIT License", nickname: null, key: "mit"}, 8 | url: "https://github.com/lowlighter/metrics", 9 | databaseId: 293860197, 10 | }, 11 | }, 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/notable.issues.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > notable/issues") 4 | return /after: "MOCKED_CURSOR"/m.test(query) 5 | ? ({ 6 | user: { 7 | issues: { 8 | edges: [], 9 | }, 10 | pullRequests: { 11 | edges: [], 12 | }, 13 | }, 14 | }) 15 | : ({ 16 | user: { 17 | issues: { 18 | totalCount: faker.number.int(1000), 19 | edges: [ 20 | { 21 | cursor: "MOCKED_CURSOR", 22 | node: { 23 | repository: { 24 | nameWithOwner: `${faker.internet.userName()}/${faker.lorem.slug()}`, 25 | }, 26 | }, 27 | }, 28 | ], 29 | }, 30 | get pullRequests() { 31 | return this.issues 32 | }, 33 | }, 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/people.default.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > people/default") 4 | const type = query.match(/(?followers|following)[(]/)?.groups?.type ?? "(unknown type)" 5 | return /after: "MOCKED_CURSOR"/m.test(query) 6 | ? ({ 7 | user: { 8 | [type]: { 9 | edges: [], 10 | }, 11 | }, 12 | }) 13 | : ({ 14 | user: { 15 | [type]: { 16 | edges: new Array(Math.ceil(20 + 80 * Math.random())).fill(null).map((login = faker.internet.userName()) => ({ 17 | cursor: "MOCKED_CURSOR", 18 | node: { 19 | login, 20 | avatarUrl: null, 21 | }, 22 | })), 23 | }, 24 | }, 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/people.repository.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > people/repository") 4 | const type = query.match(/(?stargazers|watchers)[(]/)?.groups?.type ?? "(unknown type)" 5 | return /after: "MOCKED_CURSOR"/m.test(query) 6 | ? ({ 7 | user: { 8 | repository: { 9 | [type]: { 10 | edges: [], 11 | }, 12 | }, 13 | }, 14 | }) 15 | : ({ 16 | user: { 17 | repository: { 18 | [type]: { 19 | edges: new Array(Math.ceil(20 + 80 * Math.random())).fill(null).map((login = faker.internet.userName()) => ({ 20 | cursor: "MOCKED_CURSOR", 21 | node: { 22 | login, 23 | avatarUrl: null, 24 | }, 25 | })), 26 | }, 27 | }, 28 | }, 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/people.sponsors.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > people/sponsors") 4 | const type = query.match(/(?sponsorshipsAsSponsor|sponsorshipsAsMaintainer)[(]/)?.groups?.type ?? "(unknown type)" 5 | return /after: "MOCKED_CURSOR"/m.test(query) 6 | ? ({ 7 | user: { 8 | login, 9 | [type]: { 10 | edges: [], 11 | }, 12 | }, 13 | }) 14 | : ({ 15 | user: { 16 | login, 17 | [type]: { 18 | edges: new Array(Math.ceil(20 + 80 * Math.random())).fill(null).map((login = faker.internet.userName()) => ({ 19 | cursor: "MOCKED_CURSOR", 20 | node: { 21 | sponsorEntity: { 22 | login: faker.internet.userName(), 23 | avatarUrl: null, 24 | }, 25 | sponsorable: { 26 | login: faker.internet.userName(), 27 | avatarUrl: null, 28 | }, 29 | }, 30 | })), 31 | }, 32 | }, 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/projects.repository.legacy.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > projects/repository.legacy") 4 | return ({ 5 | user: { 6 | repository: { 7 | project: { 8 | name: "Repository project example", 9 | updatedAt: `${faker.date.recent()}`, 10 | body: faker.lorem.paragraph(), 11 | progress: { 12 | doneCount: faker.number.int(10), 13 | inProgressCount: faker.number.int(10), 14 | todoCount: faker.number.int(10), 15 | enabled: true, 16 | }, 17 | }, 18 | }, 19 | }, 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/projects.repository.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > projects/repository") 4 | return ({ 5 | user: { 6 | repository: { 7 | projectV2: { 8 | name: "Repository project example", 9 | updatedAt: `${faker.date.recent()}`, 10 | body: faker.lorem.paragraph(), 11 | items: { 12 | get totalCount() { 13 | return this.nodes.length 14 | }, 15 | nodes: new Array(faker.number.int(10)).fill(null).map(() => ({type: faker.helpers.arrayElement(["DRAFT_ISSUE", "ISSUE", "PULL_REQUEST", "REDACTED"]), fieldValues: {nodes: [{text: faker.lorem.sentence()}]}})), 16 | }, 17 | }, 18 | }, 19 | }, 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/projects.user.legacy.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > projects/user.legacy") 4 | return ({ 5 | user: { 6 | projects: { 7 | totalCount: 1, 8 | nodes: [ 9 | { 10 | name: "User-owned project", 11 | updatedAt: `${faker.date.recent()}`, 12 | body: faker.lorem.paragraph(), 13 | progress: { 14 | doneCount: faker.number.int(10), 15 | inProgressCount: faker.number.int(10), 16 | todoCount: faker.number.int(10), 17 | enabled: true, 18 | }, 19 | }, 20 | ], 21 | }, 22 | }, 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/projects.user.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > projects/user") 4 | return ({ 5 | user: { 6 | projectsV2: { 7 | totalCount: 1, 8 | nodes: [ 9 | { 10 | name: "User-owned project", 11 | updatedAt: `${faker.date.recent()}`, 12 | body: faker.lorem.paragraph(), 13 | items: { 14 | get totalCount() { 15 | return this.nodes.length 16 | }, 17 | nodes: new Array(faker.number.int(10)).fill(null).map(() => ({type: faker.helpers.arrayElement(["DRAFT_ISSUE", "ISSUE", "PULL_REQUEST", "REDACTED"]), fieldValues: {nodes: [{text: faker.lorem.sentence()}]}})), 18 | }, 19 | }, 20 | ], 21 | }, 22 | }, 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/reactions.default.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > reactions/default") 4 | const type = query.match(/(?issues|issueComments)[(]/)?.groups?.type ?? "(unknown type)" 5 | return /after: "MOCKED_CURSOR"/m.test(query) 6 | ? ({ 7 | user: { 8 | [type]: { 9 | edges: [], 10 | nodes: [], 11 | }, 12 | }, 13 | }) 14 | : ({ 15 | user: { 16 | [type]: { 17 | edges: new Array(100).fill(null).map(_ => ({ 18 | cursor: "MOCKED_CURSOR", 19 | node: { 20 | createdAt: faker.date.recent(), 21 | reactions: { 22 | nodes: new Array(50).fill(null).map(_ => ({ 23 | user: {login: faker.internet.userName()}, 24 | content: faker.helpers.arrayElement(["HEART", "THUMBS_UP", "THUMBS_DOWN", "LAUGH", "CONFUSED", "EYES", "ROCKET", "HOORAY"]), 25 | })), 26 | }, 27 | }, 28 | })), 29 | }, 30 | }, 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/repositories.random.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > repositories/random") 4 | return ({ 5 | user: { 6 | repositories: { 7 | nodes: [ 8 | {nameWithOwner: "lowlighter/metrics"}, 9 | ], 10 | }, 11 | }, 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/repositories.repository.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > repositories/repository") 4 | return ({ 5 | repository: { 6 | createdAt: faker.date.past(), 7 | description: "📊 An image generator with 20+ metrics about your GitHub account such as activity, community, repositories, coding habits, website performances, music played, starred topics, etc. that you can put on your profile or elsewhere !", 8 | forkCount: faker.number.int(100), 9 | isFork: false, 10 | issues: { 11 | totalCount: faker.number.int(100), 12 | }, 13 | nameWithOwner: "lowlighter/metrics", 14 | openGraphImageUrl: "https://repository-images.githubusercontent.com/293860197/7fd72080-496d-11eb-8fe0-238b38a0746a", 15 | pullRequests: { 16 | totalCount: faker.number.int(100), 17 | }, 18 | stargazerCount: faker.number.int(10000), 19 | licenseInfo: { 20 | nickname: null, 21 | name: "MIT License", 22 | }, 23 | primaryLanguage: { 24 | color: "#f1e05a", 25 | name: "JavaScript", 26 | }, 27 | }, 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/repositories.starred.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > repositories/starred") 4 | return ({ 5 | user: { 6 | repositories: { 7 | nodes: [ 8 | {nameWithOwner: "lowlighter/metrics"}, 9 | ], 10 | }, 11 | }, 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/sponsors.active.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > sponsors/default") 4 | return /after: "MOCKED_CURSOR"/m.test(query) 5 | ? ({ 6 | user: { 7 | sponsorshipsAsMaintainer: { 8 | edges: [], 9 | nodes: [], 10 | }, 11 | }, 12 | }) 13 | : ({ 14 | user: { 15 | sponsorshipsAsMaintainer: { 16 | edges: new Array(10).fill("MOCKED_CURSOR"), 17 | nodes: new Array(10).fill(null).map(_ => ({ 18 | privacyLevel: faker.helpers.arrayElement(["PUBLIC", "PRIVATE"]), 19 | sponsorEntity: { 20 | login: faker.internet.userName(), 21 | avatarUrl: null, 22 | }, 23 | tier: { 24 | monthlyPriceInDollars: faker.number.int(10), 25 | }, 26 | })), 27 | }, 28 | }, 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/sponsors.all.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > sponsors/all") 4 | return /after: "MOCKED_CURSOR"/m.test(query) 5 | ? ({ 6 | user: { 7 | sponsorsActivities: { 8 | edges: [], 9 | nodes: [], 10 | }, 11 | }, 12 | }) 13 | : ({ 14 | user: { 15 | sponsorsActivities: { 16 | edges: new Array(10).fill("MOCKED_CURSOR"), 17 | nodes: new Array(10).fill(null).map(_ => ({ 18 | sponsor: { 19 | login: faker.internet.userName(), 20 | avatarUrl: null, 21 | }, 22 | sponsorsTier: { 23 | monthlyPriceInDollars: faker.number.int(10), 24 | }, 25 | })), 26 | }, 27 | }, 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/sponsors.description.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > sponsors/default") 4 | return ({ 5 | user: { 6 | sponsorsListing: { 7 | fullDescription: faker.lorem.sentences(), 8 | activeGoal: { 9 | percentComplete: faker.number.int(100), 10 | title: faker.lorem.sentence(), 11 | description: faker.lorem.sentence(), 12 | }, 13 | }, 14 | }, 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/sponsorships.all.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > sponsorships/all") 4 | return /after: "MOCKED_CURSOR"/m.test(query) 5 | ? ({ 6 | user: { 7 | sponsorshipsAsSponsor: { 8 | edges: [], 9 | nodes: [], 10 | }, 11 | }, 12 | }) 13 | : ({ 14 | user: { 15 | sponsorshipsAsSponsor: { 16 | edges: new Array(10).fill("MOCKED_CURSOR"), 17 | nodes: new Array(10).fill(null).map(_ => ({ 18 | createdAt: `${faker.date.recent()}`, 19 | isActive: faker.datatype.boolean(), 20 | isOneTimePayment: faker.datatype.boolean(), 21 | tier: { 22 | name: "$X a month", 23 | }, 24 | privacyLevel: "PUBLIC", 25 | sponsorable: { 26 | login: faker.internet.userName(), 27 | avatarUrl: null, 28 | }, 29 | })), 30 | }, 31 | }, 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/sponsorships.default.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > sponsorships/default") 4 | return ({ 5 | user: { 6 | totalSponsorshipAmountAsSponsorInCents: faker.number.int(100000), 7 | sponsorshipsAsSponsor: { 8 | nodes: [{createdAt: `${faker.date.recent()}`}], 9 | }, 10 | }, 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /tests/mocks/api/github/graphql/stargazers.default.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default function({faker, query, login = faker.internet.userName()}) { 3 | console.debug("metrics/compute/mocks > mocking graphql api result > stargazers/default") 4 | return /after: "MOCKED_CURSOR"/m.test(query) 5 | ? ({ 6 | repository: { 7 | stargazers: { 8 | edges: [], 9 | }, 10 | }, 11 | }) 12 | : ({ 13 | repository: { 14 | stargazers: { 15 | edges: new Array(faker.number.int({min: 50, max: 100})).fill(null).map(() => ({ 16 | starredAt: `${faker.date.recent({days: 30})}`, 17 | cursor: "MOCKED_CURSOR", 18 | node: { 19 | location: faker.location.city(), 20 | }, 21 | })), 22 | }, 23 | }, 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/activity/listRepoEvents.mjs: -------------------------------------------------------------------------------- 1 | //Imports 2 | import listEventsForAuthenticatedUser from "./listEventsForAuthenticatedUser.mjs" 3 | 4 | /**Mocked data */ 5 | export default async function({faker}, target, that, [{username: login, page, per_page}]) { 6 | console.debug("metrics/compute/mocks > mocking rest api result > rest.activity.listRepoEvents") 7 | return listEventsForAuthenticatedUser(...arguments) 8 | } 9 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/rateLimit/get.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default async function({faker}, target, that, args) { 3 | return ({ 4 | status: 200, 5 | url: "https://api.github.com/rate_limit", 6 | headers: { 7 | server: "GitHub.com", 8 | status: "200 OK", 9 | "x-oauth-scopes": "repo", 10 | }, 11 | data: { 12 | resources: { 13 | core: {limit: 5000, used: 0, remaining: 5000, reset: 0}, 14 | search: {limit: 30, used: 0, remaining: 30, reset: 0}, 15 | graphql: {limit: 5000, used: 0, remaining: 5000, reset: 0}, 16 | integration_manifest: {limit: 5000, used: 0, remaining: 5000, reset: 0}, 17 | source_import: {limit: 100, used: 0, remaining: 100, reset: 0}, 18 | code_scanning_upload: {limit: 500, used: 0, remaining: 500, reset: 0}, 19 | }, 20 | rate: {limit: 5000, used: 0, remaining: "MOCKED", reset: 0}, 21 | }, 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/repos/get.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default async function({faker}, target, that, [{owner, repo}]) { 3 | console.debug("metrics/compute/mocks > mocking rest api result > rest.repos.get") 4 | return ({ 5 | status: 200, 6 | url: `https://api.github.com/repos/${owner}/${repo}`, 7 | headers: { 8 | server: "GitHub.com", 9 | status: "200 OK", 10 | "x-oauth-scopes": "repo", 11 | }, 12 | data: { 13 | id: faker.number.int(100000), 14 | name: repo, 15 | full_name: `${owner}/${repo}`, 16 | private: false, 17 | owner: { 18 | login: owner, 19 | id: faker.number.int(100000), 20 | }, 21 | description: faker.lorem.sentences(), 22 | created_at: faker.date.past(), 23 | license: { 24 | key: "mit", 25 | name: "MIT License", 26 | }, 27 | default_branch: "main", 28 | }, 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/repos/getContributorsStats.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default async function({faker}, target, that, [{owner, repo}]) { 3 | console.debug("metrics/compute/mocks > mocking rest api result > rest.repos.getContributorsStats") 4 | return ({ 5 | status: 200, 6 | url: `https://api.github.com/repos/${owner}/${repo}/stats/contributors`, 7 | headers: { 8 | server: "GitHub.com", 9 | status: "200 OK", 10 | "x-oauth-scopes": "repo", 11 | }, 12 | data: [ 13 | { 14 | total: faker.number.int(10000), 15 | weeks: [ 16 | {w: faker.date.recent(), a: faker.number.int(10000), d: faker.number.int(10000), c: faker.number.int(10000)}, 17 | {w: faker.date.recent(), a: faker.number.int(10000), d: faker.number.int(10000), c: faker.number.int(10000)}, 18 | {w: faker.date.recent(), a: faker.number.int(10000), d: faker.number.int(10000), c: faker.number.int(10000)}, 19 | {w: faker.date.recent(), a: faker.number.int(10000), d: faker.number.int(10000), c: faker.number.int(10000)}, 20 | ].sort((a, b) => new Date(a.w) - new Date(b.w)), 21 | author: { 22 | login: owner, 23 | }, 24 | }, 25 | ], 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/repos/getViews.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default async function({faker}, target, that, [{owner, repo}]) { 3 | console.debug("metrics/compute/mocks > mocking rest api result > rest.repos.getViews") 4 | const count = faker.number.int(10000) * 2 5 | const uniques = faker.number.int(count) * 2 6 | return ({ 7 | status: 200, 8 | url: `https://api.github.com/repos/${owner}/${repo}/traffic/views`, 9 | headers: { 10 | server: "GitHub.com", 11 | status: "200 OK", 12 | "x-oauth-scopes": "repo", 13 | }, 14 | data: { 15 | count, 16 | uniques, 17 | views: [ 18 | {timestamp: `${faker.date.recent()}`, count: count / 2, uniques: uniques / 2}, 19 | {timestamp: `${faker.date.recent()}`, count: count / 2, uniques: uniques / 2}, 20 | ], 21 | }, 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/repos/listCommits.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default async function({faker}, target, that, [{page, per_page, owner, repo}]) { 3 | console.debug("metrics/compute/mocks > mocking rest api result > rest.repos.listCommits") 4 | return ({ 5 | status: 200, 6 | url: `https://api.github.com/repos/${owner}/${repo}/commits?per_page=${per_page}&page=${page}`, 7 | headers: { 8 | server: "GitHub.com", 9 | status: "200 OK", 10 | "x-oauth-scopes": "repo", 11 | }, 12 | data: page < 2 13 | ? new Array(per_page).fill(null).map(() => ({ 14 | sha: "MOCKED_SHA", 15 | get author() { 16 | return this.commit.author 17 | }, 18 | commit: { 19 | message: faker.lorem.sentence(), 20 | author: { 21 | name: owner, 22 | login: faker.internet.userName(), 23 | avatar_url: null, 24 | date: `${faker.date.recent({days: 14})}`, 25 | }, 26 | committer: { 27 | name: owner, 28 | login: faker.internet.userName(), 29 | avatar_url: null, 30 | date: `${faker.date.recent({days: 14})}`, 31 | }, 32 | }, 33 | })) 34 | : [], 35 | }) 36 | } 37 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/repos/listContributors.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default async function({faker}, target, that, [{owner, repo}]) { 3 | console.debug("metrics/compute/mocks > mocking rest api result > rest.repos.listContributors") 4 | return ({ 5 | status: 200, 6 | url: `https://api.github.com/repos/${owner}/${repo}/contributors`, 7 | headers: { 8 | server: "GitHub.com", 9 | status: "200 OK", 10 | "x-oauth-scopes": "repo", 11 | }, 12 | data: new Array(40 + faker.number.int(60)).fill(null).map(() => ({ 13 | login: faker.internet.userName(), 14 | avatar_url: null, 15 | contributions: faker.number.int(1000), 16 | })), 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/users/getByUsername.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default async function({faker}, target, that, [{username}]) { 3 | console.debug("metrics/compute/mocks > mocking rest api result > rest.repos.getByUsername") 4 | return ({ 5 | status: 200, 6 | url: `https://api.github.com/users/${username}/`, 7 | headers: { 8 | server: "GitHub.com", 9 | status: "200 OK", 10 | "x-oauth-scopes": "repo", 11 | }, 12 | data: { 13 | login: faker.internet.userName(), 14 | avatar_url: null, 15 | contributions: faker.number.int(1000), 16 | }, 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /tests/mocks/api/github/rest/users/listGpgKeysForUser.mjs: -------------------------------------------------------------------------------- 1 | /**Mocked data */ 2 | export default async function({faker}, target, that, [{username}]) { 3 | console.debug("metrics/compute/mocks > mocking rest api result > rest.users.listGpgKeysForUser") 4 | return ({ 5 | status: 200, 6 | url: `https://api.github.com/users/${username}/`, 7 | headers: { 8 | server: "GitHub.com", 9 | status: "200 OK", 10 | "x-oauth-scopes": "repo", 11 | }, 12 | data: [ 13 | { 14 | key_id: faker.datatype.hexadecimal(16), 15 | raw_key: "-----BEGIN PGP PUBLIC KEY BLOCK-----\n(dummy content)\n-----END PGP PUBLIC KEY BLOCK-----", 16 | emails: [ 17 | { 18 | email: faker.internet.email(), 19 | verified: true, 20 | }, 21 | ], 22 | }, 23 | ], 24 | }) 25 | } 26 | -------------------------------------------------------------------------------- /tests/secrets.json: -------------------------------------------------------------------------------- 1 | { 2 | "METRICS_TOKEN":"MOCKED_TOKEN", 3 | "METRICS_TOKEN_WITH_SCOPES":"MOCKED_TOKEN", 4 | "METRICS_TOKEN_PERSONAL": "MOCKED_TOKEN", 5 | "PAGESPEED_TOKEN":"MOCKED_TOKEN", 6 | "SPOTIFY_TOKENS":"MOCKED_CLIENT_ID, MOCKED_CLIENT_SECRET, MOCKED_REFRESH_TOKEN", 7 | "YOUTUBE_MUSIC_TOKENS":"SAPISID=MOCKED_COOKIE; OTHER_PARAM=OTHER_VALUE;", 8 | "LASTFM_TOKEN":"MOCKED_TOKEN", 9 | "NIGHTSCOUT_URL":"https://testapp.herokuapp.com/", 10 | "WAKATIME_TOKEN":"MOCKED_TOKEN", 11 | "TWITTER_TOKEN":"MOCKED_TOKEN", 12 | "GOOGLE_MAP_TOKEN": "MOCKED_TOKEN", 13 | "STOCK_TOKEN":"MOCKED_TOKEN", 14 | "CHESS_TOKEN":"MOCKED_TOKEN", 15 | "STEAM_TOKEN":"MOCKED_TOKEN", 16 | "SPLATOON_TOKEN":"{}", 17 | "SPLATOON_STATINK_TOKEN":"MOCKED_TOKEN", 18 | "POOPMAP_TOKEN":"MOCKED_TOKEN", 19 | "SIXTEEN_PERSONALITIES_URL":"https://www.16personalities.com/profiles/b7d9f29453ea5" 20 | } -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "rewrites":[ 3 | {"source": "/.uncache", "destination": "https://metrics.lecoq.io/.uncache"}, 4 | {"source": "/.requests", "destination": "https://metrics.lecoq.io/.requests"}, 5 | {"source": "/.templates", "destination": "/.templates__"}, 6 | {"source": "/.templates/:template", "destination": "/.templates_/:template"}, 7 | {"source": "/about/query/:login", "destination": "https://metrics.lecoq.io/about/query/:login"}, 8 | {"source": "/about/query/:login/:plugin", "destination": "https://metrics.lecoq.io/about/query/:login/:plugin"}, 9 | {"source": "/insights/query/:login", "destination": "https://metrics.lecoq.io/insights/query/:login"}, 10 | {"source": "/insights/query/:login/:plugin", "destination": "https://metrics.lecoq.io/insights/query/:login/:plugin"}, 11 | {"source": "/:login([-\\w]+)", "destination": "https://metrics.lecoq.io/:login"}, 12 | {"source": "/:login([-\\w]+)/:repository([-\\w]+)", "destination": "https://metrics.lecoq.io/:login/:repository"} 13 | ], 14 | "github":{ 15 | "silent": true, 16 | "autoJobCancelation": true 17 | } 18 | } --------------------------------------------------------------------------------