Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

223
LINES

< > BotCompany Repo | #1002157 - Cookie + IP-Based Double Visitor Counter Bot

JavaX source code (desktop) [tags: butter use-pretranspiled] - run with: x30.jar - homepage

Libraryless. Click here for Pure Java version (9597L/61K).

!7

// TODO: use concepts DB

static S cookieName = "cookie";
static int cookieDays = 32, cookieLength = 20;

static int cookieCounter = 1;

static long countingForUnixDay;
static new L<S> ips;
static new L<S> cookies;
static long cookieLess;
static new L<Uaip> uaips;
static new MultiSet<S> referers;
static Lock lock = lock();

static new ThreadLocal<S> cookieFromUser;
static new ThreadLocal<S> cookieSent;
  
static class Uaip {
  S ua, ip;
  bool hasCookie;
  *() {}
  *(S *ua, S *ip, bool *hasCookie) {}
}

static class Data {
  long day, ips, cookies, cookieLess;
  new L<Uaip> uaips;
  
  *(long *day, long *ips, long *cookies, long *cookieLess) {}
  *() {}
}

static PersistentLog<Data> stats;

static ReliableSingleThread_Multi<S> rstSaveVars = new(60000, lambda1 save);

p {
  stats = new PersistentLog("stats.log");
  load("cookieCounter");
  load("countingForUnixDay");
  load("ips");
  load("cookies");
  load("cookieLess");
  load("uaips");
  load("referers");
}

set flag NoNanoHTTPD. html {
  lock lock;
  if (eq(uri, "/referers"))
    ret hmobilefix() + h3("Referers!") + htable(
      renderMapForTable(orderMapByDescendingValue(referers.asMap()), "Referer", "Count", true));
      
  if (eq(uri, "/requests"))
    ret str(getOpt(getOpt(mainBot(), 'serveHttp_server), 'requests));

  if (eq(uri, "/requests-plus-serving")) {
    O server = getOpt(mainBot(), 'serveHttp_server);
    int serving = l(getOpt(server, 'currentlyServing));
    ret getOpt(server, 'requests) + (serving != 0 ? " [" + serving + "]" : "");
  }
    
  if (eq(uri, "/stats")) {
    ret 
      htag("p", "IPs in the day: " + l(ips) + ", cookies in the day: " + l(cookies) + ", cookieless today: " + cookieLess + ". Total cookies given out since all time: " + cookieCounter) +
      htag("pre", fromLines(reversedList(toLines(stats.fileContents()))));
  }
  
  if (eq(uri, "/uaips")) {
    int n = toInt(params.get("n"));
    L<S> lines = map sfu(dropFirst(n, cloneList(uaips)));
    S after = params.get('after);
    if (nempty(after)) lines = subList(lines, indexOf(lines, after)+1);
    ret serveText(lines(lines));
  }

  O session = call(getMainBot(), "getSession");
  O cookieHandler = call(getMainBot(), "getCookies");
  S cookie = cast call(cookieHandler, "read", cookieName);
  cookieFromUser.set(cookie);
  
  // rotate if day changed
  long day = unixDay();
  if (day != countingForUnixDay) {
    if (countingForUnixDay != 0) {
      // archive
      print("Archiving stats for unix day " + countingForUnixDay + "!");
      stats.add(today());
    }

    // rotate
    countingForUnixDay = day;
    saveLater("countingForUnixDay");
    ips.clear();
    saveLater("ips");
    cookies.clear();
    saveLater("cookies");
    cookieLess = 0;
    saveLater("cookieLess");
    uaips = new L;
    saveLater("uaips");
  }
  
  // save only cookies returned by user
  if (!cookies.contains(cookie)) {
    cookies.add(cookie);
    saveLater("cookies");
  } else {
    ++cookieLess;
    saveLater("cookieLess");
  }
  
  // record IP
  Map headers = cast call(session, "getHeaders");
  S remoteAddr = cast headers.get("remote-addr");
  S client = cast headers.get("x-forwarded-for");
  if (nempty(client)) remoteAddr += "," + client;
  if (!empty(remoteAddr) && !ips.contains(remoteAddr)) {
    ips.add(remoteAddr);
    saveLater("ips");
  }

  // add uaip
  S ua = cast headers.get("user-agent");
  addUAIP(ua, remoteAddr, nempty(cookie));
  
  // referer
  S referer = cast headers.get("referer");
  if (nempty(referer)) {
    referers.add(referer);
    saveLater("referers"); // TODO: rotate etc.
  }
    
  boolean isNew = false;
  if (cookie == null) {
    isNew = true;
    //cookie = "Cookie " + (cookieCounter++);
    if (empty((S) headers.get("x-no-cookies")))
      cookie = randomID(cookieLength);
    //saveLater("cookieCounter");
  }
  
  if (cookie != null) {
    cookieSent.set(cookie);
    O cookieObject = call(cookieHandler, "set", cookieName, cookie, cookieDays); // hopefully this refreshes the expiration?
    S domain = domain();
    if (isAGIBlueDomain(domain))
      setOpt(cookieObject, domain := theAGIBlueDomain());
    setOpt(cookieObject, path := "/");
    print("Setting path for cookie object " + cookieObject + ": " + getOpt(cookieObject, 'path));
  }
  
  S s = cookie == null ? "" : "Your " + (isNew ? "new " : "recurring ") + "cookie is: " + cookie;
  s += "<br>";
  Data y = yesterday();
  S yesterday = y == null ? "" : " (" + y.cookies + "/" + y.ips + " yesterday)";
  s += l(cookies) + " cookies, " + l(ips) + " IPs" + yesterday + " seen today. " + cookieLess + " requests.";
  ret s;
}

synchronized answer {
  if (subBot_master()) if "clear referers" {
    lock lock;
    referers.clear();
    saveLater("referers");
    ret "OK";
  }
  
  if "visitors today" {
    ret structure(today());
  }
  
  if "visitors yesterday" {
    Data data = yesterday();
    if (data == null)
      ret "There was no yesterday.";
    ret structure(data);
  }
  
  if "visitors last * days" {
    int i = max(0, l(stats)-parseInt(m.unq(0))+1);
    
    new L<Map> stats_;
    for (Map map : objectToMap(concatLists(
      subList(stats, i),
      litlist(today())
    )))
      stats_.add(mapWithoutKey(map, "uaips")); // drop the long stuff

    ret "```" + structureLines(stats_) + "```";
  }
  
  if "uaips today"
    ret sfu(cloneList(uaips));
}

static Data today() {
  Data d = new Data(countingForUnixDay, l(ips), l(cookies), cookieLess);
  d.uaips = cloneList(uaips);
  ret d;
}

static synchronized Data yesterday() {
  ret last(stats);
}

static void addUAIP(S ua, S ip, bool hasCookie) {
  for (Uaip x : uaips)
    if (eq(x.ua, ua) && eq(x.ip, ip) && hasCookie == x.hasCookie)
      ret;
  uaips.add(new Uaip(ua, ip, hasCookie));
  saveLater("uaips");
}

sS cookieFromUser() { ret cookieFromUser!; }
sS cookieSent() { ret cookieSent!; }

svoid saveLater(S var) {
  rstSaveVars.add(var);
}

Author comment

Began life as a copy of #1002155

download  show line numbers  debug dex   

Travelled to 17 computer(s): aoiabmzegqzx, bhatertpkbcr, bvmoasoxxqgd, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, jtubtzbbkimh, lpdgvwnxivlt, mqqgnosmbjvj, nsosnbthvwzj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, xrpafgyirdlv

No comments. add comment

Snippet ID: #1002157
Snippet name: Cookie + IP-Based Double Visitor Counter Bot
Eternal ID of this version: #1002157/37
Text MD5: 2328d22f199b70d4c1d4fdc7c737fcc2
Transpilation MD5: ab3b8406103fe7a8b737cc4dd172e5e2
Author: stefan
Category: javax
Type: JavaX source code (desktop)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2021-02-18 11:52:40
Source code size: 6133 bytes / 223 lines
Pitched / IR pitched: No / No
Views / Downloads: 757 / 8945
Version history: 36 change(s)
Referenced in: [show references]

Formerly at http://tinybrain.de/1002157 & http://1002157.tinybrain.de