webchat/www/index.php

309 lines
10 KiB
PHP

<?php
session_start();
// Webchat data dir
$webchatdir='/var/games/minetest-server/.minetest/worlds/SecklSurvival/webchat';
// Generate a unique color for every username based on its crc32 hash sum
function playercolor($player,$color) {
list($r1,$r2,$g1,$g2,$b1,$b2)=str_split(dechex(crc32($player)),1);
if ($color=="r") {
return 'ff'.$g1.$g2.$b1.$b2;
} elseif ($color=="g") {
return $r1.$r2.'ff'.$b1.$b2;
} elseif ($color=="b") {
return $r1.$r2.$g1.$g2.'ff';
}
}
if (empty($_SESSION['player'])) {
// Not logged in => Please login first
header('Location: /login/');
exit();
} elseif (isset($_GET['lastchatline']) and isset($_GET['lastservline'])) {
// Send/update chat history to browser
$mt_socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($mt_socket,'127.0.0.1','29999');
$cmd=json_encode(array('lua'=>"webchat.ping('".$_SESSION['player']."')",'id'=>'chat_ping'))."\n";
socket_write($mt_socket,$cmd,strlen($cmd));
$reply=socket_read($mt_socket,1048576);
socket_close($mt_socket);
$chatdata=array();
$chatlines=0;
$loglines=file($webchatdir.'/chat.log');
foreach ($loglines as $chatline) {
$chatlines++;
// Return all lines after $_GET['lastchatline']
if ($chatlines > $_GET['lastchatline']) {
// Edit line
list($timestamp,$user,$text)=explode("\t",htmlspecialchars(trim($chatline),ENT_QUOTES));
$date=date('Y-m-d',$timestamp);
$time=date('H:i:s T',$timestamp);
$color=playercolor($user,"b");
$chatline='<tr style="color: #'.$color.'"><td id="u">&lt;'.$user.'&gt;</td><td><span id="d">&nbsp;'.$date.'</span><span id="t">&nbsp;'.$time.'</span></td></tr><tr style="color: #'.$color.'"><td id="txt" colspan="2">'.$text.'</td></tr>';
array_push($chatdata,$chatline);
}
}
$dmdata=array();
$dmlines=0;
$loglines=file($webchatdir.'/playerdata/'.$_SESSION['player'].'/dm.log');
foreach ($loglines as $dmline) {
$dmlines++;
// Return all lines after $_GET['lastdmline']
if ($dmlines > $_GET['lastdmline']) {
// Edit line
list($timestamp,$fromto,$user,$text)=explode("\t",htmlspecialchars(trim($dmline),ENT_QUOTES));
$date=date('Y-m-d',$timestamp);
$time=date('H:i:s T',$timestamp);
if ($user=="+error+") {
if ($timestamp > time()-300) {
// Show only error messages from the last 5 min
$color='ff0000';
$dmline='<tr style="color: #'.$color.'"><td id="err" colspan="2"><dfn class="wchat-tooltip" wchat-tooltip-text="Valid commands are: /msg &lt;player&gt; &lt;message&gt;, /me &lt;message&gt;">Error: '.$text.'</dfn></td></tr>';
array_push($dmdata,$dmline);
}
} else {
$color=playercolor($user,"r");
$dmline='<tr style="color: #'.$color.'"><td id="u">DM '.$fromto.' '.$user.':</td><td><span id="d">&nbsp;'.$date.'</span><span id="t">&nbsp;'.$time.'</span></td></tr><tr style="color: #'.$color.'"><td id="txt" colspan="2">'.$text.'</td></tr>';
array_push($dmdata,$dmline);
}
}
}
$servdata=array();
$servlines=0;
$loglines=file($webchatdir.'/server.log');
foreach ($loglines as $servline) {
$servlines++;
// Return all lines after $_GET['lastservline']
if ($servlines > $_GET['lastservline']) {
// Edit line
list($timestamp,$text)=explode("\t",htmlspecialchars(trim($servline),ENT_QUOTES));
$date=date('Y-m-d',$timestamp);
$time=date('H:i:s T',$timestamp);
$servline='<tr><td id="txt">'.$text.'</td><td><span id="d">&nbsp;'.$date.'</span><span id="t">&nbsp;'.$time.'</span></td></tr>';
array_push($servdata,$servline);
}
}
echo json_encode(array("chatlines"=>$chatlines,"servlines"=>$servlines,"dmlines"=>$dmlines,"chatdata"=>$chatdata,"servdata"=>$servdata,"dmdata"=>$dmdata));
exit();
} elseif (!empty($_POST['msg'])) {
// Send chat message
$mt_socket=socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($mt_socket,'127.0.0.1','29999');
// Sanitize $message
$message=addslashes($_POST['msg']); // Escape some special characters ('"\)
$message=trim($message," \n\r\t\v\0\\"); // Remove some special chars from the beginning and end
$message=substr($message,0,500); // Max length 500 chars
$cmd=json_encode(array('lua'=>"webchat.receive_msg('".$_SESSION['player']."','".$message."')",'id'=>'chat_msg'))."\n";
socket_write($mt_socket,$cmd,strlen($cmd));
$reply=socket_read($mt_socket,1048576);
socket_close($mt_socket);
// Send HTTP 204 so that the browser stays on the page
ob_start();
header("HTTP/1.1 204 NO CONTENT");
header("Cache-Control: no-cache, no-store, must-revalidate");
header("Pragma: no-cache");
header("Expires: 0");
ob_end_flush();
exit();
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Minetest Web Chat</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/style.css">
<script src="jquery.min.js"></script>
<script>
function ToggleChat() {
var chlog=document.getElementById("wchat-chatlog");
var chbut=document.getElementById("wchat-chswbt-ch");
var dmlog=document.getElementById("wchat-dmlog");
var dmbut=document.getElementById("wchat-chswbt-dm");
if (chlog.style.display==="none") {
chlog.style.display="flex";
chlog.style.width="50%";
chlog.style.float="left";
chbut.style.color="#000";
chbut.style.background="#2c9cdc";
dmlog.style.display="flex";
dmlog.style.width="50%";
dmbut.style.color="#000";
dmbut.style.background="#2c9cdc";
} else {
chlog.style.display="none";
chbut.style.color="inherit";
chbut.style.background="inherit";
dmlog.style.display="flex";
dmlog.style.width="100%";
dmbut.style.color="#000";
dmbut.style.background="#2c9cdc";
}
}
function ToggleDM() {
var dmlog=document.getElementById("wchat-dmlog");
var dmbut=document.getElementById("wchat-chswbt-dm");
var chlog=document.getElementById("wchat-chatlog");
var chbut=document.getElementById("wchat-chswbt-ch");
if (dmlog.style.display==="none") {
chlog.style.display="flex";
chlog.style.width="50%";
chlog.style.float="left";
chbut.style.color="#000";
chbut.style.background="#2c9cdc";
dmlog.style.display="flex";
dmlog.style.width="50%";
dmbut.style.color="#000";
dmbut.style.background="#2c9cdc";
} else {
chlog.style.display="flex";
chlog.style.width="100%";
chlog.style.float="none";
chbut.style.color="#000";
chbut.style.background="#2c9cdc";
dmlog.style.display="none";
dmbut.style.color="inherit";
dmbut.style.background="inherit";
}
}
function playSound(url) {
const audio=new Audio(url);
audio.play();
}
function scrollDown() {$("html, body").animate({scrollTop: $(document).height()}, "fast")}
function SelectChatMsg() {document.getElementsByName("msg")[0].select()}
function Logout() {window.location.replace('/login/?logout')}
lastChatLine=0;
lastDmLine=0;
lastServLine=0;
scrollOnce=true;
$(document).ready(function() {
// Scroll to bottom once after the page has loaded
scrollDown();
});
// Update the chat/dm/server history
$.ajaxSetup({timeout: 1500}); // Timeout 1.5 sec for getJSON
setInterval("updateHist()",2000); // Update history every 2 sec
function updateHist() {
$.getJSON('?lastchatline='+lastChatLine+'&lastdmline='+lastDmLine+'&lastservline='+lastServLine,function(data) {
if (lastChatLine!=data.chatlines || lastDmLine!=data.dmlines || lastServLine!=data.servlines) {
// Play sound and scroll to bottom on incoming message
playSound('snd-msg.ogg');
scrollDown();
}
lastChatLine=data.chatlines;
lastDmLine=data.dmlines;
lastServLine=data.servlines;
$.each(data.chatdata,function(key,value) {
$("#wchat-chatlog").append(''+value);
});
$.each(data.dmdata,function(key,value) {
$("#wchat-dmlog").append(''+value);
});
$.each(data.servdata,function(key,value) {
$("#wchat-servlog").append(''+value);
});
// Scroll to bottom once when chat history has been loaded
if (scrollOnce) {
scrollDown();
scrollOnce=false;
}
});
}
</script>
</head>
<body>
<div class="wchat-content">
<h3 id="help">Minetest Web Chat</h3>
<p>The chat works the same as the Minetest in-game chat:
<ul>
<li>Chat and /me messages will be sent to all connected players (Minetest and Web Chat).</li>
<li>Direct messages (DM) to one player can be sent with /msg &lt;player&gt; &lt;message&gt;.</li>
</ul>
See the <a href="https://wiki.minetest.net/Chat#Sending_messages" target="_blank">Minetest Wiki</a> for details.
Chat and /me messages are shown on the left side, DM on the right.
</p>
<p>
You can hide and unhide the columns by clicking on the green buttons below.
</p>
<table class="wchat-chatout" id="wchat-chatlog"></table>
<table class="wchat-chatout" id="wchat-dmlog"></table>
<table id="wchat-chatsw"><tr><td class="wchat-chswbt" id="wchat-chswbt-ch" onclick="ToggleChat()">Chat</td><td class="wchat-chswbt" id="wchat-chswbt-dm" onclick="ToggleDM()"><span id="long">Direct Messages</span><span id="short">DM</span></td></tr></table>
<table id="wchat-chatin"><tbody>
<tr><td>
<form method="POST" action="" onsubmit="SelectChatMsg()">
<?php
echo ' <p id="u">&lt;'.$_SESSION['player'].'&gt;&nbsp;&nbsp;<a href="#help">?</a></p>'."\n";
?>
<p><input type="text" required minlength="1" name="msg" placeholder="Type your message here and press enter..." autofocus autocomplete="off"></p>
<p><input style="width: 65%; margin-right: 5px" type="submit" value="Send"><input style="width: calc(100% - 65% - 10px); margin-left: 5px" type="button" value="Logout" onclick="Logout()"></p>
</form>
</td></tr>
</tbody></table>
<table class="wchat-chatout" id="wchat-servlog"></table>
</div>
</body>
</html>