|
|
|
|
@ -102,25 +102,32 @@ except Exception as e: |
|
|
|
|
logging.error(f"Failed to initialize OpenAI client: {e}", exc_info=True) |
|
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
|
|
# Load author backgrounds |
|
|
|
|
# Load author backgrounds into a dictionary for faster lookup |
|
|
|
|
try: |
|
|
|
|
if not os.path.exists(AUTHOR_BACKGROUNDS_FILE): |
|
|
|
|
logging.error(f"Author backgrounds file not found at {AUTHOR_BACKGROUNDS_FILE}") |
|
|
|
|
raise FileNotFoundError(f"Author backgrounds file not found at {AUTHOR_BACKGROUNDS_FILE}") |
|
|
|
|
with open(AUTHOR_BACKGROUNDS_FILE, 'r') as f: |
|
|
|
|
AUTHOR_BACKGROUNDS = json.load(f) |
|
|
|
|
if not isinstance(AUTHOR_BACKGROUNDS, list): |
|
|
|
|
logging.error(f"Invalid format in {AUTHOR_BACKGROUNDS_FILE}: Expected a list, got {type(AUTHOR_BACKGROUNDS)}") |
|
|
|
|
background_list = json.load(f) |
|
|
|
|
if not isinstance(background_list, list): |
|
|
|
|
logging.error(f"Invalid format in {AUTHOR_BACKGROUNDS_FILE}: Expected a list, got {type(background_list)}") |
|
|
|
|
raise ValueError("Author backgrounds must be a list") |
|
|
|
|
for bg in AUTHOR_BACKGROUNDS: |
|
|
|
|
AUTHOR_BACKGROUNDS = {} |
|
|
|
|
for bg in background_list: |
|
|
|
|
if "username" not in bg: |
|
|
|
|
logging.error(f"Invalid entry in {AUTHOR_BACKGROUNDS_FILE}: Missing 'username' key in {bg}") |
|
|
|
|
raise ValueError("Each author background must have a 'username' key") |
|
|
|
|
loaded_usernames = [bg["username"] for bg in AUTHOR_BACKGROUNDS] |
|
|
|
|
username = bg["username"] |
|
|
|
|
if not isinstance(username, str): |
|
|
|
|
logging.error(f"Invalid username type in {AUTHOR_BACKGROUNDS_FILE}: {username} (type: {type(username)})") |
|
|
|
|
raise ValueError("Username must be a string") |
|
|
|
|
cleaned_username = username.strip().lower() |
|
|
|
|
AUTHOR_BACKGROUNDS[cleaned_username] = bg |
|
|
|
|
loaded_usernames = list(AUTHOR_BACKGROUNDS.keys()) |
|
|
|
|
logging.debug(f"Loaded author backgrounds: {loaded_usernames}") |
|
|
|
|
except Exception as e: |
|
|
|
|
logging.error(f"Failed to load author_backgrounds.json: {e}", exc_info=True) |
|
|
|
|
AUTHOR_BACKGROUNDS = [] |
|
|
|
|
AUTHOR_BACKGROUNDS = {} |
|
|
|
|
sys.exit(1) |
|
|
|
|
|
|
|
|
|
def validate_twitter_credentials(author): |
|
|
|
|
@ -205,28 +212,24 @@ def generate_engagement_tweet(author): |
|
|
|
|
persona = author["persona"] |
|
|
|
|
persona_config = PERSONA_CONFIGS.get(persona, PERSONA_CONFIGS["Visionary Editor"]) |
|
|
|
|
|
|
|
|
|
# Case-insensitive lookup for background with whitespace stripping |
|
|
|
|
# Lookup background using a dictionary |
|
|
|
|
username_cleaned = username.strip().lower() |
|
|
|
|
background = {} |
|
|
|
|
available_usernames = [] |
|
|
|
|
for bg in AUTHOR_BACKGROUNDS: |
|
|
|
|
bg_username = bg.get("username") |
|
|
|
|
if bg_username is None: |
|
|
|
|
logging.warning(f"Skipping background entry with missing username: {bg}") |
|
|
|
|
continue |
|
|
|
|
if not isinstance(bg_username, str): |
|
|
|
|
logging.warning(f"Skipping background entry with non-string username: {bg_username} (type: {type(bg_username)})") |
|
|
|
|
continue |
|
|
|
|
bg_username_cleaned = bg_username.strip().lower() |
|
|
|
|
available_usernames.append(bg_username) |
|
|
|
|
logging.debug( |
|
|
|
|
f"Comparing usernames for {username}: " |
|
|
|
|
f"author username (cleaned) = '{username_cleaned}', " |
|
|
|
|
f"background username (cleaned) = '{bg_username_cleaned}'" |
|
|
|
|
) |
|
|
|
|
if bg_username_cleaned == username_cleaned: |
|
|
|
|
background = bg |
|
|
|
|
break |
|
|
|
|
background = AUTHOR_BACKGROUNDS.get(username_cleaned, {}) |
|
|
|
|
|
|
|
|
|
# Debug comparison |
|
|
|
|
available_usernames = list(AUTHOR_BACKGROUNDS.keys()) |
|
|
|
|
if username_cleaned in available_usernames: |
|
|
|
|
logging.debug(f"Direct key check: '{username_cleaned}' found in AUTHOR_BACKGROUNDS keys") |
|
|
|
|
else: |
|
|
|
|
logging.debug(f"Direct key check: '{username_cleaned}' NOT found in AUTHOR_BACKGROUNDS keys") |
|
|
|
|
# Log byte-level comparison for the first available username as a sample |
|
|
|
|
if available_usernames: |
|
|
|
|
sample_key = available_usernames[0] |
|
|
|
|
logging.debug( |
|
|
|
|
f"Byte-level comparison sample: " |
|
|
|
|
f"username_cleaned bytes = {list(username_cleaned.encode('utf-8'))}, " |
|
|
|
|
f"sample background key bytes = {list(sample_key.encode('utf-8'))}" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if not background or "engagement_themes" not in background: |
|
|
|
|
logging.warning( |
|
|
|
|
|