mirror of
https://github.com/tcsenpai/keyfleur.git
synced 2025-06-01 16:20:09 +00:00
First commit
This commit is contained in:
parent
cb15ee49e1
commit
899bf7d7e0
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build
|
||||
*.egg-info
|
93
README.md
Normal file
93
README.md
Normal file
@ -0,0 +1,93 @@
|
||||
# 🌸 Keyfleur
|
||||
|
||||
_Keyfleur_ is a poetic API key generator — blending structure and beauty into every token.
|
||||
Whether you want a delicate **haiku**, a **steampunk sigil**, or a **mythic mantra**,
|
||||
Keyfleur creates keys that are elegant, readable, and never boring.
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Installation
|
||||
|
||||
```bash
|
||||
pip install .
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
## 🚀 CLI Usage
|
||||
|
||||
```bash
|
||||
keyfleur --theme=forest --mode=haiku --count=3
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Description |
|
||||
| --------- | ------------------------------------------- |
|
||||
| `--theme` | The semantic dictionary to draw words from. |
|
||||
| | *(haiku, forest, mythic, sunny, etc.)* |
|
||||
| `--mode` | The structural format of the key. |
|
||||
| | *(haiku, sigil, quartz, mantra, etc.)* |
|
||||
| `--count` | Number of keys to generate. Default is `1`. |
|
||||
|
||||
---
|
||||
|
||||
## ✨ Modes
|
||||
|
||||
| Mode | Description |
|
||||
| --------- | -------------------------------------------------------------- |
|
||||
| `haiku` | A 5-7-5 syllable poetic identifier. |
|
||||
| `lace` | Symmetric structure with mirrored syllables. |
|
||||
| `mirrora` | Reversed syllable pairs (e.g., `im-mi`). |
|
||||
| `rune` | A haiku fused with a time-based symbolic rune. |
|
||||
| `sonnet` | Two-part name with soft romantic cadence. |
|
||||
| `sigil` | Word-number-word combo, evocative of arcane codes. |
|
||||
| `seed` | Short base+hex identifier, suitable for seed values. |
|
||||
| `mantra` | Repetitive and affirming (e.g., `Glow-Glow-Sky`). |
|
||||
| `quartz` | Crystal-inspired symmetrical compound (e.g., `Opal22.22lApO`). |
|
||||
|
||||
---
|
||||
|
||||
## 🌿 Themes
|
||||
|
||||
Themes determine the pool of vocabulary used:
|
||||
|
||||
* `haiku` – melodic invented roots
|
||||
* `nocturnal` – night, shadow, echo
|
||||
* `sunny` – light, warmth, radiance
|
||||
* `floreal` – flowers, petals, blooming
|
||||
* `forest` – leaves, moss, trees
|
||||
* `desert` – dust, sand, mirage
|
||||
* `celestial` – stars, moons, galaxies
|
||||
* `crystalline` – gems, quartz, clarity
|
||||
* `oceanic` – tides, coral, depths
|
||||
* `mythic` – runes, phoenixes, arcane
|
||||
* `library` – ink, scrolls, tomes
|
||||
* `decay` – rust, ash, erosion
|
||||
* `steampunk` – cogs, brass, valves
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Example
|
||||
|
||||
```bash
|
||||
keyfleur --theme=celestial --mode=haiku
|
||||
```
|
||||
|
||||
Might output:
|
||||
|
||||
```
|
||||
Nova-DriftingOrbit-Moonlight
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Use cases
|
||||
|
||||
* Generate poetic API keys or user-facing identifiers
|
||||
* Use in games, lore systems, or design prototypes
|
||||
* Inject elegance into otherwise boring IDs
|
||||
|
||||
---
|
||||
|
||||
Made without a goal
|
1
keyfleur/__init__.py
Normal file
1
keyfleur/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# Keyfleur package
|
201
keyfleur/cli.py
Normal file
201
keyfleur/cli.py
Normal file
@ -0,0 +1,201 @@
|
||||
# keyfleur_poetic_generator.py
|
||||
|
||||
import random
|
||||
|
||||
# === THEME WORDS ===
|
||||
THEMES = {
|
||||
'haiku': [
|
||||
'nyrae','soliv','virel','ethae','omura','lyr','aeli','sirune','nuvia','evara',
|
||||
'halen','ilari','tyrel','elune','kairi','syrel','narun','velia','orune','faeli'
|
||||
],
|
||||
'nocturnal': [
|
||||
'luna','night','star','owl','dusk','twilight','midnight','shade','echo','eclipse',
|
||||
'gloom','moth','raven','void','mist','sleep','howl','nova','quiet','shiver',
|
||||
'dark','silence','phantom','crescent','hollow','dream','veil','crypt','umbra','noir'
|
||||
],
|
||||
'sunny': [
|
||||
'sol','sun','ray','bright','day','dawn','shine','gold','beam','sky',
|
||||
'flare','light','summer','glow','warmth','clear','zenith','haze','amber','bliss',
|
||||
'gleam','glint','sunrise','radiant','beam','halo','lucid','fire','flare','glory'
|
||||
],
|
||||
'floreal': [
|
||||
'rose','lily','petal','bloom','ivy','orchid','daisy','violet','primrose','stem',
|
||||
'pollen','sprout','bud','blossom','flora','camellia','garden','leaf','nectar','thistle',
|
||||
'lavender','tulip','clover','hyacinth','marigold','chrysant','wisteria','magnolia','peony','fern'
|
||||
],
|
||||
'oceanic': [
|
||||
'wave','coral','foam','drift','deep','pearl','tide','gull','salt','whale',
|
||||
'kelp','abyss','current','surf','ocean','marina','shoal','siren','lagoon','shell',
|
||||
'reef','seastar','nautilus','spray','undertow','isle','brine','anchor','swell','ripple'
|
||||
],
|
||||
'crystalline': [
|
||||
'crystal','gem','shard','opal','quartz','glint','ice','snow','frost','facet',
|
||||
'prism','glass','clear','gleam','diamond','shine','mirror','spark','flake','glow',
|
||||
'glacier','amethyst','glisten','translucent','silica','bismuth','halo','chime','lucent','citrine'
|
||||
],
|
||||
'mythic': [
|
||||
'aether','wyrm','oracle','sigil','blade','fable','mythos','grimoire','phoenix','echo',
|
||||
'titan','nymph','elysium','lore','rune','arcane','wyrd','hero','legend','shade',
|
||||
'sphinx','hydra','oblivion','divine','hex','omen','ritual','saga','daemon','prophecy'
|
||||
],
|
||||
'forest': [
|
||||
'moss','bark','deer','grove','tree','fern','owl','leaf','fox','thicket',
|
||||
'pine','birch','root','sap','fungus','log','trail','wild','branch','meadow',
|
||||
'cedar','acorn','willow','glade','lichen','bluff','elm','spruce','hedge','nest'
|
||||
],
|
||||
'desert': [
|
||||
'sand','dune','mirage','sun','dry','camel','cactus','arid','scorch','salt',
|
||||
'wind','dust','stone','haze','burn','sol','flame','crack','barren','sizzle',
|
||||
'ember','serpent','blister','parch','ash','glare','mesa','quartz','sirocco','ridge'
|
||||
],
|
||||
'celestial': [
|
||||
'nova','orbit','comet','moon','star','sol','galaxy','void','pulse','flare',
|
||||
'venus','eclipse','plasma','space','light','sphere','sky','drift','saturn','zero',
|
||||
'nebula','equinox','zenith','meteor','lunar','solstice','mercury','aster','axis','horizon'
|
||||
],
|
||||
'library': [
|
||||
'scroll','ink','book','page','shelf','quiet','dust','study','read','verse',
|
||||
'prose','codex','folio','scribe','script','glyph','letter','note','pen','volume',
|
||||
'archive','index','library','margin','annotation','spine','binding','tome','quill','text'
|
||||
],
|
||||
'decay': [
|
||||
'rot','rust','moss','mold','crack','fade','peel','dust','crumble','ash',
|
||||
'time','void','wilt','droop','filth','wear','flaw','scratch','stain','dull',
|
||||
'brittle','smudge','erode','fracture','debris','decay','fester','grime','soot','relic'
|
||||
],
|
||||
'steampunk': [
|
||||
'gear','steam','cog','brass','pipe','gauge','valve','weld','bolt','clock',
|
||||
'spark','smoke','engine','vane','dial','joint','helm','rivets','boiler','coil',
|
||||
'piston','frame','rotor','socket','vent','torque','copper','chrono','lever','mech'
|
||||
]
|
||||
}
|
||||
|
||||
SOFT_CONS = 'flmnrschv'
|
||||
VOWELS = 'aeiouy'
|
||||
RUNES = ['now+1d','now-2h','dawn','midnight','solstice','infinite','epoch']
|
||||
|
||||
|
||||
def syllable():
|
||||
return random.choice(SOFT_CONS) + random.choice(VOWELS)
|
||||
|
||||
# === MODES ===
|
||||
|
||||
def estimate_syllables(word):
|
||||
if not word or not isinstance(word, str):
|
||||
return 0
|
||||
word = word.lower()
|
||||
vowels = 'aeiouy'
|
||||
count = 0
|
||||
prev_char = ''
|
||||
for char in word:
|
||||
if char in vowels and prev_char not in vowels:
|
||||
count += 1
|
||||
prev_char = char
|
||||
if word.endswith("e") and count > 1:
|
||||
count -= 1
|
||||
return max(1, count)
|
||||
|
||||
def haiku(theme):
|
||||
all_words = [word for words in THEMES.values() for word in words if word]
|
||||
random.shuffle(all_words)
|
||||
|
||||
used_words = set()
|
||||
|
||||
def find_words(target_syllables):
|
||||
result = []
|
||||
total = 0
|
||||
for word in all_words:
|
||||
if not word or word in used_words:
|
||||
continue
|
||||
syll = estimate_syllables(word)
|
||||
if syll == 0:
|
||||
continue
|
||||
if total + syll <= target_syllables:
|
||||
result.append(word.capitalize())
|
||||
used_words.add(word)
|
||||
total += syll
|
||||
if total == target_syllables:
|
||||
break
|
||||
return result if total == target_syllables else []
|
||||
|
||||
line1 = find_words(5)
|
||||
line2 = find_words(7)
|
||||
line3 = find_words(5)
|
||||
|
||||
if not (line1 and line2 and line3):
|
||||
return "incomplete-haiku"
|
||||
|
||||
return "-".join(["".join(line1), "".join(line2), "".join(line3)])
|
||||
|
||||
def lace(theme):
|
||||
roots = THEMES.get(theme, THEMES['haiku'])
|
||||
word = random.choice(roots)
|
||||
mid = syllable()
|
||||
return f"{word}{mid}-{mid[::-1]}{word[::-1]}"
|
||||
|
||||
def mirrora():
|
||||
s = syllable()
|
||||
return f"{s[::-1]}-{s}"
|
||||
|
||||
def rune_key(theme):
|
||||
base = haiku(theme).capitalize()
|
||||
rune = random.choice(RUNES)
|
||||
return f"{base}_{rune}"
|
||||
|
||||
def sonnet(theme):
|
||||
roots = THEMES.get(theme, THEMES['haiku'])
|
||||
return f"{random.choice(roots).capitalize()}{syllable()[:2]}-{random.choice(roots).capitalize()}{syllable()[:2]}"
|
||||
|
||||
def sigil(theme):
|
||||
roots = THEMES.get(theme, THEMES['haiku'])
|
||||
return f"{random.choice(roots).capitalize()}-{random.randint(100,999)}-{random.choice(roots).capitalize()}"
|
||||
|
||||
def seed(theme):
|
||||
roots = THEMES.get(theme, THEMES['haiku'])
|
||||
return f"{random.choice(roots).capitalize()[:4]}-{random.randint(1000,9999):04x}"
|
||||
|
||||
def mantra(theme):
|
||||
word = random.choice(THEMES.get(theme, THEMES['haiku'])).capitalize()
|
||||
return f"{word}-{word}-{random.choice(THEMES[theme]).capitalize()}"
|
||||
|
||||
def quartz(theme):
|
||||
root = random.choice(THEMES.get(theme, THEMES['haiku'])).capitalize()
|
||||
rev = root[::-1][:4]
|
||||
num = str(random.randint(10,99))
|
||||
return f"{root}{num}.{num}{rev}"
|
||||
|
||||
MODES = {
|
||||
'haiku': haiku,
|
||||
'lace': lace,
|
||||
'mirrora': lambda t: mirrora(),
|
||||
'rune': rune_key,
|
||||
'sonnet': sonnet,
|
||||
'sigil': sigil,
|
||||
'seed': seed,
|
||||
'mantra': mantra,
|
||||
'quartz': quartz
|
||||
}
|
||||
|
||||
|
||||
def poetic_key(mode='haiku', theme='haiku'):
|
||||
func = MODES.get(mode, haiku)
|
||||
return func(theme)
|
||||
|
||||
|
||||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description="Keyfleur: generate poetic API keys.")
|
||||
parser.add_argument("--theme", default="haiku", choices=THEMES.keys(), help="Theme for word source")
|
||||
parser.add_argument("--mode", default="haiku", choices=MODES.keys(), help="Poetic structure to use")
|
||||
parser.add_argument("--count", type=int, default=1, help="Number of keys to generate")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
for _ in range(args.count):
|
||||
print(poetic_key(mode=args.mode, theme=args.theme))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
12
pyproject.toml
Normal file
12
pyproject.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[project]
|
||||
name = "keyfleur"
|
||||
version = "0.1.0"
|
||||
description = "Generate poetic API keys with haiku, mythic and crystalline elegance."
|
||||
readme = "README.md"
|
||||
authors = [{ name="Your Name", email="you@example.com" }]
|
||||
license = {text = "MIT"}
|
||||
requires-python = ">=3.7"
|
||||
dependencies = []
|
||||
|
||||
[project.scripts]
|
||||
keyfleur = "keyfleur.cli:main"
|
Loading…
x
Reference in New Issue
Block a user