Compare commits

...

5 Commits

Author SHA1 Message Date
Wizzard
a2cdc4f2f1 Make theming the bar a configurable option 2023-10-17 12:50:37 -04:00
Wizzard
f0b79090de Blacklist default cover icon 2023-10-16 23:29:01 -04:00
Wizzard
1b0cf7c2b3 Made handling of bar changing nicer, high quality images 2023-10-16 20:30:46 -04:00
Wizzard
62285d572b Change bar colors with album cover in the most retarded way possible 2023-10-16 20:21:13 -04:00
Wizzard
79dcfa7b83 Start script and pm2 2023-10-16 16:46:29 -04:00
6 changed files with 104 additions and 37 deletions

View File

@@ -1,4 +1,5 @@
{ {
"apiKey": "YOUR_LASTFM_API_KEY", "apiKey": "YOUR_LASTFM_API_KEY",
"username": "YOUR_LASTFM_USERNAME" "username": "YOUR_LASTFM_USERNAME",
"themeBar": true
} }

View File

@@ -1 +1,3 @@
npm install axios sharp get-image-colors npm install axios sharp get-image-colors pm2
pip3 install libqtile --break-system-packages
pip3 install pyautogui --break-system-packages

94
main.js
View File

@@ -1,13 +1,15 @@
const axios = require('axios'); const axios = require('axios');
const sharp = require('sharp'); const sharp = require('sharp');
const getColors = require('get-image-colors'); const rp = require('request-promise');
const rp = require("request-promise");
const fs = require('fs'); const fs = require('fs');
const { exec } = require('child_process'); const { exec } = require('child_process');
const crypto = require('crypto');
const config = JSON.parse(fs.readFileSync("config.json")); const config = JSON.parse(fs.readFileSync("config.json"));
const updateInterval = 5000; const updateInterval = 5000;
let previousHash = null;
async function processAlbumCover(url) { async function processAlbumCover(url) {
try { try {
console.log(`Processing album cover from URL: ${url}`); console.log(`Processing album cover from URL: ${url}`);
@@ -18,10 +20,6 @@ async function processAlbumCover(url) {
const imageSharp = sharp(imageBuffer); const imageSharp = sharp(imageBuffer);
const metadata = await imageSharp.metadata(); const metadata = await imageSharp.metadata();
if (metadata.format !== 'jpeg' && metadata.format !== 'jpg' && metadata.format !== 'png') {
throw new Error('Not a supported image format');
}
const dominantColor = await getDominantColor(imageBuffer); const dominantColor = await getDominantColor(imageBuffer);
const resizedBuffer = await imageSharp const resizedBuffer = await imageSharp
@@ -43,10 +41,12 @@ async function processAlbumCover(url) {
}) })
.toBuffer(); .toBuffer();
return outputBuffer; console.log('Processed album cover successfully.');
return { outputBuffer, dominantColor };
} catch (error) { } catch (error) {
console.error(`Error processing album cover from URL: ${url}`, error); console.error(`Failed to process album cover from URL: ${url}`, error);
throw error;
} }
} }
@@ -58,6 +58,7 @@ async function getDominantColor(imageBuffer) {
const greenAvg = channels[1].mean; const greenAvg = channels[1].mean;
const blueAvg = channels[2].mean; const blueAvg = channels[2].mean;
console.log(`Determined dominant color: r=${Math.round(redAvg)}, g=${Math.round(greenAvg)}, b=${Math.round(blueAvg)}`);
return { return {
r: Math.round(redAvg), r: Math.round(redAvg),
g: Math.round(greenAvg), g: Math.round(greenAvg),
@@ -65,34 +66,47 @@ async function getDominantColor(imageBuffer) {
}; };
} }
async function setAsWallpaper(buffer) { async function setAsWallpaper(buffer, dominantColor) {
try { try {
await fs.promises.writeFile('/tmp/current_album_cover.png', buffer); await fs.promises.writeFile('/tmp/current_album_cover.png', buffer, 'binary');
exec('feh --bg-center /tmp/current_album_cover.png'); exec('feh --bg-center /tmp/current_album_cover.png');
console.log("Wallpaper set using feh.");
if (config.themeBar) {
const colorString = `#${dominantColor.r.toString(16).padStart(2, '0')}${dominantColor.g.toString(16).padStart(2, '0')}${dominantColor.b.toString(16).padStart(2, '0')}`;
console.log(`Sending color string to Python script: ${colorString}`);
const command = `python3 ./tap_in.py '${colorString}'`;
console.log("Running command:", command);
exec(command, (error, stdout, stderr) => {
if (error) {
console.error(`Error running the command: ${error}`);
}
console.log(`Python stdout: ${stdout}`);
console.log(`Python stderr: ${stderr}`);
});
}
console.log('Wallpaper and Qtile colors successfully updated.');
} catch (error) { } catch (error) {
console.error("Error setting wallpaper:", error); console.error("Failed to set wallpaper and update Qtile colors:", error);
throw error;
} }
} }
async function fetchCurrentScrobble(user) { async function fetchCurrentScrobble(user) {
let lastTrackName;
let lastArtist;
try { try {
console.log("Fetching current scrobble...");
const optionsGetTrack = { const optionsGetTrack = {
uri: `http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${user}&api_key=${config.apiKey}&format=json&limit=1`, uri: `http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${user}&api_key=${config.apiKey}&format=json&limit=1`,
json: true json: true
}; };
const lastTrack = await rp(optionsGetTrack); const lastTrack = await rp(optionsGetTrack);
const lastArtist = lastTrack.recenttracks.track[0].artist["#text"];
if (!lastTrack.recenttracks || !lastTrack.recenttracks.track || !lastTrack.recenttracks.track[0]) { const lastTrackName = lastTrack.recenttracks.track[0].name;
console.error("No valid track data in recenttracks");
return null;
}
lastArtist = lastTrack.recenttracks.track[0].artist["#text"];
lastTrackName = lastTrack.recenttracks.track[0].name;
const images = lastTrack.recenttracks.track[0].image; const images = lastTrack.recenttracks.track[0].image;
@@ -104,27 +118,51 @@ async function fetchCurrentScrobble(user) {
} }
} }
if (coverURL) { if (coverURL && coverURL.includes('300x300')) {
coverURL = coverURL.replace('300x300', '1000x1000'); coverURL = coverURL.replace('300x300', '1000x1000');
} }
const ignoreURL = "https://lastfm.freetls.fastly.net/i/u/1000x1000/2a96cbd8b46e442fc41c2b86b821562f.png";
if (coverURL === ignoreURL) {
console.log("Ignored URL detected. Skipping update.");
return;
}
if (coverURL) { if (coverURL) {
const processedCover = await processAlbumCover(coverURL); const { outputBuffer, dominantColor } = await processAlbumCover(coverURL);
await setAsWallpaper(processedCover);
console.log("Wallpaper updated to album cover of: " + lastTrackName); const hash = crypto.createHash('sha256').update(outputBuffer).digest('hex');
if (hash === previousHash) {
console.log("Image is the same as before. Skipping updates.");
return;
}
previousHash = hash;
await setAsWallpaper(outputBuffer, dominantColor);
console.log("Successfully fetched current scrobble.");
return { outputBuffer, dominantColor };
} else { } else {
console.error(`Cover URL not found for track: ${lastTrackName}`); console.error(`Cover URL not found for track: ${lastTrackName}`);
throw new Error('Cover URL not found');
} }
} catch (error) { } catch (error) {
console.error(`Failed to fetch current scrobble`, error); console.error(`Failed to fetch current scrobble:`, error);
throw error;
} }
} }
function startFetching() { function startFetching() {
setInterval(async () => { setInterval(async () => {
try {
console.log('Initiating fetch sequence.');
await fetchCurrentScrobble(config.username); await fetchCurrentScrobble(config.username);
console.log('Fetch sequence completed.');
} catch (error) {
console.error(`Failed in startFetching:`, error);
}
}, updateInterval); }, updateInterval);
} }
startFetching(); startFetching();

View File

@@ -3,6 +3,7 @@
"axios": "^1.5.1", "axios": "^1.5.1",
"file-type": "^18.5.0", "file-type": "^18.5.0",
"get-image-colors": "^4.0.1", "get-image-colors": "^4.0.1",
"pm2": "^5.3.0",
"request-promise": "^4.2.6", "request-promise": "^4.2.6",
"sharp": "^0.32.6" "sharp": "^0.32.6"
} }

2
start_linux.sh Executable file
View File

@@ -0,0 +1,2 @@
git pull
node_modules/.bin/pm2 start main.js

23
tap_in.py Normal file
View File

@@ -0,0 +1,23 @@
import sys
import time
import pyautogui
print("Arguments received:", sys.argv)
def write_color_to_file(color):
with open("/tmp/bar_color.txt", "w") as f:
f.write(color)
print(f"Successfully wrote color {color} to /tmp/bar_color.txt")
def simulate_f7_keypress():
time.sleep(1) # Give a little time for the file to be written
pyautogui.press('f7')
print("Simulated F7 keypress")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python tap_in.py <color>")
else:
color = sys.argv[1]
write_color_to_file(color)
simulate_f7_keypress()