#!/usr/bin/env python3 # Shoutout to VVD on QuakeNet:#qw-dev. It's because of him not understanding why user's homedir # overrides are a good thing, even for server software, that I even had to write this bullshit. # Seriously. This entire script wouldn't be necessary if mvdsv just supported directory layering like # ezquake, darkplaces(-ded), zandronum(-ded), etc. all do. C'mon. Get with the times. import os import pwd import datetime import json import subprocess from urllib.request import urlopen timestamp = datetime.datetime.now().strftime('%Y.%m.%d_%H%M.%S') user = pwd.getpwuid(os.geteuid()).pw_name homedir = os.environ['HOME'] nquakedir = homedir + '/.nquakesv' pkgdir = '/usr/share/nquakesv' def getVer(): try: ver = 'unknown' pkginfo = subprocess.check_output(['pacman', '-Qi', 'nquakesv']).decode('utf-8').splitlines() for line in pkginfo: if line.startswith('Version'): ver = line.split(':')[1].strip() break except: ver = 'unknown' return(ver) # Probably not actually necessary... #def symLinker(srcdir, destparent, filext = False): # for f in os.listdir(srcdir): # # We only want files # if not os.path.isfile('{0}/{1}'.format(srcdir, f)): # continue # if filext: # if f.endswith(filext): # os.symlink('{0}/{1}'.format(srcdir, f), # '{0}/{1}'.format(destparent, f)) # else: # os.symlink('{0}/{1}'.format(srcdir, f), # '{0}/{1}'.format(destparent, f)) def populateTree(): # First we'll do the id1/ dir. It's easy enough. os.symlink('{0}/id1/pak0.pak.DEMO'.format(pkgdir), '{0}/id1/pak0.pak'.format(nquakedir)) # Sometimes other games/engines/whatever might be installed that require the retail pak placed here. if os.path.isfile('/opt/quake/id1/pak1.pak'): os.symlink('/opt/quake/id1/pak1.pak', '{0}/id1/pak1.pak'.format(nquakedir)) # Now the bulk of it. for rootdir in ('ktx', 'qw', 'qtv'): for root, dirs, files in os.walk('{0}/{1}'.format(pkgdir, rootdir)): destpath = root.replace(pkgdir, nquakedir) for f in files: os.symlink('{0}/{1}'.format(root, f), '{0}/{1}'.format(destpath, f)) def buildRootTree(ver = False): # We dont need these dirs. # Matches "greedily"- that is, "addons" will match e.g. addons/somedir/someotherdir # So be as explicit as possible. direxcludes = ['addons', 'run'] # And these should be links to /usr/share/nquakesv/ # These, unlike the above, are *inherently* explicit- the path must be exact. dirlinks = [] if ver == False: ver = getVer() # Overwriting is bad, mmk? if os.path.isdir(nquakedir): os.rename(nquakedir, '{0}.bak_{1}'.format(nquakedir, timestamp)) os.makedirs(nquakedir, exist_ok = True) # Some meta information with open(nquakedir + '/VERSION', 'w') as f: f.write('Generated on nquakesv package version {0}\n'.format(ver)) with open(nquakedir + '/admin', 'w') as f: f.write(user + '\n') with urlopen('https://ipinfo.io/ip') as ipfetch: ipaddr = ipfetch.read().decode('utf-8') with open(nquakedir + '/hostdns', 'w') as f: f.write(ipaddr) with open(nquakedir + '/ip', 'w') as f: f.write(ipaddr) with open(nquakedir + '/hostname', 'w') as f: f.write('nQuake running on Arch Linux\n') with open(nquakedir + '/install_dir', 'w') as f: f.write(nquakedir + '\n') with open(nquakedir + '/README', 'w') as f: f.write("""Please review the following files in this directory to ensure that they contain the correct information. admin - your name and contact info. Typically, this is in the form of: Handle (email@address.tld) hostdns - the DNS entry of your server. If you don't have one, just map this to your external IP address. hostname - the name used for server browsers. install_dir - leave this unchanged. ip - your external/WAN-accessible IP address.""") f.write('\n\nNote that these files are not used by default, but are compatible with the upstream nquakesv scripts- so if you opt to use them, you can.\n') # Generated from a vanilla from-"source" nquakesv install # and generated by running the following inside the directory: # find ./ -type d -printf "%P\n" | sed -e '/^$/d' | sort with open('{0}/dirtree.lst'.format(pkgdir), 'r') as raw: dirtree = raw.read().splitlines() # Generated from a vanilla from-"source" nquakesv install # and generated by running the following inside the directory: # for l in $(find ./ -type l); do echo -n "${l} " | sed -re "s@^\./@@g"; readlink ${l}; done with open('{0}/linktree.lst'.format(pkgdir), 'r') as raw: linktree = raw.read().splitlines() # Walk the paths and build the tree. for d in dirtree: makeme = True for e in direxcludes: if d.startswith(e): makeme = False break if makeme == True and d in dirlinks: os.symlink('{0}/{1}'.format(pkgdir, d), '{0}/{1}'.format(nquakedir, d)) elif makeme == True: os.makedirs('{0}/{1}'.format(nquakedir, d), exist_ok = True) for l in linktree: src = l.split()[1] dest = l.split()[0] makeme = True for e in direxcludes: if dest.startswith(e): makeme = False break if makeme == True: destpath = '{0}/{1}'.format(nquakedir, dest) if not os.path.isdir(os.path.dirname(destpath)): os.makedirs(os.path.dirname(destpath)) os.symlink(src, destpath) def main(): buildRootTree() populateTree() print('Setup has completed successfully. Please review ~/.nquakesv/README') if __name__ == '__main__': main()