brandkit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fec24aa78cc7f4ac5dd130e84d05e7fa2d119baef30d403f644ce27d3f36e326
4
+ data.tar.gz: 444d5f42e748f3c53ffeaa23bde9bc79e2215ea851875869ad81508e45d4cc4a
5
+ SHA512:
6
+ metadata.gz: 84331e4f351c06029a594164d06cf475275436ed6a09f645c2f35e078d5370250e94503c9d6eaee0af25a9df8c35254c265ef958fb9748d7039d1a049a421cd1
7
+ data.tar.gz: 7de99fac92531a86570b77f2a5ce6bc60a729fa82c3be069bdfe07a67bb6e48b2e426a44b84daf53526600d8ce85cfcca14d896230d316043570b8afbf6b68df
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Rajan Bhattarai
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # BrandKit
2
+
3
+ **BrandKit** is a modern, interactive CLI tool designed to help entrepreneurs,
4
+ developers, and creatives quickly check the availability of domains and social
5
+ media usernames — all from the command line. It combines domain availability
6
+ checks via the Namecheap API with username availability checks on popular social
7
+ platforms, helping you secure your brand identity in one place.
8
+
9
+ ---
10
+
11
+ ## Features
12
+
13
+ - **Domain Availability Check**
14
+ Checks if a domain (e.g. `example.com`) is available to register using the
15
+ Namecheap API. If a domain is not provided with a TLD, it suggests popular
16
+ extensions like `.com`, `.net`, `.io`, etc., and shows their availability in a
17
+ table.
18
+
19
+ - **Social Username Availability Check**
20
+ Interactively checks if your chosen username is available on multiple social
21
+ media platforms including GitHub, Twitter, Instagram, TikTok, LinkedIn, and
22
+ more.
23
+
24
+ - **Interactive CLI Experience**
25
+ Powered by TTY::Prompt for user-friendly menus, multi-selects, and prompts,
26
+ plus colorful terminal output for better readability.
27
+
28
+ - **Clean & Extensible Codebase**
29
+ Modular design with dedicated classes for API communication (
30
+ `NamecheapClient`), domain checks (`DomainChecker`), and social username
31
+ checks (`SocialUsernameChecker`).
32
+
33
+ - **Dockerized for Easy Setup**
34
+ Runs inside a container for hassle-free installation and dependency
35
+ management.
36
+
37
+ ---
38
+
39
+ ## Getting Started
40
+
41
+ ### Prerequisites
42
+
43
+ - Ruby 3.x installed locally or use Docker
44
+ - Namecheap API credentials (API user, API key, username, client IP)
45
+ - Internet connection to query domain and social media availability
46
+
47
+ ### Environment Variables
48
+
49
+ Before running, set these environment variables in your shell or `.env` file:
50
+
51
+ ```bash
52
+ export NAMECHEAP_API_USER=your_api_user
53
+ export NAMECHEAP_API_KEY=your_api_key
54
+ export NAMECHEAP_USERNAME=your_namecheap_username
55
+ export CLIENT_IP=your_client_ip
56
+ ```
57
+
58
+ ### Installation
59
+
60
+ Clone the repo and install dependencies:
61
+
62
+ ```bash
63
+ git clone https://github.com/yourusername/brandkit.git
64
+ cd brandkit
65
+ bundle install
66
+ ```
67
+
68
+ Alternatively, use Docker:
69
+
70
+ ```bash
71
+ docker-compose build
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Usage
77
+
78
+ ### Run interactively
79
+
80
+ Launch the CLI with an interactive prompt experience, guiding you step-by-step:
81
+
82
+ ```bash
83
+ docker-compose run cli
84
+ ```
85
+
86
+ Or locally:
87
+
88
+ ```bash
89
+ ruby bin/brandkit
90
+ ```
91
+
92
+ ### Run with command-line arguments
93
+
94
+ Provide a domain upfront to skip prompts:
95
+
96
+ ```bash
97
+ docker-compose run cli ruby bin/brandkit --domain=example.com
98
+ ```
99
+
100
+ This will check the domain immediately and display availability, with an option
101
+ to check social usernames.
102
+
103
+ ---
104
+
105
+ ## Code Overview
106
+
107
+ ### `BrandKit`
108
+
109
+ The main CLI application class coordinating user input, output formatting, and
110
+ flow control. Uses:
111
+
112
+ - `TTY::Prompt` for interactive prompts
113
+ - `Artii` for ASCII banners
114
+ - `Colorize` for colored terminal output
115
+
116
+ ### `DomainChecker`
117
+
118
+ Handles domain availability checking logic:
119
+
120
+ - Uses the `NamecheapClient` API wrapper to query domain status
121
+ - Suggests popular TLDs if no extension is provided
122
+ - Displays results in a neat table format
123
+
124
+ ### `ApiClients::NamecheapClient`
125
+
126
+ API client encapsulating communication with the Namecheap XML API:
127
+
128
+ - Authenticates via environment variables
129
+ - Handles building query parameters and HTTP requests
130
+ - Parses XML responses and handles errors gracefully
131
+
132
+ ### `SocialUsernameChecker`
133
+
134
+ Checks username availability on popular social platforms by performing HTTP GET
135
+ requests to profile URLs and interpreting the HTTP response status.
136
+
137
+ - Supports GitHub, Twitter, Instagram, Facebook, YouTube, TikTok, Pinterest,
138
+ LinkedIn, Reddit, Threads
139
+ - Allows querying single or multiple platforms interactively
140
+
141
+ ---
142
+
143
+ ## Contributing
144
+
145
+ Contributions are welcome! Please fork the repo and submit pull requests with
146
+ descriptive commit messages. Make sure to follow the existing code style and add
147
+ tests if applicable.
148
+
149
+ ---
150
+
151
+ ## License
152
+
153
+ MIT License © Rajan Bhattarai
154
+
155
+ ---
156
+
157
+ ## Acknowledgments
158
+
159
+ - [Namecheap API](https://www.namecheap.com/support/api/)
160
+ - [TTY Toolkit](https://ttytoolkit.org/)
161
+ - [Artii](https://github.com/miketierney/artii)
162
+ - [Colorize](https://github.com/fazibear/colorize)
163
+
164
+ ---
data/bin/brandkit ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/brand_kit'
5
+
6
+ BrandKit.new.run
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'httparty'
4
+
5
+ module ApiClients
6
+ # A client for interacting with the Namecheap XML API.
7
+ # Currently supports checking domain availability.
8
+ class NamecheapClient
9
+ include HTTParty
10
+ base_uri 'https://api.namecheap.com/xml.response'
11
+
12
+ attr_reader :api_user, :api_key, :username, :client_ip
13
+
14
+ def initialize
15
+ @api_user = ENV.fetch('NAMECHEAP_API_USER')
16
+ @api_key = ENV.fetch('NAMECHEAP_API_KEY')
17
+ @username = ENV.fetch('NAMECHEAP_USERNAME')
18
+ @client_ip = ENV.fetch('CLIENT_IP')
19
+ end
20
+
21
+ # Public: Check if a domain is available for registration.
22
+ #
23
+ # domain - A String domain name to check (e.g., "example.com").
24
+ #
25
+ # Returns true if the domain is available, false otherwise.
26
+ def check_domain(domain)
27
+ response = make_request(
28
+ command: 'namecheap.domains.check',
29
+ params: { DomainList: domain }
30
+ )
31
+
32
+ available = response.dig('ApiResponse', 'CommandResponse', 'DomainCheckResult', 'Available')
33
+ available == 'true'
34
+ rescue StandardError => e
35
+ warn "Error checking domain '#{domain}': #{e.message}"
36
+ false
37
+ end
38
+
39
+ private
40
+
41
+ # Private: Build the query parameters for the API call.
42
+ #
43
+ # command - Namecheap API command string.
44
+ # params - Additional parameters for the specific command.
45
+ #
46
+ # Returns a Hash with all query parameters merged.
47
+ def build_query(command:, params: {})
48
+ {
49
+ ApiUser: api_user,
50
+ ApiKey: api_key,
51
+ UserName: username,
52
+ ClientIp: client_ip,
53
+ Command: command
54
+ }.merge(params)
55
+ end
56
+
57
+ # Private: Perform the HTTP GET request to the Namecheap API.
58
+ #
59
+ # command - The API command to call (e.g., "namecheap.domains.check").
60
+ # params - Additional parameters for the command.
61
+ #
62
+ # Returns a parsed Hash of the XML response.
63
+ def make_request(command:, params: {})
64
+ query = build_query(command: command, params: params)
65
+ response = self.class.get('/', query: query)
66
+
67
+ raise "API call failed with HTTP #{response.code}" unless response.success?
68
+
69
+ parsed = response.parsed_response
70
+ raise 'Invalid API response structure' unless parsed.is_a?(Hash)
71
+
72
+ parsed
73
+ end
74
+ end
75
+ end
data/lib/brand_kit.rb ADDED
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'byebug'
4
+ require 'tty-prompt'
5
+ require 'tty-table'
6
+ require 'colorize'
7
+ require 'artii'
8
+ require 'dotenv/load' # this auto-loads .env
9
+
10
+ require_relative 'domain_checker'
11
+ require_relative 'social_username_checker'
12
+ require_relative 'api_clients/namecheap_client'
13
+
14
+ # BrandKit CLI app for checking domain and social media username availability
15
+ class BrandKit
16
+ # Initialize the CLI with prompt, ASCII art generator, and JSON output flag
17
+ def initialize
18
+ @prompt = TTY::Prompt.new
19
+ @artii = Artii::Base.new
20
+ @json_output = ARGV.include?('--json')
21
+ end
22
+
23
+ # Main entry point to run the app flow:
24
+ # 1. Show intro banner
25
+ # 2. Get domain input from args or prompt
26
+ # 3. Check domain availability
27
+ # 4. Show domain result with purchase link if available
28
+ # 5. Optionally check social username availability
29
+ # 6. Show farewell banner
30
+ def run
31
+ intro_banner
32
+
33
+ domain = extract_domain_from_argv || prompt_for_domain
34
+ domain_result = DomainChecker.new(domain).check
35
+
36
+ show_result_box(domain_result[:message], :green)
37
+
38
+ print_purchase_link(domain_result) if domain_result[:link]
39
+
40
+ ask_social_check(domain_result[:domain])
41
+ farewell_banner
42
+ end
43
+
44
+ private
45
+
46
+ # Extract domain argument from ARGV (e.g. --domain=example.com)
47
+ #
48
+ # Returns domain string or nil if not present
49
+ def extract_domain_from_argv
50
+ domain_arg = ARGV.find { |arg| arg.start_with?('--domain=') }
51
+ domain_arg&.split('=', 2)&.last
52
+ end
53
+
54
+ # Prompt the user for a domain input with colored prompt message
55
+ #
56
+ # Returns the user-entered domain string
57
+ def prompt_for_domain
58
+ colored_prompt('🌐 Enter domain (e.g. example or example.com):')
59
+ end
60
+
61
+ # Show ASCII art intro banner with app title and tagline
62
+ def intro_banner
63
+ ascii = @artii.asciify('BrandKit').colorize(:cyan)
64
+ puts ascii
65
+
66
+ width = 60
67
+ title = '🚀 Welcome to BrandKit'
68
+ top_border = " #{title.ljust(width - 2)}"
69
+ bottom_border = '─' * width
70
+
71
+ body = [
72
+ '',
73
+ 'The fastest way to check domain and',
74
+ 'social media username availability!',
75
+ ''
76
+ ].map { |line| line.colorize(:light_white).center(width) }
77
+
78
+ puts top_border
79
+ body.each { |line| puts line }
80
+ puts bottom_border
81
+ end
82
+
83
+ # Show farewell banner with thanks message
84
+ def farewell_banner
85
+ width = 60
86
+ title = '👋'
87
+ top_border = " #{title.ljust(width - 2)}"
88
+ bottom_border = '─' * width
89
+
90
+ body = [
91
+ '',
92
+ 'Thanks for using BrandKit!',
93
+ 'Start building your brand today. ✨',
94
+ ''
95
+ ].map { |line| line.colorize(:light_magenta).center(width) }
96
+
97
+ puts top_border
98
+ body.each { |line| puts line }
99
+ puts bottom_border
100
+ end
101
+
102
+ # Display a formatted box with a status message in specified color
103
+ #
104
+ # message - String message to display
105
+ # color - Symbol colorize color (default :green)
106
+ def show_result_box(message, color = :green)
107
+ return if message.to_s.strip.empty?
108
+
109
+ width = 60
110
+ label = '✦ Domain Status'
111
+ top_border = " #{label.ljust(width - 2)}"
112
+ bottom_border = '─' * width
113
+
114
+ body = ['', message.colorize(:light_green).center(width), '']
115
+
116
+ puts "\n"
117
+ puts top_border.colorize(color)
118
+ body.each { |line| puts line }
119
+ puts bottom_border.colorize(color)
120
+ end
121
+
122
+ # Prompt with colorized question and return the answer
123
+ #
124
+ # question - String question to ask user
125
+ #
126
+ # Returns user input string
127
+ def colored_prompt(question)
128
+ @prompt.ask(question.colorize(:light_blue))
129
+ end
130
+
131
+ # Print domain purchase link if domain is available
132
+ #
133
+ # domain_result - Hash containing domain info (expects :domain key)
134
+ def print_purchase_link(domain_result)
135
+ purchase_url = "https://www.namecheap.com/domains/registration/results/?domain=#{domain_result[:domain]}"
136
+ puts "\n🔗 #{'Purchase here:'.colorize(:light_green)} #{purchase_url.underline}"
137
+ puts "\n"
138
+ end
139
+
140
+ # Prompt user whether to check social username availability,
141
+ # allow selection of platforms, check availability, and print results in a table
142
+ #
143
+ # domain - String domain name to check usernames for
144
+ def ask_social_check(domain)
145
+ return unless @prompt.yes?('📱 Check if the username is available on social platforms?'.colorize(:light_cyan))
146
+
147
+ all_choice = '🌍 All supported platforms'
148
+ choices = [all_choice] + SocialUsernameChecker::PLATFORMS.keys.map(&:to_s)
149
+
150
+ selected = prompt_platform_selection(choices, all_choice)
151
+
152
+ platforms_to_check = if selected.include?(all_choice)
153
+ SocialUsernameChecker::PLATFORMS.keys
154
+ else
155
+ selected.map(&:to_sym)
156
+ end
157
+
158
+ checker = SocialUsernameChecker.new
159
+ username = checker.send(:strip_extension, domain)
160
+
161
+ results = platforms_to_check.map do |platform|
162
+ available = checker.username_available?(username, platform)
163
+ status = available ? '✔ Available'.colorize(:green) : '✘ Taken'.colorize(:red)
164
+ [platform.to_s.capitalize, status]
165
+ end
166
+
167
+ table = TTY::Table.new(['📡 Platform', '🔍 Status'], results)
168
+ puts "\n#{table.render(:unicode, padding: [0, 3], alignment: [:center])}"
169
+ end
170
+
171
+ # Loop prompting user to select platforms, enforcing selection rules
172
+ #
173
+ # choices - Array of choice strings including 'All supported platforms'
174
+ # all_choice - String representing 'all platforms' option
175
+ #
176
+ # Returns array of selected platform strings
177
+ def prompt_platform_selection(choices, all_choice)
178
+ selected = []
179
+
180
+ loop do
181
+ puts "\n"
182
+ selected = @prompt.multi_select('✔ Select platforms to check (space to select):'.colorize(:cyan), choices, per_page: 12)
183
+
184
+ if selected.empty?
185
+ puts '⚠️ You must select at least one platform.'.colorize(:yellow)
186
+ elsif selected.include?(all_choice) && selected.length > 1
187
+ puts "⚠️ Please select either '#{all_choice}' or specific platforms, not both.".colorize(:yellow)
188
+ else
189
+ break
190
+ end
191
+ end
192
+
193
+ selected
194
+ end
195
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-table'
4
+ require 'colorize'
5
+
6
+ # DomainChecker handles checking domain availability using Namecheap API.
7
+ # Supports both exact domain check and suggestions with common TLDs.
8
+ class DomainChecker
9
+ COMMON_TLDS = %w[.com .net .org .io .dev .app .co .xyz .tech .site].freeze
10
+
11
+ # Initialize with the domain string to check.
12
+ #
13
+ # domain - String domain or base name (e.g. "example" or "example.com")
14
+ def initialize(domain)
15
+ @domain = domain
16
+ @client = ApiClients::NamecheapClient.new
17
+ end
18
+
19
+ # Perform the domain availability check.
20
+ #
21
+ # Returns a Hash with keys:
22
+ # - :available (Boolean)
23
+ # - :domain (String)
24
+ # - :message (String, colorized)
25
+ # - :link (String URL if available)
26
+ # - :suggestions (Array of [domain, available] for common TLDs if no exact domain)
27
+ def check
28
+ if exact_domain?(@domain)
29
+ check_exact_domain(@domain)
30
+ else
31
+ check_domain_suggestions(@domain)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ # Determine if the domain includes a dot (TLD)
38
+ #
39
+ # domain - String
40
+ #
41
+ # Returns Boolean
42
+ def exact_domain?(domain)
43
+ domain.include?('.')
44
+ end
45
+
46
+ # Check availability for exact domain (with TLD)
47
+ #
48
+ # domain - String
49
+ #
50
+ # Returns Hash with availability info and message
51
+ def check_exact_domain(domain)
52
+ available = @client.check_domain(domain)
53
+
54
+ {
55
+ available: available,
56
+ domain: domain,
57
+ message: available ? success_message(domain) : failure_message(domain),
58
+ link: available ? purchase_link(domain) : nil
59
+ }
60
+ end
61
+
62
+ # Check availability for common TLD suggestions and display results
63
+ #
64
+ # base_domain - String domain base without TLD (e.g. "example")
65
+ #
66
+ # Returns Hash with message, suggestions, and availability false
67
+ def check_domain_suggestions(base_domain)
68
+ suggestions = COMMON_TLDS.map do |tld|
69
+ full_domain = "#{base_domain}#{tld}"
70
+ available = @client.check_domain(full_domain)
71
+ [full_domain, available]
72
+ end
73
+
74
+ print_suggestions_table(suggestions.first(10))
75
+
76
+ available_count = suggestions.count { |_, available| available }
77
+
78
+ {
79
+ available: false,
80
+ domain: base_domain,
81
+ message: availability_summary_message(base_domain, available_count),
82
+ suggestions: suggestions
83
+ }
84
+ end
85
+
86
+ # Print a formatted table of domain suggestions and their availability
87
+ #
88
+ # suggestions - Array of [domain, Boolean availability]
89
+ def print_suggestions_table(suggestions)
90
+ rows = suggestions.map do |domain, available|
91
+ [domain, available ? '✔ Available'.colorize(:green) : '✖ Taken'.colorize(:red)]
92
+ end
93
+
94
+ table = TTY::Table.new(%w[Domain Status], rows)
95
+ puts "\nTop Domain Extensions:\n"
96
+ puts table.render(:unicode, padding: [0, 2])
97
+ end
98
+
99
+ # Compose a colorized success message for available domain
100
+ #
101
+ # domain - String
102
+ #
103
+ # Returns String
104
+ def success_message(domain)
105
+ "✔ Domain #{domain} is available!".colorize(:green)
106
+ end
107
+
108
+ # Compose a colorized failure message for taken domain
109
+ #
110
+ # domain - String
111
+ #
112
+ # Returns String
113
+ def failure_message(domain)
114
+ "✘ Domain #{domain} is taken.".colorize(:red)
115
+ end
116
+
117
+ # Generate a purchase link URL for a domain
118
+ #
119
+ # domain - String
120
+ #
121
+ # Returns String URL
122
+ def purchase_link(domain)
123
+ "https://www.namecheap.com/domains/registration/results/?domain=#{domain}"
124
+ end
125
+
126
+ # Return a user-friendly message summarizing availability across TLDs
127
+ #
128
+ # base_domain - String base domain (without TLD)
129
+ # available_count - Integer count of available domains
130
+ #
131
+ # Returns String message
132
+ def availability_summary_message(base_domain, available_count)
133
+ case available_count
134
+ when 0
135
+ "😞 No common domain extensions are available for ‘#{base_domain}’. Try a different name."
136
+ when 1..3
137
+ "⚠️ Only a few options are available for ‘#{base_domain}’. Consider securing one quickly!"
138
+ when 4..6
139
+ "🙂 Some good domain extensions are still available for ‘#{base_domain}’."
140
+ else
141
+ "🎉 Great news! Many domain extensions are available for ‘#{base_domain}’."
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'colorize'
6
+
7
+ # SocialUsernameChecker checks username availability across multiple social platforms.
8
+ class SocialUsernameChecker
9
+ # Supported platforms and their URL patterns for usernames
10
+ PLATFORMS = {
11
+ github: 'https://github.com/%<username>s',
12
+ twitter: 'https://twitter.com/%<username>s',
13
+ instagram: 'https://www.instagram.com/%<username>s',
14
+ facebook: 'https://www.facebook.com/%<username>s',
15
+ youtube: 'https://www.youtube.com/@%<username>s',
16
+ tiktok: 'https://www.tiktok.com/@%<username>s',
17
+ pinterest: 'https://www.pinterest.com/%<username>s',
18
+ linkedin: 'https://www.linkedin.com/in/%<username>s',
19
+ reddit: 'https://www.reddit.com/user/%<username>s',
20
+ threads: 'https://www.threads.net/@%<username>s'
21
+ }.freeze
22
+
23
+ # Returns an array of supported platform names as strings
24
+ #
25
+ # Returns Array<String>
26
+ def supported_platforms
27
+ PLATFORMS.keys.map(&:to_s)
28
+ end
29
+
30
+ # Check if a username is available on a given platform.
31
+ #
32
+ # username - String username to check
33
+ # platform - Symbol or String platform key (e.g., :github or "github")
34
+ #
35
+ # Returns Boolean true if available, false if taken or on error.
36
+ def username_available?(username, platform)
37
+ platform_key = platform.to_sym
38
+
39
+ unless PLATFORMS.key?(platform_key)
40
+ warn "Unsupported platform: #{platform}"
41
+ return false
42
+ end
43
+
44
+ url = format(PLATFORMS[platform_key], username: username)
45
+ uri = URI.parse(url)
46
+
47
+ response = fetch_response(uri)
48
+
49
+ # If HTTP status is not 200, assume username is available (profile not found)
50
+ return true unless response.code == '200'
51
+
52
+ # Check response body for username presence (basic heuristic)
53
+ body = response.body.force_encoding('UTF-8')
54
+
55
+ # If the username appears in the page content, it's likely taken
56
+ !body.include?(username)
57
+ rescue StandardError => e
58
+ warn "⚠️ Error checking #{platform}: #{e.message}".colorize(:yellow)
59
+ false
60
+ end
61
+
62
+ private
63
+
64
+ # Perform a GET request and return the HTTP response
65
+ #
66
+ # uri - URI object
67
+ #
68
+ # Returns Net::HTTPResponse
69
+ def fetch_response(uri)
70
+ Net::HTTP.get_response(uri)
71
+ end
72
+
73
+ # Remove TLD extension from a domain to get a clean username base
74
+ #
75
+ # domain - String domain name (e.g. "example.com")
76
+ #
77
+ # Returns String username base (e.g. "example")
78
+ def strip_extension(domain)
79
+ domain.split('.').first
80
+ end
81
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brandkit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Rajan Bhattarai
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-06-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.18'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.18'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-prompt
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.23'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.23'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tty-table
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.12'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: colorize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.8'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.8'
69
+ - !ruby/object:Gem::Dependency
70
+ name: artii
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.10'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.10'
97
+ - !ruby/object:Gem::Dependency
98
+ name: byebug
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '11.1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '11.1'
111
+ description: BrandKit is a Ruby CLI that helps check domain availability via Namecheap
112
+ API and social media username availability across multiple platforms.
113
+ email:
114
+ - publisher@rajanbhattarai.com
115
+ executables:
116
+ - brandkit
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - LICENSE
121
+ - README.md
122
+ - bin/brandkit
123
+ - lib/api_clients/namecheap_client.rb
124
+ - lib/brand_kit.rb
125
+ - lib/domain_checker.rb
126
+ - lib/social_username_checker.rb
127
+ homepage: https://github.com/cdrrazan/brandkit
128
+ licenses:
129
+ - MIT
130
+ metadata:
131
+ bug_tracker_uri: https://github.com/cdrrazan/brandkit/issues
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '3.2'
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubygems_version: 3.4.17
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: A CLI tool to check domain and social username availability
151
+ test_files: []