#!/usr/bin/env ruby # BEGIN: Includes & Requires require 'erb' require 'time' require 'json' require 'zlib' require 'find' require 'English' require 'net/http' require 'optparse' require 'fileutils' require 'rubygems/package' # END: Includes & Requires # BEGIN: Overrides class Dir def / (path) output_path = File.join(self.path + '/' + path) if File.directory? output_path Dir.new(output_path) else output_path end end ## For backwards compat def chdir(dir = nil, &block) if dir.nil? Dir.chdir(self, &block) else Dir.chdir(dir, &block) end end end class String def / (other) File.join(self, other) end end # END: Overrides # BEGIN: Variables URL_DOWNLOAD_BASE='https://dl.discordapp.net/apps/linux/{VERSION}/discord-{VERSION}.tar.gz' DOWNLOAD_URL='https://discord.com/api/download/stable?platform=linux&format=tar.gz' $CONFIG = Hash.new $CONFIG[:icon_dir] = Dir.new(Dir.home) / '.local' / 'share' / 'icons' File.mkdir($CONFIG[:icon_dir]) if not File.exist?($CONFIG[:icon_dir]) $CONFIG[:discord_config_path] = Dir.new(Dir.home) / '.config' / 'discord' $CONFIG[:local_application_install_dir] = Dir.new(Dir.home) / '.local' / 'share' / 'applications' File.mkdir($CONFIG[:local_application_install_dir]) if not File.exist?($CONFIG[:local_application_install_dir]) $CONFIG[:install_dir] = Dir.new(Dir.home) / '.opt' $CONFIG[:desktop_path] = $CONFIG[:install_dir] / 'Discord' / 'discord.desktop' File.mkdir($CONFIG[:install_dir]) if not File.exist?($CONFIG[:install_dir]) $CONFIG[:discord_path] = $CONFIG[:install_dir] / 'Discord' $CONFIG[:desktop_file_path] = $CONFIG[:discord_path] / 'discord.desktop' $CONFIG[:discord_version_file] = $CONFIG[:discord_path] / 'resources' / 'build_info.json' $CONFIG[:action] = 'install' $CONFIG[:keep_installer] = false $CONFIG[:debug] = false DISCORD_DESKTOP_CONTENTS=<\d+\.\d+\.\d+).tar.gz/ @remote_version = Gem::Version.new($LAST_MATCH_INFO['version']) else raise "Failed to retrieve remote version" end end @remote_version end def local_version if @local_version.nil? @local_version = if File.exist? $CONFIG[:discord_version_file] data = JSON.load_file($CONFIG[:discord_version_file]) Gem::Version.new(data['version']) else Gem::Version.new('0.0.0') end end @local_version end def download version = self.remote_version.to_s uri = URI(URL_DOWNLOAD_BASE.gsub('{VERSION}',version)) puts "download_installer: Downloading The discord #{version} tar.gz" file_contents = Net::HTTP.get(uri) output_file = "discord-#{version}.tar.gz" puts "download_installer: Output file will #{output_file}" $CONFIG[:install_dir].chdir do File.open(output_file, 'wb') do |file| file.write(file_contents) end end puts "download_installer: tar.gz was downloaded" end def install installer_file = "discord-#{self.remote_version}.tar.gz" puts "do_install: Extracting new installer" $CONFIG[:install_dir].chdir do File.open(installer_file, 'rb') do |file| Gem::Package.new("").extract_tar_gz(file, $CONFIG[:install_dir]) end if not $CONFIG[:keep_installer] puts "do_install: Removing new installer (#{installer_file})" File.unlink(installer_file) end end update_desktop_file end end # END: Helper Classes # BEGIN: Helper Functions def update_desktop_file file_needs_updating = true puts "update_desktop_file: Checking if desktop entry needs updating" if File.exist?($CONFIG[:desktop_path]) puts "update_desktop_file: Desktop file exists, checking if it matches template" File.open($CONFIG[:desktop_path], 'r') do |file| if file.read() == DISCORD_DESKTOP_CONTENTS puts "update_desktop_file: Desktop file matches template. Not updating" file_needs_updating = false end end end if file_needs_updating File.open($CONFIG[:desktop_path], 'w') do |file| puts "update_desktop_file: Desktop File was written" file.write(DISCORD_DESKTOP_CONTENTS) end puts "update_desktop_file: Triggering desktop to install new desktop entry and refresh entries" %x[ desktop-file-install --dir=#{$CONFIG[:local_application_install_dir].path} #{$CONFIG[:desktop_path]} ] end end def make_backup files = { files: Array.new, dirs: Array.new, symlinks: Array.new } [ $CONFIG[:discord_config_path].path, $CONFIG[:discord_path].path ].each do |backup_dir| puts "make_backup: Getting Files from #{backup_dir})" Find.find("#{backup_dir}").each{ |item| puts("#{item} was retrieved from #{backup_dir}") if $CONFIG[:debug] if File.file?(item) puts("#{item} was found to be a file") if $CONFIG[:debug] files[:files] << item elsif File.symlink?(item) puts("#{item} was found to be a symlink") if $CONFIG[:debug] files[:symlinks] << item elsif File.directory?(item) puts("#{item} was found to be a directory") if $CONFIG[:debug] files[:dirs] << item end } end Dir.chdir(Dir.home) do puts "make_backup: Beginning backup process (OUTPUT_FILE = #{$CONFIG[:backup_filename]})" File.open($CONFIG[:backup_filename], "wb") do |backup_file| Zlib::GzipWriter.wrap(backup_file) do |gzip| Gem::Package::TarWriter.new(gzip) do |tar| puts "\nmake_backup : files : Beginning backup process for files (Count: #{files[:files].count})" file_count = files[:files].count files[:files].each_with_index { |file, i| puts "make_backup : files : Backing up #{file} (#{i+1}/#{file_count})" if $CONFIG[:debug] File.open(file, 'rb') { |file_to_archive| contents = file_to_archive.read() tar.add_file_simple(file_to_archive.path.sub("#{Dir.home}/",''), file_to_archive.stat.mode, contents.length) { |io| io.write(contents) } } } puts "\nmake_backup : directories : Beginning backup process for directories (Count: #{files[:dirs].count})" dir_count = files[:dirs].count files[:dirs].each_with_index {|dir,i| puts "make_backup : directories : Backing up #{dir} (#{i+1}/#{dir_count})" if $CONFIG[:debug] tar.mkdir(dir.sub("#{Dir.home}/",""), File.stat(dir).mode) } puts "\nmake_backup : symlinks : Beginning backup process for symlinks (Count: #{files[:symlinks].count})" symlink_count = files[:symlinks].count files[:symlinks].each_with_index {|symlink,i| puts "make_backup : symlinks : Backing up #{symlink} (#{i+1}/#{symlink_count})" if $CONFIG[:debug] tar.add_symlink(symlink.sub("#{Dir.home}/",""), File.readlink(symlink), File.lstat(symlink).mode) } end end end end end # END: Helper Functions # BEGIN: Work installer = Installer.new case $CONFIG[:action] when 'install' if installer.needs_update? puts "main: Installed Version will be updated" installer.download installer.install elsif installer.local_version == installer.remote_version puts "main: Installed Version is up-to-date" else puts "main: What?" end when 'check' puts puts " Report" puts "-------------------------------------" puts " Remote Version: #{installer.remote_version.to_s}" puts " Local Version: #{installer.local_version.to_s}" puts " Needs Updating: #{installer.needs_update? ? "Yes" : "No"}" when 'backup' make_backup end # END: Work