sloodle_mod_chat-1.0.lslp 29 KB

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