import requests
import sys
import json
import datetime

# Provide your keys

apikey = "paste_your_api_key_here"
apisecret = "paste_your_api_secret_here"

#

apiurl = "https://api.codepunch.com/dnfeed/v2/"


def get_api_token():
    AUTHURLFMT = "{}auth/{}/{}"
    url = AUTHURLFMT.format(apiurl, apikey, apisecret)
    response = requests.get(url)
    if response.status_code == 200:
        apiresponse = response.json()
    else:
        raise Exception('Authentication: {}'.format(response.status_code))
    if bool(apiresponse['status']) != True:
        raise Exception(apiresponse['error'])
    return apiresponse['token']


def get_api_data(token, command, parameters):
    APIURLFMT = "{}{}/{}/"
    url = APIURLFMT.format(apiurl, token, command)
    response = requests.get(url, params=parameters)
    if response.status_code != 200:
        raise Exception('Invalid response code: {}'.format(response.status_code))
    apiresponse = response.json()
    if bool(apiresponse['status']) != True:
        raise Exception(apiresponse['error'])
    return apiresponse


def get_api_zip_file(token, command, parameters, filename):
    APIURLFMT = "{}{}/{}/"
    url = APIURLFMT.format(apiurl, token, command)
    response = requests.get(url, params=parameters, stream=True)
    totalbits = 0
    if response.status_code == 200:
        with open(filename, 'wb') as f:
            for chunk in response.iter_content(chunk_size=1024):
                if chunk:
                    totalbits += 1024
                    f.write(chunk)
        print("Downloaded {} KB to {}".format(round(totalbits / 1024), filename))
    else:
        raise Exception('Invalid response code: {}'.format(response.status_code))


try:
    idx = 0
    source_name     = 'added'
    keywords        = "%apple%|%paypal%"
    number_of_days  = 1
    only_domain_names = False
    show_information  = True
    tlds_to_get     = ''
    show_raw_data   = False
    download_zip    = False
    zip_date        = None      # None = previous day unless -latest is used
    zip_latest      = False     # True = current day so far
    zip_output_file = None      # None = auto-named

    for i in sys.argv:
        if i == "-h":
            print("\ndnfeed-app.py [options]\n")
            print("Domain query options:")
            print("  -d days      Number of preceding days (0-14) to get data for")
            print("               Sample-client limit; API retention can vary from 14-45 days.")
            print("  -kw keywords Keywords to filter by. Separate with comma. Use % for wildcard.")
            print("               Enclose in double quotes when using %. Example: -kw \"%apple%,%amazon%\"")
            print("  -tlds tlds   TLDs to filter by. Separate with commas. Example: com,net,org")
            print("  -s source    Data source: added or deleted. Default: added")
            print("  -od          Print domain names only, no dates")
            print("  -raw         Print returned data rows as formatted JSON")
            print("  -v           Query information (already shown by default)")
            print("\nZIP download options:")
            print("  -zip         Download the daily ZIP file instead of querying")
            print("  -zd date     Date for ZIP download in yyyymmdd format.")
            print("               Omit for previous day. Cannot be used with -latest.")
            print("  -latest      Download ZIP for the current day (domains processed so far).")
            print("               Only valid without -zd.")
            print("  -o filename  Output filename. Default: dnfeed-<source>-<label>.zip")
            print("\nExamples:")
            print("  python dnfeed-app.py -zip                          # previous day added ZIP")
            print("  python dnfeed-app.py -zip -s deleted               # previous day deleted ZIP")
            print("  python dnfeed-app.py -zip -zd 20240101             # specific date added ZIP")
            print("  python dnfeed-app.py -zip -latest                  # current day so far")
            print("  python dnfeed-app.py -zip -latest -s deleted -o del.zip")
            print("  python dnfeed-app.py -d 10 -kw \"%bank%\" -tlds com,net")
            sys.exit()
        elif i == "-d":
            idx += 1
            number_of_days = int(sys.argv[idx])
            if number_of_days > 14:
                number_of_days = 14
        elif i == "-kw":
            idx += 1
            keywords = sys.argv[idx]
            keywords = keywords.replace(",", "|")
        elif i == "-od":
            only_domain_names = True
            idx += 1
        elif i == "-raw":
            show_raw_data = True
            idx += 1
        elif i == "-v":
            show_information = True
            idx += 1
        elif i == "-s":
            idx += 1
            source_name = sys.argv[idx]
        elif i == "-tlds":
            idx += 1
            tlds_to_get = sys.argv[idx]
        elif i == "-zip":
            download_zip = True
            idx += 1
        elif i == "-zd":
            idx += 1
            zip_date = sys.argv[idx]
        elif i == "-latest":
            zip_latest = True
            idx += 1
        elif i == "-o":
            idx += 1
            zip_output_file = sys.argv[idx]
        else:
            idx += 1

    if source_name != 'added' and source_name != 'deleted':
        source_name = 'added'

    token = get_api_token()

    # ── ZIP download mode ──────────────────────────────────────────────────
    if download_zip:
        params = {"source": source_name}

        if zip_latest and zip_date:
            raise Exception("Use either -zd or -latest, not both.")

        if zip_date:
            params["date"] = zip_date
            label = zip_date
        elif zip_latest:
            params["latest"] = ""
            label = "latest"
        else:
            label = "prev"

        if zip_output_file is None:
            zip_output_file = "dnfeed-{}-{}.zip".format(source_name, label)

        print("Downloading {} {} ZIP to {}...".format(source_name, label, zip_output_file))
        get_api_zip_file(token, "dailyzip", params, zip_output_file)

    # ── Domain query mode ──────────────────────────────────────────────────
    else:
        today_date = datetime.datetime.now()
        delta      = datetime.timedelta(days=number_of_days)
        olddate    = today_date - delta
        datecode   = olddate.strftime("%Y%m%d")

        if show_information:
            printdatecode = olddate.strftime("%Y-%m-%d")
            print('\nGetting domain data after {} for keywords \'{}\' from the {} domains list.\n'.format(
                printdatecode, keywords, source_name))

        parameters = {
            "date":   datecode,
            "limit":  5000,
            "kw":     keywords,
            "dcm":    'gte',
            "tlds":   tlds_to_get,
            "format": "json"
        }
        thedata    = get_api_data(token, source_name, parameters)
        domaindata = thedata['data']

        if show_raw_data:
            print(json.dumps(domaindata, indent=2))
        else:
            for d in domaindata:
                if only_domain_names:
                    print(d['domain'])
                else:
                    print(d['domain'] + ', ' + d['date'])

except Exception as e:
    print(repr(e))