forked from j62/ctbrec
1
0
Fork 0

Improve online detection for MFC

This commit is contained in:
0xb00bface 2021-12-19 11:43:20 +01:00
parent 08052bbd4e
commit ea7f56c0fd
3 changed files with 96 additions and 46 deletions

View File

@ -5,6 +5,7 @@ import static ctbrec.io.HttpConstants.*;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -71,7 +72,7 @@ public class MyFreeCams extends AbstractSite {
.build();
try(Response response = getHttpClient().execute(req)) {
if(response.isSuccessful()) {
String content = response.body().string();
String content = Objects.requireNonNull(response.body(), "HTTP response is null").string();
Elements tags = HtmlParser.getTags(content, "div.content > p > b");
String tokens = tags.get(2).text();
return Double.parseDouble(tokens);

View File

@ -58,12 +58,12 @@ public class MyFreeCamsClient {
private MyFreeCams mfc;
private WebSocket ws;
private Thread keepAlive;
private Moshi moshi;
private final Moshi moshi;
private volatile boolean running = false;
private Cache<Integer, SessionState> sessionStates = CacheBuilder.newBuilder().maximumSize(4000).build();
private Cache<Integer, MyFreeCamsModel> models = CacheBuilder.newBuilder().maximumSize(4000).build();
private Lock lock = new ReentrantLock();
private final Cache<Integer, SessionState> sessionStates = CacheBuilder.newBuilder().maximumSize(4000).build();
private final Cache<Integer, MyFreeCamsModel> models = CacheBuilder.newBuilder().maximumSize(4000).build();
private final Lock lock = new ReentrantLock();
private ServerConfig serverConfig;
@SuppressWarnings("unused")
private String tkx;
@ -74,9 +74,10 @@ public class MyFreeCamsClient {
private long heartBeat;
private volatile boolean connecting = false;
private static int messageId = 31415; // starting with 31415 just for fun
private Map<Integer, Consumer<Message>> responseHandlers = new HashMap<>();
private final Map<Integer, Consumer<Message>> responseHandlers = new HashMap<>();
private final Random rng = new Random();
private Queue<String> receivedTextHistory = new LinkedList<>();
private final Queue<String> receivedTextHistory = new LinkedList<>();
private MyFreeCamsClient() {
moshi = new Moshi.Builder().build();
@ -104,7 +105,7 @@ public class MyFreeCamsClient {
}
}
String server = websocketServers.get(new Random().nextInt(websocketServers.size() - 1));
String server = websocketServers.get(rng.nextInt(websocketServers.size() - 1));
String wsUrl = "wss://" + server + ".myfreecams.com/fcsl";
LOG.debug("Connecting to random websocket server {}", wsUrl);
@ -636,7 +637,7 @@ public class MyFreeCamsClient {
public String getStreamUrl(SessionState state) {
int userChannel = 100000000 + state.getUid();
String phase = Optional.ofNullable(state).map(SessionState::getU).map(User::getPhase).orElse("z");
String phase = Optional.of(state).map(SessionState::getU).map(User::getPhase).orElse("z");
String phasePrefix = phase.equals("z") ? "" : '_' + phase;
String server = "video" + getCamServ(state).replaceAll("^\\D+", "");
String nonce = Double.toString(Math.random());
@ -645,21 +646,21 @@ public class MyFreeCamsClient {
}
private String getCamServ(SessionState state) {
Integer camserv = Optional.ofNullable(state.getU()).map(User::getCamserv).orElse(-1);
String camservString = camserv.toString();
int camserv = Optional.ofNullable(state.getU()).map(User::getCamserv).orElse(-1);
String camservString = Integer.toString(camserv);
if (serverConfig.isOnWzObsVideoServer(state)) {
camservString = serverConfig.wzobsServers.get(camserv.toString());
camservString = serverConfig.wzobsServers.get(camservString);
} else if (serverConfig.isOnObsServer(state)) {
camservString = serverConfig.ngVideoServers.get(camserv.toString());
camservString = serverConfig.ngVideoServers.get(camservString);
} else if (serverConfig.isOnHtml5VideoServer(state)) {
camservString = serverConfig.h5Servers.get(camserv.toString());
camservString = serverConfig.h5Servers.get(camservString);
} else if (camserv > 500) {
if (camserv >= 3000) {
camserv -= 1000;
} else {
camserv -= 500;
}
camservString = camserv.toString();
camservString = Integer.toString(camserv);
}
return camservString;
}
@ -674,9 +675,12 @@ public class MyFreeCamsClient {
}
public SessionState getSessionState(ctbrec.Model model) {
for (SessionState state : sessionStates.asMap().values()) {
if (Objects.equals(state.getNm(), model.getName())) {
return state;
if (model instanceof MyFreeCamsModel) {
MyFreeCamsModel mfcModel = (MyFreeCamsModel) model;
for (SessionState state : sessionStates.asMap().values()) {
if (mfcModel.getUid() > 0 && state.getUid() != null && state.getUid() > 0 && mfcModel.getUid() == state.getUid()) {
return state;
}
}
}
return null;
@ -723,6 +727,37 @@ public class MyFreeCamsClient {
return result;
}
/**
* Tries to look up the sessionId of a model
*/
public String getSessionId(String modelName) throws InterruptedException {
if (ws == null) {
return "";
}
LOG.trace("Sending USERNAMELOOKUP for {}", modelName);
int msgId = messageId++;
Object monitor = new Object();
List<String> resultHolder = new ArrayList<>();
responseHandlers.put(msgId, msg -> {
LOG.trace("Search result: {}", msg);
if (StringUtil.isNotBlank(msg.getMessage()) && !Objects.equals(msg.getMessage(), modelName)) {
JSONObject json = new JSONObject(msg.getMessage());
resultHolder.add(Integer.toString(json.optInt("sid")));
}
synchronized (monitor) {
monitor.notifyAll();
}
});
ws.send("10 " + sessionId + " 0 " + msgId + " 0 " + modelName + "\n");
synchronized (monitor) {
monitor.wait();
}
return resultHolder.isEmpty() ? "" : resultHolder.get(0);
}
public Collection<SessionState> getSessionStates() {
return Collections.unmodifiableCollection(sessionStates.asMap().values());
}

View File

@ -1,31 +1,9 @@
package ctbrec.sites.mfc;
import static ctbrec.io.HttpConstants.*;
import static java.util.Optional.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import javax.xml.bind.JAXBException;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.iheartradio.m3u8.ParseException;
import com.iheartradio.m3u8.PlaylistException;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import ctbrec.AbstractModel;
import ctbrec.Config;
import ctbrec.io.HtmlParser;
@ -38,6 +16,19 @@ import okhttp3.FormBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.jsoup.nodes.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;
import java.util.concurrent.ExecutionException;
import static ctbrec.io.HttpConstants.*;
import static java.util.Optional.ofNullable;
public class MyFreeCamsModel extends AbstractModel {
@ -67,15 +58,38 @@ public class MyFreeCamsModel extends AbstractModel {
@Override
public boolean isOnline(boolean ignoreCache) throws IOException, ExecutionException, InterruptedException {
return isOnline();
if (ignoreCache) {
String sessionId = MyFreeCamsClient.getInstance().getSessionId(getName());
boolean online = !(sessionId.isEmpty() || sessionId.equals("0"));
SessionState sessionState = MyFreeCamsClient.getInstance().getSessionState(this);
if (online) {
if (sessionState == null) {
LOG.warn("MFC model {} [{}] seems to be online but a SessionState could not be found", getName(), getUid());
}
} else {
state = ctbrec.sites.mfc.State.OFFLINE;
}
return online;
} else {
return isOnline();
}
}
@Override
public State getOnlineState(boolean failFast) throws IOException, ExecutionException {
if(state == null) {
if (state == null) {
return State.UNKNOWN;
}
if (!failFast) {
MyFreeCamsClient.getInstance().update(this);
try {
isOnline(true);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
switch(state) {
case ONLINE:
case RECORDING:
@ -106,7 +120,7 @@ public class MyFreeCamsModel extends AbstractModel {
}
private String updateStreamUrl() {
if(streamUrl == null) {
if (streamUrl == null) {
MyFreeCams mfc = (MyFreeCams) getSite();
mfc.getClient().update(this);
}
@ -129,9 +143,9 @@ public class MyFreeCamsModel extends AbstractModel {
.header(USER_AGENT, Config.getInstance().getSettings().httpUserAgent)
.header(CONNECTION, KEEP_ALIVE)
.build();
try(Response resp = site.getHttpClient().execute(req)) {
if(resp.isSuccessful()) {
String page = resp.body().string();
try (Response resp = site.getHttpClient().execute(req)) {
if (resp.isSuccessful()) {
String page = Objects.requireNonNull(resp.body(), "HTTP response is null").string();
Element hiddenInput = HtmlParser.getTag(page, "input[name=token]");
String token = hiddenInput.attr("value");
if (!Objects.equals(System.getenv("CTBREC_DEV"), "1")) {