From 89e709d8d593939ab528b81d125fd37d303c4fa9 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Wed, 30 Sep 2020 19:12:29 +0200 Subject: Allow linking a Träwelling account, auto-sync Träwelling→travelynx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit travelynx→Träwelling is still work-in-progress Squashed commit of the following: commit 97faa6e2e6c8d20fba30f2d0f6e78187ceeb72e6 Author: Daniel Friesel Date: Wed Sep 30 18:50:05 2020 +0200 improve traewelling log and tx handling commit 487d7dd728b9d45b731bdc7098cf3358ea2e206e Author: Daniel Friesel Date: Wed Sep 30 18:02:41 2020 +0200 add missing traewelling template commit 0148da2f48d9a52dcddc0ab81f83d8f8ac3062ab Author: Daniel Friesel Date: Wed Sep 30 18:02:35 2020 +0200 improve traewelling pull sync commit 4861a9750f9f2d7621043361d0af6b0a8869a0df Author: Daniel Friesel Date: Tue Sep 29 22:14:24 2020 +0200 wip checkin from traewelling commit f6aeb6f06998a2a7a80f63a7b1b688b1a26b66bd Author: Daniel Friesel Date: Tue Sep 29 18:37:53 2020 +0200 refactor traewelling integration. login and logout are less of a hack now. checkin and checkout are not supported at the moment. --- lib/Travelynx/Model/Traewelling.pm | 204 +++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 lib/Travelynx/Model/Traewelling.pm (limited to 'lib/Travelynx/Model/Traewelling.pm') diff --git a/lib/Travelynx/Model/Traewelling.pm b/lib/Travelynx/Model/Traewelling.pm new file mode 100644 index 0000000..7f08b0d --- /dev/null +++ b/lib/Travelynx/Model/Traewelling.pm @@ -0,0 +1,204 @@ +package Travelynx::Model::Traewelling; + +use strict; +use warnings; +use 5.020; + +use DateTime; + +sub epoch_to_dt { + my ($epoch) = @_; + + # Bugs (and user errors) may lead to undefined timestamps. Set them to + # 1970-01-01 to avoid crashing and show obviously wrong data instead. + $epoch //= 0; + + return DateTime->from_epoch( + epoch => $epoch, + time_zone => 'Europe/Berlin', + locale => 'de-DE', + ); + +} + +sub new { + my ( $class, %opt ) = @_; + + return bless( \%opt, $class ); +} + +sub now { + return DateTime->now( time_zone => 'Europe/Berlin' ); +} + +sub link { + my ( $self, %opt ) = @_; + + my $log = [ [ $self->now->epoch, "Erfolgreich angemeldet" ] ]; + + my $data = { + user_id => $opt{uid}, + email => $opt{email}, + push_sync => 0, + pull_sync => 0, + token => $opt{token}, + data => JSON->new->encode( { log => $log } ), + }; + + $self->{pg}->db->insert( + 'traewelling', + $data, + { + on_conflict => \ +'(user_id) do update set email = EXCLUDED.email, token = EXCLUDED.token, push_sync = false, pull_sync = false, data = null, errored = false, latest_run = null' + } + ); + + return $data; +} + +sub set_user { + my ( $self, %opt ) = @_; + + my $res_h + = $self->{pg} + ->db->select( 'traewelling', 'data', { user_id => $opt{uid} } ) + ->expand->hash; + + $res_h->{data}{user_id} = $opt{trwl_id}; + $res_h->{data}{screen_name} = $opt{screen_name}; + $res_h->{data}{user_name} = $opt{user_name}; + + $self->{pg}->db->update( + 'traewelling', + { data => JSON->new->encode( $res_h->{data} ) }, + { user_id => $opt{uid} } + ); +} + +sub unlink { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + + $self->{pg}->db->delete( 'traewelling', { user_id => $uid } ); +} + +sub get { + my ( $self, $uid ) = @_; + $uid //= $self->current_user->{id}; + + my $res_h + = $self->{pg}->db->select( 'traewelling_str', '*', { user_id => $uid } ) + ->expand->hash; + + $res_h->{latest_run} = epoch_to_dt( $res_h->{latest_run_ts} ); + for my $log_entry ( @{ $res_h->{data}{log} // [] } ) { + $log_entry->[0] = epoch_to_dt( $log_entry->[0] ); + } + + return $res_h; +} + +sub log { + my ( $self, %opt ) = @_; + my $uid = $opt{uid}; + my $message = $opt{message}; + my $is_error = $opt{is_error}; + my $db = $opt{db} // $self->{pg}->db; + my $res_h + = $db->select( 'traewelling', 'data', { user_id => $uid } )->expand->hash; + splice( @{ $res_h->{data}{log} // [] }, 9 ); + unshift( + @{ $res_h->{data}{log} }, + [ $self->now->epoch, $message, $opt{status_id} ] + ); + + if ($is_error) { + $res_h->{data}{error} = $message; + } + $db->update( + 'traewelling', + { + errored => $is_error ? 1 : 0, + latest_run => $self->now, + data => JSON->new->encode( $res_h->{data} ) + }, + { user_id => $uid } + ); +} + +sub set_latest_pull_status_id { + my ( $self, %opt ) = @_; + my $uid = $opt{uid}; + my $status_id = $opt{status_id}; + my $db = $opt{db} // $self->{pg}->db; + + my $res_h + = $db->select( 'traewelling', 'data', { user_id => $uid } )->expand->hash; + + $res_h->{data}{latest_pull_status_id} = $status_id; + + $db->update( + 'traewelling', + { data => JSON->new->encode( $res_h->{data} ) }, + { user_id => $uid } + ); +} + +sub set_latest_push_status_id { + my ( $self, %opt ) = @_; + my $uid = $opt{uid}; + my $status_id = $opt{status_id}; + my $db = $opt{db} // $self->{pg}->db; + + my $res_h + = $db->select( 'traewelling', 'data', { user_id => $uid } )->expand->hash; + + $res_h->{data}{latest_push_status_id} = $status_id; + + $db->update( + 'traewelling', + { data => JSON->new->encode( $res_h->{data} ) }, + { user_id => $uid } + ); +} + +sub set_sync { + my ( $self, %opt ) = @_; + + my $uid = $opt{uid}; + my $push_sync = $opt{push_sync}; + my $pull_sync = $opt{pull_sync}; + + $self->{pg}->db->update( + 'traewelling', + { + push_sync => $push_sync, + pull_sync => $pull_sync + }, + { user_id => $uid } + ); +} + +sub get_push_accounts { + my ($self) = @_; + my $res = $self->{pg}->db->select( + 'traewelling', + [ 'user_id', 'token', 'data' ], + { push_sync => 1 } + ); + return $res->expand->hashes->each; +} + +sub get_pull_accounts { + my ($self) = @_; + my $res = $self->{pg}->db->select( + 'traewelling', + [ 'user_id', 'token', 'data' ], + { pull_sync => 1 } + ); + return $res->expand->hashes->each; +} + +1; -- cgit v1.2.3