# -*- coding: utf-8 -*- # == Author # Marvin Gülker (Quintus) # # == Modification author # Liothen # # == License # A named-pipe plugin for Cinch. # Copyright © 2012 Marvin Gülker # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # Plugin for inspecting links pasted into channels. require 'video_info' require 'mechanize' require 'action_view' require 'timeout' module Plugins class Snooper include Cinch::Plugin include Cinch::Helpers include ActionView::Helpers::DateHelper enable_acl(:nobody) # Default list of URL regexps to ignore. # DEFAULT_BLACKLIST = [/\.png$/i, /\.jpe?g$/i, /\.bmp$/i, /\.gif$/i, /\.pdf$/i].freeze set :help, <<-HELP http[s]://... I’ll fire a GET request at any link I encounter, parse the HTML meta tags, and paste the result back into the channel. HELP match %r{\b((https?:\/\/)?(([0-9a-zA-Z_!~*'().&=+$%-]+:)?[0-9a-zA-Z_!~*'().&=+$%-]+\@)?(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+\.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z]\.[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/[0-9a-zA-Z_!~*'().;?:\@&=+$,%#-]+)*\/?))}i, use_prefix: false, react_on: :channel def execute(msg, url) url = "http://#{url}" unless url=~/^https?:\/\// url = URI.encode(url) # Ignore items on blacklist # blacklist = DEFAULT_BLACKLIST.dup # blacklist.concat(config[:blacklist]) if config[:blacklist] # return if blacklist.any?{|entry| url =~ entry} # Log # debug "URL matched: #{url}" # Parse URI p = URI(url) # Disregaurd on blacklist return if Blacklist.urls.include? p.host # API key lookup VideoInfo.provider_api_keys = { youtube: Config.secrets[:google] } # Parse out specific websites if p.host == 'youtube.com' || p.host == 'www.youtube.com' || p.host == 'youtu.be' match_youtube(msg, url) elsif p.host == 'i.imgur.com' || p.host == 'imgur.com' match_imgur(msg, url) else match_other(msg,url) end rescue => e error "#{e.class.name}: #{e.message}" error "[404] #{msg.user} - #{url}" end private def match_youtube(msg, url) if Config.secrets[:google] video = VideoInfo.new(url) msg.reply "#{Format(:red, 'YouTube ')}∴ #{video.title} ( #{Format(:green, Time.at(video.duration).strftime("%H:%M:%S"))} )" else match_other(msg, url) end end def match_github(msg, url) # TODO parse github url end def match_imgur(msg, url) id = url.to_s.match(%r{(?:https?://i?\.?imgur.com/)(?:.*\/)?([A-Za-z0-9]+)(?:\.jpg|png|gif|gifv)?}i) return match_other(msg, url) unless id # Query Data data = JSON.parse( RestClient.get("https://api.imgur.com/3/image/#{id[1]}", { Authorization: "Client-ID #{Config.secrets[:imgur_id]}" }) ) return 'Unable to query imgur' unless defined?(data) i = Hashie::Mash.new(data) # SET Not Safe For Work if i.data.nsfw nsf = "[#{Format(:red, 'NSFW')}]" else nsf = "[#{Format(:green, 'SAFE')}]" end # Trigger reply message msg.reply("#{Format(:purple, 'IMGUR')} #{nsf} ∴ [#{Format(:yellow, i.data.type)}] #{i.data.width}x#{i.data.height} "\ "∴ Views: #{ i.data.views.to_s} ∴ #{i.data.title ? i.data.title[0..100] : 'No Title'} "\ "∴ Posted #{time_ago_in_words(Time.at(i.data.datetime))} ago") end def match_other(msg,url) begin html = Mechanize.start { |m| # Timeout longwinded pages m.max_history = 1 m.read_timeout = 4 m.max_file_buffer = 2_097_152 # Parse the HTML Timeout::timeout(12) { Nokogiri::HTML(m.get(url).content, nil, 'utf-8') } } # Reply Blocks if node = html.at_xpath("html/head/title") msg.reply("‡ #{node.text.lstrip.gsub(/\r|\n|\n\r/, ' ')[0..300]}") end if node = html.at_xpath('html/head/meta[@name="description"]') msg.reply("» #{node[:content].lines.first(3).join.gsub(/\r|\n|\n\r/, ' ')[0..300]}") end info "[200] #{msg.user} - #{url}" rescue Timeout::Error error "[408] #{msg.user} - #{url}" msg.reply 'URL was forced Timed out' rescue => e error e error "[404] #{msg.user} - #{url}" msg.safe_reply 'I am unable to load that URL' end end end end # AutoLoad Bot.config.plugins.plugins.push Plugins::Snooper