Syntax highlighting.

Syntax highlighting.

#!/usr/bin/env ruby

require File.expand_path('../../lib/terminal.com', __FILE__)
require 'json'
require 'coderay'

# TODO (later): Don't force tokens for methods that don't need them.
# TODO (maybe): DBG=ruby/curl/off. Curl would output curl commands.

def log(message)
  STDERR.puts("\x1B[1;30m~ #{message}\x1B[0m") unless ENV['DBG'] == 'off'
end

def dbg(command, arguments, **options)
  log "Terminal::API.#{command}(" +
    ("#{arguments.inspect[1..-2]}" unless arguments.empty?).to_s +
    (", #{options.inspect[1..-2]}" unless options.empty?).to_s +
    ")\n"
end

def print_as_json(data)
  json = JSON.pretty_generate(data)
  puts CodeRay.scan(json, :json).term
end

def api_call(command, arguments, options)
  # Ruby **args expansion doesn't work as I expected, that's why the extra if.
  # pry(main)> def xxx(*args) args; end
  # pry(main)> xxx(**{})
  # => [{}]
  if options
    dbg command, arguments, options
    print_as_json Terminal::API.send(command, *arguments, **options)
  else
    dbg command, arguments
    print_as_json Terminal::API.send(command, *arguments)
  end
end

def usage
  DATA.read
end

# -h | --help
if ARGV.include?('-h') || ARGV.include?('--help')
  puts usage; exit
end

if ARGV.first == 'configure'
  puts <<-EOF
Welcome to the Terminal.com CLI client.

We don't want to bother you with asking for credentials every single time,
so instead we'll ask you for them now and save them to ~/.terminal.com.json.

Alright?

Go to https://www.terminal.com/settings/api

And:
  EOF

  print "1. Paste your user token here: "
  user_token = STDIN.readline.chomp
  print "2. Generate an access token if you don't have one and paste it here: "
  access_token = STDIN.readline.chomp

  File.open(File.expand_path('~/.terminal.com.json'), 'w') do |file|
    file.puts({user_token: user_token, access_token: access_token}.to_json)
  end

  puts "\nYour tokens were saved to ~/.terminal.com.json."
  exit
end

# Tokens.
# TODO: Add --no-config
if File.exist?(File.expand_path('~/.terminal.com.json'))
  config = JSON.parse(File.read(File.expand_path('~/.terminal.com.json')))
  user_token, access_token = config.values_at('user_token', 'access_token')

  if user_token.nil?
    abort("Config file found, but user_token is missing. Add user_token key.")
  end

  if access_token.nil?
    abort("Config file found, but access_token is missing. Add access_token key.")
  end
else
  user_token, access_token = ARGV.shift(2)

  if user_token.nil? || access_token.nil?
    STDERR.puts("Credentials missing.\n\n")
    abort usage
  end
end

if ARGV.empty?
  STDERR.puts("Command missing.\n\n")
  abort usage
else
  command = ARGV.shift

  unless Terminal::API.respond_to?(command)
    STDERR.puts("Invalid command '#{command}'.\n\n")
    abort usage
  end

  # Not every method requires authentication.
  method_args = Terminal::API.method(command).parameters.map(&:last)

  if method_args.include?(:options)
    options = ARGV.reduce(Hash.new) do |buffer, argument|
      if argument.match(/^--(.+)=(.+)$/)
        buffer[$1.to_sym] = $2
      elsif argument.match(/^--no-(.+)$/)
        buffer[$1.to_sym] = false
      elsif argument.match(/^--(.+)$/)
        buffer[$1.to_sym] = true
      end

      buffer
    end

    ARGV.delete_if { |argument| argument.start_with?('--') }
  end

  arguments = []
  arguments << user_token if method_args.include?(:user_token)
  arguments << access_token if method_args.include?(:access_token)
  arguments.push(*ARGV)

  api_call(command, arguments, options)
end

__END__
== Usage ==

1. Explicit configuration.

terminal.com [user_token] [access_token] [command]

2. With a configuration file.

First run terminal.com configure. This command will
save your credentials into ~/.terminal.com.json.
{"user_token": "...", "access_token": "..."}

Then you can run commands like so:

terminal.com [command]

== Commands ==

These are identical to what the API provides.

# BROWSE SNAPSHOTS & USERS #
get_snapshot snapshot_id
get_profile username
list_public_snapshots [options]
  --username=value
  --tag=value
  --featured
  --title=value
  --page=value
  --perPage=value
  --sortby=value

count_public_snapshots [options]
  --username=value
  --tag=value
  --featured
  --title=value

# CREATE AND MANAGE TERMINALS #
list_terminals user_token access_token
get_terminal user_token access_token [options]
  --container_key=value
  --subdomain=value

start_snapshot user_token access_token snapshot_id [options]
  --cpu=value
  --ram=value
  --temporary
  --name=value
  --autopause=value
  --startup_script=value
  --custom_data=value

delete_terminal user_token access_token container_key
restart_terminal user_token access_token container_key
pause_terminal user_token access_token container_key
resume_terminal user_token access_token container_key
edit_terminal user_token access_token container_key [options]
  --cpu=value
  --ram=value
  --diskspace=value
  --name=value

# CREATE AND MANAGE SNAPSHOTS #
list_snapshots user_token access_token [options]
  --username=value
  --tag=value
  --featured
  --title=value
  --page=value
  --perPage=value

count_snapshots user_token access_token [options]
  --username=value
  --tag=value
  --featured
  --title=value

delete_snapshot user_token access_token snapshot_id
edit_snapshot user_token access_token snapshot_id [options]
  --body=value
  --title=value
  --readme=value
  --public
  --custom_data=value

snapshot_terminal user_token access_token container_key [options]
  --body=value
  --title=value
  --readme=value
  --public

# MANAGE TERMINAL ACCESS #
add_terminal_links user_token access_token container_key *links
remove_terminal_links user_token access_token container_key *links
list_terminal_access user_token access_token container_key
edit_terminal_access user_token access_token container_key [options]
  --is_public_list
  --access_rules=value

# MANAGE TERMINAL DNS & DOMAINS #
get_cname_records user_token access_token
add_domain_to_pool user_token access_token domain
remove_domain_from_pool user_token access_token domain
add_cname_record user_token access_token domain subdomain port
remove_cname_record user_token access_token domain

# MANAGE TERMINAL IDLE SETTINGS #
set_terminal_idle_settings user_token access_token container_key action *triggers
get_terminal_idle_settings user_token access_token container_key

# MANAGE USAGE & CREDITS #
instance_types
instance_price instance_type status (defaults to running)
balance user_token access_token
balance_added user_token access_token
gift user_token access_token email cents
burn_history user_token access_token
terminal_usage_history user_token access_token
burn_state user_token access_token
burn_estimates user_token access_token

# MANAGE SSH PUBLIC KEYS #
add_authorized_key_to_terminal user_token access_token container_key publicKey
add_authorized_key_to_ssh_proxy user_token access_token name publicKey
del_authorized_key_from_ssh_proxy user_token access_token name fingerprint
get_authorized_keys_from_ssh_proxy user_token access_token

# OTHER #
who_am_i user_token, access_token
request_progress request_id

#!/usr/bin/env ruby

require File.expand_path('../../lib/terminal.com', __FILE__)
require 'json'

# TODO (later): Don't force tokens for methods that don't need them.
# TODO: terminal.com configure -> ask for the credentials and save them.

def usage
  DATA.read
end

# -h | --help
if ARGV.include?('-h') || ARGV.include?('--help')
  puts usage; exit
end

if ARGV.first == 'configure'
  puts <<-EOF
Welcome to the Terminal.com CLI client.

We don't want to bother you with asking for credentials every single time,
so instead we'll ask you for them now and save them to ~/.terminal.com.json.

Alright?

Go to https://www.terminal.com/settings/api

And:
  EOF

  print "1. Paste your user token here: "
  user_token = STDIN.readline.chomp
  print "2. Generate an access token if you don't have one and paste it here: "
  access_token = STDIN.readline.chomp

  File.open(File.expand_path('~/.terminal.com.json'), 'w') do |file|
    file.puts({user_token: user_token, access_token: access_token}.to_json)
  end

  puts "\nYour tokens were saved to ~/.terminal.com.json."
  exit
end

# Tokens.
# TODO: Add --no-config
if File.exist?(File.expand_path('~/.terminal.com.json'))
  config = JSON.parse(File.read(File.expand_path('~/.terminal.com.json')))
  user_token, access_token = config.values_at('user_token', 'access_token')

  if user_token.nil?
    abort("Config file found, but user_token is missing. Add user_token key.")
  end

  if access_token.nil?
    abort("Config file found, but access_token is missing. Add access_token key.")
  end
else
  user_token, access_token = ARGV.shift(2)

  if user_token.nil? || access_token.nil?
    STDERR.puts("Credentials missing.\n\n")
    abort usage
  end
end

if ARGV.empty?
  STDERR.puts("Command missing.\n\n")
  abort usage
else
  command = ARGV.shift

  unless Terminal::API.respond_to?(command)
    STDERR.puts("Invalid command '#{command}'.\n\n")
    abort usage
  end

  # Not every method requires authentication.
  method_args = Terminal::API.method(command).parameters.map(&:last)

  if method_args.include?(:options)
    options = ARGV.reduce(Hash.new) do |buffer, argument|
      if argument.match(/^--(.+)=(.+)$/)
        ARGV.delete(argument)
        buffer[$1.to_sym] = $2
      elsif argument.match(/^--no-(.+)$/)
        ARGV.delete(argument)
        buffer[$1.to_sym] = false
      elsif argument.match(/^--(.+)$/)
        ARGV.delete(argument)
        buffer[$1.to_sym] = true
      end

      buffer
    end
  end

  arguments = []
  arguments << user_token if method_args.include?(:user_token)
  arguments << access_token if method_args.include?(:access_token)
  arguments.push(*ARGV)

  # Ruby **args expansion doesn't work as I expected, that's why the extra if.
  # pry(main)> def xxx(*args) args; end
  # pry(main)> xxx(**{})
  # => [{}]
  if options
    STDERR.puts("~ Terminal::API.#{command}(*#{arguments.inspect}, **#{options.inspect})\n\n")
    puts Terminal::API.send(command, *arguments, **options)
  else
    STDERR.puts("~ Terminal::API.#{command}(*#{arguments.inspect})\n\n")
    puts Terminal::API.send(command, *arguments)
  end
end

__END__
== Usage ==

1. Explicit configuration.

terminal.com [user_token] [access_token] [command]

2. With a configuration file.

First run terminal.com configure. This command will
save your credentials into ~/.terminal.com.json.
{"user_token": "...", "access_token": "..."}

Then you can run commands like so:

terminal.com [command]

== Commands ==

These are identical to what the API provides.

# BROWSE SNAPSHOTS & USERS #
get_snapshot snapshot_id
get_profile username
list_public_snapshots [options]
  --username=value
  --tag=value
  --featured
  --title=value
  --page=value
  --perPage=value
  --sortby=value

count_public_snapshots [options]
  --username=value
  --tag=value
  --featured
  --title=value

# CREATE AND MANAGE TERMINALS #
list_terminals user_token access_token
get_terminal user_token access_token [options]
  --container_key=value
  --subdomain=value

start_snapshot user_token access_token snapshot_id [options]
  --cpu=value
  --ram=value
  --temporary=value
  --name=value
  --autopause=value
  --startup_script=value
  --custom_data=value

delete_terminal user_token access_token container_key
restart_terminal user_token access_token container_key
pause_terminal user_token access_token container_key
resume_terminal user_token access_token container_key
edit_terminal user_token access_token container_key [options]
  --cpu=value
  --ram=value
  --diskspace=value
  --name=value

# CREATE AND MANAGE SNAPSHOTS #
list_snapshots user_token access_token [options]
  --username=value
  --tag=value
  --featured
  --title=value
  --page=value
  --perPage=value

count_snapshots user_token access_token [options]
  --username=value
  --tag=value
  --featured
  --title=value

delete_snapshot user_token access_token snapshot_id
edit_snapshot user_token access_token snapshot_id [options]
  --body=value
  --title=value
  --readme=value
  --public
  --custom_data=value

snapshot_terminal user_token access_token container_key [options]
  --body=value
  --title=value
  --readme=value
  --public

# MANAGE TERMINAL ACCESS #
add_terminal_links user_token access_token container_key *links
remove_terminal_links user_token access_token container_key *links
list_terminal_access user_token access_token container_key
edit_terminal_access user_token access_token container_key [options]
  --is_public_list
  --access_rules=value

# MANAGE TERMINAL DNS & DOMAINS #
get_cname_records user_token access_token
add_domain_to_pool user_token access_token domain
remove_domain_from_pool user_token access_token domain
add_cname_record user_token access_token domain subdomain port
remove_cname_record user_token access_token domain

# MANAGE TERMINAL IDLE SETTINGS #
set_terminal_idle_settings user_token access_token container_key action *triggers
get_terminal_idle_settings user_token access_token container_key

# MANAGE USAGE & CREDITS #
instance_types
instance_price instance_type status (defaults to running)
balance user_token access_token
balance_added user_token access_token
gift user_token access_token email cents
burn_history user_token access_token
terminal_usage_history user_token access_token
burn_state user_token access_token
burn_estimates user_token access_token

# MANAGE SSH PUBLIC KEYS #
add_authorized_key_to_terminal user_token access_token container_key publicKey
add_authorized_key_to_ssh_proxy user_token access_token name publicKey
del_authorized_key_from_ssh_proxy user_token access_token name fingerprint
get_authorized_keys_from_ssh_proxy user_token access_token

# OTHER #
who_am_i user_token, access_token
request_progress request_id


yesodweb.com update

yesodweb.com update


Adds manifest-src to CSP header

Adds manifest-src to CSP header

# NGINX configuration for playarchipelago.com.
#
# Listens for requests made to https://playarchipelago.com, serving
# static files from  the archipelago/web dir and forwards requests
# to /ws to the archipelago server.
#

# Cache map for different file types, see:
# https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-centos-7
map $sent_http_content_type $expires {
	default                    off;
	text/html                  epoch;
	text/css                   max;
	application/javascript     max;
	~image/                    max;
}

# Redirect http:// -> https://
server {
	listen 80;
	listen [::]:80;
	server_name www.playarchipelago.com playarchipelago.com;
	return 301 https://playarchipelago.com$request_uri;
}

# Redirect https://www.playarchipelago.com -> https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name www.playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;
	return 301 https://playarchipelago.com$request_uri;
}

# Primary, https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;

	access_log /var/log/playarchipelago.com/nginx.access.log;
	error_log  /var/log/playarchipelago.com/nginx.error.log;

	root /home/deploy/go/src/github.com/verath/archipelago/web/dist;
	index index.html;

	# Basic security headers
	add_header X-Frame-Options SAMEORIGIN;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";
	add_header Referrer-Policy no-referrer-when-downgrade;
	add_header Content-Security-Policy "default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src 'self'; connect-src 'self' wss://playarchipelago.com; img-src 'self' data:; manifest-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self'; worker-src 'self';";

	# Serve "/.well-known/acme-challenge" from a separate directory
	# this directory is used by let's encrypt to validate ownership
	location ^~ /.well-known/acme-challenge/ {
		root /var/www/letsencrypt/playarchipelago.com;
		try_files $uri $uri/ =404;
	}

	# Proxy requests for /ws to the archipelago server on :8080
	location /ws {
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header Host $host;
		proxy_pass http://localhost:8080;
		# Websockets
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	# Never cache the service worker file
	location = /sw.js {
		expires 0;
	}

	# All other requests are served from the web folder
	location / {
		try_files $uri $uri/ =404;
		expires $expires;
	}

	# Deny access to .-files
	location ~ /\. {
		return 403;
	}
}

# NGINX configuration for playarchipelago.com.
#
# Listens for requests made to https://playarchipelago.com, serving
# static files from  the archipelago/web dir and forwards requests
# to /ws to the archipelago server.
#

# Cache map for different file types, see:
# https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-centos-7
map $sent_http_content_type $expires {
	default                    off;
	text/html                  epoch;
	text/css                   max;
	application/javascript     max;
	~image/                    max;
}

# Redirect http:// -> https://
server {
	listen 80;
	listen [::]:80;
	server_name www.playarchipelago.com playarchipelago.com;
	return 301 https://playarchipelago.com$request_uri;
}

# Redirect https://www.playarchipelago.com -> https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name www.playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;
	return 301 https://playarchipelago.com$request_uri;
}

# Primary, https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;

	access_log /var/log/playarchipelago.com/nginx.access.log;
	error_log  /var/log/playarchipelago.com/nginx.error.log;

	root /home/deploy/go/src/github.com/verath/archipelago/web/dist;
	index index.html;

	# Basic security headers
	add_header X-Frame-Options SAMEORIGIN;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";
	add_header Referrer-Policy no-referrer-when-downgrade;
	add_header Content-Security-Policy "default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src 'self'; connect-src 'self' wss://playarchipelago.com; img-src 'self' data:; script-src 'self' 'unsafe-eval'; style-src 'self'; worker-src 'self';";

	# Serve "/.well-known/acme-challenge" from a separate directory
	# this directory is used by let's encrypt to validate ownership
	location ^~ /.well-known/acme-challenge/ {
		root /var/www/letsencrypt/playarchipelago.com;
		try_files $uri $uri/ =404;
	}

	# Proxy requests for /ws to the archipelago server on :8080
	location /ws {
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header Host $host;
		proxy_pass http://localhost:8080;
		# Websockets
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	# Never cache the service worker file
	location = /sw.js {
		expires 0;
	}

	# All other requests are served from the web folder
	location / {
		try_files $uri $uri/ =404;
		expires $expires;
	}

	# Deny access to .-files
	location ~ /\. {
		return 403;
	}
}


14/11/17 made changes to the solvent filter

#!/bin/csh

# In this experiment we had some issues with the base line.
# In order to tackle this we used a weaker solvent filter
# |   nmrPipe  -fn POLY -time -auto \
#
# Instead of the stronger filter
# |   nmrPipe  -fn SOL \
#
# this is an important consideration if you then
# have a baseline correction later on.

xyz2pipe -in fid/test%03d.fid -x -verb                   \
      |   nmrPipe  -fn POLY -time -auto \
      |   nmrPipe  -fn SP -off 0.4  -end 0.98 -pow 2 -c .5    \
      |   nmrPipe  -fn ZF -auto                               \
      |   nmrPipe  -fn FT                              \
      |   nmrPipe  -fn PS -p0 197.2 -p1 205 -di               \
      |   nmrPipe  -fn EXT  -sw  -xn 5.5ppm -x1 14ppm                     \
      |   nmrPipe  -fn TP                                     \
      |   nmrPipe  -fn SP -off 0.5  -end 0.98 -pow 2 -c .5    \
      |   nmrPipe  -fn ZF -auto                               \
      |   nmrPipe  -fn FT                                \
      |   nmrPipe  -fn PS -p0 90 -p1 0  -di               \
      |   nmrPipe  -fn TP                                     \
      |   pipe2xyz -out ft/test%03d.ft2 -x -ov              \

xyz2pipe -in ft/test%03d.ft2  -z -verb                     \
     |   nmrPipe -fn SP -off 0.5 -end 0.98 -pow 2 -c .5   \
     |   nmrPipe -fn ZF -auto                              \
     |   nmrPipe -fn FT -alt                             \
     |   nmrPipe -fn PS -p0 0. -p1 0 -di                 \
     |   nmrPipe -fn ZTP                                 \
     |   nmrPipe -POLY  -auto                                \
     |   pipe2xyz -out ft/test%03d.ft3  -z

xyz2pipe -in ft/test%03d.ft3 | nmrPipe -ov -verb -out test.ft3
proj3D.tcl test.ft3

#!/bin/csh

xyz2pipe -in fid/test%03d.fid -x -verb                   \
      |   nmrPipe  -fn SOL                                    \
      |   nmrPipe  -fn SP -off 0.4  -end 0.98 -pow 2 -c .5    \
      |   nmrPipe  -fn ZF -auto                               \
      |   nmrPipe  -fn FT                              \
      |   nmrPipe  -fn PS -p0 0. -p1 0 -di               \
      |   nmrPipe  -fn EXT  -sw  -xn 5ppm -x1 11ppm                     \
      |   nmrPipe  -fn TP                                     \
      |   nmrPipe  -fn SP -off 0.5  -end 0.98 -pow 2 -c .5    \
      |   nmrPipe  -fn ZF -auto                               \
      |   nmrPipe  -fn FT                                \
      |   nmrPipe  -fn PS -p0 90 -p1 0  -di               \
      |   nmrPipe  -fn TP                                     \
      |   pipe2xyz -out ft/test%03d.ft2 -x -ov              \

xyz2pipe -in ft/test%03d.ft2  -z -verb                     \
     |   nmrPipe -fn SP -off 0.5 -end 0.98 -pow 2 -c .5   \
     |   nmrPipe -fn ZF -auto                              \
     |   nmrPipe -fn FT -alt                       \
     |   nmrPipe -fn PS -p0 0. -p1 0 -di                 \
     |   nmrPipe -fn ZTP \
     |   pipe2xyz -out ft/test%03d.ft3  -z

xyz2pipe -in ft/test%03d.ft3 | nmrPipe -ov -verb -out test.ft3
proj3D.tcl test.ft3


fixes in nginx config file

fixes in nginx config file

Conflicts:
	nginx/sites-available/mran.revolutionanalytics.com

#mran.revolutionanalytics.com
#Chris Mosetick 2014-06-12
#last update    2014-07-24

server {
        #listen on IPv4 and IPv6 addresses at the same time
        listen 80;
        listen [::]:80;

        #directory in the file system to serve web pages and packages from
        #this is a detachable block disk formatted with ZFS that can be easily moved to another server
	      #www dir is for landing page stuff
        root /MRAN/www;
        index index.html index.htm;

        # public facing domain name for this vhost
        server_name marmoset.revolutionanalytics.com;

        location /snapshots {
                try_files $uri $uri/ =404;
                #autoindex is needed since we are not serving up any html or php pages
                autoindex  on;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
                #snapshots is directory containing symlinks to various .zfs/snapshot dirs
        }

        location /metadata {
                try_files $uri $uri/ =404;
                autoindex on;
		            # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules

        }

        location /diffs {
                try_files $uri $uri/ =404;
                autoindex on;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
        }

        location /accounting {
                try_files $uri $uri/ =404;
                autoindex on;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
        }

        location /history {

                try_files $uri $uri/ =404;
                autoindex on;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
                #history is symlink pointing to snapshots of the /MRAN/www FS itself
                #this URL is hidden right now, not on index.html
        }

        location /exports {
		            try_files $uri $uri/ =404;
        	      autoindex on;
        	      # Uncomment to enable naxsi on this location
        	      # include /etc/nginx/naxsi.rules

}
#this last bracket is needed to close this vhost

#mran.revolutionanalytics.com
#Chris Mosetick 2014-06-12
#last update    2014-07-19

server {
        #listen on IPv4 and IPv6 addresses at the same time
        listen 80;
        listen [::]:80;

        #directory in the file system to serve web pages and packages from
        #this is a detachable block disk formatted with ZFS that can be easily moved to another server
	#www dir is for landing page stuff
        root /MRAN/www;
        index index.html index.htm;

        # public facing domain name for this vhost
        server_name marmoset.revolutionanalytics.com;

        location /snapshots {
                try_files $uri $uri/ =404;
                #autoindex is needed since we are not serving up any html or php pages
                autoindex  on;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
                #snapshots is directory containing symlinks to various .zfs/snapshot dirs
        }

        location /metadata {
                try_files $uri $uri/ =404;
                autoindex on;
		            # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules

        }

        location /diffs {
                try_files $uri $uri/ =404;
                autoindex on;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
        }

        location /accounting {
                try_files $uri $uri/ =404;
                autoindex on;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
        }

        location /history {
                try_files $uri $uri/ =404;
                autoindex on;
                # Uncomment to enable naxsi on this location
                # include /etc/nginx/naxsi.rules
                #history is symlink poiniting to snapshots of the /MRAN/www FS itself
                #this URL is hidden right now, not on index.html
        }

        location /exports {
		            try_files $uri $uri/ =404;
        	      autoindex on;
        	      # Uncomment to enable naxsi on this location
        	      # include /etc/nginx/naxsi.rules
                #exports is symlink pointing to zpool named "exports"
	}

}
#this last bracket is needed to close this vhost


Re-enabled certificates

Re-enabled certificates

#server {
#    listen 80;
#    server_name radio.deepsouthsounds.com;
#
#    location /a {
#        proxy_pass http://radio:8888;
#        proxy_set_header Host $host;
#        proxy_set_header X-Real-IP $remote_addr;
#        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#    }
#
#    location / {
#        proxy_pass http://icecast:8000;
#        proxy_set_header Host $host;
#        proxy_set_header X-Real-IP $remote_addr;
#        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#    }
#}

server {
    listen 80;
    server_name api.deepsouthsounds.com api-test.deepsouthsounds.com;
    client_max_body_size 0;

    location /assets/grappelli {
	alias /usr/local/lib/python2.7/site-packages/grappelli/static/grappelli;
    }

   location /assets {
        alias /files/static;
   }

    location / {
        proxy_pass http://api:8001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

server {
	listen 80;
	server_name deepsouthsounds.com;
	return 301 http://www.deepsouthsounds.com$request_uri;
}

server {
    listen 80;
    listen 443 default ssl;

    server_name www.deepsouthsounds.com ext-test.deepsouthsounds.com;
    root /files/static/;

    ssl_certificate /etc/nginx/ssl/dss.crt;
    ssl_certificate_key /etc/nginx/ssl/dss.key;

    if ($ssl_protocol = "") {
       rewrite ^ https://$server_name$request_uri? permanent;
    }

    client_max_body_size 250M;

    location ~ /\.(eot|otf|ttf|woff)$ {
        add_header Access-Control-Allow-Origin *;
    }

    location /media {
        alias /files/media;
    }
    location / {
        if ($request_filename ~* ^.*?/([^/]*?)$) {
            set $filename $1;
        }
        if ($filename ~* ^.*?\.(eot)|(ttf)|(woff)$){
            add_header Access-Control-Allow-Origin *;
        }
        proxy_pass http://web:8080;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

#server {
#    listen 80;
#    server_name radio.deepsouthsounds.com;
#
#    location /a {
#        proxy_pass http://radio:8888;
#        proxy_set_header Host $host;
#        proxy_set_header X-Real-IP $remote_addr;
#        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#    }
#
#    location / {
#        proxy_pass http://icecast:8000;
#        proxy_set_header Host $host;
#        proxy_set_header X-Real-IP $remote_addr;
#        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#    }
#}

server {
    listen 80;
    server_name api.deepsouthsounds.com api-test.deepsouthsounds.com;
    client_max_body_size 0;

    location /assets/grappelli {
	alias /usr/local/lib/python2.7/site-packages/grappelli/static/grappelli;
    }

   location /assets {
        alias /files/static;
   }

    location / {
        proxy_pass http://api:8001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

server {
	listen 80;
	server_name deepsouthsounds.com;
	return 301 http://www.deepsouthsounds.com$request_uri;
}

server {
    listen 80;
    listen 443 default ssl;

    server_name www.deepsouthsounds.com ext-test.deepsouthsounds.com;
    root /files/static/;

    ssl_certificate /etc/nginx/ssl/dss.crt;
    ssl_certificate_key /etc/nginx/ssl/dss.key;

    #if ($ssl_protocol = "") {
    #   rewrite ^ https://$server_name$request_uri? permanent;
    #}

    client_max_body_size 250M;

    location ~ /\.(eot|otf|ttf|woff)$ {
        add_header Access-Control-Allow-Origin *;
    }

    location /media {
        alias /files/media;
    }
    location / {
        #if ($request_filename ~* ^.*?/([^/]*?)$) {
        #    set $filename $1;
        #}
        #if ($filename ~* ^.*?\.(eot)|(ttf)|(woff)$){
        #    add_header Access-Control-Allow-Origin *;
        #}
        proxy_pass http://web:8080;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}


Making sure to not block access to the new api route

# managed by puppet

server {

	server_name journeymonitor.com www.journeymonitor.com;
	listen 0.0.0.0:80;
	access_log /var/log/nginx/journeymonitor.com.access.log;
	error_log /var/log/nginx/journeymonitor.com.error.log;
	charset utf-8;

	root /opt/selenior/control-web-frontend/web;
	index index.php;

	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index app.php;
		include fastcgi_params;
	}

	location / {
		if (-f $request_filename) {
			expires max;
			break;
		}
		rewrite ^(.*) /app.php last;
	}

	location /api/control {
		deny all;
	}

	location /testresult-screenshots {
		proxy_pass http://127.0.0.1:8083/;
	}

}

server {

	server_name control-api;
	listen 127.0.0.1:8082;
	access_log /var/log/nginx/journeymonitor-control-api.access.log;
	error_log /var/log/nginx/journeymonitor-control-api.error.log;
	charset utf-8;

	root /opt/selenior/control-web-frontend/web;
	index index.php;

	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index app.php;
		include fastcgi_params;
	}

	location / {
		if (-f $request_filename) {
			expires max;
			break;
		}
		rewrite ^(.*) /app.php last;
	}

}

server {

	server_name monitor-api;
	listen 127.0.0.1:8081;
	access_log /var/log/nginx/journeymonitor-monitor-api.access.log;
	error_log /var/log/nginx/journeymonitor-monitor-api.error.log;
	charset utf-8;

	root /opt/selenior/monitor/web;
	index index.php;

	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index index.php;
		include fastcgi_params;
		fastcgi_param PHP_ENV prod;
	}

	location / {
		if (-f $request_filename) {
			expires max;
			break;
		}
		rewrite ^(.*) /index.php last;
	}

}

server {

	server_name monitor-media;
	listen 127.0.0.1:8083;
	access_log /var/log/nginx/journeymonitor-monitor-media.access.log;
	error_log /var/log/nginx/journeymonitor-monitor-media.error.log;
	charset utf-8;

	root /var/tmp/selenior-screenshots;
	index index.html;

	location / {
		if (-f $request_filename) {
			expires max;
			break;
		}
	}

}

# managed by puppet

server {

	server_name journeymonitor.com www.journeymonitor.com;
	listen 0.0.0.0:80;
	access_log /var/log/nginx/journeymonitor.com.access.log;
	error_log /var/log/nginx/journeymonitor.com.error.log;
	charset utf-8;

	root /opt/selenior/control-web-frontend/web;
	index index.php;

	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index app.php;
		include fastcgi_params;
	}

	location / {
		if (-f $request_filename) {
			expires max;
			break;
		}
		rewrite ^(.*) /app.php last;
	}

	location /api {
		deny all;
	}

	location /testresult-screenshots {
		proxy_pass http://127.0.0.1:8083/;
	}

}

server {

	server_name control-api;
	listen 127.0.0.1:8082;
	access_log /var/log/nginx/journeymonitor-control-api.access.log;
	error_log /var/log/nginx/journeymonitor-control-api.error.log;
	charset utf-8;

	root /opt/selenior/control-web-frontend/web;
	index index.php;

	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index app.php;
		include fastcgi_params;
	}

	location / {
		if (-f $request_filename) {
			expires max;
			break;
		}
		rewrite ^(.*) /app.php last;
	}

}

server {

	server_name monitor-api;
	listen 127.0.0.1:8081;
	access_log /var/log/nginx/journeymonitor-monitor-api.access.log;
	error_log /var/log/nginx/journeymonitor-monitor-api.error.log;
	charset utf-8;

	root /opt/selenior/monitor/web;
	index index.php;

	location ~ \.php$ {
		fastcgi_pass unix:/var/run/php5-fpm.sock;
		fastcgi_index index.php;
		include fastcgi_params;
		fastcgi_param PHP_ENV prod;
	}

	location / {
		if (-f $request_filename) {
			expires max;
			break;
		}
		rewrite ^(.*) /index.php last;
	}

}

server {

	server_name monitor-media;
	listen 127.0.0.1:8083;
	access_log /var/log/nginx/journeymonitor-monitor-media.access.log;
	error_log /var/log/nginx/journeymonitor-monitor-media.error.log;
	charset utf-8;

	root /var/tmp/selenior-screenshots;
	index index.html;

	location / {
		if (-f $request_filename) {
			expires max;
			break;
		}
	}

}


Adds CSP, referrer policy headers

Adds CSP, referrer policy headers

# NGINX configuration for playarchipelago.com.
#
# Listens for requests made to https://playarchipelago.com, serving
# static files from  the archipelago/web dir and forwards requests
# to /ws to the archipelago server.
#

# Cache map for different file types, see:
# https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-centos-7
map $sent_http_content_type $expires {
	default                    off;
	text/html                  epoch;
	text/css                   max;
	application/javascript     max;
	~image/                    max;
}

# Redirect http:// -> https://
server {
	listen 80;
	listen [::]:80;
	server_name www.playarchipelago.com playarchipelago.com;
	return 301 https://playarchipelago.com$request_uri;
}

# Redirect https://www.playarchipelago.com -> https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name www.playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;
	return 301 https://playarchipelago.com$request_uri;
}

# Primary, https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;

	access_log /var/log/playarchipelago.com/nginx.access.log;
	error_log  /var/log/playarchipelago.com/nginx.error.log;

	root /home/deploy/go/src/github.com/verath/archipelago/web/dist;
	index index.html;

	# Basic security headers
	add_header X-Frame-Options SAMEORIGIN;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";
	add_header Referrer-Policy no-referrer-when-downgrade;
	add_header Content-Security-Policy "default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src 'self'; connect-src 'self' wss://playarchipelago.com; img-src 'self' data:; script-src 'self' 'unsafe-eval'; style-src 'self'; worker-src 'self';";

	# Serve "/.well-known/acme-challenge" from a separate directory
	# this directory is used by let's encrypt to validate ownership
	location ^~ /.well-known/acme-challenge/ {
		root /var/www/letsencrypt/playarchipelago.com;
		try_files $uri $uri/ =404;
	}

	# Proxy requests for /ws to the archipelago server on :8080
	location /ws {
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header Host $host;
		proxy_pass http://localhost:8080;
		# Websockets
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	# Never cache the service worker file
	location = /sw.js {
		expires 0;
	}

	# All other requests are served from the web folder
	location / {
		try_files $uri $uri/ =404;
		expires $expires;
	}

	# Deny access to .-files
	location ~ /\. {
		return 403;
	}
}

# NGINX configuration for playarchipelago.com.
#
# Listens for requests made to https://playarchipelago.com, serving
# static files from  the archipelago/web dir and forwards requests
# to /ws to the archipelago server.
#

# Cache map for different file types, see:
# https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-centos-7
map $sent_http_content_type $expires {
	default                    off;
	text/html                  epoch;
	text/css                   max;
	application/javascript     max;
	~image/                    max;
}

# Redirect http:// -> https://
server {
	listen 80;
	listen [::]:80;
	server_name www.playarchipelago.com playarchipelago.com;
	return 301 https://playarchipelago.com$request_uri;
}

# Redirect https://www.playarchipelago.com -> https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name www.playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;
	return 301 https://playarchipelago.com$request_uri;
}

# Primary, https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;

	access_log /var/log/playarchipelago.com/nginx.access.log;
	error_log  /var/log/playarchipelago.com/nginx.error.log;

	root /home/deploy/go/src/github.com/verath/archipelago/web/dist;
	index index.html;

	# Basic security headers
	add_header X-Frame-Options SAMEORIGIN;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";

	# Serve "/.well-known/acme-challenge" from a separate directory
	# this directory is used by let's encrypt to validate ownership
	location ^~ /.well-known/acme-challenge/ {
		root /var/www/letsencrypt/playarchipelago.com;
		try_files $uri $uri/ =404;
	}

	# Proxy requests for /ws to the archipelago server on :8080
	location /ws {
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header Host $host;
		proxy_pass http://localhost:8080;
		# Websockets
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	# Never cache the service worker file
	location = /sw.js {
		expires 0;
	}

	# All other requests are served from the web folder
	location / {
		try_files $uri $uri/ =404;
		expires $expires;
	}

	# Deny access to .-files
	location ~ /\. {
		return 403;
	}
}


Update example.com

Update example.com

# Redirect to non-www
server {
    listen 8080;
    server_name www.example.com;
    return 301 $scheme://example.com$request_uri;
}

server {

    listen 8080;

    # Document root
    root /var/www/example.com;

    # Try static files first, then php
    index index.html index.htm index.php;

    # Specific logs for this vhost
    access_log /var/log/nginx/example.com-access.log;
    error_log  /var/log/nginx/example.com-error.log error;

    # Make site accessible from http://localhost/
    server_name example.com;

    # Specify a character set
    charset utf-8;

    # Redirect needed to "hide" index.php
    location / {
            try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    # Don't log robots.txt or favicon.ico files
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt { access_log off; log_not_found off; }
    location = /apple-touch-icon.png { access_log off; log_not_found off; }
    location = /apple-touch-icon-precomposed.png { access_log off; log_not_found off; }

    # 404 errors handled by our application
    error_page 404 /index.html;

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
              root /usr/share/nginx/www;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    location ~ \.php$ {

            fastcgi_buffers 8 256k;
            fastcgi_buffer_size 128k;
            fastcgi_intercept_errors on;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            try_files $uri =404;
            fastcgi_pass unix:/var/run/php5-fpm.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;
    }

    # Deny access to .htaccess
    location ~ /\. { deny  all; access_log off; log_not_found off; }
    location ~ /\.ht {
            deny all;
    }

    # rewrite for Yoast sitemap
    location ~ ([^/]*)sitemap(.*)\.x(m|s)l$ {
        rewrite ^/sitemap\.xml$ /sitemap_index.xml permanent;
        rewrite ^/([a-z]+)?-?sitemap\.xsl$ /index.php?xsl=$1 last;
	    rewrite ^/sitemap_index\.xml$ /index.php?sitemap=1 last;
	    rewrite ^/([^/]+?)-sitemap([0-9]+)?\.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;

    ## following lines are options. Needed for wordpress-seo addons
        rewrite ^/news_sitemap\.xml$ /index.php?sitemap=wpseo_news last;
	    rewrite ^/locations\.kml$ /index.php?sitemap=wpseo_local_kml last;
	    rewrite ^/geo_sitemap\.xml$ /index.php?sitemap=wpseo_local last;
	    rewrite ^/video-sitemap\.xsl$ /index.php?xsl=video last;

	    access_log off;
    }

# Define default caching of 24h
    expires 86400s;
    add_header Pragma public;
    add_header Cache-Control "max-age=86400, public, must-revalidate, proxy-revalidate";

# Do not allow access to files giving away your WordPress version
    location ~ /(\.|wp-config.php|readme.html|licence.txt) {
        return 404;
    }

# Rewrite for versioned CSS+JS via filemtime
    location ~* ^.+\.(css|js)$ {
        rewrite ^(.+)\.(\d+)\.(css|js)$ $1.$3 last;
        expires 31536000s;
        access_log off;
        log_not_found off;
        add_header Pragma public;
        add_header Cache-Control "max-age=31536000, public";
}
# Expire rules for static content

# cache.appcache, your document html and data
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
  expires -1;
  access_log /var/log/nginx/static.log;
}

# Feed
location ~* \.(?:rss|atom)$ {
  expires 1h;
  add_header Cache-Control "public";
}

# Media: images, icons, video, audio, HTC
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
  expires 1M;
  access_log off;
  add_header Cache-Control "public";
}

# CSS and Javascript
location ~* \.(?:css|js)$ {
  expires 1y;
  access_log off;
  add_header Cache-Control "public";
}

    # Cross domain webfont access
    location ~* \.(?:ttf|ttc|otf|eot|woff)$ {
    add_header "Access-Control-Allow-Origin" "*";

    expires 1M;
    access_log off;
    add_header Cache-Control "public";
    }

    # Prevent clients from accessing hidden files (starting with a dot)
    # This is particularly important if you store .htpasswd files in the site hierarchy
    location ~* (?:^|/)\. {
    deny all;
    }

    # Prevent clients from accessing to backup/config/source files
    location ~* (?:\.(?:bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)|~)$ {
    deny all;
    }
}

server {
    listen 8080;
        #root /usr/share/nginx/html;
        root /var/www/example.com;

        # Tell the browser about SPDY
        # add_header  Alternate-Protocol 443:npn-spdy/2;

        index index.php index.html index.htm;

        # Make site accessible from http://localhost/
        server_name example.com;

        autoindex off;
        location /app/                { deny all; }
        location /includes/           { deny all; }
        location /lib/                { deny all; }
        location /media/downloadable/ { deny all; }
        location /pkginfo/            { deny all; }
        location /report/config.xml   { deny all; }
        location /var/                { deny all; }
        location = /RELEASE_NOTES.txt { deny all; }
        location = /LICENSE_AFL.txt   { deny all; }
        location = /LICENSE.html      { deny all; }
        location = /LICENSE.txt       { deny all; }
        location = /php.ini.sample    { deny all; }
        location = /index.php.sample  { deny all; }
        location  /.                  { return 404; }

        location ~* \.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
               access_log off;
               expires 30d;
        }

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ /index.php?q=$uri&$args;    # /index.html;
        # Uncomment to enable naxsi on this location
        # include /etc/nginx/naxsi.rules

        if ($request_uri ~* "\.(png|gif|jpg|jpeg|css|js|swf|ico|txt|xml|bmp|pdf|doc|docx|ppt|pptx|zip)$") {
        expires max;
        }

    }

    # Only for nginx-naxsi used with nginx-naxsi-ui : process denied requests
    #location /RequestDenied {
    #   proxy_pass http://127.0.0.1:8080;
    #}

    error_page 404 /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
            try_files $uri = 404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
        # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

        expires        off; # Do not cache dynamic content

        # With php5-cgi alone:
        #fastcgi_pass 127.0.0.1:9000;
        # With php5-fpm:
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
                fastcgi_param  QUERY_STRING     $query_string;
                fastcgi_param  REQUEST_METHOD   $request_method;
                fastcgi_param  CONTENT_TYPE     $content_type;
                fastcgi_param  CONTENT_LENGTH   $content_length;
                fastcgi_intercept_errors        on;
                fastcgi_ignore_client_abort     off;
                fastcgi_connect_timeout 60;
                fastcgi_send_timeout 180;
                fastcgi_read_timeout 180;
                fastcgi_buffer_size 128k;
                fastcgi_buffers 4 256k;
                fastcgi_busy_buffers_size 256k;
                fastcgi_temp_file_write_size 256k;
    }

        rewrite ^/sitemap_index\.xml$ /index.php?sitemap=1 last;
        rewrite ^/([^/]+?)-sitemap([0-9]+)?\.xml$ /index.php?sitemap=$1&sitemap_n=$2 last;
        # rewrite ^(.*) https://$host$1 permanent;
}

# HTTPS server

#server {
#        listen 443 spdy;
#        server_name example.com;
#
#        root /var/www/example.com;
#        index index.php index.html index.htm;
#
#        ssl on;
#        # SSL Certificate and private key
#        ssl_certificate /etc/nginx/ssl/example.com.crt;
#        ssl_certificate_key /etc/nginx/ssl/example.com_encrypted.key;
#        example.com.csr  example.com_encrypted.key
#        # Tell the browser about SPDY
#        add_header  Alternate-Protocol 443:npn-spdy/2;
#}


Remove hardcoded index.html in try_files

index.html is already set as index on the top-level,
the second paramter ($url/) should already match index.html

# NGINX configuration for playarchipelago.com.
#
# Listens for requests made to https://playarchipelago.com, serving
# static files from  the archipelago/web dir and forwards requests
# to /ws to the archipelago server.
#

# Cache map for different file types, see:
# https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-centos-7
map $sent_http_content_type $expires {
	default                    off;
	text/html                  epoch;
	text/css                   max;
	application/javascript     max;
	~image/                    max;
}

# Redirect http:// -> https://
server {
	listen 80;
	listen [::]:80;
	server_name www.playarchipelago.com playarchipelago.com;
	return 301 https://playarchipelago.com$request_uri;
}

# Redirect https://www.playarchipelago.com -> https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name www.playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;
	return 301 https://playarchipelago.com$request_uri;
}

# Primary, https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;

	access_log /var/log/playarchipelago.com/nginx.access.log;
	error_log  /var/log/playarchipelago.com/nginx.error.log;

	root /home/deploy/go/src/github.com/verath/archipelago/web/dist;
	index index.html;

	# Basic security headers
	add_header X-Frame-Options SAMEORIGIN;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";

	# Serve "/.well-known/acme-challenge" from a separate directory
	# this directory is used by let's encrypt to validate ownership
	location ^~ /.well-known/acme-challenge/ {
		root /var/www/letsencrypt/playarchipelago.com;
		try_files $uri $uri/ =404;
	}

	# Proxy requests for /ws to the archipelago server on :8080
	location /ws {
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header Host $host;
		proxy_pass http://localhost:8080;
		# Websockets
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	# Never cache the service worker file
	location = /sw.js {
		expires off;
	}

	# All other requests are served from the web folder
	location / {
		try_files $uri $uri/ =404;
		expires $expires;
	}

	# Deny access to .-files
	location ~ /\. {
		return 403;
	}
}

# NGINX configuration for playarchipelago.com.
#
# Listens for requests made to https://playarchipelago.com, serving
# static files from  the archipelago/web dir and forwards requests
# to /ws to the archipelago server.
#

# Cache map for different file types, see:
# https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-centos-7
map $sent_http_content_type $expires {
	default                    off;
	text/html                  epoch;
	text/css                   max;
	application/javascript     max;
	~image/                    max;
}

# Redirect http:// -> https://
server {
	listen 80;
	listen [::]:80;
	server_name www.playarchipelago.com playarchipelago.com;
	return 301 https://playarchipelago.com$request_uri;
}

# Redirect https://www.playarchipelago.com -> https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name www.playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;
	return 301 https://playarchipelago.com$request_uri;
}

# Primary, https://playarchipelago.com
server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name playarchipelago.com;
	ssl_certificate /etc/letsencrypt/live/playarchipelago.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/playarchipelago.com/privkey.pem;

	access_log /var/log/playarchipelago.com/nginx.access.log;
	error_log  /var/log/playarchipelago.com/nginx.error.log;

	root /home/deploy/go/src/github.com/verath/archipelago/web/dist;
	index index.html;

	# Basic security headers
	add_header X-Frame-Options SAMEORIGIN;
	add_header X-Content-Type-Options nosniff;
	add_header X-XSS-Protection "1; mode=block";

	# Serve "/.well-known/acme-challenge" from a separate directory
	# this directory is used by let's encrypt to validate ownership
	location ^~ /.well-known/acme-challenge/ {
		root /var/www/letsencrypt/playarchipelago.com;
		try_files $uri $uri/ =404;
	}

	# Proxy requests for /ws to the archipelago server on :8080
	location /ws {
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $remote_addr;
		proxy_set_header Host $host;
		proxy_pass http://localhost:8080;
		# Websockets
		proxy_http_version 1.1;
		proxy_set_header Upgrade $http_upgrade;
		proxy_set_header Connection "upgrade";
	}

	# Never cache the service worker file
	location = /sw.js {
		expires off;
	}

	# All other requests are served from the web folder
	location / {
		try_files $uri $uri/ index.html;
		expires $expires;
	}

	# Deny access to .-files
	location ~ /\. {
		return 403;
	}
}


Removed extraneous ` from PRODUCT_VERSION.

#
# Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#ident	"$Id$"
#

MACH = $(shell mach)

PUBLISH_ROOT = $(DIST)
ifeq ($(CORE_DEPTH),../../..)
ROOT = ROOT
else
ROOT = $(subst ../../../,,$(CORE_DEPTH))/ROOT
endif

PKGARCHIVE = $(PUBLISH_ROOT)/pkgarchive
DATAFILES = copyright
FILES = $(DATAFILES) pkginfo

PACKAGE = $(shell basename `pwd`)

PRODUCT_VERSION = $(shell grep NSS_VERSION $(CORE_DEPTH)/../dist/public/nss/nss.h \
	| sed -e 's/"$$//' -e 's/.*"//' -e 's/ .*//')

LN = /usr/bin/ln

CLOBBERFILES = $(FILES)

include $(CORE_DEPTH)/coreconf/config.mk
include $(CORE_DEPTH)/coreconf/rules.mk

# vim: ft=make

#
# Copyright 2002 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
#ident	"$Id$"
#

MACH = $(shell mach)

PUBLISH_ROOT = $(DIST)
ifeq ($(CORE_DEPTH),../../..)
ROOT = ROOT
else
ROOT = $(subst ../../../,,$(CORE_DEPTH))/ROOT
endif

PKGARCHIVE = $(PUBLISH_ROOT)/pkgarchive
DATAFILES = copyright
FILES = $(DATAFILES) pkginfo

PACKAGE = $(shell basename `pwd`)

PRODUCT_VERSION = $(shell grep NSS_VERSION $(CORE_DEPTH)/../dist/public/nss/nss.h \
	| sed -e 's/"$$//' -e 's/.*"//' -e 's/ .*//'`)

LN = /usr/bin/ln

CLOBBERFILES = $(FILES)

include $(CORE_DEPTH)/coreconf/config.mk
include $(CORE_DEPTH)/coreconf/rules.mk

# vim: ft=make


Fixed DCL typo.

Fixed DCL typo.

Instllation testing revealed a lack or parenthesis in a DCL IF test
experession.

$ ! Procedure:	MMK___STARTUP.COM
$ __vfy = "VFY_''f$parse(f$environment("procedure"),,,"name")'"
$ if (f$type('__vfy') .eqs. "") then __vfy = 0
$ __vfy_saved = f$verify(&__vfy)
$
$err: subroutine
$ set noon
$ severity = f$edit(P1,"COLLAPSE,UPCASE")
$ identification = f$edit(P2,"COLLAPSE,UPCASE")
$ text = f$edit(P3,"TRIM")
$ continuation = (f$edit(P4,"COLLAPSE,UPCASE") .nes. "")
$ say = "write sys$output"
$ percent = "%"
$ if (continuation) then percent = "-"
$ if ((severity .eqs. "") .or. (identification .eqs. "") .or. (text .eqs. ""))
$ then say "%''facility'-F-SPOTTHEERR, <''severity'><''identification'><''text'>"
$ else say "''percent'''facility'-''severity'-''identification', ''text'"
$ endif
$ exitt 1
$ endsubroutine
$
$ procedure = f$element(0,";",f$environment("PROCEDURE"))
$ procedure_name = f$parse(procedure,,,"NAME")
$ facility = procedure_name
$ location = f$parse(procedure,,,"DEVICE","NO_CONCEAL") -
		+ f$parse(procedure,,,"DIRECTORY","NO_CONCEAL") -
		- "][" - ".]" - "]"
$
$ set noon
$ set symbol/scope=(nolocal)
$ on warning then goto bail_out
$ on control_y then goto bail_out
$
$ if ((f$getsyi("HW_MODEL") .gt. 0) .and. (f$getsyi("HW_MODEL") .lt. 1024))
$ then _arch_type = 1
$ else _arch_type = f$getsyi("ARCH_TYPE")
$ endif
$ _arch_name = f$element(_arch_type,",","OTHER,VAX,AXP,I64") - ","
$ _vax = (_arch_type .eq. 1)
$ _axp = (_arch_type .eq. 2)
$ _i64 = (_arch_type .eq. 3)
$ _other = (.not. (_vax .or. _axp .or. _i64))
$
$ dns = "define/nolog/system"
$ say = "write sys$output"
$ err = "call___ err"
$ saysym = "write/symbol sys$output"
$
$start:
$ dns/translation=concealed	MMK_ROOT	'location'.]
$ dns				MMK_EXE_AXP	MMK_ROOT:[EXE_AXP]
$ dns				MMK_EXE_I64	MMK_ROOT:[EXE_I64]
$ dns				MMK_EXE_VAX	MMK_ROOT:[EXE_VAX]
$ dns				MMK_EXE		MMK_EXE_'_arch_name':
$
$ dns				MMK		MMK_EXE:MMK.EXE
$
$ if (f$parse(mmk_root+".SRC]") .nes. "") then -
$ dns				MMK_SRC		MMK_ROOT:[SRC]
$ if (f$parse(mmk_root+".DOC]") .nes. "") then -
$ dns				MMK_DOC		MMK_ROOT:[DOC]
$
$bail_out:
$ exitt 1.or.(0*f$verify(__vfy_saved))
$ !+==========================================================================
$ !
$ !  FACILITY:   MMK
$ !
$ !  ABSTRACT:   MMK system startup procedure.
$ !
$ !  AUTHOR:         Tim Sneddon
$ !
$ !  Copyright (c) 2013, Endless Software Solutions.
$ !
$ !  All rights reserved.
$ !
$ !  Redistribution and use in source and binary forms, with or without
$ !  modification, are permitted provided that the following conditions
$ !  are met:
$ !
$ !      * Redistributions of source code must retain the above
$ !        copyright notice, this list of conditions and the following
$ !        disclaimer.
$ !      * Redistributions in binary form must reproduce the above
$ !        copyright notice, this list of conditions and the following
$ !        disclaimer in the documentation and/or other materials provided
$ !        with the distribution.
$ !      * Neither the name of the copyright owner nor the names of any
$ !        other contributors may be used to endorse or promote products
$ !        derived from this software without specific prior written
$ !        permission.
$ !
$ !  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
$ !  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
$ !  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
$ !  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
$ !  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
$ !  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
$ !  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
$ !  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
$ !  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
$ !  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
$ !  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
$ !
$ !  CREATION DATE:  07-APR-2013
$ !
$ !  MODIFICATION HISTORY:
$ !
$ !      07-APR-2013 V1.0    Sneddon     Initial coding.
$ !-==========================================================================

$ ! Procedure:	MMK___STARTUP.COM
$ __vfy = "VFY_''f$parse(f$environment("procedure"),,,"name")'"
$ if (f$type('__vfy') .eqs. "") then __vfy = 0
$ __vfy_saved = f$verify(&__vfy)
$
$err: subroutine
$ set noon
$ severity = f$edit(P1,"COLLAPSE,UPCASE")
$ identification = f$edit(P2,"COLLAPSE,UPCASE")
$ text = f$edit(P3,"TRIM")
$ continuation = (f$edit(P4,"COLLAPSE,UPCASE") .nes. "")
$ say = "write sys$output"
$ percent = "%"
$ if (continuation) then percent = "-"
$ if ((severity .eqs. "") .or. (identification .eqs. "") .or. (text .eqs. ""))
$ then say "%''facility'-F-SPOTTHEERR, <''severity'><''identification'><''text'>"
$ else say "''percent'''facility'-''severity'-''identification', ''text'"
$ endif
$ exitt 1
$ endsubroutine
$
$ procedure = f$element(0,";",f$environment("PROCEDURE"))
$ procedure_name = f$parse(procedure,,,"NAME")
$ facility = procedure_name
$ location = f$parse(procedure,,,"DEVICE","NO_CONCEAL") -
		+ f$parse(procedure,,,"DIRECTORY","NO_CONCEAL") -
		- "][" - ".]" - "]"
$
$ set noon
$ set symbol/scope=(nolocal)
$ on warning then goto bail_out
$ on control_y then goto bail_out
$
$ if (f$getsyi("HW_MODEL") .gt. 0) .and. (f$getsyi("HW_MODEL") .lt. 1024))
$ then _arch_type = 1
$ else _arch_type = f$getsyi("ARCH_TYPE")
$ endif
$ _arch_name = f$element(_arch_type,",","OTHER,VAX,AXP,I64") - ","
$ _vax = (_arch_type .eq. 1)
$ _axp = (_arch_type .eq. 2)
$ _i64 = (_arch_type .eq. 3)
$ _other = (.not. (_vax .or. _axp .or. _i64))
$
$ dns = "define/nolog/system"
$ say = "write sys$output"
$ err = "call___ err"
$ saysym = "write/symbol sys$output"
$
$start:
$ dns/translation=concealed	MMK_ROOT	'location'.]
$ dns				MMK_EXE_AXP	MMK_ROOT:[EXE_AXP]
$ dns				MMK_EXE_I64	MMK_ROOT:[EXE_I64]
$ dns				MMK_EXE_VAX	MMK_ROOT:[EXE_VAX]
$ dns				MMK_EXE		MMK_EXE_'_arch_name':
$
$ dns				MMK		MMK_EXE:MMK.EXE
$
$ if (f$parse(mmk_root+".SRC]") .nes. "") then -
$ dns				MMK_SRC		MMK_ROOT:[SRC]
$ if (f$parse(mmk_root+".DOC]") .nes. "") then -
$ dns				MMK_DOC		MMK_ROOT:[DOC]
$
$bail_out:
$ exitt 1.or.(0*f$verify(__vfy_saved))
$ !+==========================================================================
$ !
$ !  FACILITY:   MMK
$ !
$ !  ABSTRACT:   MMK system startup procedure.
$ !
$ !  AUTHOR:         Tim Sneddon
$ !
$ !  Copyright (c) 2013, Endless Software Solutions.
$ !
$ !  All rights reserved.
$ !
$ !  Redistribution and use in source and binary forms, with or without
$ !  modification, are permitted provided that the following conditions
$ !  are met:
$ !
$ !      * Redistributions of source code must retain the above
$ !        copyright notice, this list of conditions and the following
$ !        disclaimer.
$ !      * Redistributions in binary form must reproduce the above
$ !        copyright notice, this list of conditions and the following
$ !        disclaimer in the documentation and/or other materials provided
$ !        with the distribution.
$ !      * Neither the name of the copyright owner nor the names of any
$ !        other contributors may be used to endorse or promote products
$ !        derived from this software without specific prior written
$ !        permission.
$ !
$ !  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
$ !  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
$ !  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
$ !  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
$ !  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
$ !  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
$ !  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
$ !  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
$ !  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
$ !  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
$ !  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
$ !
$ !  CREATION DATE:  07-APR-2013
$ !
$ !  MODIFICATION HISTORY:
$ !
$ !      07-APR-2013 V1.0    Sneddon     Initial coding.
$ !-==========================================================================


Syntax highlighting is optional.

Syntax highlighting is optional.

#!/usr/bin/env ruby

# TODO (later): Don't force tokens for methods that don't need them.
# TODO (maybe): DBG=ruby/curl/off. Curl would output curl commands.

############
# Helpers. #
############

def log(message)
  STDERR.puts("\x1B[1;30m~ #{message}\x1B[0m") unless ENV['DBG'] == 'off'
end

def dbg(command, arguments, **options)
  log "Terminal::API.#{command}(" +
    ("#{arguments.inspect[1..-2]}" unless arguments.empty?).to_s +
    (", #{options.inspect[1..-2]}" unless options.empty?).to_s +
    ")\n"
end

def try_highlight_syntax(json)
  CodeRay.scan(json, :json).term
rescue
  json
end

def print_as_json(data)
  json = JSON.pretty_generate(data)
  puts try_highlight_syntax(json)
end

def api_call(command, arguments, options)
  # Ruby **args expansion doesn't work as I expected, that's why the extra if.
  # pry(main)> def xxx(*args) args; end
  # pry(main)> xxx(**{})
  # => [{}]
  if options
    dbg command, arguments, options
    print_as_json Terminal::API.send(command, *arguments, **options)
  else
    dbg command, arguments
    print_as_json Terminal::API.send(command, *arguments)
  end
end

def usage
  DATA.read
end

#########
# Main. #
#########

require File.expand_path('../../lib/terminal.com', __FILE__)
require 'json'

begin
  require 'coderay'
rescue LoadError
  log "CodeRay is not installed. Syntax highlighting won't be available."
end

# -h | --help
if ARGV.include?('-h') || ARGV.include?('--help')
  puts usage; exit
end

if ARGV.first == 'configure'
  puts <<-EOF
Welcome to the Terminal.com CLI client.

We don't want to bother you with asking for credentials every single time,
so instead we'll ask you for them now and save them to ~/.terminal.com.json.

Alright?

Go to https://www.terminal.com/settings/api

And:
  EOF

  print "1. Paste your user token here: "
  user_token = STDIN.readline.chomp
  print "2. Generate an access token if you don't have one and paste it here: "
  access_token = STDIN.readline.chomp

  File.open(File.expand_path('~/.terminal.com.json'), 'w') do |file|
    file.puts({user_token: user_token, access_token: access_token}.to_json)
  end

  puts "\nYour tokens were saved to ~/.terminal.com.json."
  exit
end

# Tokens.
# TODO: Add --no-config
if File.exist?(File.expand_path('~/.terminal.com.json'))
  config = JSON.parse(File.read(File.expand_path('~/.terminal.com.json')))
  user_token, access_token = config.values_at('user_token', 'access_token')

  if user_token.nil?
    abort("Config file found, but user_token is missing. Add user_token key.")
  end

  if access_token.nil?
    abort("Config file found, but access_token is missing. Add access_token key.")
  end
else
  user_token, access_token = ARGV.shift(2)

  if user_token.nil? || access_token.nil?
    STDERR.puts("Credentials missing.\n\n")
    abort usage
  end
end

if ARGV.empty?
  STDERR.puts("Command missing.\n\n")
  abort usage
else
  command = ARGV.shift

  unless Terminal::API.respond_to?(command)
    STDERR.puts("Invalid command '#{command}'.\n\n")
    abort usage
  end

  # Not every method requires authentication.
  method_args = Terminal::API.method(command).parameters.map(&:last)

  if method_args.include?(:options)
    options = ARGV.reduce(Hash.new) do |buffer, argument|
      if argument.match(/^--(.+)=(.+)$/)
        buffer[$1.to_sym] = $2
      elsif argument.match(/^--no-(.+)$/)
        buffer[$1.to_sym] = false
      elsif argument.match(/^--(.+)$/)
        buffer[$1.to_sym] = true
      end

      buffer
    end

    ARGV.delete_if { |argument| argument.start_with?('--') }
  end

  arguments = []
  arguments << user_token if method_args.include?(:user_token)
  arguments << access_token if method_args.include?(:access_token)
  arguments.push(*ARGV)

  api_call(command, arguments, options)
end

__END__
== Usage ==

1. Explicit configuration.

terminal.com [user_token] [access_token] [command]

2. With a configuration file.

First run terminal.com configure. This command will
save your credentials into ~/.terminal.com.json.
{"user_token": "...", "access_token": "..."}

Then you can run commands like so:

terminal.com [command]

== Commands ==

These are identical to what the API provides.

# BROWSE SNAPSHOTS & USERS #
get_snapshot snapshot_id
get_profile username
list_public_snapshots [options]
  --username=value
  --tag=value
  --featured
  --title=value
  --page=value
  --perPage=value
  --sortby=value

count_public_snapshots [options]
  --username=value
  --tag=value
  --featured
  --title=value

# CREATE AND MANAGE TERMINALS #
list_terminals user_token access_token
get_terminal user_token access_token [options]
  --container_key=value
  --subdomain=value

start_snapshot user_token access_token snapshot_id [options]
  --cpu=value
  --ram=value
  --temporary
  --name=value
  --autopause=value
  --startup_script=value
  --custom_data=value

delete_terminal user_token access_token container_key
restart_terminal user_token access_token container_key
pause_terminal user_token access_token container_key
resume_terminal user_token access_token container_key
edit_terminal user_token access_token container_key [options]
  --cpu=value
  --ram=value
  --diskspace=value
  --name=value

# CREATE AND MANAGE SNAPSHOTS #
list_snapshots user_token access_token [options]
  --username=value
  --tag=value
  --featured
  --title=value
  --page=value
  --perPage=value

count_snapshots user_token access_token [options]
  --username=value
  --tag=value
  --featured
  --title=value

delete_snapshot user_token access_token snapshot_id
edit_snapshot user_token access_token snapshot_id [options]
  --body=value
  --title=value
  --readme=value
  --public
  --custom_data=value

snapshot_terminal user_token access_token container_key [options]
  --body=value
  --title=value
  --readme=value
  --public

# MANAGE TERMINAL ACCESS #
add_terminal_links user_token access_token container_key *links
remove_terminal_links user_token access_token container_key *links
list_terminal_access user_token access_token container_key
edit_terminal_access user_token access_token container_key [options]
  --is_public_list
  --access_rules=value

# MANAGE TERMINAL DNS & DOMAINS #
get_cname_records user_token access_token
add_domain_to_pool user_token access_token domain
remove_domain_from_pool user_token access_token domain
add_cname_record user_token access_token domain subdomain port
remove_cname_record user_token access_token domain

# MANAGE TERMINAL IDLE SETTINGS #
set_terminal_idle_settings user_token access_token container_key action *triggers
get_terminal_idle_settings user_token access_token container_key

# MANAGE USAGE & CREDITS #
instance_types
instance_price instance_type status (defaults to running)
balance user_token access_token
balance_added user_token access_token
gift user_token access_token email cents
burn_history user_token access_token
terminal_usage_history user_token access_token
burn_state user_token access_token
burn_estimates user_token access_token

# MANAGE SSH PUBLIC KEYS #
add_authorized_key_to_terminal user_token access_token container_key publicKey
add_authorized_key_to_ssh_proxy user_token access_token name publicKey
del_authorized_key_from_ssh_proxy user_token access_token name fingerprint
get_authorized_keys_from_ssh_proxy user_token access_token

# OTHER #
who_am_i user_token, access_token
request_progress request_id

#!/usr/bin/env ruby

require File.expand_path('../../lib/terminal.com', __FILE__)
require 'json'
require 'coderay'

# TODO (later): Don't force tokens for methods that don't need them.
# TODO (maybe): DBG=ruby/curl/off. Curl would output curl commands.

def log(message)
  STDERR.puts("\x1B[1;30m~ #{message}\x1B[0m") unless ENV['DBG'] == 'off'
end

def dbg(command, arguments, **options)
  log "Terminal::API.#{command}(" +
    ("#{arguments.inspect[1..-2]}" unless arguments.empty?).to_s +
    (", #{options.inspect[1..-2]}" unless options.empty?).to_s +
    ")\n"
end

def print_as_json(data)
  json = JSON.pretty_generate(data)
  puts CodeRay.scan(json, :json).term
end

def api_call(command, arguments, options)
  # Ruby **args expansion doesn't work as I expected, that's why the extra if.
  # pry(main)> def xxx(*args) args; end
  # pry(main)> xxx(**{})
  # => [{}]
  if options
    dbg command, arguments, options
    print_as_json Terminal::API.send(command, *arguments, **options)
  else
    dbg command, arguments
    print_as_json Terminal::API.send(command, *arguments)
  end
end

def usage
  DATA.read
end

# -h | --help
if ARGV.include?('-h') || ARGV.include?('--help')
  puts usage; exit
end

if ARGV.first == 'configure'
  puts <<-EOF
Welcome to the Terminal.com CLI client.

We don't want to bother you with asking for credentials every single time,
so instead we'll ask you for them now and save them to ~/.terminal.com.json.

Alright?

Go to https://www.terminal.com/settings/api

And:
  EOF

  print "1. Paste your user token here: "
  user_token = STDIN.readline.chomp
  print "2. Generate an access token if you don't have one and paste it here: "
  access_token = STDIN.readline.chomp

  File.open(File.expand_path('~/.terminal.com.json'), 'w') do |file|
    file.puts({user_token: user_token, access_token: access_token}.to_json)
  end

  puts "\nYour tokens were saved to ~/.terminal.com.json."
  exit
end

# Tokens.
# TODO: Add --no-config
if File.exist?(File.expand_path('~/.terminal.com.json'))
  config = JSON.parse(File.read(File.expand_path('~/.terminal.com.json')))
  user_token, access_token = config.values_at('user_token', 'access_token')

  if user_token.nil?
    abort("Config file found, but user_token is missing. Add user_token key.")
  end

  if access_token.nil?
    abort("Config file found, but access_token is missing. Add access_token key.")
  end
else
  user_token, access_token = ARGV.shift(2)

  if user_token.nil? || access_token.nil?
    STDERR.puts("Credentials missing.\n\n")
    abort usage
  end
end

if ARGV.empty?
  STDERR.puts("Command missing.\n\n")
  abort usage
else
  command = ARGV.shift

  unless Terminal::API.respond_to?(command)
    STDERR.puts("Invalid command '#{command}'.\n\n")
    abort usage
  end

  # Not every method requires authentication.
  method_args = Terminal::API.method(command).parameters.map(&:last)

  if method_args.include?(:options)
    options = ARGV.reduce(Hash.new) do |buffer, argument|
      if argument.match(/^--(.+)=(.+)$/)
        buffer[$1.to_sym] = $2
      elsif argument.match(/^--no-(.+)$/)
        buffer[$1.to_sym] = false
      elsif argument.match(/^--(.+)$/)
        buffer[$1.to_sym] = true
      end

      buffer
    end

    ARGV.delete_if { |argument| argument.start_with?('--') }
  end

  arguments = []
  arguments << user_token if method_args.include?(:user_token)
  arguments << access_token if method_args.include?(:access_token)
  arguments.push(*ARGV)

  api_call(command, arguments, options)
end

__END__
== Usage ==

1. Explicit configuration.

terminal.com [user_token] [access_token] [command]

2. With a configuration file.

First run terminal.com configure. This command will
save your credentials into ~/.terminal.com.json.
{"user_token": "...", "access_token": "..."}

Then you can run commands like so:

terminal.com [command]

== Commands ==

These are identical to what the API provides.

# BROWSE SNAPSHOTS & USERS #
get_snapshot snapshot_id
get_profile username
list_public_snapshots [options]
  --username=value
  --tag=value
  --featured
  --title=value
  --page=value
  --perPage=value
  --sortby=value

count_public_snapshots [options]
  --username=value
  --tag=value
  --featured
  --title=value

# CREATE AND MANAGE TERMINALS #
list_terminals user_token access_token
get_terminal user_token access_token [options]
  --container_key=value
  --subdomain=value

start_snapshot user_token access_token snapshot_id [options]
  --cpu=value
  --ram=value
  --temporary
  --name=value
  --autopause=value
  --startup_script=value
  --custom_data=value

delete_terminal user_token access_token container_key
restart_terminal user_token access_token container_key
pause_terminal user_token access_token container_key
resume_terminal user_token access_token container_key
edit_terminal user_token access_token container_key [options]
  --cpu=value
  --ram=value
  --diskspace=value
  --name=value

# CREATE AND MANAGE SNAPSHOTS #
list_snapshots user_token access_token [options]
  --username=value
  --tag=value
  --featured
  --title=value
  --page=value
  --perPage=value

count_snapshots user_token access_token [options]
  --username=value
  --tag=value
  --featured
  --title=value

delete_snapshot user_token access_token snapshot_id
edit_snapshot user_token access_token snapshot_id [options]
  --body=value
  --title=value
  --readme=value
  --public
  --custom_data=value

snapshot_terminal user_token access_token container_key [options]
  --body=value
  --title=value
  --readme=value
  --public

# MANAGE TERMINAL ACCESS #
add_terminal_links user_token access_token container_key *links
remove_terminal_links user_token access_token container_key *links
list_terminal_access user_token access_token container_key
edit_terminal_access user_token access_token container_key [options]
  --is_public_list
  --access_rules=value

# MANAGE TERMINAL DNS & DOMAINS #
get_cname_records user_token access_token
add_domain_to_pool user_token access_token domain
remove_domain_from_pool user_token access_token domain
add_cname_record user_token access_token domain subdomain port
remove_cname_record user_token access_token domain

# MANAGE TERMINAL IDLE SETTINGS #
set_terminal_idle_settings user_token access_token container_key action *triggers
get_terminal_idle_settings user_token access_token container_key

# MANAGE USAGE & CREDITS #
instance_types
instance_price instance_type status (defaults to running)
balance user_token access_token
balance_added user_token access_token
gift user_token access_token email cents
burn_history user_token access_token
terminal_usage_history user_token access_token
burn_state user_token access_token
burn_estimates user_token access_token

# MANAGE SSH PUBLIC KEYS #
add_authorized_key_to_terminal user_token access_token container_key publicKey
add_authorized_key_to_ssh_proxy user_token access_token name publicKey
del_authorized_key_from_ssh_proxy user_token access_token name fingerprint
get_authorized_keys_from_ssh_proxy user_token access_token

# OTHER #
who_am_i user_token, access_token
request_progress request_id