Forráskód Böngészése

Merge branch 'main' of https://github.com/fosrl/pangolin

Milo Schwartz 8 hónapja
szülő
commit
84e118d1fa

+ 11 - 0
bruno/Sites/Get Site.bru

@@ -0,0 +1,11 @@
+meta {
+  name: Get Site
+  type: http
+  seq: 2
+}
+
+get {
+  url: http://localhost:3000/api/v1/org/theorg/sites/mexican-mole-lizard-windy
+  body: none
+  auth: none
+}

+ 1711 - 360
server/db/names.json

@@ -1,360 +1,1711 @@
-[
-    "Cape Fox",
-    "Short-Beaked Echidna",
-    "Platypus",
-    "Arctic Ground Squirrel",
-    "Black-Tailed Prairie Dog",
-    "Franklin's Ground Squirrel",
-    "Golden-Mantled Ground Squirrel",
-    "Groundhog",
-    "Yellow-Bellied Marmot",
-    "Eastern Mole",
-    "Pink Fairy Armadillo",
-    "Star-Nosed Mole",
-    "Smooth-Coated Otter",
-    "Degu",
-    "Meadow Vole",
-    "Campbell's Dwarf Hamster",
-    "Fat Sand Rat",
-    "Striped Ground Squirrel",
-    "Syrian Hamster",
-    "Common Wombat",
-    "Greater Bilby",
-    "Marsupial Mole",
-    "Numbat",
-    "Southern Hairy-Nosed Wombat",
-    "American Badger",
-    "Little Blue Penguin",
-    "Giant Armadillo",
-    "Eastern Long-Beaked Echidna",
-    "Screaming Hairy Armadillo",
-    "Chinese Hamster",
-    "Roborovski Hamster",
-    "Djungarian Hamster",
-    "Indian Desert Jird",
-    "Great Gerbil",
-    "Plains Rat",
-    "Big-Headed Mole-Rat",
-    "Cape Ground Squirrel",
-    "Colorado Chipmunk",
-    "Alpine Chipmunk",
-    "Cliff Chipmunk",
-    "Hoary Marmot",
-    "Himalayan Marmot",
-    "Olympic Marmot",
-    "San Joaquin Antelope Squirrel",
-    "Gunnison's Prairie Dog",
-    "California Ground Squirrel",
-    "White-Tailed Prairie Dog",
-    "Spotted Ground Squirrel",
-    "Uinta Ground Squirrel",
-    "Columbian Ground Squirrel",
-    "Richardson's Ground Squirrel",
-    "European Ground Squirrel",
-    "Speckled Ground Squirrel",
-    "Broad-Footed Mole",
-    "European Mole",
-    "Sunda Pangolin",
-    "Desert Rosy Boa",
-    "Desert Tortoise",
-    "Brahminy Blind Snake",
-    "Eastern Hognose Snake",
-    "Saharan Horned Viper",
-    "Gopher Snake",
-    "Scarlet Kingsnake",
-    "Eastern Pine Snake",
-    "Eastern Coral Snake",
-    "Naked Mole-Rat",
-    "Mud Snake",
-    "Barbados Threadsnake",
-    "Arabian Sand Boa",
-    "Japanese Badger",
-    "Rainbow Snake",
-    "Red-Eyed Crocodile Skink",
-    "Texas Coral Snake",
-    "Glossy Snake",
-    "Oriental Wolf Snake",
-    "Hog Badger",
-    "Mongolian Gerbil",
-    "Damaraland Mole-Rat",
-    "Steppe Polecat",
-    "Woma Python",
-    "Southern Hognose Snake",
-    "Asian Badger",
-    "Giant Girdled Lizard",
-    "Common Vole",
-    "Bank Vole",
-    "Chinese Ferret-Badger",
-    "Desert Grassland Whiptail Lizard",
-    "Rough Earth Snake",
-    "Thirteen-Lined Ground Squirrel",
-    "Southern Three-Banded Armadillo",
-    "Slowworm",
-    "Siberian Chipmunk",
-    "Round-Tailed Ground Squirrel",
-    "Pygmy Rabbit",
-    "Pied Kingfisher",
-    "Northern Short-Tailed Shrew ",
-    "Northern Pika",
-    "Nine-Banded Armadillo",
-    "Nile Monitor",
-    "Lowland Streaked Tenrec",
-    "Lowland Paca",
-    "Long-Nosed Bandicoot",
-    "Long-Eared Jerboa",
-    "Idaho Ground Squirrel",
-    "Ground Pangolin",
-    "Great Plains Rat Snake",
-    "Gopher Tortoise",
-    "Giant Pangolin",
-    "European Hedgehog",
-    "European Hamster",
-    "Common Box Turtle",
-    "Brown Rat",
-    "Bog Turtle",
-    "Bengal Fox",
-    "American Alligator",
-    "Aardvark",
-    "Olm",
-    "Tiger salamander",
-    "Chinese giant salamander",
-    "Spotted salamander",
-    "Blue-spotted salamander",
-    "Eastern worm snake",
-    "Deinagkistrodon",
-    "Northern crested newt",
-    "Barred tiger salamander",
-    "Rainbow bee-eater",
-    "Sunbeam Snake",
-    "Sandfish Skink",
-    "Mexican Mole Lizard",
-    "Tarbagan marmot",
-    "Black-Headed Python",
-    "Vancouver Island Marmot",
-    "Bothrochilus",
-    "Western Box Turtle",
-    "Long-toed salamander",
-    "Fat-Tailed Gerbil",
-    "Mexican Prairie Dog",
-    "Marbled salamander",
-    "Bandy-Bandy",
-    "Smooth Earth Snake",
-    "Boodie",
-    "Zebra-Tailed Lizard",
-    "White-headed langur",
-    "Javan Ferret-Badger",
-    "Southwestern Blackhead Snake",
-    "Malagasy Giant Rat",
-    "Big Hairy Armadillo",
-    "Camas pocket gopher",
-    "Woodland vole",
-    "Lesser Egyptian jerboa",
-    "Little Brown Skink",
-    "Plains pocket gopher",
-    "Alaska marmot",
-    "Gray marmot",
-    "Louisiana waterthrush",
-    "Ord's kangaroo rat",
-    "North American least shrew",
-    "Western rosella",
-    "Northwestern salamander",
-    "Acrochordus granulatus",
-    "Kowari",
-    "Anilius",
-    "Gastrophryne carolinensis",
-    "Yellow mud turtle",
-    "Plateau pika",
-    "Steppe lemming",
-    "American shrew mole",
-    "Calabar python",
-    "Dermophis mexicanus",
-    "Rufous rat-kangaroo",
-    "Hairy-tailed mole",
-    "Mexican burrowing toad",
-    "Seven-banded armadillo",
-    "Scaphiopus holbrookii",
-    "Asiatic brush-tailed porcupine",
-    "Bolson tortoise",
-    "Common midwife toad",
-    "Ambystoma talpoideum",
-    "Crucifix toad",
-    "Red Hills salamander",
-    "Uperodon taprobanicus",
-    "Plains spadefoot toad",
-    "Spea hammondii",
-    "Puerto Rican crested toad",
-    "Physalaemus nattereri",
-    "Yosemite toad",
-    "Frosted flatwoods salamander",
-    "Striped newt",
-    "Streamside salamander",
-    "Southern red-backed salamander",
-    "Spencer's burrowing frog",
-    "Ringed salamander",
-    "Kaloula baleata",
-    "Uperodon systoma",
-    "Ichthyophis beddomei",
-    "Uperodon globulosus",
-    "Herpele squalostoma",
-    "Ichthyophis mindanaoensis",
-    "Sandhill frog",
-    "Strecker's chorus frog",
-    "Uraeotyphlus oxyurus",
-    "Caecilia nigricans",
-    "Uraeotyphlus menoni",
-    "Savannah forest tree frog",
-    "Uraeotyphlus interruptus",
-    "Rose's rain frog",
-    "Dermophis parviceps",
-    "Leptopelis gramineus",
-    "Rhombophryne coudreaui",
-    "Elachistocleis pearsei",
-    "Hylodes heyeri",
-    "Carphophis vermis",
-    "Anniella pulchra",
-    "Lampropeltis calligaster rhombomaculata",
-    "Xerotyphlops vermicularis",
-    "Iberian worm lizard",
-    "Lytorhynchus diadema",
-    "Micrurus frontalis",
-    "Euprepiophis conspicillata",
-    "Amphisbaena fuliginosa",
-    "Greater earless lizard",
-    "Afrotyphlops schlegelii",
-    "Texas lined snake",
-    "Atractaspis branchi",
-    "Calamaria gervaisii",
-    "Brachyurophis fasciolatus",
-    "Brongersma's worm snake",
-    "Letheobia simonii",
-    "Grypotyphlops acutus",
-    "Acontias breviceps",
-    "Reticulate worm snake",
-    "Trinidad worm snake",
-    "Amphisbaena microcephala",
-    "Lerista labialis",
-    "Flathead worm snake",
-    "Mertens's worm lizard",
-    "Elegant worm snake",
-    "Iranian worm snake",
-    "Pernambuco worm snake",
-    "Crest-tailed mulgara",
-    "Southern long-nosed armadillo",
-    "Greater fairy armadillo",
-    "Steppe pika",
-    "Black-capped marmot",
-    "Armored rat",
-    "Giant mole-rat",
-    "Montane vole",
-    "Oldfield mouse",
-    "Southeastern pocket gopher",
-    "Long-tailed vole",
-    "Greater naked-tailed armadillo",
-    "Common mole-rat",
-    "Philippine porcupine",
-    "Milne-Edwards's sifaka",
-    "Townsend's mole",
-    "Giant golden mole",
-    "Daurian pika",
-    "Cape golden mole",
-    "Yellow-faced pocket gopher",
-    "Indian gerbil",
-    "Plains viscacha rat",
-    "Red tree vole",
-    "Middle East blind mole-rat",
-    "Mountain paca",
-    "Pallas's pika",
-    "Bicolored shrew",
-    "Cape mole-rat",
-    "Cascade golden-mantled ground squirrel",
-    "Unstriped ground squirrel",
-    "Townsend's vole",
-    "Yellow ground squirrel",
-    "Desert pocket gopher",
-    "Bunny rat",
-    "Washington ground squirrel",
-    "Mole-like rice tenrec",
-    "Greater mole-rat",
-    "Hottentot golden mole",
-    "Plains pocket mouse",
-    "Cheesman's gerbil",
-    "Judean Mountains blind mole-rat",
-    "Chisel-toothed kangaroo rat",
-    "Rough-haired golden mole",
-    "Southeastern shrew",
-    "California pocket mouse",
-    "Coruro",
-    "Merriam's shrew",
-    "Long-tailed mole",
-    "Orange leaf-nosed bat",
-    "South African pouched mouse",
-    "Selous's mongoose",
-    "Ash-grey mouse",
-    "Russet ground squirrel",
-    "Gulf Coast kangaroo rat",
-    "Olive-backed pocket mouse",
-    "Northeast African mole-rat",
-    "San Diego pocket mouse",
-    "Nelson's pocket mouse",
-    "Geoffroy's horseshoe bat",
-    "Narrow-faced kangaroo rat",
-    "Chilean rock rat",
-    "R\u00fcppell's horseshoe bat",
-    "Long-tailed pocket mouse",
-    "Aztec mouse",
-    "Western mouse",
-    "Felten's myotis",
-    "Akodon azarae",
-    "Talas tuco-tuco",
-    "Upper Galilee Mountains blind mole-rat",
-    "Pearson's tuco-tuco",
-    "Mount Carmel blind mole-rat",
-    "Plethobasus cyphyus",
-    "Long-Nosed Snake",
-    "Russian Desman",
-    "Texas Blind Snake",
-    "Florida Box Turtle",
-    "Lesser Bandicoot Rat",
-    "Bush Rat",
-    "Six-Lined Racerunner",
-    "Eastern Bearded Dragon",
-    "Lesser Antillean Iguana",
-    "Eastern Mud Turtle",
-    "Slender Glass Lizard",
-    "Scarlet Snake",
-    "Natal Multimammate Mouse",
-    "Mountain Beaver",
-    "Bobak Marmot",
-    "Kirtland's Snake",
-    "Pine Woods Snake",
-    "Western Whiptail",
-    "Boxelder bug",
-    "Porcellio scaber",
-    "German cockroach",
-    "Forficula auricularia",
-    "Anisolabis maritima",
-    "Trigoniulus corallinus",
-    "Sinea diadema",
-    "Black imported fire ant",
-    "Scutigera coleoptrata",
-    "Mastigoproctus giganteus",
-    "Dermacentor andersoni",
-    "Deathstalker",
-    "Larinioides cornutus",
-    "Cheiracanthium inclusum",
-    "Latrodectus hesperus",
-    "Scytodes thoracica",
-    "Atypus affinis",
-    "Illacme plenipes",
-    "Ommatoiulus moreleti",
-    "Narceus americanus",
-    "Madagascar hissing cockroach",
-    "Labidura riparia",
-    "Forficula smyrnensis",
-    "Argentine ant",
-    "Texas leafcutter ant",
-    "Brachypelma klaasi",
-    "Western Blind Snake",
-    "Desert Box Turtle",
-    "African Striped Weasel"
-]
+{
+    "descriptors": [
+        "abandoned",
+        "able",
+        "absolute",
+        "adorable",
+        "adventurous",
+        "academic",
+        "acceptable",
+        "acclaimed",
+        "accomplished",
+        "accurate",
+        "aching",
+        "acidic",
+        "acrobatic",
+        "active",
+        "actual",
+        "adept",
+        "admirable",
+        "admired",
+        "adolescent",
+        "adorable",
+        "adored",
+        "advanced",
+        "afraid",
+        "affectionate",
+        "aged",
+        "aggravating",
+        "aggressive",
+        "agile",
+        "agitated",
+        "agonizing",
+        "agreeable",
+        "ajar",
+        "alarmed",
+        "alarming",
+        "alert",
+        "alienated",
+        "alive",
+        "all",
+        "altruistic",
+        "amazing",
+        "ambitious",
+        "ample",
+        "amused",
+        "amusing",
+        "anchored",
+        "ancient",
+        "angelic",
+        "angry",
+        "anguished",
+        "animated",
+        "annual",
+        "another",
+        "antique",
+        "anxious",
+        "any",
+        "apprehensive",
+        "appropriate",
+        "apt",
+        "arctic",
+        "arid",
+        "aromatic",
+        "artistic",
+        "ashamed",
+        "assured",
+        "astonishing",
+        "athletic",
+        "attached",
+        "attentive",
+        "attractive",
+        "austere",
+        "authentic",
+        "authorized",
+        "automatic",
+        "avaricious",
+        "average",
+        "aware",
+        "awesome",
+        "awful",
+        "awkward",
+        "babyish",
+        "bad",
+        "back",
+        "baggy",
+        "bare",
+        "barren",
+        "basic",
+        "beautiful",
+        "belated",
+        "beloved",
+        "beneficial",
+        "better",
+        "best",
+        "bewitched",
+        "big",
+        "big-hearted",
+        "biodegradable",
+        "bite-sized",
+        "bitter",
+        "black",
+        "black-and-white",
+        "bland",
+        "blank",
+        "blaring",
+        "bleak",
+        "blind",
+        "blissful",
+        "blond",
+        "blue",
+        "blushing",
+        "bogus",
+        "boiling",
+        "bold",
+        "bony",
+        "boring",
+        "bossy",
+        "both",
+        "bouncy",
+        "bountiful",
+        "bowed",
+        "brave",
+        "breakable",
+        "brief",
+        "bright",
+        "brilliant",
+        "brisk",
+        "broken",
+        "bronze",
+        "brown",
+        "bruised",
+        "bubbly",
+        "bulky",
+        "bumpy",
+        "buoyant",
+        "burdensome",
+        "burly",
+        "bustling",
+        "busy",
+        "buttery",
+        "buzzing",
+        "calculating",
+        "calm",
+        "candid",
+        "canine",
+        "capital",
+        "carefree",
+        "careful",
+        "careless",
+        "caring",
+        "cautious",
+        "cavernous",
+        "celebrated",
+        "charming",
+        "cheap",
+        "cheerful",
+        "cheery",
+        "chief",
+        "chilly",
+        "chubby",
+        "circular",
+        "classic",
+        "clean",
+        "clear",
+        "clear-cut",
+        "clever",
+        "close",
+        "closed",
+        "cloudy",
+        "clueless",
+        "clumsy",
+        "cluttered",
+        "coarse",
+        "cold",
+        "colorful",
+        "colorless",
+        "colossal",
+        "comfortable",
+        "common",
+        "compassionate",
+        "competent",
+        "complete",
+        "complex",
+        "complicated",
+        "composed",
+        "concerned",
+        "concrete",
+        "confused",
+        "conscious",
+        "considerate",
+        "constant",
+        "content",
+        "conventional",
+        "cooked",
+        "cool",
+        "cooperative",
+        "coordinated",
+        "corny",
+        "corrupt",
+        "costly",
+        "courageous",
+        "courteous",
+        "crafty",
+        "crazy",
+        "creamy",
+        "creative",
+        "creepy",
+        "criminal",
+        "crisp",
+        "critical",
+        "crooked",
+        "crowded",
+        "cruel",
+        "crushing",
+        "cuddly",
+        "cultivated",
+        "cultured",
+        "cumbersome",
+        "curly",
+        "curvy",
+        "cute",
+        "cylindrical",
+        "damaged",
+        "damp",
+        "dangerous",
+        "dapper",
+        "daring",
+        "darling",
+        "dark",
+        "dazzling",
+        "dead",
+        "deadly",
+        "deafening",
+        "dear",
+        "dearest",
+        "decent",
+        "decimal",
+        "decisive",
+        "deep",
+        "defenseless",
+        "defensive",
+        "defiant",
+        "deficient",
+        "definite",
+        "definitive",
+        "delayed",
+        "delectable",
+        "delicious",
+        "delightful",
+        "delirious",
+        "demanding",
+        "dense",
+        "dental",
+        "dependable",
+        "dependent",
+        "descriptive",
+        "deserted",
+        "detailed",
+        "determined",
+        "devoted",
+        "different",
+        "difficult",
+        "digital",
+        "diligent",
+        "dim",
+        "dimpled",
+        "dimwitted",
+        "direct",
+        "disastrous",
+        "discrete",
+        "disfigured",
+        "disgusting",
+        "disloyal",
+        "dismal",
+        "distant",
+        "downright",
+        "dreary",
+        "dirty",
+        "disguised",
+        "dishonest",
+        "dismal",
+        "distant",
+        "distinct",
+        "distorted",
+        "dizzy",
+        "dopey",
+        "doting",
+        "double",
+        "downright",
+        "drab",
+        "drafty",
+        "dramatic",
+        "dreary",
+        "droopy",
+        "dry",
+        "dual",
+        "dull",
+        "dutiful",
+        "each",
+        "eager",
+        "earnest",
+        "early",
+        "easy",
+        "easy-going",
+        "ecstatic",
+        "edible",
+        "educated",
+        "elaborate",
+        "elastic",
+        "elated",
+        "elderly",
+        "electric",
+        "elegant",
+        "elementary",
+        "elliptical",
+        "embarrassed",
+        "embellished",
+        "eminent",
+        "emotional",
+        "empty",
+        "enchanted",
+        "enchanting",
+        "energetic",
+        "enlightened",
+        "enormous",
+        "enraged",
+        "entire",
+        "envious",
+        "equal",
+        "equatorial",
+        "essential",
+        "esteemed",
+        "ethical",
+        "euphoric",
+        "even",
+        "evergreen",
+        "everlasting",
+        "every",
+        "evil",
+        "exalted",
+        "excellent",
+        "exemplary",
+        "exhausted",
+        "excitable",
+        "excited",
+        "exciting",
+        "exotic",
+        "expensive",
+        "experienced",
+        "expert",
+        "extraneous",
+        "extroverted",
+        "extra-large",
+        "extra-small",
+        "fabulous",
+        "failing",
+        "faint",
+        "fair",
+        "faithful",
+        "fake",
+        "false",
+        "familiar",
+        "famous",
+        "fancy",
+        "fantastic",
+        "far",
+        "faraway",
+        "far-flung",
+        "far-off",
+        "fast",
+        "fat",
+        "fatal",
+        "fatherly",
+        "favorable",
+        "favorite",
+        "fearful",
+        "fearless",
+        "feisty",
+        "feline",
+        "female",
+        "feminine",
+        "few",
+        "fickle",
+        "filthy",
+        "fine",
+        "finished",
+        "firm",
+        "first",
+        "firsthand",
+        "fitting",
+        "fixed",
+        "flaky",
+        "flamboyant",
+        "flashy",
+        "flat",
+        "flawed",
+        "flawless",
+        "flickering",
+        "flimsy",
+        "flippant",
+        "flowery",
+        "fluffy",
+        "fluid",
+        "flustered",
+        "focused",
+        "fond",
+        "foolhardy",
+        "foolish",
+        "forceful",
+        "forked",
+        "formal",
+        "forsaken",
+        "forthright",
+        "fortunate",
+        "fragrant",
+        "frail",
+        "frank",
+        "frayed",
+        "free",
+        "French",
+        "fresh",
+        "frequent",
+        "friendly",
+        "frightened",
+        "frightening",
+        "frigid",
+        "frilly",
+        "frizzy",
+        "frivolous",
+        "front",
+        "frosty",
+        "frozen",
+        "frugal",
+        "fruitful",
+        "full",
+        "fumbling",
+        "functional",
+        "funny",
+        "fussy",
+        "fuzzy",
+        "gargantuan",
+        "gaseous",
+        "general",
+        "generous",
+        "gentle",
+        "genuine",
+        "giant",
+        "giddy",
+        "gigantic",
+        "gifted",
+        "giving",
+        "glamorous",
+        "glaring",
+        "glass",
+        "gleaming",
+        "gleeful",
+        "glistening",
+        "glittering",
+        "gloomy",
+        "glorious",
+        "glossy",
+        "glum",
+        "golden",
+        "good",
+        "good-natured",
+        "gorgeous",
+        "graceful",
+        "gracious",
+        "grand",
+        "grandiose",
+        "granular",
+        "grateful",
+        "grave",
+        "gray",
+        "great",
+        "greedy",
+        "green",
+        "gregarious",
+        "grim",
+        "grimy",
+        "gripping",
+        "grizzled",
+        "gross",
+        "grotesque",
+        "grouchy",
+        "grounded",
+        "growing",
+        "growling",
+        "grown",
+        "grubby",
+        "gruesome",
+        "grumpy",
+        "guilty",
+        "gullible",
+        "gummy",
+        "hairy",
+        "half",
+        "handmade",
+        "handsome",
+        "handy",
+        "happy",
+        "happy-go-lucky",
+        "hard",
+        "hard-to-find",
+        "harmful",
+        "harmless",
+        "harmonious",
+        "harsh",
+        "hasty",
+        "hateful",
+        "haunting",
+        "healthy",
+        "heartfelt",
+        "hearty",
+        "heavenly",
+        "heavy",
+        "hefty",
+        "helpful",
+        "helpless",
+        "hidden",
+        "hideous",
+        "high",
+        "high-level",
+        "hilarious",
+        "hoarse",
+        "hollow",
+        "homely",
+        "honest",
+        "honorable",
+        "honored",
+        "hopeful",
+        "horrible",
+        "hospitable",
+        "hot",
+        "huge",
+        "humble",
+        "humiliating",
+        "humming",
+        "humongous",
+        "hungry",
+        "hurtful",
+        "husky",
+        "icky",
+        "icy",
+        "ideal",
+        "idealistic",
+        "identical",
+        "idle",
+        "idiotic",
+        "idolized",
+        "ignorant",
+        "ill",
+        "illegal",
+        "ill-fated",
+        "ill-informed",
+        "illiterate",
+        "illustrious",
+        "imaginary",
+        "imaginative",
+        "immaculate",
+        "immaterial",
+        "immediate",
+        "immense",
+        "impassioned",
+        "impeccable",
+        "impartial",
+        "imperfect",
+        "imperturbable",
+        "impish",
+        "impolite",
+        "important",
+        "impossible",
+        "impractical",
+        "impressionable",
+        "impressive",
+        "improbable",
+        "impure",
+        "inborn",
+        "incomparable",
+        "incompatible",
+        "incomplete",
+        "inconsequential",
+        "incredible",
+        "indelible",
+        "inexperienced",
+        "indolent",
+        "infamous",
+        "infantile",
+        "infatuated",
+        "inferior",
+        "infinite",
+        "informal",
+        "innocent",
+        "insecure",
+        "insidious",
+        "insignificant",
+        "insistent",
+        "instructive",
+        "insubstantial",
+        "intelligent",
+        "intent",
+        "intentional",
+        "interesting",
+        "internal",
+        "international",
+        "intrepid",
+        "ironclad",
+        "irresponsible",
+        "irritating",
+        "itchy",
+        "jaded",
+        "jagged",
+        "jam-packed",
+        "jaunty",
+        "jealous",
+        "jittery",
+        "joint",
+        "jolly",
+        "jovial",
+        "joyful",
+        "joyous",
+        "jubilant",
+        "judicious",
+        "juicy",
+        "jumbo",
+        "junior",
+        "jumpy",
+        "juvenile",
+        "kaleidoscopic",
+        "keen",
+        "key",
+        "kind",
+        "kindhearted",
+        "kindly",
+        "klutzy",
+        "knobby",
+        "knotty",
+        "knowledgeable",
+        "knowing",
+        "known",
+        "kooky",
+        "kosher",
+        "lame",
+        "lanky",
+        "large",
+        "last",
+        "lasting",
+        "late",
+        "lavish",
+        "lawful",
+        "lazy",
+        "leading",
+        "lean",
+        "leafy",
+        "left",
+        "legal",
+        "legitimate",
+        "light",
+        "lighthearted",
+        "likable",
+        "likely",
+        "limited",
+        "limp",
+        "limping",
+        "linear",
+        "lined",
+        "liquid",
+        "little",
+        "live",
+        "lively",
+        "livid",
+        "loathsome",
+        "lone",
+        "lonely",
+        "long",
+        "long-term",
+        "loose",
+        "lopsided",
+        "lost",
+        "loud",
+        "lovable",
+        "lovely",
+        "loving",
+        "low",
+        "loyal",
+        "lucky",
+        "lumbering",
+        "luminous",
+        "lumpy",
+        "lustrous",
+        "luxurious",
+        "mad",
+        "made-up",
+        "magnificent",
+        "majestic",
+        "major",
+        "male",
+        "mammoth",
+        "married",
+        "marvelous",
+        "masculine",
+        "massive",
+        "mature",
+        "meager",
+        "mealy",
+        "mean",
+        "measly",
+        "meaty",
+        "medical",
+        "mediocre",
+        "medium",
+        "meek",
+        "mellow",
+        "melodic",
+        "memorable",
+        "menacing",
+        "merry",
+        "messy",
+        "metallic",
+        "mild",
+        "milky",
+        "mindless",
+        "miniature",
+        "minor",
+        "minty",
+        "miserable",
+        "miserly",
+        "misguided",
+        "misty",
+        "mixed",
+        "modern",
+        "modest",
+        "moist",
+        "monstrous",
+        "monthly",
+        "monumental",
+        "moral",
+        "mortified",
+        "motherly",
+        "motionless",
+        "mountainous",
+        "muddy",
+        "muffled",
+        "multicolored",
+        "mundane",
+        "murky",
+        "mushy",
+        "musty",
+        "muted",
+        "mysterious",
+        "naive",
+        "narrow",
+        "nasty",
+        "natural",
+        "naughty",
+        "nautical",
+        "near",
+        "neat",
+        "necessary",
+        "needy",
+        "negative",
+        "neglected",
+        "negligible",
+        "neighboring",
+        "nervous",
+        "new",
+        "next",
+        "nice",
+        "nifty",
+        "nimble",
+        "nippy",
+        "nocturnal",
+        "noisy",
+        "nonstop",
+        "normal",
+        "notable",
+        "noted",
+        "noteworthy",
+        "novel",
+        "noxious",
+        "numb",
+        "nutritious",
+        "nutty",
+        "obedient",
+        "obese",
+        "oblong",
+        "oily",
+        "oblong",
+        "obvious",
+        "occasional",
+        "odd",
+        "oddball",
+        "offbeat",
+        "offensive",
+        "official",
+        "old",
+        "old-fashioned",
+        "only",
+        "open",
+        "optimal",
+        "optimistic",
+        "opulent",
+        "orange",
+        "orderly",
+        "organic",
+        "ornate",
+        "ornery",
+        "ordinary",
+        "original",
+        "other",
+        "our",
+        "outlying",
+        "outgoing",
+        "outlandish",
+        "outrageous",
+        "outstanding",
+        "oval",
+        "overcooked",
+        "overdue",
+        "overjoyed",
+        "overlooked",
+        "palatable",
+        "pale",
+        "paltry",
+        "parallel",
+        "parched",
+        "partial",
+        "passionate",
+        "past",
+        "pastel",
+        "peaceful",
+        "peppery",
+        "perfect",
+        "perfumed",
+        "periodic",
+        "perky",
+        "personal",
+        "pertinent",
+        "pesky",
+        "pessimistic",
+        "petty",
+        "phony",
+        "physical",
+        "piercing",
+        "pink",
+        "pitiful",
+        "plain",
+        "plaintive",
+        "plastic",
+        "playful",
+        "pleasant",
+        "pleased",
+        "pleasing",
+        "plump",
+        "plush",
+        "polished",
+        "polite",
+        "political",
+        "pointed",
+        "pointless",
+        "poised",
+        "poor",
+        "popular",
+        "portly",
+        "posh",
+        "positive",
+        "possible",
+        "potable",
+        "powerful",
+        "powerless",
+        "practical",
+        "precious",
+        "present",
+        "prestigious",
+        "pretty",
+        "precious",
+        "previous",
+        "pricey",
+        "prickly",
+        "primary",
+        "prime",
+        "pristine",
+        "private",
+        "prize",
+        "probable",
+        "productive",
+        "profitable",
+        "profuse",
+        "proper",
+        "proud",
+        "prudent",
+        "punctual",
+        "pungent",
+        "puny",
+        "pure",
+        "purple",
+        "pushy",
+        "putrid",
+        "puzzled",
+        "puzzling",
+        "quaint",
+        "qualified",
+        "quarrelsome",
+        "quarterly",
+        "queasy",
+        "querulous",
+        "questionable",
+        "quick",
+        "quick-witted",
+        "quiet",
+        "quintessential",
+        "quirky",
+        "quixotic",
+        "quizzical",
+        "radiant",
+        "ragged",
+        "rapid",
+        "rare",
+        "rash",
+        "raw",
+        "recent",
+        "reckless",
+        "rectangular",
+        "ready",
+        "real",
+        "realistic",
+        "reasonable",
+        "red",
+        "reflecting",
+        "regal",
+        "regular",
+        "reliable",
+        "relieved",
+        "remarkable",
+        "remorseful",
+        "remote",
+        "repentant",
+        "required",
+        "respectful",
+        "responsible",
+        "repulsive",
+        "revolving",
+        "rewarding",
+        "rich",
+        "rigid",
+        "right",
+        "ringed",
+        "ripe",
+        "roasted",
+        "robust",
+        "rosy",
+        "rotating",
+        "rotten",
+        "rough",
+        "round",
+        "rowdy",
+        "royal",
+        "rubbery",
+        "rundown",
+        "ruddy",
+        "rude",
+        "runny",
+        "rural",
+        "rusty",
+        "sad",
+        "safe",
+        "salty",
+        "same",
+        "sandy",
+        "sane",
+        "sarcastic",
+        "sardonic",
+        "satisfied",
+        "scaly",
+        "scarce",
+        "scared",
+        "scary",
+        "scented",
+        "scholarly",
+        "scientific",
+        "scornful",
+        "scratchy",
+        "scrawny",
+        "second",
+        "secondary",
+        "second-hand",
+        "secret",
+        "self-assured",
+        "self-reliant",
+        "selfish",
+        "sentimental",
+        "separate",
+        "serene",
+        "serious",
+        "serpentine",
+        "several",
+        "severe",
+        "shabby",
+        "shadowy",
+        "shady",
+        "shallow",
+        "shameful",
+        "shameless",
+        "sharp",
+        "shimmering",
+        "shiny",
+        "shocked",
+        "shocking",
+        "shoddy",
+        "short",
+        "short-term",
+        "showy",
+        "shrill",
+        "shy",
+        "sick",
+        "silent",
+        "silky",
+        "silly",
+        "silver",
+        "similar",
+        "simple",
+        "simplistic",
+        "sinful",
+        "single",
+        "sizzling",
+        "skeletal",
+        "skinny",
+        "sleepy",
+        "slight",
+        "slim",
+        "slimy",
+        "slippery",
+        "slow",
+        "slushy",
+        "small",
+        "smart",
+        "smoggy",
+        "smooth",
+        "smug",
+        "snappy",
+        "snarling",
+        "sneaky",
+        "sniveling",
+        "snoopy",
+        "sociable",
+        "soft",
+        "soggy",
+        "solid",
+        "somber",
+        "some",
+        "spherical",
+        "sophisticated",
+        "sore",
+        "sorrowful",
+        "soulful",
+        "soupy",
+        "sour",
+        "Spanish",
+        "sparkling",
+        "sparse",
+        "specific",
+        "spectacular",
+        "speedy",
+        "spicy",
+        "spiffy",
+        "spirited",
+        "spiteful",
+        "splendid",
+        "spotless",
+        "spotted",
+        "spry",
+        "square",
+        "squeaky",
+        "squiggly",
+        "stable",
+        "staid",
+        "stained",
+        "stale",
+        "standard",
+        "starchy",
+        "stark",
+        "starry",
+        "steep",
+        "sticky",
+        "stiff",
+        "stimulating",
+        "stingy",
+        "stormy",
+        "straight",
+        "strange",
+        "steel",
+        "strict",
+        "strident",
+        "striking",
+        "striped",
+        "strong",
+        "studious",
+        "stunning",
+        "stupendous",
+        "stupid",
+        "sturdy",
+        "stylish",
+        "subdued",
+        "submissive",
+        "substantial",
+        "subtle",
+        "suburban",
+        "sudden",
+        "sugary",
+        "sunny",
+        "super",
+        "superb",
+        "superficial",
+        "superior",
+        "supportive",
+        "sure-footed",
+        "surprised",
+        "suspicious",
+        "svelte",
+        "sweaty",
+        "sweet",
+        "sweltering",
+        "swift",
+        "sympathetic",
+        "tall",
+        "talkative",
+        "tame",
+        "tan",
+        "tangible",
+        "tart",
+        "tasty",
+        "tattered",
+        "taut",
+        "tedious",
+        "teeming",
+        "tempting",
+        "tender",
+        "tense",
+        "tepid",
+        "terrible",
+        "terrific",
+        "testy",
+        "thankful",
+        "that",
+        "these",
+        "thick",
+        "thin",
+        "third",
+        "thirsty",
+        "this",
+        "thorough",
+        "thorny",
+        "those",
+        "thoughtful",
+        "threadbare",
+        "thrifty",
+        "thunderous",
+        "tidy",
+        "tight",
+        "timely",
+        "tinted",
+        "tiny",
+        "tired",
+        "torn",
+        "total",
+        "tough",
+        "traumatic",
+        "treasured",
+        "tremendous",
+        "tragic",
+        "trained",
+        "tremendous",
+        "triangular",
+        "tricky",
+        "trifling",
+        "trim",
+        "trivial",
+        "troubled",
+        "true",
+        "trusting",
+        "trustworthy",
+        "trusty",
+        "truthful",
+        "tubby",
+        "turbulent",
+        "twin",
+        "ugly",
+        "ultimate",
+        "unacceptable",
+        "unaware",
+        "uncomfortable",
+        "uncommon",
+        "unconscious",
+        "understated",
+        "unequaled",
+        "uneven",
+        "unfinished",
+        "unfit",
+        "unfolded",
+        "unfortunate",
+        "unhappy",
+        "unhealthy",
+        "uniform",
+        "unimportant",
+        "unique",
+        "united",
+        "unkempt",
+        "unknown",
+        "unlawful",
+        "unlined",
+        "unlucky",
+        "unnatural",
+        "unpleasant",
+        "unrealistic",
+        "unripe",
+        "unruly",
+        "unselfish",
+        "unsightly",
+        "unsteady",
+        "unsung",
+        "untidy",
+        "untimely",
+        "untried",
+        "untrue",
+        "unused",
+        "unusual",
+        "unwelcome",
+        "unwieldy",
+        "unwilling",
+        "unwitting",
+        "unwritten",
+        "upbeat",
+        "upright",
+        "upset",
+        "urban",
+        "usable",
+        "used",
+        "useful",
+        "useless",
+        "utilized",
+        "utter",
+        "vacant",
+        "vague",
+        "vain",
+        "valid",
+        "valuable",
+        "vapid",
+        "variable",
+        "vast",
+        "velvety",
+        "venerated",
+        "vengeful",
+        "verifiable",
+        "vibrant",
+        "vicious",
+        "victorious",
+        "vigilant",
+        "vigorous",
+        "villainous",
+        "violet",
+        "violent",
+        "virtual",
+        "virtuous",
+        "visible",
+        "vital",
+        "vivacious",
+        "vivid",
+        "voluminous",
+        "wan",
+        "warlike",
+        "warm",
+        "warmhearted",
+        "warped",
+        "wary",
+        "wasteful",
+        "watchful",
+        "waterlogged",
+        "watery",
+        "wavy",
+        "wealthy",
+        "weak",
+        "weary",
+        "webbed",
+        "wee",
+        "weekly",
+        "weepy",
+        "weighty",
+        "weird",
+        "welcome",
+        "well-documented",
+        "well-groomed",
+        "well-informed",
+        "well-lit",
+        "well-made",
+        "well-off",
+        "well-to-do",
+        "well-worn",
+        "wet",
+        "which",
+        "whimsical",
+        "whirlwind",
+        "whispered",
+        "white",
+        "whole",
+        "whopping",
+        "wicked",
+        "wide",
+        "wide-eyed",
+        "wiggly",
+        "wild",
+        "willing",
+        "wilted",
+        "winding",
+        "windy",
+        "winged",
+        "wiry",
+        "wise",
+        "witty",
+        "wobbly",
+        "woeful",
+        "wonderful",
+        "wooden",
+        "woozy",
+        "wordy",
+        "worldly",
+        "worn",
+        "worried",
+        "worrisome",
+        "worse",
+        "worst",
+        "worthless",
+        "worthwhile",
+        "worthy",
+        "wrathful",
+        "wretched",
+        "writhing",
+        "wrong",
+        "wry",
+        "yawning",
+        "yearly",
+        "yellow",
+        "yellowish",
+        "young",
+        "youthful",
+        "yummy",
+        "zany",
+        "zealous",
+        "zesty",
+        "zigzag"
+    ],
+    "animals": [
+        "Cape Fox",
+        "Short-Beaked Echidna",
+        "Platypus",
+        "Arctic Ground Squirrel",
+        "Black-Tailed Prairie Dog",
+        "Franklin's Ground Squirrel",
+        "Golden-Mantled Ground Squirrel",
+        "Groundhog",
+        "Yellow-Bellied Marmot",
+        "Eastern Mole",
+        "Pink Fairy Armadillo",
+        "Star-Nosed Mole",
+        "Smooth-Coated Otter",
+        "Degu",
+        "Meadow Vole",
+        "Campbell's Dwarf Hamster",
+        "Fat Sand Rat",
+        "Striped Ground Squirrel",
+        "Syrian Hamster",
+        "Common Wombat",
+        "Greater Bilby",
+        "Marsupial Mole",
+        "Numbat",
+        "Southern Hairy-Nosed Wombat",
+        "American Badger",
+        "Little Blue Penguin",
+        "Giant Armadillo",
+        "Eastern Long-Beaked Echidna",
+        "Screaming Hairy Armadillo",
+        "Chinese Hamster",
+        "Roborovski Hamster",
+        "Djungarian Hamster",
+        "Indian Desert Jird",
+        "Great Gerbil",
+        "Plains Rat",
+        "Big-Headed Mole-Rat",
+        "Cape Ground Squirrel",
+        "Colorado Chipmunk",
+        "Alpine Chipmunk",
+        "Cliff Chipmunk",
+        "Hoary Marmot",
+        "Himalayan Marmot",
+        "Olympic Marmot",
+        "San Joaquin Antelope Squirrel",
+        "Gunnison's Prairie Dog",
+        "California Ground Squirrel",
+        "White-Tailed Prairie Dog",
+        "Spotted Ground Squirrel",
+        "Uinta Ground Squirrel",
+        "Columbian Ground Squirrel",
+        "Richardson's Ground Squirrel",
+        "European Ground Squirrel",
+        "Speckled Ground Squirrel",
+        "Broad-Footed Mole",
+        "European Mole",
+        "Sunda Pangolin",
+        "Desert Rosy Boa",
+        "Desert Tortoise",
+        "Brahminy Blind Snake",
+        "Eastern Hognose Snake",
+        "Saharan Horned Viper",
+        "Gopher Snake",
+        "Scarlet Kingsnake",
+        "Eastern Pine Snake",
+        "Eastern Coral Snake",
+        "Naked Mole-Rat",
+        "Mud Snake",
+        "Barbados Threadsnake",
+        "Arabian Sand Boa",
+        "Japanese Badger",
+        "Rainbow Snake",
+        "Red-Eyed Crocodile Skink",
+        "Texas Coral Snake",
+        "Glossy Snake",
+        "Oriental Wolf Snake",
+        "Hog Badger",
+        "Mongolian Gerbil",
+        "Damaraland Mole-Rat",
+        "Steppe Polecat",
+        "Woma Python",
+        "Southern Hognose Snake",
+        "Asian Badger",
+        "Giant Girdled Lizard",
+        "Common Vole",
+        "Bank Vole",
+        "Chinese Ferret-Badger",
+        "Desert Grassland Whiptail Lizard",
+        "Rough Earth Snake",
+        "Thirteen-Lined Ground Squirrel",
+        "Southern Three-Banded Armadillo",
+        "Slowworm",
+        "Siberian Chipmunk",
+        "Round-Tailed Ground Squirrel",
+        "Pygmy Rabbit",
+        "Pied Kingfisher",
+        "Northern Short-Tailed Shrew ",
+        "Northern Pika",
+        "Nine-Banded Armadillo",
+        "Nile Monitor",
+        "Lowland Streaked Tenrec",
+        "Lowland Paca",
+        "Long-Nosed Bandicoot",
+        "Long-Eared Jerboa",
+        "Idaho Ground Squirrel",
+        "Ground Pangolin",
+        "Great Plains Rat Snake",
+        "Gopher Tortoise",
+        "Giant Pangolin",
+        "European Hedgehog",
+        "European Hamster",
+        "Common Box Turtle",
+        "Brown Rat",
+        "Bog Turtle",
+        "Bengal Fox",
+        "American Alligator",
+        "Aardvark",
+        "Olm",
+        "Tiger salamander",
+        "Chinese giant salamander",
+        "Spotted salamander",
+        "Blue-spotted salamander",
+        "Eastern worm snake",
+        "Deinagkistrodon",
+        "Northern crested newt",
+        "Barred tiger salamander",
+        "Rainbow bee-eater",
+        "Sunbeam Snake",
+        "Sandfish Skink",
+        "Mexican Mole Lizard",
+        "Tarbagan marmot",
+        "Black-Headed Python",
+        "Vancouver Island Marmot",
+        "Bothrochilus",
+        "Western Box Turtle",
+        "Long-toed salamander",
+        "Fat-Tailed Gerbil",
+        "Mexican Prairie Dog",
+        "Marbled salamander",
+        "Bandy-Bandy",
+        "Smooth Earth Snake",
+        "Boodie",
+        "Zebra-Tailed Lizard",
+        "White-headed langur",
+        "Javan Ferret-Badger",
+        "Southwestern Blackhead Snake",
+        "Malagasy Giant Rat",
+        "Big Hairy Armadillo",
+        "Camas pocket gopher",
+        "Woodland vole",
+        "Lesser Egyptian jerboa",
+        "Little Brown Skink",
+        "Plains pocket gopher",
+        "Alaska marmot",
+        "Gray marmot",
+        "Louisiana waterthrush",
+        "Ord's kangaroo rat",
+        "North American least shrew",
+        "Western rosella",
+        "Northwestern salamander",
+        "Acrochordus granulatus",
+        "Kowari",
+        "Anilius",
+        "Gastrophryne carolinensis",
+        "Yellow mud turtle",
+        "Plateau pika",
+        "Steppe lemming",
+        "American shrew mole",
+        "Calabar python",
+        "Dermophis mexicanus",
+        "Rufous rat-kangaroo",
+        "Hairy-tailed mole",
+        "Mexican burrowing toad",
+        "Seven-banded armadillo",
+        "Scaphiopus holbrookii",
+        "Asiatic brush-tailed porcupine",
+        "Bolson tortoise",
+        "Common midwife toad",
+        "Ambystoma talpoideum",
+        "Crucifix toad",
+        "Red Hills salamander",
+        "Uperodon taprobanicus",
+        "Plains spadefoot toad",
+        "Spea hammondii",
+        "Puerto Rican crested toad",
+        "Physalaemus nattereri",
+        "Yosemite toad",
+        "Frosted flatwoods salamander",
+        "Striped newt",
+        "Streamside salamander",
+        "Southern red-backed salamander",
+        "Spencer's burrowing frog",
+        "Ringed salamander",
+        "Kaloula baleata",
+        "Uperodon systoma",
+        "Ichthyophis beddomei",
+        "Uperodon globulosus",
+        "Herpele squalostoma",
+        "Ichthyophis mindanaoensis",
+        "Sandhill frog",
+        "Strecker's chorus frog",
+        "Uraeotyphlus oxyurus",
+        "Caecilia nigricans",
+        "Uraeotyphlus menoni",
+        "Savannah forest tree frog",
+        "Uraeotyphlus interruptus",
+        "Rose's rain frog",
+        "Dermophis parviceps",
+        "Leptopelis gramineus",
+        "Rhombophryne coudreaui",
+        "Elachistocleis pearsei",
+        "Hylodes heyeri",
+        "Carphophis vermis",
+        "Anniella pulchra",
+        "Lampropeltis calligaster rhombomaculata",
+        "Xerotyphlops vermicularis",
+        "Iberian worm lizard",
+        "Lytorhynchus diadema",
+        "Micrurus frontalis",
+        "Euprepiophis conspicillata",
+        "Amphisbaena fuliginosa",
+        "Greater earless lizard",
+        "Afrotyphlops schlegelii",
+        "Texas lined snake",
+        "Atractaspis branchi",
+        "Calamaria gervaisii",
+        "Brachyurophis fasciolatus",
+        "Brongersma's worm snake",
+        "Letheobia simonii",
+        "Grypotyphlops acutus",
+        "Acontias breviceps",
+        "Reticulate worm snake",
+        "Trinidad worm snake",
+        "Amphisbaena microcephala",
+        "Lerista labialis",
+        "Flathead worm snake",
+        "Mertens's worm lizard",
+        "Elegant worm snake",
+        "Iranian worm snake",
+        "Pernambuco worm snake",
+        "Crest-tailed mulgara",
+        "Southern long-nosed armadillo",
+        "Greater fairy armadillo",
+        "Steppe pika",
+        "Black-capped marmot",
+        "Armored rat",
+        "Giant mole-rat",
+        "Montane vole",
+        "Oldfield mouse",
+        "Southeastern pocket gopher",
+        "Long-tailed vole",
+        "Greater naked-tailed armadillo",
+        "Common mole-rat",
+        "Philippine porcupine",
+        "Milne-Edwards's sifaka",
+        "Townsend's mole",
+        "Giant golden mole",
+        "Daurian pika",
+        "Cape golden mole",
+        "Yellow-faced pocket gopher",
+        "Indian gerbil",
+        "Plains viscacha rat",
+        "Red tree vole",
+        "Middle East blind mole-rat",
+        "Mountain paca",
+        "Pallas's pika",
+        "Bicolored shrew",
+        "Cape mole-rat",
+        "Cascade golden-mantled ground squirrel",
+        "Unstriped ground squirrel",
+        "Townsend's vole",
+        "Yellow ground squirrel",
+        "Desert pocket gopher",
+        "Bunny rat",
+        "Washington ground squirrel",
+        "Mole-like rice tenrec",
+        "Greater mole-rat",
+        "Hottentot golden mole",
+        "Plains pocket mouse",
+        "Cheesman's gerbil",
+        "Judean Mountains blind mole-rat",
+        "Chisel-toothed kangaroo rat",
+        "Rough-haired golden mole",
+        "Southeastern shrew",
+        "California pocket mouse",
+        "Coruro",
+        "Merriam's shrew",
+        "Long-tailed mole",
+        "Orange leaf-nosed bat",
+        "South African pouched mouse",
+        "Selous's mongoose",
+        "Ash-grey mouse",
+        "Russet ground squirrel",
+        "Gulf Coast kangaroo rat",
+        "Olive-backed pocket mouse",
+        "Northeast African mole-rat",
+        "San Diego pocket mouse",
+        "Nelson's pocket mouse",
+        "Geoffroy's horseshoe bat",
+        "Narrow-faced kangaroo rat",
+        "Chilean rock rat",
+        "R\u00fcppell's horseshoe bat",
+        "Long-tailed pocket mouse",
+        "Aztec mouse",
+        "Western mouse",
+        "Felten's myotis",
+        "Akodon azarae",
+        "Talas tuco-tuco",
+        "Upper Galilee Mountains blind mole-rat",
+        "Pearson's tuco-tuco",
+        "Mount Carmel blind mole-rat",
+        "Plethobasus cyphyus",
+        "Long-Nosed Snake",
+        "Russian Desman",
+        "Texas Blind Snake",
+        "Florida Box Turtle",
+        "Lesser Bandicoot Rat",
+        "Bush Rat",
+        "Six-Lined Racerunner",
+        "Eastern Bearded Dragon",
+        "Lesser Antillean Iguana",
+        "Eastern Mud Turtle",
+        "Slender Glass Lizard",
+        "Scarlet Snake",
+        "Natal Multimammate Mouse",
+        "Mountain Beaver",
+        "Bobak Marmot",
+        "Kirtland's Snake",
+        "Pine Woods Snake",
+        "Western Whiptail",
+        "Boxelder bug",
+        "Porcellio scaber",
+        "German cockroach",
+        "Forficula auricularia",
+        "Anisolabis maritima",
+        "Trigoniulus corallinus",
+        "Sinea diadema",
+        "Black imported fire ant",
+        "Scutigera coleoptrata",
+        "Mastigoproctus giganteus",
+        "Dermacentor andersoni",
+        "Deathstalker",
+        "Larinioides cornutus",
+        "Cheiracanthium inclusum",
+        "Latrodectus hesperus",
+        "Scytodes thoracica",
+        "Atypus affinis",
+        "Illacme plenipes",
+        "Ommatoiulus moreleti",
+        "Narceus americanus",
+        "Madagascar hissing cockroach",
+        "Labidura riparia",
+        "Forficula smyrnensis",
+        "Argentine ant",
+        "Texas leafcutter ant",
+        "Brachypelma klaasi",
+        "Western Blind Snake",
+        "Desert Box Turtle",
+        "African Striped Weasel"
+    ]
+}

+ 37 - 0
server/db/names.ts

@@ -0,0 +1,37 @@
+import { fileURLToPath } from 'url';
+import { dirname, join } from 'path';
+import { readFileSync } from 'fs';
+import { db } from '@server/db';
+import { sites } from './schema';
+import { eq, and } from 'drizzle-orm';
+
+// Get the directory name of the current module
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+
+// Load the names from the names.json file
+const file = join(__dirname, 'names.json');
+export const names = JSON.parse(readFileSync(file, 'utf-8'));
+
+export async function getUniqueName(orgId: string): Promise<string> {
+    let loops = 0;
+    while (true) {
+        if (loops > 100) {
+            throw new Error('Could not generate a unique name');
+        }
+
+        const name = generateName();
+        const count = await db.select({ niceId: sites.niceId, orgId: sites.orgId }).from(sites).where(and(eq(sites.niceId, name), eq(sites.orgId, orgId)));
+        if (count.length === 0) {
+            return name;
+        }
+        loops++;
+    }
+}
+
+export function generateName(): string {
+    return (
+        names.descriptors[Math.floor(Math.random() * names.descriptors.length)] + "-" +
+        names.animals[Math.floor(Math.random() * names.animals.length)]
+    ).toLowerCase().replace(/\s/g, '-');
+}

+ 1 - 0
server/db/schema.ts

@@ -12,6 +12,7 @@ export const sites = sqliteTable("sites", {
     orgId: text("orgId").references(() => orgs.orgId, {
         onDelete: "cascade",
     }),
+    niceId: text("niceId"),
     exitNode: integer("exitNode").references(() => exitNodes.exitNodeId, {
         onDelete: "set null",
     }),

+ 6 - 4
server/routers/external.ts

@@ -44,10 +44,12 @@ authenticated.delete("/org/:orgId", verifyOrgAccess, org.deleteOrg);
 
 authenticated.put("/org/:orgId/site", verifyOrgAccess, site.createSite);
 authenticated.get("/org/:orgId/sites", verifyOrgAccess, site.listSites);
-authenticated.get("/site/:siteId", verifySiteAccess, site.getSite);
-authenticated.get("/site/:siteId/roles", verifySiteAccess, site.listSiteRoles);
-authenticated.post("/site/:siteId", verifySiteAccess, site.updateSite);
-authenticated.delete("/site/:siteId", verifySiteAccess, site.deleteSite);
+authenticated.get("/org/:orgId/site/:niceId", verifyOrgAccess, site.getSite);
+
+authenticated.get("/site/siteId/:siteId", verifySiteAccess, site.getSite);
+authenticated.get("/site/siteId/:siteId/roles", verifySiteAccess, site.listSiteRoles);
+authenticated.post("/site/siteId/:siteId", verifySiteAccess, site.updateSite);
+authenticated.delete("/site/siteId/:siteId", verifySiteAccess, site.deleteSite);
 
 authenticated.put(
     "/org/:orgId/site/:siteId/resource",

+ 28 - 6
server/routers/site/createSite.ts

@@ -9,6 +9,7 @@ import fetch from 'node-fetch';
 import { ActionsEnum, checkUserActionPermission } from '@server/auth/actions';
 import logger from '@server/logger';
 import { eq, and } from 'drizzle-orm';
+import { getUniqueName } from '@server/db/names';
 
 const API_BASE_URL = "http://localhost:3000";
 
@@ -24,6 +25,16 @@ const createSiteSchema = z.object({
     subnet: z.string().optional(),
 });
 
+export type GetSiteResponse = {
+    name: string;
+    siteId: number;
+    orgId: string;
+    niceId: string;
+    // niceId: string;
+    // subdomain: string;
+    // subnet: string;
+};
+
 export async function createSite(req: Request, res: Response, next: NextFunction): Promise<any> {
     try {
         // Validate request body
@@ -62,11 +73,15 @@ export async function createSite(req: Request, res: Response, next: NextFunction
             return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have a role'));
         }
 
+        const niceId = await getUniqueName(orgId);
+
+        // TODO: pick a subnet
+
         // Create new site in the database
-        const newSite = await db.insert(sites).values({
+        const [newSite] = await db.insert(sites).values({
             orgId,
             name,
-            subdomain,
+            niceId,
             pubKey,
             subnet,
         }).returning();
@@ -87,26 +102,33 @@ export async function createSite(req: Request, res: Response, next: NextFunction
 
         await db.insert(roleSites).values({
             roleId: superuserRole[0].roleId,
-            siteId: newSite[0].siteId,
+            siteId: newSite.siteId,
         });
 
         if (req.userOrgRoleId != superuserRole[0].roleId) {
             // make sure the user can access the site
             db.insert(userSites).values({
                 userId: req.user?.userId!,
-                siteId: newSite[0].siteId,
+                siteId: newSite.siteId,
             });
         }
 
         return response(res, {
-            data: newSite[0],
+            data: {
+                name: newSite.name,
+                niceId: newSite.niceId,
+                siteId: newSite.siteId,
+                orgId: newSite.orgId,
+                // subdomain: newSite.subdomain,
+                // subnet: newSite.subnet,
+            },
             success: true,
             error: false,
             message: "Site created successfully",
             status: HttpCode.CREATED,
         });
     } catch (error) {
-        logger.error(error);
+        throw error;
         return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
     }
 }

+ 23 - 9
server/routers/site/getSite.ts

@@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from 'express';
 import { z } from 'zod';
 import { db } from '@server/db';
 import { sites } from '@server/db/schema';
-import { eq } from 'drizzle-orm';
+import { eq, and } from 'drizzle-orm';
 import response from "@server/utils/response";
 import HttpCode from '@server/types/HttpCode';
 import createHttpError from 'http-errors';
@@ -11,7 +11,9 @@ import logger from '@server/logger';
 
 // Define Zod schema for request parameters validation
 const getSiteSchema = z.object({
-    siteId: z.string().transform(Number).pipe(z.number().int().positive())
+    siteId: z.string().transform(Number).pipe(z.number().int().positive()).optional(),
+    niceId: z.string().optional(),
+    orgId: z.string().optional(),
 });
 
 export type GetSiteResponse = {
@@ -34,7 +36,7 @@ export async function getSite(req: Request, res: Response, next: NextFunction):
             );
         }
 
-        const { siteId } = parsedParams.data;
+        const { siteId, niceId, orgId } = parsedParams.data;
 
         // Check if the user has permission to list sites
         const hasPermission = await checkUserActionPermission(ActionsEnum.updateSite, req);
@@ -42,11 +44,23 @@ export async function getSite(req: Request, res: Response, next: NextFunction):
             return next(createHttpError(HttpCode.FORBIDDEN, 'User does not have permission to perform this action'));
         }
 
+        let site;
         // Fetch the site from the database
-        const site = await db.select()
-            .from(sites)
-            .where(eq(sites.siteId, siteId))
-            .limit(1);
+        if (siteId) {
+            site = await db.select()
+                .from(sites)
+                .where(eq(sites.siteId, siteId))
+                .limit(1);
+        } else if (niceId && orgId) {
+            site = await db.select()
+                .from(sites)
+                .where(and(eq(sites.niceId, niceId), eq(sites.orgId, orgId)))
+                .limit(1);
+        }
+
+        if (!site) {
+            return next(createHttpError(HttpCode.NOT_FOUND, 'Site not found'));
+        }
 
         if (site.length === 0) {
             return next(
@@ -60,8 +74,8 @@ export async function getSite(req: Request, res: Response, next: NextFunction):
         return response(res, {
             data: {
                 siteId: site[0].siteId,
+                niceId: site[0].niceId,
                 name: site[0].name,
-                subdomain: site[0].subdomain,
                 subnet: site[0].subnet,
             },
             success: true,
@@ -70,7 +84,7 @@ export async function getSite(req: Request, res: Response, next: NextFunction):
             status: HttpCode.OK,
         });
     } catch (error) {
-        logger.error(error);
+        logger.error("Error from getSite: ", error);
         return next(createHttpError(HttpCode.INTERNAL_SERVER_ERROR, "An error occurred..."));
     }
 }

+ 1 - 0
server/routers/site/listSites.ts

@@ -32,6 +32,7 @@ function querySites(orgId: string, accessibleSiteIds: number[]) {
     return db
         .select({
             siteId: sites.siteId,
+            niceId: sites.niceId,
             name: sites.name,
             pubKey: sites.pubKey,
             subnet: sites.subnet,

+ 0 - 0
src/app/[orgId]/sites/[siteId]/appearance/page.tsx → src/app/[orgId]/sites/[niceId]/appearance/page.tsx


+ 5 - 35
src/app/[orgId]/sites/[siteId]/components/create-site.tsx → src/app/[orgId]/sites/[niceId]/components/create-site.tsx

@@ -8,14 +8,6 @@ import { z } from "zod"
 import { cn } from "@/lib/utils"
 import { toast } from "@/hooks/use-toast"
 import { Button, buttonVariants } from "@/components/ui/button"
-import {
-    Command,
-    CommandEmpty,
-    CommandGroup,
-    CommandInput,
-    CommandItem,
-    CommandList,
-} from "@/components/ui/command"
 import {
     Form,
     FormControl,
@@ -26,15 +18,9 @@ import {
     FormMessage,
 } from "@/components/ui/form"
 import { Input } from "@/components/ui/input"
-import {
-    Popover,
-    PopoverContent,
-    PopoverTrigger,
-} from "@/components/ui/popover"
 import { generateKeypair } from "./wireguard-config";
 import React, { useState, useEffect } from "react";
 import { api } from "@/api";
-import { AxiosResponse } from "axios"
 import { useParams } from "next/navigation";
 import { useRouter } from "next/navigation";
 import { Checkbox } from "@app/components/ui/checkbox"
@@ -53,16 +39,6 @@ const accountFormSchema = z.object({
         .max(30, {
             message: "Name must not be longer than 30 characters.",
         }),
-    subdomain: z
-        .string()
-        // cant be too long and cant have spaces or special characters
-        .regex(/^[a-zA-Z0-9-]+$/)
-        .min(2, {
-            message: "Subdomain must be at least 2 characters.",
-        })
-        .max(30, {
-            message: "Subdomain must not be longer than 30 characters.",
-        }),
     method: z.enum(["wg", "newt"]),
 });
 
@@ -99,17 +75,11 @@ export function CreateSiteForm() {
         }
     }, []);
 
-    const name = form.watch("name");
-    useEffect(() => {
-        const subdomain = name.toLowerCase().replace(/\s+/g, "-");
-        form.setValue("subdomain", subdomain, { shouldValidate: true });
-    }, [name, form]);
-
     async function onSubmit(data: AccountFormValues) {
         const res = await api
             .put(`/org/${orgId}/site/`, {
                 name: data.name,
-                subdomain: data.subdomain,
+                // subdomain: data.subdomain,
                 pubKey: keypair?.publicKey,
             })
             .catch((e) => {
@@ -119,9 +89,9 @@ export function CreateSiteForm() {
             });
 
         if (res && res.status === 201) {
-            const siteId = res.data.data.siteId;
+            const niceId = res.data.data.niceId;
             // navigate to the site page
-            router.push(`/${orgId}/sites/${siteId}`);
+            router.push(`/${orgId}/sites/${niceId}`);
         }
     }
 
@@ -161,7 +131,7 @@ sh get-docker.sh`;
                             </FormItem>
                         )}
                     />
-                    <FormField
+                    {/* <FormField
                         control={form.control}
                         name="subdomain"
                         render={({ field }) => (
@@ -176,7 +146,7 @@ sh get-docker.sh`;
                                 <FormMessage />
                             </FormItem>
                         )}
-                    />
+                    /> */}
                     <FormField
                         control={form.control}
                         name="method"

+ 0 - 0
src/app/[orgId]/sites/[siteId]/components/newt-config.tsx → src/app/[orgId]/sites/[niceId]/components/newt-config.tsx


+ 0 - 0
src/app/[orgId]/sites/[siteId]/components/wireguard-config.ts → src/app/[orgId]/sites/[niceId]/components/wireguard-config.ts


+ 0 - 0
src/app/[orgId]/sites/[siteId]/display/page.tsx → src/app/[orgId]/sites/[niceId]/display/page.tsx


+ 20 - 21
src/app/[orgId]/sites/[siteId]/layout.tsx → src/app/[orgId]/sites/[niceId]/layout.tsx

@@ -20,25 +20,25 @@ export const metadata: Metadata = {
 const sidebarNavItems = [
     {
         title: "Profile",
-        href: "/{orgId}/sites/{siteId}",
+        href: "/{orgId}/sites/{niceId}",
     },
     {
         title: "Appearance",
-        href: "/{orgId}/sites/{siteId}/appearance",
+        href: "/{orgId}/sites/{niceId}/appearance",
     },
     {
         title: "Notifications",
-        href: "/{orgId}/sites/{siteId}/notifications",
+        href: "/{orgId}/sites/{niceId}/notifications",
     },
     {
         title: "Display",
-        href: "/{orgId}/sites/{siteId}/display",
+        href: "/{orgId}/sites/{niceId}/display",
     },
 ];
 
 interface SettingsLayoutProps {
     children: React.ReactNode;
-    params: { siteId: string; orgId: string };
+    params: { niceId: string; orgId: string };
 }
 
 export default async function SettingsLayout({
@@ -46,10 +46,10 @@ export default async function SettingsLayout({
     params,
 }: SettingsLayoutProps) {
     let site = null;
-    if (params.siteId !== "create") {
+    if (params.niceId !== "create") {
         try {
             const res = await internal.get<AxiosResponse<GetSiteResponse>>(
-                `/site/${params.siteId}`,
+                `/org/${params.orgId}/site/${params.niceId}`,
                 authCookieHeader(),
             );
             site = res.data.data;
@@ -78,27 +78,26 @@ export default async function SettingsLayout({
             </div>
 
             <div className="mb-4">
-            <Link
-                href={`/${params.orgId}/sites`}
-                className="text-primary font-medium"
-            >
-                <div className="flex items-center gap-0.5 hover:underline">
-                    <ChevronLeft />
-                    <span>View all sites</span>
-                </div>
-            </Link>
+                <Link
+                    href={`/${params.orgId}/sites`}
+                    className="text-primary font-medium"
+                >
+                    <div className="flex items-center gap-0.5 hover:underline">
+                        <ChevronLeft />
+                        <span>View all sites</span>
+                    </div>
+                </Link>
             </div>
 
             <div className="hidden space-y-6 0 pb-16 md:block">
                 <div className="space-y-0.5">
                     <h2 className="text-2xl font-bold tracking-tight">
-                        {params.siteId == "create"
+                        {params.niceId == "create"
                             ? "New Site"
-                            : site?.name + " Settings" || "Site Settings"
-                        }
+                            : site?.name + " Settings" || "Site Settings"}
                     </h2>
                     <p className="text-muted-foreground">
-                        {params.siteId == "create"
+                        {params.niceId == "create"
                             ? "Create a new site"
                             : "Configure the settings on your site: " +
                                   site?.name || ""}
@@ -109,7 +108,7 @@ export default async function SettingsLayout({
                     <aside className="-mx-4 lg:w-1/5">
                         <SidebarNav
                             items={sidebarNavItems}
-                            disabled={params.siteId == "create"}
+                            disabled={params.niceId == "create"}
                         />
                     </aside>
                     <div className="flex-1 lg:max-w-2xl">

+ 0 - 0
src/app/[orgId]/sites/[siteId]/notifications/page.tsx → src/app/[orgId]/sites/[niceId]/notifications/page.tsx


+ 2 - 2
src/app/[orgId]/sites/[siteId]/page.tsx → src/app/[orgId]/sites/[niceId]/page.tsx

@@ -6,9 +6,9 @@ import { CreateSiteForm } from "./components/create-site";
 export default function SettingsProfilePage({
     params,
 }: {
-    params: { siteId: string };
+    params: { niceId: string };
 }) {
-    const isCreateForm = params.siteId === "create";
+    const isCreateForm = params.niceId === "create";
 
     return (
         <div className="space-y-6">

+ 4 - 4
src/components/sidebar-nav.tsx

@@ -17,7 +17,7 @@ export function SidebarNav({ className, items, disabled = false, ...props }: Sid
     const pathname = usePathname();
     const params = useParams();
     const orgId = params.orgId as string;
-    const siteId = params.siteId as string;
+    const niceId = params.niceId as string;
     const resourceId = params.resourceId as string;
 
     return (
@@ -31,11 +31,11 @@ export function SidebarNav({ className, items, disabled = false, ...props }: Sid
         >
             {items.map((item) => (
                 <Link
-                    key={item.href.replace("{orgId}", orgId).replace("{siteId}", siteId).replace("{resourceId}", resourceId)}
-                    href={item.href.replace("{orgId}", orgId).replace("{siteId}", siteId).replace("{resourceId}", resourceId)}
+                    key={item.href.replace("{orgId}", orgId).replace("{niceId}", niceId).replace("{resourceId}", resourceId)}
+                    href={item.href.replace("{orgId}", orgId).replace("{niceId}", niceId).replace("{resourceId}", resourceId)}
                     className={cn(
                         buttonVariants({ variant: "ghost" }),
-                        pathname === item.href.replace("{orgId}", orgId).replace("{siteId}", siteId).replace("{resourceId}", resourceId)
+                        pathname === item.href.replace("{orgId}", orgId).replace("{niceId}", niceId).replace("{resourceId}", resourceId)
                             ? "bg-muted hover:bg-muted"
                             : "hover:bg-transparent hover:underline",
                         "justify-start",