import sys
import base64

import click
from collections import Counter
from string import digits, ascii_letters, punctuation
import random

random = random.SystemRandom()
ascii = digits + ascii_letters + punctuation


def get_random_char():
    return random.choice(ascii)


def generate_masked_url(url, privacy):
    letters = []
    for i, letter in enumerate(url):
        if random.random() < privacy:
            letters.append(get_random_char())
        else:
            letters.append(url[i])
    return ''.join(letters)


def check_reports(url, counters):
    for i, letter in enumerate(url):
        if counters[i].most_common(1)[0][0] == letter:
            continue
        else:
            return False
    return True


def _simulate(url, privacy):
    assert 0 < privacy < 1
    counters = [Counter() for _ in range(len(url))]
    num_generated = 0

    while True:
        num_generated += 1
        masked = generate_masked_url(url, privacy)
        for i, letter in enumerate(masked):
            counters[i][letter] += 1

        sys.stdout.write('\rrecov: {} | gen: {}'.format(
            ''.join([counters[i].most_common(1)[0][0] for i in range(len(url))]), masked))
        sys.stdout.flush()

        if check_reports(url, counters):
            click.echo(
                click.style('\n\n{} reports required to recover the original URL {} with privacy level {}%'
                            .format(num_generated, url, privacy*100.0), fg='green'))
            return


@click.command()
@click.argument('url', default='http://stackoverflow.com/questions/5290994/python-remove-and-replace-printed-items')
@click.option('-p', '--privacy', default=90.0, help='Level of privacy <100. Higher == better user privacy')
def simulate(url, privacy):
    _simulate(url, privacy/100.0)


@click.command()
@click.argument('path', default='reports.txt')
def recover(path):
    with open(path, 'r') as f:
        reports = f.readlines()

    reports = [base64.urlsafe_b64decode(r) for r in reports if r]

    num_chars = len(reports[0])
    counters = [Counter() for _ in range(num_chars)]
    recovered = b''
    recovered_reports = []

    for report in reports:
        for i, letter in enumerate(report):
            counters[i][letter] += 1
        recovered = bytes([counters[l].most_common(1)[0][0] for l in range(num_chars)])
        print('recov: {}'.format(recovered))
        recovered_reports.append(recovered)
    try:
        click.echo(
            click.style('\nRecovered! {}'.format(recovered.decode('utf-8')),
                        fg='green'))
        reports_needed = len([r for r in recovered_reports if r != recovered])
        click.echo(
            click.style('Reports needed: {}'.format(reports_needed),
                        fg='green'))
    except UnicodeDecodeError:
        click.echo(
            click.style('\nUnable to recover full URL :(', fg='red'))


@click.group()
def cli():
    pass

cli.add_command(simulate)
cli.add_command(recover)

@@ -1332,23 +1332,22 @@
 ired to 
-recover
+decode
  the ori
@@ -1804,32 +1804,55 @@
 click.command()%0A
+@click.argument('url')%0A
 @click.argument(
@@ -1894,16 +1894,21 @@
 recover(
+url, 
 path):%0A 
@@ -2126,63 +2126,24 @@
 s)%5D%0A
+%0A
     
-recovered = b''%0A    recovered_reports = %5B%5D%0A%0A    for
+for needed,
  rep
@@ -2149,23 +2149,34 @@
 port in 
+enumerate(
 reports
+)
 :%0A      
@@ -2276,16 +2276,29 @@
 = bytes(
+%0A            
 %5Bcounter
@@ -2400,61 +2400,158 @@
 d))%0A
-        recovered_reports.append(recovered)%0A    try:%0A
+%0A        try:%0A            recovered = recovered.decode('utf-8')%0A        except UnicodeDecodeError:%0A            pass%0A%0A        if recovered == url:%0A    
     
@@ -2570,32 +2570,36 @@
 ho(%0A            
+    
 click.style('%5CnR
@@ -2598,24 +2598,43 @@
 yle(
+%0A                    
 '%5Cn
-Recover
+Decod
 ed
-!
  %7B%7D
+!
 '.fo
@@ -2651,31 +2651,11 @@
 ered
-.decode('utf-8')),%0A    
+),%0A
     
@@ -2691,83 +2691,8 @@
     
-    reports_needed = len(%5Br for r in recovered_reports if r != recovered%5D)%0A
     
@@ -2711,32 +2711,36 @@
 ho(%0A            
+    
 click.style('Rep
@@ -2767,25 +2767,23 @@
 mat(
-reports_
 needed
++1
 ),%0A
+    
     
@@ -2823,39 +2823,24 @@
     
-except UnicodeDecodeError:%0A    
+        return%0A%0A
     
@@ -2843,36 +2843,32 @@
     click.echo(%0A
-    
         click.st
@@ -2884,23 +2884,22 @@
 able to 
-recover
+decode
  full UR

Add url parameter to recover command