source code
Here is the source code for all generators utilized for the daily messages from Ethel Cain. Written in python and requires lyricsgenius and a Genius API token
import os
import lyricsgenius
import random
import re
import sys
# ---------------------------------------------------------
# GENIUS TOKEN (set it here)
# ---------------------------------------------------------
GENIUS_ACCESS_TOKEN = "ENTER_TOKEN_HERE"
# Cache file
CACHE_FILE = "ethel_cain_lyrics.txt"
# ---------------------------------------------------------
# Initialize Genius API client
# ---------------------------------------------------------
genius = lyricsgenius.Genius(
GENIUS_ACCESS_TOKEN,
remove_section_headers=True,
skip_non_songs=True,
excluded_terms=["(Remix)", "(Live)"],
timeout=15
)
# Global storage
all_lyrics = ""
words = []
markov = {}
# ---------------------------------------------------------
# Save lyrics to cache
# ---------------------------------------------------------
def save_cache(text):
with open(CACHE_FILE, "w", encoding="utf-8") as f:
f.write(text)
print(f"\nLyrics cached in {CACHE_FILE}\n")
# ---------------------------------------------------------
# Load lyrics from cache
# ---------------------------------------------------------
def load_cache():
global all_lyrics
if os.path.exists(CACHE_FILE):
print(f"\nLoading cached lyrics from {CACHE_FILE}...")
with open(CACHE_FILE, "r", encoding="utf-8") as f:
all_lyrics = f.read()
return True
return False
# ---------------------------------------------------------
# Fetch Ethel Cain lyrics
# ---------------------------------------------------------
def fetch_lyrics(force=False):
global all_lyrics, words, markov
# Try cache first unless forced
if not force and load_cache():
print("Cache loaded successfully.")
else:
print("\nFetching Ethel Cain songs from Genius...")
artist = genius.search_artist("Ethel Cain", max_songs=50)
all_lyrics = ""
for song in artist.songs:
if song.lyrics:
print(f"Collected: {song.title}")
all_lyrics += song.lyrics + "\n"
save_cache(all_lyrics)
# Clean lyrics → word list
clean = re.sub(r"[^a-zA-Z\s]", "", all_lyrics).lower()
words = clean.split()
print(f"\nTotal words collected: {len(words)}")
# Build Markov chain
markov = {}
for i in range(len(words) - 1):
word = words[i]
next_word = words[i + 1]
if word not in markov:
markov[word] = []
markov[word].append(next_word)
print("Markov chain built successfully.\n")
# ---------------------------------------------------------
# Generate a sentence using only her words
# ---------------------------------------------------------
def generate_sentence(length=12):
if not words:
return "Error: No lyrics loaded yet. Choose option 1 first."
word = random.choice(words)
sentence = [word]
for _ in range(length - 1):
if word in markov:
word = random.choice(markov[word])
else:
word = random.choice(words)
sentence.append(word)
return " ".join(sentence)
# ---------------------------------------------------------
# CLI Menu
# ---------------------------------------------------------
def menu():
while True:
print("\n==============================")
print(" Ethel Cain Sentence Maker")
print("==============================")
print("1. Load lyrics (cached or fetch)")
print("2. Force refetch lyrics")
print("3. Generate a sentence")
print("4. Generate multiple sentences")
print("5. Exit")
print("==============================")
choice = input("Choose an option: ").strip()
if choice == "1":
fetch_lyrics(force=False)
elif choice == "2":
fetch_lyrics(force=True)
elif choice == "3":
length = input("Sentence length (default 15): ").strip()
length = int(length) if length.isdigit() else 15
print("\nGenerated sentence:")
print(generate_sentence(length))
elif choice == "4":
count = input("How many sentences? ").strip()
count = int(count) if count.isdigit() else 5
length = input("Sentence length (default 15): ").strip()
length = int(length) if length.isdigit() else 15
print("\nGenerated sentences:\n")
for _ in range(count):
print("-", generate_sentence(length))
elif choice == "5":
print("Goodbye.")
sys.exit(0)
else:
print("Invalid choice. Try again.")
# ---------------------------------------------------------
# Run menu
# ---------------------------------------------------------
if __name__ == "__main__":
menu()
Second generator here which generates sentences taken directly from lyrics, while the above generator takes individual words to generate sentences
import lyricsgenius
import re
import random
# ---------------------------------------------------------
# Insert your Genius API token directly here
# ---------------------------------------------------------
GENIUS_ACCESS_TOKEN = "GENIUS_TOKEN_HERE"
# ---------------------------------------------------------
# Initialize Genius API client
# ---------------------------------------------------------
genius = lyricsgenius.Genius(
GENIUS_ACCESS_TOKEN,
remove_section_headers=True,
skip_non_songs=True,
excluded_terms=["(Remix)", "(Live)"],
timeout=15
)
# Global storage
all_lyrics = ""
sentences = []
# ---------------------------------------------------------
# Fetch lyrics
# ---------------------------------------------------------
def fetch_lyrics():
global all_lyrics, sentences
print("\nFetching Ethel Cain songs from Genius...")
artist = genius.search_artist("Ethel Cain", max_songs=50)
all_lyrics = ""
for song in artist.songs:
if song.lyrics:
print(f"Collected: {song.title}")
all_lyrics += song.lyrics + "\n"
sentences = re.split(r'[.!?]\s+', all_lyrics)
sentences = [s.strip() for s in sentences if len(s.strip()) > 0]
print(f"\nTotal sentences extracted: {len(sentences)}")
# ---------------------------------------------------------
# Generate random sentences
# ---------------------------------------------------------
def generate_random_sentences():
if not sentences:
print("\nNo lyrics loaded yet. Choose option 1 first.")
return
try:
n = int(input("How many random sentences? "))
except ValueError:
print("Invalid number.")
return
print("\nRandom sentences:")
for _ in range(n):
print("-", random.choice(sentences))
# ---------------------------------------------------------
# CLI Menu
# ---------------------------------------------------------
def menu():
while True:
print("\n=== Ethel Cain Sentence Generator ===")
print("1. Fetch lyrics")
print("2. Generate random sentences")
print("3. Show number of extracted sentences")
print("4. Exit")
choice = input("Select an option: ")
if choice == "1":
fetch_lyrics()
elif choice == "2":
generate_random_sentences()
elif choice == "3":
print(f"\nSentences available: {len(sentences)}")
elif choice == "4":
print("Goodbye.")
break
else:
print("Invalid option.")
# ---------------------------------------------------------
# Start CLI
# ---------------------------------------------------------
if __name__ == "__main__":
menu()