From 233dd3fa9cec5ee7f265bd7fa0a3561fb602ddb3 Mon Sep 17 00:00:00 2001 From: 0xboobface <0xboobface@gmail.com> Date: Fri, 2 Nov 2018 18:14:36 +0100 Subject: [PATCH] Implement tipping for CamSoda Sending tips for CamSoda works now --- .../java/ctbrec/sites/camsoda/Camsoda.java | 12 +-- .../ctbrec/sites/camsoda/CamsodaModel.java | 81 ++++++++++++------- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/src/main/java/ctbrec/sites/camsoda/Camsoda.java b/src/main/java/ctbrec/sites/camsoda/Camsoda.java index 74a5ebb0..3cf7f937 100644 --- a/src/main/java/ctbrec/sites/camsoda/Camsoda.java +++ b/src/main/java/ctbrec/sites/camsoda/Camsoda.java @@ -65,11 +65,11 @@ public class Camsoda extends AbstractSite { @Override public Integer getTokenBalance() throws IOException { - String username = Config.getInstance().getSettings().camsodaUsername; - if (username == null || username.trim().isEmpty()) { - throw new IOException("Not logged in"); + if (!credentialsAvailable()) { + throw new IOException("Account settings not available"); } + String username = Config.getInstance().getSettings().camsodaUsername; String url = BASE_URI + "/api/v1/user/" + username; Request request = new Request.Builder().url(url).build(); Response response = getHttpClient().execute(request, true); @@ -113,12 +113,14 @@ public class Camsoda extends AbstractSite { @Override public void shutdown() { - httpClient.shutdown(); + if(httpClient != null) { + httpClient.shutdown(); + } } @Override public boolean supportsTips() { - return false; + return true; } @Override diff --git a/src/main/java/ctbrec/sites/camsoda/CamsodaModel.java b/src/main/java/ctbrec/sites/camsoda/CamsodaModel.java index 24274259..1fe5beeb 100644 --- a/src/main/java/ctbrec/sites/camsoda/CamsodaModel.java +++ b/src/main/java/ctbrec/sites/camsoda/CamsodaModel.java @@ -6,11 +6,14 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import com.iheartradio.m3u8.Encoding; import com.iheartradio.m3u8.Format; import com.iheartradio.m3u8.ParseException; @@ -24,6 +27,7 @@ import com.iheartradio.m3u8.data.StreamInfo; import ctbrec.AbstractModel; import ctbrec.recorder.download.StreamSource; import ctbrec.sites.Site; +import okhttp3.FormBody; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; @@ -34,10 +38,15 @@ public class CamsodaModel extends AbstractModel { private String streamUrl; private Site site; private List streamSources = null; - private int[] resolution; private String status = "n/a"; private float sortOrder = 0; + private static Cache streamResolutionCache = CacheBuilder.newBuilder() + .initialCapacity(10_000) + .maximumSize(10_000) + .expireAfterWrite(30, TimeUnit.MINUTES) + .build(); + public String getStreamUrl() throws IOException { if(streamUrl == null) { // load model @@ -95,7 +104,10 @@ public class CamsodaModel extends AbstractModel { @Override public List getStreamSources() throws IOException, ExecutionException, ParseException, PlaylistException { - LOG.debug("Loading master playlist {}", streamUrl); + String streamUrl = getStreamUrl(); + if(streamUrl == null) { + return Collections.emptyList(); + } Request req = new Request.Builder().url(streamUrl).build(); Response response = site.getHttpClient().execute(req); try { @@ -126,11 +138,12 @@ public class CamsodaModel extends AbstractModel { @Override public void invalidateCacheEntries() { streamSources = null; - resolution = null; + streamResolutionCache.invalidate(getName()); } @Override public int[] getStreamResolution(boolean failFast) throws ExecutionException { + int[] resolution = streamResolutionCache.getIfPresent(getName()); if(resolution != null) { return resolution; } else { @@ -139,9 +152,14 @@ public class CamsodaModel extends AbstractModel { } else { try { List streamSources = getStreamSources(); - StreamSource src = streamSources.get(0); - resolution = new int[] {src.width, src.height}; - return resolution; + if(streamSources.isEmpty()) { + return new int[] {0,0}; + } else { + StreamSource src = streamSources.get(0); + resolution = new int[] {src.width, src.height}; + streamResolutionCache.put(getName(), resolution); + return resolution; + } } catch (IOException | ParseException | PlaylistException e) { throw new ExecutionException(e); } @@ -151,22 +169,29 @@ public class CamsodaModel extends AbstractModel { @Override public void receiveTip(int tokens) throws IOException { - // TODO Auto-generated method stub - /* - sendTip: function(i, a, r, o, c, d) { - if (!s.isAuthenticated()) return s.showRegister(), t.when(!1); - var u = t.defer(); - return e.post("/api/v1/tip/" + i, { - amount: a, - comment: o, - type: r, - app_data: c, - source_id: d - }).then(function(e) { - 1 == e.data.status ? (s.currentUser.tokens = e.data.total, void 0 != e.data.tipped_performer_last_24hrs && e.data.tipped_performer_last_24hrs >= 25 && (n.$emit("local.allowed_to_rate"), 0 == n.allowedToRate && (n.allowedToRate = !0, l.pop("info", "Voting Unlocked", "You tipped " + i + " 25 tokens in the past 24 hours, you may now vote!"))), u.resolve(e.data)) : (l.pop("error", e.data.error, e.data.message), u.reject(e.data)) - }), u.promise - }, - */ + 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("comment", "") + .build(); + Request request = new Request.Builder() + .url(url) + .post(body) + .addHeader("Referer", Camsoda.BASE_URI + '/' + getName()) + .addHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0") + .addHeader("Accept", "application/json, text/plain, */*") + .addHeader("Accept-Language", "en") + .addHeader("X-CSRF-Token", csrfToken) + .build(); + try(Response response = site.getHttpClient().execute(request, true)) { + if(!response.isSuccessful()) { + throw new IOException("HTTP status " + response.code() + " " + response.message()); + } + } + } } @Override @@ -178,9 +203,9 @@ public class CamsodaModel extends AbstractModel { .url(url) .post(RequestBody.create(null, "")) .addHeader("Referer", Camsoda.BASE_URI + '/' + getName()) - .addHeader("User-Agent", " Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0") - .addHeader("Accept", " application/json, text/plain, */*") - .addHeader("Accept-Language", " de,en-US;q=0.7,en;q=0.3") + .addHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0") + .addHeader("Accept", "application/json, text/plain, */*") + .addHeader("Accept-Language", "en") .addHeader("X-CSRF-Token", csrfToken) .build(); Response resp = site.getHttpClient().execute(request, true); @@ -202,9 +227,9 @@ public class CamsodaModel extends AbstractModel { .url(url) .post(RequestBody.create(null, "")) .addHeader("Referer", Camsoda.BASE_URI + '/' + getName()) - .addHeader("User-Agent", " Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0") - .addHeader("Accept", " application/json, text/plain, */*") - .addHeader("Accept-Language", " de,en-US;q=0.7,en;q=0.3") + .addHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0") + .addHeader("Accept", "application/json, text/plain, */*") + .addHeader("Accept-Language", "en") .addHeader("X-CSRF-Token", csrfToken) .build(); Response resp = site.getHttpClient().execute(request, true);