Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Add discord ping scheduler #231

Merged
merged 12 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/deploy-fallctf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- '_global/content/events/**'
- '_global/content/profiles/**'
- '.github/**'
- '!.github/workflows/scheduled-pings.yml'
- 'fallctf.com/**'
- 'guides'
concurrency:
Expand Down
17 changes: 15 additions & 2 deletions .github/workflows/deploy-sigpwny.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ on:
paths:
- '_global/**'
- '.github/**'
- '!.github/workflows/scheduled-pings.yml'
- 'sigpwny.com/**'
- 'guides'
concurrency:
Expand All @@ -19,7 +20,7 @@ jobs:
name: Deploy (sigpwny.com)
runs-on: ubuntu-latest
permissions:
contents: read
contents: write
deployments: write
steps:
- name: Check out repository code
Expand Down Expand Up @@ -59,4 +60,16 @@ jobs:
working-directory: ${{ env.CI_WORKING_DIR }}
env:
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}
DISCORD_SERVER_ID: ${{ secrets.DISCORD_SERVER_ID }}
DISCORD_SERVER_ID: ${{ secrets.DISCORD_SERVER_ID }}

- name: Schedule Discord pings
run: npm run schedule-discord-ping
if: github.ref_name == github.event.repository.default_branch
shell: bash
working-directory: ${{ env.CI_WORKING_DIR }}
- name: Save scheduled discord pings
if: github.ref_name == github.event.repository.default_branch
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "chore: update workflow schedule"
file_pattern: "*.yml"
1 change: 1 addition & 0 deletions .github/workflows/deploy-uiuctf.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
- '_global/content/events/**'
- '_global/content/profiles/**'
- '.github/**'
- '!.github/workflows/scheduled-pings.yml'
- 'uiuc.tf/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
41 changes: 35 additions & 6 deletions sigpwny.com/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions sigpwny.com/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"preview": "astro preview",
"serve": "astro preview",
"sync-discord": "npx tsx --env-file=.env src/scripts/discord.ts",
"send-discord-ping": "npx tsx --env-file=.env src/scripts/send-discord-ping.ts",
"schedule-discord-ping": "npx tsx src/scripts/schedule-discord-ping.ts",
"astro": "astro"
},
"dependencies": {
Expand All @@ -29,6 +31,7 @@
"@astrojs/tailwind": "^5.1.0",
"@floating-ui/dom": "^1.6.8",
"@floating-ui/react": "^0.26.20",
"@reteps/github-action-scheduler": "^1.0.2",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.2.25",
"astro": "^4.14.3",
Expand Down
96 changes: 96 additions & 0 deletions sigpwny.com/src/scripts/schedule-discord-ping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { scheduleJobs, Job } from '@reteps/github-action-scheduler';
import fs from 'fs';
import path from 'path';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
import duration, { type Duration } from 'dayjs/plugin/duration';
import advanced from 'dayjs/plugin/advancedFormat';
dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(duration);
dayjs.extend(advanced);


const fetchMeetings = async () => {
const meetingsPath = path.join(__dirname, '..', '..', 'dist', 'meetings', 'all.json');
if (fs.existsSync(meetingsPath)) {
const data = fs.readFileSync(meetingsPath, 'utf8');
return JSON.parse(data);
}
}

const makeJob = (meeting: Record<string, any>, beforeDuration: Duration) => {
const { data : { title, type, location, card_image, week_number, time_end, time_start, description }, body, filePath, slug } = meeting;
const url = `https://sigpwny.com${slug}`;

const formattedDuration = beforeDuration.format('D[d] H[h] m[m]');
const message = `**${title}** is in ${formattedDuration}!
${url}
`;

const runAt = time_start.subtract(beforeDuration);
const job: Job = {
time: runAt.toDate(),
name: `helper ping ${title}`,
'runs-on': 'ubuntu-latest',
steps: [
{
uses: 'actions/checkout@v4',
},
{
name: 'Use Node.js',
uses: 'actions/setup-node@v4',
with: {
'node-version': 'latest',
},
},
{
run: 'npm ci',
'working-directory': 'sigpwny.com',
},
{
run: 'npm run send-discord-ping',
'working-directory': 'sigpwny.com',
env: {
DISCORD_TOKEN: '${{ secrets.DISCORD_TOKEN }}',
DISCORD_CHANNEL_ID: '${{ vars.DISCORD_CONTENT_CHANNEL_ID }}',
DISCORD_SERVER_ID: '${{ secrets.DISCORD_SERVER_ID }}',
DISCORD_B64_MESSAGE: Buffer.from(message).toString('base64'),
}
},
],
};
return job;
}

async function main() {
const meetings = await fetchMeetings();
const upcomingMeetings = meetings.map((meeting : any) => {
return {
...meeting,
data: {
...meeting.data,
time_start: dayjs(meeting.data.time_start).tz(meeting.data.timezone),
time_end: dayjs(meeting.data.time_start).tz(meeting.data.timezone).add(dayjs.duration(meeting.data.duration)),
}
}
}).filter((meeting: any) => meeting.data.time_start > dayjs());

const pingNotice = [
dayjs.duration({ days: 1, hours: 0, minutes: 0 }),
dayjs.duration({ days: 0, hours: 1, minutes: 0 })
]

const jobs = upcomingMeetings.flatMap((meeting: any) => {
return pingNotice.map((notice) => makeJob(meeting, notice));
})

scheduleJobs(jobs, {
path: path.join(__dirname, '..', '..', '..', '.github', 'workflows', 'scheduled-pings.yml'),
check: true,
merge: false
});
}

main();
47 changes: 47 additions & 0 deletions sigpwny.com/src/scripts/send-discord-ping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Client, GatewayIntentBits, TextChannel } from 'discord.js';

async function sendDiscordPing() {
// Retrieve environment variables
const b64Message = process.env.DISCORD_B64_MESSAGE;
const channelId = process.env.DISCORD_CONTENT_CHANNEL_ID;
const serverId = process.env.DISCORD_SERVER_ID;
const token = process.env.DISCORD_TOKEN;

// Check if all required environment variables are present
if (!b64Message || !channelId || !serverId || !token) {
console.error('Missing required environment variables');
process.exit(1);
}

// Decode the base64 message
const message = Buffer.from(b64Message, 'base64').toString('utf-8');

// Create a new Discord client
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages]
});

try {
// Log in to Discord
await client.login(token);

// Fetch the server and channel
const server = await client.guilds.fetch(serverId);
const channel = await server.channels.fetch(channelId) as TextChannel;

if (!channel || !channel.isTextBased()) {
throw new Error('Invalid channel');
}

// Send the message
await channel.send(message);
console.log('Message sent successfully');
} catch (error) {
console.error('Error sending message:', error);
} finally {
// Destroy the client connection
client.destroy();
}
}

sendDiscordPing();
Loading