|
1 | 1 | # frozen_string_literal: true
|
2 | 2 |
|
3 | 3 | require 'erb'
|
| 4 | +require 'json' |
| 5 | +require 'shellwords' |
4 | 6 |
|
5 |
| -query = ARGV[0] |
6 |
| -# Regex is from: https://gist.github.com/gruber/8891611 |
7 |
| -urls = query.scan(%r{(?i)\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])|(?:(?<!@)[a-z0-9]+(?:[.\-][a-z0-9]+)*[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)\b/?(?!@)))}) |
8 |
| - .flatten # The result before is an embed array [[a], [b]]. |
9 |
| - .map { |url| url =~ %r{^https?://} ? url : "https://#{url}" } # Add https to raw domains. |
| 7 | +# Extends File object. |
| 8 | +class File |
| 9 | + # Remove single quote around file path from Alfred File Browser |
| 10 | + def self.strip_single_quote(filepath) |
| 11 | + /^'.*'$/.match?(filepath) ? filepath[1..-2] : filepath |
| 12 | + end |
10 | 13 |
|
11 |
| -if urls.any? |
12 |
| - urls.each { |url| system "open #{url}" } |
13 |
| -else |
| 14 | + # File types are limited by Google Image Search |
| 15 | + # The image must be in one of the following formats: |
| 16 | + # .jpg, .gif, .png, .bmp, .tif, or .webp. |
| 17 | + def self.image?(filepath) |
| 18 | + /^.*\.(jpe?g|gif|png|bmp|tif|webp)$/i.match?(filepath) |
| 19 | + end |
| 20 | +end |
| 21 | + |
| 22 | +def search_text(query) |
14 | 23 | lines = query.split("\n").reject(&:empty?)
|
15 | 24 | lines.each do |line|
|
16 | 25 | system "open 'https://google.com/search?q=#{ERB::Util.url_encode(line)}'"
|
17 | 26 | end
|
18 | 27 | end
|
| 28 | + |
| 29 | +def extract_urls(query) |
| 30 | + # Regex is from: https://gist.github.com/gruber/8891611 |
| 31 | + url_regex = %r{(?i)\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])|(?:(?<!@)[a-z0-9]+(?:[.\-][a-z0-9]+)*[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)\b/?(?!@)))} |
| 32 | + # The result is an embed array [[a], [b]], flatten is required. |
| 33 | + urls = query.scan(url_regex).flatten |
| 34 | + # Add https to raw domains. |
| 35 | + urls.map { |url| url =~ %r{^https?://} ? url : "https://#{url}" } |
| 36 | +end |
| 37 | + |
| 38 | +def open_urls(query) |
| 39 | + extract_urls(query).each { |url| system "open #{url}" } |
| 40 | +end |
| 41 | + |
| 42 | +def upload_image(filepath) |
| 43 | + push_notification('Uploading... Please wait for seconds', filepath) |
| 44 | + JSON.parse(`curl -X POST -F smfile=@#{filepath.shellescape} https://sm.ms/api/v2/upload`) |
| 45 | +rescue StandardError |
| 46 | + push_notification('JSON::ParseError', 'Please check the network or contact the developer.') |
| 47 | + nil |
| 48 | +end |
| 49 | + |
| 50 | +def extract_image_url(response) |
| 51 | + if response['code'] == 'success' |
| 52 | + response['data']['url'] |
| 53 | + elsif response['code'] == 'image_repeated' |
| 54 | + response['images'] |
| 55 | + else |
| 56 | + push_notification('https://sm.ms returns unexpected data', 'Please contact the developer.') |
| 57 | + nil |
| 58 | + end |
| 59 | +end |
| 60 | + |
| 61 | +def search_image(filepath) |
| 62 | + response = upload_image(filepath) |
| 63 | + return if response.nil? |
| 64 | + |
| 65 | + image_url = extract_image_url(response) |
| 66 | + return if image_url.nil? |
| 67 | + |
| 68 | + system "open https://images.google.com/searchbyimage?image_url=#{image_url}" |
| 69 | +end |
| 70 | + |
| 71 | +def push_notification(title, text) |
| 72 | + `osascript -e 'display notification "#{text}" with title "#{title}"'` |
| 73 | +end |
| 74 | + |
| 75 | +query = ARGV[0] |
| 76 | +filepath = File.strip_single_quote(query) |
| 77 | + |
| 78 | +if File.exist?(filepath) |
| 79 | + if File.image?(filepath) |
| 80 | + search_image(filepath) |
| 81 | + else |
| 82 | + push_notification('Please select an image', 'Supports jpg, gif, png, bmp, tif, or webp') |
| 83 | + end |
| 84 | +elsif extract_urls(query).any? |
| 85 | + open_urls(query) |
| 86 | +else |
| 87 | + search_text(query) |
| 88 | +end |
0 commit comments