Merge pull request #48 from PaulCombal/feat-cli

Added CLI commands
This commit is contained in:
PaulCombal 2020-01-10 18:23:21 +01:00 committed by GitHub
commit 1091c4daa5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 2407 additions and 33 deletions

View File

@ -49,12 +49,26 @@ Run SamRewritten by opening the corresponding desktop entry, or by using the `sa
# Command line options # Command line options
I know you linux geeks love to use command line options. I know you linux geeks love to use command line options! SamRewritten has a few, let us know if you want to see more!
We have big ambitions for SamRewritten, and I believe many of them are related to these command-line options, so stay put, because that list will be growing soon!
* -a \<appid\> ```
* Prevents the window from showing and sets your status to "In Game" Usage:
* `./bin/launch.sh -a 10` will idle Counter Strike samrewritten [AppId] [OPTION...]
--apps Get the list of your owned apps.
-h, --help Show CLI help.
-a, --app arg Set which AppId you want to use. Same as using positional
'AppId'
-i, --idle Set your Steam profile as 'ingame'. Ctrl+c to stop.
--ls Display stats (TODO) and achievements for selected app.
--sort arg Sort option for --ls. You can leave empty or set to
'unlock_rate'
--unlock arg Unlock achievements for an AppId. Separate achievement
names by a comma.
--lock arg Lock achievements for an AppId. Separate achievement
names by a comma.
--launch Actually just launch the app.
```
--- ---

View File

@ -1,46 +1,192 @@
#include "cli_funcs.h" #include "cli_funcs.h"
#include "../controller/MySteam.h" #include "../controller/MySteam.h"
#include "../globals.h" #include "../globals.h"
#include "../common/cxxopts.hpp"
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <csignal> #include <csignal>
#include <unistd.h> #include <unistd.h>
void handle_sigint_cli(int signum) { void handle_sigint_cli(int signum)
{
std::cout << "Quitting cli idling" << std::endl; std::cout << "Quitting cli idling" << std::endl;
g_steam->quit_game(); g_steam->quit_game();
exit(0); exit(EXIT_SUCCESS);
} }
void idle_app(std::string appid) { void idle_app(AppId_t appid)
{
std::cout << "Idling from command line " << appid << std::endl; std::cout << "Idling from command line " << appid << std::endl;
AppId_t realid = strtoul(appid.c_str(), NULL, 10); g_steam->launch_app(appid);
g_steam->launch_game(realid);
signal(SIGINT, handle_sigint_cli); signal(SIGINT, handle_sigint_cli);
// Wait for ctrl+c, so we can kill both processes, otherwise
// GUI process will exit while game process still goes on
for(;;) {
sleep(10000);
}
}
bool compareByUnlockRateDesc(const Achievement_t &a, const Achievement_t &b)
{
return a.global_achieved_rate > b.global_achieved_rate;
} }
bool go_cli_mode(int argc, char* argv[]) { bool go_cli_mode(int argc, char* argv[]) {
bool cli = false; cxxopts::Options options(argv[0], "Steam Achievements Manager");
int opt;
while((opt = getopt(argc, argv, ":a:")) != -1) options
{ .positional_help("[AppId]")
switch(opt) .show_positional_help()
{ .add_options()
case 'a': ("apps", "Get the list of your owned apps.")
const std::string appid = std::string(optarg); ("h,help", "Show CLI help.")
idle_app(appid); ("a,app", "Set which AppId you want to use. Same as using positional 'AppId'", cxxopts::value<AppId_t>())
cli = true; ("i,idle", "Set your Steam profile as 'ingame'. Ctrl+c to stop.")
break; ("ls", "Display stats (TODO) and achievements for selected app.")
} ("sort", "Sort option for --ls. You can leave empty or set to 'unlock_rate'", cxxopts::value<std::string>())
} ("unlock", "Unlock achievements for an AppId. Separate achievement names by a comma.", cxxopts::value<std::vector<std::string>>())
("lock", "Lock achievements for an AppId. Separate achievement names by a comma.", cxxopts::value<std::vector<std::string>>())
("launch", "Actually just launch the app.");
// If cli, wait for ctrl+c, so we can kill both processes, otherwise
// GUI process will exit while game process still goes on options.parse_positional({"app"});
if ( cli ) {
for(;;) { auto result = options.parse(argc, argv);
sleep(10000); bool cli = false;
AppId_t app = 0;
if (result.count("help"))
{
std::cout << options.help() << std::endl;
return true;
}
if (result.count("app") > 0)
{
cli = true;
app = result["app"].as<AppId_t>();
}
if (result.count("apps") > 0)
{
cli = true;
g_steam->refresh_owned_apps();
auto apps = g_steam->get_subscribed_apps();
std::cout << "AppId \t App Name" << std::endl;
for ( Game_t& it : apps )
{
std::cout << it.app_id << "\t " << it.app_name << std::endl;
} }
} }
if (result.count("idle") > 0)
{
cli = true;
if (app == 0)
{
std::cout << "Please provide an AppId argument before idling." << std::endl;
return cli;
}
idle_app(app);
}
if (result.count("ls") > 0) {
cli = true;
if (app == 0)
{
std::cout << "Please provide an AppId argument before listing stats." << std::endl;
return cli;
}
g_steam->launch_app(app);
g_steam->refresh_achievements();
auto achievements = g_steam->get_achievements();
g_steam->quit_game();
if (result.count("sort") > 0)
{
const std::string sort = result["sort"].as<std::string>();
if (sort == "unlock_rate")
{
std::sort(achievements.begin(), achievements.end(), compareByUnlockRateDesc);
std::cout << "Sorted by global unlock rate\n" << std::endl;
}
}
// https://github.com/haarcuba/cpp-text-table -> worth? nah but best I've found
std::cout << "API Name \t\tName \t\tDescription \t\tUnlock rate \t\tUnlocked" << std::endl;
std::cout << "--------------------------------------------------------------" << std::endl;
for ( Achievement_t& it : achievements )
{
std::cout
<< it.id << " \t"
<< it.name << " \t"
<< it.desc << " \t"
<< it.global_achieved_rate << "% \t"
<< (it.achieved ? "✔️" : "") << std::endl;
}
}
if (result.count("unlock") > 0)
{
if (app == 0)
{
std::cout << "Please provide an AppId argument before unlocking achievements." << std::endl;
return true;
}
cli = true;
const std::vector<std::string> ids = result["unlock"].as<std::vector<std::string>>();
for ( std::string it : ids )
{
g_steam->add_modification_ach(it, true);
}
g_steam->launch_app(app);
g_steam->commit_changes();
g_steam->quit_game();
}
if (result.count("lock") > 0)
{
if (app == 0)
{
std::cout << "Please provide an AppId argument before relocking achievements." << std::endl;
return true;
}
cli = true;
const std::vector<std::string> ids = result["lock"].as<std::vector<std::string>>();
for ( std::string it : ids )
{
g_steam->add_modification_ach(it, false);
}
g_steam->launch_app(app);
g_steam->commit_changes();
g_steam->quit_game();
}
if (result.count("launch") > 0)
{
if (app == 0)
{
std::cout << "Please provide an AppId argument before launching the app." << std::endl;
return true;
}
std::cout << "Launching app with Steam. Make sure you have xdg-open installed." << std::endl;
system(("xdg-open steam://run/" + std::to_string(app)).c_str());
}
return cli; return cli;
} }

2214
src/common/cxxopts.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -65,7 +65,7 @@ MySteam::get_instance() {
* Fakes a new game being launched. Keeps running in the background until quit_game is called. * Fakes a new game being launched. Keeps running in the background until quit_game is called.
*/ */
bool bool
MySteam::launch_game(AppId_t appID) { MySteam::launch_app(AppId_t appID) {
// Print an error if a game is already launched // Print an error if a game is already launched
// allow multiple games at the same time in the future via new window launching // allow multiple games at the same time in the future via new window launching
@ -84,7 +84,7 @@ MySteam::launch_game(AppId_t appID) {
m_app_id = appID; m_app_id = appID;
return true; return true;
} }
// => launch_game // => launch_app
/** /**

View File

@ -31,10 +31,10 @@ public:
* given appId. Returns false if this process failed to launch. * given appId. Returns false if this process failed to launch.
* The process may start successfully but fail during execution. * The process may start successfully but fail during execution.
*/ */
bool launch_game(AppId_t appId); bool launch_app(AppId_t appId);
/** /**
* Stops the process started with the above method launch_game. * Stops the process started with the above method launch_app.
* Returns true if a process was successfully stopped. * Returns true if a process was successfully stopped.
*/ */
bool quit_game(); bool quit_game();

View File

@ -126,7 +126,7 @@ MainPickerWindow::on_game_row_activated(Gtk::ListBoxRow* row) {
} }
switch_to_achievement_page(); switch_to_achievement_page();
g_steam->launch_game(appid); g_steam->launch_app(appid);
m_async_loader.populate_achievements(); m_async_loader.populate_achievements();
} }
// => on_game_row_activated // => on_game_row_activated