2022-11-27 19:19:11 +01:00
#!/usr/bin/env python3
import os
import subprocess
import argparse
from shutil import unpack_archive
import yaml
import mergedeep
from lib import handlers
from appdirs import user_data_dir , user_config_dir
config = {
' global ' : {
' game_dir ' : os . path . join ( user_data_dir ( ) , ' minitch ' ) ,
' os ' : ' linux '
} ,
' games ' : { }
}
def read_config ( ) :
global config
path = os . path . join ( user_config_dir ( ) , ' minitchrc ' )
try :
with open ( path , ' r ' ) as f :
c = { * * config , * * yaml . safe_load ( f ) }
mergedeep . merge ( config , c )
except FileNotFoundError :
pass
except yaml . YAMLError :
raise SystemExit ( ' Invalid config ' )
def write_config ( ) :
global config
path = os . path . join ( user_config_dir ( ) , ' minitchrc ' )
with open ( path , ' w ' ) as f :
yaml . dump ( config , f , default_flow_style = False )
def parse_config ( args ) :
if args . api_key :
config [ ' global ' ] [ ' api_key ' ] = args . api_key
def parse_search ( args ) :
global config
if not ' api_key ' in config [ ' global ' ] :
raise SystemExit ( ' You have to set your api key first. ' )
game_handler = handlers . GameHandler ( config [ ' global ' ] [ ' api_key ' ] , output_format = args . output )
game_handler . find ( args . query )
def parse_uploads ( args ) :
global config
if not ' api_key ' in config [ ' global ' ] :
raise SystemExit ( ' You have to set your api key first. ' )
game_handler = handlers . GameHandler ( config [ ' global ' ] [ ' api_key ' ] , output_format = args . output )
game_handler . uploads ( args . game_id )
def install_game ( game_id , dst_path , output_format ) :
global config
# Download game
game_handler = handlers . GameHandler ( config [ ' global ' ] [ ' api_key ' ] , output_format = output_format )
dst , upload , meta = game_handler . download ( game_id , dst_path , os_type = config [ ' global ' ] [ ' os ' ] )
# Unpack game
print ( ' Extracting... ' )
unpack_archive ( dst , dst_path )
return dst , upload , meta
def parse_install ( args ) :
global config
# Create target directory
game_path = os . path . join ( config [ ' global ' ] [ ' game_dir ' ] , args . game_id )
os . makedirs ( game_path , exist_ok = True )
dst , upload , meta = install_game ( args . game_id , game_path , args . output )
# Write game to config
config [ ' games ' ] [ args . game_id ] = {
' path ' : game_path ,
' last_update ' : upload [ ' updated_at ' ] ,
' url ' : meta [ ' url ' ] ,
' title ' : meta [ ' title ' ] ,
' description ' : meta [ ' short_text ' ]
}
print ( ' FYI: As itch.io does not have any information on how to execute the game, you have to set the executable manually on first run with the --executable option ' )
def parser_run ( args ) :
global config
if not args . game_id in config [ ' games ' ] :
raise SystemExit ( ' Game is not installed. ' )
if args . executable :
config [ ' games ' ] [ args . game_id ] [ ' executable ' ] = args . executable
if not ' executable ' in config [ ' games ' ] [ args . game_id ] :
raise SystemExit ( ' You have to define the executable before you can run the game. ' )
if args . update :
game_handler = handlers . GameHandler ( config [ ' global ' ] [ ' api_key ' ] , output_format = args . output )
print ( ' Checking for updates... ' )
if game_handler . check_update ( args . game_id , config [ ' games ' ] [ args . game_id ] [ ' last_update ' ] , config [ ' global ' ] [ ' os ' ] ) :
dst , upload , meta = install_game ( args . game_id , config [ ' games ' ] [ args . game_id ] [ ' path ' ] , args . output )
config [ ' games ' ] [ args . game_id ] [ ' last_update ' ] = upload [ ' updated_at ' ]
# Run executable
os . chdir ( config [ ' games ' ] [ args . game_id ] [ ' path ' ] )
os . chmod ( config [ ' games ' ] [ args . game_id ] [ ' executable ' ] , 755 )
subprocess . run ( config [ ' games ' ] [ args . game_id ] [ ' executable ' ] )
def parser_list ( args ) :
global config
game_handler = handlers . GameHandler ( config [ ' global ' ] [ ' api_key ' ] , output_format = args . output )
game_handler . list_local ( config [ ' games ' ] )
def main ( ) :
read_config ( )
parser = argparse . ArgumentParser ( description = ' Tiny little itch.io client ' )
subparsers = parser . add_subparsers ( title = ' subcommands ' , description = ' valid subcommands ' , help = ' additional help ' )
# Global arguments
parser . add_argument ( ' --output ' , ' -o ' , choices = ( ' table ' , ' json ' ) , default = ' table ' , help = ' set the output format ' )
# Parser for "config" command
parser_config = subparsers . add_parser ( ' config ' , aliases = [ ' c ' ] , help = ' config help ' )
parser_config . add_argument ( ' --api_key ' , type = str , help = ' set api key ' )
parser_config . set_defaults ( func = parse_config )
# Parser for "search" command
parser_search = subparsers . add_parser ( ' search ' , aliases = [ ' s ' ] , help = ' search help ' )
parser_search . add_argument ( ' query ' , type = str , help = ' the search query ' )
parser_search . set_defaults ( func = parse_search )
# Parser for "uploads" command
parser_search = subparsers . add_parser ( ' uploads ' , help = ' uploads help ' )
parser_search . add_argument ( ' game_id ' , type = str , help = ' game_id to query ' )
parser_search . set_defaults ( func = parse_uploads )
# Parser for "install" command
parser_search = subparsers . add_parser ( ' install ' , aliases = [ ' i ' ] , help = ' install help ' )
parser_search . add_argument ( ' game_id ' , type = str , help = ' game_id to query ' )
parser_search . set_defaults ( func = parse_install )
# Parser for "run" command
parser_search = subparsers . add_parser ( ' run ' , aliases = [ ' r ' ] , help = ' run help ' )
parser_search . add_argument ( ' game_id ' , type = str , help = ' game_id to run ' )
parser_search . add_argument ( ' --executable ' , ' -e ' , type = str , help = ' set executable relative to game path (e.g. -e " chess_2_linux_v2/chess 2.x86_64 " ) ' )
parser_search . add_argument ( ' --update ' , ' -u ' , help = ' check for update before running ' , action = ' store_true ' )
parser_search . set_defaults ( func = parser_run )
# Parser for "list" command
parser_search = subparsers . add_parser ( ' list ' , aliases = [ ' l ' ] , help = ' list help ' )
parser_search . set_defaults ( func = parser_list )
args = parser . parse_args ( )
2022-11-27 19:49:52 +01:00
try :
args . func ( args )
except AttributeError :
parser . error ( ' too few arguments ' )
2022-11-27 19:19:11 +01:00
write_config ( )
if __name__ == " __main__ " :
main ( )