From 2ddab756440333fb42a9813df87b978a82e490d2 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Mon, 6 May 2019 16:59:48 +0200 Subject: basic webhook support, onwards to betatesting --- lib/Travelynx.pm | 84 ++++++++++++++++++++++++++++++++++--- lib/Travelynx/Controller/Account.pm | 1 + lib/Travelynx/Controller/Api.pm | 65 +--------------------------- templates/webhooks.html.ep | 35 +++++++++++----- 4 files changed, 106 insertions(+), 79 deletions(-) diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index f058eee..51fe1a2 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -574,9 +574,10 @@ sub startup { } if ( $has_arrived or $force ) { - return ( 0, undef ); $self->run_hook( $uid, 'checkout' ); + return ( 0, undef ); } + $self->run_hook( $uid, 'update' ); return ( 1, undef ); } ); @@ -1009,6 +1010,10 @@ sub startup { $opt{uid} //= $self->current_user->{id}; + if ( $opt{token} ) { + $opt{token} =~ tr{\r\n}{}d; + } + my $res = $self->pg->db->insert( 'webhooks', { @@ -1029,8 +1034,8 @@ sub startup { 'mark_hook_status' => sub { my ( $self, $uid, $url, $success, $text ) = @_; - if ( length($text) > 1024 ) { - $text = "(output too long)"; + if ( length($text) > 1000 ) { + $text = substr( $text, 0, 1000 ) . '…'; } $self->pg->db->update( @@ -1059,7 +1064,7 @@ sub startup { return; } - my $status = { todo => 1 }; + my $status = $self->get_user_status_json_v1($uid); my $header = {}; my $hook_body = { reason => $reason, @@ -1067,7 +1072,6 @@ sub startup { }; if ( $hook->{token} ) { - $hook->{token} =~ tr{\r\n}{}d; $header->{Authorization} = "Bearer $hook->{token}"; } @@ -1699,6 +1703,76 @@ sub startup { } ); + $self->helper( + 'get_user_status_json_v1' => sub { + my ( $self, $uid ) = @_; + my $status = $self->get_user_status($uid); + + my $ret = { + deprecated => \0, + checkedIn => ( + $status->{checked_in} + or $status->{cancelled} + ) ? \1 : \0, + fromStation => { + ds100 => $status->{dep_ds100}, + name => $status->{dep_name}, + uic => undef, + longitude => undef, + latitude => undef, + scheduledTime => $status->{sched_departure}->epoch || undef, + realTime => $status->{real_departure}->epoch || undef, + }, + toStation => { + ds100 => $status->{arr_ds100}, + name => $status->{arr_name}, + uic => undef, + longitude => undef, + latitude => undef, + scheduledTime => $status->{sched_arrival}->epoch || undef, + realTime => $status->{real_arrival}->epoch || undef, + }, + train => { + type => $status->{train_type}, + line => $status->{train_line}, + no => $status->{train_no}, + id => $status->{train_id}, + }, + actionTime => $status->{timestamp}->epoch, + }; + + if ( $status->{dep_ds100} ) { + my @station_descriptions + = Travel::Status::DE::IRIS::Stations::get_station( + $status->{dep_ds100} ); + if ( @station_descriptions == 1 ) { + ( + undef, undef, + $ret->{fromStation}{uic}, + $ret->{fromStation}{longitude}, + $ret->{fromStation}{latitude} + ) = @{ $station_descriptions[0] }; + } + } + + if ( $status->{arr_ds100} ) { + my @station_descriptions + = Travel::Status::DE::IRIS::Stations::get_station( + $status->{arr_ds100} ); + if ( @station_descriptions == 1 ) { + ( + undef, undef, + $ret->{toStation}{uic}, + $ret->{toStation}{longitude}, + $ret->{toStation}{latitude} + ) = @{ $station_descriptions[0] }; + } + } + + return $ret; + } + ); + $self->helper( 'get_travel_distance' => sub { my ( $self, $from, $to, $route_ref ) = @_; diff --git a/lib/Travelynx/Controller/Account.pm b/lib/Travelynx/Controller/Account.pm index 75b8f02..c02fb1a 100644 --- a/lib/Travelynx/Controller/Account.pm +++ b/lib/Travelynx/Controller/Account.pm @@ -244,6 +244,7 @@ sub webhook { token => $hook->{token}, enabled => $hook->{enabled} ); + $self->run_hook( $self->current_user->{id}, 'ping' ); $hook = $self->get_webhook; } else { diff --git a/lib/Travelynx/Controller/Api.pm b/lib/Travelynx/Controller/Api.pm index b0047b9..a442784 100755 --- a/lib/Travelynx/Controller/Api.pm +++ b/lib/Travelynx/Controller/Api.pm @@ -142,70 +142,7 @@ sub get_v1 { return; } if ( $api_action eq 'status' ) { - my $status = $self->get_user_status($uid); - - my $ret = { - deprecated => \0, - checkedIn => ( - $status->{checked_in} - or $status->{cancelled} - ) ? \1 : \0, - fromStation => { - ds100 => $status->{dep_ds100}, - name => $status->{dep_name}, - uic => undef, - longitude => undef, - latitude => undef, - scheduledTime => $status->{sched_departure}->epoch || undef, - realTime => $status->{real_departure}->epoch || undef, - }, - toStation => { - ds100 => $status->{arr_ds100}, - name => $status->{arr_name}, - uic => undef, - longitude => undef, - latitude => undef, - scheduledTime => $status->{sched_arrival}->epoch || undef, - realTime => $status->{real_arrival}->epoch || undef, - }, - train => { - type => $status->{train_type}, - line => $status->{train_line}, - no => $status->{train_no}, - id => $status->{train_id}, - }, - actionTime => $status->{timestamp}->epoch, - }; - - if ( $status->{dep_ds100} ) { - my @station_descriptions - = Travel::Status::DE::IRIS::Stations::get_station( - $status->{dep_ds100} ); - if ( @station_descriptions == 1 ) { - ( - undef, undef, - $ret->{fromStation}{uic}, - $ret->{fromStation}{longitude}, - $ret->{fromStation}{latitude} - ) = @{ $station_descriptions[0] }; - } - } - - if ( $status->{arr_ds100} ) { - my @station_descriptions - = Travel::Status::DE::IRIS::Stations::get_station( - $status->{arr_ds100} ); - if ( @station_descriptions == 1 ) { - ( - undef, undef, - $ret->{toStation}{uic}, - $ret->{toStation}{longitude}, - $ret->{toStation}{latitude} - ) = @{ $station_descriptions[0] }; - } - } - - $self->render( json => $ret ); + $self->render( json => $self->get_user_status_json_v1($uid) ); } else { $self->render( diff --git a/templates/webhooks.html.ep b/templates/webhooks.html.ep index fec485d..0bf8cc8 100644 --- a/templates/webhooks.html.ep +++ b/templates/webhooks.html.ep @@ -8,14 +8,9 @@

- Die im Web Hook konfigurierte URL wird bei jedem Checkin und Checkout - des ausgewählten Zuges aufgerufen. Falls ein Token eingetragen - ist, wird er als Bearer Token verwendet. -

-

- Events werden als JSON POST übertragen. Das JSON-Dokument besteht aus - zwei Feldern: „reason“ gibt den Grund des API-Aufrufs an (checkin, - checkout, undo), „status“ den aktuellen Status. + Die im Web Hook konfigurierte URL wird bei Änderungen des aktuellen + Reisestatus (z.B. Checkin oder Ankunft am Ziel) aufgerufen. Falls ein + Token eingetragen ist, wird er als Bearer Token verwendet.

%= form_for '/account/hooks' => (method => 'POST') => begin @@ -28,7 +23,7 @@
link - %= text_field 'url', id => 'url', class => 'validate', maxlength => 1000 + %= text_field 'url', id => 'url', class => 'validate', pattern => 'https?://.+', maxlength => 1000
@@ -38,7 +33,7 @@
% if ($hook->{latest_run}->epoch) { - Zuletzt ausgeführt: <%= $hook->{latest_run} %>
+ Zuletzt ausgeführt <%= $hook->{latest_run}->strftime('am %d.%m.%Y um %H:%M:%S') %>
% if ($hook->{errored}) { error Status: <%= $hook->{output} %> @@ -59,4 +54,24 @@
%= end +
+

Events werden als JSON POST mit folgender Payload übertragen.

+

+ {
+ "reason" : "Grund für den Webhook-Aufruf",
+ "status" : { Aktueller Nutzerstatus }
+ }
+

+

+ Gültige Werte für reason sind derzeit: +

+ Falls der Zug das Ziel bei der Zielwahl schon erreicht hat, wird ohne + update direkt ein checkout abgeschickt. +

-- cgit v1.2.3