-
-
Save masterpoppy/88612afd78add9853e95fc94070a50ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//*********************** | |
//Sample Chat App | |
//2016-12-04 MasterPoppy | |
//*********************** | |
string html = "<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset='UTF-8'> | |
<title>Sample Chat App</title> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js'></script> | |
<script src='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.4/semantic.min.js'></script> | |
<link rel='stylesheet' type='text/css' href='https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.4/semantic.min.css' /> | |
<style type='text/css'> | |
@import url(http://fonts.googleapis.com/earlyaccess/notosansjp.css); | |
.ui, | |
.item, | |
input { | |
font-family: 'Noto Sans JP', helvetica, sans-serif; | |
} | |
.ui, | |
.item, | |
.ui.header, | |
.ui.table { | |
font-size: 1.1rem; | |
line-height: 1.5rem; | |
} | |
.ui.container { | |
padding-top: 1vh; | |
width: calc(100% - 16px); | |
} | |
.ui.middle.attached.segment { | |
height: calc(100vh - 165px); | |
overflow-y: auto; | |
} | |
</style> | |
</head> | |
<body> | |
<div id='main' class='ui container'> | |
<div id='id-header' class='ui top attached block header'> | |
Sample Chat App | |
</div> | |
<div class='ui middle attached menu'> | |
<div id='id-ch' class='item'> | |
通信チャンネル xxx | |
</div> | |
<div class='menu'> | |
<div id='username' class='item'><i class='user icon'></i>USRNAME</div> | |
</div> | |
<div class='right menu'> | |
<a id='id-logout' class='item'>LOGOUT</a> | |
</div> | |
</div> | |
<div id='log' class='ui middle attached segment'> | |
<table class='ui celled padded table'> | |
</table> | |
</div> | |
<div class='ui bottom attached segment'> | |
<div class='ui fluid action input'> | |
<input id='id-input' type='text' placeholder='・・・'> | |
<div id='id-enter' class='ui button'>ENTER</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
$(document).ready(function() { | |
$.ajax({ | |
'type': 'POST', | |
'url': location.href, | |
'dataType': 'json', | |
'data': 'init', | |
'timeout': 0 | |
}).done(function(data) { | |
$('#id-ch').text('通信チャンネル ' + data.channel); | |
$('#username').html('<i></i>' + data.name).children().addClass('user icon'); | |
log(data.timestamp, 'システムログ', 'チャンネル ' + data.channel + ' で開始しました。 チャンネルは ObjectDesc で変更できます。', 1); | |
getchat(); | |
}).fail(function(data) { | |
end = new Date(); | |
log(gettimestamp(), 'ERROR(0)', data.statusText, 2); | |
}); | |
}, false); | |
function getchat() { | |
$.ajax({ | |
'type': 'POST', | |
'url': location.href, | |
'dataType': 'json', | |
'data': 'getchat', | |
'timeout': 0 | |
}).done(function(data) { | |
log(data.timestamp, data.name, data.body); | |
scrollbottom(); | |
getchat(); | |
}).fail(function(data) { | |
if (data.status == 504) { | |
getchat(); | |
} else { | |
end = new Date(); | |
log(gettimestamp(), 'ERROR(1)', data.statusText, 2); | |
} | |
}); | |
} | |
$('.ui.button').on('click', function() { | |
var speech = $('#id-input').val(); | |
if (speech !== '') { | |
$('#id-input').val(''); | |
$.ajax({ | |
'type': 'POST', | |
'url': location.href, | |
'dataType': 'json', | |
'data': JSON.stringify({ | |
'speech': speech | |
}) | |
}).done(function(data) { | |
log(data.timestamp, data.name, data.body); | |
scrollbottom(); | |
}).fail(function(data) { | |
log(gettimestamp(), 'ERROR(2)', data.statusText, 2); | |
scrollbottom(); | |
}); | |
} | |
}); | |
$('#id-input').on('keydown', function(e) { | |
if (e.keyCode === 13) { | |
$('#id-enter').trigger('click'); | |
} | |
}); | |
$('#id-logout').on('click', function() { | |
$.ajax({ | |
'type': 'POST', | |
'url': location.href, | |
'data': 'logout' | |
}); | |
}); | |
function gettimestamp() { | |
var d = new Date(); | |
var hour = (d.getHours() < 10) ? '0' + d.getHours() : d.getHours(); | |
var min = (d.getMinutes() < 10) ? '0' + d.getMinutes() : d.getMinutes(); | |
var sec = (d.getSeconds() < 10) ? '0' + d.getSeconds() : d.getSeconds(); | |
return (hour + ':' + min + ':' + sec); | |
} | |
function log(a, b, c, d) { | |
$('table').append( | |
$('<tr></tr>') | |
.append($('<td></td>').text(a).addClass('left top aligned single line one wide')) | |
.append($('<td></td>').text(b).addClass('left top aligned single line one wide')) | |
.append($('<td></td>').text(c).addClass('left top aligned')) | |
); | |
if (d == 1) { | |
$('table tr:last').addClass('positive'); | |
} else if (d == 2) { | |
$('table tr:last').addClass('error'); | |
} | |
} | |
function scrollbottom() { | |
$('#log').scrollTop($('#log').scrollTop() + $('#log').height()); | |
} | |
</script> | |
</body> | |
</html>"; | |
integer i; | |
integer line; | |
key query_id; | |
vector scale; | |
integer status; | |
key request; | |
key client; | |
string URI; | |
integer handle; | |
integer ch = 100; | |
integer render_face = 4; //-X | |
float HUD_scale = 0.85; | |
check_memory() | |
{ | |
float freememory = llGetFreeMemory()/1024.0; | |
llOwnerSay("freememory = " + (string)freememory+" / 64 kbyte"); | |
} | |
string ConvertWallclockToTime() | |
{ | |
integer now = (integer)llGetWallclock(); | |
integer seconds = now % 60; | |
integer minutes = (now / 60) % 60; | |
integer hours = now / 3600; | |
return llGetSubString("0" + (string)hours, -2, -1) + ":" | |
+ llGetSubString("0" + (string)minutes, -2, -1) + ":" | |
+ llGetSubString("0" + (string)seconds, -2, -1); | |
} | |
default | |
{ | |
state_entry() | |
{ | |
llReleaseURL(URI); | |
request = llRequestURL(); | |
check_memory(); | |
} | |
changed(integer change) | |
{ | |
if(change & CHANGED_REGION || change & CHANGED_REGION_START){ | |
llReleaseURL(URI); | |
request = llRequestURL(); | |
} | |
else if(change & CHANGED_SCALE){ | |
scale = llGetScale(); | |
status = llSetLinkMedia(LINK_THIS, render_face, [ | |
PRIM_MEDIA_AUTO_SCALE, FALSE, | |
PRIM_MEDIA_WIDTH_PIXELS, 1024.0 * scale.y / HUD_scale, | |
PRIM_MEDIA_HEIGHT_PIXELS, 1024.0 * scale.z / HUD_scale, | |
PRIM_MEDIA_PERMS_INTERACT, PRIM_MEDIA_PERM_NONE, | |
PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE | |
]); | |
} | |
} | |
on_rez(integer start_param) | |
{ | |
llReleaseURL(URI); | |
request = llRequestURL(); | |
} | |
attach(key id) | |
{ | |
if(id){ | |
llReleaseURL(URI); | |
request = llRequestURL(); | |
} | |
} | |
http_request(key id, string method, string body) | |
{ | |
key owner = llGetOwner(); | |
vector ownerSize = llGetAgentSize(owner); | |
string useragent = llGetHTTPHeader(id, "user-agent"); | |
if (request == id){ | |
request = ""; | |
if (method == URL_REQUEST_GRANTED){ | |
URI = body; | |
scale = llGetScale(); | |
llClearPrimMedia(render_face); | |
status = llSetLinkMedia(LINK_THIS, render_face, [ | |
PRIM_MEDIA_HOME_URL, URI, | |
PRIM_MEDIA_CURRENT_URL, URI, | |
PRIM_MEDIA_AUTO_ZOOM, FALSE, | |
PRIM_MEDIA_AUTO_PLAY, TRUE, | |
PRIM_MEDIA_AUTO_SCALE, FALSE, | |
PRIM_MEDIA_WIDTH_PIXELS, 1024.0 * scale.y / HUD_scale, | |
PRIM_MEDIA_HEIGHT_PIXELS, 1024.0 * scale.z / HUD_scale, | |
PRIM_MEDIA_PERMS_INTERACT, PRIM_MEDIA_PERM_NONE, | |
PRIM_MEDIA_PERMS_CONTROL, PRIM_MEDIA_PERM_NONE | |
]); | |
} | |
else if (method == URL_REQUEST_DENIED){ | |
llOwnerSay("Something went wrong, no url:\n" + body); | |
} | |
} | |
else{ | |
if(method == "GET"){ | |
llSetContentType(id, CONTENT_TYPE_HTML); | |
llHTTPResponse(id, 200, html); | |
} | |
else if(method == "POST"){ | |
if(body == "init"){ | |
ch = (integer)llGetObjectDesc(); | |
if(ch == 0){ | |
ch = 100; | |
} | |
llListenRemove(handle); | |
llListen(ch, "", NULL_KEY, ""); | |
llSetContentType(id, CONTENT_TYPE_JSON); | |
llHTTPResponse(id, 200, llList2Json(JSON_OBJECT, [ | |
"name",llGetDisplayName(llGetOwner()), | |
"timestamp",ConvertWallclockToTime(), | |
"channel",ch | |
])); | |
} | |
else if(body == "getchat"){ | |
//グローバル変数にhttp requestのIDを保持する(*) | |
query_id = id; | |
} | |
else if(body == "logout"){ | |
if(llGetAttached()){ | |
llRequestPermissions(llGetOwner(), PERMISSION_ATTACH ); | |
} | |
} | |
else{ | |
string var = llJsonGetValue(body, ["speech"]); | |
if(var != JSON_INVALID){ | |
//通信チャンネル向けにRegionSay | |
llRegionSay(ch, var); | |
//CEFにResponse | |
llHTTPResponse(id, 200, llList2Json(JSON_OBJECT, [ | |
"name",llGetDisplayName(llGetOwner()), | |
"timestamp",ConvertWallclockToTime(), | |
"body",var | |
])); | |
} | |
} | |
} | |
} | |
} | |
listen(integer channel, string name, key id, string message) | |
{ | |
if(query_id != NULL_KEY){ | |
llSetContentType(query_id, CONTENT_TYPE_JSON); | |
if(ch == 0){ | |
name = llGetDisplayName(id); | |
} | |
else{ | |
name = llGetDisplayName(llGetOwnerKey(id)); | |
} | |
if(name != ""){ | |
//保持しておいたHTTP requestのID向けにResponseする(*) | |
llHTTPResponse(query_id, 200, llList2Json(JSON_OBJECT, [ | |
"name",name, | |
"timestamp",ConvertWallclockToTime(), | |
"body",message | |
])); | |
} | |
} | |
} | |
run_time_permissions(integer perm) | |
{ | |
if(perm & PERMISSION_ATTACH){ | |
llDetachFromAvatar( ); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment