mirror of
https://github.com/System-End/YSWS-Catalog.git
synced 2026-04-19 16:38:15 +00:00
Add RSS feed and GitHub Action workflow for automatic updates
This commit is contained in:
parent
242c3c4a55
commit
5612c9c601
5 changed files with 151 additions and 0 deletions
36
.github/workflows/generate-rss.yml
vendored
Normal file
36
.github/workflows/generate-rss.yml
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
name: Generate RSS Feed
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'data.yml'
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
generate-rss:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install js-yaml
|
||||
|
||||
- name: Generate RSS feed
|
||||
run: node generate-rss.js
|
||||
|
||||
- name: Commit and push if changed
|
||||
run: |
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add feed.xml
|
||||
git diff --quiet && git diff --staged --quiet || git commit -m "Update RSS feed"
|
||||
git push
|
||||
|
|
@ -12,6 +12,7 @@
|
|||
- **Deadline Indicators:** Visual indicators for program deadlines, highlighting urgent and very urgent statuses to help prioritize participation.
|
||||
- **Real-time Deadline Updates:** Deadlines are updated in real-time to reflect the current status, ensuring information is always up-to-date.
|
||||
- **Responsive Design:** Optimized for various screen sizes and devices, providing a seamless experience on desktops, tablets, and mobile devices.
|
||||
- **RSS Feed:** Subscribe to get notifications about active YSWS programs in your favorite RSS reader.
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
|
@ -34,6 +35,14 @@
|
|||
5. **Toggle Theme:**
|
||||
- Click the 🌙/☀️ button to switch between dark and light modes.
|
||||
|
||||
## RSS Feed
|
||||
|
||||
You can subscribe to updates about active YSWS programs using our RSS feed:
|
||||
|
||||
- **Feed URL**: `https://ysws.hackclub.com/feed.xml`
|
||||
|
||||
This feed is automatically updated whenever new programs are added or existing programs' statuses change. You can use this feed with any RSS reader like Feedly, Inoreader, or apps like Glance to get notified about new opportunities.
|
||||
|
||||
## Project Structure
|
||||
|
||||
- **index.html:** The main HTML file containing the container for program cards and the modal structure.
|
||||
|
|
|
|||
86
generate-rss.js
Normal file
86
generate-rss.js
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
const fs = require('fs');
|
||||
const jsyaml = require('js-yaml');
|
||||
const path = require('path');
|
||||
|
||||
function generateRSS(programs) {
|
||||
const host = 'https://ysws.hackclub.com';
|
||||
const now = new Date().toUTCString();
|
||||
|
||||
const activePrograms = Object.values(programs)
|
||||
.flat()
|
||||
.filter(program => program.status === 'active')
|
||||
.sort((a, b) => {
|
||||
if (!a.deadline) return 1;
|
||||
if (!b.deadline) return -1;
|
||||
return new Date(a.deadline) - new Date(b.deadline);
|
||||
});
|
||||
|
||||
let rss = `<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>Hack Club YSWS Programs</title>
|
||||
<link>${host}</link>
|
||||
<description>Active "You Ship, We Ship" programs from Hack Club</description>
|
||||
<language>en-us</language>
|
||||
<lastBuildDate>${now}</lastBuildDate>
|
||||
<atom:link href="${host}/feed.xml" rel="self" type="application/rss+xml" />
|
||||
`;
|
||||
|
||||
activePrograms.forEach(program => {
|
||||
const pubDate = program.pubDate ? new Date(program.pubDate).toUTCString() : now;
|
||||
const deadline = program.deadline ?
|
||||
`<p><strong>Deadline:</strong> ${new Date(program.deadline).toLocaleDateString('en-US', {
|
||||
year: 'numeric', month: 'long', day: 'numeric'
|
||||
})}</p>` : '';
|
||||
|
||||
const channelRef = program.slackChannel ? program.slackChannel.replace(/^#+/, '#') : '';
|
||||
|
||||
rss += `
|
||||
<item>
|
||||
<title>${escapeXML(program.name)}</title>
|
||||
<link>${program.website || host}</link>
|
||||
<guid isPermaLink="false">${program.name}-${Date.now()}</guid>
|
||||
<pubDate>${pubDate}</pubDate>
|
||||
<description><![CDATA[
|
||||
<p>${escapeXML(program.description)}</p>
|
||||
${deadline}
|
||||
${program.detailedDescription ? `<p>${escapeXML(program.detailedDescription)}</p>` : ''}
|
||||
${channelRef ? `<p>Join the discussion in <a href="${program.slack}">${channelRef}</a></p>` : ''}
|
||||
]]></description>
|
||||
</item>`;
|
||||
});
|
||||
|
||||
rss += `
|
||||
</channel>
|
||||
</rss>`;
|
||||
|
||||
return rss;
|
||||
}
|
||||
|
||||
function escapeXML(text) {
|
||||
if (!text) return '';
|
||||
return text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const dataFile = path.join(__dirname, 'data.yml');
|
||||
const fileContent = fs.readFileSync(dataFile, 'utf8');
|
||||
const data = jsyaml.load(fileContent);
|
||||
|
||||
const rssFeed = generateRSS(data);
|
||||
|
||||
fs.writeFileSync(path.join(__dirname, 'feed.xml'), rssFeed);
|
||||
console.log('RSS feed generated successfully!');
|
||||
} catch (error) {
|
||||
console.error('Error generating RSS feed:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="alternate" type="application/rss+xml" title="Hack Club YSWS Programs" href="/feed.xml" />
|
||||
<script>
|
||||
const favicons = [
|
||||
"logos/(ch)airtable.png",
|
||||
|
|
@ -135,6 +136,10 @@
|
|||
</div>
|
||||
<nav class="main-nav">
|
||||
<a href="https://hackclub.com/slack" target="_blank" rel="noopenner noreferrer" class="nav-link">Join Slack</a>
|
||||
<a href="/feed.xml" target="_blank" rel="noopenner noreferrer" class="nav-link rss-link">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 11a9 9 0 0 1 9 9"></path><path d="M4 4a16 16 0 0 1 16 16"></path><circle cx="5" cy="19" r="1"></circle></svg>
|
||||
RSS Feed
|
||||
</a>
|
||||
<a href="https://github.com/hackclub/YSWS-Catalog" target="_blank" rel="noopenner noreferrer" class="nav-link">GitHub</a>
|
||||
<button class="theme-toggle" id="theme-toggle" aria-label="Toggle dark mode">🌙</button>
|
||||
</nav>
|
||||
|
|
|
|||
15
styles.css
15
styles.css
|
|
@ -1914,3 +1914,18 @@ body.modal-open {
|
|||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
.rss-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.rss-link svg {
|
||||
color: var(--primary);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.rss-link:hover svg {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue