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


Campaign Promises


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


Data Rescue Projects


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


Immigration


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


Major Actions & Statements


Project 2025


Regulatory Changes


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

  1. Intégrez le script dans un nœud de fonction JavaScript dans N8N.

  2. 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

Trumpwatch

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:

  1. Log into your Bluesky account.
  2. Fetch all posts that match certain criteria (e.g., containing a specific domain in their facets, embeds, or entities).
  3. 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.
  • 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 a 429 Rate Limit Exceeded error, it will parse the ratelimit-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

werd.io/2024/blue…

Au fond bluesky c’est ça le reste c’est de la déco :))

l’année passée on avait mis en place un annuaire de custom feed en Français, il est dispo ici pour rajouter vos feed à l’annuaire c’est par

l'année passée on avait mis en place un annuaire de custom feed en Français, il est dispo [ici](​https://base.skyfleet.blue/public/grid/4W_lCTnwaL0S7wFwZ6zW3Yhf0byVeFD_3A8wh0Csf8g) pour rajouter vos feed à l'annuaire c'est par [là](https://base.skyfleet.blue/form/0Bmzxqsv19BNgzWuo9Ikh_zhxODTX5E8BnVKStpO2nk)

un Feed pour voir comment les utilisateurs de Bluesky interragissent avec les posts de la team Bluesky

Fascinating #bluesky graph ps : you NEED to enabe WebGPU in your browser for this site to work !

This is really neat :

How to self-host all of #Bluesky except the AppView (for now)

alice.bsky.sh/post/3lae…

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 😊

Deploy your self-hosted Bluesky PDS with or without Docker !

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 📌