diceline-chartmagnifiermouse-upquestion-marktwitter-whiteTwitter_Logo_Blue

Today I Learned

TIL How to Batch Compress PDF Files Using Ghostscript

brew install ghostscript
#!/bin/bash
[ $# -lt 3 ] && { echo "Usage: $0 /input_dir /output_dir /quality"; exit 1; }
input_dir="$1"; output_dir="$2"; quality="$3"
mkdir -p "$output_dir"
for file in "$input_dir"/*.pdf; do
  base=$(basename "$file" .pdf)
  gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS="$quality" -dNOPAUSE -dQUIET -dBATCH -sOutputFile="$output_dir/${base}_compressed.pdf" "$file"
done
./compress_pdfs.sh /path/to/input /path/to/output /quality_setting

Quality options: /screen, /ebook, /printer, /prepress.

Say goodbye to online pdf converters.

TIL: How to Quickly Check Which AWS Regions Support SES Using a Bash Script

Although it has improved lately for some services, AWS is still notoriously unfriendly when it comes to checking which services are activated and running across different regions. Here's a script you can run in the console to quickly see which regions have SES (Simple Email Service) available:

#!/bin/bash
for region in $(aws ec2 describe-regions --query "Regions[].RegionName" --output text); do
    echo "Checking SES in region: $region"
    if output=$(aws ses get-send-quota --region $region 2>&1); then
        echo "SES is active in region: $region"
        echo "$output"
    else
        echo "SES is not available in region: $region"
    fi
    echo "---------------------------------------"
done

This script loops through all AWS regions and checks if SES is running in each one, giving you a quick and easy overview of SES availability.

The output:

Checking SES in region: us-east-1
SES is active in region: us-east-1
{
    "Max24HourSend": 50000.0,
    "MaxSendRate": 14.0,
    "SentLast24Hours": 0.0
}
---------------------------------------
Checking SES in region: us-west-1
SES is not available in region: us-west-1
---------------------------------------
Checking SES in region: eu-west-1
SES is active in region: eu-west-1
{
    "Max24HourSend": 50000.0,
    "MaxSendRate": 10.0,
    "SentLast24Hours": 0.0
}
---------------------------------------

Fastest way to delete a folder structure in Linux

The problem

Deleting a huge folder structure is a pain and can take forever. However if you want to take forever divided by 3, you can use rsync.

It seems rsync is 3 time faster when deleting a huge folder structure than rm or find because it doesn't read the files before deleting.

The trick

  • Create an empty folder in /tmp/empty_folder
  • Run the command:

rsync -aP --delete ./empty_folder/ ./target_folder/


Enjoy!

MUI Tooltip overflow problem

If you're encountering an inexplicable overflow issue with the Tooltip component in Material-UI on hover, here's a solution that might help.

First, make sure you have popper.js installed using the following command:

npm install --save-dev @types/popper.js

Next, in the component containing Tooltip, add the following imports:

import { OptionsGeneric } from '@popperjs/core';

Then, update your Tooltip usage as follows:

<Tooltip
  title={'Some text'}
  PopperProps={{
    disablePortal: true,
    popperOptions: {
      modifiers: [
        {
          name: 'preventOverflow',
          options: {
            enabled: true,
            boundariesElement: 'window',
          },
        },
      ] as OptionsGeneric<any>['modifiers'],
    },
  }}
  aria-label='Some text'
>
  {/* ... your content ... */}
</Tooltip>

This configuration adds Popper options to handle overflow.

HTTP pools - Laravel HTTP client

In PHP, unlike JavaScript, we don't have native support for Promises or asynchronous programming. This limitation can become apparent when dealing with multiple HTTP requests that need to be made simultaneously. However, the Http::pool method, as shown in the code snippet, offers a workaround by allowing us to leverage parallel processing.

The code uses the HTTP pools functionality provided by the Laravel HTTP client, which is a convenient way to execute multiple HTTP requests concurrently. Here's an expanded explanation of the code:

//dummy code

$responses = Http::pool(fn (Pool $pool) => [
    $pool->get("https://jsonplaceholder.typicode.com/todos/1"),
    $pool->get("https://jsonplaceholder.typicode.com/users/1"),
    $pool->get("https://jsonplaceholder.typicode.com/posts/1")
]);

$todoInfo = $responses[0]->json();
$userInfo = $responses[1]->json();
$postInfo = $responses[2]->json();

This code snippet demonstrates how to make three (or more) simultaneous HTTP calls to different endpoints using HTTP pools in PHP. In a specific situation on the project I'm working on, this approach significantly reduced the load time from 3 seconds to 1.1 seconds.

Transfer TB of files in the background via rsync and tmux on linux

Problem

Transfering files in the background via rsync is possible via nohup command and some other workarounds.

These don't really work when your transfer takes days (>50TB of data) because the background job might get killed by the system.

In order to create a persistent session we need to use tmux.

Solution

Authentication

Create a ssh key and upload it to the server you want to transfer from.

ssh-keygen -t ed25519
ssh-copy-id -i ~/.ssh/id_rsa.pub [your_old_server.domain.com]

Create a new session and run rsync

tmux new -s [your_session_name]

rsync --avhPW --stats [your_old_server.domain.com]:[/source/path/] [/destination/path]

Detach from session

Press CTRL+B and then D. You session will detach and run in background.

Re-attach session

To get back into your session just:

tmux a -t [your_session_name]

That's it.

How to dynamically infer TypeScript single object types from tRPC query outputs

This is how you can dynamically infer a single object type from a tRPC Query returning an array of elements of that specific type:

export const exampleRouter = router({
  exampleQuery: exampleQueryImplementation,
});

// extracting a single object type from an array of that type 
export type ArrayElement<ArrayType extends unknown[] | null> =
  ArrayType extends (infer ElementType)[] ? ElementType : never;

// the output types of a specific router, indexable by query identifiers
type RouterOutput = inferRouterOutputs<typeof exampleRouter>;

// return type of a single query
export type QueryOutputArray = RouterOutput['exampleQuery'];

// the type of each element from the returned array
export type QueryOutputObject = ArrayElement<QueryOutputArray>;

How To Change The Slug of A Custom Post Type in WordPress

To change the slug for a post type in WordPress, you can use the register_post_type() function. Within the arguments array for the function, you can set the rewrite parameter to an array with the new slug you want to use.

Here's an example code snippet:

function change_post_type_slug() {
    $args = array(
        'rewrite' => array( 'slug' => 'new-slug' ),
        // other post type arguments
    );
    register_post_type( 'your_post_type', $args );
}
add_action( 'init', 'change_post_type_slug' );

In this example, replace your_post_type with the name of the post type you want to change, and replace new-slug with the new slug you want to use.

Once you've added this code to your functions.php file, you'll need to go to Settings > Permalinks in the WordPress admin dashboard and click the "Save Changes" button to update your permalinks. This will ensure that your new slug is properly applied.