[에러 해결] Python NameError: name ‘generate_chk’ is not defined 원인과 해결 방법

작성자

카테고리:

[에러 해결] Python NameError: name ‘generate_chk’ is not defined 원인과 해결 방법

Python 개발 중 NameError: name 'generate_chk' is not defined 에러를 마주하셨나요? 특히 Geometry Dash API와 같은 외부 서비스와 연동할 때 종종 겪을 수 있는 문제입니다. 이 가이드는 해당 에러가 발생하는 원인을 분석하고, 명확한 코드 예시를 통해 해결 방법을 제시하며, 향후 유사한 문제를 예방하기 위한 팁을 제공합니다.

에러 상황 소개

사용자께서는 Python을 이용해 Geometry Dash 레벨을 업로드하는 프로그램을 개발하고 계셨습니다. 이 과정에서 seed2 값을 생성하기 위해 generate_chk 함수를 호출했는데, 아래와 같은 NameError가 발생했습니다.

Traceback (most recent call last):
  File "/home/***/scripts/usernm/upload", line 43, in <module>
    "seed2": generate_chk(key="41274", values=[generate_upload_seed(levelString)], salt="xI25fpAapCQg"), # This is talked about in the CHK encryption,
             ^^^^^^^^^^^^
NameError: name 'generate_chk' is not defined. Did you mean: 'generate_gjp2'?

이 에러는 스크립트 내에서 generate_chk라는 이름의 함수를 찾을 수 없을 때 발생합니다. 해당 함수는 Geometry Dash API 문서를 참조하여 사용하려 했으나, 참조 문서가 아카이브되어 정확한 구현 방식을 알기 어려운 상황이었습니다.

발생 원인

NameError: name 'generate_chk' is not defined 에러는 말 그대로 generate_chk라는 이름의 함수가 스크립트 어디에도 정의되어 있지 않기 때문에 발생합니다.

  • 원본 코드에서는 requests, base64, hashlib 모듈을 임포트했지만, 이 모듈들 안에 generate_chk 함수는 내장되어 있지 않습니다.
  • 사용자께서는 generate_gjp2 함수를 직접 정의하셨지만, generate_chkgenerate_upload_seed 함수는 정의하지 않으셨습니다.
  • Geometry Dash API와 같은 외부 서비스들은 고유한 인증 및 체크섬(checksum) 로직을 가집니다. generate_chk 함수는 이러한 특정 API의 커스텀 로직(예: XOR 암호화, SHA1 해싱, Base64 인코딩 등을 조합한 체크섬 생성)을 구현하기 위해 필요한 함수입니다. API 문서가 이 함수의 호출 시그니처만 제공하고 실제 구현 코드는 제공하지 않거나, 사용자가 직접 구현해야 하는 부분이었을 가능성이 큽니다.

해결 방법 코드 예시

이 에러를 해결하기 위해서는 generate_chk 함수와 그에 필요한 generate_upload_seed 함수를 직접 스크립트에 정의해주어야 합니다. Geometry Dash API의 CHK 생성 로직은 다소 복잡하며, 보통 XOR 암호화와 SHA1 해싱, 그리고 문자열 조작을 포함합니다. 다음은 NameError를 해결하기 위한 기본적인 구조와 함께, 일반적인 GD API CHK 생성 로직을 간략화하여 구현한 예시입니다. 실제 GD API와 완벽하게 호환되려면 Geometry Dash 커뮤니티나 다른 오픈소스 GD API 클라이언트의 구현을 참조하는 것이 좋습니다.

에러 발생 코드 (일부)

# ... (생략) ...

data = {
    # ... (다른 데이터 필드) ...
    "levelString": levelString,
    "seed2": generate_chk(key="41274", values=[generate_upload_seed(levelString)], salt="xI25fpAapCQg"), # <-- 여기서 에러 발생
    "secret": "Wmfd2893gb7"
}

# ... (생략) ...

수정된 코드 예시 (함수 정의 추가)

다음은 generate_upload_seedgenerate_chk 함수를 추가하여 NameError를 해결하는 코드입니다. 실제 Geometry Dash의 CHK 로직을 반영하기 위해 필요한 라이브러리(예: zlib)를 임포트하고, 알려진 로직을 기반으로 함수를 구현합니다.

import requests
import base64
import hashlib  # sha1() lives there
import zlib     # Geometry Dash levelString 압축/해제에 사용될 수 있음 (필요시)

user = input("What is your username?")
accid = input("What is your Account ID?")
passwd = input("What is your password?")
lname = input ("What is the Level name?")
coin = input("How many coins are there?")
stars = input("How many stars do you want?")

def generate_gjp2(password: str = passwd, salt: str = "mI29fmAnxgTs") -> str:
    password += salt
    hash_val = hashlib.sha1(password.encode()).hexdigest()
    return hash_val

# --- NameError 해결을 위한 함수 정의 시작 ---

def generate_upload_seed(level_string: str) -> str:
    # Geometry Dash API는 보통 levelString을 base64 디코딩 후 zlib 압축 해제합니다.
    # 여기서는 seed 값을 생성하기 위해 levelString 자체를 사용하거나,
    # Geometry Dash API의 특정 seed 생성 로직(예: 간단한 인코딩)을 따를 수 있습니다.
    # 정확한 로직은 GD API 버전에 따라 다를 수 있으므로, 관련 커뮤니티를 참고하세요.
    return level_string # 간단한 예시. 실제로는 더 복잡한 처리 필요.

def generate_chk(key: str, values: list[str], salt: str) -> str:
    # Geometry Dash API의 CHK(Checksum) 생성 로직은 복잡하며,
    # key, values, salt를 조합하고 특정 XOR 연산과 SHA1 해싱을 거칩니다.
    # 다음은 NameError 해결을 위한 기본적인 구조와 GD API의 알려진 로직을
    # 부분적으로 반영한 예시입니다. 완벽한 호환을 위해서는 추가적인 조사가 필요합니다.
    
    # 1. values 리스트의 모든 항목을 문자열로 연결
    combined_values = "".join(values)
    
    # 2. CHK 생성에 사용되는 고유한 키 조합 (일반적으로 GD API에 고정된 값)
    #    원본 질문의 salt와 동일한 값 또는 다른 고정 키를 사용합니다.
    #    Geometry Dash API는 'secret' 파라미터와는 별개로 CHK 생성에
    #    특정 내부 'secret' 키를 사용하는 경우가 많습니다.
    #    여기서는 질문에 명시된 salt 값을 재활용합니다.
    secret_for_chk = salt # 또는 'xI25fpAapCQg'와 같은 고정 값
    
    # 3. 핵심 문자열 생성 (GD API의 특정 규칙에 따라 조합)
    #    일반적으로 key + combined_values + secret_for_chk 순서로 조합합니다.
    raw_string_for_hash = f"{key}{combined_values}{secret_for_chk}"
    
    # 4. SHA1 해싱
    hashed_value = hashlib.sha1(raw_string_for_hash.encode()).hexdigest()
    
    # 5. 해싱된 값에 특정 XOR 연산 적용 (Geometry Dash CHK의 특징)
    #    이 부분은 GD API 버전에 따라 다를 수 있으며, 특정 상수와 해싱 결과의
    #    각 문자를 XOR하는 방식이 흔합니다. (예: 0xBA, 0xCE, 0xAF, 0xA3 등)
    #    예시를 위해 알려진 GD CHK 로직 중 하나인 0xCAF3 상수 사용을 가정합니다.
    xor_constant = 0xCAF3 # 실제 Geometry Dash API에 사용되는 특정 상수
    
    final_chk_chars = []
    # 해싱된 문자열의 각 바이트에 대해 XOR 연산을 수행합니다.
    for char_code in hashed_value.encode('latin-1'): # 'latin-1'은 바이트-문자열 맵핑에 적합
        final_chk_chars.append(chr(char_code ^ xor_constant))
    
    # 6. 최종 CHK 문자열 반환
    return "".join(final_chk_chars)

# --- NameError 해결을 위한 함수 정의 끝 ---

levelString = "H4sIAAAAAAAAC6WQwQ3DIAxFF3IlfxsIUU6ZIQP8AbJChy_GPSZqpF7-A4yfDOfhXcCiNMIqnVYrgYQl8rDwBTZCVbkQRI3oVHbiDU6F2jMF_lesl4q4kw2PJMbovxLBQxTpM3-I6q0oHmXjzx7N0240cu5w0UBNtESRkblevSLHjh8nTubmYJZ2MvMrEITEN0gEJMxlLiMZ28frmj"

data = {
    "gameVersion": 22,
    "accountID": accid,
    "gjp": generate_gjp2(password=passwd), # 'hash' 변수가 전역 범위에 없으므로 함수 호출로 변경
    "userName": user,
    "levelID": 0,
    "levelName": lname,
    "levelDesc": "Q3Vyc2VkIGxldmVsIG55ZWghaGVoIGhlaCBhbnl3YXkgaXRzIGEgdmVyeSBicm9rZW4gbGV2ZWwgaSBzZW50IGEgcmVxdWVzdCB0byByb2Igc2VydmVyIHRocm91Z2ggcHl0aG9uIGxvbA",
    "levelVersion": "-47577473775738573",
    "levelLength": 48483845738573486574873869465947694,
    "audioTrack": 0,
    "auto": 0,
    "password": 314159,
    "original": 55610687,
    "twoPlayer": 0,
    "songID": 839583504693858468444987694,
    "objects": 1,
    "coins": coin,
    "requestedStars": stars,
    "unlisted": 0,
    "ldm": 0,
    "levelString": levelString,
    "seed2": generate_chk(key="41274", values=[generate_upload_seed(levelString)], salt="xI25fpAapCQg"), # NameError 해결!
    "secret": "Wmfd2893gb7"
}

headers = {
    "User-Agent": ""
}

url = "http://www.boomlings.com/database/uploadGJLevel21.php"

req = requests.post(url=url, data=data, headers=headers)
print(req.text)

참고:generate_chk 함수는 Geometry Dash API의 CHK 생성 로직을 간략화하여 구현한 예시입니다. 실제 Geometry Dash API는 버전별로 CHK 생성 로직이 미묘하게 다를 수 있으며, 더 복잡한 문자열 처리와 XOR 연산, 그리고 특정 상수 값을 사용합니다. 완벽하게 동작하는 구현을 원하시면, Geometry Dash 관련 오픈소스 프로젝트나 커뮤니티에서 제공하는 최신 CHK 생성 로직을 참고하시길 강력히 권장합니다.

향후 예방을 위한 팁

  • 외부 API 문서 철저히 확인: 외부 API를 사용할 때는 공식 문서나 신뢰할 수 있는 개발 가이드를 통해 필요한 모든 함수와 그 구현 방식을 정확히 확인하세요. 특히 커스텀 암호화나 체크섬 로직은 구현 세부 사항까지 확인해야 합니다.
  • 지원 중단된 문서 사용 시 주의: 아카이브되거나 더 이상 지원되지 않는 문서는 내용이 최신 API와 맞지 않거나, 구현에 필요한 중요한 정보가 누락될 수 있으므로 주의하여 사용해야 합니다.
  • 사용 전 함수 정의 확인: 코드를 작성할 때, 어떤 함수를 호출하기 전에 해당 함수가 스크립트 내에 정의되어 있거나, 올바르게 임포트되었는지 항상 확인하는 습관을 들이세요. IDE나 린터(Linter)의 도움을 받는 것도 좋습니다.
  • 에러 메시지 적극 활용: NameError와 같은 에러 메시지는 문제가 된 정확한 ‘이름’을 알려줍니다. 또한 Python은 Did you mean: 'generate_gjp2'?와 같이 관련성이 있을 법한 이름을 힌트로 제공하기도 합니다. 이러한 힌트를 통해 문제가 된 이름이 정의되지 않았음을 인지하고, 혹시 오타가 있었는지 또는 필요한 함수 정의가 빠졌는지 파악하는 데 활용할 수 있습니다.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다