kerbo_

A3PresetExport.py

May 27th, 2025 (edited)
774
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.23 KB | None | 0 0
  1. #!/usr/bin/python3
  2. #
  3. # A rough Python script to build an HTML mod list for ArmA 3 under Linux.
  4. # The launcher locks up when using the built in export feature.
  5. # Twitter: @Kerbo_
  6.  
  7. import os, sys, getopt, glob
  8. import xml.etree.ElementTree as ET
  9. import requests
  10. from html.parser import HTMLParser
  11. # avoid broken pipe
  12. from signal import signal, SIGPIPE, SIG_DFL  
  13. signal(SIGPIPE,SIG_DFL)
  14.  
  15. verbose = 0
  16.  
  17. class colors:
  18.     RED="\033[91m"
  19.     GREEN="\033[92m"
  20.     NC="\033[0m"
  21.  
  22. def usage():
  23.     print("Usage: " + os.path.basename(__file__) + " [options]\n")
  24.     print("Options:")
  25.     print("    -s   Steam presets directory")
  26.     print("    -l   list presets")
  27.     print("    -e   export preset")
  28.     print("")
  29.     print("    -h    show this output")
  30.     print("    -v    be verbose")
  31.  
  32. def error(msg):
  33.     sys.stderr.write(colors.RED + "Error: " +colors.NC + str(msg) + "\n")
  34.    
  35. def debug(msg):
  36.     global verbose
  37.     if verbose == 1:
  38.         sys.stderr.write(colors.RED + "DEBUG: " +colors.NC + str(msg) + "\n")
  39.  
  40. def main(argv):
  41.     global verbose
  42.     steamPresetDir = None
  43.     listMode = None
  44.     exportName = None
  45.     workshopURLBase = "https://steamcommunity.com/sharedfiles/filedetails/?id="
  46.  
  47.     # <div class="workshopItemTitle">Antistasi - The Mod</div>
  48.     class WorkshopParser(HTMLParser):
  49.         def __init__(self):
  50.             super().__init__()
  51.             self.in_name_tag = False
  52.             self.name = ""
  53.         def handle_starttag(self, tag, attrs):
  54.             attrs = dict(attrs)
  55.             if tag == 'div' and attrs.get('class') == 'workshopItemTitle':
  56.                 self.in_name_tag = True
  57.         def handle_data(self, data):
  58.             if self.in_name_tag:
  59.                 self.name = data
  60.                 self.in_name_tag = False
  61.  
  62.     try:
  63.         opts, args = getopt.getopt(argv, "hvs:le:")
  64.     except getopt.GetoptError:
  65.         usage()
  66.         sys.exit(2)
  67.     for opt, arg in opts:
  68.         if opt == '-s':
  69.             steamPresetDir = arg
  70.         if opt == '-l':
  71.             listMode = True
  72.         if opt == '-e':
  73.             exportName = arg
  74.         if opt == "-h":
  75.             usage()
  76.             sys.exit()
  77.         if opt == "-v":
  78.             verbose = 1
  79.  
  80.     if steamPresetDir is None:
  81.         error("-s is required")
  82.         usage()
  83.         sys.exit(1)
  84.  
  85.     if exportName is None and not listMode:
  86.         error("-e or -l is required")
  87.         usage()
  88.         sys.exit(1)
  89.  
  90.     if exportName is not None and listMode:
  91.         error("-l and -e are mutually exclusive")
  92.         usage()
  93.         sys.exit(1)
  94.  
  95.     if listMode:
  96.         if not os.path.isdir(steamPresetDir):
  97.             error(f"Directory {steamPresetDir} doesn't exist")
  98.             sys.exit(1)
  99.         os.chdir(steamPresetDir)
  100.         for file in glob.glob("*.preset2"):
  101.             print(os.path.splitext(file)[0])
  102.     else:
  103.         presetFileName = f"{steamPresetDir}/{exportName}.preset2"
  104.         if not os.path.isfile(presetFileName):
  105.             error(f"Preset {presetFileName} not found")
  106.             sys.exit(1)
  107.  
  108.         debug(f"Parsing {presetFileName}")
  109.         tree = ET.parse(presetFileName)
  110.         root = tree.getroot()
  111.         pids = root.find('published-ids')
  112.         ids = []
  113.  
  114.         for pid in pids.findall('id'):
  115.             source,steamid = pid.text.split(':')
  116.             if source == 'steam':
  117.                 ids.append(steamid)
  118.         idnames = {}
  119.         for id in ids:
  120.             debug(f"Fetching page for {id}")
  121.             response = requests.get(f"{workshopURLBase}{id}")
  122.             if response.ok:
  123.                 parser = WorkshopParser()
  124.                 parser.feed(response.text)
  125.                 name = parser.name
  126.                 debug(f"Found {id} {name}")
  127.                 idnames[id] = name
  128.  
  129.         html = "<html><head><title>ArmA 3</title></head><body><table>\n"
  130.         sorted_items = sorted(idnames.items(), key=lambda kv: (kv[1], [kv[0]]))
  131.         for item in sorted_items:
  132.             id = item[0]
  133.             name = item[1]
  134.             html += f"<tr><td>{name}</td><td><a href=\"{workshopURLBase}{id}\">{workshopURLBase}{id}</a>\n"
  135.         html += "</table></body></html>"
  136.         print(html)
  137.     sys.exit()
  138.  
  139. if __name__ == "__main__":
  140.     main(sys.argv[1:])
Advertisement
Add Comment
Please, Sign In to add comment