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
}
---------------------------------------

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.

How to Configure Traefik to Use Existing TLS Certificates

  1. Create a new file tls.yml
tls:
  stores:
    default:
      defaultCertificate:
        certFile: /etc/traefik/certs/your-domain.dev/cert.pem
        keyFile: /etc/traefik/certs/your-domain.dev/privkey.pem
  1. Make sure you're copying this file in your Dockerfile

COPY .docker/traefik/conf.d/tls.yml /etc/traefik/tls.yml

  1. Mount the certs folder in your docker-compose.yml file
volumes:
  ...
	- .docker/traefik/certs:/etc/traefik/certs
  ...
  1. Update the traefik.yml config to support the file provider:
providers:
		...
    file:
      filename: "/etc/traefik/tls.yml
    ...

How To Keep Your Github Actions Workflows Private in an Open Source Repository

If you want to make your repository open source, but keep the workflows private, you can do the following:

  1. Create a separate repository for your workflows and make it private.
  2. In the open source repository, include only the necessary configuration files (e.g. .github/actions) and reference the private repository as a submodule.
  3. In the private repository, configure the GitHub Actions workflows as you normally would.
  4. When someone clones or forks the open source repository, the submodule reference to the private repository will not be included.

This way, you can keep your workflows private, while still making your repository open source.

Meteor.js powered React hook for retrieving articles with error and loading state handling

The custom hook created uses Meteor's useTracker hook and the subscribe method to subscribe to the article publication, as well as the ArticlesCollection to find the article with the matching _id (which is the same as the slug in this case).

const useArticle = (slug: string): any => {
    const [error, setError] = useState<Error | null>(null)

    return useTracker(() => {
        const sub = Meteor.subscribe('article', { _id: slug })
        if (sub.ready()) {
            const article = ArticlesCollection.findOne({ _id: slug })
            if (article) {
                return {
                    loading: false,
                    error: null,
                    article,
                }
            } else {
                setError(new Error(`Article with slug "${slug}" not found`))
                return {
                    loading: false,
                    error,
                    article: undefined,
                }
            }
        } else {
            return {
                loading: true,
                error: null,
                article: undefined,
            }
        }
    }, [slug, setError])
}

This hook can be used in a React component to display the article, its loading state and error:

const Article = ({ slug }: { slug: string }) => {
    const { loading, error, article } = useArticle(slug)

    if (loading) {
        return <div>Loading...</div>
    }

    if (error) {
        return <div>Error: {error.message}</div>
    }

    return (
        <div>
            <h1>{article.title}</h1>
            <p>{article.body}</p>
        </div>
    )
}

Eager Loading with Subqueries in Laravel Eloquent

Eager loading with subqueries allows you to load related models using a subquery instead of joining the tables, which can improve performance in certain situations. For example, if you have a User model and a Post model, you can count the number of posts created by each user in the last month using a subquery like this:

$users = User::withCount(['posts as post_count' => function ($query) {
    $query->select(DB::raw('count(*)'))
          ->where('created_at', '>', now()->subMonth());
}])->get();

Laravel Request Authorization: Understanding the Differences between Request Classes and Policies

In Laravel, both request classes and policies can handle authorization.

Request classes have an authorize method that is called automatically by the framework before the request is handled. It is a convenient way to perform authorization checks on a specific request.

Policies provide a more flexible and reusable way to handle authorization across multiple request classes. They are classes that organize authorization logic around a particular model or resource. They allow you to define granular abilities for your application's users and groups.

When both the request's authorize method and a policy's __call method (or method with the same name as the action) return false for the same action, the framework will consider the user as unauthorized and will return a 403 Forbidden response.

In such scenarios, the priority is given to the authorize method of the request class. If it returns true, the framework will continue to process the request and will not check against any policy. However, if it returns false or throws an exception, Laravel will check the policy's method with the same name as the action, and if it returns false, the user will be considered unauthorized and a 403 Forbidden response will be returned.

In summary, both request classes and policies can handle authorization in Laravel, with priority given to the authorize method of request classes.

Matching dates within a monthly Interval that crosses over multiple years with PHP and Carbon

function getDatesInRange($dates, $start, $end) {
    $datesInRange = $dates->filter(function ($date) use ($start, $end) {
        if ((int) $start->format('Y') === (int) $end->format('Y')) {
            $start->year((int)$date->format('Y'));
            $end-> year((int)$date->format('Y'));
        } elseif ((int) $start->format('Y') < (int) $end->format('Y')) {
            if ((int) $date->format('m') >= (int) $start->format('m')) {
                $start->year((int) $date->format('Y'));
                $end->year((int) $date->format('Y'))->addYears(1);
            } else {
                $end->year((int) $date->format('Y'));
                $start->year((int) $date->format('Y'))->subYears(1);
            }
        }

        return Carbon::parse($date)->isBetween($start, $end);
    });

    return $datesInRange;
}

How to optimize the performance of the map function in JavaScript

To optimize the performance of a map function in JavaScript, you can do a few things:

  1. Use the forEach method instead of map if you are not creating a new array from the iteration. forEach is faster because it does not create a new array.

  2. Use the map method on a smaller array if possible. For example, if you have a large array and you only need to map over a subset of it, create a new array with just the subset and use map on that.

  3. If you are using map to transform each element of the array, use a specialized method for the transformation instead of using map. For example, if you are transforming each element to a string, use the toString method instead of using map.

  4. If you are using map to filter an array, use the filter method instead. filter is optimized for filtering and will be faster than using map for that purpose.

  5. Use a for loop instead of map if you need to perform complex operations on each element of the array. map is optimized for simple transformations, so a for loop will be faster for more complex operations.