Files
rise-cook/rice-cook.py
T

442 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
import gdown
from git import Repo
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.WARNING
)
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')
exceptions = [
'retired',
'data.conf',
'wrappedhl',
'Hyprland',
'install.sh',
'logg.log',
'README.md',
'rice-cook.py',
'Laptop-configs',
]
for z in exceptions:
if z in lis:
lis.remove(z)
# 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:
themes_urls = [
'https://drive.google.com/uc?id=1KkqC5vaBjePSHxjBI_8PWfm3jNW5gO7k',
'https://drive.google.com/uc?id=1-qq3wmuQhkKHpW_8OrRNS92AHD9LE4un',
'https://drive.google.com/uc?id=1mxkN9b4Ws7CeqF_KaTlA3dA5e75UUa4y',
'https://drive.google.com/uc?id=1cYLRsxmWeQJMOS7QEGEgJenRPKxgwN7X',
]
for index, file in enumerate(themes_urls):
output = str(index) + '.zip'
gdown.download(file, output, quiet=False)
subprocess.run(f"unzip {output} -d {os.path.join(home, '.themes')}", shell=True, stdout=subprocess.DEVNULL)
# 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-Macchiato-Standard-Blue-Dark'", 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-Macchiato-Standard-Blue-Dark", 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()