Category: Bluesky
An elected regime, how to track the Trump Administration
How to Track the Trump Administration
As the Trump administration implements numerous changes that could undermine the federal state and democracy, staying informed is key. Below is a comprehensive list of tools and trackers that cover various aspects of the administration’s actions—from budgetary control to environmental rollbacks. Use these resources to hold the administration accountable and build a stronger, more transparent democracy.
Apportionment
- OpenOMB (via Protect Democracy)
Tracks how the president, through the Office of Management and Budget, implements Congress’s spending laws.
Cabinet / Appointees
- Trump Cabinet confirmation status: Which nominees have been confirmed? (via AP)
- Trump Appointees’ Corporate Conflicts of Interest (via Public Citizen)
These trackers monitor confirmation status, prior employment, and corporate ties of administration appointees.
Campaign Promises
- MAGA-Meter: Trump’s Second Term (via Politifact)
Follow and rate Trump’s campaign promises to see if they’re being fulfilled.
Climate / Environment
- Climate & Clean Energy Rollback Tracker (via Climate Action Campaign)
Tracks actions aimed at rolling back or weakening key climate policies. - Climate Backtracker (via Sabin Center)
Identifies steps taken to scale back or eliminate federal climate mitigation measures. - Federal Environmental Justice Tracker (via Harvard Law School)
Monitors policies and regulations that affect communities’ exposure to environmental pollution. - Inflation Reduction Act Tracker (via Sabin Center & Environmental Defense Fund)
Tracks changes in the status of climate programs established under the Inflation Reduction Act. - Silencing Science Tracker (via Sabin Center & Climate Science Legal Defense Fund)
Monitors anti-science actions and efforts to undermine environmental policy.
Congressional Response
- U.S. House votes 2025: Is Your Rep Standing Up to Trump? (via Jonathan Cohn)
Tracks every vote in the US House and highlights how often representatives align with Trump’s agenda.
Data Rescue Projects
- Data Rescue Tracker (via Data Rescue Project)
Also see the Bluesky version and the original crowd-sourced Google document.
Executive Orders
- Tracking Trump’s executive actions (via CNN)
Monitors executive orders, proclamations, and memos issued by the administration. - Tracking the Legal Showdown Over Trump’s Executive Orders (via US News & World Report)
Follows lawsuits challenging some of Trump’s most significant executive orders.
Federal Policy
- Federal Policy Watch (via Economic Policy Institute)
Tracks how the Trump administration, Congress, and the courts are affecting workers' quality of life.
Health Care
- Health Care Sabotage Tracker (via Protect Our Care)
Monitors all of the ways Trump’s policies target health care services.
Immigration
- Immigration Policy Tracking Project (via Professor Lucas Guttentag with teams of Stanford/Yale law students & national immigration experts)
Catalogues known Trump administration immigration policies, complete with source documents. - Tracking Notable Executive Branch Action during the Second Trump Administration (via American Immigration Lawyers Association)
Tracks select changes to immigration-related regulations and policies.
LGBTQ+
- Trump Accountability Tracker (via GLAAD)
Monitors Trump’s LGBTQ record, including executive orders, legislative support, nominations, and statements. - HRC’s Accountability Tracker (via Human Rights Campaign)
Tracks legal and policy threats impacting LGBTQ+ rights from all three federal branches.
Litigation
- Civil Rights Litigation Clearinghouse
Tracks actions related to immigration, civil service, anti-discrimination law, challenges to presidential authority, and more. - Litigation Tracker: Legal Challenges to Trump Administration Actions (via Just Security)
Summarizes legal challenges to the Trump administration’s actions with detailed case information.
Major Actions & Statements
- All of the Trump Administration’s Major Moves in the First __ Days (via New York Times)
Tracks major actions and significant statements during the first 100 days of the term.
(Filter by category and type of action/announcement.) - Tracking Trump – updates on the presidency’s first 100 days (via The Guardian)
Provides a guide to the major developments of the first 100 days, updated every Monday.
Project 2025
- Project 2025 Executive Action Tracker (via Center for Progressive Reform)
Direct link to the tracker document
Tracks the implementation of Project 2025 across 20 federal agencies.
Regulatory Changes
- Regulatory Tracker (via Harvard Law School)
Monitors regulatory and litigation actions related to clean energy deployment and environmental protection. - Tracking regulatory changes in the second Trump administration (via Brookings)
Follow new, delayed, or repealed rules, key guidance, and policy revocations across several policy areas.
Together, these resources empower you to monitor, analyze, and respond to the sweeping changes of the Trump administration. By staying informed and using these tools, we can collectively fight back against the administration’s destructive policies and protect democracy.
Spread the word and build upon these tools to defend democracy!
Un compteur pour déterminer quand Trump va être dégagé (ou pas)
Documentation du Script N8N
Description
Ce script JavaScript est conçu pour N8N afin de calculer et de publier quotidiennement des décomptes avant des événements politiques majeurs aux États-Unis, à savoir :
- Les Midterms (élections de mi-mandat).
- L'élection présidentielle.
- Le jour de l’investiture.
Il génère également une barre de progression graphique pour chaque événement sous forme de texte.
Fonctionnalités
1. Définition des dates clés
Le script définit les dates des événements cibles :
- Midterms : 3 novembre 2026.
- Élection présidentielle : 7 novembre 2028.
- Jour de l’investiture : 20 janvier 2029.
2. Calcul des jours restants
Le script calcule :
- Le nombre total de jours entre aujourd’hui et chaque événement.
- Le pourcentage de progression en fonction des jours écoulés.
3. Génération de barres de progression
Une fonction génère une barre de progression graphique, composée de blocs pleins (█
) et de blocs vides (▒
), représentant visuellement l’avancée jusqu’à l’événement.
4. Génération et publication du message
Le script produit un message comprenant :
- Le décompte des jours restants pour chaque événement.
- Les barres de progression associées.
Exemple de Résultat
Voici un exemple du message généré :
There are 646 days until the Midterms, 1381 days until the next Presidential Election, and 1490 days until the next Inauguration Day.
Midterms Progress: █▒▒▒▒▒▒▒▒▒ 9%
Presidential Election Progress: █▒▒▒▒▒▒▒▒▒ 4%
Until Inauguration: ▒▒▒▒▒▒▒▒▒▒ 0%
Code
// JavaScript code for N8N to calculate and post daily countdowns with a graphical loading bar
// Define the reference start date (Trump's 2025 inauguration)
const startOfMandate = new Date('2025-01-20T00:00:00Z');
// Define the target dates
const midtermsDate = new Date('2026-11-03T00:00:00Z'); // Next USA Midterms
const presidentialElectionDate = new Date('2028-11-07T00:00:00Z'); // Next Presidential Election
const inaugurationDate = new Date('2029-01-20T00:00:00Z'); // Next Inauguration Day
// Get the current date
const currentDate = new Date();
// Function to calculate correct progress
function calculateProgress(targetDate) {
const totalDays = Math.ceil((targetDate - startOfMandate) / (1000 * 60 * 60 * 24));
const elapsedDays = Math.ceil((currentDate - startOfMandate) / (1000 * 60 * 60 * 24));
return Math.min(100, Math.max(0, Math.floor((elapsedDays / totalDays) * 100)));
}
// Calculate days remaining
const daysUntilMidterms = Math.ceil((midtermsDate - currentDate) / (1000 * 60 * 60 * 24));
const daysUntilPresidentialElection = Math.ceil((presidentialElectionDate - currentDate) / (1000 * 60 * 60 * 24));
const daysUntilInauguration = Math.ceil((inaugurationDate - currentDate) / (1000 * 60 * 60 * 24));
// Calculate accurate progress percentages
const midtermsProgress = calculateProgress(midtermsDate);
const presidentialProgress = calculateProgress(presidentialElectionDate);
const inaugurationProgress = calculateProgress(inaugurationDate);
// Create a graphical loading bar function
function createLoadingBar(percentage) {
const totalBars = 10; // Length of the loading bar
const filledBars = Math.floor((percentage / 100) * totalBars);
const emptyBars = totalBars - filledBars;
return `${'█'.repeat(filledBars)}${'▒'.repeat(emptyBars)} ${percentage}%`;
}
// Generate the loading bars
const midtermsLoadingBar = createLoadingBar(midtermsProgress);
const presidentialLoadingBar = createLoadingBar(presidentialProgress);
const inaugurationLoadingBar = createLoadingBar(inaugurationProgress);
// Generate the message
const message = `There are ${daysUntilMidterms} days until the Midterms, ${daysUntilPresidentialElection} days until the next Presidential Election, and ${daysUntilInauguration} days until the next Inauguration Day.\n\n` +
`Midterms Progress: \n${midtermsLoadingBar}\n\n` +
`Presidential Election Progress: \n${presidentialLoadingBar}\n\n` +
`Inauguration Progress: \n${inaugurationLoadingBar}`;
// Output the message
return [{
json: {
message,
},
}];
Où il publie
Le script retourne le message sous forme d’un objet JSON, prêt à être utilisé dans un flux N8N pour une publication quotidienne via un nœud horaire configuré.
Configuration Recommandée
- Fuseau horaire du serveur : CET (heure allemande).
- Heure de publication : 14h00 CET, correspondant à 8h00 ET (heure de la côte Est des États-Unis).
Utilisation
-
Intégrez le script dans un nœud de fonction JavaScript dans N8N.
-
Ajoutez un nœud horaire configuré pour exécuter le flux quotidiennement.3. Reliez le nœud de fonction à un nœud de sortie ou à un service tiers pour publier le message (par exemple Bluesky.).
Résultat
Setting up a Bluesky PDS Details on setting up a Bluesky PDS with S3 for blob storage, Mailgun for SMTP, and a Ubuntu VM. By @jaredallard.dev
Bluesky Won’t Save Us Like radiation, social media is invisible scientific effluence that leaves us both more knowledgeable and more ignorant of the causes of our own afflictions than ever
#bluesky #moderation #mastodon
#Bluesky et L’affaire Singal by @FaineG
How to Bulk Delete Bluesky Posts With Rate Limit Management
In some cases, you may find that you need to bulk-delete many posts from your Bluesky account. For example, perhaps you shared many links to a particular domain and now you want to remove them en masse. Doing this manually would be tedious. Fortunately, we can automate the process using a script written in TypeScript.
This script leverages the official @atproto/api
package to:
- Log into your Bluesky account.
- Fetch all posts that match certain criteria (e.g., containing a specific domain in their facets, embeds, or entities).
- Delete them in batches while respecting and reacting to rate limits.
Key Features
-
Domain-based Filtering:
The script identifies posts containing a specific domain by checking:- Facets with
app.bsky.richtext.facet#link
. - External embeds with
app.bsky.embed.external
. - Legacy entities with
type: link
.
- Facets with
-
Rate Limit Management (Proactive):
The Bluesky PDS imposes a rate limit of 5000 deletion points per hour. Deletions cost 1 point each. The script proactively monitors how many deletions it has performed within the current hour. When it approaches the limit, it waits until the hour has elapsed before continuing. -
Rate Limit Management (Fallback):
If the script ever hits a429 Rate Limit Exceeded
error, it will parse theratelimit-reset
header and wait until the given time before retrying that batch of deletions. This ensures that if the proactive limit check is not enough, the script still handles the server’s instructions gracefully. -
Batch Operations and Delays:
To avoid rapid-fire requests, the script:- Performs deletions in configurable batch sizes (default: 200 per batch).
- Waits a short delay between batches to spread requests out over time.
Prerequisites
-
Node.js and npm:
Ensure you have a recent version of Node.js installed. -
Install Dependencies:
npm install @atproto/api p-ratelimit
Credentials
Replace your-handle and your-password in the script with your Bluesky account credentials. You should only do this with an account you control and trust running scripts on.
Running the Script
Save the script below as bluesky-sweep.ts.
Run it using:
npx ts-node bluesky-sweep.ts
Configuration Parameters
- TARGET_DOMAIN: Set this to the domain you want to search for in your posts.
- DELETES_PER_BATCH: Number of posts per deletion batch.
- MAX_DELETES_PER_HOUR: Maximum deletions allowed per hour (5000 is the current default from Bluesky).
- SAFE_MARGIN: A buffer to start waiting before hitting the exact limit.
- DELAY_BETWEEN_BATCHES_MS: Milliseconds to wait between each batch.
/**
* Bulk Delete Bluesky Posts with Domain Filtering and Rate Limit Management
*
* This script:
* - Logs in to a Bluesky account.
* - Fetches posts containing a specified domain via facets, embeds, or entities.
* - Deletes them in batches, respecting and reacting to rate limits.
*
* Adjust the constants below to fit your needs before running.
*/
import { BskyAgent } from '@atproto/api';
import { pRateLimit } from 'p-ratelimit';
const VERBOSE = false;
const TARGET_DOMAIN = 'futura-sciences.com';
// Known limit and configurations
const MAX_DELETES_PER_HOUR = 5000;
const DELETES_PER_BATCH = 200;
const DELAY_BETWEEN_BATCHES_MS = 5000; // 5 seconds between batches
const SAFE_MARGIN = 100; // Start waiting before we hit exactly 5000
(async () => {
const agent = new BskyAgent({ service: 'https://bsky.social' });
await agent.login({
identifier: 'your-handle',
password: 'your-password',
});
console.log(`Logged in as ${agent.session!.handle} (${agent.session!.did})`);
const limit = pRateLimit({ concurrency: 3, interval: 1000, rate: 5 });
const getRecordId = (uri: string) => {
const idx = uri.lastIndexOf('/');
return uri.slice(idx + 1);
};
const chunked = <T>(arr: T[], size: number): T[][] => {
const chunks: T[][] = [];
for (let idx = 0; idx < arr.length; idx += size) {
chunks.push(arr.slice(idx, idx + size));
}
return chunks;
};
const sleep = (ms: number) => new Promise((res) => setTimeout(res, ms));
let deletes: any[] = [];
let cursor: string | undefined;
let batchCount = 0;
// Fetch posts
do {
console.log(`Fetching records (cursor: ${cursor || 'none'})...`);
const response = await limit(() =>
agent.api.com.atproto.repo.listRecords({
repo: agent.session!.did,
collection: 'app.bsky.feed.post',
limit: 100,
cursor,
reverse: true,
})
);
cursor = response.data.cursor;
batchCount++;
console.log(`Processing batch #${batchCount}, ${response.data.records.length} records fetched`);
for (const record of response.data.records) {
if (VERBOSE) console.log(`\nChecking record URI: ${record.uri}`);
const val = record.value as any;
let found = false;
// Check facets for links
const facets = val?.facets || [];
for (const facet of facets) {
const features = facet.features || [];
for (const feature of features) {
if (feature.$type === 'app.bsky.richtext.facet#link' && feature.uri.includes(TARGET_DOMAIN)) {
if (VERBOSE) console.log(`Found target domain in facet link: ${feature.uri}`);
found = true;
break;
}
}
if (found) break;
}
// Check embed if not found yet
if (!found && val?.embed) {
const embed = val.embed;
if (embed.$type === 'app.bsky.embed.external' && embed.external?.uri?.includes(TARGET_DOMAIN)) {
if (VERBOSE) console.log(`Found target domain in embed: ${embed.external.uri}`);
found = true;
}
}
// Check entities (legacy) if not found yet
if (!found && val?.entities && Array.isArray(val.entities)) {
for (const entity of val.entities) {
if (entity.type === 'link' && entity.value.includes(TARGET_DOMAIN)) {
if (VERBOSE) console.log(`Found target domain in entities link: ${entity.value}`);
found = true;
break;
}
}
}
if (found) {
deletes.push({
$type: 'com.atproto.repo.applyWrites#delete',
collection: 'app.bsky.feed.post',
rkey: getRecordId(record.uri),
});
}
}
} while (cursor);
console.log(`\nFound ${deletes.length} posts containing '${TARGET_DOMAIN}'`);
if (deletes.length === 0) {
console.log('No posts to delete.');
return;
}
const chunkedDeletes = chunked(deletes, DELETES_PER_BATCH);
console.log(`Deletion can be done in ${chunkedDeletes.length} batched operations`);
let hourWindowStart = Date.now();
let deletesThisHour = 0;
for (let idx = 0; idx < chunkedDeletes.length; idx++) {
const chunk = chunkedDeletes[idx];
// Check if we're near the hourly limit
if (deletesThisHour + chunk.length > (MAX_DELETES_PER_HOUR - SAFE_MARGIN)) {
const now = Date.now();
const elapsed = now - hourWindowStart;
const oneHourMs = 3600000;
if (elapsed < oneHourMs) {
const waitTime = oneHourMs - elapsed;
console.log(`Approaching hourly limit. Waiting ${Math.ceil(waitTime / 60000)} minutes to reset.`);
await sleep(waitTime);
}
hourWindowStart = Date.now();
deletesThisHour = 0;
}
console.log(`Deleting batch #${idx + 1} with ${chunk.length} posts...`);
// Retry loop in case of rate limit errors
let success = false;
while (!success) {
try {
await limit(() =>
agent.api.com.atproto.repo.applyWrites({
repo: agent.session!.did,
writes: chunk,
})
);
console.log(`Batch operation #${idx + 1} completed`);
success = true;
} catch (error: any) {
if (error.status === 429) {
console.warn('Rate limit exceeded, checking headers to wait until reset...');
const resetTimeStr = error.headers?.['ratelimit-reset'];
let waitSeconds = 60; // default wait
if (resetTimeStr) {
const resetTime = parseInt(resetTimeStr, 10);
const now = Math.floor(Date.now() / 1000);
const diff = resetTime - now;
if (diff > 0) {
waitSeconds = diff;
}
}
console.log(`Waiting ${waitSeconds} seconds before retrying...`);
await sleep(waitSeconds * 1000);
console.log('Retrying this batch...');
} else {
console.error(`Error performing batch #${idx + 1}:`, error);
// If it's a non-rate-limit error, stop the process
break;
}
}
}
if (success) {
deletesThisHour += chunk.length;
await sleep(DELAY_BETWEEN_BATCHES_MS);
} else {
// If we failed without rate limit handling, break out
break;
}
}
console.log('Done');
})();
Notes
Rate Limits
Post Structure
Gist
Code
Take and or delete your data and Leave X
cyd.social is now available! #Xodus
Join #Bluesky or #Mastodon instead.
We are the “social graph”, whereever we go.
Hmm libstc.cc #doi #library
Bluesky, AI, and the battle for consent on the open web
Au fond bluesky c’est ça le reste c’est de la déco :))
un Feed pour voir comment les utilisateurs de Bluesky interragissent avec les posts de la team Bluesky
This is really neat :
How to self-host all of #Bluesky except the AppView (for now)
The future is fragmented, decentralized, so I’m publishing from my own blog and cross-posting to several platforms at once, this is a test for #Threads, having already connected #mastodon #bluesky #nostr #linkedin
New safety tools in Bluesky
Detach quote posts from your original post Hide replies Filter your notifications to only people you follow
#bluesky #moderation #safety
The way I see it evolve and broaden its usecases, the labels/moderation systems in Bluesky is light years ahead of what any other network is doing.
It puts users in charge of what they want to see or not, it doesn’t solve the entire issue of moderation but it’s a step in the right direction.
These two articles, part 1 and part 2 are such fascinating read 🤩 by @jaz.bsky.social
I don’t understand everything but I’m always in awe at this kind of implementation and anything related to graph databases and social networks.
Je repassais sur le wiki Bluesky en me disant, il y a tellement de chose à adapter dans les tutos sur les feed 😅
hmmm that’s new right? I can see all my #mastodon and #bluesky notifications from within the #microblog android app 😊
Bluesky is now open to everyone! without Invites! #atproto #bluesky
Interesting… on why Bluesky isn’t p2p
#p2p #dat #ipfs #ssb pfrazee.com/blog/why-…
un outil par mary.my.id qui vous permet d’archiver facilement vos publications Bluesky !
Une fois généré, vous pouvez l’héberger en tant que site Web autonome que les gens peuvent voir ou garder l’archive en privé ! L’outil est conçu pour les deux cas de figure 📌