#!/usr/bin/env python2.7

# this file is part of tmww
# willee, 2014, GPL v3

# ip.py - check known player ids and ips for intersecting domains

# ./ip.py /path/to/dbplayers.jsonl < input > domains
# where input data consists of lines of 2 fields:
# 1st field -- id
# 2nd field -- ip

import json, sys

class domain(object):
   def __init__(self):
       self.ids = []
       self.nids = []
       self.players = []
       self.ips = []

   def to_JSON(self):
       return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True)

def prepare_domains(altsdb, d):
   with open(altsdb) as db:
       while True:
           i = db.readline()
           if not i:
               break
           t = json.loads(i)
           dom = domain()
           if "accounts" in t:
               dom.nids = t["accounts"]
               dom.players = [ t["player"] ]
               d.append(dom)

def search(d, field, value):
   if field == "ids":
       for i in d:
           if (value in i.ids) or (value in i.nids):
               return d.index(i)
   elif field == "ips":
       for i in d:
           if value in i.ips:
               return d.index(i)

def merge(d, i1, i2):
   d[i1].ids += d[i2].ids
   d[i1].nids += d[i2].nids
   d[i1].players += d[i2].players
   d[i1].ips += d[i2].ips
   del d[i2]

def form_domain(d,id,ip):
   id_domain = search(d, "ids", id)
   ip_domain = search(d, "ips", ip)
   if id_domain is None and ip_domain is None:
       t = domain()
       t.ids.append(id)
       t.ips.append(ip)
       d.append(t)
   elif id_domain is None and ip_domain is not None:
       if id not in d[ip_domain].ids:
           d[ip_domain].ids.append(id)
   elif id_domain is not None and ip_domain is None:
       if ip not in d[id_domain].ips:
           d[id_domain].ips.append(ip)
   else:
       if not (id_domain == ip_domain):
           merge(d, id_domain, ip_domain)

if __name__ == "__main__":
   domains = []

   # altsdb full path
   altsdb = sys.argv[1]

   # generate domains for known ids based on altsdb
   prepare_domains(altsdb, domains)

   # generate domains from stdin (login.log expected)
   for line in sys.stdin:
       i = line.split()
       if len(i) != 2:
           continue
       form_domain(domains,i[0],i[1])

   # put on stdout result JSONlines
   # filter non-informative domains
   for i in domains:
       if (not i.ids) and (len(i.players) < 2):
           continue
       print i.to_JSON()