Annoying Facebook Conversations removal

Messages in Facebook share a lot in common with Google Voice messages. Soon you’ll find your inbox full of “Conversations” and there’s no way to remove them in bulk.

Here’s a bit of vanilla javascript to clean it up.

Just make sure you’re:

  1. Logged in to Facebook with Google Chrome

  2. On messages page or archived conversations page

  3. Open console, paste this code and hit return

// Make sure you're in Google Chrome:
// 1. Logged in to Facebook
// 2. On https://www.facebook.com/messages
// 3. Open Console and paste following / or create a snippet, save and run it
 
+function() {
    'use strict';
    var findNodeWithText = function(text, type){
      var children = document.querySelectorAll(type);
      var i = 0, node;
      var reg = new RegExp(text, 'g');
      for (; i < children.length; i++) {
        node = children[i];
        if (reg.test(node.textContent)) {
            return node;
        }
      }  
 
    };
 
 
    var remove = function(){
        console.log('remove')
        var evt2 = new Event('click', {
            bubbles: true, 
            cancelable: true
        });
        var el2 = findNodeWithText('Actions', 'button');
 
        console.log('click', el2);
        el2.dispatchEvent(evt2);
 
        var evt = new Event('click', {
            bubbles: true, 
            cancelable: true
        });
        var el = findNodeWithText('Delete Conversation...', 'span');
        el.dispatchEvent(evt);
 
 
        var to = setTimeout(function(){
        var btn = document.querySelector('[name="delete_conversation"]')
        var ev = new Event('click', {
            bubbles: true, 
            cancelable: true
        });
            btn.dispatchEvent(ev);
            clearTimeout(to);
            main();
        }, 300);
    };
 
    var main = function() {
        var to = setTimeout(function(){
            var item = document.querySelector('[role="listitem"] .img');
            var ev = new Event('click', {
                bubbles: true, 
                cancelable: true
            });
            console.log('found list item', item)
            item.dispatchEvent(ev);
            remove();
            clearTimeout(to);
        }, 200);
    }
    main();
}();

As always, use it at your own risk.

CORS headers in Rails stack ?

When working with API it’s important to set up CORS headers to support Web Client (Browser) requests.

Common solution for most of Rails developers is to create

1
before_action
with custom headers.

def enable_cross_resource sharing
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Headers'] = 'GET, POST, PUT, DELETE, OPTIONS'
  headers['Access-Control-Allow-Methods'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
end

Well that’s WRONG.

What you should do instead is to setup CORS at the (Rack)[http://rack.github.io] middleware level before your Rails routes. Routes only accessible after HTTP OPTIONS method succeeded on the web client.

Rack Cors is helpful if you don’t want to write your own middleware.

In

1
application.rb
make sure that you serve CORS at the top of the stack or at least before middleware you need (in my case I had
1
Warden::Manager
instead of
1
0
).

config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '*'
    resource '*',
      :headers => :any,
      :methods => [:get, :post, :delete, :put, :options, :head]
  end
end

All above is an OK setup for Heroku, (Aptible)[https://www.aptible.com] or other services that allow you to deploy your app with cli gem but won’t let you access higher stack like Nginx or Apache

“The proper way” of handling Cross-origin is to set it up at the Nginx level. So your Rails app is only busy with serving API.

Make use of add_header in the

1
location
context (or
1
server
if all your server does is serving API)

add_header Access-Control-Allow-Headers "X-Requested-With";
add_header Access-Control-Allow-Methods "GET, HEAD, OPTIONS";
add_header Access-Control-Allow-Origin "*";

Fun with Vagrant and Docker containers

This article requires some knowledge about Vagrant and Docker.

Almost any reasonable deploy process now requires a docker box. Docker is awesome but I’d rather have an isolated environment for my containers.

Here is where vagrant’s docker priovider comes in to play. Vagrant guys did a great job explaining abstraction here.

As always things are not so easy when you actually try to implement Vagrant Docker Proxy/Host on your own.

After a day of googling errors caused by

1
vagrant up
I figured that Vagrant is too green for automating Docker installation. Another issue came up after I failed to install Docker on linux box. Even if you get Docker instaled you instantly get a permission error.

All issues above fixed with custom

1
shell.sh
provision script:

#!/bin/bash
sudo apt-get update &&
sudo apt-get install curl -y &&
curl -sSL https://get.docker.com/ubuntu/ | sudo sh &&
sudo usermod -a -G docker vagrant &&
ps aux | grep 'sshd:' | awk '{print $2}' | xargs kill

1
curl -sSL https://get.docker.com/ubuntu/ | sudo sh &&
will take care of installing correct binaries.

Here’s working

1
Vagrantfile
for host machine:

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|

  config.vm.provision "shell", path: "shell.sh"
  config.vm.box = "ubuntu/trusty64"
 
  config.vm.provider :virtualbox do |vb|
      vb.name = "dockerhost"
  end
end

Then you can reference other containers in main

1
Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.provider "docker" do |v|
    v.vagrant_vagrantfile = "./docker-host/Vagrantfile"
  end

  config.vm.define "core" do |v|
    v.vm.provider "docker" do |d|
      d.build_dir = "."
    end
  end

  config.vm.define "db" do |v|
    v.vm.provider "docker" do |d|
      d.image = "paintedfox/postgresql"
      d.name = "db"
    end 
  end
end

That’s it!

Remove Google Voice messages

Today I realized that there are about 2000 of messages / voicemail in my Google Voice account. By default Google will only allow 10 messages to be removed in one shot. Then you’ll find deleted messages in “History” which you also need to clean up.

I hate to leave all this text about me laying around on Google servers.

So here’s the gist of a code that will remove all of your messages from Google voice.

WARNING: this code will delete everything from your account. So use it cautiously!

This is first post for the Overengineering blog. I will be posting more usless or usefull stuff as I feel like sharing.

If want some details please let me know in comments…