From 89e9e67b8eb2d98cbb1c1dede5e6c31c60f8f6b5 Mon Sep 17 00:00:00 2001 From: Dmitrii Date: Sat, 16 May 2026 00:33:31 +0300 Subject: [PATCH] feat: add language stats workflow using GitHub API --- .github/workflows/languages.yml | 118 ++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .github/workflows/languages.yml diff --git a/.github/workflows/languages.yml b/.github/workflows/languages.yml new file mode 100644 index 00000000..4b80ad99 --- /dev/null +++ b/.github/workflows/languages.yml @@ -0,0 +1,118 @@ +name: Language Stats + +on: + schedule: [{cron: "0 0 * * 0"}] + workflow_dispatch: + +jobs: + language-stats: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - name: Generate language SVG + env: + GH_TOKEN: ${{ secrets.METRICS_TOKEN }} + run: | + python3 << 'EOF' + import urllib.request, json, math + + token = "${{ secrets.METRICS_TOKEN }}" + headers = {"Authorization": f"Bearer {token}", "Accept": "application/vnd.github+json"} + + repos = [ + "yawaflua/HallOfDoors", "yawaflua/ShardLight", "yawaflua/sigma_market", + "yawaflua/hall_of_doors", "yawaflua/shardlight-web-panel", "yawaflua/AskMeAboutBot", + "yawaflua/binarshina", "yawaflua/SpectrBot", "yawaflua/shardlight-harmony", + "yawaflua/Plinko.Games.Elysium", "yawaflua/Dice.Elysium", "yawaflua/ElysiumChat", + "yawaflua/FireWatch", "yawaflua/S3-Container", "yawaflua/SkinsApi", + "yawaflua/FileSender", "yawaflua/PSQL_backupper", "yawaflua/TGShock", + "yawaflua/BiahadHakatonProject", "yawaflua/WebSockets", "yawaflua/Telegram.Net", + "yawaflua/PixelTalk", "yawaflua/SPMega", "yawaflua/vue.yawaflua.ru", + "yawaflua/react-frontend.yawaflua.ru", "yawaflua/api.yawaflua.ru", + "yawaflua/Aoyo", "yawaflua/TheatreCube", "yawaflua/Discord.Net", + "yawaflua/Aoyo.Taiga", "yawaflua/OrderHabrFreelance", "yawaflua/PL_JusticeBot", + "yawaflua/Q-FordBot", "yawaflua/SPWorlds", "yawaflua/Telegram-Bot-Template", + "yawaflua/SexPlugin", "yawaflua/frontend.yawaflua.ru", "yawaflua/Go.Template.Elysium", + "yawaflua/TestAnswer", "DITTeam/DIT.Notifier", "DITTeam/Aoyo.Elysium", + "DITTeam/Elysium.Telegram", "DITTeam/ElysiumBitcoinProcessor", "DITTeam/ElysiumBackend", + "DITTeam/VideoCutv1", "RoyalArena/SpDonate", "RoyalArena/SPDonateFrontend", + "Diamonds-studio/SpDonateDeprecated" + ] + + ignored = {'HTML', 'CSS', 'CMake', 'Dockerfile', 'Makefile', 'YAML', 'JSON', + 'XML', 'Markdown', 'Text', 'SVG', 'Batchfile', 'PowerShell', + 'EditorConfig', 'Ini', 'TOML', 'Nix'} + colors = { + 'C#': '#178600', 'C++': '#f34b7d', 'JavaScript': '#f1e05a', + 'TypeScript': '#3178c6', 'Go': '#00ADD8', 'Python': '#3572A5', + 'Java': '#b07219', 'Vue': '#41b883', 'Shell': '#89e051' + } + + langs = {} + for repo in repos: + try: + req = urllib.request.Request(f"https://api.github.com/repos/{repo}/languages", headers=headers) + with urllib.request.urlopen(req) as r: + data = json.loads(r.read()) + for lang, bytes_ in data.items(): + if lang not in ignored: + langs[lang] = langs.get(lang, 0) + bytes_ + except Exception as e: + print(f"Skip {repo}: {e}") + + langs = dict(sorted(langs.items(), key=lambda x: x[1], reverse=True)[:10]) + total = sum(langs.values()) + + if total == 0: + print("No data") + exit(1) + + bar_width = 448 + row_h = 30 + padding = 16 + bar_h = 8 + header_h = 44 + height = header_h + bar_h + padding + math.ceil(len(langs) / 2) * row_h + padding * 2 + + svg = f'\n' + svg += f'\n' + svg += f'Most used languages\n' + + cx = 0 + for lang, count in langs.items(): + w = count / total * bar_width + color = colors.get(lang, '#ededed') + svg += f'\n' + cx += w + + items = list(langs.items()) + for i, (lang, count) in enumerate(items): + col = i % 2 + row = i // 2 + lx = 16 + col * 232 + ly = header_h + bar_h + padding + row * row_h + 14 + pct = count / total * 100 + color = colors.get(lang, '#ededed') + svg += f'\n' + svg += f'{lang}\n' + svg += f'{pct:.1f}%\n' + + svg += '' + + with open('languages.svg', 'w') as f: + f.write(svg) + print(f"Done: {len(langs)} languages, {total} bytes total") + for l, b in langs.items(): + print(f" {l}: {b/total*100:.1f}%") + EOF + + - name: Commit SVG + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add languages.svg + git diff --staged --quiet || git commit -m "Update languages.svg - [Skip GitHub Action]" + git push