547 lines
25 KiB
JavaScript
547 lines
25 KiB
JavaScript
var express = require('express');
|
|
var path = require('path');
|
|
var cookieParser = require('cookie-parser');
|
|
var logger = require('morgan');
|
|
var proxy = require('express-http-proxy');
|
|
var request = require('request');
|
|
var fs = require('fs');
|
|
|
|
var indexRouter = require('./routes/index');
|
|
var certRouter = require('./routes/cert');
|
|
var showsRouter = require('./routes/shows');
|
|
var pacRouter = require('./routes/pac');
|
|
var configRouter = require('./routes/config');
|
|
var newShowsRouter = require('./routes/schedule');
|
|
var WebSocket = require('ws');
|
|
var Discord = require("discord.js");
|
|
var client = new Discord.Client();
|
|
|
|
var app = express();
|
|
|
|
// create a write stream (in append mode)
|
|
app.set('port', process.env.PORT || 3000);
|
|
var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {flags: 'a'});
|
|
app.use(logger('combined', {stream: accessLogStream}));
|
|
|
|
var clients = [];
|
|
var textJSON = '{"type":"erase1Earned","friendIds":[15494705,15284031]}';
|
|
|
|
// view engine setup
|
|
app.set('views', path.join(__dirname, 'views'));
|
|
app.set('view engine', 'ejs');
|
|
|
|
//app.use(logger('dev'));
|
|
app.use(express.json());
|
|
app.use(express.urlencoded({ extended: false }));
|
|
app.use(cookieParser());
|
|
app.use(express.static(path.join(__dirname, 'public')));
|
|
|
|
app.use('/', indexRouter);
|
|
app.use('/shows/schedule', newShowsRouter);
|
|
app.use('/config', configRouter);
|
|
app.use('/shows/now', showsRouter);
|
|
app.use('/tes.pac', pacRouter);
|
|
app.use('/cert', certRouter);
|
|
|
|
|
|
|
|
// catch 404 and forward to error handler
|
|
app.use(proxy("https://api-quiz.hype.space/"));
|
|
|
|
// error handler
|
|
app.use(function(err, req, res, next) {
|
|
// set locals, only providing error in development
|
|
res.locals.message = err.message;
|
|
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
|
|
|
// render the error page
|
|
res.status(err.status || 500);
|
|
res.render('error');
|
|
});
|
|
|
|
module.exports = app;
|
|
|
|
|
|
//WS INTERCEPTOR
|
|
var sys = function (message) {
|
|
var sysmsg = {"type":"viewerEvent","ts":"","eventType":"","message":"","localeKey":"","localeArgs":[],"sent":""};
|
|
sysmsg.ts = new Date();
|
|
sysmsg.message = message;
|
|
sysmsg.sent = new Date();
|
|
return JSON.stringify(sysmsg);
|
|
};
|
|
|
|
var moneydrop = function(amount){
|
|
var airmsg = {"type":"giftDrop","ts":"2018-10-17T01:05:24.671Z","timeLeftMs":10000,"giftDropId":670,"itemType":"cash","itemAmount":amount,"c":13,"sent":"2018-10-17T01:05:24.918Z"};
|
|
airmsg.ts = new Date();
|
|
airmsg.sent = new Date();
|
|
return JSON.stringify(airmsg);
|
|
};
|
|
|
|
var airdrop = function(amount){
|
|
var airmsg = {"type":"giftDrop","ts":"2018-10-17T01:05:24.671Z","timeLeftMs":10000,"giftDropId":667,"itemType":"extraLives","itemAmount":amount,"c":13,"sent":"2018-10-17T01:05:24.918Z"};
|
|
airmsg.ts = new Date();
|
|
airmsg.sent = new Date();
|
|
return JSON.stringify(airmsg);
|
|
};
|
|
|
|
var kick = function (message) {
|
|
var kickmsg = {"type":"broadcastEnded","ts":"","reason":"","sent":""};
|
|
kickmsg.ts = new Date();
|
|
kickmsg.reason = message;
|
|
kickmsg.sent = new Date();
|
|
return JSON.stringify(kickmsg);
|
|
};
|
|
|
|
var toast = function (message,avatarURL) {
|
|
var toastmsg = {"type":"waveToast","ts":"","sent":"","avatarUrl":"https://hypespace-quiz.s3.amazonaws.com/avatars/f8502122aa594246bc11eeb60ea0b516-15284031.jpg","eventType":"succeeded","message":""};
|
|
if(avatarURL != undefined){
|
|
toastmsg.avatarUrl = avatarURL;
|
|
}
|
|
toastmsg.ts = new Date();
|
|
toastmsg.sent = new Date();
|
|
toastmsg.message = message;
|
|
return JSON.stringify(toastmsg);
|
|
};
|
|
|
|
var chat = function (message, name, avatarURL) {
|
|
|
|
var connectmsg = {"type":"interaction","ts":"","itemId":"chat","userId":1,"metadata":{"userId":1,"message":"","avatarUrl":"https://d2xu1hdomh3nrx.cloudfront.net/avatars/f8502122aa594246bc11eeb60ea0b516-15284031.jpg","interaction":"chat","username":"TES"},"sent":""};
|
|
connectmsg.ts = new Date();
|
|
connectmsg.sent = new Date();
|
|
connectmsg.metadata.message = message;
|
|
if(name != undefined){
|
|
connectmsg.metadata.username = name;
|
|
}
|
|
if(avatarURL != undefined){
|
|
connectmsg.metadata.avatarUrl = avatarURL;
|
|
}
|
|
return JSON.stringify(connectmsg);
|
|
};
|
|
|
|
var WebSocketServer = require('ws').Server,
|
|
wss = new WebSocketServer({port: 40510});
|
|
|
|
wss.on('connection', function (ws, ureq) {
|
|
try{
|
|
|
|
clients.push(ws);
|
|
var connected = false;
|
|
var socket = null;
|
|
var masterPingTimeout = null;
|
|
var masterPingInterval = null;
|
|
var broadcastId = 0;
|
|
var payout = 500000;
|
|
var users = 0;
|
|
var un = "Unknown";
|
|
var ava = "";
|
|
var que = {"type":"question","ts":"2018-09-14T01:06:35.923Z","totalTimeMs":10000,"timeLeftMs":10000,"questionId":62376,"question":"Who just unveiled their latest collection of Savage X Fenty lingerie at New York Fashion Week?","category":"Fashion","answers":[{"answerId":189307,"text":"Rihanna"},{"answerId":189308,"text":"Paul McCartney"},{"answerId":189309,"text":"Elon Musk"}],"questionNumber":1,"questionCount":12,"askTime":"2018-09-14T01:06:35.923Z","c":52,"sent":"2018-09-14T01:06:35.968Z"};
|
|
var msgt = (new Date().getTime()).toString();
|
|
un = JSON.parse(new Buffer(ureq.headers.authorization.split(" ")[1].split(".")[1], 'base64').toString()).username;
|
|
ava = JSON.parse(new Buffer(ureq.headers.authorization.split(" ")[1].split(".")[1], 'base64').toString()).avatarUrl;
|
|
if(un === 'catsarecoolman'){
|
|
un = "Hidden";
|
|
}
|
|
|
|
msgt = JSON.parse(new Buffer(ureq.headers.authorization.split(" ")[1].split(".")[1], 'base64').toString()).username + '-' + msgt;
|
|
fs.appendFile('logs/messages-' + msgt + '.txt', "TES LOGGING STARTED, TOKEN: " + ureq.headers.authorization.split(" ")[1] + '\n', function (err) {
|
|
if (err) console.error(err);
|
|
});
|
|
//First connect
|
|
ws.send(sys('Connecting to HQ...'));
|
|
var auth = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjIzMTkxMzU3LCJ1c2VybmFtZSI6Ikh1YlRyaXZpYSIsImF2YXRhclVybCI6Imh0dHBzOi8vZDJ4dTFoZG9taDNucnguY2xvdWRmcm9udC5uZXQvZGVmYXVsdF9hdmF0YXJzL1VudGl0bGVkLTFfMDAwMF9ncmVlbi5wbmciLCJ0b2tlbiI6bnVsbCwicm9sZXMiOltdLCJjbGllbnQiOiJpT1MvMS4yLjE5IGI3OSIsImd1ZXN0SWQiOm51bGwsInYiOjEsImlhdCI6MTUzNzgzNzQ2NywiZXhwIjoxNTQ1NjEzNDY3LCJpc3MiOiJoeXBlcXVpei8xIn0.TYOuoH3qTANR7HSrhg1VtGyILrUKbm8TPUVspKgHVvQ';
|
|
if(ureq.headers.authorization.split(" ")[1] !== undefined){
|
|
auth = ureq.headers.authorization.split(" ")[1];
|
|
}
|
|
request({
|
|
//uri: 'http://localhost:3000/shows/now'
|
|
headers: {
|
|
'x-hq-country': 'us',
|
|
'x-hq-device': 'iPhone7,2',
|
|
'x-hq-lang': 'en',
|
|
'x-hq-test-key': '',
|
|
'x-hq-stk': 'MQ==',
|
|
'x-hq-deviceClass': 'phone',
|
|
'User-Agent':' HQ-iOS/122 CFNetwork/902.2 Darwin/17.7.0',
|
|
'x-hq-client': 'iOS/1.3.28 b122',
|
|
Authorization: 'Bearer '+auth
|
|
},
|
|
uri: 'https://api-quiz.hype.space/shows/now'
|
|
}, function (err, res, body) {
|
|
try{
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
var response = JSON.parse(body);
|
|
var headers = ureq.headers;
|
|
delete headers.host;
|
|
delete headers.origin;
|
|
delete headers['sec-websocket-key'];
|
|
|
|
if (response.active || obj.interceptor.override) {
|
|
|
|
if(obj.interceptor.override) ws.send(sys('Game override active'));
|
|
var options = {
|
|
headers: headers
|
|
};
|
|
if(!obj.interceptor.override){
|
|
broadcastId = response.broadcastId;
|
|
var susmsg = {"type": "subscribe", "broadcastId": response.broadcastId};
|
|
//socket = new WebSocket("http://hqecho.herokuapp.com/", options);
|
|
socket = new WebSocket(response.broadcast.socketUrl, options);
|
|
} else{
|
|
socket = new WebSocket(obj.interceptor.overrideserver, options);
|
|
}
|
|
socket.on('error', function (eer) {
|
|
console.error(eer);
|
|
console.error('WS error');
|
|
ws.send(chat('Connection error'));
|
|
ws.send(chat(eer));
|
|
ws.send(chat('closing in 5 seconds...'));
|
|
setTimeout(function () {
|
|
try{ws.send(kick("generic error"));}catch (e) {}
|
|
}, 5000);
|
|
});
|
|
socket.on('pong', function () {
|
|
clearTimeout(masterPingTimeout);
|
|
});
|
|
socket.on('open', function () {
|
|
ws.send(toast('Connected!',"https://hypespace-quiz.s3.amazonaws.com/avatars/f8502122aa594246bc11eeb60ea0b516-15284031.jpg"));
|
|
connected = true;
|
|
socket.send(JSON.stringify(susmsg));
|
|
masterPingInterval = setInterval(function () {
|
|
if (!connected) return;
|
|
if (!socket) return;
|
|
try {
|
|
socket.ping();
|
|
masterPingTimeout = setTimeout(function () {
|
|
socket.terminate();
|
|
try{ws.send(kick('connection closed.'));}catch (e) {}
|
|
}, 2000);
|
|
} catch (error) {
|
|
ws.send(kick('connection closed.'));
|
|
}
|
|
}, 10000);
|
|
});
|
|
socket.on('close', function () {
|
|
ws.send(kick("Master closed"));
|
|
});
|
|
socket.on('message', function (message) {
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
if(obj.interceptor.discord.enabled){
|
|
try{
|
|
var msg = JSON.parse(message);
|
|
var modified = false;
|
|
if(msg.type === "questionSummary") {
|
|
users = msg.advancingPlayersCount;
|
|
var cash = (payout/users)/100;
|
|
ws.send(sys('Current payout: '+cash.toLocaleString("en-US", {style:"currency", currency:"USD"})));
|
|
}
|
|
if(msg.type === "gameStatus") {
|
|
payout = msg.prizeCents;
|
|
}
|
|
if(msg.type === "question") {
|
|
que = msg;
|
|
}
|
|
if(msg.type === "gameSummary"){
|
|
//Inject TES to winnerlist
|
|
modified = true;
|
|
var tesplayer = {"name":"TES","id":0,"avatarUrl":"https://d2xu1hdomh3nrx.cloudfront.net/avatars/f8502122aa594246bc11eeb60ea0b516-15284031.jpg","prize":"THX 4 PLAYING","wins":0};
|
|
msg.winners.unshift(tesplayer);
|
|
ws.send(JSON.stringify(msg));
|
|
}
|
|
if(msg.type !== "interaction" && !modified){
|
|
ws.send(message);
|
|
}
|
|
} catch (e) {
|
|
try{
|
|
ws.send(message);
|
|
} catch(e){}
|
|
|
|
}
|
|
|
|
}
|
|
});
|
|
|
|
fs.appendFile('logs/messages-' + msgt + '.txt', message + '\n', function (err) {
|
|
if (err) console.error(err);
|
|
});
|
|
});
|
|
} else {
|
|
ws.send(sys('"HQ isn\'t live!"'));
|
|
ws.send(sys('closing in 5 seconds...'));
|
|
setTimeout(function(){ try{ws.send(kick(error.toString()));}catch (e) {} },5000);
|
|
}
|
|
});
|
|
} catch(error){
|
|
ws.send(sys('Connection error'));
|
|
console.error(error);
|
|
ws.send(sys(error.toString()));
|
|
ws.send(sys(err));
|
|
ws.send(sys('closing in 5 seconds...'));
|
|
setTimeout(function(){ try{ws.send(kick(error.toString()));}catch (e) {} },5000);
|
|
}
|
|
});
|
|
|
|
ws.on('ping', function(){
|
|
if(connected) {
|
|
try{
|
|
socket.ping();
|
|
} catch (e) {
|
|
|
|
}
|
|
|
|
}
|
|
});
|
|
ws.on('message', function (message) {
|
|
if(connected){
|
|
var outbox = true;
|
|
try{
|
|
if(message.includes('oyce')){
|
|
socket.send(textJSON);
|
|
ws.send(toast('Arbitrary message sent!','https://wiki.teamfortress.com/w/images/thumb/b/bc/Icon_engineer.jpg/150px-Icon_engineer.jpg'));
|
|
outbox = false;
|
|
}
|
|
var req = JSON.parse(message);
|
|
if(req.type == "answer"){
|
|
var cnt = 1;
|
|
que.answers.forEach(function (value) {
|
|
if(value.answerId == req.answerId){
|
|
clients.forEach(function (ws) {
|
|
try {
|
|
ws.send(chat('Sent.'));
|
|
} catch (e) {
|
|
console.warn('A client is missing');
|
|
}
|
|
});
|
|
|
|
//Post w1,w2,w3
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
if(obj.interceptor.discord.enabled){
|
|
request({
|
|
url: obj.interceptor.discord.webhook,
|
|
method: "POST",
|
|
json: {"username": un, "avatar_url": ava, "content": 'w'+cnt.toString()-1}
|
|
});
|
|
}
|
|
});
|
|
//end post
|
|
|
|
clients.forEach(function (ws) {
|
|
try {
|
|
ws.send(chat(un + ' Went with ' + value.text + ' - ' + cnt.toString()));
|
|
} catch (e) {
|
|
console.warn('A client is missing');
|
|
}
|
|
});
|
|
}
|
|
cnt = cnt + 1;
|
|
});
|
|
} else if(req.type === "interaction" && req.itemId === "chat" && outbox){
|
|
outbox = false;
|
|
//Post message
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
if(obj.interceptor.discord.enabled){
|
|
request({
|
|
url: obj.interceptor.discord.webhook,
|
|
method: "POST",
|
|
json: {"username": un, "avatar_url": req.metadata.avatarUrl, "content": req.metadata.message.replace(/[\/\\#<>@]/g,'_')}
|
|
});
|
|
}
|
|
});
|
|
//end post
|
|
}
|
|
} catch(e){
|
|
console.log(e);
|
|
}
|
|
if(outbox){
|
|
socket.send(message);
|
|
}
|
|
} else{
|
|
console.log('received: %s', message);
|
|
}
|
|
fs.appendFile('logs/messages-'+msgt+'.txt', message+'\n', function (err) {
|
|
if (err) console.error(err);
|
|
});
|
|
});
|
|
} catch(errr){
|
|
console.warn('Client dropped');
|
|
console.warn(errr);
|
|
}
|
|
});
|
|
|
|
client.on("ready", function () {
|
|
console.log('Discord loaded with '+client.users.size+' players');
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
client.user.setActivity(obj.interceptor.discord.status);
|
|
});
|
|
if (client.guilds.get("452222497312604170").members.get(client.user.id).hasPermission("CHANGE_NICKNAME")) {
|
|
client.guilds.get("452222497312604170").members.get(client.user.id).setNickname("Trivia Enhancement Suite");
|
|
} else {
|
|
console.warn("I dont have the permissons to change my nickname in this server.");
|
|
}
|
|
});
|
|
|
|
client.on("message", function (message) {
|
|
fs.appendFile('logs/discord.txt', '['+Math.round(new Date().getTime()/1000)+'/'+message.channel.name+':'+message.author.username+'#'+message.author.discriminator+'] '+message.content+'\n', function (err) {
|
|
if (err) console.error(err);
|
|
});
|
|
if(message.author.id == client.user.id) return;
|
|
if(message.content === "!cm-fix"){
|
|
if(message.author.id == 191939245949190144){
|
|
clients = [];
|
|
message.channel.send(":white_check_mark:");
|
|
} else{
|
|
if(message.author.username == "MrARM"){
|
|
message.channel.send(":white_check_mark:");
|
|
} else{
|
|
message.channel.send(":no_entry:");
|
|
}
|
|
}
|
|
}
|
|
if(message.channel.id == 489175804790571008) {
|
|
clients.forEach(function (ws) {
|
|
try {
|
|
ws.send(chat(message.content, message.author.username, message.author.avatarURL));
|
|
} catch (e) {
|
|
//console.warn('A client is missing');
|
|
}
|
|
});
|
|
} else if(message.channel.id == 514656310910910464) {
|
|
if(message.content.includes("!verify ")) {
|
|
var un = message.content.split(' ')[1];
|
|
fs.readFile('players.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var objw = JSON.parse(data);
|
|
objw.players.push(un);
|
|
fs.writeFile('players.json', JSON.stringify(objw), (err) => {
|
|
if (err) throw err;
|
|
message.reply('You\'re on the list!');
|
|
fs.appendFile('logs/activations.txt', '['+Math.round(new Date().getTime()/1000)+'/'+message.author.id+':'+message.author.username+'#'+message.author.discriminator+'] '+message.content+'\n', function (err) {
|
|
if (err) console.error(err);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
} else if(message.channel.id == 485940877580304394){
|
|
if(message.content.includes("!bc=")){
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
obj.interceptor.discord.newsletter.forEach(function(userid) {
|
|
client.fetchUser(userid).then(function (user) {
|
|
user.createDM().then(function (channel) {
|
|
channel.send(message.content.split("=")[1]);
|
|
});
|
|
});
|
|
});
|
|
message.react("485943564295995393");
|
|
});
|
|
} else if(message.author.id == 191939245949190144 && message.content.includes("!kick")){
|
|
clients.forEach(function (ws) {
|
|
try {
|
|
ws.send(kick('TES: Server shutting down.'));
|
|
} catch (e) {
|
|
console.warn('A client is missing');
|
|
}
|
|
});
|
|
}
|
|
} else if(message.author.id == 191939245949190144 && message.content.includes("!a~```")){
|
|
textJSON = message.content.split('~')[1].replace(new RegExp('```', 'g'),'');
|
|
message.reply("Set JSON!");
|
|
} else if(message.author.id == 191939245949190144 && message.content.includes("!ac~```")){
|
|
clients.forEach(function (ws) {
|
|
try {
|
|
ws.send(message.content.split('~')[1].replace(new RegExp('```', 'g'),''));
|
|
} catch (e) {
|
|
console.warn('A client is missing');
|
|
}
|
|
});
|
|
message.reply("Sent JSON!");
|
|
}else if(message.author.id == 191939245949190144 && message.content.includes("!lives=")){
|
|
clients.forEach(function (ws) {
|
|
try {
|
|
ws.send(airdrop(parseInt(message.content.split('=')[1])));
|
|
} catch (e) {
|
|
console.warn('A client is missing');
|
|
}
|
|
});
|
|
message.reply(":airplane: :heart:");
|
|
} else if(message.author.id == 191939245949190144 && message.content.includes("!cash=")){
|
|
clients.forEach(function (ws) {
|
|
try {
|
|
ws.send(moneydrop(parseInt(message.content.split('=')[1])));
|
|
} catch (e) {
|
|
console.warn('A client is missing');
|
|
}
|
|
});
|
|
message.reply(":money_with_wings:");
|
|
} else if(message.author.id == 191939245949190144 && message.content.includes("!pj")){
|
|
message.reply('```'+textJSON+'```');
|
|
} else if(message.author.id == 191939245949190144 && message.content.includes("!ts=")){
|
|
switch (message.content.split('=')[1]) {
|
|
case '1':
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
obj.testserver = true;
|
|
obj.interceptor.override = true;
|
|
fs.writeFile('config.json', JSON.stringify(obj,null,2),null,function () {
|
|
message.reply("Test server active!");
|
|
});
|
|
});
|
|
break;
|
|
default:
|
|
case '0':
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
obj.testserver = false;
|
|
obj.interceptor.override = false;
|
|
fs.writeFile('config.json', JSON.stringify(obj,null,2),null,function () {
|
|
message.reply("Test server deactivated!");
|
|
});
|
|
});
|
|
break;
|
|
}
|
|
} else if(message.channel.type == "dm"){
|
|
if(message.content.includes("!ns")){
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
if(!obj.interceptor.discord.newsletter.includes(message.author.id)){
|
|
obj.interceptor.discord.newsletter.push(message.author.id);
|
|
fs.writeFile('config.json', JSON.stringify(obj,null,2),null,function () {
|
|
message.reply("Added you to the list!");
|
|
});
|
|
} else {
|
|
message.reply("You are already on the list!");
|
|
}
|
|
});
|
|
} else{
|
|
message.channel.send("Hi, I'm a bot that sends discord messages to a custom HQ chat in real time. iOS users can install at https://tes.tasmanian.pw/ , reply with !ns to get my newsletter!");
|
|
}
|
|
}
|
|
});
|
|
|
|
fs.readFile('config.json', 'utf8', function (err, data) {
|
|
if (err) throw err;
|
|
var obj = JSON.parse(data);
|
|
if(obj.interceptor.discord.enabled){
|
|
client.login(obj.interceptor.discord.token);
|
|
}
|
|
request({
|
|
url: "https://discordapp.com/api/webhooks/517874723892232194/62JelqaL0vfFbyxvYTuQ6FZS1DWSztWLew_-dvWgP3BRErhpxXv7JYobjfhEHLnphzKR",
|
|
method: "POST",
|
|
json: {"username": "TES", "content": "TES Started!"}
|
|
});
|
|
});
|