code:
[{
    "default" : {
       "default" : {.
           "default" : {.
                "default" : [
                ],
                "climaxing" : [
                ],
				"pregnant" : [
				]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			}
		},
		"male" : {
			"default" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			}
		},
		"female" : {
			"default" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			}
		}
	},
	"pregnant" : {
		"default" : {
			"default" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			}
		},
		"male" : {
			"default" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			}
		},
		"female" : {
			"default" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			}
		}
	},
	"climax" : {
		"default" : {
			"default" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			}
		},
		"male" : {
			"default" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			}
		},
		"female" : {
			"default" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"avian" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"felin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"floran" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"glitch" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"human" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"hylotl" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"novakid" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			},
			"penguin" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climax" : [
				]
			}
		}
	}
},
{
    "default" : {
        "default" : {
            "default" : {
                "default" : [
					"You've got me from behind, I wonder how long you'll go at it~!",
					"Ooh, I'm so horny all of the sudden~! Keep going~!",
					"My ass is red from all this pounding~!",
					"Grab my hips and plow me~!",
					"Put it in my ass!",
					"Unng! Finger my asshole while you fill me up!"
					"Ooooh~! You've found the perfect spot~!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Oh you came already? Let me clean you up~~!"
                ]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
            "avali" : {
                "default" : [
					"Ooooh~~! Your feathers tickle!",
					"So graceful! So rough!",
					"Do you always take your prey from behind~~!"
					"Oh YESS take me like prey!"
                ],
				"pregnant" : [
					"You're so full of eggs, it makes me wet to think about!"
				],
                "climaxing" : [
					"I hope you have your anti-water augment, because we've soaked your pretty feathers fucking me!"
                ]
			},
            "avian" : {
                "default" : [
					"Ooooh~~! Your feathers tickle!",
					"So graceful! So rough!",
					"Do you always take your prey from behind~~!"
                ],
				"pregnant" : [
					"You're so full of eggs, it makes me wet to think about!"
				],
                "climaxing" : [
					"We've soaked your pretty feathers fucking me~~!"
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "ferenox" : {
                "default" : [
					"You know just where to rub me!"
                ],
				"pregnant" : [
					"It feels like a big litter in your belly~!!"
				],
                "climaxing" : [
                ]
			},
            "floran" : {
                "default" : [
					"What's... what's in your pollen?",
					"I've never been this wet before, your nectar is driving me wild!",
					"Your petals are this soaked for me?"
                ],
				"pregnant" : [
					"Your petals are so plump and swollen!"
				],
                "climaxing" : [
					"Your nectar is running everywhere~~"
                ]
			},
            "glitch" : {
                "default" : [
					"Oooohh~ I didn't know you could do that~~!",
					"You're making my pussy tingle~!",
					"Ohmygod! How do you fit me so perfectly? I'm going to c-c-c-cum!",
					"I hope you're waterproof~! I'm about to squirt all over you~!",
					"You didn't tell me you could vibrate~!"
                ],
				"pregnant" : [
					"I can hear the gears in your belly!"
				],
                "climaxing" : [
                ]
			},
            "human" : {
                "default" : [
					"Your belly turns me on so much!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "hylotl" : {
                "default" : [
					"Your fin is rubbing... my asshole~~~!",
					"You're so slippery! I want to slide on top of you next~!"
					"Your fin is rubbing me just right!",
					"Your rod is so slippery and thick! Can we try it in my asshole?",
					"Your scales are hitting all the right places~~~~!"
                ],
				"pregnant" : [
					"I can feel your eggs moving around, you're so full!"
				],
                "climaxing" : [
                ]
			},
            "novakid" : {
                "default" : [
					"O-oh~, your body is so hot against me!",
					"Have you ever had a human girl?"
                ],
				"pregnant" : [
					"Your belly is so hot on my skin!",
					"Your glowing belly is so sexy!"
				],
                "climaxing" : [
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		},
		"male" : {
            "default" : {
                "default" : [
					"You've got me from behind, I wonder how long you can last~!",
					"Ooh, I'm so horny all of the sudden~! Keep going~!",
					"I've wanted this for a long time!",
					"Are you going to empty your load inside me?",
					"Unng! You'd better not pull out!",
					"I'm so wet, you could slip right into my asshole~~!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"O-oh~! You're cumming~! Unng, fill me up~!",
					"It's running out of me!",
					"So much cum! Spray it inside me until it runs out!~",
					"Mmmm! Yes~! Fill up my womb!",
					"Yess I want you to fill my womb!"
                ]
			},
			"apex" : {
				"default" : [
					"It's so big and so thick!!~",
					"Ohmygod! Human cocks aren't this thiiiiiick!",
					"YESS! Stuff me full with your hairy cock!",
					"OH! Yes! You're MY Big Ape!"
				],
				"pregnant" : [
				],
				"climaxing" : [
					"So much hot cum... just for me!",
					"It's so thick and warmm!",
					"OH you're filling me up! Make me carry your little apes!"
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
					"Hng yess! I want to have your chicks!"
				]
			},
            "avian" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Hng yess! I want to have your chicks!"
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "ferenox" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "floran" : {
                "default" : [
					"Ooooh~, your cock tingles",
					"Your scent makes me... it makes me want your cock so badly..."
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Your cum is making me dizzy~!",
					"Your cum tingles! Is it going to make me pregnant?",
					"Plant your seeds inside me!",
					"I want to carry your seedlings!!~~"
                ]
			},
            "glitch" : {
                "default" : [
					"I... I didn't know it could extend like thiiiiiisss!",
					"It's so big... and greasy!",
					"I can feel it twisting inside me!~~~~"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"OH~ This oil... this oil feels so good!",
					"You're squirting your oil down my thighs!",
					"Your oil is so thick and warm!",
					"OH~ That's not just oil... is it.",
					"I hope that's more than just oil, I want you to knock me up~!"
                ]
			},
            "human" : {
                "default" : [
					"Fuck yeah, fill me up!",
					"You're in me just right~!",
					"Are you going to finish in me?"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Oh god yes! Fill me to the brim!",
					"YESSS! Keep cumminnnggggg!",
					"Fill up my womb~~!"
                ]
			},
            "hylotl" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Yesss, give me your milt!"
                ]
			},
            "novakid" : {
                "default" : [
					"Your rod is burning hot inside me~~!",
					"What will... what will happen if you come inside me?",
					"Your cock is making my belly glowwww!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Your spunk is so hot!",
					"Our juices are glowing together~~!",
					"Your cum is lighting up my pussy!!",
					"I can see it glowing in my womb~~!",
					"Steam is coming out! ohhh it feels so good!!!~",
					"I hope you knocked me up! It feels so hot inside me!"
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		},
		"female" : {
            "default" : {
                "default" : [
					"Yes! Pound it into me!",
					"I've been so naughty! Punish me harder~!",
					"Ooh, I'm so horny all of the sudden~! Keep going~!",
					"My thighs are wet with your juices~! I feel so dirty!",
					"Grab my hips and plow me~!",
					"I've wanted this for so long!",
					"I had no idea you were so aggressive~!",
					"Mmmmff~~! Spank me while you do that!~"
                ],
				"pregnant" : [
					"I can feel your pregnant belly against me! I didn't know that would make me so wet!~~"
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
					"Oh! Your grip on me is so strong!",
					"You're so strong, but so soft~!",
					"I can feel your fat pussy rubbing on my ass!",
					"You know how I like it, be rough with me~~!"
				],
				"pregnant" : [
					"Your furry belly is so sexy against me!"
				],
				"climaxing" : [
					"OH! You're gushing all over me!",
					"Your juice is everywhere! It feels so good!",
					"I'm softer than Apex girls.... I hope my pussy is enough for you!",
					"Oh YESS take me! Make me yours!"
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
            "avian" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "ferenox" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "floran" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "glitch" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "human" : {
                "default" : [
					"You're so soft and lovely. I've wanted you all day~~~~!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"You're soaking my asshole... you'd better lick that up!",
					"Save some for when I'm eating your ass!"
                ]
			},
            "hylotl" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "novakid" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Your pussy is steaming hot!"
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		}
	},
	"pregnant" : {
		"default" : {
			"default" : {
				"default" : [
					"E-easy~! Baby-on-board!",
					"I'm ready to burst but I need this so bad~!",
					"Do you like my pregnant pussy?",
					"I get so wet when I'm pregnant... I need you to lap it up!",
					"Can you feel how full I am?"
				],
				"pregnant" : [
					"It's so sexy that we're pregnant together!"
				],
                "climaxing" : [
					"Yes, pull me closer when you cum!"
                ]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
            "avali" : {
                "default" : [
					"You can be rough with me, I'm not carrying eggs!",
					"Your feathers! I'm more ticklish now that I'm pregnant!!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "avian" : {
                "default" : [
					"You can be rough with me, I'm not carrying eggs!",
					"Your feathers! I'm more ticklish now that I'm pregnant!!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "ferenox" : {
                "default" : [
                ],
				"pregnant" : [
					"I wish I could have... a big litter like yoursss~!"
				],
                "climaxing" : [
					"Oh god, your claws are digging into me! It feels so good!"
                ]
			},
            "floran" : {
                "default" : [
					"... even though I'm pregnant, I can't stop thinking about your nectar!"
                ],
				"pregnant" : [
					"Since we got pregnant, your scent has become... intoxicating..."
				],
                "climaxing" : [
					"Your petals feel so good against my pregnant pussy!"
                ]
			},
            "glitch" : {
                "default" : [
					"Yes! Spank my pregnant ass raw with your gears!"
                ],
				"pregnant" : [
					"I'm getting slick with your oil~~!"
				],
                "climaxing" : [
                ]
			},
            "human" : {
                "default" : [
					"I want your soft hands all over my pregnant body!",
					"Does my pregnant belly turn you on?"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "hylotl" : {
                "default" : [
					"Ohgod, your scales are rubbing just right! Don't stop!"
                ],
				"pregnant" : [
					"We're both carrying big clutches!"
				],
                "climaxing" : [
                ]
			},
            "novakid" : {
                "default" : [
					"Your hands are so hot on my belly!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		},
		"male" : {
            "default" : {
                "default" : [
					"Fuck! You're stuffing me so full!",
					"Unload in my pregnant asshole~~!",
					"I'm already pregnant, but I can't get enough cum~!"
					"Being pregnant makes me crave cock!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Mmh~! Fill up my pregnant pussy~!",
					"Your cum is running down my thighs~~~!",
					"Your hot cum is pouring out of me~!",
					"Soon, you'll be able to knock me up~!",
					"Yessss! Please I want to be even more full!"
					"I feel so full, yes~!!"
                ]
			},
			"apex" : {
				"default" : [
					"I need a big ape to fill up my swollen pussy!"
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
            "avian" : {
                "default" : [
					"Your hands feel so soft on my pregnant belly!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "floran" : {
                "default" : [
					"I can feel you wriggling inside me!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"This nectar is... so strong! I need more!"
                ]
			},
            "glitch" : {
                "default" : [
					"It's... it's getting bigger inside me~!"
                ],
				"pregnant" : [
					"Yess! Pump it into my pregnant hole!"
				],
                "climaxing" : [
                ]
			},
            "human" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "hylotl" : {
                "default" : [
					"It's not enough that I'm knocked up, I need your milt!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Your scaly cock is just what I need since I got pregnant!"
                ]
			},
            "novakid" : {
                "default" : [
					"It's almost too hot to touch, but my pregnant pussy needs to be filled~!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Yes! Shoot me full of your hot gases! I'm already knocked up!"
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		},
		"female" : {
            "default" : {
                "default" : [
					"You know... unnnf~... he could get you pregnant, too, if you wanted...",
					"My pregnant ass is wet with your juice~!"
                ],
				"pregnant" : [
				"I can feel your belly against me!"
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
					"We should get pregnant together next time!"
				],
				"pregnant" : [
					"Which of our bellies is bigger?"
				],
				"climaxing" : [
					"You're drenching my thighs!"
				]
			},
			"avali" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
					"I get so horny when I'm pregnant! Does that happen to Avalis?"
				]
			},
            "avian" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"I get so horny when I'm pregnant! Does that happen to Avians?"
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "floran" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "glitch" : {
                "default" : [
                ],
				"pregnant" : [
					"We're bigger in all the same places!"
				],
                "climaxing" : [
                ]
			},
            "human" : {
                "default" : [
					"Do you want him to get you pregnant next?"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "hylotl" : {
                "default" : [
                ],
				"pregnant" : [
					"I'm already carrying babies, but your eggs feel so good!"
				],
                "climaxing" : [
                ]
			},
            "novakid" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		}
	},
	"climax" : {
		"default" : {
			"default" : {
				"default" : [
					"I'm gushing everywhere~~!",
					"Yesssss~~~~~! I'm Cominggg~!",
					"Ohmygodyes don't stop!"
				],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
            "avali" : {
                "default" : [
					"Oh, I'm soaking your feathers!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "avian" : {
                "default" : [
					"Oh, I'm soaking your feathers!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "floran" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "glitch" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "human" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "hylotl" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "novakid" : {
                "default" : [
                ],
				"pregnant" : [
					"I'm coming all over your steaming belly!"
				],
                "climaxing" : [
					"It's like fucking in a sauna!"
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		},
		"male" : {
            "default" : {
                "default" : [
					"Yessss~! Your cock is so good~~ I'm cominggg~!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
					"Oh yes, your ape cock is making me cum!"
				],
				"pregnant" : [
				],
				"climaxing" : [
					"Fill me up with your banana cream!"
				]
			},
			"avali" : {
				"default" : [
					"Your prey is cumming~!"
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
            "avian" : {
                "default" : [
					"I want to lay your eggs!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "floran" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "glitch" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "human" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "hylotl" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "novakid" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		},
		"female" : {
            "default" : {
                "default" : [
					"I'm gushing all over your pussy~! Yesss~!",
					"Ohmygod Yes~! Keep doing that! I'm Cominggg~!"
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
			"apex" : {
				"default" : [
					"Your wet ape pussy is gushing!"
				],
				"pregnant" : [
					"Your hairy belly is so full!"
				],
				"climaxing" : [
					"Your wet ape pussy is gushing!"
				]
			},
			"avali" : {
				"default" : [
					"Oooh~~! Your cloaca is rubbing on my clit!"
				],
				"pregnant" : [
				],
				"climaxing" : [
				]
			},
            "avian" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "felin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "floran" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "glitch" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "human" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "hylotl" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			},
            "novakid" : {
                "default" : [
					"Your cock is red hot! Don't stop!!!~"
                ],
				"pregnant" : [
				],
                "climaxing" : [
					"Yes let's cum together, it's sizzling!"
                ]
			},
            "penguin" : {
                "default" : [
                ],
				"pregnant" : [
				],
                "climaxing" : [
                ]
			}
		}
	}
}]


default: You've got me from behind, I wonder how long you'll go at it~!

default: Ooh, I'm so horny all of the sudden~! Keep going~!

default: I've been so naughty! Punish me harder~!

default: My thighs are wet with your juices~! I feel so dirty!

pregnant: I can feel your pregnant belly against me! I didn't know that would make me so wet!~~

default: You've got me from behind, I wonder how long you can last~!

default: Are you going to empty your load inside me?

default: I'm so wet, you could slip it all the way into my asshole~~!

climaxing: O-oh~! You're cumming~! Unng, fill me up~!

climaxing: So much cum! Spray it inside me until it runs out!~

default:
O-oh~, your body is so hot against me!
Have you ever had a human boy?

pregnant:
Your belly is so hot on my skin!
Your glowing belly is so sexy!

default: What will... what will happen if you come inside me?

climaxing: Steam is coming out! ohhh it feels so good!!!~

climaxing: I hope you knocked me up! It feels so hot inside me!

default: I can feel your fat pussy rubbing on my ass!

default: You know how I like it, be rough with me~~!

climaxing: Your juice is everywhere! It feels so good!

climaxing: I'm softer than Apex girls.... I hope my pussy is enough for you!

default: Ohmygod! Human cocks aren't this thiiiiiick!

default: YESS! Stuff me full with your hairy cock!

climaxing: OH you're filling me up! Make me carry your little apes!

default: Do you always take your prey from behind~~!

climaxing: We've soaked your pretty feathers fucking me~~!

pregnant: You're so full of eggs, it makes me wet to think about!

climaxing: Oh you came already? Let me clean you up~~!

pregnant: It feels like a big litter in your belly~!!

default: I've never been this wet before, your nectar is driving me wild!

default: Your scent makes me... it makes me want your cock so badly...

climaxing: Your cum tingles! Is it going to make me pregnant?

default: Oooohh~ I didn't know you could do that~~!

default: Ohmygod! How do you fit me so perfectly? I'm going to c-c-c-cum!

climaxing: You're squirting your oil down my thighs!

default: I... I didn't know it could extend like thiiiiiisss!

climaxing: I hope that's more than just oil, I want you to knock me up~!

default: You're so soft and lovely. I've wanted you all day~~~~!

climaxing: You're soaking my asshole... you'd better lick that up!

default:
Fuck yeah, fill me up!
You're in me just right~!
Are you going to finish in me?

climaxing:
Oh god yes! Fill me to the brim!
YESSS! Keep cumminnnggggg!
Fill up my ass~~!

default: You're so slippery! I want to slide on top of you next~!

climaxing: Are you... are you putting eggs in me? Ohgod it feels so good... don't stop!

pregnant: I can feel your eggs moving around, you're so full!

default: Your rod is so slippery and thick! Can i taste it?

default: Your scales are hitting all the right places~~~~!

default: I'm ready to burst but I need this so bad~!

default: You know... unnnf~... he could get you pregnant, too, if you wanted...

default: My pregnant ass is wet with your juice~!

default: I'm already pregnant, but I can't get enough cum~!

climaxing:
Mmh~! Fill up my pregnant ass~!
Your cum is running down my thighs~~~!
Your hot cum is pouring out of me~!

default: It's almost too hot to touch, but my pregnant ass needs to be filled~!

climaxing: Yes! Shoot me full of your hot gases! I'm already knocked up!

default: We should get pregnant together next time!

default: I need a big ape to fill up my swollen asshole!

default: You can be rough with me, I'm not carrying eggs!

climaxing: Your feathers! I'm more ticklish now that I'm pregnant!!

pregnant: I get so horny when I'm pregnant! Does that happen to Avian?

default: Your hands feel so soft on my pregnant belly!

default: I get so wet when I'm pregnant... I need you to lap it up!

climaxing: Oh god, your claws are digging into me! It feels so good!

pregnant: I wish I could have... a big litter like yoursss~!

climaxing: Yessss! Please I want to be even more full!

default: ... even though I'm pregnant, I can't stop thinking about your nectar!

climaxing: Your petals feel so good against my pregnant ass!

pregnant: Since we got pregnant, your scent has become... intoxicating...

climaxing: This nectar is... so strong! I need more!

default: Yes! Spank my pregnant ass raw with your gears!

default: I want your soft hands all over my pregnant body!

default: Do you want me to get you pregnant next?

pregnant: It's so sexy that we're pregnant together!

default: Ohgod, your scales are rubbing just right! Don't stop!

climaxing: I'm already carrying babies, but your eggs feel so good!

default: It's not enough that I'm knocked up, I need your milt!

climaxing: Your scaly cock is just what I need since I got pregnant!

default:
I'm gushing everywhere~~!
Yesssss~~~~~! I'm Cominggg~!

default: Yessss~! Your cock is so good~~ I'm cominggg~!

default: I'm gushing all over your pussy~! Yesss~!

default: Ohmygod Yes~! Keep doing that! I'm Cominggg~!

pregnant: I'm coming all over your steaming belly!

license: unknown


default: You're pulling me so tight~! Dig your nails into my scales, lover~!

default: What magnificent poise you demonstrate pumping into me~!

climaxing: Unng, tear into my scales, and inseminate my eggs, lover~!

default: Uunf. How uncouth your barbaric thrusts, yet oh so pleasurable. Mmnh~!

default: Ah~! Mmph~!... You exude such a delightful aroma~!

climaxing: Ahh~!... How can it be that such barbarism feels so good?~

climaxing: Uunh~!... You Florans are insatiable~!...

default: Your member feels so hard against my scales~!...

default: Ah~! The breeding efficiency of a machine~!...

climaxing: Ahh~! Wh- what is this you're injecting into me~?!

default: Mmnh~... Your soft member feels perfect against my scales~!

default: Uunf. Yes~!... Show me what mating is like on Earth~!

climaxing: Ahh~! Yes~! Use me to carry your Human DNA~!

climaxing: Aaahh~! D- Do all Humans carry so much semen~?

default: I- It's so hot~!... Ahn!~ You'll boil me alive~!

climaxing: Uhhnn~!... Ah~! Launch your shinining emissions into me~!

climaxing: A- Ahhh~!... Is this what Novakid semen feels like~?... So hot~!...

default: Ahn~! Yes~!... Let us breed together as animals do~!

default: Mmnh~! Your fur feels absolutely delightful against my scales~!

climaxing: Yes~! May our children all have such fur as yours~!

climaxing: O- Oh~! I feel it~! Release your Apex load inside of me~!

default: Ahh~! Yes!~ Dig your mighty talons into me~!

climaxing: Oooh~!... Yes~! May our children be blessed by your Kluex~!

default: Ummh~! Let us populate the stars with our noble blood~!

default: Ah!~ Yes!~ Fill my womb with beautiful Hylotl DNA~!

climaxing: Mmnh~... I can feel your Hylotl sperm swimming inside of me~!


default: Ah!~ Yes!~ Fill my rectum with beautiful Hylotl DNA~!


climaxing: Yee-haw~! Plant some seeds in my field pard'ner~! Let's create a spark of life~!


code:
[{--// Position: Butterfly. I am the one standing (Actor 1)
    "default" : {--This actor's state. Valid entries are: "default" (having sex), "pregnant" and "climaxing".
        "default" : {--The partner's gender. Valid entries (so far) are "male", "female" or "default" (Basically functions as a wildcard).
            "default" : {--The partner's race. Entries should be obvious; "human", "penguin", etc. Also accepts "default" as a wildcard.
                "default" : [--The partner's state. Same valid entries as first tag. Note: Dialogue for both actors climaxing at once can be tricky to appear in-game, but works.
                    "I am fucking a unspecified gender partner of an unspecified race in the X!"
                ],
                "climaxing" : [
                    "My unspecified gender partner of an unspecified race is cumming!"
                ],
				"pregnant" : [
					"My unspecified gender partner is pregnant!"
				]
			}
		},
		"male" : {
			"avali" : {
				"default" : [
					"I am fucking a male avali in the ass!"
				],
				"climaxing" : [
					"My avali male partner is cumming all over the floor!"
				]
			}
		}
	},
	"pregnant" : {
		"default" : {
			"default" : {
				"default" : [
					"I am fucking a unspecified gender partner of an unspecified race, and i am pregnant!"
				]
			}
		}
	}
},
{--// Position: Butterfly. I am the one being held. (Actor 2)
    "default" : {--This actor's state. Valid entries are: "default" (having sex), "pregnant" and "climaxing".
        "default" : {--The partner's gender. Valid entries (so far) are "male", "female" or "default" (Basically functions as a wildcard).
            "default" : {--The partner's race. Entries should be obvious; "human", "penguin", etc. Also accepts "default" as a wildcard.
                "default" : [--The partner's state. Same valid entries as first tag. Note: Dialogue for both actors climaxing at once can be tricky to appear in-game, but works.
                    "I am being fucked by a unspecified gender partner of an unspecified race in the X!"
                ],
                "climaxing" : [
                    "My unspecified gender partner of an unspecified race is cumming!"
                ],
				"pregnant" : [
					"My unspecified gender partner is pregnant!"
				]
			}
		},
		"male" : {
			"avali" : {
				"default" : [
					"I am being fucked by a male avali in the ass!"
				],
				"climaxing" : [
					"My avali male partner is cumming!"
				]
			}
		}
	},
	"pregnant" : {
		"default" : {
			"default" : {
				"default" : [
					"I am fucking a unspecified gender partner of an unspecified race, and i am pregnant!"
				]
			}
		}
	}
}]


code:
A python script that creates a zip file without timestamp metadata, adding all files and directories in the current working directory into it. Note that some extraction programs may parse the zero byte in the date and time field as December 31st, 1979, while others may interpret it as having no timestamp.

## Usage
`cd` first to the directory to zip before running pycleanzip.
```sh
python3 /path/to/pycleanzip.py -o out.zip
```
`-o` parameter is optional, defaults to `file.zip`.

repo_name: anglekh/pycleanzip


code:
import os
import zipfile
import argparse

argparser = argparse.ArgumentParser("Create a zip file from all the files in the working directory")
argparser.add_argument("-o", action="store", default="file.zip", help="output filename")
base_dir = os.curdir
zip_filename = argparser.parse_args().o

print("creating "+zip_filename+"' and adding '"+base_dir+"' to it")

def strip_zipinfo(zi):
    zi.date_time = (1980,0,0,0,0,0) # The final byte will become 0 after CPython does its bit manipulation
    zi.create_system = 3 # Unix
    zi.external_attr = None # Defaults to ?rw------- on CPython
    if zi.is_dir():
        zi.external_attr = 0o40775 << 16 # drwxrwxr-x, explicit default since CPython doesn't set the directory flag

with zipfile.ZipFile(zip_filename, "x", zipfile.ZIP_DEFLATED, False, 9) as zf:
    path = os.path.normpath(base_dir)
    if path != os.curdir:
        zf.write(path, path)
        print("adding "+path)
    for dirpath, dirnames, filenames in os.walk(base_dir):
        for name in dirnames:
            path = os.path.normpath(os.path.join(dirpath, name))
            zi = zipfile.ZipInfo.from_file(path)
            strip_zipinfo(zi)
            zf.writestr(zi, bytes())
            print("adding "+path)
        for name in filenames:
            path = os.path.normpath(os.path.join(dirpath, name))
            if path != zip_filename and os.path.isfile(path):
                with open(path, "rb") as f:
                    zi = zipfile.ZipInfo.from_file(path)
                    strip_zipinfo(zi)
                    zf.writestr(zi, f.read(), compress_type=zipfile.ZIP_DEFLATED, compresslevel=9)
                    print("adding "+path)


code:
name: alis-site-deploy

on:
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.97.3
    steps:
      - uses: actions/checkout@v2
        with:
          ref: master
      - uses: actions/checkout@v2
        with:
          path: site/deploy/
          ref: gh-pages
      - name: Environment information
        run: |
          uname -a
          lsb_release -a
      - name: Cache hugo resources
        uses: actions/cache@v2
        env:
          cache-name: cache-hugo-resources
        with:
          path: ./resources
          key: ${{ runner.os }}-build-${{ env.cache-name }}
      - name: Install packages (hugo)
        run: |
          wget https://github.com/gohugoio/hugo/releases/download/v${{ env.HUGO_VERSION }}/hugo_extended_${{ env.HUGO_VERSION }}_Linux-64bit.tar.gz
          tar xzf hugo_extended_${{ env.HUGO_VERSION }}_Linux-64bit.tar.gz hugo
          rm hugo_extended_${{ env.HUGO_VERSION }}_Linux-64bit.tar.gz
          chmod +x ./hugo
          sudo mv ./hugo /usr/local/bin
      - name: Echo content (deploy)
        run: |
          ls site/deploy/
      - name: Generate content
        run: |
          cd site/
          hugo gen chromastyles --style=github > themes/alis/assets/syntax.css
          hugo --destination="deploy/" --gc --cleanDestinationDir
      - name: Echo content (deploy)
        run: |
          ls site/deploy/
      - name: Deploy
        run: |
          cd site/deploy/
          git config user.name github-actions
          git config user.email github-actions@github.com
          git add .
          git commit -m "Site update at `LC_ALL=en_US.utf8 date +%Y-%m-%dT%H:%M:%S%z`"
          git push origin gh-pages
          cd ..

repo_name: supersonicsataa/alis

license: mit


code:
name: Shellcheck
on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  shellcheck:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Run ShellCheck
      uses: ludeeus/action-shellcheck@master


code:
packer_cache/
output-archlinux-alis-virtualbox/

site/resources/_gen/
*.vala
*.patch
*.iso
cloud-init/alis.key
cloud-init/iso/

path: .gitignore


code:
# alis

![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-badge.svg)
![Bash](https://raw.githubusercontent.com/picodotdev/alis/master/images/sh-bash-badge.svg)

Arch Linux Install Script (or alis, also known as _the Arch Linux executable installation guide and wiki_) installs an unattended, automated and customized Arch Linux system.

It is a simple Bash script developed from many Arch Linux Wiki pages that fully automates the installation of an [Arch Linux](https://archlinux.org/) system after booting from the original Arch Linux installation media. It contains the same commands that you would type and execute one by one interactively to complete the installation. The only user intervention needed is to edit a configuration file to choose the installation options and preferences from partitioning, to encryption, bootloader, file system, language and keyboard mapping, desktop environment, kernels, packages to install and graphic drivers. This automation makes the installation easy and fast, as fast as your internet connection allows.

If some time later after a system update, for any reason the system does not boot correctly, a recovery script is also provided to enter into a recovery mode that allows you to downgrade packages or execute any other commands to restore the system. Also, a log of the installation can be taken with asciinema.

A simple powerful Bash based script for an unattended, easy and fast way to install Arch Linux.
Boot. Get. Configure. Install. Enjoy.

**Warning! This script can delete all partitions of the persistent storage. It is recommended to test it first in a virtual machine like VirtualBox.**

Currently these scripts are for me, but maybe they are useful for you too.

Follow the [Arch Way](https://wiki.archlinux.org/title/Arch_Linux) of doing things and learn what this script does. This will allow you to know what is happening.

Please, don't ask for support for this script in Arch Linux forums, first read the [Arch Linux wiki](https://wiki.archlinux.org), the [Installation Guide](https://wiki.archlinux.org/title/Installation_guide) and the [General Recommendations](https://wiki.archlinux.org/title/General_recommendations), later compare those commands with the commands of this script.

For new features, improvements and bugs, fill an issue in GitHub or make a pull request. You can test it in a virtual machine (strongly recommended) like [VirtualBox](https://www.virtualbox.org/) before you run it in real hardware. If you test it in real hardware, please send me an email to pico.dev@gmail.com with the machine description and tell me if something goes wrong or all works fine. [Pull request](https://github.com/picodotdev/alis/pulls) and [new feature request](https://github.com/picodotdev/alis/issues) are welcome!

**Arch Linux Install Script (alis) is based on Arch Linux but is NOT approved, sponsored, or affiliated with Arch Linux or its related projects.**

[![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux.svg "Arch Linux")](https://www.archlinux.org/)

## Index

* [Principles](https://github.com/picodotdev/alis#principles)
* [Features](https://github.com/picodotdev/alis#features)
* [System installation](https://github.com/picodotdev/alis#system-installation)
* [Packages installation](https://github.com/picodotdev/alis#packages-installation)
* [Recovery](https://github.com/picodotdev/alis#recovery)
* [SSH install and cloud-init](https://github.com/picodotdev/alis#ssh-install-and-cloud-init)
* [Screenshots](https://github.com/picodotdev/alis#screenshots)
* [Video](https://github.com/picodotdev/alis#video)
* [How you can help](https://github.com/picodotdev/alis#how-you-can-help)
* [Media reference](https://github.com/picodotdev/alis#media-reference)
* [Alternatives](https://github.com/picodotdev/alis#alternatives)
* [Test in VirtualBox with Packer](https://github.com/picodotdev/alis#test-in-virtualbox-with-packer)
* [Arch Linux Installation Media](https://github.com/picodotdev/alis#arch-linux-installation-media)
* [Reference](https://github.com/picodotdev/alis#reference)

## Principles

* Use the original Arch Linux installation media
* As much unattended and automated as possible, require as little interactivity as possible
* Allow to customize the installation to cover the most common cases
* Provide support for system recovery
* Provide support for installation log
* Use sane configuration default values

## Features

* **System**: UEFI, BIOS
* **Storage**: SATA, NVMe and MMC
* **Encryption**: root partition encrypted and no encrypted
* **Partition**: no LVM, LVM, LVM on LUKS, GPT on UEFI, MBR on BIOS, custom partition scheme and mountpoints
* **File system**: ext4, btrfs (with subvols), xfs, f2fs, reiserfs
* **Kernels**: linux, linux-lts, linux-hardened, linux-zen
* **Desktop environment**: GNOME, KDE, XFCE, Mate, Cinnamon, LXDE, i3-wm, i3-gaps, Deepin, Budgie, Bspwm, Awesome, Qtile, Openbox, Leftwm, Dusk
* **Display managers**: GDM, SDDM, Lightdm, lxdm
* **Graphics controller**: intel, nvidia and amd with optionally early KMS start. With intel optionally fastboot, hardware video acceleration and framebuffer compression.
* **Bootloader**: GRUB, rEFInd, systemd-boot
* **Custom shell**: bash, zsh, dash, fish
* **WPA WIFI network** installation
* **Periodic TRIM** for SSD storage
* Intel and AMD **processors microcode**
* Optional **swap file**
* **VirtualBox guest additions** and **VMware tools** support
* **Kernel compression** and **custom parameters**
* **Users creation** and **add to sudoers**
* **systemd units enable or disable**
* **systemd-homed** support
* **PipeWire** support
* **Multilib** support
* **Files provision** support
* **SSH install** and **cloud-init** support
* Arch Linux custom **packages installation** and **repositories installation**
* Flatpak utility installation and **Flatpak packages installation**
* SDKMAN utility installation and **SDKMAN packages installation**
* **AUR utility** installation (paru, yay, aurman) and **AUR packages installation**
* **Packages installation after base system installation** (preferred way of packages installation)
* Script for download installation and **recovery scripts** and configuration files
* **Retry packages download** on connection/mirror error
* **Packer support** for testing in VirtualBox
* **Installation log** with all commands executed and output in a file and/or **asciinema video**
* Wait after installation for an **abortable reboot**
* **Use your own configuration**
* Bash scripts validated by [Shellcheck](https://www.shellcheck.net/)

## System installation

Download and boot from the latest original Arch Linux installation media. After boot use the following commands to start the installation.

Follow the Arch Way of doing things and learn what this script does. This will allow you to know what is happening.

Internet connection is required, with wireless WIFI connection see Wireless_network_configuration to bring up WIFI connection before start the installation.

Minimum usage

```
#                         # Start the system with latest Arch Linux installation media
# loadkeys [keymap]       # Load keyboard keymap, eg. loadkeys es, loadkeys us, loadkeys de
# curl -sL https://raw.githubusercontent.com/picodotdev/alis/master/download.sh | bash     # Download alis scripts
# vim alis.conf           # Edit configuration and change variables values with your preferences (system configuration)
# ./alis.sh               # Start installation
```

Advanced usage

```
#                         # Start the system with latest Arch Linux installation media
# loadkeys [keymap]       # Load keyboard keymap, eg. loadkeys es, loadkeys us, loadkeys de
# iwctl --passphrase "[WIFI_KEY]" station [WIFI_INTERFACE] connect "[WIFI_ESSID]"          # (Optional) Connect to WIFI network. _ip link show_ to know WIFI_INTERFACE.
# curl -sL https://raw.githubusercontent.com/picodotdev/alis/master/download.sh | bash     # Download alis scripts
# # curl -sL https://git.io/JeaH6 | bash                                                   # Alternative download URL with URL shortener
# # curl -sL https://raw.githubusercontent.com/picodotdev/alis/master/download.sh | bash -s -- -h [HASH_COMMIT] # Use specific version of the script based on the commit hash
# ./alis-asciinema.sh     # (Optional) Start asciinema video recording
# vim alis.conf           # Edit configuration and change variables values with your preferences (system configuration)
# vim alis-packages.conf  # (Optional) Edit configuration and change variables values with your preferences (packages to install)
#                         # (The preferred way to install packages is after system installation, see Packages installation)
# ./alis.sh               # Start installation
# ./alis-reboot.sh        # (Optional) Reboot the system, only necessary when REBOOT="false"
```

## Packages installation

After the base Arch Linux system is installed, alis can install packages with pacman, Flatpak, SDKMAN and from AUR.

```
#                                  # After system installation start a user session
# curl -sL https://raw.githubusercontent.com/picodotdev/alis/master/download.sh | bash     # Download alis scripts
# # curl -sL https://git.io/JeaH6 | bash                                                   # Alternative download URL with URL shortener
# ./alis-packages-asciinema.sh     # (Optional) Start asciinema video recording
# vim alis-packages.conf           # Edit configuration and change variables values with your preferences (packages to install)
# ./alis-packages.sh               # Start packages installation
```

## Recovery

Boot from the latest original Arch Linux installation media. After boot use the following commands to start the recovery, this will allow you to enter in the arch-chroot environment.

```
#                                  # Start the system with latest Arch Linux installation media
# loadkeys [keymap]                # Load keyboard keymap, eg. loadkeys es, loadkeys us, loadkeys de
# iwctl --passphrase "[WIFI_KEY]" station [WIFI_INTERFACE] connect "[WIFI_ESSID]"          # (Optional) Connect to WIFI network. _ip link show_ to know WIFI_INTERFACE.
# curl -sL https://raw.githubusercontent.com/picodotdev/alis/master/download.sh | bash     # Download alis scripts
# # curl -sL https://git.io/JeaH6 | bash                                                   # Alternative download URL with URL shortener
# ./alis-recovery-asciinema.sh     # (Optional) Start asciinema video recording
# vim alis-recovery.conf           # Edit configuration and change variables values with your last installation configuration with alis (mainly device and partition scheme)
# ./alis-recovery.sh               # Start recovery
# ./alis-recovery-reboot.sh        # Reboot the system
```

## SSH install and cloud-init

SSH install and cloud-init allows to install Arch Linux unattended and automated way in local virtual machines and cloud environments.

Build the cloud-init ISO, mount it in the VM along side the official Arch Linux installation media, start the VM and get its IP address.

```
$ ./alis-cloud-init-iso.sh
```

SSH to the VM.

```
$ ./alis-cloud-init-ssh.sh -i "${IP_ADDRESS}"
```

Or, start a unattended installation with the provided configuration.

```
$ ./alis-cloud-init-ssh.sh -i "${IP_ADDRESS}" -c "alis-config-efi-ext4-systemd.sh"
```

## Screenshots

Once the installation ends you have a ready to use system with your choosen preferences including all the free software latest version you wish to do produtive task from browsing, multimedia and office programs, to programming languages, compilers and server software and tools for creative and artistic tasks.

These are some desktop environments that can be installed.

[![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-gnome-thumb.jpg "Arch Linux with GNOME")](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-gnome.jpg)
[![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-kde-thumb.jpg "Arch Linux with KDE")](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-kde.jpg)
[![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-xfce-thumb.jpg "Arch Linux with XFCE")](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-xfce.jpg)
[![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-cinnamon-thumb.jpg "Arch Linux with Cinnamon")](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-cinnamon.jpg)
[![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-mate-thumb.jpg "Arch Linux with Mate")](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-mate.jpg)
[![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-lxde-thumb.jpg "Arch Linux with LXDE")](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-lxde.jpg)
[![Arch Linux](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-root-password-thumb.png "Arch Linux unloking LUKS on boot")](https://raw.githubusercontent.com/picodotdev/alis/master/images/archlinux-root-password.png)

## Video

Arch Linux base installation installed in less than 4 minutes with a fiber internet connection and a NVMe SSD. Don't trust me? See the video.

Type the system installation commands and wait to the installation complete. After a reboot the system is ready to use and customized with your choosen preferences.

[![asciicast](https://asciinema.org/a/444025.png)](https://asciinema.org/a/444025)

## How you can help

* Test in VirtualBox and create an issue if something does not work, attach the main parts of the used configuration file and the error message
* Create issues with new features
* Send pull requests
* Share it in social networks, forums, create a blog post or video about it
* Send me an email, I like to read that the script is being used and is useful :). Which are your computer specs, which is your alis configuration, if is your personal or working computer, if all worked fine or some suggestion to improve the script

## Media reference

* 2022.01 [Arch + Alis, Arco Linux](https://www.arcolinuxiso.com/aa/) ([video playlist](https://www.youtube.com/playlist?list=PLlloYVGq5pS7lMblPjiifVxxnMAqYzBU5))
* 2020.07 [Arch installer - alis](https://r1ce.net/2020/07/07/arch-installer-alis/)
* 2019.06 [Arch Linux OS Challenge: Install Arch 'The Easy Way' With These 2 Alternative Methods](https://www.forbes.com/sites/jasonevangelho/2019/06/10/arch-linux-os-challenge-2-alternatives-install-gui-script-easy/)

## Alternatives

There are other quite good similar projects that can be used as alternative to install a vanilla Arch Linux without any additions.

* [Arch Installer](https://github.com/archlinux/archinstall) (archinstall) (maybe is the most relevant as is included in the official installation media)
* [archfi](https://github.com/MatMoul/archfi/)
* [Archlinux Ultimate Installer (aui)](https://github.com/helmuthdu/aui) (only accepts patches)

Also, if you prefer to install an Arch Linux using a guided graphical installer you can choose an [Arch based distribution](https://wiki.archlinux.org/title/Arch-based_distributions#Active).

* [ArcoLinux](https://arcolinux.com/)
* [Manjaro](https://manjaro.org/)
* [EndeavourOS](https://endeavouros.com/)
* [Archlabs](https://archlabslinux.com/)
* [RebornOS](https://rebornos.org/)
* [BlackArch](https://blackarch.org/)

Also and recomended for new Arch Linux new comers follow the Arch Way of doing things is a good way to use and learn about Arch. There are many guides out here, the official Arch Linux installation guide the first one. These are other good ones that explains step by step from instalation media creation to first boot and programs installation, all the necessary to start.

* [The Arch Linux Handbook](https://www.freecodecamp.org/news/how-to-install-arch-linux/)

## Test in VirtualBox with Packer

VirtualBox and [Packer](https://packer.io/) are required.

* Firmware: efi, bios
* File system: ext4, btrfs, f2fs, xfs
* Partition: luks, lvm
* Bootloader: grub, refind, systemd
* Desktop environment: gnome, kde, xfce, ...

```
$ ./alis-packer.sh -c alis-packer-efi-ext4-systemd.sh
$ ./alis-packer.sh -c alis-packer-efi-ext4-systemd-gnome.sh
$ ./alis-packer.sh -c alis-packer-efi-ext4-luks-lvm-grub.sh
$ ./alis-packer.sh -c alis-packer-efi-btrfs-luks-lvm-systemd.sh
$ ./alis-packer.sh -c alis-packer-efi-f2fs-luks-lvm-systemd.sh
$ ./alis-packer.sh -c alis-packer-efi-ext4-grub-gnome.sh
$ ./alis-packer.sh -c alis-packer-efi-ext4-grub-kde.sh
$ ./alis-packer.sh -c alis-packer-efi-ext4-grub-xfce.sh
```

## Arch Linux Installation Media

https://www.archlinux.org/download/

## Reference

* https://archlinux.org/pacman/pacman.conf.5.html#_repository_sections
* https://gitlab.archlinux.org/archlinux/archiso/-/blob/master/configs/releng/packages.x86_64
* https://tldp.org/LDP/abs/html/
* https://tldp.org/LDP/Bash-Beginners-Guide/html/
* https://wiki.archlinux.org/title/AMDGPU
* https://wiki.archlinux.org/title/Arch_User_Repository
* https://wiki.archlinux.org/title/ATI
* https://wiki.archlinux.org/title/Awesome
* https://wiki.archlinux.org/title/Bluetooth
* https://wiki.archlinux.org/title/Bspwm
* https://wiki.archlinux.org/title/Btrfs
* https://wiki.archlinux.org/title/Budgie
* https://wiki.archlinux.org/title/Category:Boot_loaders
* https://wiki.archlinux.org/title/Cloud-init
* https://wiki.archlinux.org/title/Command-line_shell
* https://wiki.archlinux.org/title/Deepin_Desktop_Environment
* https://wiki.archlinux.org/title/Desktop_environment
* https://wiki.archlinux.org/title/Dm-crypt
* https://wiki.archlinux.org/title/Dm-crypt/Device_encryption
* https://wiki.archlinux.org/title/Dm-crypt/Encrypting_an_entire_system
* https://github.com/bakkeby/dusk
* https://wiki.archlinux.org/title/EFI_System_Partition
* https://wiki.archlinux.org/title/Ext4
* https://wiki.archlinux.org/title/F2FS
* https://wiki.archlinux.org/title/File_systems
* https://wiki.archlinux.org/title/Fstab
* https://wiki.archlinux.org/title/General_recommendations
* https://wiki.archlinux.org/title/GNOME
* https://wiki.archlinux.org/title/GRUB
* https://wiki.archlinux.org/title/Hardware_video_acceleration
* https://wiki.archlinux.org/title/I3
* https://wiki.archlinux.org/title/Install_Arch_Linux_via_SSH
* https://wiki.archlinux.org/title/Installation_guide
* https://wiki.archlinux.org/title/Intel_graphics
* https://wiki.archlinux.org/title/Intel_NUC
* https://wiki.archlinux.org/title/KDE
* https://wiki.archlinux.org/title/Kernel_mode_setting
* https://wiki.archlinux.org/title/Kernel_parameters
* https://wiki.archlinux.org/title/Kernels
* https://wiki.archlinux.org/title/LeftWM
* https://wiki.archlinux.org/title/List_of_applications
* https://wiki.archlinux.org/title/LVM
* https://wiki.archlinux.org/title/Main_page
* https://wiki.archlinux.org/title/Microcode
* https://wiki.archlinux.org/title/Mirrors
* https://wiki.archlinux.org/title/Mkinitcpio
* https://wiki.archlinux.org/title/Network_configuration
* https://wiki.archlinux.org/title/NetworkManager
* https://wiki.archlinux.org/title/Nouveau
* https://wiki.archlinux.org/title/NVIDIA
* https://wiki.archlinux.org/title/Openbox
* https://wiki.archlinux.org/title/Pacman
* https://wiki.archlinux.org/title/Partitioning
* https://wiki.archlinux.org/title/Persistent_block_device_naming
* https://wiki.archlinux.org/title/PipeWire
* https://wiki.archlinux.org/title/Qtile
* https://wiki.archlinux.org/title/REFInd
* https://wiki.archlinux.org/title/Reflector
* https://wiki.archlinux.org/title/Solid_state_drive/NVMe
* https://wiki.archlinux.org/title/Solid_State_Drives
* https://wiki.archlinux.org/title/Swap
* https://wiki.archlinux.org/title/Systemd
* https://wiki.archlinux.org/title/Systemd-boot
* https://wiki.archlinux.org/title/Systemd-homed
* https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface
* https://wiki.archlinux.org/title/VirtualBox
* https://wiki.archlinux.org/title/Wayland
* https://wiki.archlinux.org/title/Wireless_network_configuration
* https://wiki.archlinux.org/title/Wireless_network_configuration#Connect_to_an_access_point
* https://wiki.archlinux.org/title/Xfce
* https://wiki.archlinux.org/title/XFS
* https://wiki.archlinux.org/title/Xorg


code:
#!/usr/bin/env bash
set -eu

# Arch Linux Install Script (alis) installs unattended, automated
# and customized Arch Linux system.
# Copyright (C) 2022 picodotdev

#curl -L -o asciinema-2.0.2.zip https://github.com/asciinema/asciinema/archive/v2.0.2.zip
#bsdtar xvf asciinema-2.0.2.zip
#rm -f alis.asciinema
#(cd asciinema-2.0.2 && python3 -m asciinema rec --stdin -i 5 ~/alis.asciinema)

rm -f alis.asciinema

pacman -Sy
pacman -S --noconfirm asciinema

clear
asciinema rec --stdin -i 5 ~/alis.asciinema


code:
#!/usr/bin/env bash
set -eu
set -o xtrace

if [ ! -f cloud-init/alis.key ]; then
    openssl genrsa -out cloud-init/alis.key 8192
fi
SSH_RSA=$(ssh-keygen -y -f cloud-init/alis.key)
mkdir -p cloud-init/iso/
cp cloud-init/meta-data cloud-init/user-data cloud-init/iso/
sed -i "s#\\\${SSH_RSA}#${SSH_RSA}#" cloud-init/iso/user-data
mkisofs -o cloud-init/alis-cloud-init.iso -V CIDATA -iso-level 3 -J -R cloud-init/iso/


code:
#!/usr/bin/env bash
set -eu

GITHUB_USER="picodotdev"
BRANCH="master"
BRANCH_QUALIFIER=""
IP_ADDRESS=""
VM_TYPE="virtualbox"
VM_NAME="Arch Linux"
CONFIG_FILE_SH=""

while getopts "b:c:i:n:t:u:" arg; do
  case $arg in
    b)
      BRANCH="$OPTARG"
      ;;
    c)
      CONFIG_FILE_SH="$OPTARG"
      ;;
    i)
      IP_ADDRESS="$OPTARG"
      ;;
    n)
      VM_NAME="$OPTARG"
      ;;
    t)
      VM_TYPE="$OPTARG"
      ;;
    u)
      GITHUB_USER=${OPTARG}
      ;;
    *)
      echo "Unknown option: $arg"
      exit 1
      ;;
  esac
done

if [ "$BRANCH" == "sid" ]; then
  BRANCH_QUALIFIER="-sid"
fi

if [ "$IP_ADDRESS" == "" ] && [ "$VM_TYPE" != "" ] && [ "$VM_NAME" != "" ]; then
  IP_ADDRESS=$(VBoxManage guestproperty get "${VM_NAME}" "/VirtualBox/GuestInfo/Net/0/V4/IP" | cut -f2 -d " ")
fi

set -o xtrace
ssh-keygen -R "$IP_ADDRESS"
ssh-keyscan -H "$IP_ADDRESS" >> ~/.ssh/known_hosts

ssh -t -i cloud-init/alis.key root@"$IP_ADDRESS" "bash -c \"curl -sL https://raw.githubusercontent.com/${GITHUB_USER}/alis/${BRANCH}/download${BRANCH_QUALIFIER}.sh | bash -s -- -b ${BRANCH}\""

if [ -z "$CONFIG_FILE_SH" ]; then
  ssh -t -i cloud-init/alis.key root@"$IP_ADDRESS"
else
  ssh -t -i cloud-init/alis.key root@"$IP_ADDRESS" "bash -c \"configs/$CONFIG_FILE_SH\""
  ssh -t -i cloud-init/alis.key root@"$IP_ADDRESS" "bash -c \"./alis.sh -w\""
fi


code:
#!/usr/bin/env bash
set -eu

# Arch Linux Install Script (alis) installs unattended, automated
# and customized Arch Linux system.
# Copyright (C) 2022 picodotdev

# Common configuration.

WARNING_CONFIRM="true"

COMMOMS_LOADED="true"
PARTITION_BOOT=""
PARTITION_ROOT=""
PARTITION_BOOT_NUMBER=""
PARTITION_ROOT_NUMBER=""
DEVICE_ROOT=""
DEVICE_LVM=""
LUKS_DEVICE_NAME="cryptroot"
LVM_VOLUME_GROUP="vg"
LVM_VOLUME_LOGICAL="root"
SWAPFILE="/swapfile"
BOOT_DIRECTORY=""
ESP_DIRECTORY=""
UUID_BOOT=""
UUID_ROOT=""
PARTUUID_BOOT=""
PARTUUID_ROOT=""
CMDLINE_LINUX_ROOT=""
CMDLINE_LINUX=""
BTRFS_SUBVOLUME_ROOT=()
BTRFS_SUBVOLUME_SWAP=()
USER_NAME_INSTALL="root"

MNT_DIR="/mnt"

AUR_PACKAGE="yay"
AUR_COMMAND="yay"

BIOS_TYPE=""
ASCIINEMA=""
DEVICE_SDA="true"
DEVICE_NVME="false"
DEVICE_VDA="false"
DEVICE_MMC="false"
CPU_VENDOR=""
GPU_VENDOR=""
VIRTUALBOX=""
VMWARE=""
SYSTEM_INSTALLATION=""

LOG_TRACE="true"
LOG_FILE="false"
USER_NAME="sparks"
USER_PASSWORD="ask"
PACKAGES_PIPEWIRE="true"


code:
#!/usr/bin/env bash
# shellcheck disable=SC2034,SC2001,SC2155,SC2153,SC2143
# SC2034: foo appears unused. Verify it or export it.
# SC2001: See if you can use ${variable//search/replace} instead.
# SC2155 Declare and assign separately to avoid masking return values
# SC2153: Possible Misspelling: MYVARIABLE may not be assigned. Did you mean MY_VARIABLE?
# SC2143: Use grep -q instead of comparing output with [ -n .. ].

set -eu

# Arch Linux Install Script (alis) installs unattended, automated
# and customized Arch Linux system.
# Copyright (C) 2022 picodotdev

# Common functions and definitions.

# common static variables
ALIS_CONF_FILE="alis.conf"
ALIS_LOG_FILE="alis.log"
ALIS_ASCIINEMA_FILE="alis.asciinema"
RECOVERY_CONF_FILE="alis-recovery.conf"
RECOVERY_LOG_FILE="alis-recovery.log"
RECOVERY_ASCIINEMA_FILE="alis-recovery.asciinema"
PACKAGES_CONF_FILE="alis-packages.conf"
PACKAGES_LOG_FILE="alis-packages.log"
COMMONS_CONF_FILE="alis-commons.conf"
PROVISION_DIRECTORY="files/"

RED='\033[0;91m'
GREEN='\033[0;92m'
BLUE='\033[0;96m'
WHITE='\033[0;97m'
NC='\033[0m'

function sanitize_variable() {
    local VARIABLE="$1"
    local VARIABLE=$(echo "$VARIABLE" | sed "s/![^ ]*//g") # remove disabled
    local VARIABLE=$(echo "$VARIABLE" | sed -r "s/ {2,}/ /g") # remove unnecessary white spaces
    local VARIABLE=$(echo "$VARIABLE" | sed 's/^[[:space:]]*//') # trim leading
    local VARIABLE=$(echo "$VARIABLE" | sed 's/[[:space:]]*$//') # trim trailing
    echo "$VARIABLE"
}

function trim_variable() {
    local VARIABLE="$1"
    local VARIABLE=$(echo "$VARIABLE" | sed 's/^[[:space:]]*//') # trim leading
    local VARIABLE=$(echo "$VARIABLE" | sed 's/[[:space:]]*$//') # trim trailing
    echo "$VARIABLE"
}

function check_variables_value() {
    local NAME="$1"
    local VALUE="$2"
    if [ -z "$VALUE" ]; then
        echo "$NAME environment variable must have a value."
        exit 1
    fi
}

function check_variables_boolean() {
    local NAME="$1"
    local VALUE="$2"
    check_variables_list "$NAME" "$VALUE" "true false" "true" "true"
}

function check_variables_list() {
    local NAME="$1"
    local VALUE="$2"
    local VALUES="$3"
    local REQUIRED="$4"
    local SINGLE="$5"

    if [ "$REQUIRED" == "" ] || [ "$REQUIRED" == "true" ]; then
        check_variables_value "$NAME" "$VALUE"
    fi

    if [[ ("$SINGLE" == "" || "$SINGLE" == "true") && "$VALUE" != "" && "$VALUE" =~ " " ]]; then
        echo "$NAME environment variable value [$VALUE] must be a single value of [$VALUES]."
        exit 1
    fi

    if [ "$VALUE" != "" ] && [ -z "$(echo "$VALUES" | grep -F -w "$VALUE")" ]; then #SC2143
        echo "$NAME environment variable value [$VALUE] must be in [$VALUES]."
        exit 1
    fi
}

function check_variables_equals() {
    local NAME1="$1"
    local NAME2="$2"
    local VALUE1="$3"
    local VALUE2="$4"
    if [ "$VALUE1" != "$VALUE2" ]; then
        echo "$NAME1 and $NAME2 must be equal [$VALUE1, $VALUE2]."
        exit 1
    fi
}

function check_variables_size() {
    local NAME="$1"
    local SIZE_EXPECT="$2"
    local SIZE="$3"
    if [ "$SIZE_EXPECT" != "$SIZE" ]; then
        echo "$NAME array size [$SIZE] must be [$SIZE_EXPECT]."
        exit 1
    fi
}

function configure_network() {
    if [ -n "$WIFI_INTERFACE" ]; then
        iwctl --passphrase "$WIFI_KEY" station "$WIFI_INTERFACE" connect "$WIFI_ESSID"
        sleep 10
    fi

    # only one ping -c 1, ping gets stuck if -c 5
    if ! ping -c 1 -i 2 -W 5 -w 30 "$PING_HOSTNAME"; then
        echo "Network ping check failed. Cannot continue."
        exit 1
    fi
}

function facts_commons() {
    if [ -d /sys/firmware/efi ]; then
        BIOS_TYPE="uefi"
    else
        BIOS_TYPE="bios"
    fi

    if [ -f "$ALIS_ASCIINEMA_FILE" ] || [ -f "$RECOVERY_ASCIINEMA_FILE" ]; then
        ASCIINEMA="true"
    else
        ASCIINEMA="false"
    fi

    if lscpu | grep -q "GenuineIntel"; then
        CPU_VENDOR="intel"
    elif lscpu | grep -q "AuthenticAMD"; then
        CPU_VENDOR="amd"
    fi

    if lspci -nn | grep "\[03" | grep -qi "intel"; then
        GPU_VENDOR="intel"
    elif lspci -nn | grep "\[03" | grep -qi "amd"; then
        GPU_VENDOR="amd"
    elif lspci -nn | grep "\[03" | grep -qi "nvidia"; then
        GPU_VENDOR="nvidia"
    elif lspci -nn | grep "\[03" | grep -qi "vmware"; then
        GPU_VENDOR="vmware"
    fi

    if systemd-detect-virt | grep -qi "oracle"; then
        VIRTUALBOX="true"
    fi

    if systemd-detect-virt | grep -qi "vmware"; then
        VMWARE="true"
    fi

    USER_NAME_INSTALL="$(whoami)"
    if [ "$USER_NAME_INSTALL" == "root" ]; then
        SYSTEM_INSTALLATION="true"
    else
        SYSTEM_INSTALLATION="false"
    fi
}

function init_log_trace() {
    local ENABLE="$1"
    if [ "$ENABLE" == "true" ]; then
        set -o xtrace
    fi
}

function init_log_file() {
    local ENABLE="$1"
    local FILE="$2"
    if [ "$ENABLE" == "true" ]; then
        exec &> >(tee -a "$FILE")
    fi
}

function pacman_uninstall() {
    local ERROR="true"
    local PACKAGES=()
    set +e
    IFS=' ' read -ra PACKAGES <<< "$1"
    local PACKAGES_UNINSTALL=()
    for PACKAGE in "${PACKAGES[@]}"
    do
        execute_sudo "pacman -Qi $PACKAGE > /dev/null 2>&1"
        local PACKAGE_INSTALLED=$?
        if [ $PACKAGE_INSTALLED == 0 ]; then
            local PACKAGES_UNINSTALL+=("$PACKAGE")
        fi
    done
    if [ -z "${PACKAGES_UNINSTALL[*]}" ]; then
        return
    fi
    local COMMAND="pacman -Rdd --noconfirm ${PACKAGES_UNINSTALL[*]}"
    if execute_sudo "$COMMAND"; then
        local ERROR="false"
    fi
    set -e
    if [ "$ERROR" == "true" ]; then
        exit 1
    fi
}

function pacman_install() {
    local ERROR="true"
    local PACKAGES=()
    set +e
    IFS=' ' read -ra PACKAGES <<< "$1"
    for VARIABLE in {1..5}
    do
        local COMMAND="pacman -Syu --noconfirm --needed ${PACKAGES[*]}"
       if execute_sudo "$COMMAND"; then
            local ERROR="false"
            break
        else
            sleep 10
        fi
    done
    set -e
    if [ "$ERROR" == "true" ]; then
        exit 1
    fi
}

function aur_install() {
    local ERROR="true"
    local PACKAGES=()
    set +e
    which "$AUR_COMMAND"
    if [ "$AUR_COMMAND" != "0" ]; then
        aur_command_install "$USER_NAME" "$AUR_PACKAGE"
    fi
    IFS=' ' read -ra PACKAGES <<< "$1"
    for VARIABLE in {1..5}
    do
        local COMMAND="$AUR_COMMAND -Syu --noconfirm --needed ${PACKAGES[*]}"
        if execute_aur "$COMMAND"; then
            local ERROR="false"
            break
        else
            sleep 10
        fi
    done
    set -e
    if [ "$ERROR" == "true" ]; then
        return
    fi
}

function aur_command_install() {
    pacman_install "git"
    local USER_NAME="$1"
    local COMMAND="$2"
    execute_aur "rm -rf /home/$USER_NAME/.alis && mkdir -p /home/$USER_NAME/.alis/aur && cd /home/$USER_NAME/.alis/aur && git clone https://aur.archlinux.org/${COMMAND}.git && (cd $COMMAND && makepkg -si --noconfirm) && rm -rf /home/$USER_NAME/.alis"
}

function systemd_units() {
    local UNITS=()
    IFS=' ' read -ra UNITS <<< "$SYSTEMD_UNITS"
    for U in "${UNITS[@]}"; do
        local ACTION=""
        local UNIT=${U}
        if [[ $UNIT == -* ]]; then
            local ACTION="disable"
            local UNIT=$(echo "$UNIT" | sed "s/^-//g")
        elif [[ $UNIT == +* ]]; then
            local ACTION="enable"
            local UNIT=$(echo "$UNIT" | sed "s/^+//g")
        elif [[ $UNIT =~ ^[a-zA-Z0-9]+ ]]; then
            local ACTION="enable"
            local UNIT=$UNIT
        fi

        if [ -n "$ACTION" ]; then
            execute_sudo "systemctl $ACTION $UNIT"
        fi
    done
}

function execute_flatpak() {
    local COMMAND="$1"
    if [ "$SYSTEM_INSTALLATION" == "true" ]; then
        arch-chroot "${MNT_DIR}" bash -c "$COMMAND"
    else
        bash -c "$COMMAND"
    fi
}

function execute_aur() {
    local COMMAND="$1"
    if [ "$SYSTEM_INSTALLATION" == "true" ]; then
        arch-chroot "${MNT_DIR}" sed -i 's/^%wheel ALL=(ALL:ALL) ALL$/%wheel ALL=(ALL:ALL) NOPASSWD: ALL/' /etc/sudoers
        arch-chroot "${MNT_DIR}" bash -c "echo -e \"$USER_PASSWORD\n$USER_PASSWORD\n$USER_PASSWORD\n$USER_PASSWORD\n\" | su $USER_NAME -s /usr/bin/bash -c \"$COMMAND\""
        arch-chroot "${MNT_DIR}" sed -i 's/^%wheel ALL=(ALL:ALL) NOPASSWD: ALL$/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers
    else
        bash -c "$COMMAND"
    fi
}

function execute_sudo() {
    local COMMAND="$1"
    if [ "$SYSTEM_INSTALLATION" == "true" ]; then
        arch-chroot "${MNT_DIR}" bash -c "$COMMAND"
    else
        sudo bash -c "$COMMAND"
    fi
}

function execute_user() {
    local USER_NAME="$1"
    local COMMAND="$2"
    if [ "$SYSTEM_INSTALLATION" == "true" ]; then
        arch-chroot "${MNT_DIR}" bash -c "su $USER_NAME -s /usr/bin/bash -c \"$COMMAND\""
    else
        bash -c "$COMMAND"
    fi
}

function do_reboot() {
    umount -R "${MNT_DIR}"/boot
    umount -R "${MNT_DIR}"
    reboot
}

function print_step() {
    STEP="$1"
    echo ""
    echo -e "${BLUE}# ${STEP} step${NC}"
    echo ""
}

function execute_step() {
    local STEP="$1"
    eval "$STEP"
}

function partition_setup() {
    # setup
    if [ "$PARTITION_MODE" == "auto" ]; then
        PARTITION_PARTED_FILE_SYSTEM_TYPE="$FILE_SYSTEM_TYPE"
        if [ "$PARTITION_PARTED_FILE_SYSTEM_TYPE" == "f2fs" ]; then
            PARTITION_PARTED_FILE_SYSTEM_TYPE=""
        fi
        PARTITION_PARTED_UEFI="mklabel gpt mkpart ESP fat32 1MiB 512MiB mkpart root $PARTITION_PARTED_FILE_SYSTEM_TYPE 512MiB 100% set 1 esp on"
        PARTITION_PARTED_BIOS="mklabel msdos mkpart primary ext4 4MiB 512MiB mkpart primary $PARTITION_PARTED_FILE_SYSTEM_TYPE 512MiB 100% set 1 boot on"
    elif [ "$PARTITION_MODE" == "custom" ]; then
        PARTITION_PARTED_UEFI="$PARTITION_CUSTOM_PARTED_UEFI"
        PARTITION_PARTED_BIOS="$PARTITION_CUSTOM_PARTED_BIOS"
    fi

    if [ "$DEVICE_SDA" == "true" ]; then
        PARTITION_BOOT="$(partition_device "${DEVICE}" "${PARTITION_BOOT_NUMBER}")"
        PARTITION_ROOT="$(partition_device "${DEVICE}" "${PARTITION_ROOT_NUMBER}")"
        DEVICE_ROOT="$(partition_device "${DEVICE}" "${PARTITION_ROOT_NUMBER}")"
    fi

    if [ "$DEVICE_NVME" == "true" ]; then
        PARTITION_BOOT="$(partition_device "${DEVICE}" "${PARTITION_BOOT_NUMBER}")"
        PARTITION_ROOT="$(partition_device "${DEVICE}" "${PARTITION_ROOT_NUMBER}")"
        DEVICE_ROOT="$(partition_device "${DEVICE}" "${PARTITION_ROOT_NUMBER}")"
    fi

    if [ "$DEVICE_VDA" == "true" ]; then
        PARTITION_BOOT="$(partition_device "${DEVICE}" "${PARTITION_BOOT_NUMBER}")"
        PARTITION_ROOT="$(partition_device "${DEVICE}" "${PARTITION_ROOT_NUMBER}")"
        DEVICE_ROOT="$(partition_device "${DEVICE}" "${PARTITION_ROOT_NUMBER}")"
    fi

    if [ "$DEVICE_MMC" == "true" ]; then
        PARTITION_BOOT="$(partition_device "${DEVICE}" "${PARTITION_BOOT_NUMBER}")"
        PARTITION_ROOT="$(partition_device "${DEVICE}" "${PARTITION_ROOT_NUMBER}")"
        DEVICE_ROOT="$(partition_device "${DEVICE}" "${PARTITION_ROOT_NUMBER}")"
    fi
}

function partition_device() {
    local DEVICE="$1"
    local NUMBER="$2"
    local PARTITION_DEVICE=""

    if [ "$DEVICE_SDA" == "true" ]; then
        PARTITION_DEVICE="${DEVICE}${NUMBER}"
    fi

    if [ "$DEVICE_NVME" == "true" ]; then
        PARTITION_DEVICE="${DEVICE}p${NUMBER}"
    fi

    if [ "$DEVICE_VDA" == "true" ]; then
        PARTITION_DEVICE="${DEVICE}${NUMBER}"
    fi

    if [ "$DEVICE_MMC" == "true" ]; then
        PARTITION_DEVICE="${DEVICE}p${NUMBER}"
    fi

    echo "$PARTITION_DEVICE"
}

function partition_options() {
    PARTITION_OPTIONS_BOOT="defaults"
    PARTITION_OPTIONS="defaults"

    if [ "$DEVICE_TRIM" == "true" ]; then
        PARTITION_OPTIONS_BOOT="$PARTITION_OPTIONS_BOOT,noatime"
        PARTITION_OPTIONS="$PARTITION_OPTIONS,noatime"
        if [ "$FILE_SYSTEM_TYPE" == "f2fs" ]; then
            PARTITION_OPTIONS="$PARTITION_OPTIONS,nodiscard"
        fi
    fi
}

function partition_mount() {
    if [ "$FILE_SYSTEM_TYPE" == "btrfs" ]; then
        # mount subvolumes
        mount -o "subvol=${BTRFS_SUBVOLUME_ROOT[1]},$PARTITION_OPTIONS,compress=zstd" "$DEVICE_ROOT" "${MNT_DIR}"
        mkdir -p "${MNT_DIR}"/boot
        mount -o "$PARTITION_OPTIONS_BOOT" "$PARTITION_BOOT" "${MNT_DIR}"/boot
        for I in "${BTRFS_SUBVOLUMES_MOUNTPOINTS[@]}"; do
            IFS=',' read -ra SUBVOLUME <<< "$I"
            if [ "${SUBVOLUME[0]}" == "root" ]; then
                continue
            fi
            if [ "${SUBVOLUME[0]}" == "swap" ] && [ -z "$SWAP_SIZE" ]; then
                continue
            fi
            if [ "${SUBVOLUME[0]}" == "swap" ]; then
                mkdir -p "${MNT_DIR}${SUBVOLUME[2]}"
                chmod 0755 "${MNT_DIR}${SUBVOLUME[2]}"
            else
                mkdir -p "${MNT_DIR}${SUBVOLUME[2]}"
            fi
            mount -o "subvol=${SUBVOLUME[1]},$PARTITION_OPTIONS,compress=zstd" "$DEVICE_ROOT" "${MNT_DIR}${SUBVOLUME[2]}"
        done
    else
        # root
        mount -o "$PARTITION_OPTIONS" "$DEVICE_ROOT" "${MNT_DIR}"

        # boot
        mkdir -p "${MNT_DIR}"/boot
        mount -o "$PARTITION_OPTIONS_BOOT" "$PARTITION_BOOT" "${MNT_DIR}"/boot

        # mount points
        for I in "${PARTITION_MOUNT_POINTS[@]}"; do
            if [[ "$I" =~ ^!.* ]]; then
                continue
            fi
            IFS='=' read -ra PARTITION_MOUNT_POINT <<< "$I"
            if [ "${PARTITION_MOUNT_POINT[1]}" == "/boot" ] || [ "${PARTITION_MOUNT_POINT[1]}" == "/" ]; then
                continue
            fi
            local PARTITION_DEVICE="$(partition_device "${DEVICE}" "${PARTITION_MOUNT_POINT[0]}")"
            mkdir -p "${MNT_DIR}${PARTITION_MOUNT_POINT[1]}"
            mount -o "$PARTITION_OPTIONS" "${PARTITION_DEVICE}" "${MNT_DIR}${PARTITION_MOUNT_POINT[1]}"
        done
    fi
}

function ask_password() {
    PASSWORD_NAME="$1"
    PASSWORD_VARIABLE="$2"
    read -r -sp "Type ${PASSWORD_NAME} password: " PASSWORD1
    echo ""
    read -r -sp "Retype ${PASSWORD_NAME} password: " PASSWORD2
    echo ""
    if [[ "$PASSWORD1" == "$PASSWORD2" ]]; then
        declare -n VARIABLE="${PASSWORD_VARIABLE}"
        VARIABLE="$PASSWORD1"
    else
        echo "${PASSWORD_NAME} password don't match. Please, type again."
        ask_password "${PASSWORD_NAME}" "${PASSWORD_VARIABLE}"
    fi
}


code:
#!/usr/bin/env bash
set -eu

# https://wiki.archlinux.org/title/Libvirt#Server
# https://wiki.archlinux.org/title/QEMU#Bridged_networking_using_qemu-bridge-helper
# sudo pacman -S virt-install dnsmasq dmidecode
# sudo usermod -a -G libvirtd picodotdev
# sudo systemctl start libvirtd.service
# mkdir -p /etc/qemu
# vim /etc/qemu/bridge.conf
# allow virbr0

# 3D Acceleration
# Host and guest shared clipboard
# Host and guest file sharing

DISK_DIRECTORY="/run/media/picodotdev/Samsung microSD/KVM VMs"
ISO_DIRECTORY="/run/media/picodotdev/Samsung microSD/Iso"

virt-install \
    --connect=qemu:///session \
    --name=archlinux-alis \
    --os-variant=archlinux \
    --vcpu=2 \
    --ram=4096 \
    --boot uefi \
    --disk path="$DISK_DIRECTORY/archlinux-alis.qcow2,format=qcow2,size=40,sparse=yes" \
    --cdrom "$ISO_DIRECTORY/archlinux-2022.11.01-x86_64.iso" \
    --disk cloud-init/alis-cloud-init.iso,device=cdrom,bus=sata \
    --network bridge=virbr0 \
    --noautoconsole


code:
#!/usr/bin/env bash
set -eu

# Arch Linux Install Script (alis) installs unattended, automated
# and customized Arch Linux system.
# Copyright (C) 2022 picodotdev

#curl -L -o asciinema-2.0.2.zip https://github.com/asciinema/asciinema/archive/v2.0.2.zip
#bsdtar xvf asciinema-2.0.2.zip
#rm -f alis.asciinema
#(cd asciinema-2.0.2 && python3 -m asciinema rec --stdin -i 5 ~/alis.asciinema)

rm -f alis-packages.asciinema

#pacman -S --noconfirm asciinema

clear
asciinema rec --stdin -i 5 ~/alis-packages.asciinema


code:
#!/usr/bin/env bash
set -eu

# Arch Linux Install Script (alis) installs unattended, automated
# and customized Arch Linux system.
# Copyright (C) 2022 picodotdev

LOG_FILE="alis-packages.log"
ASCIINEMA_FILE="alis-packages.asciinema"

function copy_logs() {
    if [ -f "$LOG_FILE" ]; then
        sudo mkdir -p /var/log/alis
        sudo cp "$LOG_FILE" "/var/log/alis/$LOG_FILE"
    fi
    if [ -f "$ASCIINEMA_FILE" ]; then
        sudo mkdir -p /var/log/alis
        sudo cp "$ASCIINEMA_FILE" "/var/log/alis/$ASCIINEMA_FILE"
    fi
}

copy_logs


code:
# Arch Linux Install Script (alis) configuration file
#
# Some variables values are preceded by a ! character, this means that the value is ignored.
# Some variables accept a single value others accept multiple values as annotated in the comments.
# Some variables are boolean with a value of true or false.
#
# Read the Arch Linux wiki pages to learn more about the variables values.
# https://github.com/picodotdev/alis/blob/master/README.md

# init
## LOG_TRACE outputs the comands executed.
## LOG_FILE generates a log file with the commands executed and output generated during installation.
### The log file is saved to /var/log/alis-packages.log.
LOG_TRACE="true"
LOG_FILE="false"

# pacman
## Arch Linux packages to install
## more at https://www.archlinux.org/packages/
## PACKAGES_PACMAN_CUSTOM_REPOSITORIES custom repositories to add to pacman configuration, see https://archlinux.org/pacman/pacman.conf.5.html#_repository_sections
### Comment lines starting with # charater are removed
PACKAGES_PACMAN_INSTALL="true"
PACKAGES_PACMAN_INSTALL_PIPEWIRE="true"
PACKAGES_PACMAN_INTERNET="firefox wget"
PACKAGES_PACMAN_MULTIMEDIA="kdeconnect kodi"
PACKAGES_PACMAN_UTILITIES=""
PACKAGES_PACMAN_DOCUMENTS_AND_TEXT="calligra nano"
PACKAGES_PACMAN_COMMUNICATION="kmail konversation signal-desktop"
PACKAGES_PACMAN_GAMES=""
PACKAGES_PACMAN_SECURITY="gnupg"
PACKAGES_PACMAN_SCIENCE=""
PACKAGES_PACMAN_OTHERS=""
PACKAGES_PACMAN_DEVELOPER="docker git libpng arm-none-eabi-binutils code"
PACKAGES_PACMAN_CUSTOM=""
PACKAGES_PACMAN_PIPEWIRE="pipewire pipewire-pulse pipewire-alsa wireplumber xdg-desktop-portal-kde"
PACKAGES_PACMAN_CUSTOM_REPOSITORIES="
#[custom]
#SigLevel = Optional TrustAll
#Server = file:///home/custompkgs
"

## Flatpak packages to install
## more at https://flathub.org/apps/collection/popular
PACKAGES_FLATPAK_INSTALL="false"
PACKAGES_FLATPAK_INTERNET=""
PACKAGES_FLATPAK_MULTIMEDIA=""
PACKAGES_FLATPAK_UTILITIES=""
PACKAGES_FLATPAK_DOCUMENTS_AND_TEXT=""
PACKAGES_FLATPAK_COMMUNICATION=""
PACKAGES_FLATPAK_GAMES=""
PACKAGES_FLATPAK_SECURITY=""
PACKAGES_FLATPAK_SCIENCE=""
PACKAGES_FLATPAK_OTHERS=""
PACKAGES_FLATPAK_DEVELOPER=""
PACKAGES_FLATPAK_CUSTOM=""

## SDKMAN packages to install
## more at https://sdkman.io/jdks and https://sdkman.io/sdks
PACKAGES_SDKMAN_INSTALL="false"
PACKAGES_SDKMAN_JDKS="!java !java:17.0.1-tem !java:11.0.13-tem !java:8.0.312-tem" # format <candidate>:[version]:[local-path]
PACKAGES_SDKMAN_SDKS="!gradle !maven !kotlin !groovy" # format <candidate>:[version]:[local-path]

## AUR utility and AUR packages to install
## more at https://aur.archlinux.org/packages/
PACKAGES_AUR_INSTALL="true"
PACKAGES_AUR_COMMAND="yay"
PACKAGES_AUR_INTERNET=""
PACKAGES_AUR_MULTIMEDIA=""
PACKAGES_AUR_UTILITIES=""
PACKAGES_AUR_DOCUMENTS_AND_TEXT=""
PACKAGES_AUR_COMMUNICATION=""
PACKAGES_AUR_GAMES="prismlauncher-qt5"
PACKAGES_AUR_SECURITY=""
PACKAGES_AUR_SCIENCE=""
PACKAGES_AUR_OTHERS=""
PACKAGES_AUR_DEVELOPER=""
PACKAGES_AUR_CUSTOM=""

PACKAGES_PACMAN="$PACKAGES_PACMAN_INTERNET $PACKAGES_PACMAN_MULTIMEDIA $PACKAGES_PACMAN_UTILITIES $PACKAGES_PACMAN_DOCUMENTS_AND_TEXT $PACKAGES_PACMAN_COMMUNICATION $PACKAGES_PACMAN_GAMES $PACKAGES_PACMAN_SECURITY $PACKAGES_PACMAN_SCIENCE $PACKAGES_PACMAN_OTHERS $PACKAGES_PACMAN_DEVELOPER $PACKAGES_PACMAN_CUSTOM"
PACKAGES_FLATPAK="$PACKAGES_FLATPAK_INTERNET $PACKAGES_FLATPAK_MULTIMEDIA $PACKAGES_FLATPAK_UTILITIES $PACKAGES_FLATPAK_DOCUMENTS_AND_TEXT $PACKAGES_FLATPAK_COMMUNICATION $PACKAGES_FLATPAK_GAMES $PACKAGES_FLATPAK_SECURITY $PACKAGES_FLATPAK_SCIENCE $PACKAGES_FLATPAK_OTHERS $PACKAGES_FLATPAK_DEVELOPER $PACKAGES_FLATPAK_CUSTOM"
PACKAGES_SDKMAN="$PACKAGES_SDKMAN_JDKS $PACKAGES_SDKMAN_SDKS"
PACKAGES_AUR="$PACKAGES_AUR_INTERNET $PACKAGES_AUR_MULTIMEDIA $PACKAGES_AUR_UTILITIES $PACKAGES_AUR_DOCUMENTS_AND_TEXT $PACKAGES_AUR_COMMUNICATION $PACKAGES_AUR_GAMES $PACKAGES_AUR_SECURITY $PACKAGES_AUR_SCIENCE $PACKAGES_AUR_OTHERS $PACKAGES_AUR_DEVELOPER $PACKAGES_AUR_CUSTOM"

# systemd
## SYSTEMD_UNITS systemd units to enable or disable.
### If preceded with a "+" unit is enabled, if preceded with "-" unit is disabled, if preceded with "!" unit is ignored (no action is performed).
### eg. "+ufw.service" to enable, "-ufw.service" to disable, "!ufw.service" to ignore
SYSTEMD_UNITS="!ufw.service !bluetooth.service !docker.service"