1. Parsing the MAME XML

    MAME's method of storing information about all its games is in the XML file, which is an absolute bear to look at. It's very organized, but almost to a fault. It's very huge, making it unweidly for text editors. Other applications that might want to use it also choke on its size. Luckily, it's faily easy to work around.

    First thing we need is a converter to get this into a nicer format. JSON is what all the cool kids use, so we'll give that a go.

    I'm using an xml2json library found here that suits my needs. We just need to get this into JSON, pick a tool that you like and run with it if you want. From there we convert from XML to JSON.

    ./xml2json.py -t xml2json -o ../mame0179.json ../mame0179.xml --strip-text

    Awesome, now we have the MAME database in JSON. So where do we go from here? For my needs, I want them split into individual files. Python to the rescue!

    #!/usr/bin/python import sys, json
    from pprint import pprint
    with open("./mame0179.json") as json_data:
    data = json.load(json_data) entries = len(data["mame"]["machine"]) for x in range(0,entries): outputfile = data["mame"]["machine"][x]["@name"] with open('./json/' + outputfile + '.json','w') as json_file: output = data["mame"]["machine"][x] pretty = json.dumps(output, sort_keys=True, indent=2) parsed = str(pretty) json_file.write(parsed)

    This loops through the massive JSON file and outputs each ROM set in its own file. From here we can import our JSON into some form of a database, read the files on their own, or pretty much whatever you want at this point.


  2. sending icinga 1.x notifications to slack

    i had some fun dealing with this. a good lot of my time is alloted to monitoring systems, so when i was told that a new team was going to play ping monkey i jumped on the opportunity to get them set up with everything they need to do the job coherently.

    previously we would send monitoring alarms to our hipchat server via hipsaint which works beautifully. we've moved to slack, so therefore our integration needs to be updated.

    step 1: you'll need to set up a new integration for your chat room via the slack web ui. you'll get a url hook as a result, which starts with https://hooks.slack.com/services/.

    step 2: you'll need a shell script that will parse the alarms and send them to slack. i save this to /usr/local/bin/slack.sh. you're welcome to put it wherever, as long as the icinga user has execute access to it. this is heavily based off of this script, just heavily modified and updated to work with slack's webhooks and using icinga instead of nagios.

    if [ "$ICINGA_SERVICESTATE" = "OK" ]
    curl -X POST --data "payload={\"channel\": \"${SLACK_CHANNEL}\", \"username\": \"${SLACK_USERNAME}\", \"icon_emoji\": \":vertical_traffic_light:\", \"text\": \"${ICON_EMOJI} host: $ICINGA_HOSTNAME\nservice: $ICINGA_SERVICEDISPLAYNAME\nstate: $ICINGA_SERVICESTATE\nmessage: $ICINGA_SERVICEOUTPUT\nrunbook: $ICINGA_SERVICENOTESURL\nlink: \"}" ${WEBHOOK_URL}

    step 3: modify your icinga instance to use your new script. this is going in the commands.cfg file but really it can go in any config file under objects.

        # 'notify-service-by-slack' command definition
        define command {
               command_name     notify-service-by-slack
               command_line      /usr/local/bin/slack.sh
        # 'notify-host-by-slack' command definition
        define command {
               command_name     notify-host-by-slack
               command_line      /usr/local/bin/slack.sh

    we also need to modify our contact so that it also sends the message over slack. find your contact that is currently getting alarms, and just add our new commands in separated by a comma.

    service_notification_commands   notify-by-email,notify-service-by-slack
    host_notification_commands      host-notify-by-email,notify-host-by-slack

    step 4: reload icinga.

    step 5 (optional): customize.

    the curl inside the script is utilizing icinga's macros to turn the variables into actual values. you can view the whole list here. please note that the format in the script prefixes ICINGA_ before each variable. i'm unsure why this is needed, the macros page doesn't talk about it.

    hopefully there is another admin out that that will find this useful.


  3. batch rename files in windows with powershell

    i had a bunch of files in a folder, and i needed to mass-rename them by replacing things. windows doesn't have a way of doing this from explorer (still! even in windows 10!). normally i would open a cygwin shell and do this via bash, but cygwin doesn't mount your network drives (where these files lived).

    so, powershell it is.

    Dir | Rename-Item –NewName { $_.name –replace "hate","love" }

    this replaces all instances of hate with love in the filename. the syntax is actually quite easy to understand, though i loathe the idea of using Title Case for commands. it just looks... ugly.

    when i finally stop spending money on other important things (like a new car) i'll buckle down and build a hackintosh and leave windows solely for the htpc. until then, it'll be my daily driver at home.


  4. moving files into subdirectories based off the first letter.

    when building an rpm-based distribution, the standard is to put packages in subdirectories based off their name. unfortunately, the distribution gods did not bless us with a script to automate the process.

    so, i wrote one.

    for i in ./*; do FOLDER=$(echo $i | cut -c 3-3 | tr '[a-z]' '[A-Z]'); mv $i ./$FOLDER/ ; done


  5. i'm an extremely lazy admin.

    so, i have this list of 7zipped files in a directory, right?

    i want to loop through and unzip them all into their own folders. this echo works.

    for z in *.7z ; do echo "7z x \"$z\" -o\"`basename "$z" .7z`\"" ; done
    7z x "my zip.7z" -o"my zip"
    7z x "my zip 2.7z" -o"my zip 2"
    7z x "my zip 3.7z" -o"my zip 3"

    but when i try it without, bash likes to toss some errors my way.

    `for z in *.7z ; do "7z x \"$z\" -o\"`basename "$z" .7z`\" ; done`       
    bash: 7z x "my zip.7z" -o"my zip": command not found

    so instead of trying to dig further into the problem, i copied the outputted echo into my buffer, ran screen, pasted, and detached.

    the neckbeard in me wants to find a proper way of doing this; the lazy coder in me is satisfied with having a functional answer.