mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
RR User Interface Improvements, including Premium notices (#992)
* RR UX Improvements, including Premium notices * Fixing Error handling bug in LoginDialog
This commit is contained in:
@@ -41,9 +41,17 @@ sourceSets {
|
||||
test.java.srcDirs 'src/test'
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
// JUnit Tests
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation 'org.assertj:assertj-core:3.8.0'
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
|
||||
|
||||
//Jitpack imports
|
||||
implementation 'com.github.nwaldispuehl:java-lame:v3.98.4'
|
||||
|
||||
@@ -49,6 +49,9 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Login dialog for radioreference.com with support for testing connection to the service.
|
||||
@@ -66,6 +69,7 @@ public class LoginDialog extends Dialog<AuthorizationInformation>
|
||||
private Button mTestConnectionButton;
|
||||
private IconNode mTestPassIcon;
|
||||
private IconNode mTestFailIcon;
|
||||
private IconNode mTextExpiredIcon;
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
@@ -166,6 +170,10 @@ public class LoginDialog extends Dialog<AuthorizationInformation>
|
||||
getTestFailIcon().setVisible(false);
|
||||
GridPane.setConstraints(getTestFailIcon(), 2, 4);
|
||||
mGridPane.getChildren().add(getTestFailIcon());
|
||||
|
||||
getTestExpiredIcon().setVisible(false);
|
||||
GridPane.setConstraints(getTestExpiredIcon(), 2, 4);
|
||||
mGridPane.getChildren().add(getTestExpiredIcon());
|
||||
}
|
||||
|
||||
return mGridPane;
|
||||
@@ -275,6 +283,7 @@ public class LoginDialog extends Dialog<AuthorizationInformation>
|
||||
getTestConnectionButton().setDisable(true);
|
||||
getTestPassIcon().setVisible(false);
|
||||
getTestFailIcon().setVisible(false);
|
||||
getTestExpiredIcon().setVisible(false);
|
||||
|
||||
String userName = getUserNameText().getText();
|
||||
String password = getPasswordField().isVisible() ? getPasswordField().getText() : getPasswordText().getText();
|
||||
@@ -307,13 +316,56 @@ public class LoginDialog extends Dialog<AuthorizationInformation>
|
||||
public void run()
|
||||
{
|
||||
boolean success = false;
|
||||
RadioReference.LoginStatus loginStatus;
|
||||
|
||||
try
|
||||
{
|
||||
success = RadioReference.testConnection(userName, password);
|
||||
loginStatus = RadioReference.testConnectionWithExp(userName, password);
|
||||
|
||||
if(loginStatus == RadioReference.LoginStatus.VALID_PREMIUM)
|
||||
{
|
||||
getTestPassIcon().setVisible(true);
|
||||
getTestFailIcon().setVisible(false);
|
||||
getTestExpiredIcon().setVisible(false);
|
||||
}
|
||||
else if (loginStatus == RadioReference.LoginStatus.EXPIRED_PREMIUM)
|
||||
{
|
||||
getTestPassIcon().setVisible(false);
|
||||
getTestFailIcon().setVisible(false);
|
||||
getTestExpiredIcon().setVisible(true);
|
||||
|
||||
Alert alert = new Alert(Alert.AlertType.WARNING, "You do not have a valid Radio Reference Premium Subscription (it may have expired).", ButtonType.OK);
|
||||
alert.setHeaderText("Expired Premium Account");
|
||||
alert.setTitle("Radio Reference Account issue");
|
||||
alert.initOwner(((Node)getTestConnectionButton()).getScene().getWindow());
|
||||
alert.showAndWait();
|
||||
}
|
||||
else if (loginStatus == RadioReference.LoginStatus.INVALID_LOGIN)
|
||||
{
|
||||
getTestPassIcon().setVisible(false);
|
||||
getTestFailIcon().setVisible(true);
|
||||
getTestExpiredIcon().setVisible(false);
|
||||
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR, "Please verify username and password", ButtonType.OK);
|
||||
alert.setHeaderText("Login Failed");
|
||||
alert.setTitle("Test Failed");
|
||||
alert.initOwner(((Node)getTestConnectionButton()).getScene().getWindow());
|
||||
alert.showAndWait();
|
||||
mLog.error("Login failed. Invalid username or password. Can't login to radioreference.com");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only way to get here is via an exception
|
||||
}
|
||||
}
|
||||
catch(RadioReferenceException rre)
|
||||
{
|
||||
|
||||
// Set an error state
|
||||
getTestPassIcon().setVisible(false);
|
||||
getTestFailIcon().setVisible(true);
|
||||
getTestExpiredIcon().setVisible(false);
|
||||
|
||||
if(rre.getCause() instanceof ConnectException)
|
||||
{
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR, "Please check network or radio reference availability", ButtonType.OK);
|
||||
@@ -327,24 +379,12 @@ public class LoginDialog extends Dialog<AuthorizationInformation>
|
||||
{
|
||||
Fault fault = rre.getFault();
|
||||
|
||||
if(fault.getFaultCode() != null && fault.getFaultCode().contentEquals("AUTH"))
|
||||
{
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR, "Please verify username and password", ButtonType.OK);
|
||||
alert.setHeaderText("Login Failed");
|
||||
alert.setTitle("Test Failed");
|
||||
alert.initOwner(((Node)getTestConnectionButton()).getScene().getWindow());
|
||||
alert.showAndWait();
|
||||
mLog.error("Login failed. Invalid username or password. Can't login to radioreference.com");
|
||||
}
|
||||
else
|
||||
{
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR, fault.getFaultString(), ButtonType.OK);
|
||||
alert.setHeaderText(fault.getFaultCode());
|
||||
alert.setTitle("Test Failed");
|
||||
alert.initOwner(((Node)getTestConnectionButton()).getScene().getWindow());
|
||||
alert.showAndWait();
|
||||
mLog.error("Test failed. Fault [" + fault.toString() + "] Can't login to radioreference.com");
|
||||
}
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR, fault.getFaultString(), ButtonType.OK);
|
||||
alert.setHeaderText(fault.getFaultCode());
|
||||
alert.setTitle("Test Failed");
|
||||
alert.initOwner(((Node)getTestConnectionButton()).getScene().getWindow());
|
||||
alert.showAndWait();
|
||||
mLog.error("Test failed. Fault [" + fault.toString() + "] Can't login to radioreference.com");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -357,8 +397,7 @@ public class LoginDialog extends Dialog<AuthorizationInformation>
|
||||
}
|
||||
}
|
||||
|
||||
getTestPassIcon().setVisible(success);
|
||||
getTestFailIcon().setVisible(!success);
|
||||
|
||||
getTestConnectionButton().setDisable(false);
|
||||
}
|
||||
});
|
||||
@@ -392,4 +431,16 @@ public class LoginDialog extends Dialog<AuthorizationInformation>
|
||||
|
||||
return mTestFailIcon;
|
||||
}
|
||||
|
||||
private IconNode getTestExpiredIcon()
|
||||
{
|
||||
if(mTextExpiredIcon == null)
|
||||
{
|
||||
mTextExpiredIcon = new IconNode(FontAwesome.EXCLAMATION_TRIANGLE);
|
||||
mTextExpiredIcon.setIconSize(32);
|
||||
mTextExpiredIcon.setFill(Color.ORANGERED);
|
||||
}
|
||||
|
||||
return mTextExpiredIcon;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import io.github.dsheirer.rrapi.type.StateInfo;
|
||||
import io.github.dsheirer.service.radioreference.RadioReference;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.Button;
|
||||
@@ -43,12 +44,7 @@ import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.util.StringConverter;
|
||||
import jiconfont.icons.font_awesome.FontAwesome;
|
||||
@@ -67,10 +63,12 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
private PlaylistManager mPlaylistManager;
|
||||
private VBox mTopBox;
|
||||
private HBox mCredentialsBox;
|
||||
private Label mRRStatusText;
|
||||
private TextField mUserNameText;
|
||||
private TextField mAccountExpiresText;
|
||||
private IconNode mTestPassIcon;
|
||||
private IconNode mTestFailIcon;
|
||||
private IconNode mTestExpiredIcon;
|
||||
private Button mLoginButton;
|
||||
private GridPane mComboBoxPane;
|
||||
private ComboBox<Country> mCountryComboBox;
|
||||
@@ -99,13 +97,13 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
|
||||
login();
|
||||
|
||||
if(mRadioReference.availableProperty().get())
|
||||
if(mRadioReference.premiumAccountProperty().get())
|
||||
{
|
||||
refreshCountries();
|
||||
}
|
||||
|
||||
//Refresh the countries combo box once we're logged on, if not already
|
||||
mRadioReference.availableProperty().addListener((observable, oldValue, newValue) -> {
|
||||
mRadioReference.premiumAccountProperty().addListener((observable, oldValue, newValue) -> {
|
||||
if(newValue)
|
||||
{
|
||||
refreshCountries();
|
||||
@@ -173,6 +171,7 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
mTabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
|
||||
mTabPane.getTabs().addAll(getCountySystemTab(), getStateSystemTab(), getCountyAgencyTab(),
|
||||
getStateAgencyTab(), getNationalAgencyTab());
|
||||
mTabPane.disableProperty().bind(mRadioReference.premiumAccountProperty().not());
|
||||
}
|
||||
|
||||
return mTabPane;
|
||||
@@ -395,6 +394,8 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
GridPane.setConstraints(getCountyComboBox(), 2, 1);
|
||||
GridPane.setHgrow(getCountyComboBox(), Priority.ALWAYS);
|
||||
mComboBoxPane.getChildren().add(getCountyComboBox());
|
||||
|
||||
mComboBoxPane.disableProperty().bind(mRadioReference.premiumAccountProperty().not());
|
||||
}
|
||||
|
||||
return mComboBoxPane;
|
||||
@@ -407,18 +408,43 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
mCredentialsBox = new HBox();
|
||||
mCredentialsBox.setAlignment(Pos.CENTER_RIGHT);
|
||||
mCredentialsBox.setSpacing(5.0);
|
||||
Region leftFiller = new Region();
|
||||
HBox.setHgrow(leftFiller, Priority.ALWAYS);
|
||||
mCredentialsBox.getChildren().add(leftFiller);
|
||||
mCredentialsBox.getChildren().add(getRRPremiumReqText());
|
||||
Region rightFiller = new Region();
|
||||
HBox.setHgrow(rightFiller, Priority.ALWAYS);
|
||||
mCredentialsBox.getChildren().add(rightFiller);
|
||||
mCredentialsBox.getChildren().add(new Label("User Name:"));
|
||||
mCredentialsBox.getChildren().add(getUserNameText());
|
||||
mCredentialsBox.getChildren().add(new Label("Expires:"));
|
||||
mCredentialsBox.getChildren().add(getAccountExpiresText());
|
||||
mCredentialsBox.getChildren().add(getTestFailIcon());
|
||||
mCredentialsBox.getChildren().add(getTestPassIcon());
|
||||
mCredentialsBox.getChildren().add(getTestExpiredIcon());
|
||||
mCredentialsBox.getChildren().add(getLoginButton());
|
||||
}
|
||||
|
||||
return mCredentialsBox;
|
||||
}
|
||||
|
||||
private Label getRRPremiumReqText()
|
||||
{
|
||||
if(mRRStatusText == null)
|
||||
{
|
||||
mRRStatusText = new Label();
|
||||
mRRStatusText.setText("A premium Radio Reference subscription is required to import systems.");
|
||||
mRRStatusText.visibleProperty().bind(
|
||||
Bindings.and(
|
||||
mRadioReference.availableProperty(),
|
||||
mRadioReference.premiumAccountProperty().not()));
|
||||
mRRStatusText.setTextFill(Color.ORANGERED);
|
||||
mRRStatusText.setStyle("-fx-font-weight: bold;"); // I guess
|
||||
}
|
||||
|
||||
return mRRStatusText;
|
||||
}
|
||||
|
||||
private TextField getUserNameText()
|
||||
{
|
||||
if(mUserNameText == null)
|
||||
@@ -449,7 +475,12 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
{
|
||||
mTestPassIcon = new IconNode(FontAwesome.CHECK);
|
||||
mTestPassIcon.setFill(Color.GREEN);
|
||||
mTestPassIcon.visibleProperty().bind(mRadioReference.availableProperty());
|
||||
mTestPassIcon.setVisible(false);
|
||||
// Need to have a valid account, _and_ have premium
|
||||
mTestPassIcon.visibleProperty().bind(
|
||||
Bindings.and(
|
||||
mRadioReference.availableProperty(),
|
||||
mRadioReference.premiumAccountProperty()));
|
||||
}
|
||||
|
||||
return mTestPassIcon;
|
||||
@@ -461,12 +492,29 @@ public class RadioReferenceEditor extends BorderPane implements Consumer<Authori
|
||||
{
|
||||
mTestFailIcon = new IconNode(FontAwesome.TIMES);
|
||||
mTestFailIcon.setFill(Color.RED);
|
||||
mTestFailIcon.setVisible(false);
|
||||
mTestFailIcon.visibleProperty().bind(mRadioReference.availableProperty().not());
|
||||
}
|
||||
|
||||
return mTestFailIcon;
|
||||
}
|
||||
|
||||
private IconNode getTestExpiredIcon()
|
||||
{
|
||||
if(mTestExpiredIcon == null)
|
||||
{
|
||||
mTestExpiredIcon = new IconNode(FontAwesome.EXCLAMATION_TRIANGLE);
|
||||
mTestExpiredIcon.setFill(Color.ORANGERED);
|
||||
// Need to be signed in, but _not_ have a valid premium subscription
|
||||
mTestExpiredIcon.visibleProperty().bind(
|
||||
Bindings.and(
|
||||
mRadioReference.availableProperty(),
|
||||
mRadioReference.premiumAccountProperty().not()));
|
||||
}
|
||||
|
||||
return mTestExpiredIcon;
|
||||
}
|
||||
|
||||
private Button getLoginButton()
|
||||
{
|
||||
if(mLoginButton == null)
|
||||
|
||||
@@ -21,6 +21,7 @@ package io.github.dsheirer.gui.playlist.radioreference;
|
||||
|
||||
import io.github.dsheirer.playlist.PlaylistManager;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.RadioReferenceException;
|
||||
import io.github.dsheirer.rrapi.type.CountyInfo;
|
||||
import io.github.dsheirer.rrapi.type.Flavor;
|
||||
import io.github.dsheirer.rrapi.type.Site;
|
||||
@@ -229,6 +230,18 @@ public class SystemEditor extends VBox
|
||||
|
||||
private String getType(System system)
|
||||
{
|
||||
if(mRadioReferenceDecoder == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
initRadioReferenceDecoder();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
mLog.error("Error retrieving system information", t);
|
||||
}
|
||||
}
|
||||
|
||||
if(mRadioReferenceDecoder != null)
|
||||
{
|
||||
Type type = mRadioReferenceDecoder.getType(system);
|
||||
@@ -268,12 +281,7 @@ public class SystemEditor extends VBox
|
||||
{
|
||||
if(mRadioReferenceDecoder == null)
|
||||
{
|
||||
Map<Integer,Type> typeMap = mRadioReference.getService().getTypesMap();
|
||||
Map<Integer,Flavor> flavorMap = mRadioReference.getService().getFlavorsMap();
|
||||
Map<Integer,Voice> voiceMap = mRadioReference.getService().getVoicesMap();
|
||||
Map<Integer,Tag> tagMap = mRadioReference.getService().getTagsMap();
|
||||
mRadioReferenceDecoder = new RadioReferenceDecoder(mUserPreferences, typeMap, flavorMap,
|
||||
voiceMap, tagMap);
|
||||
initRadioReferenceDecoder();
|
||||
}
|
||||
|
||||
//Query and load the system view editor first
|
||||
@@ -320,6 +328,20 @@ public class SystemEditor extends VBox
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Radio Reference Decoder
|
||||
* @throws RadioReferenceException
|
||||
*/
|
||||
private void initRadioReferenceDecoder() throws RadioReferenceException
|
||||
{
|
||||
Map<Integer, Type> typeMap = mRadioReference.getService().getTypesMap();
|
||||
Map<Integer, Flavor> flavorMap = mRadioReference.getService().getFlavorsMap();
|
||||
Map<Integer, Voice> voiceMap = mRadioReference.getService().getVoicesMap();
|
||||
Map<Integer, Tag> tagMap = mRadioReference.getService().getTagsMap();
|
||||
mRadioReferenceDecoder = new RadioReferenceDecoder(mUserPreferences, typeMap, flavorMap,
|
||||
voiceMap, tagMap);
|
||||
}
|
||||
|
||||
public class SystemListCell extends ListCell<System>
|
||||
{
|
||||
private HBox mHBox;
|
||||
|
||||
@@ -22,18 +22,22 @@
|
||||
|
||||
package io.github.dsheirer.service.radioreference;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.rrapi.RadioReferenceException;
|
||||
import io.github.dsheirer.rrapi.RadioReferenceService;
|
||||
import io.github.dsheirer.rrapi.response.Fault;
|
||||
import io.github.dsheirer.rrapi.type.AuthorizationInformation;
|
||||
import io.github.dsheirer.rrapi.type.UserInfo;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
import javafx.beans.property.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
@@ -51,7 +55,19 @@ public class RadioReference
|
||||
private StringProperty mPassword = new SimpleStringProperty();
|
||||
private StringProperty mAccountExpiresProperty = new SimpleStringProperty();
|
||||
private BooleanProperty mAvailable = new SimpleBooleanProperty();
|
||||
private BooleanProperty mPremiumAccount = new SimpleBooleanProperty();
|
||||
private LoginStatus mLoginStatus = LoginStatus.UNKNOWN;
|
||||
|
||||
/**
|
||||
* Enum to determine "validity" of a RR Login
|
||||
*/
|
||||
public enum LoginStatus
|
||||
{
|
||||
UNKNOWN,
|
||||
INVALID_LOGIN,
|
||||
EXPIRED_PREMIUM,
|
||||
VALID_PREMIUM
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of the radio reference service
|
||||
@@ -70,6 +86,22 @@ public class RadioReference
|
||||
return mAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Externally monitored and controlled status indicator for a Premium RR Account
|
||||
*/
|
||||
public BooleanProperty premiumAccountProperty()
|
||||
{
|
||||
return mPremiumAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Current login state / validity
|
||||
*/
|
||||
public LoginStatus getLoginStatus()
|
||||
{
|
||||
return mLoginStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* User name for radio reference account
|
||||
*/
|
||||
@@ -140,7 +172,94 @@ public class RadioReference
|
||||
}
|
||||
|
||||
/**
|
||||
* Login with credentials
|
||||
* Tests the connection to radio reference service using the provided credentials.
|
||||
* @param userName for radio reference account
|
||||
* @param password for radio reference account
|
||||
* @return The state and "validity" of the account
|
||||
* @throws RadioReferenceException if there are any issues with the connection
|
||||
*/
|
||||
public static LoginStatus testConnectionWithExp(String userName, String password) throws RadioReferenceException
|
||||
{
|
||||
|
||||
AuthorizationInformation credentials = new AuthorizationInformation(SDRTRUNK_APP_KEY, userName, password);
|
||||
|
||||
try
|
||||
{
|
||||
RadioReferenceService service = new RadioReferenceService(credentials);
|
||||
UserInfo ui = service.getUserInfo();
|
||||
|
||||
return CheckExpDate(ui.getExpirationDate());
|
||||
}
|
||||
catch (RadioReferenceException rre)
|
||||
{
|
||||
if (rre.hasFault())
|
||||
{
|
||||
Fault fault = rre.getFault();
|
||||
|
||||
if (fault.getFaultCode() != null && fault.getFaultCode().contentEquals("AUTH"))
|
||||
{
|
||||
return LoginStatus.INVALID_LOGIN;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw rre;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw rre;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the account status (Premium) based on the given expiration date
|
||||
* @param RRExpirationString The Premium Expiration string returned from RR
|
||||
* @return Account Login Status
|
||||
*/
|
||||
@VisibleForTesting
|
||||
protected static LoginStatus CheckExpDate(String RRExpirationString)
|
||||
{
|
||||
try
|
||||
{
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("MM-dd-yyyy", Locale.ENGLISH);
|
||||
Date RRExpDate = formatter.parse(RRExpirationString);
|
||||
|
||||
// We want to err on the side of the user getting an error with an invalid subscription,
|
||||
// rather than the user being prevented from using their valid, but shortly expiring, subscription.
|
||||
|
||||
// Get the current Date and subtract two days (due to no >=, only > ),
|
||||
// as I am not sure how timezones work for RR and the end user.
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(new Date());
|
||||
c.add(Calendar.DAY_OF_MONTH, -2);
|
||||
|
||||
if(RRExpDate.after(c.getTime()))
|
||||
{
|
||||
return LoginStatus.VALID_PREMIUM;
|
||||
}
|
||||
else
|
||||
{
|
||||
return LoginStatus.EXPIRED_PREMIUM;
|
||||
}
|
||||
}
|
||||
catch (ParseException e)
|
||||
{
|
||||
// This doesn't have to be a date; it can also be a string
|
||||
// If we get anything we can't parse, assume it's a string and valid
|
||||
// Accounts that have never had a valid subscription return a year of 1969
|
||||
|
||||
// See https://wiki.radioreference.com/index.php/RadioReference.com_Web_Service3.1#Versions :
|
||||
// Version 5 - Issued a fix for the getUserData method which returned a subscription expiration
|
||||
// date in 1969 for admins and feed providers. Now returns "Never - Feed Provider" and "Never - Admin"
|
||||
// in string format.
|
||||
return LoginStatus.VALID_PREMIUM;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Login with credentials, and update properties based on the login status
|
||||
*/
|
||||
private void login()
|
||||
{
|
||||
@@ -148,12 +267,31 @@ public class RadioReference
|
||||
{
|
||||
UserInfo userInfo = getService().getUserInfo();
|
||||
accountExpiresProperty().setValue(userInfo.getExpirationDate());
|
||||
availableProperty().set(true);
|
||||
|
||||
mLoginStatus = CheckExpDate(userInfo.getExpirationDate());
|
||||
if(mLoginStatus == LoginStatus.VALID_PREMIUM)
|
||||
{
|
||||
availableProperty().set(true);
|
||||
premiumAccountProperty().set(true);
|
||||
}
|
||||
else if (mLoginStatus == LoginStatus.EXPIRED_PREMIUM)
|
||||
{
|
||||
availableProperty().set(true);
|
||||
premiumAccountProperty().set(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
availableProperty().set(false);
|
||||
premiumAccountProperty().set(false);
|
||||
}
|
||||
}
|
||||
catch(RadioReferenceException rre)
|
||||
{
|
||||
accountExpiresProperty().setValue(null);
|
||||
mLoginStatus = LoginStatus.UNKNOWN;
|
||||
availableProperty().set(false);
|
||||
premiumAccountProperty().set(false);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package io.github.dsheirer.service.radioreference;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
import static io.github.dsheirer.service.radioreference.RadioReference.CheckExpDate;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class RadioReferenceTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Tests the handling of Radio Reference's Premium Expiration date to Account Statuses
|
||||
* Necessary because DateTime math gets easy to do incorrectly, and we don't want to
|
||||
* lock a user out of access due to an off-by-one Date issue.
|
||||
*/
|
||||
@Test
|
||||
void checkExpDate()
|
||||
{
|
||||
SimpleDateFormat RRDateFormatter = new SimpleDateFormat("MM-dd-yyyy");
|
||||
Date now = new Date();
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTime(now);
|
||||
|
||||
// Never had premium (expired)
|
||||
Assertions.assertEquals(RadioReference.LoginStatus.EXPIRED_PREMIUM, CheckExpDate("12-31-1969"));
|
||||
|
||||
// Expiring today (valid)
|
||||
Assertions.assertEquals(RadioReference.LoginStatus.VALID_PREMIUM, CheckExpDate(RRDateFormatter.format(c.getTime())));
|
||||
|
||||
// Expiring next week (valid)
|
||||
c.add(Calendar.DAY_OF_MONTH, 7);
|
||||
Assertions.assertEquals(RadioReference.LoginStatus.VALID_PREMIUM, CheckExpDate(RRDateFormatter.format(c.getTime())));
|
||||
|
||||
// Expired yesterday (valid)
|
||||
c.setTime(now);
|
||||
c.add(Calendar.DAY_OF_MONTH, -1);
|
||||
Assertions.assertEquals(RadioReference.LoginStatus.VALID_PREMIUM, CheckExpDate(RRDateFormatter.format(c.getTime())));
|
||||
|
||||
// Expired last week (expired)
|
||||
c.setTime(now);
|
||||
c.add(Calendar.DAY_OF_MONTH, -7);
|
||||
Assertions.assertEquals(RadioReference.LoginStatus.EXPIRED_PREMIUM, CheckExpDate(RRDateFormatter.format(c.getTime())));
|
||||
|
||||
// Broadcastify user? Admin? Any string that's not a Date is considered valid (valid)
|
||||
Assertions.assertEquals(RadioReference.LoginStatus.VALID_PREMIUM, CheckExpDate("Not a date"));
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user