diff --git a/application/controllers/Clublog.php b/application/controllers/Clublog.php index b4776344e..c70930189 100644 --- a/application/controllers/Clublog.php +++ b/application/controllers/Clublog.php @@ -76,4 +76,98 @@ class Clublog extends CI_Controller $this->clublog_model->mark_qsos_sent($clean_station_id); } + /* + * Used for displaying the uid for manually selecting log for upload to Clublog + */ + public function export() { + $this->load->model('user_model'); + if(!$this->user_model->authorize(2) || !clubaccess_check(9)) { $this->session->set_flashdata('error', __("You're not allowed to do that!")); redirect('dashboard'); } + + $this->load->model('clublog_model'); + $this->load->model('stations'); + + $data['page_title'] = __("Clublog"); + + $data['station_profiles'] = $this->stations->all_of_user(); + + $data['station_profile'] = $this->clublog_model->stations_with_clublog_enabled(); + $data['callsigns'] = $this->stations->callsigns_of_user($this->session->userdata('user_id')); + + $this->load->model('cron_model'); + $data['next_run_up'] = $this->cron_model->get_next_run("clublog_upload"); + $data['next_run_down'] = $this->cron_model->get_next_run("clublog_download"); + + $footerData = []; + $footerData['scripts'] = [ + 'assets/js/sections/clublog.js?' . filemtime(realpath(__DIR__ . "/../../assets/js/sections/clublog.js")), + ]; + + $this->load->view('interface_assets/header', $data); + $this->load->view('clublog/export'); + $this->load->view('interface_assets/footer', $footerData); + } + + public function uploadlog() { + if (!($this->config->item('disable_manual_clublog'))) { + $this->load->model('clublog_model'); + + $clean_station_id = $this->security->xss_clean($this->input->post('station_id')); + + $users = $this->clublog_model->get_clublog_users($this->session->userdata('user_id')); + + if (!empty($users)) { + foreach ($users as $user) { + $data['status'] = 'OK'; + $data['infomessage'] = $this->clublog_model->uploadUser($user->user_id, $user->user_clublog_name, $user->user_clublog_password, $clean_station_id); + $data['errormessages'] = ''; + } + } else { + $data['status'] = 'Error'; + $data['errormessages'] = __("No user has configured Clublog."); + } + $stationinfo = $this->clublog_model->stations_with_clublog_enabled(); + $info = $stationinfo->result(); + $data['info'] = $info; + + header('Content-type: application/json'); + echo json_encode($data); + } else { + redirect('dashboard'); + } + } + + public function importlog() { + if (!($this->config->item('disable_manual_clublog'))) { + + $this->load->model('user_model'); + if(!$this->user_model->authorize(2)) { $this->session->set_flashdata('error', __("You're not allowed to do that!")); redirect('dashboard'); } + + $data['page_title'] = __("Clublog QSL Import"); + + $this->load->model('clublog_model'); + + $customDate = $this->input->post('date'); + if ($customDate != NULL) { + $clublog_last_date = date($customDate); + } else { + // Query the logbook to determine when the last LoTW confirmation was + $clublog_last_date = null; + } + $users = $this->clublog_model->get_clublog_users($this->session->userdata('user_id')); + + if (!empty($users)) { + foreach ($users as $user) { + $r = $this->clublog_model->downloadUser($user->user_id, $user->user_clublog_name, $user->user_clublog_password, $clublog_last_date); + } + } else { + $r = __("No user has configured Clublog."); + } + + header('Content-type: application/json'); + echo json_encode($r); + } else { + redirect('dashboard'); + } + } + } diff --git a/application/libraries/Clublog.php b/application/libraries/Clublog.php deleted file mode 100644 index 4c690ce49..000000000 --- a/application/libraries/Clublog.php +++ /dev/null @@ -1,38 +0,0 @@ -load->library('curl'); - - // API Key - $key = "608df94896cb9c5421ae748235492b43815610c9"; - - $username = ""; - $password = ""; - - $adif = "".$qso_date."".$time_on."".$qso['call']."".$qso['band']."".$qso['mode']."".$qso['freq']; - - - echo $CI->curl->simple_post('curl_test/message', array('message'=>'Sup buddy')); - - } - public function check(){} -} - -/* End of file Clublog.php */ \ No newline at end of file diff --git a/application/models/Clublog_model.php b/application/models/Clublog_model.php index 34bc8c94d..8e114321e 100644 --- a/application/models/Clublog_model.php +++ b/application/models/Clublog_model.php @@ -3,15 +3,20 @@ class Clublog_model extends CI_Model { - function get_clublog_users() { + private $clublog_identifier = '608df94896cb9c5421ae748235492b43815610c9'; + + function get_clublog_users($userid = null) { $this->db->select('user_clublog_name, user_clublog_password, user_id'); $this->db->where('coalesce(user_clublog_name, "") != ""'); $this->db->where('coalesce(user_clublog_password, "") != ""'); + if ($userid !== null) { + $this->db->where('user_id', $userid); + } $query = $this->db->get($this->config->item('auth_table')); return $query->result(); } - function uploadUser($userid, $username, $password) { + function uploadUser($userid, $username, $password, $station_id = null) { $clean_username = $this->security->xss_clean($username); $clean_passord = $this->security->xss_clean($password); $clean_userid = $this->security->xss_clean($userid); @@ -30,7 +35,7 @@ class Clublog_model extends CI_Model $this->load->library('AdifHelper'); } - $station_profiles = $this->all_with_count($clean_userid); + $station_profiles = $this->all_with_count($clean_userid, $station_id); if ($station_profiles->num_rows()) { foreach ($station_profiles->result() as $station_row) { @@ -72,7 +77,7 @@ class Clublog_model extends CI_Model 'email' => $clean_username, 'password' => $clean_passord, 'callsign' => $station_row->station_callsign, - 'api' => "608df94896cb9c5421ae748235492b43815610c9", + 'api' => $this->clublog_identifier, 'file' => $cFile ) ); @@ -90,25 +95,27 @@ class Clublog_model extends CI_Model // If Clublog Accepts mark the QSOs if (preg_match('/\baccepted\b/', $response)) { - $return = "QSOs uploaded and Logbook QSOs marked as sent to Clublog"; + $return = "QSOs uploaded and Logbook QSOs marked as sent to Clublog."; $this->mark_qsos_sent($station_row->station_id); - $return = "Clublog upload for " . $station_row->station_callsign; + $return .= " Clublog upload for " . $station_row->station_callsign . ' successfully sent.'; log_message('info', 'Clublog upload for ' . $station_row->station_callsign . ' successfully sent.'); } else if (preg_match('/checksum duplicate/', $response)) { - $return = "QSOs uploaded (asduplicate!) and Logbook QSOs marked as sent to Clublog"; + $return = "QSOs uploaded (as duplicate!) and Logbook QSOs marked as sent to Clublog"; $this->mark_qsos_sent($station_row->station_id); - $return = "Clublog upload for " . $station_row->station_callsign; + $return .= " Clublog upload for " . $station_row->station_callsign . ' successfully sent.'; log_message('info', 'Clublog DUPLICATE upload for ' . $station_row->station_callsign . ' successfully sent.'); } else { - $return = "Error " . $response; + $return = 'Clublog upload for ' . $station_row->station_callsign . ' failed reason ' . $response; log_message('error', 'Clublog upload for ' . $station_row->station_callsign . ' failed reason ' . $response); if (substr($response,0,13) == 'Upload denied') { // Deactivate Upload for Station if Clublog rejects it due to non-configured Call (prevent being blacklisted at Clublog) - $sql = 'update station_profile set clublogignore = 1 where station_id = ?'; - $this->db->query($sql,$station_row->station_id); + log_message('info', 'Deactivated upload for station ' . $station_row->station_callsign . ' due to non-configured Call (prevent being blacklisted at Clublog.'); + $sql = 'update station_profile set clublogignore = 1 where station_id = ?'; + $this->db->query($sql,$station_row->station_id); } if (substr($response,0,14) == 'Login rejected') { // Deactivate Upload for Station if Clublog rejects it due to wrong credentials (prevent being blacklisted at Clublog) - $sql = 'update station_profile set clublogignore = 1 where station_id = ?'; - $this->db->query($sql,$station_row->station_id); + log_message('info', 'Deactivated upload for station ' . $station_row->station_callsign . ' due to wrong credentials (prevent being blacklisted at Clublog.'); + $sql = 'update station_profile set clublogignore = 1 where station_id = ?'; + $this->db->query($sql,$station_row->station_id); } } @@ -127,12 +134,12 @@ class Clublog_model extends CI_Model return $return . "\n"; } - function downloadUser($userid, $username, $password) { + function downloadUser($userid, $username, $password, $clublog_last_date = null) { $clean_username = $this->security->xss_clean($username); $clean_password = $this->security->xss_clean($password); $clean_userid = $this->security->xss_clean($userid); - $return = "Nothing to download"; + $return = ''; $this->config->load('config'); @@ -148,8 +155,9 @@ class Clublog_model extends CI_Model if ($station_profiles->num_rows()) { foreach ($station_profiles->result() as $station_row) { - $lastrec = $this->clublog_last_qsl_rcvd_date($station_row->station_callsign); - $url = 'https://clublog.org/getmatches.php?api=608df94896cb9c5421ae748235492b43815610c9&email=' . $clean_username . '&password=' . $clean_password . '&callsign=' . $station_row->station_callsign . '&startyear=' . substr($lastrec, 0, 4) . '&startmonth=' . substr($lastrec, 4, 2) . '&startday=' . substr($lastrec, 6, 2); + $lastrec = $clublog_last_date ?? $this->clublog_last_qsl_rcvd_date($station_row->station_callsign); + $lastrec = str_replace('-', '', $lastrec); + $url = 'https://clublog.org/getmatches.php?api=' . $this->clublog_identifier . '&email=' . $clean_username . '&password=' . $clean_password . '&callsign=' . $station_row->station_callsign . '&startyear=' . substr($lastrec, 0, 4) . '&startmonth=' . substr($lastrec, 4, 2) . '&startday=' . substr($lastrec, 6, 2); $request = curl_init($url); // recieve a file @@ -159,15 +167,17 @@ class Clublog_model extends CI_Model curl_close($request); if (curl_errno($request)) { - $return = curl_error($request); + $log .= curl_error($request)."
"; } elseif (preg_match_all('/Login rejected/', $response)) { $this->disable_sync4call($station_row->station_callsign, $station_row->station_ids); - $return = "Wrong Clublog username and password for Callsign: '" . $station_row->station_callsign . "'. 'LOGIN REJECTED'."; - log_message('debug', $return); + $log = "Wrong Clublog username and password for Callsign: '" . $station_row->station_callsign . "'. 'LOGIN REJECTED'."; + log_message('debug', $log); + $return .= $log."
"; } elseif (preg_match_all('/Invalid callsign/', $response)) { // We're trying to download calls for a station we're not granted. Disable Clublog-Transfer for that station(s) $this->disable_sync4call($station_row->station_callsign, $station_row->station_ids); - $return = "The callsign '" . $station_row->station_callsign . "' does not match the user account at Clublog. 'INVALID CALLSIGN'."; - log_message('debug', $return); + $log = "The callsign '" . $station_row->station_callsign . "' does not match the user account at Clublog. 'INVALID CALLSIGN'."; + log_message('debug', $log); + $return .= $log."
"; } else { try { $cl_qsls = json_decode($response); @@ -175,14 +185,18 @@ class Clublog_model extends CI_Model $this->logbook_model->clublog_update($oneqsl[2], $oneqsl[0], $oneqsl[3], 'Y', $station_row->station_callsign, $station_row->station_ids); } } catch (Exception $e) { - $return = "Something gone wrong while trying to Download for station(s) " . $station_row->station_ids . " / Call: " . $station_row->station_callsign; - log_message("error", $return); + $log = "Something gone wrong while trying to Download for station(s) " . $station_row->station_ids . " / Call: " . $station_row->station_callsign." / Response was: ".$response; + log_message("error", $log); + $return .= $log."
"; } - $return = "QSO's for Callsign: '" . $station_row->station_callsign . "' were successfully downloaded"; - log_message('info', $return); + $log = "QSO's for Callsign: '" . $station_row->station_callsign . "' were successfully downloaded"; + log_message('info', $log); + $return .= $log."
"; } } + } else { + $return = "Nothing to download"; } return $return . "\n"; @@ -288,7 +302,7 @@ class Clublog_model extends CI_Model } function all_enabled($userid) { - $sql = "select sp.station_callsign, group_concat(sp.station_id) as station_ids from station_profile sp + $sql = "select sp.station_callsign, group_concat(sp.station_id) as station_ids from station_profile sp inner join users u on (u.user_id=sp.user_id) where u.user_clublog_name is not null and u.user_clublog_password is not null and sp.clublogignore=0 and u.user_id=? group by sp.station_callsign"; @@ -296,11 +310,14 @@ class Clublog_model extends CI_Model return $query; } - function all_with_count($userid) { + function all_with_count($userid, $station_id) { $this->db->select('station_profile.station_id, station_profile.station_callsign, count(' . $this->config->item('table_name') . '.station_id) as qso_total'); $this->db->from('station_profile'); $this->db->join($this->config->item('table_name'), 'station_profile.station_id = ' . $this->config->item('table_name') . '.station_id', 'left'); $this->db->group_by('station_profile.station_id'); + if ($station_id !== null) { + $this->db->where('station_profile.station_id', $station_id); + } $this->db->where('station_profile.user_id', $userid); $this->db->where('station_profile.clublogignore', 0); $this->db->group_start(); @@ -312,4 +329,73 @@ class Clublog_model extends CI_Model return $this->db->get(); } + + function stations_with_clublog_enabled() { + $bindings=[]; + $sql = "SELECT station_profile.station_id, station_profile.station_profile_name, station_profile.station_callsign, modc.modcount, notc.notcount, totc.totcount + FROM station_profile + LEFT OUTER JOIN ( + SELECT count(*) modcount, station_id + FROM ". $this->config->item('table_name') . + " WHERE COL_CLUBLOG_QSO_UPLOAD_STATUS = 'M' + group by station_id + ) as modc on station_profile.station_id = modc.station_id + LEFT OUTER JOIN ( + SELECT count(*) notcount, station_id + FROM " . $this->config->item('table_name') . + " WHERE (coalesce(COL_CLUBLOG_QSO_UPLOAD_STATUS, '') = '' + or COL_CLUBLOG_QSO_UPLOAD_STATUS = 'N') + group by station_id + ) as notc on station_profile.station_id = notc.station_id + LEFT OUTER JOIN ( + SELECT count(*) totcount, station_id + FROM " . $this->config->item('table_name') . + " WHERE COL_CLUBLOG_QSO_UPLOAD_STATUS = 'Y' + group by station_id + ) as totc on station_profile.station_id = totc.station_id + WHERE coalesce(station_profile.clublogignore, 1) = 0 + AND station_profile.user_id = ?"; + $bindings[]=$this->session->userdata('user_id'); + $query = $this->db->query($sql, $bindings); + + return $query; + } + + function push_qso_to_clublog($cl_username, $cl_password, $station_callsign, $adif) { + + // initialise the curl request + $returner = []; + $request = curl_init('https://clublog.org/realtime.php'); + + curl_setopt($request, CURLOPT_POST, true); + curl_setopt( + $request, + CURLOPT_POSTFIELDS, + array( + 'email' => $cl_username, + 'password' => $cl_password, + 'callsign' => $station_callsign, + 'adif' => $adif, + 'api' => $this->clublog_identifier, + ) + ); + + // output the response + curl_setopt($request, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($request); + $info = curl_getinfo($request); + curl_close($request); + + if (preg_match('/\bOK\b/', $response)) { + $returner['status'] = 'OK'; + } elseif (substr($response,0,14) == 'Login rejected') { // Deactivate Upload for Station if Clublog rejects it due to wrong credentials (prevent being blacklisted at Clublog) + log_message("Error","Clublog deactivated for ".$cl_username." because of wrong creds at Realtime-Pusher"); + $sql = 'update station_profile set clublogignore = 1 where cl_username = ? and cl_password = ?'; + $this->db->query($sql,array($cl_username,$cl_password)); + $returner['status'] = $response; + } else { + $returner['status'] = $response; + } + return ($returner); + } } diff --git a/application/models/Logbook_model.php b/application/models/Logbook_model.php index 1a36edbc3..57691b3e5 100644 --- a/application/models/Logbook_model.php +++ b/application/models/Logbook_model.php @@ -784,7 +784,6 @@ class Logbook_model extends CI_Model { // No point in fetching hrdlog code or qrz api key and qrzrealtime setting if we're skipping the export if (!$skipexport) { - $result = $this->exists_clublog_credentials($data['station_id']); if (isset($result->ucp) && isset($result->ucn) && (($result->ucp ?? '') != '') && (($result->ucn ?? '') != '') && ($result->clublogrealtime == 1)) { if (!$this->load->is_loaded('AdifHelper')) { @@ -792,8 +791,12 @@ class Logbook_model extends CI_Model { } $qso = $this->get_qso($last_id, true)->result(); + if (!$this->load->is_loaded('clublog_model')) { + $this->load->model('clublog_model'); + } + $adif = $this->adifhelper->getAdifLine($qso[0]); - $result = $this->push_qso_to_clublog($result->ucn, $result->ucp, $data['COL_STATION_CALLSIGN'], $adif); + $result = $this->clublog_model->push_qso_to_clublog($result->ucn, $result->ucp, $data['COL_STATION_CALLSIGN'], $adif); if ($result['status'] == 'OK') { $this->mark_clublog_qsos_sent($last_id); } @@ -925,44 +928,6 @@ class Logbook_model extends CI_Model { } } - function push_qso_to_clublog($cl_username, $cl_password, $station_callsign, $adif) { - - // initialise the curl request - $returner = []; - $request = curl_init('https://clublog.org/realtime.php'); - - curl_setopt($request, CURLOPT_POST, true); - curl_setopt( - $request, - CURLOPT_POSTFIELDS, - array( - 'email' => $cl_username, - 'password' => $cl_password, - 'callsign' => $station_callsign, - 'adif' => $adif, - 'api' => "608df94896cb9c5421ae748235492b43815610c9", - ) - ); - - // output the response - curl_setopt($request, CURLOPT_RETURNTRANSFER, true); - $response = curl_exec($request); - $info = curl_getinfo($request); - curl_close($request); - - if (preg_match('/\bOK\b/', $response)) { - $returner['status'] = 'OK'; - } elseif (substr($response,0,14) == 'Login rejected') { // Deactivate Upload for Station if Clublog rejects it due to wrong credentials (prevent being blacklisted at Clublog) - log_message("Error","Clublog deactivated for ".$cl_username." because of wrong creds at Realtime-Pusher"); - $sql = 'update station_profile set clublogignore = 1 where cl_username = ? and cl_password = ?'; - $this->db->query($sql,array($cl_username,$cl_password)); - $returner['status'] = $response; - } else { - $returner['status'] = $response; - } - return ($returner); - } - /* * Function uploads a QSO to HRDLog with the API given. * $adif contains a line with the QSO in the ADIF format. QSO ends with an @@ -3167,7 +3132,7 @@ class Logbook_model extends CI_Model { /* Return total number of QSOs per operator */ function total_operators($yr = 'All') { - + //Load logbook model and get station locations $this->load->model('logbooks_model'); $logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook')); @@ -5586,7 +5551,7 @@ class Logbook_model extends CI_Model { function getContestQSO(array $station_ids, string $station_callsign, string $contest_id, string $callsign, string $band, string $mode, string $date, string $time) { - + //load QSO table $this->db->select('*'); $this->db->from($this->config->item('table_name')); @@ -5617,7 +5582,7 @@ class Logbook_model extends CI_Model { $from_datetime = $datetime->format('Y-m-d H:i:s'); $datetime->add(new DateInterval('PT1M')); $to_datetime = $datetime->format('Y-m-d H:i:s'); - + //load only QSOs during this minute $this->db->where('COL_TIME_ON >=', $from_datetime); $this->db->where('COL_TIME_ON <', $to_datetime); @@ -5627,7 +5592,7 @@ class Logbook_model extends CI_Model { } function set_contest_fields($qso_primary_key, ?int $stx, ?string $stxstring, ?int $srx, ?string $srxstring) { - + //assemble data fields from input $data = $data = array( 'COL_STX' => $stx, @@ -5635,15 +5600,15 @@ class Logbook_model extends CI_Model { 'COL_SRX' => $srx, 'COL_SRX_STRING' => $srxstring == null ? null : substr($srxstring, 0, 32) ); - + //narrow db operation down to 1 QSO $this->db->where(array('COL_PRIMARY_KEY' => $qso_primary_key)); - + //update data and return $this->db->update($this->config->item('table_name'), $data); return; } - + } function validateADIFDate($date, $format = 'Ymd') { diff --git a/application/views/clublog/export.php b/application/views/clublog/export.php new file mode 100644 index 000000000..edb736516 --- /dev/null +++ b/application/views/clublog/export.php @@ -0,0 +1,85 @@ + +
+ +

+ +
+
+ + +
+ +
+
+
+ ".__("The next automatic Upload to Clublog will happen at: ").$next_run_up."

"; } ?> +

+

+result()) { + echo ' + + + + + + + + + + + + '; + foreach ($station_profile->result() as $station) { // Fills the table with the data + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + if (!($this->config->item('disable_manual_clublog'))) { + echo ''; + } else { + echo ''; + } + echo ''; + } + echo '
' . __("Profile name") . '' . __("Station callsign") . '' . __("Edited QSOs not uploaded") . '' . __("Total QSOs not uploaded") . '' . __("Total QSOs uploaded") . '' . __("Actions") . '
' . $station->station_profile_name . '' . $station->station_callsign . '' . $station->modcount . '' . $station->notcount . '' . $station->totcount . ' 
'; + + } + else { + echo ''; + } + ?> + +
+ config->item('disable_manual_clublog'))) { ?> +
+ +
+ ".__("The next automatic Download from Clublog-QSLs will happen at: ").$next_run_down."

"; } ?> +

+
+
+ + +
+
+
+ +
+
+ +
+
+
+
diff --git a/application/views/interface_assets/header.php b/application/views/interface_assets/header.php index 7841ff6bd..bd97e57a4 100644 --- a/application/views/interface_assets/header.php +++ b/application/views/interface_assets/header.php @@ -472,6 +472,7 @@
  • +
  • diff --git a/assets/js/sections/clublog.js b/assets/js/sections/clublog.js new file mode 100644 index 000000000..7ffcfc129 --- /dev/null +++ b/assets/js/sections/clublog.js @@ -0,0 +1,72 @@ +function ExportClublog(station_id) { + if ($(".alert").length > 0) { + $(".alert").remove(); + } + if ($(".errormessages").length > 0) { + $(".errormessages").remove(); + } + $(".ld-ext-right-"+station_id).addClass('running'); + $(".ld-ext-right-"+station_id).prop('disabled', true); + + $.ajax({ + url: base_url + 'index.php/clublog/uploadlog', + type: 'post', + data: {'station_id': station_id}, + success: function (data) { + $(".ld-ext-right-"+station_id).removeClass('running'); + $(".ld-ext-right-"+station_id).prop('disabled', false); + if (data.status == 'OK') { + $.each(data.info, function(index, value){ + $('#modcount'+value.station_id).html(value.modcount); + $('#notcount'+value.station_id).html(value.notcount); + $('#totcount'+value.station_id).html(value.totcount); + }); + $("#export").append(''); + } + else { + $("#export").append(''); + } + + if (data.errormessages.length > 0) { + $("#export").append( + '
    \n' + + '
    \n' + + '
    \n' + + ' Error Message\n' + + '
    \n' + + '
    \n' + + '
    \n' + + '
    \n' + + '
    \n' + + '
    ' + ); + $.each(data.errormessages, function (index, value) { + $(".errors").append('
  • ' + value); + }); + } + } + }); +} + + +function importlog() { + if ($(".alert").length > 0) { + $(".alert").remove(); + } + if ($(".errormessages").length > 0) { + $(".errormessages").remove(); + } + $(".ld-ext-right-import").addClass('running'); + $(".ld-ext-right-import").prop('disabled', true); + + $.ajax({ + url: base_url + 'index.php/clublog/importlog', + type: 'post', + data: {'date': $(".importdate").val()}, + success: function (data) { + $(".ld-ext-right-import").removeClass('running'); + $(".ld-ext-right-import").prop('disabled', false); + $("#import").append(''); + } + }); +}