# ==== Customize these values ====

CLIENT_SECRET=""
COMMUNITY_BASE_URL=""
REDIRECT_URI=""
CLIENT_ID=""
SHARED_SECRET_KEY = ""
HTACCESS_USER = ""
HTACCESS_PASSWORD = ""

# ==== Customize these values ====

# You can change the GraqhQL query at the bottom of the page.


import base64
import hashlib
import hmac
import time
import uuid

import requests

try:
    from Crypto.Hash import RIPEMD160
except ImportError:
    RIPEMD160 = None

try:
    import pyscrypt
except ImportError:
    pyscrypt = None

import binascii


def generate_cc_hash(client_id, client_secret, nonce, epoch_minute, shared_secret_key, algorithm="SHA512"):
    str_to_hash = f"{client_id}:{client_secret}:{nonce}:{epoch_minute}"
    algorithm = algorithm.upper()

    if algorithm == "SHA256":
        digest = hashlib.sha256()
        digest.update(str_to_hash.encode("utf-8"))
        digest.update(shared_secret_key.encode("utf-8"))
        return digest.hexdigest()

    elif algorithm == "SHA512":
        digest = hashlib.sha512()
        digest.update(str_to_hash.encode("utf-8"))
        digest.update(shared_secret_key.encode("utf-8"))
        return digest.hexdigest()

    elif algorithm == "RIPEMD160":
        if RIPEMD160 is None:
            raise ImportError("pycryptodome is required for RIPEMD160")
        digest = RIPEMD160.new()
        digest.update(str_to_hash.encode("utf-8"))
        digest.update(shared_secret_key.encode("utf-8"))
        return digest.hexdigest()

    elif algorithm == "SCRYPT":
        if pyscrypt is None:
            raise ImportError("pyscrypt module is required for SCRYPT")
        hash_bytes = pyscrypt.hash(password=str_to_hash.encode("utf-8"),
                                   salt=shared_secret_key.encode("utf-8"),
                                   N=16, r=16, p=16, dkLen=16)
        return binascii.hexlify(hash_bytes).decode("utf-8")

    else:
        raise ValueError(f"Unsupported algorithm: {algorithm}")


def get_khoros_access_token(
    client_id,
    client_secret,
    shared_secret_key,
    redirect_uri,
    community_base_url,
    algorithm="sha512"
):
    nonce = str(time.time())
    epoch_time_minute = str(int(time.time() // 60))

    cc_hash = generate_cc_hash(client_id, client_secret, nonce, epoch_time_minute, shared_secret_key, algorithm)
    token_url = f"{community_base_url}/t5/s/api/2.1/auth/accessToken"

    headers = {
        "Content-Type": "application/json",
        "nonce": nonce,
        'Authorization': 'Basic bWljcm9zb2Z0YXVyb3JhOmdMcU5mQ3JU'
    }

    payload = {
        "client_id": client_id,
        "client_secret": client_secret,
        "redirect_uri": redirect_uri,
        "grant_type": "client_credentials",
        "cc_hash": cc_hash,
        "hash_algorithm": algorithm
    }

    response = requests.post(token_url, headers=headers, json=payload)

    data = response.json()
    return data['access_token'], data

# ==== Request Token ====
try:
    access_token, full_response = get_khoros_access_token(
        CLIENT_ID, CLIENT_SECRET, SHARED_SECRET_KEY,
        REDIRECT_URI, COMMUNITY_BASE_URL
    )
except Exception as e:
    print("Error during authentication:", str(e))


graphQL = COMMUNITY_BASE_URL + "/api/2.1/graphql"
creds = HTACCESS_USER+":"+HTACCESS_PASSWORD
creds = creds.encode('UTF-8')
htacces = base64.b64encode(creds)

headers = {
    "Authorization": f'Bearer {access_token}, Basic {htacces}',
    "Content-Type": "application/json"
}

print("Authorization: " + headers['Authorization'])

body = {"query": """query GetMessagesLevelMetadata($messageId: [ID!]!) {
   messages(constraints: {id: {in: $messageId}}) {
      edges {         node {
            customFields {
               name
               ... on CustomStringField {
                  stringValue
               }
               ... on CustomStringListField {
                 stringListValue
               }
            }
         }
     }
   }
}""",
"variables":{"messageId":"message:358"}
}

response = requests.post(graphQL, json=body, headers=headers) 

print("Response: " + response.text)