Files
rise-cook/rice-cook.py
T
2026-05-23 16:37:52 -04:00

422 lines
14 KiB
Python
Executable File

#!/bin/python3
# Program Should run with sudo -HE
# https://github.com/acidburnmonkey
#
import os
import re
import subprocess
import requests
import shutil
import logging
from git import Repo
import zipfile
import urllib.request
from rich.console import Console
from rich.theme import Theme
from slimParser import SlimParser
# pylint: disable=subprocess-run-check
# pylint: disable=broad-exception-caught
# pylint: disable=logging-fstring-interpolation
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s | %(levelno)s | %(funcName)s| %(message)s")
f_handler = logging.FileHandler('logg.log')
f_handler.setFormatter(formatter)
logger.addHandler(f_handler)
logging.basicConfig(
format="%(asctime)s | %(levelno)s | %(funcName)s| %(message)s ", filename='logg.log', level=logging.INFO
)
ap_theme = Theme({'ok': 'green', 'error': 'red', 'checked': 'bold cyan', 'rule': 'orange1'})
console = Console(theme=ap_theme)
user = os.getlogin()
home = os.path.join('/home', user)
def main():
setup = ''
local_user = user
sudo_check()
console.print(f"Setting up for user {local_user} ", style='rule')
console.print('optimizing dnf.conf', style='ok')
dnf_config()
install_programs_dnf()
zsh_fonts()
hyprland()
msic_configs()
# This should not need sudo
# Pass D or L to copy_dotfiles function
if os.path.exists('dotfiles'):
while True:
console.print('Set up dotfiles for Desktop (D) or Laptop (L) ?', style='rule')
setup = input('>').lower()
if setup == 'l' or setup == 'd':
copy_dotfiles(setup)
break
else:
console.print('Dotfiles not found skipping...', style='error')
executable_scripts()
systemd()
# correcting ownership
subprocess.run(f"chown -R {user}:{user} {home}", shell=True, stdout=subprocess.DEVNULL)
################
# END OF MAIN #
################
def dnf_config():
console.rule("Configuring dnf", style='checked')
# dnf conf
with open('/etc/dnf/dnf.conf', 'r+') as f:
text = 'max_parallel_downloads=10 \nfastestmirror=true'
match = re.search(r'(max_parallel_downloads=10)', f.read())
if not match:
with open('/etc/dnf/dnf.conf', 'a+') as f:
f.write(text)
console.print(' changes made to dnf_config :heavy_check_mark:', style='ok')
logger.info('changes made to dnf_config')
else:
console.print(' dnf.conf already optimized :heavy_check_mark:', style='checked')
subprocess.check_call(
'sudo dnf install -y https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm',
stdout=subprocess.DEVNULL,
shell=True,
)
subprocess.check_call(
'sudo dnf install -y https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm',
stdout=subprocess.DEVNULL,
shell=True,
)
console.print('rpmfusion added to repos :heavy_check_mark:', style='ok')
logger.info('rpmfusion added to repos')
# update Dnf
subprocess.run('dnf upgrade -y', shell=True)
logger.info('Updated Dnf ')
def hyprland():
console.rule("Configuring hyprland", style='checked')
if not os.path.exists(home + '/.local/bin'):
os.mkdir(home + '/.local/bin')
# create tty launcher
with open(home + '/.local/bin/wrappedhl', 'w+') as file:
file.write('''#!/bin/sh
cd ~
export _JAVA_AWT_WM_NONREPARENTING=1
export XCURSOR_SIZE=24
exec Hyprland ''')
file.seek(0)
for line in file:
line.strip()
# create .desktop file
with open('/usr/share/wayland-sessions/hyprland.desktop', 'w+') as file:
file.write(f'''[Desktop Entry]
Name=Hyprland
Comment=An intelligent dynamic tiling Wayland compositor
Exec={home}/.local/bin/wrappedhl
Type=Application ''')
file.seek(0)
for line in file:
line.strip()
# making them executable
subprocess.run(f'chmod +x {home}/.local/bin/wrappedhl', shell=True)
subprocess.run('chmod +x /usr/share/wayland-sessions/hyprland.desktop', shell=True)
logger.info('Created hyprland .desktop and wrappedhl')
console.print('Created hyprland .desktop and wrappedhl :heavy_check_mark:', style='ok')
# install programs dnf
def install_programs_dnf():
console.rule("Installing All Programs DNF ", style='checked')
parser = SlimParser('data.conf')
parser.cleanAll()
repos = parser.get('Repolist')
main = parser.get('Main')
programs = parser.get('Programs')
flatpaks = parser.get('Flatpak')
copr = parser.get('Copr')
# try to add repos
if repos:
for url in repos:
try:
subprocess.run(f'sudo dnf config-manager addrepo --from-repofile={url}', shell=True)
except Exception as e:
console.print(Exception(), ":x:", style='error')
logging.critical(f"Error adding extra repos: {str(e)}")
if copr:
for id in copr:
try:
subprocess.run(f'sudo dnf copr enable -y {id}', shell=True)
except Exception as e:
console.print(Exception(), ":x:", style='error')
logging.critical(f"Err adding Copr: {str(e)}")
# for some reason they have to be passed to dnf individually
# instead of unpacked list *programs
main.extend(programs)
for program in main:
try:
subprocess.run(f'dnf install -y {program} ', shell=True)
except Exception as e:
console.print(Exception(), ":x:", style='error')
logging.critical(f"Error at Installing programs: {str(e)}")
for fp in flatpaks:
try:
subprocess.run(f'flatpak install flathub -y {fp}', shell=True)
except Exception as e:
console.print(Exception(), ":x:", style='error')
logging.critical(f"Error at Installing flatpaks: {str(e)}")
logger.info('Installed programs in data.config')
## checks for sudo
def sudo_check():
sudo_user = os.getenv("SUDO_USER")
if sudo_user is None:
console.print("This program must run as sudo -HE ./script ", style='error')
exit()
else:
console.print('ok :heavy_check_mark:', style='ok')
# Oh my zsh setup + flathub
def zsh_fonts():
console.rule("Installing Zsh fonts", style='checked')
try:
console.print("installing oh my zsh ", style='ok')
# installs oh my zsh
ohmy_url = "https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh"
zsh_installer = requests.get(ohmy_url, timeout=10)
open('install.sh', 'wb').write(zsh_installer.content)
# removing exec line
with open('install.sh', 'r') as f:
contents = f.read()
pattern = r'^\s*exec zsh -l$'
matches = re.findall(pattern, contents, flags=re.MULTILINE)
if matches:
contents = re.sub(pattern, '', contents, flags=re.MULTILINE)
with open('install.sh', 'w') as f:
f.write(contents)
subprocess.run('chmod +x install.sh ', stdout=subprocess.DEVNULL, shell=True, check=True)
subprocess.run(f'sudo -u {user} ./install.sh', shell=True, check=True)
console.print("installing oh my zsh auto suggestions ", style='ok')
# zsh auto suggestions
subprocess.run(
f'git clone https://github.com/zsh-users/zsh-autosuggestions {home}/.oh-my-zsh/custom/plugins/zsh-autosuggestions',
shell=True,
)
console.print("installing powerlevel10k ", style='ok')
# powerlevel 10k
subprocess.run(
f"git clone --depth=1 https://github.com/romkatv/powerlevel10k.git {home}/.oh-my-zsh/custom/themes/powerlevel10k",
shell=True,
)
logger.info('Installed Oh_my_zsh , powerlevel10k , autosuggestions')
except Exception as e:
logging.warning(f"Could not set up Zsh: {str(e)}")
console.print("Error setting up ohmyzsh :X:", style='error')
console.print("installing flathub", style='ok')
# flathub
subprocess.run(
'flatpak remote-add --if-not-exists flathub https://flatInstalled programs in data.txthub.org/repo/flathub.flatpakrepo',
shell=True,
stdout=subprocess.DEVNULL,
)
logger.info('Installed Flathub')
# copy and override dotfiles
def copy_dotfiles(setup):
console.rule("Copying Dotfiles", style='checked')
# list of relevant configs
lis = os.listdir('dotfiles/desktop')
# filter out .
lis = [item for item in lis if not item.startswith('.')]
destination = os.path.join(home, '.config')
shutil.copy2('dotfiles/.zshrc', home)
shutil.copy2('dotfiles/.p10k.zsh', home)
shutil.copy2('dotfiles/.vimrc', home)
shutil.copy2('dotfiles/.ideavimrc', home)
if setup == 'l':
console.print("Setting up dotfiles for Laptop", style='ok')
# copying files recursively
for dir in lis:
print(subprocess.run(f'cp -r {dir} {destination}', shell=True))
elif setup == 'd':
console.print("Setting up dotfiles for Desktop", style='ok')
for dir in lis:
source = os.path.join('dotfiles', dir)
dest = os.path.join(destination, dir)
try:
print(shutil.copytree(source, dest, dirs_exist_ok=True))
except NotADirectoryError:
shutil.copy2(source, dest)
console.print("Dotfiles copied :heavy_check_mark:", style='ok')
logger.info('Dotfiles copied')
def executable_scripts():
console.rule('Making scripts executable', style='checked')
for root, _, files in os.walk(os.path.join(home, '.config')):
for element in files:
if '.sh' in element or '.py' in element:
try:
subprocess.run(f"chmod +x {os.path.join(root, element)}", shell=True)
except Exception as e:
logging.critical(f"Error at executable_scripts: {str(e)}")
console.print("Job done :heavy_check_mark:", style='ok')
logger.info('Made scripts in .config executable')
# need sudo
def msic_configs():
console.rule('Setting up final configs', style='checked')
current_dir = os.getcwd()
try:
os.mkdir('misic')
os.mkdir(os.path.join(home, '.themes'))
except FileExistsError:
pass
os.chdir(os.path.join(current_dir, 'misic'))
fonts_url = "https://github.com/acidburnmonkey/fonts"
fonts_dir = os.path.join(home, ".fonts")
try:
Repo.clone_from(fonts_url, fonts_dir)
except Exception as e:
print(f"Failed to clone repository: {e}")
# to system
shutil.copytree(home + "/.fonts", '/usr/share/fonts/', dirs_exist_ok=True)
console.print("Fonts downloaded :heavy_check_mark:", style='ok')
logger.info('Fonts downloaded ')
# Icons
subprocess.run(
'git clone --depth 1 https://github.com/EliverLara/candy-icons.git /usr/share/icons/candy-icons',
shell=True,
stdout=subprocess.DEVNULL,
)
console.print("Icons have been downloaded :heavy_check_mark:", style='ok')
logger.info('candy-icons downloaded')
try:
url = 'https://github.com/catppuccin/gtk/releases/download/v1.0.3/catppuccin-mocha-blue-standard+default.zip'
urllib.request.urlretrieve(url, 'catppuccin-mocha-blue.zip')
with zipfile.ZipFile('catppuccin-mocha-blue.zip') as zip:
zip.extractall(os.path.join(home, '.themes'))
# to system
shutil.copytree(home + "/.themes", '/usr/share/themes/', dirs_exist_ok=True)
console.print("Themes have been downloaded :heavy_check_mark:", style='ok')
logger.info('Themes have been downloaded')
## Set themes Gtk
subprocess.run("gsettings set org.gnome.desktop.interface icon-theme 'candy-icons'", shell=True)
subprocess.run(
"gsettings set org.gnome.desktop.interface gtk-theme 'catppuccin-mocha-blue-standard+default'", shell=True
)
subprocess.run("gsettings set org.gnome.desktop.interface font-name 'Roboto-Regular'", shell=True)
# Flatpak force theme
subprocess.run("flatpak override --filesystem=$HOME/.themes", shell=True)
subprocess.run("flatpak override --env=GTK_THEME=catppuccin-mocha-blue-standard+default", shell=True)
console.print("Themes have been Set :heavy_check_mark:", style='ok')
logger.info('Themes have been Set')
except Exception as e:
logging.critical(f"Could not get themes :{str(e)}")
console.print("Error with Themes :X:", style='error')
# codec and multimedia
try:
subprocess.run('dnf swap ffmpeg-free ffmpeg --allowerasing', shell=True)
subprocess.run(
'dnf update @multimedia --setopt="install_weak_deps=False" --exclude=PackageKit-gstreamer-plugin',
shell=True,
)
subprocess.run('dnf update @sound-and-video', shell=True)
console.print("ffmpeg non free installed + all codecs :heavy_check_mark:", style='ok')
logger.info('ffmpeg non free installed + all codecs ')
except Exception as e:
logging.critical(f"Could not install codecs :{str(e)}")
console.print("Something failed with new codecs :X:", style='error')
def systemd():
console.rule('Enabling user services', style='checked')
user_services = [
'gnome-keyring.service',
'ssh-agent.service',
'polkit-gnome-authentication-agent.service',
'hypridle.service',
'gnome-keyring-daemon.service',
]
try:
for services in user_services:
subprocess.run(f'systemctl --user enable {services}', shell=True)
except Exception as e:
logging.critical(f"Could not start service :{str(e)}")
console.print("Error starting some services :X:", style='error')
if __name__ == '__main__':
main()