DEV Community


Posted on • Updated on

Small code refactor - Moriarty part-2

GitHub logo decentralizuj / moriarty

Moriarty - Tool to check social networks for available username

  • GIF preview v-0.2.0 - without latest changes'

Moriarty Preview

Gem is still in alpha, many things will be added (like scrapping info from social networks) Breaking changes are highly possible, so I do not suggest use of this gem except for development and test That means, do not use it in production services, otherwise feel free to play with it.


Tool to check social networks for available username.
Idea from python tool - sherlock

What it do

Search multiple social networks for free username It's reverse from Sherlock, so not-found username is success. Argument --hunt will run search like sherlock would, looking for valid users.

How to install

Clone repo and install dependencies:

# Moriarty use rest-client, nokogiri and colorize gems
 git clone && cd moriarty && bundle install
Enter fullscreen mode Exit fullscreen mode

Or install from rubygems:

DISCLAIMER GitHub repository is updated before Rubygems. Before v-1.0.0 is released, recommended way is to clone repo,…

First code is never good enough, especially in Ruby, where everything could be done in many different ways. I'll start with initializer:

  # Set username and site for search request
  # exclude 'https', #make_url will add it for you
  # To use different protocol, set it as third parameter
  # @jim = :moriarty, '', :http )
  #  => @jim.user == 'moriarty'
  #  => @jim.url  == ''

  def initialize( name = '', site = '', prot = :https )
    @user = name.to_s
    @url  = make_url site, prot
Enter fullscreen mode Exit fullscreen mode

Here we added 'make_url(site_name, protocol)'. This method purpose is to construct URL from string, so we can use instead of

  # create URL from site name, add 'https' if needed
  # @jim.make_url ''
  #  => ''

  def make_url( link, prot = :https )
    prot = nil if link.to_s.start_with? prot.to_s
    url  = prot.nil? ? link.to_s : prot.to_s + '://' + link.to_s
    url += '/' unless url.end_with?('/')
    return url
Enter fullscreen mode Exit fullscreen mode

Here we can add parameter site: in Moriarty#go, without https://. In first part I said that we'll create setters manually. Now we can use #make_url in setter to create link from string.

  # Set URL from site name and protocol(optional)
  # @jim.url = ''
  #  => @jim.url == ''

  def url=( link, prot = :https )
    @url = make_url link, prot

  # Set username from string or :symbol
  # @jim.user = :moriarty
  #  => @jim.user == 'moriarty'

  def user=( name )
    @user = name.to_s
Enter fullscreen mode Exit fullscreen mode

It's time to edit Moriarty#go, method in charge to send request.

  # execute request (args are optional)
  # @jim.go site: '', user: 'mynickname'
  #  => true/false
  #  -> @jim.response (.code, .headers, .body)
  #  -> @jim.html (page HTML if request success)

  def go( opt = {} )

    # define username to search, or use default
    opt[:user] ||= @user

    # if option 'site:' is 'nil', use default
    # otherwise construct url with '#make_url'
    url = opt[:site].nil? ? @url : make_url(opt[:site])

    # create url for request, and send
    uri = url + opt[:user]
    @response = RestClient.get uri

    # try to scrap data from page
    @html     = Nokogiri::HTML @response

    # return true or false
    return @success = true
    return @success = false

  # add alias search, just because of convention
  alias search go
Enter fullscreen mode Exit fullscreen mode

There's one more thing that we should add here, to check for response success:

  # Check does request succeeded or not
  # @jim.success?
  #  => true/false

  def success?
    @success == true
Enter fullscreen mode Exit fullscreen mode

Create method to execute search request, and output data in terminal. Default method is search for free username, in that case fail requests mean username is free. If we define :hunt as type parameter, we will search for registered user.

  # Find method is responsible to handle all other methods
  # and to tell use final results

  def find!( user = @user, web = @url, type = :search )

    @jim.go user: user, site: site

    name = print_name(user).to_s
    site = print_url(web).to_s

    when type.to_sym == :hunt && @jim.success?
      puts "#{name} found on #{site}"

    when type.to_sym == :hunt && !@jim.success?
      puts "#{name} not found #{site}"

   when @jim.success?
      puts "#{name} is taken on #{site}"

      puts "#{name} is free on #{site}"
Enter fullscreen mode Exit fullscreen mode

Methods #print_name and #print_url prepare strings for printing in cli. Names are cleaned from signs like @, #, /u/, and site is stripped of extensions and capitalized.

  # Remove extensions from domain name
  # Moriarty.print_url('')
  #  => 'github'

  def print_url( site )

    # define site from string
    # make name empty string
    site, name = site.to_s, ''

    # if site start with 'http', try to remove 'https'
    # if not, then remove 'http'

    if site.start_with?('http')
      site.gsub!("https://", '') or site.gsub!("http://", '')

    # remove 'www.' from sitename, if included

    site.gsub!("www.", '') if site.start_with?('www.')

    # split domain on '.' to get extension, and remove it

    ext  = site.to_s.split('.').last
    name = site.gsub(".#{ext}", '')

    # if ext is longer then 5, routes contain more data
    # example: '*'

    name = name.split('/').first if ext.size < 5

    # first letter uppercase

    return name.capitalize


  # Remove extensions from username
  # @jim.print_name('@moriarty') 
  #  => 'moriarty'

  def print_name( name )
    name.gsub!('@','') if name.to_s.start_with?('@')
    name.gsub!('#','') if name.to_s.start_with?('#')
    name.gsub!('/u/','') if name.to_s.start_with?('/u/')
    return name
Enter fullscreen mode Exit fullscreen mode

Now we have class with all objects needed to do what we want it to do. For sites that need to check html for success (like twitter), there's variable @html ( getter Moriarty.html ).

Let's run search from terminal. How? We need to define sites to search, and usernames. We'll define sites as array, and accept usernames as arguments. If we add --hunt, it will run in hunt mode, otherwise in default (search for free name).

  # define sites to search

  SITES = [ '', '' ].freeze

  # run hunt if arg --hunt included, otherwise search

  hunt = ARGV.include?('--hunt') ? :hunt : :search

  unless ARGV.empty?

    @jim = :jim

    ARGV.each do |user|
      SITES.each do |site|

        next if user == '--hunt'
        @jim.find! user, site, hunt


Enter fullscreen mode Exit fullscreen mode

Thanks all for reading this post(s), don't forget to share content...somewhere :) In next article I'll pack and compile this into a gem.

Top comments (0)