Advertisement
SapphireViking

Visitor Counter

Feb 23rd, 2018
274
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.10 KB | None | 0 0
  1. /* This is a free fullperm script to record all visitors to a parcel (or region).
  2. * Unlike most visitor recorders this is not based on range, but by parcel or region boundaries.
  3. * Names are only recorded once, no matter how often they visit, so this is not a traffic monitor.
  4. * Names are listed back as profile links, for easy access to information about your visitors.
  5. * The owner can either touch the object with the script or say 'list' to see the list,
  6. * or optionally say 'listPublic' to send the list to public chat.
  7. * If anyone else touches the object it merely quietly reruns the scan. Otherwise it will scane every 'scanHowOften' seconds.
  8. * You can freely redistribute this script.
  9. * by Pussycat Catnap. 11/28/2015
  10. *
  11. * UPDATE 01/30/2016
  12. * On the first visit on avatar makes in day, it will now record
  13. * the time and up a counter by 1 for that day.
  14. *
  15. * UPDATE 03/08/2016
  16. * Now has a MAX_COUNT that is the maximum number of entries on the list.
  17. * List now shows newest names first, and clears out oldest names as list hits maximum.
  18. * Added bars above and below list output to make it easier to see in chat.
  19. * UPDATE 03/09/2016
  20. * Fixed bars to only appear above and below whole list and not between each name.
  21. */
  22.  
  23. list visitors; // A global record of all avatars that have visited since last script reset.
  24. integer scanHowOften = 30; // Rerun the region scan every 'scanHowOften' seconds.
  25. integer MAX_COUNT = 100; // How many names to keep on the list.
  26.  
  27. // Uncomment the desire scanDistance setting.
  28. // Avatars in this parcel
  29. integer scanDistance = AGENT_LIST_PARCEL;
  30. // Avatars in parcels in this region owned by the owner of the parcel this is rezzed in.
  31. // integer scanDistance = AGENT_LIST_PARCEL_OWNER;
  32. // All avatars in the region.
  33. // integer scanDistance = AGENT_LIST_REGION;
  34.  
  35.  
  36. string findTimeEntry()
  37. {
  38. string rightNow = llGetTimestamp();
  39. list piecesOfTime = llParseString2List(rightNow,["T", ".","Z"],[]);
  40.  
  41. string theTime = "Last seen on " + llList2String(piecesOfTime, 0) + " at UTC time: " + llList2String(piecesOfTime, 1);
  42. // llSay( 0,theTime);
  43. return theTime;
  44. }
  45.  
  46. list ListStridedUpdate(list dest, list src, integer start, integer end, integer stride) {
  47. return llListReplaceList(dest, src, start * stride, ((end + 1) * stride) - 1 );
  48. }
  49.  
  50. // Compares any ID key to the permanent list to prevent duplicate entries
  51. integer isIDKeyOnList( key id )
  52. {
  53. list listofIDs = llList2ListStrided(visitors,0,-1,3);
  54. integer len = llGetListLength( listofIDs );
  55. integer i;
  56. for( i = 0; i < len; i++ )
  57. {
  58. if( llList2Key(listofIDs, i) == id )
  59. {
  60. list timeCheck = llParseString2List(llList2String(visitors, (i*3)+2),["Last seen on ", " at UTC time: "],[]);
  61. // Insert a date and visit count update on first visit of each day.
  62. // We could do this on every scan, but then it would add to the count 1 entry every 'scanHowOften' seconds.
  63. // We could also parse the time string out and pick a certain amount of delay, but a day is reasonable for seeing if
  64. // someone is becomming a regular.
  65. if (llList2String(timeCheck ,0) != llGetDate( ))
  66. {
  67. integer visitCount = llList2Integer(visitors, (i*3)+1);
  68. visitCount +=1;
  69.  
  70. list update = [id, visitCount, findTimeEntry()];
  71. visitors = ListStridedUpdate(visitors, update, i, i, 3);
  72. }
  73. return TRUE;
  74. }
  75. }
  76. return FALSE;
  77. }
  78.  
  79.  
  80. // Scans the parcel, records any new entries.
  81. scanRegion(integer touched)
  82. {
  83. list visitorsRightNow = llGetAgentList(scanDistance, []);
  84. integer numOfAvatars = llGetListLength(visitorsRightNow);
  85.  
  86. if (!numOfAvatars)
  87. {
  88. return;
  89. }
  90. integer index;
  91. while (index < numOfAvatars)
  92. {
  93. key id = llList2Key(visitorsRightNow, index);
  94.  
  95. if(touched == 3 || (id != llGetOwner()))
  96. {
  97. if( isIDKeyOnList(id) == FALSE)
  98. {
  99. // visitors += [id, 1, findTimeEntry()];
  100. visitors = [id, 1, findTimeEntry()] + llList2List(visitors, 0, ((MAX_COUNT-1)*3)-1);
  101. // Keep the list limited in size.
  102. }
  103. }
  104. ++index;
  105. }
  106. visitorsRightNow = []; // null the temp list.
  107. }
  108.  
  109. // Outputs names to the owner, or to public chat depending on request.
  110. outputNames(integer public)
  111. {
  112. list listofIDs = llList2ListStrided(visitors,0,-1,3);
  113. integer numOfAvatars = llGetListLength(listofIDs);
  114.  
  115. integer index;
  116.  
  117. if (public == TRUE) llSay( 0,"+--------------------------------------------------------------------------------------+\n");
  118. else llOwnerSay("+--------------------------------------------------------------------------------------+\n");
  119. while (index < numOfAvatars)
  120. {
  121. key id = llList2Key(listofIDs, index);
  122. string name = llKey2Name(id);
  123. string whenLastVisited = llList2String(visitors, (index*3)+2);
  124. string visitCount = (string)llList2Integer(visitors, (index*3)+1);
  125.  
  126. if (public == TRUE)
  127. llSay( 0,"secondlife:///app/agent/" + (string)id + "/about : Visited " + visitCount + " times. " + whenLastVisited);
  128. else
  129. llOwnerSay("secondlife:///app/agent/" + (string)id + "/about : Visited " + visitCount + " times. " + whenLastVisited);
  130. ++index;
  131. }
  132. if (public == TRUE) llSay( 0,"+--------------------------------------------------------------------------------------+\n");
  133. else llOwnerSay("+--------------------------------------------------------------------------------------+\n");
  134. }
  135.  
  136.  
  137.  
  138. // The default LSL function.
  139. default
  140. {
  141. // run when the item is rezed, reset, or the script resaved.
  142. state_entry()
  143. {
  144. visitors = []; // Ensure a blank list at the start.
  145. scanRegion(3); // First scan is allowed to scan object owner.
  146. llSetTimerEvent(scanHowOften); // sets how often to scan
  147. llListen(0, "", llGetOwner(), ""); // enables the owner to use chat commands
  148. outputNames(FALSE); // Let us see the first pass just to see what it looks like.
  149. }
  150.  
  151. // tells the script to scan the region.
  152. timer()
  153. {
  154. scanRegion(FALSE);
  155. }
  156.  
  157. // allows touching to run the scan, and if touched by owner, sends the list to the owner.
  158. touch_start(integer total_number)
  159. {
  160. scanRegion(TRUE);
  161. if (llDetectedKey(0) == llGetOwner())
  162. outputNames(FALSE);
  163. }
  164.  
  165. // The available chat commands:
  166. // list = sends list to owner.
  167. // listPublic = sends the list to public chat. Use with caution.
  168. listen( integer channel, string name, key id, string message )
  169. {
  170. if( id != llGetOwner() ) // match the ID of the chatter to the owner, or stop.
  171. {
  172. return;
  173. }
  174. else
  175. if( message == "list" )
  176. {
  177. scanRegion(FALSE);
  178. outputNames(FALSE);
  179. }
  180. else
  181. if( message == "listPublic" )
  182. {
  183. scanRegion(FALSE);
  184. outputNames(TRUE);
  185. }
  186. }
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement