#!/usr/bin/perl -w use strict; # Creating an archive of http://livejournal.com/users/.../friends/ # Written by Misha Verbitsky under GPL # "WITH FRIENDS LIKE THESE - WHO NEEDS ENEMIES?" # Takes a site provided by ljsm-strip.pl # (the stripped down version of ljsm by Sasha Nikolaev) # Parses the entries, creates a static version of # .../friends/ and the archives of individual users use Date::Manip qw(ParseDate UnixDate); my $MAXENT=35; # How many entries per page my $MEM_MAXENT=20; # Same for memory indexes my $PATH = "/LJ/"; # The main directory (locally on your Unix system) my $BAR_COLOR = "#8888AA"; # Horizontal bar color my $LENTA = "f"; my $HEADER=" ljdir.pl title With friends like these...
[ О проекте | Лента | Поиск | От составителя ]

Архивы френд-ленты Livejournal.com (02.2001-10.2002)

\n "; my $FOOTER="

With friends like these...
Advertisement on IMPERIUM.LENIN.RU:


:ЛЕНИН:

"; my $HEAD=$HEADER; # Temporary header and footer my $FOOT=$FOOTER; if (@ARGV >0) { lj_user("$ARGV[0]"); } else { & do_all; & friends_copy; & lj_lenta; & friends_clean; } sub do_all { my @topdir = glob "*"; my @users = (); foreach (@topdir) { # print "Testing the directory $_...\n"; next if (! (-d $_)); next if ($_ eq $LENTA); next if ((! (-d "$_/2001")) && (! (-d "$_/2002"))); push (@users, $_); } foreach (@users) { print "ljdir.pl: archive directory for $_...\n"; lj_user($_); } } ########################################################################## ########################################################################## # Subroutine lj_lenta # takes a tree of directories produced by the ljsm-strip, # removes /LJ/friends, copies everything into /LJ/friends, # runs lj_dir, removes all files in /LJ/friends/ except # index*.html. It is very similar to lj_user, except # in building the header and footer file. # We assume that in all months 02.2001 - 10.2002 # something happened sub lj_lenta { # &friends_copy; # Takes too long to do it every time my @monthly = glob ("$LENTA/[0-9][0-9][0-9][0-9]/[0-9][0-9] $LENTA/[0-9][0-9][0-9][0-9]/[0-9]"); my $mbar= "
2001-2002: Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec | Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct |
"; # The userbar is done! Now for the directories $FOOT= "

". $mbar . $FOOTER; $HEAD = $HEADER . $mbar . "

"; foreach (@monthly) { print "Entering $_ to make lenta...\n"; lj_dir ($_); } } ########################################################################## ########################################################################## # Copies all files to friends directory sub friends_copy { system "rm -rf /LJ/$LENTA" || warn "Cannot remove /LJ/$LENTA/: $!\n"; mkdir "$LENTA" || warn "Cannot create /LJ/$LENTA/: $!\n"; my @topdir = glob "*"; my @users = (); foreach (@topdir) { next if (! (-d $_)); next if ((! (-d "$_/2001")) && (! (-d "$_/2002"))); push (@users, $_); } # print "Users:"; print @users; my $year=0; my $month=0; foreach $year (2001..2002) { mkdir "$LENTA/$year" || warn "Cannot create /LJ/$LENTA/$year: $!\n"; foreach $month (1..12) { next if (($year == 2001) and ($month == 1)); next if (($year == 2002) and ($month > 10)); mkdir "$LENTA/$year/$month" || warn "Cannot create $LENTA/$year/$month: $!\n";; my $user=""; foreach $user (@users) { # Now copying all LJ-files from $user/$year/$month # to the lenta directory my $dir = "$user/$year/$month"; my @file_list = glob("$dir/*"); # print "All files in directory $user/$year/$month\n"; # print @file_list; my @files =(); my $file = ""; # Testing the files in file_list, adding them to @files if passed foreach $file (@file_list) { # print "Testing $file...\n"; next if (! (-f $file)); next if ($file =~ /index[0-9]*\.html/); push (@files, $file); } # List of files is found # print "list of files to make ljdir: "; print "@files\n"; foreach $file (@files) { system "cp -i $file $LENTA/$year/$month" || die "Couldn't copy $file to $LENTA/$year/$month: $!\n"; } } } } } sub friends_clean # Cleans the friends directory after lj_lenta is run { my $year=0; my $month=0; print "Cleaning the lenta dir ($LENTA)...\n"; foreach $year (2001..2002) { foreach $month (1..12) { my $dir = "$LENTA/$year/$month"; my @file_list = glob("$dir/*"); my $file = ""; foreach $file (@file_list) { # print "Testing $file...\n"; if (! ($file =~ /index[0-9]*\.html/)) { unlink $file || die "Cannot unlink $file: $!\n"; } } } } } ########################################################################## ########################################################################## # Subroutine lj_user # given a directory of LJ entries produced by ljsm-strip, # sets $HEAD and $FOOT files and runs lj_dir in all user's # directories # # The header/footer should contain the following. # 1. The links to LJ-archive pages (same for all pages of LJ-archive) # a). Introduction b). Lenta c). http://lj.eonline.ru/ (Anything else? Hm...) # We should also put reklama.cgi and :LENIN: logo to the footer # (the very bottom part). # 2. User-specific links: intro, archives, # index-ljsm.html, memories, monthly archives, LJ-userinfo, # adding the user to friend-list (Anything else? Hm...) # We should set the title "user's Livejournal archives - YYYY/MM" # and set the

header on top the same. sub lj_user { my $user = $_[0]; # Let's find all user's monthly directories my @monthly = glob ("$user/[0-9][0-9][0-9][0-9]/[0-9][0-9] $user/[0-9][0-9][0-9][0-9]/[0-9]"); my %months = (); # print "Monthly...\n"; print @monthly; foreach (@monthly) { if ((/\/(\d\d\d\d\/\d\d)/ || /\/(\d\d\d\d\/\d)/) && (-d $_)) { $months{$1}=1; # print "Directory $1 found...\n"; } } # print "Months...\n"; # print map { "$_ => $months{$_}\n" } keys %months; # Now make the user's personal bar my @userbar= ( "
[ \u$user\'s Livejournal  |  info  |  Add this user  |  Архивы \u$user  |  Оглавление  |  "); push (@userbar, (-d "$user/memories") ? " memories ]
" : " memories ]
"); my $year=2001; my $month=0; foreach $month (2..12) { my $monthyear = ""; $monthyear = $year."/".$month; if (defined ($months{$monthyear})) { push (@userbar, " $month  |  ") } else{ push (@userbar, " $month  |  "); } } push (@userbar, " "); $year=2002; foreach $month (1..10) { my $monthyear = ""; $monthyear = $year."/".$month; if (defined ($months{$monthyear})) { push (@userbar, " $month  |  ") } else{ push (@userbar, " $month  |  "); } } push (@userbar, "
"); $FOOT= "

". join("\n", @userbar). $FOOTER; $HEAD = $HEADER . join("\n", @userbar) . "

"; $HEAD =~s/Livejournal.com \(02.2001/Livejournal.com \(\u$user:<\/a> 02.2001/; open (HDR, ">$user/.header") || die ("couldn't open $user/.header: $!"); print HDR $HEAD || die ("couldn't write to $user/.header: $!"); close (HDR) || die ("couldn't close $user/.header: $!"); open (FTR, ">$user/.footer") || die ("couldn't open $user/.footer: $!"); print FTR $FOOT || die ("couldn't write to $user/.footer: $!"); close (FTR) || die ("couldn't close $user/.footer: $!"); # The userbar is done! Now for the directories foreach (@monthly) { # print "Entering $_..."; lj_dir ($_); } my $MAXENT_orig = $MAXENT; $MAXENT = $MEM_MAXENT; lj_dir ("$user/memories") if (-d "$user/memories"); $MAXENT = $MAXENT_orig; } ########################################################################## ########################################################################## # Subroutine lj_dir # 1. Reads all files in a given directory # containing # 2. parses the files, extracting mood, # music, number of comments, picture, date # 3. Creates index files with $MAXENT entries, sequentially. sub lj_dir { my $dir=$_[0]; my @file_list = glob("$dir/*"); my @files =(); my $file = ""; # Testing the files in file_list, adding them to @files if passed foreach $file (@file_list) { next if (! (-f $file)); next if ($file =~ /index[0-9]*\.html/); open (FILE, "< $file") || die ("couldn't open $file: $!\n"); while () { if (//) { push (@files, $file); last; } } close (FILE); } # List of files is found # print "list of files to make ljdir: "; print "@files\n"; # Determine the monthline my $monthline =""; if ($dir =~ /\d\d\d\d\/\d/) { my %first = parse_entry ("$files[0]"); my $udate = ParseDate ($first{'date'}); $monthline = UnixDate($udate, "%B %Y"); } else { $monthline = "Memories"; } my $HEAD_orig=$HEAD; my $FOOT_orig=$FOOT; $HEAD =~ s/ljdir.pl title/...With friends like these... ($monthline)/; my $numfiles =0; $numfiles = @files; my $numindexes = $numfiles/$MAXENT +1; my $index=0; my $i=0; for ($index = 1; $index < $numindexes; $index++) { my @result =(); for ($i= (($index-1)*$MAXENT); ($i< $index*($MAXENT) and ($i < $numfiles)); $i++) { my $file = $files[$i]; my $stripped_entry = strip($file); push (@result, $stripped_entry) } # Making links to other indexes in the same directory my @indices_bar=(); my $j=0; for ($j=1; $j< $numindexes; $j++) { my $numentries = ""; $numentries .= ($j-1)*$MAXENT. "-" ; $numentries .= ($j*$MAXENT-1<$numfiles) ? $j*$MAXENT-1 : $numfiles; push (@indices_bar, "|  $numentries\  "); } my $numentries = ""; $numentries .= ($index-1)*$MAXENT. "-"; $numentries .= ($index*$MAXENT-1<$numfiles) ? $index*$MAXENT-1 : $numfiles; $indices_bar[$index-1] ="|  $numentries  "; push(@indices_bar, " |

"); # print "Processing $monthline...\n"; my $table_tops = ($numindexes > 19) ? "

\n"; # Left cell is done # The right cell (the body of the message) my $right_cell=""; # Right cell is done. Now making the table $main_table = "
Записи $numentries ($monthline)
" : "

"; $result = "
Записи $numentries ($monthline)
"; unshift(@indices_bar,$table_tops); # print "numindexes=$numindexes\n"; if ($numindexes >2) { push (@result, @indices_bar); unshift (@result, @indices_bar); } push (@result, $FOOT); unshift (@result, $HEAD); # Now writing the file my $indexname= "$dir/index" . "$index" . ".html"; open (INDEX, ">$indexname") || die ("couldn't open $indexname"); print INDEX "@result " || die ("couldn't write to $indexname"); close (INDEX) || die ("couldn't close $indexname"); } if (-l "$dir/index.html") { unlink("$dir/index.html") || warn "couldn't unlink $dir/index.html"; } # print "Symlinking $dir/index1.html to $dir/index.html...\n"; symlink("index1.html" ,"$dir/index.html") || warn "couldn't symlink index1.html to $dir/index.html"; $HEAD=$HEAD_orig; $FOOT=$FOOT_orig; } ########################################################################## ########################################################################## # Routine strip takes a filename and produces # the stripped-down version of its content # suitabe for inclusion into index files sub strip { my $file=$_[0]; my %event= parse_entry ($file); # print " Stripping $file: the hash:\n"; # print map { "$_ => $event{$_}\n" } keys %event; my $ev = \%event; my $url = $ev->{'url'}; if ($ev->{'error'}) { my $result = $ev->{'body'}; $result = "
ERROR
$result

Оригинал сообщения

                                                                     
"; return $result; } my $filename= $file; $filename =~ s/.*\///; my $result = $ev->{'name'}; my $community = $ev->{'community'}; $result .= "
writes in $community " if (defined ($ev->{'community'})); my $udate = ParseDate ($ev->{'date'}) ; my $date = UnixDate($udate, "%H:%M, %B %E %Y"); # print "Date parsed with ParseDate: $date"; $result = "
$result $date
$result
\n\n"; # Top line is done # Now let's do the main table. # The left cell my $user = $ev->{"username"}; my $main_table = (-d ( "/$PATH/$user")) ? "$user" : "$user"; $main_table .= "
[ $community ]" if (defined ($ev->{'community'})); if (defined ($ev->{'pic'})) { my $pic=$ev->{'pic'}; $main_table = $main_table . "
\n"; } else { $main_table = $main_table . "\n"; } $main_table .= "
"; $main_table = "

$main_table
                                                                      
"; if (defined ($ev->{'subject'})) { my $subj = $ev->{'subject'}; $right_cell .= "      $subj
"; } $right_cell .= $ev->{'body'}; # $right_cell .= "

"; if (defined ($ev->{'mood'})) { my $mood = $ev->{'mood'}; $right_cell .= "      Current mood: $mood
"; } if (defined ($ev->{'music'})) { my $music = $ev->{'music'}; $right_cell .= "      Current music: $music
"; } if (defined($ev->{'replies_num'})) { my $rnum = $ev->{'replies_num'}; $right_cell .="       ($rnum replies)" } else { $right_cell .="       (Оригинал сообщения) " } $right_cell .="
$main_table $right_cell
\n\n"; $result .= $main_table; return $result; } ########################################################################## ########################################################################## # Routine parse_entry reads a filename # and produces a hash with the fields ->{mood}, ->{music} ->{body} ->{date} # ->{name} ->{username} ->{picture} ->{subject} ->{url} ->{pic} # ->{replies_num} ->{error} # The field ->{body} is just the event. # Unless it's an error message, # the fields ->{url} ->{body}, ->{date}, # ->{username}, ->{name} are always defined, # the rest is optional. Also, ->{body} is equipped with extra linefeeds # after
, for readability. # Parsing does not work on the entries # from communities. Oh well. sub parse_entry { my $file = $_[0]; open (FILE, "< $file") || die ("couldn't open $file: $!\n"); my @entry = ; close (FILE); my %res =(); my $result = \%res; my $content = join (" ", @entry); # Read the bottom part for url and ->{replies_num}, discard # everything above and below body area tags $content =~ s/.*//s; $content =~ s/