WordPress Enfold YouTube video only displaying link

I had a problem recently on a website using WordPress and the Enfold theme. A YouTube video that was initially marked as private, but later updated to public (embeddable) was still only showing the link, and not the actual video player.

A previously private video but later publicly released was still showing as a link on the website.

Other videos however in the same page, where showing properly.

Other videos however, as this one in the image where showing properly.
Other videos, however, as this one in the image where showing properly.

It turns out that from reading here that WordPress does some caching and is not pulling the latest youtube change.

To fix the problem, connect to the MySQL client, and retrieve all pages with an embedded video:

mysql> SELECT * FROM wp_postmeta WHERE meta_key like '%_oembed%';

My results were something like this:

+---------+---------+-----------------------------+------------------------------------------+
| meta_id | post_id | meta_key | meta_value |
+---------+---------+-----------------------------+------------------------------------------+
| 306 | 86 | _oembed_5c3aff6d73f219 | {{unknown}} |
| 336 | 10 | _oembed_39378045d82af3 | {{unknown}} |
| 337 | 10 | _oembed_a26684b605680e | {{unknown}} |
| 354 | 86 | _oembed_af60fe80d2fe16 | <iframe src="yt.com/S3edckDk_qo></iframe>|
| 355 | 86 | _oembed_time_af60fe80d2fe16 | 1503662521 |
| 356 | 10 | _oembed_f4d0e4e5251dea | <iframe src="yt.com/S3edckDk_qo</iframe> |
| 357 | 10 | _oembed_time_f4d0e4e5251dea | 1503662579 |
| 359 | 71 | _oembed_time_a26684b605680e | 1503662615 |
| 385 | 138 | _oembed_f4d0e4e5251dea | <iframe src="yt.com/S3edckDk_qo</iframe> |
| 386 | 138 | _oembed_time_f4d0e4e5251dea | 1503777685 |
| 387 | 138 | _oembed_4c76e997d8b21a | {{unknown}} |
| 389 | 138 | _oembed_268d95c8d907aa | {{unknown}} |
| 391 | 138 | _oembed_time_a26684b605680e | 1505355944 |
+---------+---------+-----------------------------------------------+------------------------+

I tried removing the offending meta_id, by issuing:

mysql> DELETE from wp_postmeta WHERE meta_key like '%_oembed%' and meta_value like '%OeiZNr24o7g%';

However that didn’t work when I refreshed the page, so I decided on the more radical solution:

mysql> DELETE from wp_postmeta WHERE meta_key like '%_oembed%';

That solved all my problems!

Python Stripe Signature Verification Error

Building a Django + Stripe integration today I kept hitting the SignatureVerificationError.

According to their webhook’s documentation, they recommend something like this:

@csrf_exempt
def my_webhook_view(request):
  payload = request.body
  sig_header = request.META['HTTP_STRIPE_SIGNATURE']
  event = None

  try:
    event = stripe.Webhook.construct_event(
      payload, sig_header, endpoint_secret
    )
  except ValueError as e:
    # Invalid payload
    return HttpResponse(status=400)
  except stripe.error.SignatureVerificationError as e:
    # Invalid signature
    return HttpResponse(status=400)

  # Do something with event

  return HttpResponse(status=200)

I think would work fine with python2, but in my case the signature being generated never matched the expected signature hence triggering the exception stripe.error.SignatureVerificationError

The solution is to utf8 decode the payload, on line 3, change:

payload = request.body
payload = request.body.decode('utf-8')

That did the trick, hope it can save someone some time.

Repair experience OnePlus 3t

After many months of use without a case, I finally managed to crack the screen of my One Plus 3t. I researched online to try a repair on my own, but eventually, and from my previous experiences in which self-repairs don’t end up as nicely as you might think, I decided to reach out to their support team.

The experience was surprisingly pleasant, relatively fast and not as expensive as I had initially estimated. I will describe more or less the process and dates so you get an idea of what to expect.

To start the process you need to submit a ticket through the official Oneplus customer center website,  explaining what repairs your phone needs, in my case my cracked screen. They will reply within a few hours and give you a cost estimate. If you agree to the repairs, they will send you an address in Texas, assuming you are in the US, to where you need to ship the phone.

Once the phone has been received, they will give you a final bill, you need to pay online for the repair bill and then they will proceed with the repairs and mail the phone back to your address. My phone also needed a case replacing, apparently, upon impact, the framing body had been deformed to the point where the new screen wouldn’t fit, so that made the repairs a little more expensive.

Timeline:

  • May 12: opened a ticket with support explaining my screen was cracked
  • May 13: Support responded with an estimate of 62.81$ (not including labor and fees). I agree to the repairs.
  • May 13: Received an email from Acer (who’s in charge of the repairs for One Plus) with mailing instructions.
  • May 15: I mailed my phone using USPS to their repair center in Temple, TX.
  • May 18: I get a message informing that the phone has been received.
  • May 23: I get an email asking me to pay online for the repairs: screen + case: 133.16$. I paid a couple of hours after.
  • May 24: Repairs are completed.
  • May 25: Got a FedEx tracking number.
  • May 27: I get the repaired phone!

One last thing, in my case they did a complete phone reset, even though it wasn’t necessary, so before sending it to repair, I suggest you take off everything that want to preserve that is not backed up already. Also, my phone was rooted and they didn’t care about that.

Finally, the repair looks great, screen+case makes the phone look brand new, and they included a free phone case so that this won’t happen again.

Android RNE App

Spanish Radio and TV (RTVE) is a government funded entity that since 1956 has been broadcasting several TV and Radio channels.

Living abroad from home is thought but the radio programs from RTVE are a great companion for those missing home moments. I use the official app from Google Play Store, but unfortunately, the quality of the app is nowhere close to that of the content, so I decided to build my own.

https://play.google.com/store/apps/details?id=pandatech.rneunofficial

My app is not based on a web view as the official one, but rather on native Android elements that create a better user experience and are more visually appealing. Also, it plays audio as per the official Android documentation, i.e. requesting Audio focus before playing, and pausing if things like an alarm or a phone call come through.

I am planning to add more features in the next few days, ideally, the podcasts, and not just the live audio. Finally, and probably best, no adds!

Docker Alpine+Python3+Django+uWGSI+Nginx

Django works great when you are running in local, but the moment you decide to move onto production, the headaches begin…

Since a few months ago I deploy everything using Docker, the result is something much cleaner and easier to maintain, so when moving my Django app to production, I choose Docker for it. As expected someone had already taken the time to build a Docker image that using ubuntu as is base image will run your Django site with uWGSI&Nginx, a marriage made in heaven.

My problem with that image is that it uses Ubuntu, don’t get me wrong, I love Ubuntu for something like my laptop, but for a Django app in an EC2 instance, it just feels too heavy. So I created an equivalent Dockerfile, this time with the much lighter Alpine.

The Dockerfile is available in Github with instructions on how to deploy your app.
Enjoy!

Redshift UDF Phone Number to Country

Redshift’s UDFs (User Defined Functions) permit to execute, with some limitations, certain Python libraries and custom code.

In my case, I wanted to find a way to extract the country code from a phone number in E.164 format. UDFs are a perfect fit for this, the implementation in SQL would most certainly require creating custom views, and hacking your way around, while in python, we can use the library phone-iso3166

>>> from phone_iso3166.country import *
>>> phone_country('+1 202-111-1111')
'US'
>>> phone_country('+34645678901')
'ES'

To upload a library to Redshift, we first need to check it follows the structure:

directory/
    __init__.py
    extra_files.py
    subdirectory/
        __init__.py
        other_files.py

In our case, phone-iso3166 is already in that structure. Now we need to zip the library:

tar -xvzf phone-iso3166.tar.gz
zip -r phone-iso3166.zip phone-iso3166

With our zipped library, we need to upload it to S3. I did this part manually into a bucket named s3://redshift/custom-udfs/

Now, connect to Redshift and issue:

CREATE LIBRARY phone_iso3166 LANGUAGE plpythonu 
FROM 's3://redshift/custom-udfs/phone_iso3166.zip' 
CREDENTIALS 'aws_access_key_id=<your-aws-key>;aws_secret_access_key=<your-aws-pass>' 
region as '<your-region>';

Last step:

CREATE OR REPLACE FUNCTION udf_phone_country (phone_number VARCHAR(64)) RETURNS VARCHAR(64) IMMUTABLE as $$ 
from phone_iso3166.country import phone_country, InvalidPhone
try:
    return phone_country(phone_number)
except:
    return None
$$ LANGUAGE plpythonu;

You should be all set to use this in your queries:

SELECT 
analytics.udf_phone_country('+14151111975'),
analytics.udf_phone_country('+7652112311'),
analytics.udf_phone_country('+34626472918')

That returns:

"US","RU","ES"

DD-WRT Remote SSH Access behind VPN

SSH access doesn’t work when OpenVPN client is enabled on DD-WRT.
Packages do arrive at the router if you try to SSH against the WAN IP, however, because all OUTPUT  traffic is diverted through the VPN (interface tun0) SSH won’t succeed.

What’s missing is an OUTPUT rule on iptables  to route traffic on port 22 through the vlan2 interface (that’s the interface connected directly to the internet).

First, create table 202 via the Gateway Ip on the Interface VLAN2:

$ ip route add default via $(nvram get wan_gateway) dev vlan2 table 202

Then apply the rule on table 202 to packages marked with 22.

$ ip rule add fwmark 22 table 202

Finally, tag with 22 every output package on port 22 not coming from any machine on the local network.

$ iptables -t mangle -I OUTPUT -p tcp --sport 22 -d ! 192.168.1.0/24 -j MARK --set-mark 22

Note that the last command skips packages from the local network in my case 192.168.1.0/24, reason being that when SSHing from a host in local, the packages should be routed through br0 and not vlan2.

First issue these commands in the command line of your router to ensure they work with you, if somehow they break your routing, a restart will clear them. Once you have made sure they work, you can add them to the firewall script of your router

Note that my config IP and port is different because I am not using the default values.

 

Redshift Force Drop User

Ever tried dropping a user in Redshift only to discover that user “user_1” cannot be dropped because the user has a privilege on some object .

That’s not of great help Redshift. Luckily for us, there is a solution. Kamlesh Gallani posted a response about revoking permissions for tables and schemas that I user might still be assigned to, along with changing the ownership of tables that the user might have created. After that, dropping the user is straight forward.

I created a python snippet with his response that might save you a few minutes. You will need the view v_get_obj_priv_by_user from amazon-utils.

import psycopg2
 
# Connect to Redshift
conn = psycopg2.connect(host="", dbname="", user="", password="", port="5439")
conn.autocommit = True
cursor = conn.cursor()
 
# List of users to drop
users = ['user_to_drop_1', 'user_to_drop_2']
 
# New owner, used when changing ownership
new_owner = 'new_user'
 
# Templates to change ownership, revoke permissions, and drop users
change_ownership = "select 'alter table '+schemaname+'.'+tablename+' owner to %s;' from pg_tables where tableowner like '%s'"
revoke_schema_permissions = "select distinct 'revoke all on schema '+schemaname+' from %s;' from admin.v_get_obj_priv_by_user where usename like '%s'"
revoke_table_permissions = "select distinct 'revoke all on all tables in schema '+schemaname+' from %s;' from admin.v_get_obj_priv_by_user where usename like '%s'"
drop_user = "drop user %s;"
 
for user in users:
    # Change ownership
    cursor.execute(change_ownership % (new_owner, user))
    for r in cursor.fetchall():
        print("Executing: %s" % r[0])
        cursor.execute(r[0])
    # Revoke schema permissions
    cursor.execute(revoke_schema_permissions % (user, user))
    for r in cursor.fetchall():
        print("Executing: %s" % r[0])
        cursor.execute(r[0])
    # Revoke table permissions
    cursor.execute(revoke_table_permissions % (user, user))
    for r in cursor.fetchall():
        print("Executing: %s" % r[0])
        cursor.execute(r[0])
    # Drop user
    cursor.execute(drop_user % (user))

Miele W 1065 – Wiring for 110 Volts

Miele W 1065 Back

I got yesterday one of these Miele beauties. She is over 20 years old, and my guess is that she weights around 250 pounds. Yes, it was though carrying it downstairs from is previous owner to home with just 2 guys. 

When I brought her home, I saw that it required 220V which it’s a problem where I live, BUT if you are willing to sacrifice the second heater,  you can adapt can change the wires to make it work with the regular 110V.

Miele W 1065 Back
Miele W 1065 Back

First and foremost unplug the washer, unscrew the white plastic box and that will expose the connections box. You will see we have Ground, Neutral, phase 2 and phase 1 when reading from right to left. The washer will work for with just having phase 2 connected to 110V, but as said above, the heater won’t work, so you are stuck with washing with cold water. Which anyways is the best way to preserve your clothes.

I bought a piece of cord and cut it to expose the wiring, then just connect ground to ground, neutral to neutral and phase 2 to the remaining. I used a multimeter to make sure the wiring was correct.

Try this at your own risk. Mine is working like a champ.

WordPress HTTP Error when uploading files

Today I got this error when uploading a video to my WordPress site. I Googled around for a little bit, but the proposed solution wasn’t working.

It turns out that since I am using WordPress docker and a Nginx proxy, this later was complaining that the file was too large 413 Request Entity Too Large when the file was uploaded using the browser uploader, not the WordPress multi-file uploader.

Wordpress Browser Uploader
WordPress Browser Uploader

The solution was easy:
$ vim nginx.conf

http {
...
# Added because uploading large files to WordPress is throwing HTTP error.
client_max_body_size 64M;
...

In my case since I want my setting to take place for all the websites I am hosting with Nginx I applied the setting under the http section.

Enjoy