Skip to content

Instantly share code, notes, and snippets.

@lacostenycoder
Last active November 2, 2023 17:18
Show Gist options
  • Save lacostenycoder/23d05ace816de0f39e9e6aa940172b91 to your computer and use it in GitHub Desktop.
Save lacostenycoder/23d05ace816de0f39e9e6aa940172b91 to your computer and use it in GitHub Desktop.
Ruby script to toggle night-mode hack on Slack Desktop app - Mac only, maybe linux

- IMPORTANT

For security, since this script injects CSS via AJAX, first fork the main slack night mode repo. The reason is explained here

UPDATE: The code has been modified to download the remote css to a local file and use ruby sass compiler to verify there is no malicious code in the remote css. This will error if the code has been modified to include anything malicious (i.e. script or img tags etc.) It's also been refactored to use the local file inside the js injection, it makes sure it's safe first in the very unlikely event the local file somehow differs from the remote css. The chances of this happening are remote, but this should suffice for safety.

Installation

  • save this script wherever you keep your ruby scripts for example ~/lacostenycoder/scripts/ruby/
  • change the URL in the remote_repo variable in ruby script to use YOUR repo. The rawgit.com file is created when you fork the repo.
  • For non-MacOS, find where the slack files are and replace line 20 to point to correct path, thanks simbalinux so you would change line 20 for ubuntu like this
    • @file_target = '/usr/lib/slack/resources/app.asar.unpacked/src/static/'
  • make script executable sudo chmod +x nightslack
  • symlink to a PATH load for example: ln -s /Users/lacostenycoder/dev/ruby/nightslack.rb /usr/local/bin/nightslack
  • Or if you prefer just drop the .rb from the filename and move it directly to /usr/local/bin/nightslack

How to use this

From a terminal simply type nightslack to start desktop app in night-mode.

To toggle back to day mode, simpley run nightslack -d to pass the day mode option. This will start or restart a running slack desktop in the desired mode!

Keeping your forked repo up to date

  • To update styles, sync your forked repo with upstream but be sure to inspect the css to insure it doesn't contain js code injeciton.
#!/usr/bin/env ruby
require 'open-uri'
require 'sass'
JS_ERROR_MSG = "Possible js code injection found in remote css... check your repo!".freeze
remote_repo = 'https://raw.githubusercontent.com/lacostenycoder/slack-night-mode/master/css/raw/black.css'
remote_css = open(remote_repo) { |f| f.read }
# Check for possible js code injection in css
abort(JS_ERROR_MSG + "\n#{remote_repo}") if remote_css.index('<script>')
# double check if ruby sass compiles correctly. Will raise if any html or non css
begin
compsass = Sass::Engine.new(remote_css, :syntax => :scss, :style => :compressed).render
rescue Sass::SyntaxError => e
puts e
abort(JS_ERROR_MSG)
end
static_path = '/Applications/Slack.app/Contents/Resources/app.asar.unpacked/src/static/'
target_css_file = static_path + 'black.css'
File.open(target_css_file, 'w') {|f| f.write remote_css}
slack_pid = `ps -axcf -S -O%cpu | grep Slack | awk '{print $2}' | head -n 1`.strip
unless slack_pid.empty?
`kill -9 #{slack_pid}`
end
js_code = <<-JS
document.addEventListener('DOMContentLoaded', async function() {
const initTheme = themeCssUrl => new Promise(resolve => $.ajax({
url: themeCssUrl,
success: css => {
const styleJqueryEl = $('<style>').html(css).appendTo('head')
const styleElement = styleJqueryEl[0]
resolve(styleElement)
}
}))
initTheme("#{remote_repo}")
})
JS
@file_target = static_path + 'ssb-interop.js'
`cp #{@file_target} #{@file_target}.bak`
@current_file = File.read(@file_target)
@normal_mode = @day_mode_set ? @current_file : @current_file.split(js_code).first
@night_mode = @normal_mode + js_code
use_day_mode = ARGV[0] == '-d'
def set_mode(mode)
if mode == 'd'
File.open(@file_target, 'w'){|f| f.puts @normal_mode}
puts "Slack Normal (day) mode has been set!"
else
File.open(@file_target, 'w'){|f| f.puts @night_mode}
puts "Slack Normal night mode has been set!"
end
end
use_day_mode ? set_mode('d') : set_mode('n')
`open -a "Slack"`
@lacostenycoder
Copy link
Author

@laCour nice catch! I updated to remove the cdn, Thanks!

nice_catch

@lacostenycoder
Copy link
Author

@laCour I see https://rawgit.com is being sunset. How is https://www.jsdelivr.com/rawgit ? I've switched to that for now.

@GottZ
Copy link

GottZ commented Mar 16, 2019

forked a powershell version and hardened it:
https://gist.github.com/GottZ/621f4b6994cfb2726e43e18e7a75e49a

it removes any comment that it can find from the css and then checks if url or import is present within the css.

@butaca
Copy link

butaca commented Jul 10, 2019

Stopped working on Slack for Mac Version 4.0.0. since ssb-interop.js doesn't exist anymore

@lacostenycoder
Copy link
Author

Stopped working on Slack for Mac Version 4.0.0. since ssb-interop.js doesn't exist anymore

Hmm.... guess we'll need a new work around... not sure what is needed.

@butaca
Copy link

butaca commented Jul 10, 2019

I tried replacing ssb-interop.js with all the js files under /Applications/Slack.app/Contents/Resources/ but din't work :(

@lacostenycoder
Copy link
Author

lacostenycoder commented Jul 16, 2019

I tried replacing ssb-interop.js with all the js files under /Applications/Slack.app/Contents/Resources/ but din't work :(

Yeah, looks like they totally broke this with the release of 4.0.0. Only way now is to use the web app. Slack hates our eyes and there doesn't seem to be anything we can do except hope they one day care enough to support this in desktop app.

@butaca
Copy link

butaca commented Jul 16, 2019

They changed their app bundle. In this repo they got it working: https://github.com/LanikSJ/slack-dark-mode/pull/77/files#diff-4e5b58d0c0e2e47e41878b4116e03b7f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment