Last notes

How to select always unique next image from predefined array of images on each new post with post id incremented by 1

Let's say you have a limited array of images - let it be 100 elements - and you need to sequentially select the next image relative to the previous one for each new post.

This algorithm will help you.

So you have an array of images known as $images_array

For example your last article id will be a variable named $id. Variable $total_images — is an images array length. Then your next image index within $images_array array will be: $index = $id - $id/$total_images*$total_images;

This way you can get any of your image on $images_array[$index].


How to genereate required previews for App Store and Google Play fast from emulator screenshots

There is a huge problem to prepare images preview for mobile app stores. And often you have only screenshots of your mobile app taken from emulator (Android or iOS). Now you have to take at least two different types for iPhones (6,5" and 5,5" are required) and one type used twice for iPad (12,9 Pro and 2,3 gen are the same but required twice).

Also it will be a huge pain in the ass to take resize and crop all of them especially when there are more than one language in the app.

So, once I got tired of that and wrote an ultrasimple python script to optimize this process.

How it works

  1. You take just one set of images for each language for iPhone, iPad, Android Phone, Android Tablet
  2. Run my python script python screens.py to prepare all the required sets of images.
  3. Receive all required and ready to publish to App Store And Google play preview images.

The script


from PIL import Image, ImageOps
import os

print('Started')
sources_dir = "test/sources"
results_dir = "test/results"
bg_path = 'test/bg1.jpg'

resolutions =  { "iphone": [
                    (2778, 1284), (2208, 1242)
                  ],
                  "ipad":  [
                    (2732, 2048)
                  ] 
                }

def listdir(path):
  return [f for f in os.listdir(path) if not f.startswith('.')]

def save_screenshot(img, path, file_name):
  try:
    os.makedirs(path)
  except IOError:
    pass
  img.save(f"{path}/{file_name}")
 

for platform in listdir(sources_dir):
  platform_dir = f"{sources_dir}/{platform}"
  lc_folders = listdir(platform_dir)
  print(f"Performing {platform}")
  for lc in lc_folders:
    images_dir = f"{platform_dir}/{lc}"
    print(f"reading images in {images_dir}")
    images = listdir(images_dir)
    for image in images: 
      f = f"{images_dir}/{image}"
      i = 0
      for height, width  in resolutions[platform]:
        try:
          screenshot = Image.open(f)
          bg =  Image.open(bg_path)
          fitted =  ImageOps.contain(screenshot, (width, height))
          fwidth, fheight = fitted.size
          processed_image = Image.new('RGBA', (width, height), color=(232, 106, 28))
          processed_image.paste(bg)
          processed_image.paste(fitted, (int(width/2 - fwidth/2), int(height/2 - fheight/2)))
          save_screenshot(processed_image, f"{results_dir}/{platform}/{lc}/{height}x{width}/", file_name=f"{platform}_{lc}_{height}x{width}_{image}")
          i += 1
        except IOError:
          print(f"Error in processing")
print('Finished')

The whole script is available on github.com with all the references to app stores docs and articles that inspired me.

Test run

You can run it as is on a predefined test folder and take a closer look to results at test/results folder. Also please read the Readme.md to optimize script to your specific needs.

Grab the code at Github →


Docker compose: nginx and wordpress behind Cloudflare — HTTPS to HTTP proxying problem

Faced an unusual issue — docker wordpress image fails to work with Cloudflare out of the box.

The problem is that I originally had Flexible proxying configured instead of Full (strict) on Cloudflare. In this case, the request goes to Cloudflare via HTTPS, but from Cloudflare to server via HTTP.

As a result, I decided not to change docker-compose-yml with additional custom image assemblies and just to connect certbot without installing it onto the docker host.

So the solution is to create two folders on the host machine /data/certbot/letsencrypt for certificates and /data/certbot/www to store acme challenges from letsencrypt. Then I’ve just mounted them on the Nginx host. Here is my nginx host config as is:

nginx:
  image: nginx:1.21-alpine
  restart: unless-stopped
  volumes:
    - /data/log/nginx:/var/log/nginx
    - ./sites-enabled:/etc/nginx/sites-enabled
    - ./nginx.conf:/etc/nginx/nginx.conf
    - /data/certbot/letsencrypt:/etc/letsencrypt
    - /data/certbot/www:/var/www/certbot
    - ./127.ru:/var/www/127.ru # here goes wordpress
  ports:
    - 80:80
    - 443:443
  depends_on:
    - mysql
    - wordpress

In the nginx config at sites-enabled/127.ru

server {
  listen 80;
  server_name     127.ru;
  index index.php;
  root /var/www/127.ru;
  location /.well-known/acme-challenge/ {
    root /var/www/certbot;
  }
  location / {
    try_files $uri $uri/ /index.php;
  }
  location ~ ^/.+.php(/|$) {
    try_files $uri =404;
    include /etc/nginx/fastcgi.conf;
    fastcgi_pass wp127ru:9000;
  }
  #listen 443 ssl;
  #ssl_certificate /etc/letsencrypt/live/127.ru/fullchain.pem;
  #ssl_certificate_key /etc/letsencrypt/live/127.ru/privkey.pem;
}

Turn off port 80 later - it is useless. The important line here is /.well-known/acme-challenge/ - at this path certbot will check the acme-challenge when generating an SSL certificate.

Then, from the host machine with Docker, we obtain the certificate to the mounted folders:

docker run --rm --name temp_certbot \
-v /data/certbot/letsencrypt:/etc/letsencrypt \
-v /data/certbot/www:/tmp/letsencrypt \
certbot/certbot \
certonly --webroot --agree-tos --renew-by-default \
--preferred-challenges http-01 --server https://acme-v02.api.letsencrypt.org/directory \
--text --email my@email.com \
-w /tmp/letsencrypt -d 127.ru

Now just remove port 80 in the nginx config (line «listen 80;») and uncomment the lines off SSL certs in the same place:

#listen 443 ssl;
#ssl_certificate /etc/letsencrypt/live/127.ru/fullchain.pem;
#ssl_certificate_key /etc/letsencrypt/live/127.ru/privkey.pem;

Next s witch Cloudflare to full proxying.

Now just restart nginx:

sudo docker exec -ti your-docker-host sh -c "nginx -s reload"

Categories