Skip to content

Commit

Permalink
song blacklisting, hopefully
Browse files Browse the repository at this point in the history
  • Loading branch information
RayDeeUx committed Sep 28, 2024
1 parent 9061bc0 commit dd6e86b
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 65 deletions.
2 changes: 1 addition & 1 deletion mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"settings": {
"configdir": {
"name": "Click me to open the Config Directory!",
"desc": "<cy>(Hopefully.)</c>\nThis setting does literally nothing new except being a button that acts as a shortcut to open the config directory for this mod (which is kind of important for using this mod properly, because this is where you will store your \"New Best\" sound effects), because the legendary developers in the Geode Team themselves forgot to add a shortcut button that would have done this exact same thing, and I have gotten far too many folks (rightfully) asking me to find the config directory when using some of my other mods, and I hate repeating the same things over and over again, and I don't know if the next major update for Geode will also repeat this mistake where HJfod forgets to include a config directory shortcut button, so this setting and this button are here for extra insurance, so please enjoy this extra button, I guess. Anyway, by the time you're finished reading this, your device should be finished with opening the config directory; press \"Aight\" to close this window.",
"desc": "<cy>(Hopefully.)</c>\nThis setting does literally nothing new except being a button that acts as a shortcut to open the config directory for this mod (which is kind of important for using this mod properly, because this is where you will store menu loops), because the legendary developers in the Geode Team themselves forgot to add a shortcut button that would have done this exact same thing, and I have gotten far too many folks (rightfully) asking me to find the config directory when using some of my other mods, and I hate repeating the same things over and over again, and I don't know if the next major update for Geode will also repeat this mistake where HJfod forgets to include a config directory shortcut button, so this setting and this button are here for extra insurance, so please enjoy this extra button, I guess. Anyway, by the time you're finished reading this, your device should be finished with opening the config directory; press \"Aight\" to close this window.",
"type": "custom"
},
"useCustomSongs": {
Expand Down
Binary file added resources/blacklist-btn-sprite.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions src/MenuLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ using namespace geode::prelude;
class $modify(MenuLayerMLHook, MenuLayer) {
struct Fields {
SongManager &songManager = SongManager::get();
std::filesystem::path blacklistFile = Mod::get()->getConfigDir() / R"(blacklist.txt)";
};

bool init() {
Expand All @@ -28,6 +29,9 @@ class $modify(MenuLayerMLHook, MenuLayer) {
if (Utils::getBool("enableCopySongID"))
MenuLayerMLHook::addCopyButton();

if (Utils::getBool("enableBlacklistButton"))
MenuLayerMLHook::addBlacklistButton();

return true;
}

Expand Down Expand Up @@ -93,4 +97,40 @@ class $modify(MenuLayerMLHook, MenuLayer) {
Utils::copyCurrentSongName();
Notification::create("[MLR] Current song name copied!", NotificationIcon::None, Mod::get()->getSettingValue<double>("notificationTime"));
}

void addBlacklistButton() {
auto menu = getChildByID("right-side-menu");

auto btn = CCMenuItemSpriteExtra::create(
CircleButtonSprite::create(CCSprite::create("blacklist-btn-sprite.png"_spr)),
this,
menu_selector(MenuLayerMLHook::onBlacklistButton)
);
btn->setID("blacklist-button"_spr);

menu->addChild(btn);
menu->updateLayout();
}

void onBlacklistButton(CCObject*) {
if (m_fields->songManager.isOriginalMenuLoop()) return;
auto currentSong = m_fields->songManager.getCurrentSong();
const bool useCustomSongs = Utils::getBool("useCustomSongs");
log::info("blacklisting: {}", currentSong);
std::string toWriteToFile = currentSong;
std::string songName = Utils::getSongName();
std::string songArtist = Utils::getSongArtist();
int songID = Utils::getSongID();
if (!useCustomSongs) toWriteToFile = toWriteToFile.append(fmt::format(" # Song: {} by {}", songName, songArtist));
auto test = utils::file::readString(m_fields->blacklistFile);
if (test.isErr()) return log::info("error reading blacklist file!");
auto result = geode::utils::file::writeString(m_fields->blacklistFile, fmt::format("{}\n{}", test.unwrap(), toWriteToFile));
if (result.isErr()) return log::info("error blacklisting song {}", currentSong);
if (!useCustomSongs) Utils::makeNewCard(fmt::format("Blacklisted {} by {} ({})!", songName, songArtist, songID));
else Utils::makeNewCard(fmt::format("Blacklisted {})!", currentSong));
m_fields->songManager.clearSongs();
Utils::populateVector(useCustomSongs);
if (!Utils::getBool("playlistMode")) Utils::setNewSong();
else Utils::playlistModeNewSong();
}
};
118 changes: 118 additions & 0 deletions src/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#include "Utils.hpp"
#include <random>
#include <regex>
#include <filesystem>
#include <iostream>
#include <fstream>

static std::regex m_songEffectRegex(R"(.*(?:\\|\/)(\S+)\.(mp3|ogg|wav|flac|oga))", std::regex::optimize | std::regex::icase); // see https://regex101.com/r/CqvIvI/1.
static const std::regex m_geodeAudioRegex(R"(((?!\S+geode)(?:\\|\/)(?:([a-z0-9\-_]+\.[a-z0-9\-_]+)(?:\\|\/))([\S ]+)\.(mp3|ogg|wav|flac|oga))$)", std::regex::optimize | std::regex::icase); // see https://regex101.com/r/0b9rY1/1.
Expand Down Expand Up @@ -203,4 +206,119 @@ void Utils::copyCurrentSongName() {
result = currentSongName;
}
geode::utils::clipboard::write(result);
}

void Utils::populateVector(bool customSongs) {
auto configDir = geode::Mod::get()->getConfigDir();
/*
if custom songs are enabled search for files in the config dir
if not, just use the newgrounds songs
--elnex
*/

std::vector<std::string> blacklist {};

if (auto blacklistPath = std::filesystem::exists(configDir / R"(blacklist.txt)")) {
std::ifstream blacklistFile((configDir / R"(blacklist.txt)"));
std::string blacklistString;
while (std::getline(blacklistFile, blacklistString)) {
if (blacklistString.starts_with('#')) continue;
blacklist.push_back(blacklistString);
geode::log::info("{}", blacklistString);
}
geode::log::info("Finished storing oldDNBMessages.");
}

if (customSongs) {
for (auto file : std::filesystem::directory_iterator(configDir)) {
if (!std::filesystem::exists(file)) continue;

auto filePath = file.path();
auto filePathString = filePath.string();

if (!Utils::isSupportedExtension(filePathString) || std::ranges::find(blacklist, filePathString) != blacklist.end()) continue;

geode::log::debug("Adding custom song: {}", filePath.filename().string());
SongManager::get().addSong(filePathString);
}
} else {
auto downloadManager = MusicDownloadManager::sharedState();

// for every downloaded song push it to the m_songs vector --elnex
/*
getDownloadedSongs() function call binding for macOS found
from ninXout (ARM) and hiimjustin000 (Intel + verification)
remarks:
- getDownloadedSongs() grabs both music library and newgrounds
songs lol.
- only reason it didn't work was because file support was limited to `.mp3`.
--raydeeux
*/
geode::cocos::CCArrayExt<SongInfoObject*> songs = downloadManager->getDownloadedSongs();
for (auto song : songs) {
if (!song) continue;

std::string songPath = downloadManager->pathForSong(song->m_songID);

if (!Utils::isSupportedExtension(songPath) || std::ranges::find(blacklist, songPath) != blacklist.end()) continue;

geode::log::debug("Adding Newgrounds/Music Library song: {}", songPath);
SongManager::get().addSong(songPath);
}
// same thing as NG but for music library as well --ninXout
// SPOILER: IT DOESN'T WORK CROSSPLATFORM (android specifically)! --raydeeux
/*
std::filesystem::path musicLibrarySongs = dirs::getGeodeDir().parent_path() / "Resources" / "songs";
if (!std::filesystem::exists(musicLibrarySongs)) return;
for (const std::filesystem::path& dirEntry : std::filesystem::recursive_directory_iterator(musicLibrarySongs)) {
if (!std::filesystem::exists(dirEntry)) continue;
std::string songPath = dirEntry.string();
if (!Utils::isSupportedExtension(songPath)) continue;
log::debug("Adding Music Library song: {}", songPath);
songManager.addSong(songPath);
}
*/
}
}

SongInfoObject* Utils::getSongInfoObject() {
if (Utils::getBool("useCustomSongs")) return nullptr;
if (SongManager::get().isOriginalMenuLoop()) return nullptr;

auto songFileName = SongManager::get().getCurrentSong();

// if it's not menuLoop.mp3, then get info
size_t dotPos = songFileName.find_last_of('.');

if (dotPos == std::string::npos) return nullptr;

std::string songFileNameAsAtring = songFileName.substr(0, dotPos);

geode::Result<int> songFileNameAsID = geode::utils::numFromString<int>(songFileNameAsAtring);

if (songFileNameAsID.isErr()) return nullptr;

return MusicDownloadManager::sharedState()->getSongInfoObject(songFileNameAsID.unwrap());
}

std::string Utils::getSongName() {
const auto songInfo = Utils::getSongInfoObject();
if (!songInfo) return "";
return songInfo->m_songName;
}

std::string Utils::getSongArtist() {
const auto songInfo = Utils::getSongInfoObject();
if (!songInfo) return "";
return songInfo->m_artistName;
}

int Utils::getSongID() {
const auto songInfo = Utils::getSongInfoObject();
if (!songInfo) return -1;
return songInfo->m_songID;
}
5 changes: 5 additions & 0 deletions src/Utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ class Utils {
static void generateNotification();
static void playlistModePLAndEPL();
static void copyCurrentSongName();
static void populateVector(bool);
static SongInfoObject* getSongInfoObject();
static std::string getSongName();
static std::string getSongArtist();
static int getSongID();
};
83 changes: 19 additions & 64 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,79 +2,34 @@
#include "Utils.hpp"
#include "Settings.hpp"
#include <Geode/loader/SettingEvent.hpp>
#include <Geode/loader/Dirs.hpp>

using namespace geode::prelude;

SongManager &songManager = SongManager::get();
std::filesystem::path configDir = Mod::get()->getConfigDir();

void populateVector(bool customSongs) {
/*
if custom songs are enabled search for files in the config dir
if not, just use the newgrounds songs
--elnex
*/
if (customSongs) {
for (auto file : std::filesystem::directory_iterator(configDir)) {
if (!std::filesystem::exists(file)) continue;

auto filePath = file.path();
auto filePathString = filePath.string();

if (!Utils::isSupportedExtension(filePathString)) continue;

log::debug("Adding custom song: {}", filePath.filename().string());
songManager.addSong(filePathString);
}
} else {
auto downloadManager = MusicDownloadManager::sharedState();

// for every downloaded song push it to the m_songs vector --elnex
/*
getDownloadedSongs() function call binding for macOS found
from ninXout (ARM) and hiimjustin000 (Intel + verification)
remarks:
- getDownloadedSongs() grabs both music library and newgrounds
songs lol.
- only reason it didn't work was because file support was limited to `.mp3`.
--raydeeux
*/
CCArrayExt<SongInfoObject*> songs = downloadManager->getDownloadedSongs();
for (auto song : songs) {
if (!song) continue;

std::string songPath = downloadManager->pathForSong(song->m_songID);

if (!Utils::isSupportedExtension(songPath)) continue;

log::debug("Adding Newgrounds/Music Library song: {}", songPath);
songManager.addSong(songPath);
}
// same thing as NG but for music library as well --ninXout
// SPOILER: IT DOESN'T WORK CROSSPLATFORM (android specifically)! --raydeeux
/*
std::filesystem::path musicLibrarySongs = dirs::getGeodeDir().parent_path() / "Resources" / "songs";
if (!std::filesystem::exists(musicLibrarySongs)) return;
for (const std::filesystem::path& dirEntry : std::filesystem::recursive_directory_iterator(musicLibrarySongs)) {
if (!std::filesystem::exists(dirEntry)) continue;
std::string songPath = dirEntry.string();
if (!Utils::isSupportedExtension(songPath)) continue;
$on_mod(Loaded) {
Mod::get()->addCustomSetting<MySettingValue>("configdir", "none");

log::debug("Adding Music Library song: {}", songPath);
songManager.addSong(songPath);
auto blacklistTxt = configDir / R"(blacklist.txt)";
if (!std::filesystem::exists(blacklistTxt)) {
std::string content = R"(# Welcome to the Menu Loop Randomizer song blacklist!
# Each line that doesn't start with a "#" will be treated as a blacklisted song file.
# All lines that start with a "#" are ignored. This means you can un-blacklist a song by adding "#" next to it.
# Reports of any crashes from lines that don't begin with "#" will be ignored. Lines that do not start with "#" will be treated as song files.
# Reports of any crashes from lines that don't begin with "#" will be ignored. Lines that do not start with "#" will be treated as song files.
# Reports of any crashes from lines that don't begin with "#" will be ignored. Lines that do not start with "#" will be treated as song files.
# Reports of any crashes from lines that don't begin with "#" will be ignored. Lines that do not start with "#" will be treated as song files.
# Reports of any crashes from lines that don't begin with "#" will be ignored. Lines that do not start with "#" will be treated as song files.
# --RayDeeUx
)";
auto result = utils::file::writeString(blacklistTxt, content);
if (result.isErr()) {
log::error("Error writing to blacklist.txt");
}
*/
}
}

$on_mod(Loaded) {
Mod::get()->addCustomSetting<MySettingValue>("configdir", "none");

populateVector(Utils::getBool("useCustomSongs"));
Utils::populateVector(Utils::getBool("useCustomSongs"));

std::string lastMenuLoop = Mod::get()->getSavedValue<std::string>("lastMenuLoop");
bool saveSongOnGameClose = Utils::getBool("saveSongOnGameClose");
Expand Down Expand Up @@ -103,7 +58,7 @@ void populateVector(bool customSongs) {
if they're ng songs also push the path bc we're going to use getPathForSong
--elnexreal
*/
populateVector(value);
Utils::populateVector(value);

// change the song when you click apply, stoi will not like custom names. --elnexreal

Expand Down

0 comments on commit dd6e86b

Please sign in to comment.