[dw-free] Allow importing of your journal from another LiveJournal-based site.
[commit: http://hg.dwscoalition.org/dw-free/rev/821e7159136b]
http://bugs.dwscoalition.org/show_bug.cgi?id=114
More work on the importer. Enable importing friend groups, friends, and
entries. This is still very experimental and needs a way to bubble up
errors to the user.
Patch by
mark.
http://bugs.dwscoalition.org/show_bug.cgi?id=114
More work on the importer. Enable importing friend groups, friends, and
entries. This is still very experimental and needs a way to bubble up
errors to the user.
Patch by
--------------------------------------------------------------------------------
diff -r 913ec83595d8 -r 821e7159136b bin/upgrading/update-db-general.pl
--- a/bin/upgrading/update-db-general.pl Tue Feb 24 09:09:34 2009 +0000
+++ b/bin/upgrading/update-db-general.pl Wed Feb 25 10:25:53 2009 +0000
@@ -3008,6 +3008,21 @@ CREATE TABLE import_data (
)
EOC
+# we don't store this in userprops because we need to index this
+# backwards and load it easily...
+register_tablecreate("import_usermap", <<'EOC');
+CREATE TABLE import_usermap (
+ hostname VARCHAR(255),
+ username VARCHAR(255),
+ identity_userid INT UNSIGNED,
+ feed_userid INT UNSIGNED,
+
+ PRIMARY KEY (hostname, username),
+ INDEX (identity_userid),
+ INDEX (feed_userid)
+)
+EOC
+
# NOTE: new table declarations go ABOVE here ;)
diff -r 913ec83595d8 -r 821e7159136b cgi-bin/DW/Worker/ContentImporter.pm
--- a/cgi-bin/DW/Worker/ContentImporter.pm Tue Feb 24 09:09:34 2009 +0000
+++ b/cgi-bin/DW/Worker/ContentImporter.pm Wed Feb 25 10:25:53 2009 +0000
@@ -83,91 +83,6 @@ sub merge_watch {
}
-=head2 C<< $class->post_event( $user, $hashref, $event, $item_errors ) >>
-
-$event is a hashref representation of a single entry, with the following format:
-
- {
- subject => 'My Entry',
- event => 'I DID STUFF!!!!!',
- security => 'usemask',
- allowmask => 1,
-
- eventtime => 'yyyy-mm-dd hh:mm:ss',
- props => {
- heres_a_userprop => "there's a userprop",
- and_another_little => "userprop",
- }
- key => 'some_uniqe_key', # generally the permalink to the old entry, otherwise something unique (across *all* import sources possible)
- url => 'http://permalink.tld/', # permalink to the old entry
- }
-
-$item_errors is an arrayref of errors to be formatted nicely with a link to old and new entries.
-
-=cut
-sub post_event {
- my ( $class, $u, $opts, $evt, $item_errors ) = @_;
-
- return if $opts->{entry_map}->{$evt->{key}};
-
- my ( $yr, $month, $day, $hr, $min, $sec ) = $evt->{eventtime} =~ m/([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})/;
- my %proto = (
- lineendings => 'unix',
- subject => $evt->{subject},
- event => $evt->{event},
- security => $evt->{security},
- allowmask => $evt->{allowmask},
-
- year => $yr,
- mon => $month,
- day => $day,
- hour => $hr,
- min => $min,
- );
-
- my $props = $evt->{props};
-
- # this is a list of props that actually exist on this site
- # but have been shown to cause failures importing that entry.
- my %bad_props = (
- current_coords => 1,
- );
- foreach my $prop ( keys %$props ) {
- my $p = LJ::get_prop( "log", $prop );
-
- # skip over system and non-existant props
- next unless $p;
- next if ( $p->{ownership} eq 'system' );
- next if ( $bad_props{$prop} );
-
- $proto{"prop_$prop"} = $props->{$prop};
- };
-
- # Overwrite these here in case we're importing from an imported journal (hey, it could happen)
- $proto{prop_opt_backdated} = '1';
- $proto{prop_import_source} = $evt->{key};
-
- my %res;
- LJ::do_request({ 'mode' => 'postevent',
- 'user' => $u->{'user'},
- 'ver' => $LJ::PROTOCOL_VER,
- %proto },
- \%res, { 'u' => $u,
- 'noauth' => 1, });
-
- my $errors = $opts->{errors};
- if ( $res{success} eq 'FAIL' ) {
- push @$errors, "Entry from $evt->{url}: $res{errmsg}";
- } else {
- my $itemid = $res{itemid};
- $u->do( "UPDATE log2 SET logtime = ? where journalid = ? and jitemid = ?", undef, $evt->{realtime}, $u->userid, $itemid );
- $opts->{entry_map}->{$evt->{key}} = $itemid;
- foreach my $err ( @$item_errors ) {
- push @$errors, "Entry at $res{url}: $err ( from $evt->{url} )";
- }
- }
-}
-
=head2 C<< $class->post_event( $user, $hashref, $comment ) >>
$event is a hashref representation of a single comment, with the following format:
@@ -228,31 +143,6 @@ sub insert_comment {
my $jtalkid = LJ::Talk::Post::enter_imported_comment( $u, $parent, $item, $comment, $date, \$errref );
return undef unless $jtalkid;
return $jtalkid;
-}
-
-=head2 C<< $class->get_entry_map( $user, $hashref )
-
-Returns a hashref mapping import_source keys to jitemids
-
-=cut
-sub get_entry_map {
- my ( $class, $u, $opts ) = @_;
- return $opts->{entry_map} if $opts->{entry_map};
-
- my $p = LJ::get_prop( "log", "import_source" );
- return {} unless $p;
-
- my $dbr = LJ::get_cluster_reader( $u );
- my %map;
- my $sth = $dbr->prepare( "SELECT jitemid, value FROM logprop2 WHERE journalid = ? AND propid = ?" );
-
- $sth->execute( $u->id, $p->{id} );
-
- while ( my ( $jitemid, $value ) = $sth->fetchrow_array ) {
- $map{$value} = $jitemid;
- }
-
- return \%map;
}
=head2 C<< $class->get_comment_map( $user, $hashref )
@@ -389,4 +279,4 @@ sub ok {
}
-1;
\ No newline at end of file
+1;
diff -r 913ec83595d8 -r 821e7159136b cgi-bin/DW/Worker/ContentImporter/LiveJournal.pm
--- a/cgi-bin/DW/Worker/ContentImporter/LiveJournal.pm Tue Feb 24 09:09:34 2009 +0000
+++ b/cgi-bin/DW/Worker/ContentImporter/LiveJournal.pm Wed Feb 25 10:25:53 2009 +0000
@@ -316,25 +316,56 @@ sub get_feed_account_from_url {
return undef;
}
+sub get_remapped_userids {
+ my ( $class, $data, $user ) = @_;
+
+ return @{ $MAPS{$data->{hostname}}->{$user} }
+ if exists $MAPS{$data->{hostname}}->{$user};
+
+ my $dbh = LJ::get_db_writer()
+ or return;
+ my ( $oid, $fid ) = $dbh->selectrow_array(
+ 'SELECT identity_userid, feed_userid FROM import_usermap WHERE hostname = ? AND username = ?',
+ undef, $data->{hostname}, $user
+ );
+
+ unless ( defined $oid ) {
+ warn "[$$] Remapping identity userid of $data->{hostname}:$user\n";
+ $oid = $class->remap_username_friend( $data, $user );
+ warn " IDENTITY USERID IS STILL UNDEFINED\n"
+ unless defined $oid;
+ }
+
+ unless ( defined $fid ) {
+ warn "[$$] Remapping feed userid of $data->{hostname}:$user\n";
+ $fid = $class->remap_username_feed( $data, $user );
+ warn " FEED USERID IS STILL UNDEFINED\n"
+ unless defined $fid;
+ }
+
+ $dbh->do( 'REPLACE INTO import_usermap (hostname, username, identity_userid, feed_userid) VALUES (?, ?, ?, ?)',
+ undef, $data->{hostname}, $user, $oid, $fid );
+ $MAPS{$data->{hostname}}->{$user} = [ $oid, $fid ];
+
+ return ( $oid, $fid );
+}
+
sub remap_username_feed {
my ( $class, $data, $username ) = @_;
# canonicalize username and try to return
$username =~ s/-/_/g;
- return $MAPS{feed_map}->{$username}
- if defined $MAPS{feed_map}->{$username};
# don't allow identity accounts (they're not feeds by default)
return undef
if $username =~ m/^ext_/;
# fall back to getting it from the ATOM data
- my $url = "http://$data->{hostname}/~$username/data/atom";
+ my $url = "http://www.$data->{hostname}/~$username/data/atom";
my $acct = $class->get_feed_account_from_url( $data, $url, $username )
or return undef;
- # store it and return
- return $MAPS{feed_map}->{$username} = $acct;
+ return $acct;
}
sub remap_username_friend {
@@ -343,9 +374,6 @@ sub remap_username_friend {
# canonicalize username, in case they gave us a URL version, convert it to
# the one we know sites use
$username =~ s/-/_/g;
-
- return $MAPS{friend_map}->{$username}
- if defined $MAPS{friend_map}->{$username};
if ( $username =~ m/^ext_/ ) {
my $ua = LJ::get_useragent(
@@ -366,35 +394,33 @@ sub remap_username_friend {
if ( $url =~ m!http://(.+)\.$LJ::DOMAIN\/$! ) {
# this appears to be a local user!
# Map this to the local userid in feed_map too, as this is a local user.
- my $luid = LJ::User->new_from_url( $url )->id;
- $MAPS{feed_map}->{$username} = $luid;
- return $luid;
+ return LJ::User->new_from_url( $url )->id;
}
my $iu = LJ::User::load_identity_user( 'O', $url, undef )
or return undef;
- $MAPS{friend_map}->{$username} = $iu->userid;
+ return $iu->id;
} else {
my $url_prefix = "http://$data->{hostname}/~" . $username;
my ( $foaf_items ) = $class->get_foaf_from( $url_prefix )
or return undef;
+ # if they don't have an identity section (but foaf was successful
+ # or we would have returned undef above), then they are a community
+ # or some other account without. return 0 to signify this.
my $ident = $foaf_items->{identity}->{url}
- or return undef;
- $MAPS{ident_map}->{$username} = $ident;
+ or return 0;
my $iu = LJ::User::load_identity_user( 'O', $ident, undef )
or return undef;
- $MAPS{friend_map}->{$username} = $iu->userid;
+ return $iu->id;
}
-
- return $MAPS{friend_map}->{$username};
}
sub remap_lj_user {
- my ( $class, $server, $event ) = @_;
- $event =~ s/(<lj.+?(user|comm|syn)=["']?(.+?)["' ]?>)/<lj site="$server" $2="$3">/gi;
+ my ( $class, $data, $event ) = @_;
+ $event =~ s/(<lj.+?(user|comm|syn)=["']?(.+?)["' ]?>)/<lj site="$data->{hostname}" $2="$3">/gi;
return $event;
}
@@ -422,6 +448,7 @@ sub xmlrpc_call_helper {
my $res;
eval { $res = $xmlrpc->call($method, $req); };
if ( $res && $res->fault ) {
+ warn "XMLRPC fault: " . join( ', ', map { "$_:" . $res->fault->{$_} } keys %{$res->fault || {}} ) . "\n";
return { fault => 1 };
}
diff -r 913ec83595d8 -r 821e7159136b cgi-bin/DW/Worker/ContentImporter/LiveJournal/Bio.pm
--- a/cgi-bin/DW/Worker/ContentImporter/LiveJournal/Bio.pm Tue Feb 24 09:09:34 2009 +0000
+++ b/cgi-bin/DW/Worker/ContentImporter/LiveJournal/Bio.pm Wed Feb 25 10:25:53 2009 +0000
@@ -60,7 +60,7 @@ sub try_work {
DW::Worker::ContentImporter::Local::Bio->merge_interests( $u, $interests );
- $items->{bio} = $class->remap_lj_user( $data->{hostname}, $items->{bio} );
+ $items->{bio} = $class->remap_lj_user( $data, $items->{bio} );
DW::Worker::ContentImporter::Local::Bio->merge_bio_items( $u, $items );
return $ok->();
diff -r 913ec83595d8 -r 821e7159136b cgi-bin/DW/Worker/ContentImporter/LiveJournal/Entries.pm
--- a/cgi-bin/DW/Worker/ContentImporter/LiveJournal/Entries.pm Tue Feb 24 09:09:34 2009 +0000
+++ b/cgi-bin/DW/Worker/ContentImporter/LiveJournal/Entries.pm Wed Feb 25 10:25:53 2009 +0000
@@ -45,30 +45,24 @@ sub try_work {
# setup
my $u = LJ::load_userid( $data->{userid} )
or return $fail->( 'Unable to load target with id %d.', $data->{userid} );
+ my $entry_map = DW::Worker::ContentImporter::Local::Entries->get_entry_map( $u );
- # temporary failure, this code hasn't been ported yet
- return $fail->( 'oops, not ready yet' );
-}
-
-1;
-__END__
-
-### WORK GOES HERE
- $opts->{entry_map} = DW::Worker::ContentImporter->get_entry_map($u,$opts);
- my $synccount = 0;
- my $lastsync = 0;
- my %sync;
- while (1) {
- DW::Worker::ContentImporter->ratelimit_request( $opts );
- my $hash = call_xmlrpc( $opts, 'syncitems', {lastsync => $lastsync} );
+ # load the syncitems list; but never try to load the same lastsync time twice, just
+ # in case
+ my ( $lastsync, %tried_syncs, %sync );
+ while ( $tried_syncs{$lastsync} < 2 ) {
+ warn "[$$] Attempting lastsync = " . ( $lastsync || 'undef' ) . "\n";
+ my $hash = $class->call_xmlrpc( $data, 'syncitems', { lastsync => $lastsync } );
foreach my $item ( @{$hash->{syncitems} || []} ) {
- next unless $item->{item} =~ /L-(\d+)/;
- $synccount++;
+ next unless $item->{item} =~ /^L-(\d+)$/;
$sync{$1} = [ $item->{action}, $item->{time} ];
- $lastsync = $item->{time} if $item->{'time'} gt $lastsync;
+ $lastsync = $item->{time}
+ if !defined $lastsync || $item->{time} gt $lastsync;
+ $tried_syncs{$lastsync}++;
}
+ warn " count $hash->{count} == total $hash->{total}\n";
last if $hash->{count} == $hash->{total};
}
@@ -77,30 +71,44 @@ __END__
return $sync{$id}->[1] if @{$sync{$id} || []};
};
- my $lastgrab = 0;
- while (1) {
+ # now get the actual events
+ while ( scalar( keys %sync ) > 0 ) {
my $count = 0;
- DW::Worker::ContentImporter->ratelimit_request( $opts );
- my $hash = call_xmlrpc( $opts, 'getevents', { selecttype => 'syncitems', lastsync => $lastgrab, ver => 1, lineendings => 'unix', });
+
+ # calculate what time to get entries for
+ my @keys = sort { $sync{$a}->[1] cmp $sync{$b}->[1] } keys %sync;
+ my $lastgrab = LJ::mysql_time( LJ::mysqldate_to_time( $sync{$keys[0]}->[1] ) - 1 );
+
+ warn "[$$] Fetching from lastsync = $lastgrab forward\n";
+ my $hash = $class->call_xmlrpc( $data, 'getevents',
+ {
+ ver => 1,
+ lastsync => $lastgrab,
+ selecttype => 'syncitems',
+ lineendings => 'unix',
+ }
+ );
foreach my $evt ( @{$hash->{events} || []} ) {
$count++;
+
$evt->{realtime} = $realtime->( $evt->{itemid} );
- $lastgrab = $evt->{realtime} if $evt->{realtime} gt $lastgrab;
$evt->{key} = $evt->{url};
# skip this if we've already dealt with it before
- next if $opts->{entry_map}->{$evt->{key}};
+ warn " [$evt->{itemid}] $evt->{url} // $evt->{realtime} // map=$entry_map->{$evt->{key}}\n";
+ my $sync = delete $sync{$evt->{itemid}};
+ next if $entry_map->{$evt->{key}} || !defined $sync;
+
# clean up event for LJ
-
my @item_errors;
# remap friend groups
my $allowmask = $evt->{allowmask};
- my $newmask = remap_groupmask( $opts, $allowmask );
+ my $newmask = $class->remap_groupmask( $data, $allowmask );
- # Bah. Assume private. This shouldn't relaly happen, but
- # a good sanity check.
+ # if we are unable to determine a good groupmask, then fall back to making
+ # the entry private and mark the error.
if ( $allowmask != 1 && $newmask == 1 ) {
$newmask = 0;
push @item_errors, "Could not determine groups.";
@@ -128,19 +136,26 @@ __END__
push @item_errors, "Entry contained a template tag, please manually re-add the templated content.";
}
- $evt->{event} = remap_lj_user( $opts, $event );
+ $evt->{event} = $class->remap_lj_user( $data, $event );
# actually post it
- DW::Worker::ContentImporter->post_event( $u, $opts, $evt, \@item_errors );
+ my $res = DW::Worker::ContentImporter::Local::Entries->post_event( $data, $entry_map, $u, $evt, \@item_errors );
+
+# FIXME: do something with the return code and @item_errors ... other than
+# printing them to STDERR of course ...
+ if ( $res ) {
+ warn " imported!\n";
+ } else {
+ warn " failed!\n";
+ }
+ warn " $_\n" foreach @item_errors;
}
- last unless $count && $lastgrab;
+ warn " count = $count && lastgrab = $lastgrab\n";
}
-
- $opts->{no_entries} = 1;
return $ok->();
}
-1;
\ No newline at end of file
+1;
diff -r 913ec83595d8 -r 821e7159136b cgi-bin/DW/Worker/ContentImporter/LiveJournal/Friends.pm
--- a/cgi-bin/DW/Worker/ContentImporter/LiveJournal/Friends.pm Tue Feb 24 09:09:34 2009 +0000
+++ b/cgi-bin/DW/Worker/ContentImporter/LiveJournal/Friends.pm Wed Feb 25 10:25:53 2009 +0000
@@ -51,23 +51,31 @@ sub try_work {
my ( @friends, @feeds );
foreach my $friend (@{ $r->{friends} || [] }) {
- my $local_userid = $class->remap_username_friend( $data, $friend->{username} );
+ my ( $local_oid, $local_fid ) = $class->get_remapped_userids( $data, $friend->{username} );
+
push @friends, {
- userid => $local_userid,
+ userid => $local_oid,
groupmask => $class->remap_groupmask( $data, $friend->{groupmask} ),
- } if $local_userid;
+ } if $local_oid;
- $local_userid = $class->remap_username_feed( $data, $friend->{username} );
push @feeds, {
fgcolor => $friend->{fgcolor},
bgcolor => $friend->{bgcolor},
- userid => $local_userid,
- } if $local_userid;
+ userid => $local_fid,
+ } if $local_fid;
}
DW::Worker::ContentImporter->merge_trust( $u, $opts, \@friends );
DW::Worker::ContentImporter->merge_watch( $u, $opts, \@feeds );
+ # schedule events import
+ my $dbh = LJ::get_db_writer();
+ $dbh->do(
+ q{UPDATE import_items SET status = 'ready'
+ WHERE userid = ? AND item = 'lj_entries' AND import_data_id = ? AND status = 'init'},
+ undef, $u->id, $opts->{import_data_id}
+ );
+
return $ok->();
}
diff -r 913ec83595d8 -r 821e7159136b cgi-bin/DW/Worker/ContentImporter/Local/Entries.pm
--- a/cgi-bin/DW/Worker/ContentImporter/Local/Entries.pm Tue Feb 24 09:09:34 2009 +0000
+++ b/cgi-bin/DW/Worker/ContentImporter/Local/Entries.pm Wed Feb 25 10:25:53 2009 +0000
@@ -26,7 +26,135 @@ DW::Worker::ContentImporter::Local::Entr
These functions are part of the Saving API for entries.
+=head2 C<< $class->get_entry_map( $user, $hashref )
+
+Returns a hashref mapping import_source keys to jitemids
+
=cut
+sub get_entry_map {
+ my ( $class, $u ) = @_;
-1;
\ No newline at end of file
+ my $p = LJ::get_prop( "log", "import_source" );
+ return {} unless $p;
+
+ my $dbr = LJ::get_cluster_reader( $u );
+ my %map;
+ my $sth = $dbr->prepare( "SELECT jitemid, value FROM logprop2 WHERE journalid = ? AND propid = ?" );
+
+ $sth->execute( $u->id, $p->{id} );
+
+ while ( my ( $jitemid, $value ) = $sth->fetchrow_array ) {
+ $map{$value} = $jitemid;
+ }
+
+ return \%map;
+}
+
+=head2 C<< $class->post_event( $hashref, $u, $event, $item_errors ) >>
+
+$event is a hashref representation of a single entry, with the following format:
+
+ {
+ # standard event values
+ subject => 'My Entry',
+ event => 'I DID STUFF!!!!!',
+ security => 'usemask',
+ allowmask => 1,
+ eventtime => 'yyyy-mm-dd hh:mm:ss',
+ props => {
+ heres_a_userprop => "there's a userprop",
+ and_another_little => "userprop",
+ }
+
+ # the key is a uniquely opaque string that identifies this entry. this must be
+ # unique across all possible import sources. the permalink may work best.
+ key => 'some_unique_key',
+
+ # a url to this entry's original location
+ url => 'http://permalink.tld/',
+ }
+
+$item_errors is an arrayref of errors to be formatted nicely with a link to old and new entries.
+
+Returns 1 on success, undef on error.
+
+=cut
+
+sub post_event {
+ my ( $class, $data, $map, $u, $evt, $errors ) = @_;
+
+ return if $map->{$evt->{key}};
+
+ my ( $yr, $month, $day, $hr, $min, $sec ) = ( $1, $2, $3, $4, $5, $6 )
+ if $evt->{eventtime} =~ m/(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/;
+
+ my %proto = (
+ lineendings => 'unix',
+ subject => $evt->{subject},
+ event => $evt->{event},
+ security => $evt->{security},
+ allowmask => $evt->{allowmask},
+
+ year => $yr,
+ mon => $month,
+ day => $day,
+ hour => $hr,
+ min => $min,
+ );
+
+ my $props = $evt->{props};
+
+ # this is a list of props that actually exist on this site
+ # but have been shown to cause failures importing that entry.
+ my %bad_props = (
+ current_coords => 1,
+ personifi_word_count => 1,
+ personifi_lang => 1,
+ );
+ foreach my $prop ( keys %$props ) {
+ next if $bad_props{$prop};
+
+ my $p = LJ::get_prop( "log", $prop )
+ or next;
+ next if $p->{ownership} eq 'system';
+
+ $proto{"prop_$prop"} = $props->{$prop};
+ };
+
+ # Overwrite these here in case we're importing from an imported journal (hey, it could happen)
+ $proto{prop_opt_backdated} = '1';
+ $proto{prop_import_source} = $evt->{key};
+
+ my %res;
+ LJ::do_request(
+ {
+ mode => 'postevent',
+ user => $u->user,
+ ver => $LJ::PROTOCOL_VER,
+ %proto,
+ },
+ \%res,
+ {
+ u => $u,
+ noauth => 1,
+ }
+ );
+
+ if ( $res{success} eq 'FAIL' ) {
+ push @$errors, "Entry from $evt->{url}: $res{errmsg}";
+ return undef;
+
+ } else {
+ $u->do( "UPDATE log2 SET logtime = ? where journalid = ? and jitemid = ?",
+ undef, $evt->{realtime}, $u->userid, $res{itemid} );
+ $map->{$evt->{key}} = $res{itemid};
+ return 1;
+
+ }
+
+ # flow will never get here
+}
+
+
+1;
diff -r 913ec83595d8 -r 821e7159136b htdocs/misc/import.bml
--- a/htdocs/misc/import.bml Tue Feb 24 09:09:34 2009 +0000
+++ b/htdocs/misc/import.bml Wed Feb 25 10:25:53 2009 +0000
@@ -63,11 +63,15 @@ body<=
['lj_userpics', 'ready'],
['lj_bio', 'ready'],
['lj_tags', 'ready'],
+ ['lj_friendgroups', 'ready'],
+ ['lj_friends', 'init'],
+ ['lj_entries', 'init'],
);
# schedule userpic, bio, and tag imports
foreach my $item (@jobs) {
$dbh->do(
- "INSERT INTO import_items (userid, item, status, created, import_data_id, priority) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP())",
+ "INSERT INTO import_items (userid, item, status, created, import_data_id, priority) " .
+ "VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP())",
undef, $u->id, $item->[0], $item->[1], $id
);
return "Database error." if $dbh->err;
@@ -80,7 +84,8 @@ body<=
my $dbh = LJ::get_db_writer()
or return "No database.";
my $imps = $dbh->selectall_arrayref(
- 'SELECT import_data_id, hostname, username, password_md5 FROM import_data WHERE userid = ? ORDER BY import_data_id DESC LIMIT 10',
+ 'SELECT import_data_id, hostname, username, password_md5 FROM import_data WHERE userid = ? ' .
+ 'ORDER BY import_data_id DESC LIMIT 3',
undef, $u->id
);
@@ -109,7 +114,7 @@ body<=
foreach my $impid ( sort { $b <=> $a } keys %s ) {
my $h = $s{$impid};
$ret .= "<tr><td colspan='4'> </td></tr>";
- $ret .= "<tr><td colspan='4' style='background-color: #cccccc;'>$refresh <strong>$h->{host}</strong> | $h->{user} | $h->{pw}</td></tr>";
+ $ret .= "<tr><td colspan='4' style='background-color: #cccccc;'>$refresh <strong>$h->{host}</strong> | $h->{user}</td></tr>";
foreach my $item ( sort keys %{$h->{items}} ) {
my $i = $h->{items}->{$item};
$ret .= "<tr><td><em>$item</em></td>";
@@ -132,7 +137,8 @@ body<=
$ret .= "<select name='hostname'><option value='livejournal.com'>LiveJournal.com</option></select><br />";
$ret .= "<br />";
$ret .= "Clicking submit below will cause import jobs to be queued to import your userpics, your ";
- $ret .= "tags, and your bio fields. You can check this page for status.";
+ $ret .= "tags, and your bio fields. You can check this page for status.<br />";
+ $ret .= "<strong>This option now imports your friend groups, friends, and entries.</strong><br />";
$ret .= "<input type='submit' value='Do it!'></form>";
return $ret;
}
--------------------------------------------------------------------------------
