commit b174d304d765673e81a1c695a5942efe05669ddb Author: Insane Turkey Date: Mon Jan 4 21:13:07 2016 -0500 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..14a6af6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +conf/twitter.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..a9a696b --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +tn-service-check +========== + +Script to query the various TribesNext services, determine their state, and post notifications to Twitter. diff --git a/conf/services.json b/conf/services.json new file mode 100644 index 0000000..8d463ac --- /dev/null +++ b/conf/services.json @@ -0,0 +1,23 @@ +[ + { + "type": "auth", + "url": "http://tribesnext.com/auth", + "available": false, + "name": "Account creation", + "changed": false + }, + { + "type": "list", + "url": "http://master.tribesnext.com/list", + "available": true, + "name": "Server listing", + "changed": false + }, + { + "type": "community", + "url": "http://thyth.com/tn/robot/robot_login.php?guid=2126694&nonce=101deadbeef", + "available": false, + "name": "Community features", + "changed": false + } +] \ No newline at end of file diff --git a/conf/twitter.json.example b/conf/twitter.json.example new file mode 100644 index 0000000..6e2be39 --- /dev/null +++ b/conf/twitter.json.example @@ -0,0 +1,6 @@ +{ + "consumer_key": "app-consumer-key", + "consumer_secret": "app-consumer-secret", + "access_token": "client-access-token", + "access_token_secret": "client-access-token-secret" +} \ No newline at end of file diff --git a/src/main.rb b/src/main.rb new file mode 100644 index 0000000..7c4f7bf --- /dev/null +++ b/src/main.rb @@ -0,0 +1,97 @@ +require 'twitter' +require './services.rb' + + +module ServiceQuery + # Path to service definition file + SERVICE_CONFIG = './conf/services.json' + + # Path to twitter configuration file + TWITTER_CONFIG = './conf/twitter.json' + + + # Query services and post any updates to twitter + def run + # Load configuration + twitter_client = get_twitter_client + service_defs = get_service_defs + + # Query services + query_services(twitter_client, service_defs) + + # Save configuration + write_service_defs(service_defs) + end + + + # Load service definitions + def load_service_defs + TribesNext.read_config(SERVICE_CONFIG) + end + + + # Save service definitions + def write_service_defs(service_defs) + TribesNext.write_config(SERVICE_CONFIG, services) + end + + + # Query services, and post updates if any have changed availability + def query_services(twitter_client, service_defs) + workers = [] + + # Create background worker for each service + service_defs.each { |s| + workers << Thread.new(s) {|x| query_service(twitter_client, x)} + } + # Wait for updates to complete + workers.each {|w| w.join } + + return service_defs + end + + + # Query a service, and post an update if it has changed availability + def query_service(twitter_client, service_def) + begin + plural? = ('s' === service_def['name']) + available?, changed? = TribesNext.query(service_def) + + # if state changed: post update + if changed? then + if available? then + state = 'AVAILABLE' + verb = if plural? then 'are' else 'is' end + else + state = 'UNAVAILABLE' + verb = if plural? then 'appear to be' else 'appears to be' end + end + + twitter_client.update("#{service_def['name']} #{verb} #{state}.") + end + rescue Exception => ex + puts "Exception encountered while querying #{service['name']}: #{e.message}" + puts e.backtrace.inspect if debug? + end + end + + + # Create a client for interacting with a twitter account + def get_twitter_client + # Load config file + opts = JSON.parse(File.read(TWITTER_CONFIG)) + # create client + client = Twitter::REST::Client.new {|config| + config.consumer_key = opts['consumer_key'] + config.consumer_secret = opts['consumer_secret'] + config.access_token = opts['access_token'] + config.access_token_secret = opts['access_token_secret'] + } + end +end + + +# Run if this is file that was invoked +if __FILE__ == $0 + ServiceQuery.run +end diff --git a/src/services.rb b/src/services.rb new file mode 100644 index 0000000..5b4e62a --- /dev/null +++ b/src/services.rb @@ -0,0 +1,98 @@ +require 'json' +require 'open-uri' +require 'socket' + + +module TribesNext + # Read service definitions from a coniguration file + def read_config(config_file) + contents = File.read(config_file) + services = JSON.parse(contents) + return services + end + + + # Write service definitions to configuration file + def write_config(config_file, services) + contents = JSON.pretty_generate(services) + File.write(config_file, contents) + end + + + # Query a service + def query_service(service) + url = service['url'] + available? = case service['type'] + when 'auth' then TribesNext.Account.query(url) + when 'list' then TribesNext.Listing.query(url) + when 'community' then TribesNext.Community.query(url) + else false + end + changed? = (available? != service['available']) + + + service['changed'] = changed? + service['available'] = available? + return [available? changed?] + end + + + # Query an HTTP service + def query_http_service(url) + # Fetch details over HTTP + url = URI.parse(url) + info = url.read + # Assume online if we get a 200/OK response + return '200' === info.status[0] + end + + + module Account + # Query the account service to determine its status + def query(url) + # Discover host + auth_host, auth_port = discover(service) + unless auth_host.nil? then + # Query host + sock = TCPSocket.new auth_host, auth_port + sock.puts 'AVAIL' + status = sock.gets + sock.close + + return 'AVAIL' === status.strip + else + return false + end + end + + + # Discover the account service host/port + def discover(url) + # Fetch details over HTTP + url = URI.parse(url) + info = url.read + # Parse out host:port + if '200' === info.status[0] then + info.split(/[:\s]/) + else + return nil + end + end + end + + + module Listing + # Query the listing service to determine its status + def query(url) + return TribesNext.query_http(url) + end + end + + + module Community + # Query the community service to determine its status + def query(url) + return TribesNext.query_http(url) + end + end +end