Já faz algum tempo que o Facebook tem um bug nas listas de membros dos grupos. As listas não mostram todos os membros do grupo. Mais: os membros que não aparecem na lista nem mesmo podem ser encontrados pelo formulário de busca de nomes. Quando você é administrador de um grupo, isso pode ser um grande inconveniente, porque na interface padrão do Facebook a lista de membros é o único lugar onde é possível excluir usuários de um grupo. Ou seja, os usuários que não aparecem lá são indeletáveis!


Só ali na lista de membros aparece esse X para excluir os membros do grupo.

Há alguns meses, escrevi um user script para o GreaseMonkey (extensão para o Firefox que permite que você crie esses pequenos scripts para serem rodados em páginas específicas) que busca ajudar os administradores de grupos a removerem esses membros fantasmas.

Não havia publicado até agora por vergonha (o script é bem feio, tanto o código como o resultado). Porém, acho que não pretendo perfumá-lo tão cedo, então resolvi liberá-lo aqui até pra inspirar quem quiser fazer coisas mais bonitas.

O funcionamento dele é muito simples: quando você entra num grupo (sendo ou não administrador — porque nem distingui isso no código), ele cria botões X do lado dos links para os perfis dos usuários que estão nessa página (e só nesses — outra coisa que nem me preocupei no script). Se você for administrador do grupo em questão, quando clica no X o Facebook abre aquela caixa perguntando se você quer mesmo excluir o membro em questão (e se quer baní-lo permanentemente).


Com o script, tem X em todo o lugar! (até onde não deve… hehe)

Sem mais enrolação, eis aqui o código para (des-)apreciação e aprimoramentos (por favor! :)):

// ==UserScript==
// @name Remove users from Facebook groups
// @description Remove usuarios que postam no grupo sem precisar procurar na lista de membros
// @author  Tiago Madeira <madeira@juntos.org.br>
// @include http*://www.facebook.com/groups/*
// @version 1.32
// ==/UserScript==
 
(function(){
    var as = document.getElementsByTagName("a");
    var gid = "";
 
    for (var i = 0; i < as.length; i++) {
        var a = as[i];
        var hovercard = a.getAttribute("data-hovercard");
        if (hovercard != null && hovercard != "") {
            uid = hovercard.replace(/.*id=/, '');
            if (gid != "") {
                var button = '<a class="mhm auxiliaryButton closeButton uiCloseButton" title="Remove" rel="dialog-post" href="/ajax/groups/members/remove.php?group_id=' + gid + '&uid=' + uid + '"></a>';
                a.innerHTML = a.innerHTML + " " + button;
            }
        }
        var pattern = new RegExp("(^| )groupsCleanProfilePic( |$)");
        if (pattern.test(a.className)) {
            gid = a.getAttribute("href").replace(/.*id=/, '');
        }
    }
})();

Ou o link direto para download (ou instalação no GreaseMonkey):

fb.group.remove.user.js (1.08kb)

 

Este post possui intencionalmente apenas imagens e códigos.

Uso do programa que gera triângulo de Pascal mod m

mod 2

Pascal's Triangle mod 2

mod 3

Pascal's Triangle mod 3

mod 5

Pascal's Triangle mod 5

mod 7

Pascal's Triangle mod 7

mod 12

Pascal's Triangle mod 12

mod 23

Pascal's Triangle mod 23

Código-fonte (com alguns bugs inofensivos — procure XXX)

/* pascal -- generate colored Pascal's triangles in XPM format
 
   Copyright (C) 2011 Tiago Madeira <madeira@ime.usp.br>
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You can read a copy of the GNU General Public License at
   http://www.gnu.org/licenses/gpl-3.0.txt */
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <math.h>
 
#define DEFMOD 2
#define DEFSIZE 300
#define DEFPADDING 8
 
int mod = DEFMOD;
int size = DEFSIZE;
int padding = DEFPADDING;
 
char makecolors[6][4] = {
	"001", "010", "100", "110", "101", "001"
};
 
struct option longopts[] = {
	{"help", 0, 0, 'h'},
	{"padding", 1, 0, 'p'},
	{"size", 1, 0, 's'},
	{"mod", 1, 0, 'm'},
	{0, 0, 0, 0}
};
 
char *program_name;
 
void try_help() {
	fprintf(stderr, "Try `%s --help' for more information.\n", program_name);
}
 
void help() {
	printf("Usage: %s [OPTION]... [FILE]\n", program_name);
	printf("Generate colored Pascal's triangles (XPM format).\n\n");
	printf("Mandatory arguments to long options are mandatory for short options too.\n\n");
	printf("  -h, --help        print this help\n");
	printf("  -m, --mod=M       paint with different colors numbers mod M\n");
	printf("  -p, --padding=SZ  image padding (margin) in pixels\n\n");
	printf("  -s, --size=SZ     generate SZ lines of Pascal's triangle\n\n");
	printf("With no FILE, or when FILE is -, write to standard output.\n\n");
	printf("Report bugs to <madeira@ime.usp.br>.\n");
}
 
int baselog(int n, int base) {
	return ceil(log(n) / log(base));
}
 
void *xmalloc(size_t size) {
	void *x = malloc(size);
	if (x == NULL) {
		fprintf(stderr, "There is no enough memory to allocate.\n");
		exit(3);
	}
	return x;
}
 
int main(int argc, char **argv) {
	int optc, tofile;
	int i, j;
	int width, height, chars;
	char **color, rgb[7];
	int one, pos;
	int *pascal;
	char *line;
 
	program_name = argv[0];
	while ((optc = getopt_long(argc, argv, "hm:p:s:", longopts, (int *)0)) != -1) {
		switch (optc) {
		case 'h':
			help();
			return 0;
		case 'm':
			mod = atoi(optarg);
			if (mod > 48) { /* XXX */
				fprintf(stderr, "At the moment, this program supports only mod <= 48 (color generation limit).\n");
				return 4;
			}
			if (mod > 26) { /* XXX */
				fprintf(stderr, "At the moment, this program supports only mod <= 26 (bad implementation limit).\n");
				return 5;
			}
			break;
		case 'p':
			padding = atoi(optarg);
			break;
		case 's':
			size = atoi(optarg);
			break;
		default:
			try_help();
			return 1;
		}
	}
	if (optind < argc && strcmp("-", argv[optind])) {
		if (freopen(argv[optind], "w", stdout) == NULL) {
			fprintf(stderr, "Can't open `%s' for writing.\n", argv[optind]);
			return 2;
		}
		tofile = 1;
	} else {
		tofile = 0;
	}
 
	printf("static char *a_xpm[] = {\n");
	width = size * 2 + padding * 2;
	height = size * 2 + padding * 2;
	chars = baselog(mod, 26);
	printf("\"%d %d %d %d\",\n", width, height, mod + 1, chars);
	color = xmalloc(sizeof(color[0]) * (mod+1));
	rgb[6] = '\0';
 
	printf("\"");
	color[mod] = xmalloc(sizeof(color[mod][0]) * (chars + 1));
	for (j = 0; j < chars; j++) {
		color[mod][j] = ' ';
	}
	color[mod][chars] = '\0';
	printf("%s c #000000\",\n", color[mod]);
 
	for (i = 0; i < mod; i++) {
		color[i] = xmalloc(sizeof(color[i][0]) * (chars + 1));
		if (i == 0) {
			for (j = 0; j < chars; j++) {
				color[i][j] = 'a';
			}
			color[i][chars] = '\0';
		} else {
			strcpy(color[i], color[i-1]);
			for (j = chars-1; j >= 0; j--) {
				if (color[i][j] == 'z') {
					color[i][j] = 'a';
				} else {
					color[i][j]++;
					break;
				}
			}
		}
		one = 255 / pow(2, i / 6);
		sprintf(rgb, "%02x%02x%02x", makecolors[i%6][0] == '1' ? one : 0,
				makecolors[i%6][1] == '1' ? one : 0, makecolors[i%6][2] == '1' ? one : 0);
		printf("\"%s c #%s\",\n", color[i], rgb);
	}
 
	line = xmalloc(sizeof(line[0]) * (width+1));
	pascal = xmalloc(sizeof(pascal[0]) * size);
 
	line[width] = '\0';
	for (j = 0; j < width; j++) {
		line[j] = ' ';
	}
	for (i = 0; i < padding; i++) {
		printf("\"%s\",\n", line);
	}
 
	memset(pascal, 0, sizeof(pascal[0]) * size);
	pascal[0] = 1;
 
	for (i = 0; i < size; i++) {
		for (j = i; j >= 0; j--) {
			if (j != 0) {
				pascal[j] = (pascal[j-1] + pascal[j]) % mod;
			}
			pos = padding + 2*j + (size - 1 - i);
			/* XXX a implementacao de line ficou toda errada e so estou pegando
			 * o primeiro caractere de color aqui. precisa ser reescrito. */
			line[pos] = line[pos+1] = *color[pascal[j]];
		}
		printf("\"%s\",\n\"%s\"%s\n", line, line, i == size-1 && !padding ? "" : ",");
	}
 
	line[width] = '\0';
	for (j = 0; j < width; j++) {
		line[j] = ' ';
	}
	for (i = 0; i < padding; i++) {
		printf("\"%s\"%s\n", line, i == padding-1 ? "" : ",");
	}
	printf("};\n");
 
	if (tofile) {
		fclose(stdout);
	}
	return 0;
}

(Download — 5kb)

 

Adverte-se aos curiosos que se imprimiu esta obra nas oficinas da gráfica Vida&Consciência em 16 de julho de 2009, em papel off-set 90 gramas, composta em tipologia Walbaum Monotype de corpo oito a treze e Courier de corpo sete, em plataforma Linux (Gentoo, Ubuntu), com os softwares livres \LaTeX, \textrm{De\TeX}, Vim, Evince, Pdftk, Aspell, SVN e TRAC.

Da contracapa de uma bela edição de “Viagem em volta do meu quarto” (Xavier de Maistre) publicada pela Editora Hedra.

Tornou-se instantaneamente minha editora preferida. Não é fantástico (e de evidente bom gosto) os editores usarem e divulgarem Gentoo, LaTeX, Vim e SVN?

 

Inspirado por esse tuíte.

A ignorância me dá náuseas.

A ignorância de pessoas que se dão ao luxo de chamar outros de ignorantes me dá náuseas.

A ignorância de pessoas que se dão ao luxo de chamar de ignorantes as pessoas que se dão ao luxo de chamar outros de ignorantes me dá náuseas.

A ignorância de pessoas que se dão ao luxo de chamar de ignorantes as pessoas que se dão ao luxo de chamar de ignorantes as pessoas que se dão ao luxo de chamar outros de ignorantes me dá náuseas.

A ignorância de pessoas que se dão ao luxo de chamar de ignorantes as pessoas que se dão ao luxo de chamar de ignorantes as pessoas que se dão ao luxo de chamar de ignorantes as pessoas que se dão ao luxo de chamar outros de ignorantes me dá náuseas.

Ad infinitum.

PS: Esse post (como a ignorância do autor desse blog) também me dá náuseas.

PPS: Consultei o Houaiss duas vezes pra escrever o título desse post: a primeira pra confirmar que “despoema” não existe, a segunda pra confirmar que “nauseabundo” existe.

 

Meu primo tuitou há alguns minutos que “o maior erro na vida é ter medo de errar” e a frase me deixou pensativo.

Suponha que você leia essa frase e resolva “Então, para não errar, não vou ter medo de errar”. Nesse caso você está tendo medo de um erro (o erro seria o medo de errar); absurdo!

Suponha, por outro lado, que você leia essa frase e resolva “Então vou continuar com medo de errar.” Neste caso, você está cometendo o maior erro (sem medo dele), então você perdeu o medo de errar. Absurdo novamente!

Portanto, conclui-se que o maior erro na vida não deve ser o medo de errar. qed.

PS: Perdoem-me por possíveis falhas, tive que escrever correndo para não me atrasar para o tango.

© 2012 Blog do Tiago Suffusion theme by Sayontan Sinha