HajraLegacy Posted October 1, 2020 Share Posted October 1, 2020 23 minutes ago, HajraLegacy said: @Xiija well I actually used what you said in earlier posts to get to where I am with this script, so much appreciated for that. I'll have a look at this video but I'm not certain it'll help me out if I am not that knowledgeable about code in general lol. I guess I'm not certain how I can get multiple results with multiple llHTTPRequest 's and .. http_response if's. I used your method with the markers to get a good, solid key that I want but with the separate request, it keeps spitting out the same key even though I've assigned a different url, etc to that response. Any ideas what I can do with that? I've worked so many hours on this script (I was originally trying to use notecards but that wasn't working with me either.) @Xiija Link to comment Share on other sites More sharing options...
Xiija Posted October 1, 2020 Share Posted October 1, 2020 @HajraLegacy not sure unless you post some code, but if you are using markers, mebbe change the marker to be different for each set of data? Link to comment Share on other sites More sharing options...
Xiija Posted October 1, 2020 Share Posted October 1, 2020 Some thoughts on the new Google Apps script stuff: to use the newer google apps script, after you have followed the video, you would make 2 new scripts, one for getting a stored url, one for actually storing data. ◥◣◥◣◥◣◥◣◥ RAMBLING AREA ◣◥◣◥◣◥◣◥◣◥ storing data: I use a query string param in the Second Life prim's get request like so... string URL = "https://script.google.com/macros/s/AKfycbzigU- some long string of numbers etc etc- zjrmZg/exec?txt="; and after my prim has gotten a secure url using ... llRequestSecureURL()... i store that in a variable with... myURL = body; and the secondlife get req looks like, http_request_id = llHTTPRequest(URL + myURL, [HTTP_METHOD, "GET", HTTP_MIMETYPE, "text/plain", HTTP_BODY_MAXLENGTH,16384, HTTP_PRAGMA_NO_CACHE,TRUE], ""); here is a link to the google apps script that handles this http GET request: set Value on google sheet - https://script.google.com/d/1KMDXmVAlu9qLKO8UGdKLgVSEhMeaYT1yv24yOaxtWVddKSG8XaQ-19mz/edit?usp=sharing i have not tried it, but you could prolly make the cell that you want to store data in... into a variable. on the apps script, the relevant line is .... ws.getRange("A2").setValue(link); you could prolly add a second query string paramto your SL code with a cell, like... var query2 = "&cell="; var cellNum = "A3"; and then just use a different cell to store another line of data. Your http req would then look something like... http_request_id = llHTTPRequest(URL + myURL + query2 + cellNum , and on your apps script, add a new variable and use it... var cell_number = e.parameter.cell; ws.getRange(cell_number).setValue(link); // ============================ to get the values back into SL, you just make a GET request to your script that fetches the values... ( again, you could add a query string param to get different cells. ) get Value from google sheet - https://script.google.com/d/1aOsccUMaTZF1vhkvrkKhz64m5m2zVFbL1wq3TADB7bnSBNhNkxHR502Z/edit?usp=sharing ◥◣◥◣◥◣◥◣◥ END RAMBLING AREA ◣◥◣◥◣◥◣◥◣◥ just tryin to share the info for folks who wanna experiment Link to comment Share on other sites More sharing options...
HajraLegacy Posted October 2, 2020 Share Posted October 2, 2020 @XiijaI'm definitely going to look into this more and hopefully share some results Link to comment Share on other sites More sharing options...
Gayngel Posted October 7, 2020 Share Posted October 7, 2020 (edited) I've been using Google App Script to store date in a sheet for scripts for about 3-4 years now. I sell a greeter that can store about 200k visitor UUIDs and data like responses to ""Can we use display your profile pic here?", who took a landmdark, how long the avatar stayed on the parcel, unique visitor counts, etc. Google Sheets and App Script are really a robust way to store persistent data. Edited October 7, 2020 by Gayngel Link to comment Share on other sites More sharing options...
Chrystian Merlin Posted October 13, 2020 Share Posted October 13, 2020 IF you only need to save a few, small bits of information AND your HUD has more than 1 prim information stored in the description of child prims SEEMS to survive detach/attach even when sending the HUD to another resident. Sometimes the simplest solutions are best. 🙂 1 Link to comment Share on other sites More sharing options...
Xiija Posted October 13, 2020 Share Posted October 13, 2020 there is also another google option, with firebase ... it has 2 db's to choose from, and seems to work well .. here is a vid if you are interested.. < click for Firebase Vid > Link to comment Share on other sites More sharing options...
Xiija Posted October 19, 2020 Share Posted October 19, 2020 another note: Repl.it is a free service, and has a db you can use, here is a link to a basic db example, which you could change to use http etc ... https://repl.it/@Xiija/Repl-DB-01-1#index.js 2 Link to comment Share on other sites More sharing options...
Fritigern Gothly Posted November 15, 2020 Share Posted November 15, 2020 @Xiija, I am pretty good with LSL but Java/Javascript is way outside my capabilities. In other words, I would love to use any of your non-LSL examples, but I can only work with LSL. Other languages cause my brain to lock up, check out and throw in the towel. I blame my age. If possible, could you provide some LSL snippets which show how to use Firebase and/or Repl.it as remote db? Link to comment Share on other sites More sharing options...
animats Posted November 16, 2020 Share Posted November 16, 2020 Anyone tried using DynamoDB on AWS? It's a key/value store. The free tier offers 25 GB of data storage 2.5 million stream read requests per month from DynamoDB Streams 1 GB of data transfer out per month, aggregated across AWS services but writes are US$1.25 per million writes. Amazon does all the backups, it's a redundant system, etc. If SL is up, it's unlikely to be down. It uses HTTP requests in JSON and responds in JSON, so you should be able to access it directly from LSL. It's similar to the experience key/value system. It would be useful if LL offered this as an add-on for SL accounts, so you didn't have to set up an account with AWS directly and it was authenticated through your SL account. 1 Link to comment Share on other sites More sharing options...
Xiija Posted November 16, 2020 Share Posted November 16, 2020 (edited) @Fritigern Gothly if you are on repl.it & firebase... you can get your credentials json file from the firebase site Credentials for the repl ... and then make a node repl with something like this in it... ( in this example, i've stored the credentials in a file called ... serviceAccountKey.json const admin = require("firebase-admin"); const serviceAccount = require("./serviceAccountKey.json"); admin.initializeApp({ // credential: admin.credential.applicationDefault() credential: admin.credential.cert(serviceAccount) }) const db = admin.firestore(); const quoteData = { author: 'Bud Smalls', quote: 'Bong me again ??!' }; db.collection('sampleData').doc('Inspiration') .set(quoteData) .then(func =>{ read(); }) .catch(err =>{ console.log("err\n" + err); }); async function read(){ let snapshot = await db.collection('sampleData').get() .then(documents => { documents.forEach((doc) => { item = doc.data(); console.log( "Title: " + doc.id + "\nAuthor: " + item.author + "\nQuote: " + item.quote ); }); }) .catch(err =>{ console.log("err\n" + err); }); }; After that its a basic http call, mebbe to an express route?... to access the database. Edited November 16, 2020 by Xiija 1 Link to comment Share on other sites More sharing options...
Xiija Posted November 16, 2020 Share Posted November 16, 2020 (edited) yet another example using ... node-json-db .... https://repl.it/@Xiija/jsonDB-test-01 you could change the routes to use post, instead of get, and post a json object as the data Edited November 16, 2020 by Xiija 1 Link to comment Share on other sites More sharing options...
Xiija Posted November 18, 2020 Share Posted November 18, 2020 (edited) small update with code for the free database idea is here ... Edited November 18, 2020 by Xiija Link to comment Share on other sites More sharing options...
Xiija Posted November 21, 2020 Share Posted November 21, 2020 @Gayngel do you use POST to store the data with the apps scripts? i've only been able to get GET requests to work Link to comment Share on other sites More sharing options...
Gayngel Posted February 27, 2021 Share Posted February 27, 2021 (edited) On 11/21/2020 at 4:02 AM, Xiija said: @Gayngel do you use POST to store the data with the apps scripts? i've only been able to get GET requests to work @Xiija You can use URL parameters to send variables. Instead of using the body of the POST, just append the variables to the URL. i.e: After the App Script URL add a "?" then a key/id pair separated by "&" e.g: llHTTPRequest("https://script.google.com/macros/s/AKlycby72IWfkiup3YZdHtGk2bHSX147nhalhawYCKufV5vgvAFXsrNQ/exec?uuid=a9ba2797-81af-429d-9833-51127ad5593c&name=Gayngel×tamp=2021/02/27-10:32",[HTTP_METHOD,POST],"") In the App Script you then retrieve the data from the e argument in doPost(e). The e argument represents the group of requests parameters you specify. To get each data separately you append the specified key to the e parameter field. doPost(e) { var uuid = e.parameter.uuid; // Will be a9ba2797-81af-429d-9833-51127ad5593c var name = e.parameter.name; // Will be Gayngel var timestamp = e.paramter.timestamp; // Wil be 2021/02/27-10:32 } Edited February 27, 2021 by Gayngel Link to comment Share on other sites More sharing options...
Gayngel Posted February 27, 2021 Share Posted February 27, 2021 (edited) I've been trying to work with Google App Script in Open Sim using the same scripts I have in SL but get no input/response from the App script. It seems like OpenSim URLs are not recognized by Google. If anyone can get scripts in Open Sim to work with Google App Script please let me know how you did it. Edited February 27, 2021 by Gayngel Link to comment Share on other sites More sharing options...
bobsknief Orsini Posted February 28, 2021 Share Posted February 28, 2021 You could just store the data in a second script using a linkmessage. If you never reset this script it should store the data indefinitely. It generally depends on how important the "data" is or how long the "end user" needs to input the data. Link to comment Share on other sites More sharing options...
RunawayBunny Posted March 3, 2021 Share Posted March 3, 2021 (edited) Using external database good option for storing large data. Personal choice but IMO google services not reliable way to store your data.. they can change their APIs w/o any notice or make it prepaid subscription based or they might completely remove it (It happened with multiple APIs in the past: https://developers.google.com/+/api-shutdown) If you are planing store large amount of data PHP / Mysql on private server safest way. If you are not storing large data I recommend using prim description for data storage and retrieval: // Set prim description for no 2 link My_Options_Waiting_For_Parser llSetLinkPrimitiveParams(2, [PRIM_DESC,"My_Options_Waiting_For_Parser"]); // Get prim description from link no 2 string Ineedparsethis = llGetLinkPrimitiveParams(2, [PRIM_DESC]); Wiki: http://wiki.secondlife.com/wiki/LlSetPrimitiveParams http://wiki.secondlife.com/wiki/LlGetPrimitiveParams Hope it helps Edited March 3, 2021 by RunawayBunny Link to comment Share on other sites More sharing options...
Xiija Posted March 6, 2021 Share Posted March 6, 2021 (edited) re: Google Apps Scripts After some testing, i was able to do a POST thru sl only by going SL > thru repl.it > google apps script > repl.it > back to SL it seems google apps scripts use a redirect, and Sl only follows those if the request is GET.. Quote While the HTTP status code from the server is provided to the script, redirect codes such as 302 will result in the redirect being automatically and transparently followed ONLY IF the HTTP_METHOD is GET, with the resulting response being returned. If the HTTP_METHOD is anything other then GET then you'll get back an http_response with a status code of 302, but without any way to view the headers, you can't know where you were being redirected to unless that was also included in the body. i've got a GET apps script working, & will post it soon Edited March 6, 2021 by Xiija Link to comment Share on other sites More sharing options...
Xiija Posted March 7, 2021 Share Posted March 7, 2021 (edited) re: Google Apps Script to store data to a google doc, you can use an apps script. in my test, i use a GET request with 3 params... date, a message, and id the apps script will check if the id is blank, and if so it creates a new doc with the date as the title, and send that doc's id in the http response. if the SL prim gets an id, it can send it next time.. then the apps script will append to the current doc. you just need to set a timer & clear the id variable in SL on a date change. here is the Apps script to test with, if ya need the Sl bit, i can post that too. Google create doc apps script Edited March 7, 2021 by Xiija 1 Link to comment Share on other sites More sharing options...
Xiija Posted March 8, 2021 Share Posted March 8, 2021 (edited) A quick way to set and append data to a Sheet with Apps Scripts... Set & Append to a Sheet Edited March 8, 2021 by Xiija Link to comment Share on other sites More sharing options...
Gayngel Posted October 22, 2021 Share Posted October 22, 2021 On 3/6/2021 at 6:43 PM, Xiija said: re: Google Apps Scripts After some testing, i was able to do a POST thru sl only by going SL > thru repl.it > google apps script > repl.it > back to SL it seems google apps scripts use a redirect, and Sl only follows those if the request is GET.. i've got a GET apps script working, & will post it soon @Xiija You don't need to go through a 3rd party service communicate between Google App Script and SL. I've been meaning to post this for a looong time but haven't had time to create the example scripts until now. Google App Script: /* Google App Script Code by Gayngel of The Script Yard. Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 Description: This Google App Script keeps track of an LSL script's URL when it changes. The object the script is in can then be used as a server to retrieve persistent data from for a drop box and redelivery terminal system or scoreboard or HUD or whatever object/system you create that requires persistent stored data. The URL and stored data is saved to a spreadsheet and the data can be retrieved by a client script. Instructions: 1. Open your Google Drive and select New > More > Google App Script. 2. Before doing anything in the editor you must switch to the legacy editor. This is a very important step as some features don't work yet in the new editor. On the top right corner under your account button select "Use Legacy Editor". You can ignore and close the opt out survey. 3. Copy and paste this script into the code editor. 4. Select the save icon to save the script and give it a name. N.B: It is very important you save the script before publishing it to the web. 5. Select "Publish" on the menu bar and select "Deploy as Web App" 6. Select the Project Version dropdown and select New. 7. Under "Execute App As:" select Me(youremail@gmail.com) 8. Under "Who has access to the app:" select "Anyone, even anonymous". 9. Select "Deploy" and "Review Permissions". 10. Sign in to your google account. 11. If you get the "Google hasn't verified this app" message select "Advanced" and then select "Go to app_name(unsafe)". 12. Review and Allow Permissions. 13. Copy the web app url and paste it both in the server and client scripts in the line string app = ""; paste the url in between the quotation marks. If you make any changes to the script you must save and publish again. You must also select a new project version. */ function doGet(e) { var props = PropertiesService.getScriptProperties(); // Properties service can store properties/metadata. You can find properties by selecting File > Project Properties > Script Properties tab var url; if(e.parameter.server_url) { url = e.parameter.server_url; // gets the url of the server var obj_key = e.parameter.obj_key; var prop_obj = props.getProperty('prop_obj'); // get the prop_obj property from script properties if(prop_obj) { if(obj_key == prop_obj) // prevents two servers sharing the same app script/database { props.setProperty('URL',url); var payload = { "URL_OK":"URL_OK" // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } else // server uuid is different to stored server uuid. can not share same app script / database { var payload = { "URL_INVALID":"URL_INVALID" // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } } else { props.setProperty('prop_obj', obj_key); // sets a property prop_obj as object_key props.setProperty('URL',url); var payload = { "URL_OK":"URL_OK" // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } } else if(e.parameter.client_url) { url = e.parameter.client_url; // gets the url of the client var ssNew; var ssId = props.getProperty('ssId'); //gets the id of the spreadsheet by retrieving the stored id in script properties ssNew = SpreadsheetApp.openById(ssId); //open the spreadsheet var sheet = ssNew.getSheets()[0]; // get the first sheet in the spreadsheet var cell = sheet.getRange("A1"); // gets the range of cells. var payload = { "server_url":cell.getValue() // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) Sends the value of cell A1. }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } } function doPost(e) { var url = e.parameter.url; var props = PropertiesService.getScriptProperties(); // Properties service can store properties/metadata. You can find properties by selecting File > Project Properties > Script Properties tab var ssNew; var ssId = props.getProperty('ssId'); // get the ssId property from script properties if(ssId) // if the spreadsheet is created. I.E If the property ssId exists { ssNew = SpreadsheetApp.openById(ssId); // open the spreadsheet var sheet = ssNew.getSheets()[0]; // get first sheet of spreadsheet var cell = sheet.getRange("A1"); // target the first cell in the spreadsheet - A1 cell.clear(); // clear the data in A1 cell.setValue(e.parameter.url); // set the value of the A1 cell to the url of the server props.setProperty('URL',url); // sets a property URL as the url of the server var payload = { "url_added":"url_added" // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } // if(ssId) else // if spreadsheet is not created i.e there is no property named ssId in script properties { var ssName = e.parameter.spreadsheet; // the name of the spreadsheet set in the server script ssNew = SpreadsheetApp.create(ssName); // create a new spread sheet props.setProperty('ssId', ssNew.getId()); // sets a property ssID and set the vaue of the property to the id of the spreadsheet var payload = { "SpreadsheetReady":ssNew.getId() // body of method (POST,GET,PUT,etc). Sent as key/value pair. Can be parsed by llParseString2List(body,["="],[]) }; var options = { "method" : "post", // Method like HTTP_METHOD in the llHTTPRequest() function. We'll make a POST. "payload" : payload // what variables we are sending back to the server/client. }; var response = UrlFetchApp.fetch(url,options); // Make a http request back to the URL of the server or client that made the request. } } Here is barebones system to make send a message from a client script to request a greeting from the server to the avatar that touches the terminal and requests the greeting from the menu: Server: // Script by Gayngel of The Script Yard. //Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about //Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 // This is a barebones script to store the scripts url persistently in a Google Sheet. // The server will send a greeting when requested by a client terminal. // The server saves it's url to a Google Sheet via Google App Script. The client will request the url of the server from the spreadsheet and then request the server to greet the avatar who touched the object and requested a greeting from the menu. // Get the Google App Script from https://pastebin.com/Cc9ZbYyj and follow the instructions in the app script to setup. // Once set up paste the app url below. string app_url = "https://script.google.com/macros/s/AKfycbz-rAtEqm5clysDSL3l3-9kYqfwrDjSpFg7u4PuF9208F-ON3g/exec"; // place the url of Google App Script here. string spreadsheet = ""; // The Google App Script will create a spreadsheet in your Google Drive to store the url of the drop box. You can write a name here or leave it blank. If you leave the string blank the spreadsheet will automatically be called the "NameOfParcelDropBoxIsOn Dropbox". list parceldetails; string parcelname; string url; key reqURL; key http_req; key sheet_req; integer allow =FALSE; default { on_rez(integer start_param) { llSetObjectDesc(""); llResetScript(); } state_entry() { allow = FALSE; // verbosity just in case llReleaseURL(url); // verbosity just in case parceldetails = llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_NAME]); parcelname = llList2String(parceldetails,0); reqURL =llRequestURL(); } http_request(key id, string method, string body) { if (id == reqURL) { if (method == URL_REQUEST_DENIED) llOwnerSay("The following error occurred while attempting to get a free URL for this device:\n \n" + body); else if (method == URL_REQUEST_GRANTED) { url = body; } if(app_url != "") { http_req = llHTTPRequest(app_url+"?server_url="+url+"&obj_key="+(string)llGetKey(),[HTTP_METHOD,"GET"],""); // send the server's url to the spreadsheet to be stored. } else llOwnerSay("Please add the URL of the Google App Script at the top of the script"); } // if (id == reqURL) else if (method == "POST") { list tmp = llParseString2List(body,["="],[""]); string cmd = llToLower(llList2String(tmp,0)); string ref = llList2String(tmp,1); if(cmd == "url_ok") { string ssID = llGetObjectDesc(); if(ssID == "") // if the spreadsheet doesn't exist create one { if(spreadsheet == "") { spreadsheet = parcelname + " greeter."; } llOwnerSay("Creating spreadsheet named " + spreadsheet); if(app_url != "") sheet_req = llHTTPRequest(app_url+ "?url="+url+"&spreadsheet=" + llEscapeURL(spreadsheet),[HTTP_METHOD,"POST"],"Create"); // instruct the App Script to create a spreadsheet } else if(ssID != "") // if the spreadsheet exists { llOwnerSay("The spreadsheet database is ready."); llOwnerSay("This server can now be contacted"); allow = TRUE; sheet_req = llHTTPRequest(app_url+ "?url="+url,[HTTP_METHOD,"POST"],"Send_URL"); // update the url of the server and store in the spreadsheet } } //if(cmd == "url_ok") else if(cmd == "url_invalid") { llSetObjectDesc(""); llOwnerSay("Can not save this server's URL to the spreadsheet as the Google App Script is tied to another server. Please create a new app script and paste it's url at the top of the script."); } else if(cmd == "spreadsheetready") { llSetObjectDesc(ref); llOwnerSay("The spreadsheet database has been created."); allow = TRUE; sheet_req = llHTTPRequest(app_url+ "?url="+url,[HTTP_METHOD,"POST"],"Send_URL"); llOwnerSay("This server can now be contacted"); } else if(cmd == "url_added") { llOwnerSay("The url of your server has been updated in the spreadsheet database."); } else if(cmd == "request_greeting") { key av = (key)ref; if(allow == TRUE) { llInstantMessage(av,"Hello World!"); } } //else if(cmd == "request_redelivery") } // method is post } changed(integer change) { if(change & CHANGED_REGION_START || change & CHANGED_REGION || change & CHANGED_INVENTORY || change & CHANGED_TELEPORT) { llReleaseURL(url); // verbosity just in case llResetScript(); } } } Link to comment Share on other sites More sharing options...
Gayngel Posted October 22, 2021 Share Posted October 22, 2021 Client: // Script by Gayngel of The Script Yard. //Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about //Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 // This is a barebones script to store the scripts url persistently in a Google Sheet. // The server will send a greeting when requested by a client terminal. // The server saves it's url to a Google Sheet via Google App Script. The client will request the url of the server from the spreadsheet and then request the server to greet the avatar who touched the object and requested a greeting from the menu. // Get the Google App Script from https://pastebin.com/Cc9ZbYyj and follow the instructions in the app script to setup. // Once set up paste the app url below. string app = "https://script.google.com/macros/s/AKfycbz-rAtEqm5clysDSL3l3-9kYqfwrDjSpFg7u4PuF9208F-ON3g/exec"; // place the url of Google App Script here. string url; key reqURL; key server_req; key app_req; integer allow =FALSE; integer wait = FALSE; // if someone is using the terminal the next user must wait their turn integer listen_chan; integer listen_handle; key recipient; default { on_rez(integer start_param) { llResetScript(); } state_entry() { allow = FALSE; // verbosity just in case llReleaseURL(url); // verbosity just in case reqURL =llRequestURL(); } http_request(key id, string method, string body) { if (id == reqURL) { if (method == URL_REQUEST_DENIED) llOwnerSay("The following error occurred while attempting to get a free URL for this device:\n \n" + body); else if (method == URL_REQUEST_GRANTED) { url = body; if(app != "") { llOwnerSay("This terminal can now request greetings from the server"); allow = TRUE; } else llOwnerSay("Please add the URL of the Google App Script at the top of the script"); } } else if(id == server_req) { if(body == "redelivery_ok") { wait = TRUE; // verbosity just in case allow = TRUE; // verbosity just in case llListenRemove(listen_handle); // verbosity just in case } } else if(method == "POST") { list tmp = llParseString2List(body,["="],[""]); string cmd = llToLower(llList2String(tmp,0)); string ref = llList2String(tmp,1); if(cmd == "server_url") { server_req = llHTTPRequest(llUnescapeURL(ref),[HTTP_METHOD,"POST"],"request_greeting="+(string)recipient); // instruct server to redeliver object } } } touch_end(integer num) { key toucher = llDetectedKey(0); if(allow == TRUE) { if(wait == FALSE) { wait = TRUE; // other users must wait their turn llListenRemove(listen_handle); listen_chan = ((integer)("0x"+llGetSubString((string)toucher,-8,-1)) - 723) | 0x8000000; listen_handle = llListen(listen_chan,"",toucher,""); llDialog(toucher,"\nSelect Greet to get a greeting from the server.",["Greet"],listen_chan); } else { llRegionSayTo(toucher,0,"Someone is already using this terminal, please wait."); } } else { llRegionSayTo(toucher,0,"This server is currently offline."); } } listen(integer chan, string name, key id, string msg) { if(chan == listen_chan) { if(msg == "Greet") { llListenRemove(listen_handle); wait = FALSE; //allow next user to use the terminal allow = TRUE; // verbosity just in case //http request to google app script to get url of drop box recipient = id; app_req = llHTTPRequest(app+"?client_url="+url,[HTTP_METHOD,"GET"],""); // request url of server from spreadsheet database } } } changed(integer change) { if(change & CHANGED_REGION_START || change & CHANGED_REGION || change & CHANGED_INVENTORY || change & CHANGED_TELEPORT) { llReleaseURL(url); // verbosity just in case llResetScript(); } } } Link to comment Share on other sites More sharing options...
Gayngel Posted October 22, 2021 Share Posted October 22, 2021 Here is a simple redelivery terminal / drop box system: Server: // Script by Gayngel of The Script Yard. //Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about //Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 // This is a simple dropbox system. Redelivery systems will request redeliveries of the object you have stored in it and the drop box will deliver the object to avatar who requested a redelivery. // The drop box saves it's url to a Google Sheet via Google App Script. The redelivery client will request the url of the drop box from the spreadsheet and then request a redeivery from the drop box. // Get the Google App Script from https://pastebin.com/Cc9ZbYyj and follow the instructions in the app script to setup. // Once set up paste the app url below. string app_url = "https://script.google.com/macros/s/AKfycbyX-qKC0mpHFSa8iMDMBQyQtKzGQMdtxyICF5-pF2cebpm_HmU/exec"; // place the url of Google App Script here. string spreadsheet = ""; // The Google App Script will create a spreadsheet in your Google Drive to store the url of the drop box. You can write a name here or leave it blank. If you leave the string blank the spreadsheet will automatically be called the "NameOfParcelDropBoxIsOn Dropbox". list parceldetails; string parcelname; string url; key reqURL; key http_req; key sheet_req; integer allow =FALSE; default { on_rez(integer start_param) { llSetObjectDesc(""); llResetScript(); } state_entry() { allow = FALSE; // verbosity just in case llReleaseURL(url); // verbosity just in case parceldetails = llGetParcelDetails(llGetPos(),[PARCEL_DETAILS_NAME]); parcelname = llList2String(parceldetails,0); reqURL =llRequestURL(); } http_request(key id, string method, string body) { if (id == reqURL) { if (method == URL_REQUEST_DENIED) llOwnerSay("The following error occurred while attempting to get a free URL for this device:\n \n" + body); else if (method == URL_REQUEST_GRANTED) { url = body; } if(app_url != "") { http_req = llHTTPRequest(app_url+"?server_url="+url+"&obj_key="+(string)llGetKey(),[HTTP_METHOD,"GET"],""); // send the server's url to the spreadsheet to be stored. } else llOwnerSay("Please add the URL of the Google App Script at the top of the script"); } // if (id == reqURL) else if (method == "POST") { list tmp = llParseString2List(body,["="],[""]); string cmd = llToLower(llList2String(tmp,0)); string ref = llList2String(tmp,1); if(cmd == "url_ok") { string ssID = llGetObjectDesc(); if(ssID == "") // if the spreadsheet doesn't exist create one { if(spreadsheet == "") { spreadsheet = parcelname + " drop box."; } llOwnerSay("Creating spreadsheet named " + spreadsheet); if(app_url != "") sheet_req = llHTTPRequest(app_url+ "?url="+url+"&spreadsheet=" + llEscapeURL(spreadsheet),[HTTP_METHOD,"POST"],"Create"); // instruct the App Script to create a spreadsheet } else if(ssID != "") // if the spreadsheet exists { llOwnerSay("The spreadsheet database is ready."); llOwnerSay("This drop box will now allow redeliveries"); allow = TRUE; sheet_req = llHTTPRequest(app_url+ "?url="+url,[HTTP_METHOD,"POST"],"Send_URL"); // update the url of the server and store in the spreadsheet } } //if(cmd == "url_ok") else if(cmd == "url_invalid") { llSetObjectDesc(""); llOwnerSay("Can not save this server's URL to the spreadsheet as the Google App Script is tied to another server. Please create a new app script and paste it's url at the top of the script."); } else if(cmd == "spreadsheetready") { llSetObjectDesc(ref); llOwnerSay("The spreadsheet database has been created."); allow = TRUE; sheet_req = llHTTPRequest(app_url+ "?url="+url,[HTTP_METHOD,"POST"],"Send_URL"); llOwnerSay("This drop box will now allow redeliveries"); } else if(cmd == "url_added") { llOwnerSay("The url of your server has been updated in the spreadsheet database."); } else if(cmd == "request_redelivery") { key av = (key)ref; if(allow == TRUE) { if(llGetInventoryNumber(INVENTORY_OBJECT) > 0) // if the drop box contains an object { llInstantMessage(av,"Redelivering your object."); string obj = llGetInventoryName(INVENTORY_OBJECT,0); llGiveInventory(av,obj); llHTTPResponse(id,200,"redelivery_complete"); } else llInstantMessage(av,"Sorry there is nothing to redeliver"); } } //else if(cmd == "request_redelivery") } // method is post } changed(integer change) { if(change & CHANGED_REGION_START || change & CHANGED_REGION || change & CHANGED_INVENTORY || change & CHANGED_TELEPORT) { llReleaseURL(url); // verbosity just in case llResetScript(); } } } Client: // Script by Gayngel of The Script Yard. //Join The Script Yard Group: secondlife:///app/group/4921b4f0-c21e-7866-c0c2-791d10bb5502/about //Visit The Script Yard Marketplace: https://marketplace.secondlife.com/stores/149734 // This is a simple dropbox system. Redelivery systems will request redeliveries of the object you have stored in it and the drop box will deliver the object to avatar who requested a redelivery. // The drop box saves it's url to a Google Sheet via Google App Script. The redelivery client will request the url of the drop box from the spreadsheet and then request a redeivery from the drop box. // Get the Google App Script from https://pastebin.com/Cc9ZbYyj and follow the instructions in the app script to setup. // Once set up paste the app url below. string app = "https://script.google.com/macros/s/AKfycbyX-qKC0mpHFSa8iMDMBQyQtKzGQMdtxyICF5-pF2cebpm_HmU/exec"; // place the url of Google App Script here. string url; key reqURL; key server_req; key app_req; integer allow =FALSE; integer wait = FALSE; // if someone is using the terminal the next user must wait their turn integer listen_chan; integer listen_handle; key recipient; default { on_rez(integer start_param) { llResetScript(); } state_entry() { allow = FALSE; // verbosity just in case llReleaseURL(url); // verbosity just in case reqURL =llRequestURL(); } http_request(key id, string method, string body) { if (id == reqURL) { if (method == URL_REQUEST_DENIED) llOwnerSay("The following error occurred while attempting to get a free URL for this device:\n \n" + body); else if (method == URL_REQUEST_GRANTED) { url = body; if(app != "") { llOwnerSay("This terminal can now request redeliveries"); allow = TRUE; } else llOwnerSay("Please add the URL of the Google App Script at the top of the script"); } } else if(id == server_req) { if(body == "redelivery_ok") { wait = TRUE; // verbosity just in case allow = TRUE; // verbosity just in case llListenRemove(listen_handle); // verbosity just in case } } else if(method == "POST") { list tmp = llParseString2List(body,["="],[""]); string cmd = llToLower(llList2String(tmp,0)); string ref = llList2String(tmp,1); if(cmd == "server_url") { server_req = llHTTPRequest(llUnescapeURL(ref),[HTTP_METHOD,"POST"],"request_redelivery="+(string)recipient); // instruct server to redeliver object llOwnerSay("Requesting redelivery from server please wait..."); llSetTimerEvent(0.0); llSetTimerEvent(10.0); } } } http_response(key id, integer status, list metadata ,string body) { if(body == "redelivery_complete") { llOwnerSay("Delivery successful"); llSetTimerEvent(0.0); // redelivery was successful // do other stuff here } } touch_end(integer num) { key toucher = llDetectedKey(0); if(allow == TRUE) { if(wait == FALSE) { wait = TRUE; // other users must wait their turn llListenRemove(listen_handle); listen_chan = ((integer)("0x"+llGetSubString((string)toucher,-8,-1)) - 723) | 0x8000000; listen_handle = llListen(listen_chan,"",toucher,""); llDialog(toucher,"\nSelect redeliver to redeliver your object.",["Redeliver"],listen_chan); } else { llRegionSayTo(toucher,0,"Someone is already using this terminal, please wait."); } } else { llRegionSayTo(toucher,0,"This redelivery terminal is currently offline."); } } listen(integer chan, string name, key id, string msg) { if(chan == listen_chan) { if(msg == "Redeliver") { llListenRemove(listen_handle); wait = FALSE; //allow next user to use the terminal allow = TRUE; // verbosity just in case //http request to google app script to get url of drop box recipient = id; app_req = llHTTPRequest(app+"?client_url="+url,[HTTP_METHOD,"GET"],""); // request url of server from spreadsheet database } } } timer() { llSetTimerEvent(0.0); llInstantMessage(recipient,"There was no response from the server. Please try again."); } changed(integer change) { if(change & CHANGED_REGION_START || change & CHANGED_REGION || change & CHANGED_INVENTORY || change & CHANGED_TELEPORT) { llReleaseURL(url); // verbosity just in case llResetScript(); } } } 1 Link to comment Share on other sites More sharing options...
Kehf Nelson Posted October 26, 2022 Share Posted October 26, 2022 I've been needing external data storage for a while and decided to try to do something about it. Firstly, this is my first node.js attempt and it shows. Any ideas are welcome. So far. it works: https://github.com/knscripting/Simple-KVP-Node-for-Secondlife There are a few LSL examples in the repository. I have some important things on to do list. all comments welcome. 2 Link to comment Share on other sites More sharing options...
Recommended Posts
Please take a moment to consider if this thread is worth bumping.
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now