|
1 |
| -const passport = require('passport'); |
2 |
| -const ORCIDStrategy = require('passport-orcid').Strategy; |
3 |
| - |
4 |
| -passport.use(new ORCIDStrategy({ |
5 |
| - clientID: process.env.ORCID_CLIENT_ID, |
6 |
| - clientSecret: process.env.ORCID_CLIENT_SECRET, |
7 |
| - callbackURL: 'https://yourapp.example.com/auth/orcid/callback' |
8 |
| -}, (accessToken, refreshToken, profile, done) => { |
9 |
| - // profile.id is the ORCID iD |
10 |
| - done(null, { orcid_id: profile.id }); |
11 |
| -})); |
12 |
| - |
13 |
| -// Routes |
14 |
| -app.get('/auth/orcid', passport.authenticate('orcid')); |
15 |
| -app.get('/auth/orcid/callback', |
16 |
| - passport.authenticate('orcid', { session: true }), |
17 |
| - (req, res) => { |
18 |
| - // Session now contains req.user.orcid_id |
19 |
| - res.redirect('/pledge'); |
| 1 | +import { Client, GatewayIntentBits, TextChannel, ThreadChannel, ChannelType, EmbedBuilder } from 'discord.js'; |
| 2 | +import { BadgeClient } from 'kypria-badge-sdk'; |
| 3 | +import { promises as fs } from 'fs'; |
| 4 | +import path from 'path'; |
| 5 | +import yaml from 'js-yaml'; |
| 6 | +import { dropBadge } from './utils/dropBadge'; |
| 7 | + |
| 8 | +type BadgeConfig = { |
| 9 | + drop_channels: string[]; |
| 10 | +}; |
| 11 | + |
| 12 | +type Config = Record<string, BadgeConfig>; |
| 13 | + |
| 14 | +type SponsorPingPayload = { |
| 15 | + sponsorId: string; |
| 16 | + badgeName: string; |
| 17 | +}; |
| 18 | + |
| 19 | +type Relic = SponsorPingPayload & { |
| 20 | + timestamp: string; |
| 21 | + threadId: string; |
| 22 | +}; |
| 23 | + |
| 24 | +(async () => { |
| 25 | + // 1. Load & validate badge‐locations.yml |
| 26 | + const cfgPath = path.resolve(__dirname, '../config/badge-locations.yml'); |
| 27 | + let config: Config; |
| 28 | + try { |
| 29 | + const raw = await fs.readFile(cfgPath, 'utf8'); |
| 30 | + config = (yaml.load(raw) as Config) ?? {}; |
| 31 | + } catch (err) { |
| 32 | + console.error('❌ Failed to load badge-locations.yml:', err); |
| 33 | + process.exit(1); |
20 | 34 | }
|
21 |
| -); |
22 |
| - |
23 |
| - |
24 |
| -## Git Credential Manager |
25 |
| - |
26 |
| -[![Build Status][build-status-badge]][workflow-status] |
27 |
| - |
28 |
| ---- |
29 |
| - |
30 |
| -[Git Credential Manager][gcm] (GCM) is a secure |
31 |
| -[Git credential helper][git-credential-helper] built on [.NET][dotnet] that runs |
32 |
| -on Windows, macOS, and Linux. It aims to provide a consistent and secure |
33 |
| -authentication experience, including multi-factor auth, to every major source |
34 |
| -control hosting service and platform. |
35 |
| - |
36 |
| -GCM supports (in alphabetical order) [Azure DevOps][azure-devops], Azure DevOps |
37 |
| -Server (formerly Team Foundation Server), Bitbucket, GitHub, and GitLab. |
38 |
| -Compare to Git's [built-in credential helpers][git-tools-credential-storage] |
39 |
| -(Windows: wincred, macOS: osxkeychain, Linux: gnome-keyring/libsecret), which |
40 |
| -provide single-factor authentication support for username/password only. |
41 |
| - |
42 |
| -GCM replaces both the .NET Framework-based |
43 |
| -[Git Credential Manager for Windows][gcm-for-windows] and the Java-based |
44 |
| -[Git Credential Manager for Mac and Linux][gcm-for-mac-and-linux]. |
45 |
| - |
46 |
| -## Install |
47 |
| - |
48 |
| -See the [installation instructions][install] for the current version of GCM for |
49 |
| -install options for your operating system. |
50 |
| - |
51 |
| -## Current status |
52 |
| - |
53 |
| -Git Credential Manager is currently available for Windows, macOS, and Linux\*. |
54 |
| -GCM only works with HTTP(S) remotes; you can still use Git with SSH: |
55 |
| - |
56 |
| -- [Azure DevOps SSH][azure-devops-ssh] |
57 |
| -- [GitHub SSH][github-ssh] |
58 |
| -- [Bitbucket SSH][bitbucket-ssh] |
59 |
| - |
60 |
| -Feature|Windows|macOS|Linux\* |
61 |
| --|:-:|:-:|:-: |
62 |
| -Installer/uninstaller|✓|✓|✓ |
63 |
| -Secure platform credential storage [(see more)][gcm-credstores]|✓|✓|✓ |
64 |
| -Multi-factor authentication support for Azure DevOps|✓|✓|✓ |
65 |
| -Two-factor authentication support for GitHub|✓|✓|✓ |
66 |
| -Two-factor authentication support for Bitbucket|✓|✓|✓ |
67 |
| -Two-factor authentication support for GitLab|✓|✓|✓ |
68 |
| -Windows Integrated Authentication (NTLM/Kerberos) support|✓|_N/A_|_N/A_ |
69 |
| -Basic HTTP authentication support|✓|✓|✓ |
70 |
| -Proxy support|✓|✓|✓ |
71 |
| -`amd64` support|✓|✓|✓ |
72 |
| -`x86` support|✓|_N/A_|✗ |
73 |
| -`arm64` support|best effort|✓|✓ |
74 |
| -`armhf` support|_N/A_|_N/A_|✓ |
75 |
| - |
76 |
| -(\*) GCM guarantees support only for [the Linux distributions that are officially |
77 |
| -supported by dotnet][dotnet-distributions]. |
78 |
| - |
79 |
| -## Supported Git versions |
80 |
| - |
81 |
| -Git Credential Manager tries to be compatible with the broadest set of Git |
82 |
| -versions (within reason). However there are some know problematic releases of |
83 |
| -Git that are not compatible. |
84 |
| - |
85 |
| -- Git 1.x |
86 |
| - |
87 |
| - The initial major version of Git is not supported or tested with GCM. |
88 |
| - |
89 |
| -- Git 2.26.2 |
90 |
| - |
91 |
| - This version of Git introduced a breaking change with parsing credential |
92 |
| - configuration that GCM relies on. This issue was fixed in commit |
93 |
| - [`12294990`][gcm-commit-12294990] of the Git project, and released in Git |
94 |
| - 2.27.0. |
95 |
| - |
96 |
| -## How to use |
97 |
| - |
98 |
| -Once it's installed and configured, Git Credential Manager is called implicitly |
99 |
| -by Git. You don't have to do anything special, and GCM isn't intended to be |
100 |
| -called directly by the user. For example, when pushing (`git push`) to |
101 |
| -[Azure DevOps][azure-devops], [Bitbucket][bitbucket], or [GitHub][github], a |
102 |
| -window will automatically open and walk you through the sign-in process. (This |
103 |
| -process will look slightly different for each Git host, and even in some cases, |
104 |
| -whether you've connected to an on-premises or cloud-hosted Git host.) Later Git |
105 |
| -commands in the same repository will re-use existing credentials or tokens that |
106 |
| -GCM has stored for as long as they're valid. |
107 |
| - |
108 |
| -Read full command line usage [here][gcm-usage]. |
109 |
| - |
110 |
| -### Configuring a proxy |
111 |
| - |
112 |
| -See detailed information [here][gcm-http-proxy]. |
113 |
| - |
114 |
| -## Additional Resources |
115 |
| - |
116 |
| -See the [documentation index][docs-index] for links to additional resources. |
117 |
| - |
118 |
| -## Experimental Features |
119 |
| - |
120 |
| -- [Windows broker (experimental)][gcm-windows-broker] |
121 |
| - |
122 |
| -## Future features |
123 |
| - |
124 |
| -Curious about what's coming next in the GCM project? Take a look at the [project |
125 |
| -roadmap][roadmap]! You can find more details about the construction of the |
126 |
| -roadmap and how to interpret it [here][roadmap-announcement]. |
127 |
| - |
128 |
| -## Contributing |
129 |
| - |
130 |
| -This project welcomes contributions and suggestions. |
131 |
| -See the [contributing guide][gcm-contributing] to get started. |
132 |
| - |
133 |
| -This project follows [GitHub's Open Source Code of Conduct][gcm-coc]. |
134 |
| - |
135 |
| -## License |
136 |
| - |
137 |
| -We're [MIT][gcm-license] licensed. |
138 |
| -When using GitHub logos, please be sure to follow the |
139 |
| -[GitHub logo guidelines][github-logos]. |
140 | 35 |
|
141 |
| -[azure-devops]: https://azure.microsoft.com/en-us/products/devops |
142 |
| -[azure-devops-ssh]: https://docs.microsoft.com/en-us/azure/devops/repos/git/use-ssh-keys-to-authenticate?view=azure-devops |
143 |
| -[bitbucket]: https://bitbucket.org |
144 |
| -[bitbucket-ssh]: https://confluence.atlassian.com/bitbucket/ssh-keys-935365775.html |
145 |
| -[build-status-badge]: https://github.com/git-ecosystem/git-credential-manager/actions/workflows/continuous-integration.yml/badge.svg |
146 |
| -[docs-index]: https://github.com/git-ecosystem/git-credential-manager/blob/release/docs/README.md |
147 |
| -[dotnet]: https://dotnet.microsoft.com |
148 |
| -[dotnet-distributions]: https://learn.microsoft.com/en-us/dotnet/core/install/linux |
149 |
| -[git-credential-helper]: https://git-scm.com/docs/gitcredentials |
150 |
| -[gcm]: https://github.com/git-ecosystem/git-credential-manager |
151 |
| -[gcm-coc]: CODE_OF_CONDUCT.md |
152 |
| -[gcm-commit-12294990]: https://github.com/git/git/commit/12294990c90e043862be9eb7eb22c3784b526340 |
153 |
| -[gcm-contributing]: CONTRIBUTING.md |
154 |
| -[gcm-credstores]: https://github.com/git-ecosystem/git-credential-manager/blob/release/docs/credstores.md |
155 |
| -[gcm-for-mac-and-linux]: https://github.com/microsoft/Git-Credential-Manager-for-Mac-and-Linux |
156 |
| -[gcm-for-windows]: https://github.com/microsoft/Git-Credential-Manager-for-Windows |
157 |
| -[gcm-http-proxy]: https://github.com/git-ecosystem/git-credential-manager/blob/release/docs/netconfig.md#http-proxy |
158 |
| -[gcm-license]: LICENSE |
159 |
| -[gcm-usage]: https://github.com/git-ecosystem/git-credential-manager/blob/release/docs/usage.md |
160 |
| -[gcm-windows-broker]: https://github.com/git-ecosystem/git-credential-manager/blob/release/docs/windows-broker.md |
161 |
| -[git-tools-credential-storage]: https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage |
162 |
| -[github]: https://github.com |
163 |
| -[github-ssh]: https://help.github.com/en/articles/connecting-to-github-with-ssh |
164 |
| -[github-logos]: https://github.com/logos |
165 |
| -[install]: https://github.com/git-ecosystem/git-credential-manager/blob/release/docs/install.md |
166 |
| -[ms-package-repos]: https://packages.microsoft.com/repos/ |
167 |
| -[roadmap]: https://github.com/git-ecosystem/git-credential-manager/milestones?direction=desc&sort=due_date&state=open |
168 |
| -[roadmap-announcement]: https://github.com/git-ecosystem/git-credential-manager/discussions/1203 |
169 |
| -[workflow-status]: https://github.com/git-ecosystem/git-credential-manager/actions/workflows/continuous-integration.yml |
| 36 | + // 2. Initialize clients |
| 37 | + const badgeClient = new BadgeClient({ apiToken: process.env.BADGE_API_TOKEN! }); |
| 38 | + const discord = new Client({ intents: [GatewayIntentBits.Guilds] }); |
| 39 | + |
| 40 | + discord.once('ready', () => { |
| 41 | + console.log(`✅ Discord bot ready as ${discord.user?.tag}`); |
| 42 | + }); |
| 43 | + |
| 44 | + // 3. Handle sponsorPing |
| 45 | + badgeClient.on('sponsorPing', async ({ sponsorId, badgeName }: SponsorPingPayload) => { |
| 46 | + const channels = config[badgeName]?.drop_channels ?? []; |
| 47 | + const timestamp = new Date().toISOString(); |
| 48 | + const threadId = `thread-${timestamp.replace(/[:.]/g, '-')}`; |
| 49 | + const relic: Relic = { sponsorId, badgeName, timestamp, threadId }; |
| 50 | + |
| 51 | + // 3a. Audit-log relic |
| 52 | + const logDir = path.resolve(__dirname, '../threads'); |
| 53 | + await fs.mkdir(logDir, { recursive: true }); |
| 54 | + const outPath = path.join(logDir, `relic-drop--${badgeName}--${timestamp}.json`); |
| 55 | + await fs.writeFile(outPath, JSON.stringify(relic, null, 2)); |
| 56 | + |
| 57 | + // 3b. Broadcast badge-drop |
| 58 | + for (const chId of channels) { |
| 59 | + try { |
| 60 | + const channel = await discord.channels.fetch(chId); |
| 61 | + if ( |
| 62 | + channel && |
| 63 | + (channel.type === ChannelType.GuildText || channel.type === ChannelType.GuildPublicThread) |
| 64 | + ) { |
| 65 | + // wrap payload with embed title |
| 66 | + await dropBadge(channel as TextChannel | ThreadChannel, { |
| 67 | + ...relic, |
| 68 | + title: `🏅 ${badgeName}`, |
| 69 | + }); |
| 70 | + } else { |
| 71 | + console.warn(`⚠️ Channel ${chId} is not a text/thread channel. Skipping.`); |
| 72 | + } |
| 73 | + } catch (err) { |
| 74 | + console.error(`❌ Failed to drop badge in channel ${chId}:`, err); |
| 75 | + } |
| 76 | + } |
| 77 | + }); |
| 78 | + |
| 79 | + // 4. Connect to Discord |
| 80 | + await discord.login(process.env.DISCORD_TOKEN); |
| 81 | +})(); |
0 commit comments