class Pickynode

Allows you to easily add/ban/connect/disconnect nodes based on User Agent.

Constants

VERSION

Public Class Methods

new(opts = {}) click to toggle source
# File lib/pickynode.rb, line 14
def initialize(opts = {})
  @opts = opts
end

Public Instance Methods

add(filter, limit = nil) click to toggle source
# File lib/pickynode.rb, line 18
def add(filter, limit = nil)
  return unless filter

  validate_limit(limit)

  count = 0
  bitnode_addr_types.select { |_, v| v.include?(filter) }.each do |k, _|
    run_cmd(%(bitcoin-cli addnode "#{k}" "add"))
    count += 1
    break if limit == count
  end
end
ban(filter) click to toggle source
# File lib/pickynode.rb, line 31
def ban(filter)
  return unless filter
  addr_types.each do |k, v|
    if v.include?(filter)
      u = URI.parse("https://#{k}")
      run_cmd(%(bitcoin-cli setban "#{u.host}" "add"))
    end
  end
end
clear_cache() click to toggle source
# File lib/pickynode.rb, line 79
def clear_cache
  @addr_types = nil
  @bitnode_addr_types = nil
end
connect(filter, limit = nil) click to toggle source
# File lib/pickynode.rb, line 41
def connect(filter, limit = nil)
  return unless filter

  validate_limit(limit)

  count = 0
  bitnode_addr_types.select { |_, v| v.include?(filter) }.each do |k, _|
    run_cmd(%(bitcoin-cli addnode "#{k}" "onetry"))
    count += 1
    break if limit == count
  end
end
disconnect(filter) click to toggle source
# File lib/pickynode.rb, line 54
def disconnect(filter)
  return unless filter
  addr_types.each do |k, v|
    run_cmd(%(bitcoin-cli disconnectnode "#{k}")) if v.include?(filter)
  end
end
display() click to toggle source
# File lib/pickynode.rb, line 61
def display
  ap addr_types
end
info() click to toggle source
# File lib/pickynode.rb, line 65
def info
  ap getinfo
end
run() click to toggle source
# File lib/pickynode.rb, line 69
def run
  add(@opts[:add], @opts[:limit])
  connect(@opts[:connect], @opts[:limit])

  ban(@opts[:ban])
  disconnect(@opts[:disconnect])

  display_info
end

Private Instance Methods

addr_types() click to toggle source
# File lib/pickynode.rb, line 96
def addr_types
  return @addr_types if @addr_types
  nodes = getpeerinfo
  parsed_nodes = JSON.parse(nodes)
  @addr_types = parsed_nodes.map do |n|
    [n['addr'], n['subver']]
  end.to_h
rescue JSON::ParserError
  {}
end
bitnode_addr_types() click to toggle source
# File lib/pickynode.rb, line 107
def bitnode_addr_types
  return @bitnode_addr_types if @bitnode_addr_types
  parsed_nodelist = JSON.parse(bitnodes_snapshot)
  @bitnode_addr_types = parsed_nodelist['nodes'].map do |k, v|
    [k, v[1]]
  end.to_h
rescue JSON::ParserError
  {}
end
bitnodes_snapshot() click to toggle source
# File lib/pickynode.rb, line 117
def bitnodes_snapshot
  Net::HTTP.get(URI.parse('https://bitnodes.21.co/api/v1/snapshots/latest/'))
end
display_info() click to toggle source
# File lib/pickynode.rb, line 86
def display_info
  info if @opts[:info]
  display if @opts.values.select { |v| v }.empty?
end
getinfo() click to toggle source
# File lib/pickynode.rb, line 121
def getinfo
  JSON.parse(`bitcoin-cli getinfo`)
rescue JSON::ParserError
  {}
end
getpeerinfo() click to toggle source
# File lib/pickynode.rb, line 127
def getpeerinfo
  `bitcoin-cli getpeerinfo`
end
run_cmd(cmd) click to toggle source
# File lib/pickynode.rb, line 91
def run_cmd(cmd)
  puts "Running #{cmd}" if @opts[:output] || @opts[:debug]
  `#{cmd}` unless @opts[:debug]
end
validate_limit(limit) click to toggle source
# File lib/pickynode.rb, line 131
def validate_limit(limit)
  return unless limit
  raise 'Limit must be greater than 0' unless limit > 0
end