Jak znaleźć znajomych na Twitterze/Identi.ca.

Przy okazji chęci uporządkowania (może rozwoju) mojego μbloga identi.ca pojawił się odwieczny problem: jak znaleźć znajomych w identi.ca (w ogólności: w serwisie mikroblogowym)? Po chwili namysłu stwierdziłem, że najprostszym sposobem szukania znajomych jest przeglądanie znajomych moich znajomych. Skoro ja znam A, a A zna B, to stosunkowo spora szansa, że znam B lub że chcę go dodać do obserwowanych. Podobnie tematycznie – ludzie zwykle obserwują ludzi o podobnych zainteresowaniach.

Najprostszy wariant, ręczny, to otworzenie przeglądarki, otworzenie profili wszystkich znajomych w kartach, następnie dla każdego profilu otworzenie wszystkich obserwowanych. Teoretycznie dobre, w praktyce szybko zrobiłoby się kilkadziesiąt/kilkaset kart, na dodatek z powtarzającymi się profilami. Nie tędy droga.

Ponieważ identi.ca ma API, to postanowiłem sprawdzić, czy nie uda się lekko sobie pomóc skryptem. Okazało się, że w Perlu jest moduł do obsługi API identi.ca o nazwie Net::Identica. Tak naprawdę API identi.ca i Twittera jest identyczne (do Twittera jest Net::Twitter), ale stwierdziłem, że dodam w systemie dedykowany moduł. Co prawda nie ma go w repozytorium debianowym, ale stosunkowo łatwo go zbudować (po spełnieniu zależności) z użyciem dh-perl-make.UPDATE: Ostatecznie korzystam jednak z Net::Twitter.

Ponieważ sądzę, że pytanie jak znaleźć znajomych na Twitterze (czy też na identi.ca) zadaje sobie sporo ludzi, postanowiłem opublikować skrypt, może komuś się przyda. W skrypcie należy podać ID usera, od którego ma zacząć poszukiwania, login i hasło. Nie polecam zmieniać poziomu głębokości poszukiwań (domyślnie jest to znajomi znajomych).

Algorytm jest prosty: dopóki nie osiągnie zadanego poziomu głębokości (domyślnie 2 czyli znajomi znajomych), to pobierze wszystkie ID użytkowników będących znajomymi obecnego użytkownika i doda je do sprawdzenia. Z kolei sprawdzanego użytkownika oznaczy jako sprawdzanego (i nie będzie go sprawdzał po raz kolejny). Zaczynamy od wskazanego ID użytkownika (przypuszczalnie własnego).

W zasadzie tyle. Na koniec pobierze i wyświetli dla wszystkich zebranych ID, których nie mamy już w znajomych podstawowe dane – nazwę, link do profilu, opis itp. – raczej wystarczy, by określić, czy chcemy dodać daną osobę do obserwowanych, czy nie. Bonusowo ID użytkownika, który jest zakończeniem najkrótszej (jednej z najkrótszych) ścieżek do nowopoznanej osoby.

W trakcie pojawił się drobny problem – znajomych znajomych było ponad 3k. Przypuszczałem, że jest jakiś błąd w skrypcie, ale po bliższym przyjrzeniu się wyszło na jaw, że winny jest rms (tak, Richard M. Stallman), który obserwuje właśnie tyle osób. Na takie okazje została dodana blacklista – wystarczy podać tam ID użytkownika, którego znajomych nie chcemy sprawdzać (w ogóle).

Na koniec skrypt wyświetli nam podstawowe dane, jak dla mnie wystarczające, by zorienotwać się, czy chcemy dodać kogoś do obserwowanych. Zasadniczo nic nie stoi na przeszkodzie, by dodać ich (po ID) skryptem, ale ja wolę wejść na profil i zobaczyć najpierw, co piszą (tak, oznacza to, że prawdopodobnie niebawem będę intensywniej korzystał z identi.ca, kosztem Blipa).

Skrypt poniżej. Przy okazji być może jest to sposób na nieirytujące zamieszczanie kodu na Blox…

UPDATE: Nie bardzo chciały działać URLe, przeszedłem na Net::Twitter i zamieszcam poprawioną wersję.

UPDATE2: Jest w komentarzu, ale nie wszyscy docierają: Jak znaleźć ID użytkownika na Twitterze? ID użytkownika na Twitterze (na Identi.ca też) jest zawarta w feedzie RSS danego użytkownika.

Jak bezpiecznie korzystać z uszkodzonej pamięci RAM bez BadRAM.

BadRAM był fajny, ale jest nieutrzymywany. Ostatnią działająca u mnie wersja była do kernela 2.6.25.x, późniejsze, choć istniały (np. dla 2.6.29; dead link), to nie udało się ich – wbrew wcześniejszej radości – zmusić do poprawnego działania – nadal pojawiały się błędy np. na liczeniu sum kontrolnych.

Winny w tej maszynie jest ewidentnie RAM, co zostało już dawno stwierdzone, ale maszyna na tyle niekrytyczna, że inwestować się nie opłaca (poza tym, szkoda środowiska), a ze starszym (tj. 2.6.25.x) kernelem spokojnie i poprawnie działa. Poza tym, przecież to Linux, więc da się poprawić. I jaki uroczy temat do notek jest. 😉 Z okazji świątecznej wizyty w domu, postanowiłem jednak zerknąć, czy nie pojawiły się patche BadRAM do jakichś nowszych kerneli (serii 2.6.3x, znaczy).

Nie pojawiły się, ale zamiast tego, trafiłem na pierwszej stronie wyników na sposób radzenia sobie z uszkodzoną pamięcią pod Ubuntu, który w ogóle z BadRAM nie korzysta. Chwilę później trafiłem na ten wpis (dead link). Okazuje się, że za pomocą parametrów, które można przekazać kernelowi, w szczególności mem=XX oraz memmap=X$YY, można wyłączyć obszary pamięci z użytkowania, co przekłada się w praktyce, na możliwość bezpiecznego korzystania z uszkodzonej i dotychczas powodującej błędy pamięci. Więcej o parametrach w kernelowym Documentation/kernel-parameters.txt, ale na potrzeby tego zagadnienia wystarczą te dwa.

Pierwszy parametr (mem=) ogranicza wykorzystaną pamięć. Jeśli uszkodzenie jest w okolicy 312 MB (memtest+ prawdę powie), to mem=310M co prawda obniży dostępną pamięć do 310 MB, za to system będzie działał bez problemów. Tyle tylko, że stracimy 200 MB pamięci. Trochę sporo, zwłaszcza, jeśli całość do dyspozycji to tylko 512 MB.

Drugi (memmap=) jest ciekawszy, bo rezerwuje X pamięci od adresu YY. Przykładowo memmap=10M$305M oznaczy pamięć od  305 MB do 315 MB jako wykorzystaną. Czyli stracimy raptem 10 MB, a zyskamy niezawodny system. Tyle teorii. W praktyce na dystrybucyjnym 2.6.26 z Lenny’ego, mem=300M działało poprawnie (najprościej sprawdzić przez free -m), natomiast memmap=10M$305M był radośnie olewany – nadal pokazywało dostępną całą pamięć.

Przyczyny tego stanu rzeczy nie udało mi się ustalić (podejrzewam limit 4GB zamiast 1GB, błąd w kernelu lub korzystanie z initrd – jeśli ktoś zna odpowiedź, to proszę o info), natomiast skompilowanie własnego 2.6.32.2 na podstawie konfiga od 2.6.25.x (z którego spatchowanego BadRAM korzystałem do tej pory) rozwiązało problem – memmap=2M$311M, czyli wyłączenie tylko 2 MB spowodowało, że system działa poprawnie.

Ponieważ najłatwiej zaobserwować błędy było dotychczas na sumach kontrolnych, to testowanie wykonałem prostym skryptem (brzydki bash napędzany perlem – pewnie dałoby się prosto przespisać na gołego basha, ale kto tam ma czas…; skrypt na końcu wpisu). Stosunkowo duży plik (większy, niż dostępna pamięć RAM, mój tworzony przez dd if=/dev/urandom of=random.dat bs=1MB count=1024), z losową zawartością (tworzony raz, bo czasochłonne), liczenie sum kontrolnych. Jeśli błąd pojawi się w buforze dyskowym, to przy braku wielkiego pecha suma kontrolna będzie się różnić przed i po skopiowaniu. Zapuszczone w pętli, z logowaniem do pliku – nawet przy uszkodzonej pamięci nie wystarczy 1 przebieg – błąd nie pojawia się za każdym razem. Natomiast choćby jeden błąd oznacza, że coś jest nie tak jak być powinno.

Podstawą jest jednak free -m. Jeśli on nie widzi mniej pamięci, to można nie zaczynać nawet ze skryptem.

Jeśli po dłuższym teście brak błędów (pojedynczy błąd oznacza, że nie jest dobrze), to wystarczy dopisać linię do konfigu gruba, by przy każdej aktualizacji kernela dodawał do parametrów określony argument:

#kopt=root=/dev/hda2 ro memmap=2M$311M

Dzięki temu możemy korzystać z dowolnej (najnowszej!) wersji jądra, bez upierdliwego patchowania (cóż, patche badram były dość kijowe, włączenie z tym, że zdarzało im się mieć literówki uniemożliwiające kompilację).

Na koniec wspomniany skrypcik:

#!/usr/bin/perl
$src="/random.dat";
$dst="/tmp/memtest_tmp.dat";
$log="memtest_copy.log";
if (-f $dst){
   system (" rm $dst ");
}
system (" date >> $log ");
while (1){
  system (" cp $src $dst ");
  $res = `md5sum $dst`;
  $res2 = `sha1sum $dst`;
  $res_ = `md5sum $src`;
  $res2_ = `sha1sum $src`;
  $check = "ERROR";
   if (($res == $res_) && ($res2 == $res2_)){
     $check="OK";
   }
system (" echo \"$check $res $res_ $res2 $res2_ \" >> $log ");
system ("rm $dst");
}

Podsumowując: żegnaj BadRAM!

Zabawa z kalkulatorem – automacik.

Sama idea zabawy w porozumiewanie się kalkulatorem została przybliżona tutaj (dawniej był w tym miejscu link, ale obecnie 404), i zapowiedziałem automacik. Oto i on.

#!/usr/bin/perl

$file="/usr/share/dict/polish";
$regexp='^[osildebzjkhbgr]+$';
$regexp_strict='^([osiebzlkbg]+|[osiebzlhbg]+|[osiebzlrbg]+|[osjebzlkbg]+ \
|[osjebzlhbg]+|[osjebzlrbg]+|[dsiebzlkbg]+|[dsiebzlhbg]+|[dsiebzlrbg]+ \
|[dsjebzlkbg]+|[dsjebzlhbg]+|[dsjebzlrbg]+)$';
$strict=1;

if ($strict){
$regexp=$regexp_strict;
}

open(F,$file);
while (){
if (/$regexp/o){
chomp;
print "$_ ";

y/odilkhrszebjg/0011444523879/;

@tmp=split //;
$num=0;
while (@tmp){
$lit = pop @tmp;
if ((! $num) && ($lit =="0")){
print "$lit.";
}
else{
print $lit;
}
$num++;
}
print $/;
}
}
close (F);

Zmienna $file to oczywiście pełna ścieżka do pliku z wyrazami (jeden per linię), które sprawdzamy. W tym przypadku systemowy słownik języka polskiego. Zmienna $strict określa, czy chcemy, aby dana cyfra określała w obrębie wyrazu tylko jedną literę.

Jako wynik otrzymujemy gotowe do wpisania na kalkulator ciągi cyfr. Skrypcik jest b. prosty, pisany na szybko, więc możliwe są błędy. Za ich wskazanie będę wdzięczny. Have fun!

UPDATE: Poprawiony błąd zgłoszony przez inS.

UPDATE2: Poprawiony błąd w linii s/[g]/9/; -> s/[g]/9/g;

UPDATE3: Wdałem się we flame o językach programowania, co zmobilizowało mnie do lekkiego sprzątnięcia (tr zamiast kilku s) i optymalizacji kodu (/o) – jest jakieś 15% szybciej, choć nie o to w tym chodzi.