Skip to content

sponsorship

sponsorship #21

name: Sponsor Team Manager
on:
repository_dispatch:
types: [sponsorship]
workflow_dispatch:
inputs:
test_username:
description: 'GitHub username to test with'
required: true
default: 'francoios'
test_tier:
description: 'Tier name'
required: true
default: 'Backer'
test_price:
description: 'Monthly price in dollars'
required: true
default: '15'
test_action:
description: 'Action type'
required: true
default: 'created'
type: choice
options:
- created
- cancelled
- tier_changed
- pending_cancellation
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
manage-sponsor:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Handle sponsor event
uses: actions/github-script@v7
env:
DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}
with:
github-token: ${{ secrets.ORG_ADMIN_TOKEN }}
script: |
// Determine source: webhook (repository_dispatch) or manual test (workflow_dispatch)
let sponsor, tierName, tierPrice, action;
if (context.eventName === 'repository_dispatch') {
const payload = context.payload.client_payload;
sponsor = payload.sponsorship.sponsor.login;
tierName = payload.sponsorship.tier.name;
tierPrice = payload.sponsorship.tier.monthly_price_in_dollars;
action = payload.action;
console.log(`Webhook event: ${action} from ${sponsor}`);
} else {
// workflow_dispatch (manual test)
sponsor = '${{ github.event.inputs.test_username }}';
tierName = '${{ github.event.inputs.test_tier }}';
tierPrice = parseInt('${{ github.event.inputs.test_price }}');
action = '${{ github.event.inputs.test_action }}';
console.log(`Manual test: ${action} for ${sponsor}`);
}
const org = 'AnkleBreaker-Studio';
const teamSlug = 'sponsors';
const MIN_TIER_PRICE = 15;
const DISCORD_CHANNEL = '1476975591692435620';
async function postDiscord(message) {
try {
const resp = await fetch(
`https://discord.com/api/v10/channels/${DISCORD_CHANNEL}/messages`,
{
method: 'POST',
headers: {
'Authorization': `Bot ${process.env.DISCORD_BOT_TOKEN}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ content: message })
}
);
if (!resp.ok) console.error(`Discord error: ${resp.status}`);
} catch (e) { console.error(`Discord post failed: ${e.message}`); }
}
if (action === 'created' || action === 'tier_changed') {
if (tierPrice >= MIN_TIER_PRICE) {
try {
await github.rest.teams.addOrUpdateMembershipForUserInOrg({
org, team_slug: teamSlug, username: sponsor, role: 'member'
});
console.log(`Added ${sponsor} to sponsors team`);
} catch (error) {
console.error(`Failed to add ${sponsor}: ${error.message}`);
}
if (action === 'created') {
if (tierPrice >= 100) {
await postDiscord(
`## \ud83d\udd34 New MCP Priority Support Subscriber!\n\n` +
`**${sponsor}** just joined as an **${tierName}** subscriber! Welcome to the inner circle! \u2764\ufe0f\n\n` +
`Thank you for your incredible support of AnkleBreaker Studio! You now have priority access to our team. \ud83d\ude80\n\n` +
`> Don't forget to claim your **MCP Priority Support** Discord role in the [premium-mcps repo](https://github.com/AnkleBreaker-Studio/premium-mcps)!`
);
} else {
await postDiscord(
`## \ud83c\udf89 New Sponsor!\n\n` +
`**${sponsor}** just joined as a **${tierName}** sponsor! Welcome to the AnkleBreaker Studio family! \u2764\ufe0f\n\n` +
`Thank you for supporting our MCP tools and open-source projects! \ud83d\ude80\n\n` +
`> Don't forget to claim your **Private MCP Sponsor** Discord role in the [premium-mcps repo](https://github.com/AnkleBreaker-Studio/premium-mcps)!`
);
}
}
} else if (action === 'tier_changed') {
try {
await github.rest.teams.removeMembershipForUserInOrg({ org, team_slug: teamSlug, username: sponsor });
} catch (error) { console.log(`Note: ${sponsor} may not have been in team`); }
}
}
if (action === 'cancelled' || action === 'pending_cancellation') {
try {
await github.rest.teams.removeMembershipForUserInOrg({ org, team_slug: teamSlug, username: sponsor });
} catch (error) { console.log(`Note: ${sponsor} may not have been in team`); }
}