Skip to content

Commit

Permalink
v2.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ninoseki committed Feb 8, 2024
1 parent 9ae1ed2 commit 17498aa
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 67 deletions.
13 changes: 11 additions & 2 deletions lib/miteru.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
require "miteru/concerns/error_unwrappable"

# Core classes
require "miteru/service"

require "miteru/cache"
require "miteru/config"
require "miteru/http"

Expand Down Expand Up @@ -93,6 +96,14 @@ def development?
env == "development"
end

def cache?
!Miteru.config.cache_redis_url.nil?
end

def cache
@cache ||= Cache.new(Miteru.config.cache_redis_url)
end

#
# @return [Boolean]
#
Expand All @@ -117,8 +128,6 @@ def initialize_sentry
end

# Services
require "miteru/service"

require "miteru/crawler"
require "miteru/downloader"
require "miteru/kit"
Expand Down
53 changes: 53 additions & 0 deletions lib/miteru/cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require "redis"

module Miteru
class Cache < Service
# @return [String]
attr_reader :url

#
# @param [String] url
#
def initialize(url)
super()
@url = url
end

#
# @param [String] key
# @param [String] value
# @param [Integer. nil] ex
#
def set(key, value, ex:)
value = redis.set("#{prefix}:#{key}", value, ex:)
Miteru.logger.info("Cache:#{key} is set.") if verbose?
value
end

#
# @param [String] key
#
def cached?(key)
value = redis.exists?("#{prefix}:#{key}")
Miteru.logger.info("Cache:#{key} found.") if verbose?
value
end

private

def verbose?
Miteru.config.verbose
end

def prefix
Miteru.config.cache_prefix
end

#
# @return [Redis]
#
def redis
@redis ||= Redis.new(url:)
end
end
end
12 changes: 12 additions & 0 deletions lib/miteru/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class Config < Anyway::Config
sentry_dsn: nil,
sentry_trace_sample_rate: 0.25,
sidekiq_redis_url: nil,
cache_redis_url: nil,
cache_ex: nil,
cache_prefix: "miteru:cache",
slack_channel: "#general",
slack_webhook_url: nil,
threads: Parallel.processor_count,
Expand All @@ -39,6 +42,15 @@ class Config < Anyway::Config
# @return [Float]

# @!attribute [r] sidekiq_redis_url
# @return [String, nil]

# @!attribute [r] cache_redis_url
# @return [String, nil]

# @!attribute [r] cache_ex
# @return [Integer, nil]

# @!attribute [r] cache_prefix
# @return [String]

# @!attribute [r] http_timeout
Expand Down
36 changes: 26 additions & 10 deletions lib/miteru/crawler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,44 @@ def call(website)
Try[OpenSSL::SSL::SSLError, ::HTTP::Error, Addressable::URI::InvalidURIError] do
info = "Website:#{website.info}."
info = info.colorize(:red) if website.kits?

Miteru.logger.info(info)
return unless website.kits?

notify website

return unless auto_download?

website.kits.each do |kit|
downloader = Downloader.new(kit)
result = downloader.result
if result.success?
Miteru.logger.info("Kit:#{kit.truncated_url} downloaded as #{result.value!}.")
else

unless result.success?
Miteru.logger.warn("Kit:#{kit.truncated_url} failed to download - #{result.failure}.")
next
end

destination = result.value!
Miteru.logger.info("Kit:#{kit.truncated_url} downloaded as #{destination}.")
# Remove downloaded file if auto_download is not allowed
FileUtils.rm(destination, force: true) unless auto_download?
# Notify the website
notify website
end

# Cache the website
cache.set(website.url, website.source, ex: cache_ex) if cache?
end.recover { nil }.value!
end

private

def cache?
Miteru.cache?
end

def cache
Miteru.cache
end

def cache_ex
Miteru.config.cache_ex
end

def auto_download?
Miteru.config.auto_download
end
Expand All @@ -41,7 +57,7 @@ def auto_download?
# @param [Miteru::Website] website
#
def notify(website)
notifiers.each do |notifier|
[].each do |notifier|
result = notifier.result(website)
if result.success?
Miteru.logger.info("Notifier:#{notifier.name} succeeded.")
Expand Down
22 changes: 18 additions & 4 deletions lib/miteru/orchestrator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@
module Miteru
class Orchestrator < Service
def call
Miteru.logger.info("#{websites.length} websites loaded in total.") if verbose?
Miteru.logger.info("#{non_cached_websites.length} websites loaded in total.") if verbose?

if Miteru.sidekiq?
websites.each do |website|
non_cached_websites.each do |website|
Jobs::CrawleJob.perform_async(website.url, website.source)
Miteru.logger.info("Website:#{website.truncated_url} crawler job queued.") if verbose?
end
else
Miteru.logger.info("Use #{threads} thread(s).") if verbose?
Parallel.each(websites, in_threads: threads) do |website|
Parallel.each(non_cached_websites, in_threads: threads) do |website|
Miteru.logger.info("Website:#{website.truncated_url} crawling started.") if verbose?

result = Crawler.result(website)
Expand All @@ -26,7 +26,7 @@ def call
end

#
# @return [Array<Miteru::Websites>]
# @return [Array<Miteru::Website>]
#
def websites
@websites ||= [].tap do |out|
Expand All @@ -43,6 +43,12 @@ def websites
end.flatten.uniq(&:url)
end

def non_cached_websites
return websites unless cache?

websites.reject { |website| cache.cached?(website.url) }
end

#
# @return [Array<Miteru::Feeds::Base>]
#
Expand All @@ -52,6 +58,14 @@ def feeds

private

def cache?
Miteru.cache?
end

def cache
Miteru.cache
end

def threads
Miteru.config.threads
end
Expand Down
2 changes: 1 addition & 1 deletion lib/miteru/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Miteru
VERSION = "2.1.1"
VERSION = "2.2.0"
end
101 changes: 51 additions & 50 deletions miteru.gemspec
Original file line number Diff line number Diff line change
@@ -1,67 +1,68 @@
# frozen_string_literal: true

lib = File.expand_path('lib', __dir__)
lib = File.expand_path("lib", __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'miteru/version'
require "miteru/version"

Gem::Specification.new do |spec|
spec.name = 'miteru'
spec.name = "miteru"
spec.version = Miteru::VERSION
spec.authors = ['Manabu Niseki']
spec.email = ['manabu.niseki@gmail.com']
spec.metadata['rubygems_mfa_required'] = 'true'
spec.authors = ["Manabu Niseki"]
spec.email = ["manabu.niseki@gmail.com"]
spec.metadata["rubygems_mfa_required"] = "true"

spec.summary = 'A phishing kit collector for scavengers'
spec.description = 'A phishing kit collector for scavengers'
spec.homepage = 'https://github.com/ninoseki/miteru'
spec.license = 'MIT'
spec.summary = "A phishing kit collector for scavengers"
spec.description = "A phishing kit collector for scavengers"
spec.homepage = "https://github.com/ninoseki/miteru"
spec.license = "MIT"

# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
spec.files = Dir.chdir(File.expand_path(__dir__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
spec.bindir = 'exe'
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']
spec.require_paths = ["lib"]

spec.add_development_dependency 'bundler', '~> 2.5'
spec.add_development_dependency 'capybara', '~> 3.40'
spec.add_development_dependency 'coveralls_reborn', '~> 0.28'
spec.add_development_dependency 'fuubar', '~> 2.5'
spec.add_development_dependency 'mysql2', '~> 0.5'
spec.add_development_dependency 'pg', '~> 1.5'
spec.add_development_dependency 'rake', '~> 13.1'
spec.add_development_dependency 'rspec', '~> 3.13'
spec.add_development_dependency 'simplecov-lcov', '~> 0.8'
spec.add_development_dependency 'standard', '~> 1.33'
spec.add_development_dependency 'test-prof', '~> 1.3'
spec.add_development_dependency 'vcr', '~> 6.2'
spec.add_development_dependency 'webmock', '~> 3.19'
spec.add_development_dependency "bundler", "~> 2.5"
spec.add_development_dependency "capybara", "~> 3.40"
spec.add_development_dependency "coveralls_reborn", "~> 0.28"
spec.add_development_dependency "fuubar", "~> 2.5"
spec.add_development_dependency "mysql2", "~> 0.5"
spec.add_development_dependency "pg", "~> 1.5"
spec.add_development_dependency "rake", "~> 13.1"
spec.add_development_dependency "rspec", "~> 3.13"
spec.add_development_dependency "simplecov-lcov", "~> 0.8"
spec.add_development_dependency "standard", "~> 1.33"
spec.add_development_dependency "test-prof", "~> 1.3"
spec.add_development_dependency "vcr", "~> 6.2"
spec.add_development_dependency "webmock", "~> 3.19"

spec.add_dependency 'activerecord', '7.1.3'
spec.add_dependency 'addressable', '2.8.6'
spec.add_dependency 'anyway_config', '2.6.2'
spec.add_dependency 'colorize', '1.1.0'
spec.add_dependency 'dotenv', '2.8.1'
spec.add_dependency 'down', '5.4.1'
spec.add_dependency 'dry-files', '1.1.0'
spec.add_dependency 'dry-monads', '1.6.0'
spec.add_dependency 'http', '5.2.0'
spec.add_dependency 'memo_wise', '1.8.0'
spec.add_dependency 'oga', '3.4'
spec.add_dependency 'parallel', '1.24.0'
spec.add_dependency 'puma', '6.4.2'
spec.add_dependency 'rack', '3.0.9'
spec.add_dependency 'rack-session', '2.0.0'
spec.add_dependency 'rackup', '2.1.0'
spec.add_dependency 'semantic_logger', '4.15.0'
spec.add_dependency 'sentry-ruby', '5.16.1'
spec.add_dependency 'sentry-sidekiq', '5.16.1'
spec.add_dependency 'sidekiq', '7.2.1'
spec.add_dependency 'slack-notifier', '2.4.0'
spec.add_dependency 'sqlite3', '1.7.2'
spec.add_dependency 'thor', '1.3.0'
spec.add_dependency 'thor-hollaback', '0.2.1'
spec.add_dependency 'uuidtools', '2.2.0'
spec.add_dependency "activerecord", "7.1.3"
spec.add_dependency "addressable", "2.8.6"
spec.add_dependency "anyway_config", "2.6.3"
spec.add_dependency "colorize", "1.1.0"
spec.add_dependency "dotenv", "2.8.1"
spec.add_dependency "down", "5.4.1"
spec.add_dependency "dry-files", "1.1.0"
spec.add_dependency "dry-monads", "1.6.0"
spec.add_dependency "http", "5.2.0"
spec.add_dependency "memo_wise", "1.8.0"
spec.add_dependency "oga", "3.4"
spec.add_dependency "parallel", "1.24.0"
spec.add_dependency "puma", "6.4.2"
spec.add_dependency "rack", "3.0.9"
spec.add_dependency "rack-session", "2.0.0"
spec.add_dependency "rackup", "2.1.0"
spec.add_dependency "redis", "5.0.8"
spec.add_dependency "semantic_logger", "4.15.0"
spec.add_dependency "sentry-ruby", "5.16.1"
spec.add_dependency "sentry-sidekiq", "5.16.1"
spec.add_dependency "sidekiq", "7.2.1"
spec.add_dependency "slack-notifier", "2.4.0"
spec.add_dependency "sqlite3", "1.7.2"
spec.add_dependency "thor", "1.3.0"
spec.add_dependency "thor-hollaback", "0.2.1"
spec.add_dependency "uuidtools", "2.2.0"
end
2 changes: 2 additions & 0 deletions spec/orchestrator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ def urls
end

RSpec.describe Miteru::Orchestrator do
include_context "with mocked logger"

subject(:orchestrator) { described_class.new }

before do
Expand Down

0 comments on commit 17498aa

Please sign in to comment.