diff --git a/client/src/main/java/ctbrec/ui/JavaFxModel.java b/client/src/main/java/ctbrec/ui/JavaFxModel.java index f60ce99d..eafe3847 100644 --- a/client/src/main/java/ctbrec/ui/JavaFxModel.java +++ b/client/src/main/java/ctbrec/ui/JavaFxModel.java @@ -126,7 +126,7 @@ public class JavaFxModel implements Model { } @Override - public void receiveTip(int tokens) throws IOException { + public void receiveTip(Double tokens) throws IOException { SiteUiFactory.getUi(getSite()).login(); delegate.receiveTip(tokens); } diff --git a/client/src/main/java/ctbrec/ui/ThumbOverviewTab.java b/client/src/main/java/ctbrec/ui/ThumbOverviewTab.java index e07c6755..b727b66b 100644 --- a/client/src/main/java/ctbrec/ui/ThumbOverviewTab.java +++ b/client/src/main/java/ctbrec/ui/ThumbOverviewTab.java @@ -4,6 +4,7 @@ import static ctbrec.ui.controls.Dialogs.*; import java.io.IOException; import java.net.SocketTimeoutException; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -470,20 +471,19 @@ public class ThumbOverviewTab extends Tab implements TabSelectionListener { tipDialog.showAndWait(); String tipText = tipDialog.getResult(); if(tipText != null) { - if(tipText.matches("[1-9]\\d*")) { - int tokens = Integer.parseInt(tipText); - try { - SiteUiFactory.getUi(site).login(); - cell.getModel().receiveTip(tokens); - Map event = new HashMap<>(); - event.put("event", "tokens.sent"); - event.put("amount", tokens); - EventBusHolder.BUS.post(event); - } catch (Exception e1) { - LOG.error("An error occured while sending tip", e1); - showError("Couldn't send tip", "An error occured while sending tip:", e1); - } - } else { + DecimalFormat df = new DecimalFormat("0.##"); + try { + Number tokens = df.parse(tipText); + SiteUiFactory.getUi(site).login(); + cell.getModel().receiveTip(tokens.doubleValue()); + Map event = new HashMap<>(); + event.put("event", "tokens.sent"); + event.put("amount", tokens.doubleValue()); + EventBusHolder.BUS.post(event); + } catch (IOException ex) { + LOG.error("An error occured while sending tip", ex); + showError("Couldn't send tip", "An error occured while sending tip:", ex); + } catch (Exception ex) { showError("Couldn't send tip", "You entered an invalid amount of tokens", null); } } diff --git a/client/src/main/java/ctbrec/ui/TipDialog.java b/client/src/main/java/ctbrec/ui/TipDialog.java index 8aaefb93..d231e2f8 100644 --- a/client/src/main/java/ctbrec/ui/TipDialog.java +++ b/client/src/main/java/ctbrec/ui/TipDialog.java @@ -1,5 +1,6 @@ package ctbrec.ui; +import java.text.DecimalFormat; import java.util.Objects; import java.util.concurrent.ExecutionException; @@ -30,21 +31,21 @@ public class TipDialog extends TextInputDialog { } private void loadTokenBalance() { - Task task = new Task() { + Task task = new Task() { @Override - protected Integer call() throws Exception { + protected Double call() throws Exception { if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) { SiteUiFactory.getUi(site).login(); return site.getTokenBalance(); } else { - return 1_000_000; + return 1_000_000d; } } @Override protected void done() { try { - int tokens = get(); + double tokens = get(); Platform.runLater(() -> { if (tokens <= 0) { String msg = "Do you want to buy tokens now?\n\nIf you agree, "+site.getName()+" will open in a browser. " @@ -59,7 +60,8 @@ public class TipDialog extends TextInputDialog { } } else { getEditor().setDisable(false); - setHeaderText("Current token balance: " + tokens); + DecimalFormat df = new DecimalFormat("0.##"); + setHeaderText("Current token balance: " + df.format(tokens)); } }); } catch (InterruptedException | ExecutionException e) { diff --git a/client/src/main/java/ctbrec/ui/TokenLabel.java b/client/src/main/java/ctbrec/ui/TokenLabel.java index 2117c444..917dad12 100644 --- a/client/src/main/java/ctbrec/ui/TokenLabel.java +++ b/client/src/main/java/ctbrec/ui/TokenLabel.java @@ -1,5 +1,6 @@ package ctbrec.ui; +import java.text.DecimalFormat; import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutionException; @@ -19,7 +20,7 @@ import javafx.scene.control.Tooltip; public class TokenLabel extends Label { private static final transient Logger LOG = LoggerFactory.getLogger(TokenLabel.class); - private int tokens = -1; + private double tokens = -1; private Site site; public TokenLabel(Site site) { @@ -29,11 +30,10 @@ public class TokenLabel extends Label { @Subscribe public void tokensUpdates(Map e) { if (Objects.equals("tokens", e.get("event"))) { - tokens = (int) e.get("amount"); + tokens = (double) e.get("amount"); updateText(); } else if (Objects.equals("tokens.sent", e.get("event"))) { - int _tokens = (int) e.get("amount"); - tokens -= _tokens; + tokens -= (double) e.get("amount"); updateText(); } } @@ -45,31 +45,34 @@ public class TokenLabel extends Label { updateText(); } - public void update(int tokens) { + public void update(double tokens) { this.tokens = tokens; updateText(); } private void updateText() { - Platform.runLater(() -> setText("Tokens: " + tokens)); + Platform.runLater(() -> { + DecimalFormat df = new DecimalFormat("0.##"); + setText("Tokens: " + df.format(tokens)); + }); } public void loadBalance() { - Task task = new Task() { + Task task = new Task() { @Override - protected Integer call() throws Exception { + protected Double call() throws Exception { if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) { SiteUiFactory.getUi(site).login(); return site.getTokenBalance(); } else { - return 1_000_000; + return 1_000_000d; } } @Override protected void done() { try { - int tokens = get(); + double tokens = get(); update(tokens); } catch (InterruptedException | ExecutionException e) { LOG.error("Couldn't retrieve account balance", e); diff --git a/common/src/main/java/ctbrec/Model.java b/common/src/main/java/ctbrec/Model.java index 70ddee51..1569fff8 100644 --- a/common/src/main/java/ctbrec/Model.java +++ b/common/src/main/java/ctbrec/Model.java @@ -72,7 +72,7 @@ public interface Model extends Comparable { public void invalidateCacheEntries(); - public void receiveTip(int tokens) throws IOException; + public void receiveTip(Double tokens) throws IOException; /** * Determines the stream resolution for this model diff --git a/common/src/main/java/ctbrec/recorder/RemoteRecorder.java b/common/src/main/java/ctbrec/recorder/RemoteRecorder.java index 38d27d99..c8629a7f 100644 --- a/common/src/main/java/ctbrec/recorder/RemoteRecorder.java +++ b/common/src/main/java/ctbrec/recorder/RemoteRecorder.java @@ -453,7 +453,7 @@ public class RemoteRecorder implements Recorder { } @Override - public void receiveTip(int tokens) throws IOException { + public void receiveTip(Double tokens) throws IOException { } @Override @@ -532,8 +532,8 @@ public class RemoteRecorder implements Recorder { } @Override - public Integer getTokenBalance() throws IOException { - return 0; + public Double getTokenBalance() throws IOException { + return 0d; } @Override diff --git a/common/src/main/java/ctbrec/sites/Site.java b/common/src/main/java/ctbrec/sites/Site.java index 9225b52c..92a58087 100644 --- a/common/src/main/java/ctbrec/sites/Site.java +++ b/common/src/main/java/ctbrec/sites/Site.java @@ -14,7 +14,7 @@ public interface Site { public void setRecorder(Recorder recorder); public Recorder getRecorder(); public Model createModel(String name); - public Integer getTokenBalance() throws IOException; + public Double getTokenBalance() throws IOException; public String getBuyTokensLink(); public boolean login() throws IOException; public HttpClient getHttpClient(); diff --git a/common/src/main/java/ctbrec/sites/bonga/BongaCams.java b/common/src/main/java/ctbrec/sites/bonga/BongaCams.java index 52b2d084..ae3d9e0c 100644 --- a/common/src/main/java/ctbrec/sites/bonga/BongaCams.java +++ b/common/src/main/java/ctbrec/sites/bonga/BongaCams.java @@ -57,7 +57,7 @@ public class BongaCams extends AbstractSite { } @Override - public Integer getTokenBalance() throws IOException { + public Double getTokenBalance() throws IOException { int userId = ((BongaCamsHttpClient)getHttpClient()).getUserId(); String url = BongaCams.BASE_URL + "/tools/amf.php"; RequestBody body = new FormBody.Builder() @@ -78,7 +78,7 @@ public class BongaCams extends AbstractSite { JSONObject json = new JSONObject(response.body().string()); if(json.optString("status").equals("online")) { JSONObject userData = json.getJSONObject("userData"); - return userData.getInt("balance"); + return (double) userData.getInt("balance"); } else { throw new IOException("Request was not successful: " + json.toString(2)); } diff --git a/common/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java b/common/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java index bd891eba..a0eb8245 100644 --- a/common/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java +++ b/common/src/main/java/ctbrec/sites/bonga/BongaCamsModel.java @@ -154,13 +154,13 @@ public class BongaCamsModel extends AbstractModel { } @Override - public void receiveTip(int tokens) throws IOException { + public void receiveTip(Double tokens) throws IOException { String url = BongaCams.BASE_URL + "/chat-ajax-amf-service?" + System.currentTimeMillis(); int userId = ((BongaCamsHttpClient)site.getHttpClient()).getUserId(); RequestBody body = new FormBody.Builder() .add("method", "tipModel") .add("args[]", getName()) - .add("args[]", Integer.toString(tokens)) + .add("args[]", Integer.toString(tokens.intValue())) .add("args[]", Integer.toString(userId)) .add("args[3]", "") .build(); diff --git a/common/src/main/java/ctbrec/sites/cam4/Cam4.java b/common/src/main/java/ctbrec/sites/cam4/Cam4.java index 62a1cea2..016f2cad 100644 --- a/common/src/main/java/ctbrec/sites/cam4/Cam4.java +++ b/common/src/main/java/ctbrec/sites/cam4/Cam4.java @@ -51,7 +51,7 @@ public class Cam4 extends AbstractSite { } @Override - public Integer getTokenBalance() throws IOException { + public Double getTokenBalance() throws IOException { if (!credentialsAvailable()) { throw new IOException("Not logged in"); } diff --git a/common/src/main/java/ctbrec/sites/cam4/Cam4HttpClient.java b/common/src/main/java/ctbrec/sites/cam4/Cam4HttpClient.java index a9d8abd7..90f9eb00 100644 --- a/common/src/main/java/ctbrec/sites/cam4/Cam4HttpClient.java +++ b/common/src/main/java/ctbrec/sites/cam4/Cam4HttpClient.java @@ -55,7 +55,7 @@ public class Cam4HttpClient extends HttpClient { } } - protected int getTokenBalance() throws IOException { + protected double getTokenBalance() throws IOException { if(!loggedIn) { login(); } diff --git a/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java b/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java index 0c40a424..580b287d 100644 --- a/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java +++ b/common/src/main/java/ctbrec/sites/cam4/Cam4Model.java @@ -176,7 +176,7 @@ public class Cam4Model extends AbstractModel { } @Override - public void receiveTip(int tokens) throws IOException { + public void receiveTip(Double tokens) throws IOException { throw new RuntimeException("Not implemented for Cam4, yet"); } diff --git a/common/src/main/java/ctbrec/sites/camsoda/Camsoda.java b/common/src/main/java/ctbrec/sites/camsoda/Camsoda.java index 10a12117..316a9323 100644 --- a/common/src/main/java/ctbrec/sites/camsoda/Camsoda.java +++ b/common/src/main/java/ctbrec/sites/camsoda/Camsoda.java @@ -57,7 +57,7 @@ public class Camsoda extends AbstractSite { } @Override - public Integer getTokenBalance() throws IOException { + public Double getTokenBalance() throws IOException { if (!credentialsAvailable()) { throw new IOException("Account settings not available"); } @@ -71,7 +71,7 @@ public class Camsoda extends AbstractSite { if(json.has("user")) { JSONObject user = json.getJSONObject("user"); if(user.has("tokens")) { - return user.getInt("tokens"); + return (double) user.getInt("tokens"); } } } else { diff --git a/common/src/main/java/ctbrec/sites/camsoda/CamsodaModel.java b/common/src/main/java/ctbrec/sites/camsoda/CamsodaModel.java index 7c567fc6..71678751 100644 --- a/common/src/main/java/ctbrec/sites/camsoda/CamsodaModel.java +++ b/common/src/main/java/ctbrec/sites/camsoda/CamsodaModel.java @@ -179,13 +179,13 @@ public class CamsodaModel extends AbstractModel { } @Override - public void receiveTip(int tokens) throws IOException { + public void receiveTip(Double tokens) throws IOException { String csrfToken = ((CamsodaHttpClient)site.getHttpClient()).getCsrfToken(); String url = site.getBaseUrl() + "/api/v1/tip/" + getName(); if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) { LOG.debug("Sending tip {}", url); RequestBody body = new FormBody.Builder() - .add("amount", Integer.toString(tokens)) + .add("amount", Integer.toString(tokens.intValue())) .add("comment", "") .build(); Request request = new Request.Builder() diff --git a/common/src/main/java/ctbrec/sites/chaturbate/Chaturbate.java b/common/src/main/java/ctbrec/sites/chaturbate/Chaturbate.java index d31b7983..708def45 100644 --- a/common/src/main/java/ctbrec/sites/chaturbate/Chaturbate.java +++ b/common/src/main/java/ctbrec/sites/chaturbate/Chaturbate.java @@ -80,7 +80,7 @@ public class Chaturbate extends AbstractSite { } @Override - public Integer getTokenBalance() throws IOException { + public Double getTokenBalance() throws IOException { String username = Config.getInstance().getSettings().username; if (username == null || username.trim().isEmpty()) { throw new IOException("Not logged in"); @@ -93,7 +93,7 @@ public class Chaturbate extends AbstractSite { String profilePage = resp.body().string(); String tokenText = HtmlParser.getText(profilePage, "span.tokencount"); int tokens = Integer.parseInt(tokenText); - return tokens; + return (double) tokens; } else { throw new IOException("HTTP response: " + resp.code() + " - " + resp.message()); } diff --git a/common/src/main/java/ctbrec/sites/chaturbate/ChaturbateModel.java b/common/src/main/java/ctbrec/sites/chaturbate/ChaturbateModel.java index e8322b8c..1428c3fd 100644 --- a/common/src/main/java/ctbrec/sites/chaturbate/ChaturbateModel.java +++ b/common/src/main/java/ctbrec/sites/chaturbate/ChaturbateModel.java @@ -127,8 +127,8 @@ public class ChaturbateModel extends AbstractModel { } @Override - public void receiveTip(int tokens) throws IOException { - getChaturbate().sendTip(getName(), tokens); + public void receiveTip(Double tokens) throws IOException { + getChaturbate().sendTip(getName(), tokens.intValue()); } @Override diff --git a/common/src/main/java/ctbrec/sites/jasmin/LiveJasmin.java b/common/src/main/java/ctbrec/sites/jasmin/LiveJasmin.java index 1b3fd206..c37cd368 100644 --- a/common/src/main/java/ctbrec/sites/jasmin/LiveJasmin.java +++ b/common/src/main/java/ctbrec/sites/jasmin/LiveJasmin.java @@ -13,6 +13,7 @@ import org.jsoup.select.Elements; import ctbrec.Config; import ctbrec.Model; +import ctbrec.NotLoggedInExcetion; import ctbrec.io.HtmlParser; import ctbrec.io.HttpClient; import ctbrec.io.HttpException; @@ -51,9 +52,34 @@ public class LiveJasmin extends AbstractSite { } @Override - public Integer getTokenBalance() throws IOException { - // https://www.livejasmin.com/en/offline-surprise/get-member-balance?session=m15f0175aa97d2d3c64df8f9bf96e3d8e - return 0; + public Double getTokenBalance() throws IOException { + if(getLiveJasminHttpClient().login()) { + String sessionId = getLiveJasminHttpClient().getSessionId(); + String url = getBaseUrl() + "/en/offline-surprise/get-member-balance?session=" + sessionId; + Request request = new Request.Builder() + .url(url) + .addHeader("User-Agent", Config.getInstance().getSettings().httpUserAgent) + .addHeader("Accept", "*/*") + .addHeader("Accept-Language", "en") + .addHeader("Referer", getBaseUrl()) + .addHeader("X-Requested-With", "XMLHttpRequest") + .build(); + try (Response response = getHttpClient().execute(request)) { + if(response.isSuccessful()) { + String body = response.body().string(); + JSONObject json = new JSONObject(body); + if(json.optBoolean("success")) { + return json.optDouble("result"); + } else { + throw new IOException("Response was not successful: " + url + "\n" + body); + } + } else { + throw new HttpException(response.code(), response.message()); + } + } + } else { + throw new IOException(new NotLoggedInExcetion()); + } } @Override @@ -87,7 +113,7 @@ public class LiveJasmin extends AbstractSite { @Override public boolean supportsTips() { - return false; + return true; } @Override @@ -154,4 +180,7 @@ public class LiveJasmin extends AbstractSite { return !Config.getInstance().getSettings().livejasminUsername.isEmpty(); } + private LiveJasminHttpClient getLiveJasminHttpClient() { + return (LiveJasminHttpClient) httpClient; + } } diff --git a/common/src/main/java/ctbrec/sites/jasmin/LiveJasminModel.java b/common/src/main/java/ctbrec/sites/jasmin/LiveJasminModel.java index 8722c6f4..513a7a92 100644 --- a/common/src/main/java/ctbrec/sites/jasmin/LiveJasminModel.java +++ b/common/src/main/java/ctbrec/sites/jasmin/LiveJasminModel.java @@ -178,7 +178,7 @@ public class LiveJasminModel extends AbstractModel { } @Override - public void receiveTip(int tokens) throws IOException { + public void receiveTip(Double tokens) throws IOException { } @Override diff --git a/common/src/main/java/ctbrec/sites/mfc/MyFreeCams.java b/common/src/main/java/ctbrec/sites/mfc/MyFreeCams.java index 787fac8e..0bdd2926 100644 --- a/common/src/main/java/ctbrec/sites/mfc/MyFreeCams.java +++ b/common/src/main/java/ctbrec/sites/mfc/MyFreeCams.java @@ -59,14 +59,14 @@ public class MyFreeCams extends AbstractSite { } @Override - public Integer getTokenBalance() throws IOException { + public Double getTokenBalance() throws IOException { Request req = new Request.Builder().url(baseUrl + "/php/account.php?request=status").build(); try(Response response = getHttpClient().execute(req)) { if(response.isSuccessful()) { String content = response.body().string(); Elements tags = HtmlParser.getTags(content, "div.content > p > b"); String tokens = tags.get(2).text(); - return Integer.parseInt(tokens); + return Double.parseDouble(tokens); } else { throw new HttpException(response.code(), response.message()); } diff --git a/common/src/main/java/ctbrec/sites/mfc/MyFreeCamsModel.java b/common/src/main/java/ctbrec/sites/mfc/MyFreeCamsModel.java index 768ef5df..ae305785 100644 --- a/common/src/main/java/ctbrec/sites/mfc/MyFreeCamsModel.java +++ b/common/src/main/java/ctbrec/sites/mfc/MyFreeCamsModel.java @@ -160,7 +160,7 @@ public class MyFreeCamsModel extends AbstractModel { } @Override - public void receiveTip(int tokens) throws IOException { + public void receiveTip(Double tokens) throws IOException { String tipUrl = MyFreeCams.baseUrl + "/php/tip.php"; String initUrl = tipUrl + "?request=tip&username="+getName()+"&broadcaster_id="+getUid(); Request req = new Request.Builder().url(initUrl).build(); @@ -173,7 +173,7 @@ public class MyFreeCamsModel extends AbstractModel { RequestBody body = new FormBody.Builder() .add("token", token) .add("broadcaster_id", Integer.toString(uid)) - .add("tip_value", Integer.toString(tokens)) + .add("tip_value", Integer.toString(tokens.intValue())) .add("submit_tip", "1") .add("anonymous", "") .add("public", "1") diff --git a/common/src/main/java/ctbrec/sites/streamate/Streamate.java b/common/src/main/java/ctbrec/sites/streamate/Streamate.java index a86eb91b..7e77e786 100644 --- a/common/src/main/java/ctbrec/sites/streamate/Streamate.java +++ b/common/src/main/java/ctbrec/sites/streamate/Streamate.java @@ -57,7 +57,7 @@ public class Streamate extends AbstractSite { } @Override - public Integer getTokenBalance() throws IOException { + public Double getTokenBalance() throws IOException { // int userId = ((StreamateHttpClient)getHttpClient()).getUserId(); // String url = Streamate.BASE_URL + "/tools/amf.php"; // RequestBody body = new FormBody.Builder() @@ -86,7 +86,7 @@ public class Streamate extends AbstractSite { // throw new HttpException(response.code(), response.message()); // } // } - return 0; + return 0d; } @Override diff --git a/common/src/main/java/ctbrec/sites/streamate/StreamateModel.java b/common/src/main/java/ctbrec/sites/streamate/StreamateModel.java index 519bce2c..68c41911 100644 --- a/common/src/main/java/ctbrec/sites/streamate/StreamateModel.java +++ b/common/src/main/java/ctbrec/sites/streamate/StreamateModel.java @@ -132,7 +132,7 @@ public class StreamateModel extends AbstractModel { } @Override - public void receiveTip(int tokens) throws IOException { + public void receiveTip(Double tokens) throws IOException { /* Mt._giveGoldAjax = function(e, t) { var n = _t.getState(), @@ -180,17 +180,17 @@ public class StreamateModel extends AbstractModel { String url = "https://hybridclient.naiadsystems.com/api/v1/givegold/"; // this returns 404 at the moment. not sure if it's the wrong server, or if this is not used anymore RequestBody body = new FormBody.Builder() - .add("amt", Integer.toString(tokens)) // amount - .add("isprepopulated", "1") // ? - .add("modelname", getName()) // model's name - .add("nickname", nickname) // user's nickname - .add("performernickname", getName()) // model's name - .add("sakey", saKey) // sakey from login - .add("session", "") // is related to gold an private shows, for normal tips keep it empty - .add("smid", Long.toString(getId())) // model id - .add("streamid", getStreamId()) // id of the current stream - .add("userid", Long.toString(userId)) // user's id - .add("username", nickname) // user's nickname + .add("amt", Integer.toString(tokens.intValue())) // amount + .add("isprepopulated", "1") // ? + .add("modelname", getName()) // model's name + .add("nickname", nickname) // user's nickname + .add("performernickname", getName()) // model's name + .add("sakey", saKey) // sakey from login + .add("session", "") // is related to gold an private shows, for normal tips keep it empty + .add("smid", Long.toString(getId())) // model id + .add("streamid", getStreamId()) // id of the current stream + .add("userid", Long.toString(userId)) // user's id + .add("username", nickname) // user's nickname .build(); Buffer b = new Buffer(); body.writeTo(b);