sloodle_mod_chat-1.0.lslp.os 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. // Sloodle WebIntercom (for Sloodle 0.4)
  2. // Links in-world SL (text) chat with a Moodle chatroom
  3. // Part of the Sloodle project (www.sloodle.org)
  4. //
  5. // Copyright (c) 2006-8 Sloodle
  6. // Released under the GNU GPL
  7. //
  8. // Contributors:
  9. // Paul Andrews
  10. // Daniel Livingstone
  11. // Jeremy Kemp
  12. // Edmund Edgar
  13. // Peter R. Bloomfield
  14. //
  15. integer SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST=-1828374651; // this channel is used to send status codes for translation to the error_messages lsl script
  16. integer SLOODLE_CHANNEL_OBJECT_DIALOG = -3857343;
  17. integer SLOODLE_CHANNEL_AVATAR_DIALOG = 1001;
  18. string SLOODLE_CHAT_LINKER = "/mod/sloodle/mod/chat-1.0/linker.php";
  19. string SLOODLE_EOF = "sloodleeof";
  20. string SLOODLE_OBJECT_TYPE = "chat-1.0";
  21. integer SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC = 0;
  22. integer SLOODLE_OBJECT_ACCESS_LEVEL_OWNER = 1;
  23. integer SLOODLE_OBJECT_ACCESS_LEVEL_GROUP = 2;
  24. string sloodleserverroot = "";
  25. string sloodlepwd = "";
  26. integer sloodlecontrollerid = 0;
  27. integer sloodlemoduleid = 0;
  28. integer sloodlelistentoobjects = 0; // Should this object listen to other objects?
  29. integer sloodleobjectaccessleveluse = 0; // Who can use this object?
  30. integer sloodleobjectaccesslevelctrl = 0; // Who can control this object?
  31. integer sloodleserveraccesslevel = 0; // Who can use the server resource? (Value passed straight back to Moodle)
  32. integer sloodleautodeactivate = 1; // Should the WebIntercom auto-deactivate when not in use?
  33. string SoundFile = ""; // Sound file used for the beep
  34. string MOODLE_NAME = "(SL)";
  35. string MOODLE_NAME_OBJECT = "(SL-object)";
  36. integer isconfigured = FALSE; // Do we have all the configuration data we need?
  37. integer eof = FALSE; // Have we reached the end of the configuration data?
  38. integer listenctrl = 0; // Listening for initial control... i.e. activation/deactivation
  39. list cmddialog = []; // Alternating list of keys and timestamps, indicating who activated a command dialog (during logging) and when
  40. list recordingkeys = []; // Keys of people we're recording
  41. list recordingnames = []; // Names of people we're recording
  42. key httpchat = NULL_KEY; // Request used to send/receive chat
  43. integer message_id = 0; // ID of the last message received from Moodle
  44. float sensorrange = 30.0; // Senses somewhat beyond chat range
  45. float sensorrate = 60.0; // Scan every minute
  46. integer nosensorcount = 0; // How many recent sensor sweeps (while logging) have detected no avatars?
  47. integer nosensormax = 2; // How many failed sensor sweeps should we allow before auto-deactivating?
  48. ///// TRANSLATION /////
  49. // Link message channels
  50. integer SLOODLE_CHANNEL_TRANSLATION_REQUEST = -1928374651;
  51. integer SLOODLE_CHANNEL_TRANSLATION_RESPONSE = -1928374652;
  52. // Translation output methods
  53. string SLOODLE_TRANSLATE_LINK = "link"; // No output parameters - simply returns the translation on SLOODLE_TRANSLATION_RESPONSE link message channel
  54. string SLOODLE_TRANSLATE_SAY = "say"; // 1 output parameter: chat channel number
  55. string SLOODLE_TRANSLATE_WHISPER = "whisper"; // 1 output parameter: chat channel number
  56. string SLOODLE_TRANSLATE_SHOUT = "shout"; // 1 output parameter: chat channel number
  57. string SLOODLE_TRANSLATE_REGION_SAY = "regionsay"; // 1 output parameter: chat channel number
  58. string SLOODLE_TRANSLATE_OWNER_SAY = "ownersay"; // No output parameters
  59. string SLOODLE_TRANSLATE_DIALOG = "dialog"; // Recipient avatar should be identified in link message keyval. At least 2 output parameters: first the channel number for the dialog, and then 1 to 12 button label strings.
  60. string SLOODLE_TRANSLATE_LOAD_URL = "loadurl"; // Recipient avatar should be identified in link message keyval. 1 output parameter giving URL to load.
  61. string SLOODLE_TRANSLATE_HOVER_TEXT = "hovertext"; // 2 output parameters: colour <r,g,b>, and alpha value
  62. string SLOODLE_TRANSLATE_IM = "instantmessage"; // Recipient avatar should be identified in link message keyval. No output parameters.
  63. // Send a translation request link message
  64. sloodle_translation_request(string output_method, list output_params, string string_name, list string_params, key keyval, string batch)
  65. {
  66. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_TRANSLATION_REQUEST, output_method + "|" + llList2CSV(output_params) + "|" + string_name + "|" + llList2CSV(string_params) + "|" + batch, keyval);
  67. }
  68. ///// ----------- /////
  69. ///// FUNCTIONS /////
  70. /******************************************************************************************************************************
  71. * sloodle_error_code -
  72. * Author: Paul Preibisch
  73. * Description - This function sends a linked message on the SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST channel
  74. * The error_messages script hears this, translates the status code and sends an instant message to the avuuid
  75. * Params: method - SLOODLE_TRANSLATE_SAY, SLOODLE_TRANSLATE_IM etc
  76. * Params: avuuid - this is the avatar UUID to that an instant message with the translated error code will be sent to
  77. * Params: status code - the status code of the error as on our wiki: http://slisweb.sjsu.edu/sl/index.php/Sloodle_status_codes
  78. *******************************************************************************************************************************/
  79. sloodle_error_code(string method, key avuuid,integer statuscode){
  80. llMessageLinked(LINK_SET, SLOODLE_CHANNEL_ERROR_TRANSLATION_REQUEST, method+"|"+(string)avuuid+"|"+(string)statuscode, NULL_KEY);
  81. }
  82. sloodle_debug(string msg)
  83. {
  84. llMessageLinked(LINK_THIS, DEBUG_CHANNEL, msg, NULL_KEY);
  85. }
  86. // Configure by receiving a linked message from another script in the object
  87. // Returns TRUE if the object has all the data it needs
  88. integer sloodle_handle_command(string str)
  89. {
  90. list bits = llParseString2List(str,["|"],[]);
  91. integer numbits = llGetListLength(bits);
  92. string name = llList2String(bits,0);
  93. string value1 = "";
  94. string value2 = "";
  95. if (numbits > 1) value1 = llList2String(bits,1);
  96. if (numbits > 2) value2 = llList2String(bits,2);
  97. if (name == "set:sloodleserverroot") sloodleserverroot = value1;
  98. else if (name == "set:sloodlepwd") {
  99. // The password may be a single prim password, or a UUID and a password
  100. if (value2 != "") sloodlepwd = value1 + "|" + value2;
  101. else sloodlepwd = value1;
  102. } else if (name == "set:sloodlecontrollerid") sloodlecontrollerid = (integer)value1;
  103. else if (name == "set:sloodlemoduleid") sloodlemoduleid = (integer)value1;
  104. else if (name == "set:sloodlelistentoobjects") sloodlelistentoobjects = (integer)value1;
  105. else if (name == "set:sloodleobjectaccessleveluse") sloodleobjectaccessleveluse = (integer)value1;
  106. else if (name == "set:sloodleobjectaccesslevelctrl") sloodleobjectaccesslevelctrl = (integer)value1;
  107. else if (name == "set:sloodleserveraccesslevel") sloodleserveraccesslevel = (integer)value1;
  108. else if (name == "set:sloodleautodeactivate") sloodleautodeactivate = (integer)value1;
  109. else if (name == SLOODLE_EOF) eof = TRUE;
  110. return (sloodleserverroot != "" && sloodlepwd != "" && sloodlecontrollerid > 0 && sloodlemoduleid > 0);
  111. }
  112. // Checks if the given agent is permitted to control this object
  113. // Returns TRUE if so, or FALSE if not
  114. integer sloodle_check_access_ctrl(key id)
  115. {
  116. // Check the access mode
  117. if (sloodleobjectaccesslevelctrl == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
  118. return llSameGroup(id);
  119. } else if (sloodleobjectaccesslevelctrl == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
  120. return TRUE;
  121. }
  122. // Assume it's owner mode
  123. return (id == llGetOwner());
  124. }
  125. // Checks if the given agent is permitted to user this object
  126. // Returns TRUE if so, or FALSE if not
  127. integer sloodle_check_access_use(key id)
  128. {
  129. // Check the access mode
  130. if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_GROUP) {
  131. return llSameGroup(id);
  132. } else if (sloodleobjectaccessleveluse == SLOODLE_OBJECT_ACCESS_LEVEL_PUBLIC) {
  133. return TRUE;
  134. }
  135. // Assume it's owner mode
  136. return (id == llGetOwner());
  137. }
  138. // Add the given agent to our command dialog list
  139. sloodle_add_cmd_dialog(key id)
  140. {
  141. // Does the person already exist?
  142. integer pos = llListFindList(cmddialog, [id]);
  143. if (pos < 0) {
  144. // No - add the agent to the end
  145. cmddialog += [id, llGetUnixTime()];
  146. } else {
  147. // Yes - update the time
  148. cmddialog = llListReplaceList(cmddialog, [llGetUnixTime()], pos + 1, pos + 1);
  149. }
  150. }
  151. // Remove the given agent from our command dialog list
  152. sloodle_remove_cmd_dialog(key id)
  153. {
  154. // Is the person in the list?
  155. integer pos = llListFindList(cmddialog, [id]);
  156. if (pos >= 0) {
  157. // Yes - remove them and their timestamp
  158. cmddialog = llDeleteSubList(cmddialog, pos, pos + 1);
  159. }
  160. }
  161. // Purge the command dialog list of old activity
  162. sloodle_purge_cmd_dialog()
  163. {
  164. // Store the current timestamp
  165. integer curtime = llGetUnixTime();
  166. // Go through each command dialog
  167. integer i = 0;
  168. while (i < llGetListLength(cmddialog)) {
  169. // Is the current timestamp more than 12 seconds old?
  170. if ((curtime - llList2Integer(cmddialog, i + 1)) > 12) {
  171. // Yes - remove it
  172. cmddialog = llDeleteSubList(cmddialog, i, i + 1);
  173. } else {
  174. // No - advance to the next
  175. i += 2;
  176. }
  177. }
  178. }
  179. // Start recording the specified agent
  180. sloodle_start_recording_agent(key id)
  181. {
  182. // Do nothing if the person is already on the list
  183. if (llListFindList(recordingkeys, [id]) >= 0) {
  184. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:alreadyrecording", [llKey2Name(id)], NULL_KEY, "webintercom");
  185. return;
  186. }
  187. // Add the key and name to the lists
  188. recordingkeys += [id];
  189. recordingnames += [llKey2Name(id)];
  190. // Announce the update
  191. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:startedrecording", [llKey2Name(id)], NULL_KEY, "webintercom");
  192. sloodle_update_hover_text();
  193. // Inform the Moodle chatroom
  194. string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
  195. body += "&sloodlepwd=" + sloodlepwd;
  196. body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
  197. body += "&sloodleuuid=" + (string)llGetKey();
  198. body += "&sloodleavname=" + llEscapeURL(llGetObjectName());
  199. body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
  200. body += "&sloodleisobject=true&message=" + MOODLE_NAME_OBJECT + " " + llKey2Name(id) + " has entered this chat";
  201. httpchat = llHTTPRequest(sloodleserverroot + SLOODLE_CHAT_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
  202. }
  203. // Stop recording the specified agent
  204. sloodle_stop_recording_agent(key id)
  205. {
  206. // Do nothing if the person is not already on the list
  207. integer pos = llListFindList(recordingkeys, [id]);
  208. if (pos < 0) {
  209. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:notrecording", [llKey2Name(id)], NULL_KEY, "webintercom");
  210. return;
  211. }
  212. // Remove the key and name from the list
  213. recordingkeys = llDeleteSubList(recordingkeys, pos, pos);
  214. recordingnames = llDeleteSubList(recordingnames, pos, pos);
  215. // Announce the update
  216. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:stoppedrecording", [llKey2Name(id)], NULL_KEY, "webintercom");
  217. sloodle_update_hover_text();
  218. // Inform the Moodle chatroom
  219. string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
  220. body += "&sloodlepwd=" + sloodlepwd;
  221. body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
  222. body += "&sloodleuuid=" + (string)llGetKey();
  223. body += "&sloodleavname=" + llEscapeURL(llGetObjectName());
  224. body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
  225. body += "&sloodleisobject=true&message=" + MOODLE_NAME_OBJECT + " " + llKey2Name(id) + " has left this chat";
  226. httpchat = llHTTPRequest(sloodleserverroot + SLOODLE_CHAT_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
  227. }
  228. // Is the specified agent currently being recorded?
  229. // Returns TRUE if so, or FALSE otherwise
  230. integer sloodle_is_recording_agent(key id)
  231. {
  232. return (llListFindList(recordingkeys, [id]) >= 0);
  233. }
  234. // Update the hover text while logging
  235. sloodle_update_hover_text()
  236. {
  237. string recordlist = llDumpList2String(recordingnames, "\n");
  238. if (recordlist == "") recordlist = "-";
  239. sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<1.0, 0.2, 0.2>, 1.0], "webintercom:recording", [recordlist], NULL_KEY, "webintercom");
  240. }
  241. // Default state - waiting for configuration
  242. default
  243. {
  244. state_entry()
  245. {
  246. // Set the texture on the sides to indicate we're deactivated
  247. llSetTexture("sloodle_chat_off",ALL_SIDES);
  248. // Starting again with a new configuration
  249. llSetText("", <0.0,0.0,0.0>, 0.0);
  250. isconfigured = FALSE;
  251. eof = FALSE;
  252. // Reset our data
  253. sloodleserverroot = "";
  254. sloodlepwd = "";
  255. sloodlecontrollerid = 0;
  256. sloodlemoduleid = 0;
  257. sloodlelistentoobjects = 0;
  258. sloodleobjectaccessleveluse = 0;
  259. sloodleobjectaccesslevelctrl = 0;
  260. sloodleserveraccesslevel = 0;
  261. }
  262. link_message( integer sender_num, integer num, string str, key id)
  263. {
  264. // Check the channel
  265. if (num == SLOODLE_CHANNEL_OBJECT_DIALOG) {
  266. // Split the message into lines
  267. list lines = llParseString2List(str, ["\n"], []);
  268. integer numlines = llGetListLength(lines);
  269. integer i = 0;
  270. for (; i < numlines; i++) {
  271. isconfigured = sloodle_handle_command(llList2String(lines, i));
  272. }
  273. // If we've got all our data AND reached the end of the configuration data, then move on
  274. if (eof == TRUE) {
  275. if (isconfigured == TRUE) {
  276. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configurationreceived", [], NULL_KEY, "");
  277. state ready;
  278. } else {
  279. // Go all configuration but, it's not complete... request reconfiguration
  280. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "configdatamissing", [], NULL_KEY, "");
  281. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:reconfigure", NULL_KEY);
  282. eof = FALSE;
  283. }
  284. }
  285. }
  286. }
  287. touch_start(integer num_detected)
  288. {
  289. // Attempt to request a reconfiguration
  290. if (llDetectedKey(0) == llGetOwner()) {
  291. llMessageLinked(LINK_THIS, SLOODLE_CHANNEL_OBJECT_DIALOG, "do:requestconfig", NULL_KEY);
  292. }
  293. }
  294. }
  295. state ready
  296. {
  297. on_rez( integer param)
  298. {
  299. state default;
  300. }
  301. state_entry()
  302. {
  303. llSetTimerEvent(0);
  304. // Set the texture on the sides to indicate we're deactivated
  305. llSetTexture("sloodle_chat_off",ALL_SIDES);
  306. // Reset the list of recorded keys and names
  307. recordingkeys = [];
  308. recordingnames = [];
  309. cmddialog = [];
  310. sloodle_translation_request(SLOODLE_TRANSLATE_HOVER_TEXT, [<1.0, 1.0, 1.0>, 1.0], "off", [], NULL_KEY, "");
  311. // Determine our "beep" sound file name
  312. SoundFile = llGetInventoryName(INVENTORY_SOUND, 0);
  313. }
  314. state_exit()
  315. {
  316. llSetTimerEvent(0.0);
  317. }
  318. touch_start( integer total_number)
  319. {
  320. // Activating this requires access permission
  321. if (sloodle_check_access_ctrl(llDetectedKey(0)) == FALSE) {
  322. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "nopermission:ctrl", [llDetectedName(0)], NULL_KEY, "");
  323. return;
  324. }
  325. llListenRemove(listenctrl);
  326. listenctrl = llListen(SLOODLE_CHANNEL_AVATAR_DIALOG, "", llDetectedKey(0), "");
  327. sloodle_translation_request(SLOODLE_TRANSLATE_DIALOG, [SLOODLE_CHANNEL_AVATAR_DIALOG, "0", "1"], "webintercom:ctrlmenu", ["0", "1"], llDetectedKey(0), "webintercom");
  328. llSetTimerEvent(10.0);
  329. }
  330. listen( integer channel, string name, key id, string message)
  331. {
  332. // Check the channel
  333. if (channel == SLOODLE_CHANNEL_AVATAR_DIALOG) {
  334. // Check access to this object
  335. if (sloodle_check_access_ctrl(id) == FALSE) return;
  336. // Has chat logging been activated?
  337. if (message == "1") {
  338. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:chatloggingon", [llDetectedName(0)], NULL_KEY, "webintercom");
  339. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:joinchat", [sloodleserverroot + "/mod/chat/view.php?id="+(string)sloodlemoduleid], NULL_KEY, "webintercom");
  340. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:touchtorecord", [], NULL_KEY, "webintercom");
  341. // Initially record the one who activated us
  342. recordingkeys = [id];
  343. recordingnames = [name];
  344. state logging;
  345. return;
  346. }
  347. }
  348. }
  349. timer()
  350. {
  351. // Cancel the control listen
  352. llSetTimerEvent(0.0);
  353. llListenRemove(listenctrl);
  354. }
  355. }
  356. state logging
  357. {
  358. on_rez( integer param)
  359. {
  360. state default;
  361. }
  362. state_entry()
  363. {
  364. // Udpate the texture on the side to indicate we're logging
  365. llSetTexture("sloodle_chat_on",ALL_SIDES);
  366. // Listen for chat and commands
  367. llListen(0,"",NULL_KEY,"");
  368. llListen(SLOODLE_CHANNEL_AVATAR_DIALOG, "", NULL_KEY, "");
  369. // Update our caption indicating whom we're recording
  370. sloodle_update_hover_text();
  371. // Regularly update the chat history and purge our list of command dialogs
  372. llSetTimerEvent(12.0);
  373. // Perform a regular scan to see if the WebIntercom has been abandoned
  374. if (sloodleautodeactivate != 0) {
  375. llSensorRepeat("", NULL_KEY, AGENT, sensorrange, PI, sensorrate);
  376. }
  377. nosensorcount = 0;
  378. // Inform the Moodle chatroom
  379. string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
  380. body += "&sloodlepwd=" + sloodlepwd;
  381. body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
  382. body += "&sloodleuuid=" + (string)llGetKey();
  383. body += "&sloodleavname=" + llEscapeURL(llGetObjectName());
  384. body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
  385. body += "&sloodleisobject=true&message=" + MOODLE_NAME_OBJECT + " " + llList2String(recordingnames, 0) + " has activated this WebIntercom";
  386. httpchat = llHTTPRequest(sloodleserverroot + SLOODLE_CHAT_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
  387. }
  388. state_exit()
  389. {
  390. // Inform the Moodle chatroom
  391. string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
  392. body += "&sloodlepwd=" + sloodlepwd;
  393. body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
  394. body += "&sloodleuuid=" + (string)llGetKey();
  395. body += "&sloodleavname=" + llEscapeURL(llGetObjectName());
  396. body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
  397. body += "&sloodleisobject=true&message=" + MOODLE_NAME_OBJECT + " WebIntercom deactivated";
  398. httpchat = llHTTPRequest(sloodleserverroot + SLOODLE_CHAT_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
  399. }
  400. touch_start( integer total_number)
  401. {
  402. key id = llDetectedKey(0);
  403. // Determine what this user can do
  404. integer canctrl = sloodle_check_access_ctrl(id);
  405. integer canuse = sloodle_check_access_use(id);
  406. // Can the agent control AND use this item?
  407. if (canctrl) {
  408. sloodle_translation_request(SLOODLE_TRANSLATE_DIALOG, [SLOODLE_CHANNEL_AVATAR_DIALOG, "0", "1", "2","cmd"], "webintercom:usectrlmenu", ["0", "1", "2","cmd"], id, "webintercom");
  409. sloodle_add_cmd_dialog(id);
  410. } else if (canuse) {
  411. sloodle_translation_request(SLOODLE_TRANSLATE_DIALOG, [SLOODLE_CHANNEL_AVATAR_DIALOG, "0", "1","2"], "webintercom:usemenu", ["0", "1","2"], id, "webintercom");
  412. sloodle_add_cmd_dialog(id);
  413. } else {
  414. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "nopermission:use", [llKey2Name(id)], NULL_KEY, "webintercom");
  415. }
  416. }
  417. listen( integer channel, string name, key id, string message)
  418. {
  419. // Check the channel
  420. if (channel == SLOODLE_CHANNEL_AVATAR_DIALOG) {
  421. // Ignore this person if they are not on the list
  422. if (llListFindList(cmddialog, [id]) < 0) return;
  423. sloodle_remove_cmd_dialog(id);
  424. // Find out what the user can do
  425. integer canctrl = sloodle_check_access_ctrl(id);
  426. integer canuse = sloodle_check_access_use(id);
  427. // Check what the command is
  428. if (message == "0") {
  429. // Make sure the user can use this
  430. if (!(canctrl || canuse)) return;
  431. // Stop recording the user
  432. sloodle_stop_recording_agent(id);
  433. } else if (message == "1") {
  434. // Make sure the user can use this
  435. if (!(canctrl || canuse)) return;
  436. // Start recording the user
  437. sloodle_start_recording_agent(id);
  438. } else if (message == "cmd") {
  439. // Make sure the user can control this
  440. if (!canctrl) return;
  441. // Modified by Fumi.Iseki
  442. string chatroomurl = sloodleserverroot + "/mod/chat/view.php?id="+(string)sloodlemoduleid;
  443. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:anouncechatroom", [chatroomurl], NULL_KEY, "webintercom");
  444. llLoadURL(id, "Goto Moodle Chat Room", chatroomurl);
  445. //sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:anouncechatroom", [sloodleserverroot + "/mod/chat/view.php?id="+(string)sloodlemoduleid], NULL_KEY, "webintercom");
  446. } else if (message == "2") {
  447. // Make sure the user can use this
  448. if (!(canctrl || canuse)) return;
  449. // Display chatroom
  450. // Modified by Fumi.Iseki
  451. string chatroomurl = sloodleserverroot + "/mod/chat/view.php?id="+(string)sloodlemoduleid;
  452. sloodle_translation_request(SLOODLE_TRANSLATE_IM, [id], "webintercom:enterchatroom", [chatroomurl], id, "webintercom");
  453. llLoadURL(id, "Goto Moodle Chat Room", chatroomurl);
  454. //sloodle_translation_request(SLOODLE_TRANSLATE_IM, [id], "webintercom:enterchatroom", [sloodleserverroot + "/mod/chat/view.php?id="+(string)sloodlemoduleid], id, "webintercom");
  455. }
  456. } else if (channel == 0) {
  457. // Is this an avatar?
  458. integer isavatar = FALSE;
  459. if (llGetOwnerKey(id) == id) {
  460. // Yes - check that we are listening to them
  461. if (!sloodle_is_recording_agent(id)) return;
  462. isavatar = TRUE;
  463. } else {
  464. // No - it is an object - ignore it if necessary
  465. if (sloodlelistentoobjects == 0) return;
  466. }
  467. // Is this a SLurl command?
  468. if(message == "/slurl") {
  469. string region = llEscapeURL(llGetRegionName());
  470. vector vec = llGetPos();
  471. string posX = (string)((integer)vec.x);
  472. string posY = (string)((integer)vec.y);
  473. string posZ = (string)((integer)vec.z);
  474. // Replace the message with a SLurl
  475. message = "http://slurl.com/secondlife/" + region + "/" + posX + "/" + posY + "/" + posZ + "/?title=" + region;
  476. }
  477. // Send the request as POST data
  478. string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
  479. body += "&sloodlepwd=" + sloodlepwd;
  480. body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
  481. body += "&sloodleuuid=" + (string)id;
  482. body += "&sloodleavname=" + llEscapeURL(name);
  483. body += "&sloodleserveraccesslevel=" + (string)sloodleserveraccesslevel;
  484. if (isavatar) body += "&message=" + MOODLE_NAME + " ";
  485. else body += "&sloodleisobject=true&message=" + MOODLE_NAME_OBJECT + " ";
  486. body += name + ": " + message;
  487. httpchat = llHTTPRequest(sloodleserverroot + SLOODLE_CHAT_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
  488. }
  489. }
  490. timer()
  491. {
  492. // Get updated chat from Moodle
  493. if (httpchat == NULL_KEY) {
  494. string body = "sloodlecontrollerid=" + (string)sloodlecontrollerid;
  495. body += "&sloodlepwd=" + sloodlepwd;
  496. body += "&sloodlemoduleid=" + (string)sloodlemoduleid;
  497. httpchat = llHTTPRequest(sloodleserverroot + SLOODLE_CHAT_LINKER, [HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/x-www-form-urlencoded"], body);
  498. }
  499. // Purge any expired command dialogs
  500. sloodle_purge_cmd_dialog();
  501. }
  502. http_response(key id, integer status, list meta, string body)
  503. {
  504. // Is this the expected data?
  505. if (id != httpchat) return;
  506. httpchat = NULL_KEY;
  507. // Make sure the request worked
  508. if (status != 200) {
  509. sloodle_debug("Failed HTTP response. Status: " + (string)status);
  510. sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,status); //send message to error_message.lsl
  511. return;
  512. }
  513. // Make sure there is a body to the request
  514. if (llStringLength(body) == 0) return;
  515. // Debug output:
  516. sloodle_debug("Receiving chat data:\n" + body);
  517. // Split the data up into lines
  518. list lines = llParseStringKeepNulls(body, ["\n"], []);
  519. integer numlines = llGetListLength(lines);
  520. // Extract all the status fields
  521. list statusfields = llParseStringKeepNulls( llList2String(lines,0), ["|"], [] );
  522. // Get the statuscode
  523. integer statuscode = llList2Integer(statusfields,0);
  524. // Was it an error code?
  525. if (statuscode <= 0) {
  526. sloodle_error_code(SLOODLE_TRANSLATE_SAY, NULL_KEY,statuscode); //send message to error_message.lsl
  527. // Do we have an error message to go with it?
  528. string msg = "ERROR: linker script responded with status code " + (string)statuscode;
  529. if (numlines > 1) {
  530. msg += "\n" + llList2String(lines,1);
  531. }
  532. sloodle_debug(msg);
  533. return;
  534. }
  535. // We will use these to store each item of data
  536. integer msgnum = 0;
  537. string name = "";
  538. string text = "";
  539. // Every other line should define a chat message "id|name|text"
  540. // Start at the line after the status line
  541. integer i = 1;
  542. for (i = (numlines - 1); i > 0; i--) {
  543. // Get all the different fields for this line
  544. list fields = llParseStringKeepNulls(llList2String(lines,i),["|"],[]);
  545. // Make sure we have enough fields
  546. if (llGetListLength(fields) >= 3) {
  547. // Extract each item of data
  548. msgnum = llList2Integer(fields,0);
  549. name = llList2String(fields,1);
  550. text = llList2String(fields,2);
  551. // Make sure this is a new message
  552. if (msgnum > message_id) {
  553. message_id = msgnum;
  554. // Make sure this wasn't an SL message originally
  555. if (llSubStringIndex(text, MOODLE_NAME) != 0 && llSubStringIndex(text, MOODLE_NAME_OBJECT) != 0) {
  556. // Is this a Moodle beep?
  557. if (llSubStringIndex(text, "beep ") == 0) {
  558. // Yes - play a beep sound
  559. llStopSound();
  560. if (SoundFile == "")
  561. { // There is no sound file in inventory - plsy default
  562. llPlaySound("34b0b9d8-306a-4930-b4cd-0299959bb9f4", 1.0);
  563. } else { // Play the included one
  564. llPlaySound(SoundFile, 1.0);
  565. }
  566. }
  567. // Finally... just an ordinary chat message... output it
  568. llSay(0, name + ": " + text);
  569. }
  570. }
  571. }
  572. }
  573. }
  574. sensor(integer num_detected)
  575. {
  576. // Nearby avatars have been detected
  577. nosensorcount = 0;
  578. }
  579. no_sensor()
  580. {
  581. // Ignore this if auto-deactivation has been disabled
  582. if (sloodleautodeactivate == 0) return;
  583. // No nearby avatars detected.
  584. // Is the object attached to an avatar? (Sensors won't detect the avatar the object is attached to)
  585. if (llGetAttached() > 0) {
  586. // Yes - treat it as though avatars have been detected
  587. nosensorcount = 0;
  588. } else {
  589. // No - increment our count of failed scans
  590. nosensorcount++;
  591. // Is it time to deactivate?
  592. if (nosensorcount >= nosensormax) {
  593. sloodle_translation_request(SLOODLE_TRANSLATE_SAY, [0], "webintercom:autodeactivate", [], NULL_KEY, "webintercom");
  594. state ready;
  595. return;
  596. }
  597. }
  598. }
  599. }
  600. // Please leave the following line intact to show where the script lives in Git:
  601. // SLOODLE LSL Script Git Location: mod/chat-1.0/sloodle_mod_chat-1.0.lsl.os