189 lines
7.9 KiB
JavaScript
189 lines
7.9 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Script to update campaign call-to-action text with correct minister titles
|
|
* Run with: node scripts/update-campaigns.js
|
|
*/
|
|
|
|
const https = require('https');
|
|
|
|
// NocoDB Configuration
|
|
const NOCODB_API_URL = 'https://db.freealberta.org';
|
|
const NOCODB_API_TOKEN = 'H3z5PEgvrC25LDRuvRpF1wuzsByG9PCem5DHyjPj';
|
|
const PROJECT_ID = 'plc0u50kgobr2xh';
|
|
const CAMPAIGNS_TABLE_ID = 'mh98emvhot9gjrg';
|
|
|
|
// Campaign updates - mapping slug to correct call-to-action text
|
|
const campaignUpdates = [
|
|
// Indigenous Relations - now Rajan Sawhney
|
|
{ slug: 'indigenous-relations', call_to_action: 'Email Minister of Indigenous Relations' },
|
|
{ slug: 'land-rights', call_to_action: 'Email Minister of Indigenous Relations' },
|
|
{ slug: 'landback', call_to_action: 'Email Minister Responsible for Landback' },
|
|
|
|
// Municipal Affairs - now Dan Williams
|
|
{ slug: 'land-use', call_to_action: 'Email Minister of Municipal Affairs' },
|
|
{ slug: 'municipal-transit', call_to_action: 'Email Minister of Municipal Affairs' },
|
|
{ slug: 'gathering-spaces-municipal', call_to_action: 'Email Minister of Municipal Affairs' },
|
|
|
|
// Environment - now Grant Hunter
|
|
{ slug: 'environment-protection', call_to_action: 'Email Minister of Environment and Protected Areas' },
|
|
{ slug: 'water-protection', call_to_action: 'Email Minister of Environment and Protected Areas' },
|
|
{ slug: 'air-quality-protection', call_to_action: 'Email Minister of Environment and Protected Areas' },
|
|
|
|
// Mental Health and Addiction - now Rick Wilson
|
|
{ slug: 'mental-health', call_to_action: 'Email Minister of Mental Health and Addiction' },
|
|
{ slug: 'mental-health-rest', call_to_action: 'Email Minister of Mental Health and Addiction' },
|
|
{ slug: 'love-williams', call_to_action: 'Email Minister of Mental Health and Addiction' },
|
|
|
|
// Advanced Education - now Myles McDougall
|
|
{ slug: 'higher-education', call_to_action: 'Email Minister of Advanced Education' },
|
|
{ slug: 'higher-learning', call_to_action: 'Email Minister of Advanced Education' },
|
|
|
|
// Jobs, Economy, Trade and Immigration - now Joseph Schow
|
|
{ slug: 'economic-reform', call_to_action: 'Email Minister of Jobs, Economy, Trade and Immigration' },
|
|
{ slug: 'career-transition', call_to_action: 'Email Minister of Jobs, Economy, Trade and Immigration' },
|
|
{ slug: 'work-life', call_to_action: 'Email Minister of Jobs, Economy, Trade and Immigration' },
|
|
{ slug: 'association-rights-jobs', call_to_action: 'Email Minister of Jobs, Economy, Trade and Immigration' },
|
|
|
|
// Tourism and Sport - now Andrew Boitchenko
|
|
{ slug: 'corporate-oversight', call_to_action: 'Email Minister of Tourism and Sport' },
|
|
{ slug: 'public-spaces', call_to_action: 'Email Minister of Tourism and Sport' },
|
|
{ slug: 'recreation-tourism', call_to_action: 'Email Minister of Tourism and Sport' },
|
|
|
|
// Assisted Living and Social Services - now Jason Nixon (updated title)
|
|
{ slug: 'social-support', call_to_action: 'Email Minister of Assisted Living and Social Services' },
|
|
{ slug: 'food-access', call_to_action: 'Email Minister of Assisted Living and Social Services' },
|
|
{ slug: 'water-access', call_to_action: 'Email Minister of Assisted Living and Social Services' },
|
|
{ slug: 'seniors-housing', call_to_action: 'Email Minister of Assisted Living and Social Services' },
|
|
|
|
// Associate Minister of Multiculturalism - Muhammad Yaseen (not full minister)
|
|
{ slug: 'immigration-rights', call_to_action: 'Email Associate Minister of Multiculturalism' },
|
|
{ slug: 'cultural-association-rights', call_to_action: 'Email Associate Minister of Multiculturalism' },
|
|
|
|
// Public Safety and Emergency Services - Mike Ellis (updated title)
|
|
{ slug: 'police-accountability', call_to_action: 'Email Minister of Public Safety and Emergency Services' },
|
|
{ slug: 'anti-corruption', call_to_action: 'Email Minister of Public Safety and Emergency Services' },
|
|
{ slug: 'assembly-rights', call_to_action: 'Email Minister of Public Safety and Emergency Services' },
|
|
|
|
// Energy and Minerals - Brian Jean (updated title)
|
|
{ slug: 'clean-energy', call_to_action: 'Email Minister of Energy and Minerals' },
|
|
{ slug: 'energy-reform', call_to_action: 'Email Minister of Energy and Minerals' },
|
|
|
|
// Education and Childcare - Demetrios Nicolaides (updated title)
|
|
{ slug: 'education-reform', call_to_action: 'Email Minister of Education and Childcare' },
|
|
{ slug: 'learning-access', call_to_action: 'Email Minister of Education and Childcare' },
|
|
|
|
// Transportation and Economic Corridors - Devin Dreeshen (updated title)
|
|
{ slug: 'transport-reform', call_to_action: 'Email Minister of Transportation and Economic Corridors' },
|
|
|
|
// Agriculture and Irrigation - RJ Sigurdson (updated title)
|
|
{ slug: 'food-security', call_to_action: 'Email Minister of Agriculture and Irrigation' },
|
|
|
|
// Service Alberta and Red Tape Reduction - Dale Nally (updated title)
|
|
{ slug: 'public-services-reform', call_to_action: 'Email Minister of Service Alberta and Red Tape Reduction' },
|
|
{ slug: 'telecom-reform', call_to_action: 'Email Minister of Service Alberta and Red Tape Reduction' },
|
|
|
|
// Affordability and Utilities - Nathan Neudorf
|
|
{ slug: 'utilities-reform', call_to_action: 'Email Minister of Affordability and Utilities' },
|
|
];
|
|
|
|
// Get campaign by slug
|
|
async function getCampaignBySlug(slug) {
|
|
return new Promise((resolve, reject) => {
|
|
const options = {
|
|
hostname: 'db.freealberta.org',
|
|
port: 443,
|
|
path: `/api/v1/db/data/v1/${PROJECT_ID}/${CAMPAIGNS_TABLE_ID}?where=(Campaign%20Slug,eq,${slug})`,
|
|
method: 'GET',
|
|
headers: {
|
|
'xc-token': NOCODB_API_TOKEN
|
|
}
|
|
};
|
|
|
|
const req = https.request(options, (res) => {
|
|
let data = '';
|
|
res.on('data', chunk => data += chunk);
|
|
res.on('end', () => {
|
|
try {
|
|
const result = JSON.parse(data);
|
|
resolve(result.list && result.list.length > 0 ? result.list[0] : null);
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
});
|
|
req.on('error', reject);
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
// Update campaign
|
|
async function updateCampaign(id, updates) {
|
|
return new Promise((resolve, reject) => {
|
|
const postData = JSON.stringify(updates);
|
|
|
|
const options = {
|
|
hostname: 'db.freealberta.org',
|
|
port: 443,
|
|
path: `/api/v1/db/data/v1/${PROJECT_ID}/${CAMPAIGNS_TABLE_ID}/${id}`,
|
|
method: 'PATCH',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'xc-token': NOCODB_API_TOKEN,
|
|
'Content-Length': Buffer.byteLength(postData)
|
|
}
|
|
};
|
|
|
|
const req = https.request(options, (res) => {
|
|
let data = '';
|
|
res.on('data', chunk => data += chunk);
|
|
res.on('end', () => {
|
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
resolve({ success: true });
|
|
} else {
|
|
reject(new Error(`Failed: ${res.statusCode} - ${data}`));
|
|
}
|
|
});
|
|
});
|
|
req.on('error', reject);
|
|
req.write(postData);
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
async function main() {
|
|
console.log(`Updating ${campaignUpdates.length} campaigns with correct minister info...`);
|
|
console.log('='.repeat(60));
|
|
|
|
let successCount = 0;
|
|
let failCount = 0;
|
|
let notFoundCount = 0;
|
|
|
|
for (const update of campaignUpdates) {
|
|
try {
|
|
const campaign = await getCampaignBySlug(update.slug);
|
|
|
|
if (!campaign) {
|
|
console.log(`⚠ Not found: ${update.slug}`);
|
|
notFoundCount++;
|
|
continue;
|
|
}
|
|
|
|
const id = campaign.Id || campaign.ID || campaign.id;
|
|
await updateCampaign(id, { 'Call to Action': update.call_to_action });
|
|
console.log(`✓ Updated: ${update.slug} → "${update.call_to_action}"`);
|
|
successCount++;
|
|
|
|
// Small delay
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
} catch (error) {
|
|
console.error(`✗ Failed: ${update.slug} - ${error.message}`);
|
|
failCount++;
|
|
}
|
|
}
|
|
|
|
console.log('='.repeat(60));
|
|
console.log(`Done! Updated: ${successCount}, Failed: ${failCount}, Not found: ${notFoundCount}`);
|
|
}
|
|
|
|
main().catch(console.error);
|