1package App::SD::Replica::lighthouse; 2use Any::Moose; 3extends qw/App::SD::ForeignReplica/; 4 5use Params::Validate qw(:all); 6use Memoize; 7 8use URI; 9use Memoize; 10 11use Prophet::ChangeSet; 12 13use constant scheme => 'lighthouse'; 14use constant pull_encoder => 'App::SD::Replica::lighthouse::PullEncoder'; 15use constant push_encoder => 'App::SD::Replica::lighthouse::PushEncoder'; 16 17has lighthouse => ( isa => 'Net::Lighthouse::Project', is => 'rw' ); 18has remote_url => ( isa => 'Str', is => 'rw' ); 19has account => ( isa => 'Str', is => 'rw' ); 20has project => ( isa => 'Str', is => 'rw' ); 21has query => ( isa => 'Str', is => 'rw' ); 22 23our %PROP_MAP = ( state => 'status', title => 'summary' ); 24 25sub BUILD { 26 my $self = shift; 27 28 eval { 29 require Net::Lighthouse::Project; 30 require Net::Lighthouse::User; 31 }; 32 if ($@) { 33 die "SD requires Net::Lighthouse to sync with a Lighthouse server.\n". 34 "'cpan Net::Lighthouse' may sort this out for you"; 35 } 36 37 38 my ( $auth, $account, $project, $query ) = 39 $self->{url} =~ m{^lighthouse:(?:(.*)@)?(.*?)/(.*?)(?:/(.*))?$} 40 or die 41"Can't parse lighthouse server spec. Expected lighthouse:email:password\@account/project/query or lighthouse:token\@account/project/query."; 42 my $server = "http://$account.lighthouseapp.com"; 43 $self->query( $query || 'all' ); 44 45 my ( $email, $password, $token ); 46 if ($auth) { 47 if ( $auth =~ /@/ ) { 48 ( $email, $password ) = split /:/, $auth; 49 } 50 else { 51 $token = $auth; 52 } 53 } 54 55 unless ( $token || $password ) { 56 if ($email) { 57 ( undef, $password ) = $self->prompt_for_login( 58 uri => $server, 59 username => $email, 60 ); 61 } 62 else { 63 ( undef, $token ) = $self->prompt_for_login( 64 uri => $server, 65 username => 'not important', 66 secret_prompt => sub { 67 "token for $server: "; 68 } 69 ); 70 } 71 } 72 73 $self->remote_url($server); 74 $self->account( $account ); 75 $self->project( $project ); 76 77 my $lighthouse = Net::Lighthouse::Project->new( 78 auth => { 79 $email ? ( email => $email, password => $password ) : (), 80 $token ? ( token => $token ) : (), 81 }, 82 account => $account, 83 ); 84 $lighthouse->load( $project ); 85 $self->lighthouse( $lighthouse ); 86} 87 88 89sub get_txn_list_by_date { 90 my $self = shift; 91 my $ticket = shift; 92 my $ticket_obj = $self->lighthouse->ticket; 93 $ticket_obj->load($ticket); 94 95 my $sequence = 0; 96 my @txns = map { 97 { 98 id => $sequence++, 99 creator => $_->creator_name, 100 created => $_->created_at->epoch, 101 } 102 } $ticket_obj->versions; 103 104 if ( $ticket_obj->attachments ) { 105 my $user = Net::Lighthouse::User->new( 106 map { $_ => $self->sync_source->lighthouse->$_ } 107 grep { $self->sync_source->lighthouse->$_ } 108 qw/account email password token/ 109 ); 110 for my $att ( $ticket_obj->attachments ) { 111 $user->load( $att->uploader_id ); 112 push @txns, 113 { 114 id => $att->id, 115 creator => $user->name, 116 created => $att->created_at->epoch, 117 }; 118 } 119 @txns = sort { $a->created <=> $b->created } @txns; 120 } 121 return @txns; 122} 123 124sub foreign_username { 125 my $self = shift; 126 my $user = 127 Net::Lighthouse::User->new( map { $_ => $self->lighthouse->$_ } 128 grep { $self->lighthouse->$_ } qw/account email password token/ ); 129 130 if ( $user->token ) { 131 # so we use token, let's try to find user's name 132 require Net::Lighthouse::Token; 133 my $token = Net::Lighthouse::Token->new( 134 map { $_ => $self->lighthouse->$_ } 135 grep { $self->lighthouse->$_ } qw/account token/ 136 ); 137 $token->load( $self->lighthouse->token ); 138 my $user = Net::Lighthouse::User->new( 139 map { $_ => $self->lighthouse->$_ } 140 grep { $self->lighthouse->$_ } qw/account token/ 141 ); 142 $user->load( $token->user_id ); 143 return $user->name; 144 } 145 else { 146 # TODO we can't get user's name via email :/ 147 # wish they augment the api so we can load via email 148 return $1 if $user->email =~ /(.*?)@/; 149 } 150} 151 152sub _uuid_url { 153 my $self = shift; 154 Carp::cluck "- can't make a uuid for this" unless ($self->remote_url && $self->account && $self->project ); 155 return join( '/', $self->remote_url, $self->project ); 156} 157 158sub remote_uri_path_for_comment { 159 my $self = shift; 160 my $id = shift; 161 return "/comment/".$id; 162} 163 164sub remote_uri_path_for_id { 165 my $self = shift; 166 my $id = shift; 167 return "/ticket/".$id; 168} 169 170sub database_settings { 171 my $self = shift; 172 return { 173 project_name => $self->account . '/' . $self->project, 174 active_statuses => [ $self->lighthouse->open_states_list ], 175 statuses => [ 176 @{ $self->lighthouse->open_states_list }, 177 @{ $self->lighthouse->closed_states_list } 178 ], 179 milestones => [ '', map { $_->title } $self->lighthouse->milestones ], 180 default_milestone => '', 181 }; 182 183} 184 185__PACKAGE__->meta->make_immutable; 186no Any::Moose; 1871; 188