yapra 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.
- data/History.txt +4 -0
- data/LICENCE +22 -0
- data/License.txt +22 -0
- data/Manifest.txt +103 -0
- data/PostInstall.txt +7 -0
- data/README.txt +66 -0
- data/Rakefile +13 -0
- data/bin/yapra +52 -0
- data/config/hoe.rb +75 -0
- data/config/requirements.rb +15 -0
- data/legacy_plugins/Download/nicovideo.rb +45 -0
- data/legacy_plugins/Feed/custom_feed.rb +87 -0
- data/legacy_plugins/Feed/google_calendar.rb +51 -0
- data/legacy_plugins/Feed/google_search_history.rb +45 -0
- data/legacy_plugins/Feed/hatena_graph.rb +37 -0
- data/legacy_plugins/Feed/lirs.rb +36 -0
- data/legacy_plugins/Filter/Translations/yahoo.rb +40 -0
- data/legacy_plugins/Filter/apply_text_html.rb +26 -0
- data/legacy_plugins/Filter/average.rb +6 -0
- data/legacy_plugins/Filter/deduped.rb +51 -0
- data/legacy_plugins/Filter/find_num.rb +8 -0
- data/legacy_plugins/Filter/find_regex.rb +9 -0
- data/legacy_plugins/Filter/fresh.rb +9 -0
- data/legacy_plugins/Filter/get_html.rb +11 -0
- data/legacy_plugins/Filter/grep.rb +16 -0
- data/legacy_plugins/Filter/invert.rb +14 -0
- data/legacy_plugins/Filter/sort.rb +10 -0
- data/legacy_plugins/Filter/subs.rb +6 -0
- data/legacy_plugins/Filter/to_integer.rb +4 -0
- data/legacy_plugins/Publish/delicious.rb +91 -0
- data/legacy_plugins/Publish/google_calendar.rb +58 -0
- data/legacy_plugins/Publish/hatena_bookmark.rb +47 -0
- data/legacy_plugins/Publish/hatena_diary_writer.rb +53 -0
- data/legacy_plugins/Publish/hatena_graph.rb +39 -0
- data/legacy_plugins/Publish/lingr.rb +110 -0
- data/legacy_plugins/Publish/mixi_diary_writer.rb +104 -0
- data/legacy_plugins/Publish/scuttle.rb +92 -0
- data/legacy_plugins/Publish/twitter.rb +35 -0
- data/legacy_plugins/RSS/load.rb +38 -0
- data/legacy_plugins/RSS/save.rb +41 -0
- data/legacy_plugins/Yaml/load.rb +5 -0
- data/legacy_plugins/Yaml/save.rb +9 -0
- data/legacy_plugins/argv.rb +5 -0
- data/legacy_plugins/concat.rb +18 -0
- data/legacy_plugins/const_list.rb +15 -0
- data/legacy_plugins/first.rb +11 -0
- data/legacy_plugins/head.rb +14 -0
- data/legacy_plugins/load_path.rb +21 -0
- data/legacy_plugins/plagger.rb +94 -0
- data/legacy_plugins/plugin_from_uri.rb +31 -0
- data/legacy_plugins/pluginbase.rb +4 -0
- data/legacy_plugins/print.rb +15 -0
- data/legacy_plugins/reverse.rb +10 -0
- data/legacy_plugins/send_msg.rb +18 -0
- data/legacy_plugins/stdin.rb +6 -0
- data/legacy_plugins/stdout.rb +6 -0
- data/lib/yapra/config.rb +103 -0
- data/lib/yapra/inflector.rb +55 -0
- data/lib/yapra/legacy_plugin/advance_mode_registry.rb +38 -0
- data/lib/yapra/legacy_plugin/base.rb +26 -0
- data/lib/yapra/legacy_plugin/compatible_mode_registry.rb +34 -0
- data/lib/yapra/legacy_plugin/registry_factory.rb +21 -0
- data/lib/yapra/legacy_plugin.rb +5 -0
- data/lib/yapra/pipeline.rb +74 -0
- data/lib/yapra/plugin/base.rb +14 -0
- data/lib/yapra/plugin/context_aware.rb +14 -0
- data/lib/yapra/plugin/erb_applier.rb +15 -0
- data/lib/yapra/plugin/feed_item_operator.rb +21 -0
- data/lib/yapra/plugin/mechanize_base.rb +26 -0
- data/lib/yapra/plugin.rb +5 -0
- data/lib/yapra/runtime.rb +36 -0
- data/lib/yapra/version.rb +9 -0
- data/lib/yapra.rb +44 -0
- data/lib-plugins/yapra/plugin/config/agent.rb +34 -0
- data/lib-plugins/yapra/plugin/config/basic_auth.rb +19 -0
- data/lib-plugins/yapra/plugin/config/web_post.rb +21 -0
- data/lib-plugins/yapra/plugin/feed/custom.rb +41 -0
- data/lib-plugins/yapra/plugin/feed/load.rb +29 -0
- data/lib-plugins/yapra/plugin/filter/entry_full_text.rb +59 -0
- data/lib-plugins/yapra/plugin/publish/file_download.rb +109 -0
- data/lib-plugins/yapra/plugin/publish/gmail.rb +27 -0
- data/lib-plugins/yapra/plugin/publish/imap.rb +82 -0
- data/lib-plugins/yapra/plugin/test/append_entry.rb +25 -0
- data/plugins/Filter/deduped.rb +57 -0
- data/plugins/Filter/sort.rb +28 -0
- data/plugins/Filter/subs.rb +16 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/yapra_spec.rb +11 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- data/website/index.html +115 -0
- data/website/index.txt +57 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.html.erb +48 -0
- metadata +170 -0
data/lib/yapra/config.rb
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# = Config Examples
|
|
2
|
+
#
|
|
3
|
+
# == Format 1: Pragger like.
|
|
4
|
+
# A simplest. You can run one pipeline without global config.
|
|
5
|
+
#
|
|
6
|
+
# - module: Module:name
|
|
7
|
+
# config:
|
|
8
|
+
# a: 3
|
|
9
|
+
# - module: Module:name2
|
|
10
|
+
# config:
|
|
11
|
+
# a: b
|
|
12
|
+
# - module: Module:name3
|
|
13
|
+
# config:
|
|
14
|
+
# a: 88
|
|
15
|
+
#
|
|
16
|
+
# == Format 2: Python habu like.
|
|
17
|
+
# You can run a lot of pipelines with global config.
|
|
18
|
+
#
|
|
19
|
+
# global:
|
|
20
|
+
# log:
|
|
21
|
+
# out: stderr
|
|
22
|
+
# level: warn
|
|
23
|
+
#
|
|
24
|
+
# pipeline:
|
|
25
|
+
# pipeline1:
|
|
26
|
+
# - module: Module:name
|
|
27
|
+
# config:
|
|
28
|
+
# a: 3
|
|
29
|
+
# - module: Module:name2
|
|
30
|
+
# config:
|
|
31
|
+
# a: b
|
|
32
|
+
#
|
|
33
|
+
# pipeline2:
|
|
34
|
+
# - module: Module:name
|
|
35
|
+
# config:
|
|
36
|
+
# a: 3
|
|
37
|
+
# - module: Module:name2
|
|
38
|
+
# config:
|
|
39
|
+
# a: b
|
|
40
|
+
#
|
|
41
|
+
# == Format 3: Mixed type.
|
|
42
|
+
# You can run sigle pipeline with global config.
|
|
43
|
+
#
|
|
44
|
+
# global:
|
|
45
|
+
# log:
|
|
46
|
+
# out: stderr
|
|
47
|
+
# level: warn
|
|
48
|
+
#
|
|
49
|
+
# pipeline:
|
|
50
|
+
# - module: Module:name
|
|
51
|
+
# config:
|
|
52
|
+
# a: 3
|
|
53
|
+
# - module: Module:name2
|
|
54
|
+
# config:
|
|
55
|
+
# a: b
|
|
56
|
+
#
|
|
57
|
+
require 'logger'
|
|
58
|
+
require 'yapra'
|
|
59
|
+
|
|
60
|
+
class Yapra::Config
|
|
61
|
+
attr_reader :env
|
|
62
|
+
attr_reader :pipeline_commands
|
|
63
|
+
|
|
64
|
+
def initialize config={}
|
|
65
|
+
if config.kind_of?(Hash)
|
|
66
|
+
@env = config['global'] || {}
|
|
67
|
+
if config['pipeline']
|
|
68
|
+
if config['pipeline'].kind_of?(Hash)
|
|
69
|
+
@pipeline_commands = config['pipeline']
|
|
70
|
+
elsif config['pipeline'].kind_of?(Array)
|
|
71
|
+
@pipeline_commands = { 'default' => config['pipeline'] }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
raise 'config["global"]["pipeline"] is invalid!' unless @pipeline_commands
|
|
75
|
+
elsif config.kind_of?(Array)
|
|
76
|
+
@env = {}
|
|
77
|
+
@pipeline_commands = { 'default' => config }
|
|
78
|
+
else
|
|
79
|
+
raise 'config file is invalid!'
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def create_logger
|
|
84
|
+
logger = nil
|
|
85
|
+
if env['log'] && env['log']['out']
|
|
86
|
+
if env['log']['out'].index('file://')
|
|
87
|
+
logger = Logger.new(URI.parse(env['log']['out']).path)
|
|
88
|
+
else
|
|
89
|
+
logger = Logger.new(Yapra::Inflector.constantize(env['log']['out'].upcase))
|
|
90
|
+
end
|
|
91
|
+
else
|
|
92
|
+
logger = Logger.new(STDOUT)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
if env['log'] && env['log']['level']
|
|
96
|
+
logger.level = Yapra::Inflector.constantize("Logger::#{env['log']['level'].upcase}")
|
|
97
|
+
else
|
|
98
|
+
logger.level = Logger::WARN
|
|
99
|
+
end
|
|
100
|
+
logger
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# original from ActiveSupport-2.0.2
|
|
2
|
+
# MIT Licence
|
|
3
|
+
require 'yapra'
|
|
4
|
+
|
|
5
|
+
module Yapra::Inflector
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
# By default, camelize converts strings to UpperCamelCase. If the argument to camelize
|
|
9
|
+
# is set to ":lower" then camelize produces lowerCamelCase.
|
|
10
|
+
#
|
|
11
|
+
# camelize will also convert '/' to '::' which is useful for converting paths to namespaces
|
|
12
|
+
#
|
|
13
|
+
# Examples
|
|
14
|
+
# "active_record".camelize #=> "ActiveRecord"
|
|
15
|
+
# "active_record".camelize(:lower) #=> "activeRecord"
|
|
16
|
+
# "active_record/errors".camelize #=> "ActiveRecord::Errors"
|
|
17
|
+
# "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
|
|
18
|
+
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
|
19
|
+
if first_letter_in_uppercase
|
|
20
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
|
21
|
+
else
|
|
22
|
+
lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The reverse of +camelize+. Makes an underscored form from the expression in the string.
|
|
27
|
+
#
|
|
28
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
|
29
|
+
#
|
|
30
|
+
# Examples
|
|
31
|
+
# "ActiveRecord".underscore #=> "active_record"
|
|
32
|
+
# "ActiveRecord::Errors".underscore #=> active_record/errors
|
|
33
|
+
def underscore(camel_cased_word)
|
|
34
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
|
35
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
36
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
37
|
+
tr("-", "_").
|
|
38
|
+
downcase
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Constantize tries to find a declared constant with the name specified
|
|
42
|
+
# in the string. It raises a NameError when the name is not in CamelCase
|
|
43
|
+
# or is not initialized.
|
|
44
|
+
#
|
|
45
|
+
# Examples
|
|
46
|
+
# "Module".constantize #=> Module
|
|
47
|
+
# "Class".constantize #=> Class
|
|
48
|
+
def constantize(camel_cased_word)
|
|
49
|
+
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
|
|
50
|
+
raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
Object.module_eval("::#{$1}", __FILE__, __LINE__)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'yapra/legacy_plugin'
|
|
2
|
+
require 'yapra/inflector'
|
|
3
|
+
|
|
4
|
+
module Yapra::LegacyPlugin
|
|
5
|
+
|
|
6
|
+
class AdvanceModeRegistry
|
|
7
|
+
attr_accessor :legacy_plugins
|
|
8
|
+
attr_accessor :plugin_paths
|
|
9
|
+
attr_accessor :pipeline
|
|
10
|
+
|
|
11
|
+
def initialize paths, pipeline
|
|
12
|
+
self.legacy_plugins = {}
|
|
13
|
+
self.plugin_paths = paths.reverse
|
|
14
|
+
self.pipeline = pipeline
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def logger
|
|
18
|
+
Yapra::Runtime.logger
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def get module_name
|
|
22
|
+
plugin = legacy_plugins[module_name]
|
|
23
|
+
unless plugin
|
|
24
|
+
plugin_paths.each do |folder|
|
|
25
|
+
file = folder + (module_name.gsub('::', '/') + '.rb')
|
|
26
|
+
if file.file?()
|
|
27
|
+
plugin = Yapra::LegacyPlugin::Base.new(pipeline, file)
|
|
28
|
+
legacy_plugins[ module_name ] = plugin
|
|
29
|
+
logger.debug "#{module_name} is loaded from #{file}"
|
|
30
|
+
break
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
raise "#{module_name} is not registered." unless plugin
|
|
35
|
+
plugin
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# require 'pathname'
|
|
2
|
+
require 'yapra/legacy_plugin'
|
|
3
|
+
|
|
4
|
+
class Yapra::LegacyPlugin::Base
|
|
5
|
+
attr_reader :source
|
|
6
|
+
attr_reader :_yapra_run_method
|
|
7
|
+
attr_reader :_yapra_pipeline
|
|
8
|
+
|
|
9
|
+
def initialize(pipeline, plugin_path)
|
|
10
|
+
@_yapra_pipeline = pipeline
|
|
11
|
+
@_yapra_run_method = File.basename(plugin_path, '.*')
|
|
12
|
+
instance_eval( @source = File.read(plugin_path).toutf8, plugin_path, 1)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def logger
|
|
16
|
+
Yapra::Runtime.logger
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def eval_pragger(command_array, data)
|
|
20
|
+
pipeline.execute_plugins(command_array, data)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def _yapra_run_as_legacy_plugin(config, data)
|
|
24
|
+
self.__send__(self._yapra_run_method, config, data)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
require 'yapra/legacy_plugin'
|
|
3
|
+
|
|
4
|
+
module Yapra::LegacyPlugin
|
|
5
|
+
class CompatibleModeRegistry
|
|
6
|
+
attr_accessor :legacy_plugins
|
|
7
|
+
|
|
8
|
+
def initialize paths, pipeline
|
|
9
|
+
self.legacy_plugins = {}
|
|
10
|
+
|
|
11
|
+
paths.each do |folder|
|
|
12
|
+
Pathname.glob(folder + "**/*.rb").sort.each do |file|
|
|
13
|
+
module_name = file.relative_path_from(folder).to_s.gsub("/","::")[0..-4]
|
|
14
|
+
begin
|
|
15
|
+
legacy_plugins[ module_name ] = Yapra::LegacyPlugin::Base.new(pipeline, file)
|
|
16
|
+
logger.debug "#{module_name} is loaded from #{file}"
|
|
17
|
+
rescue LoadError => ex
|
|
18
|
+
logger.warn "#{module_name} can't load, because: #{ex.message}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def logger
|
|
25
|
+
Yapra::Runtime.logger
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get module_name
|
|
29
|
+
plugin = legacy_plugins[module_name]
|
|
30
|
+
raise "#{module_name} is not registered." unless plugin
|
|
31
|
+
plugin
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'yapra/legacy_plugin'
|
|
2
|
+
require 'yapra/inflector'
|
|
3
|
+
|
|
4
|
+
class Yapra::LegacyPlugin::RegistryFactory
|
|
5
|
+
attr_reader :plugin_paths
|
|
6
|
+
attr_reader :registry_class
|
|
7
|
+
|
|
8
|
+
def initialize plugin_paths, mode = 'compatible'
|
|
9
|
+
registry_name = "Yapra::LegacyPlugin::#{Yapra::Inflector.camelize(mode)}ModeRegistry"
|
|
10
|
+
@registry_class = Yapra.load_class_constant(registry_name)
|
|
11
|
+
raise "'#{mode}' mode is not supported." unless @registry_class
|
|
12
|
+
|
|
13
|
+
@plugin_paths = plugin_paths
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create pipeline
|
|
17
|
+
registry = registry_class.new(plugin_paths, pipeline)
|
|
18
|
+
pipeline.legacy_plugin_registry = registry
|
|
19
|
+
registry
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'yapra'
|
|
2
|
+
require 'yapra/inflector'
|
|
3
|
+
require 'yapra/legacy_plugin/base'
|
|
4
|
+
|
|
5
|
+
class Yapra::Pipeline
|
|
6
|
+
attr_reader :yapra, :context
|
|
7
|
+
attr_accessor :legacy_plugin_registry
|
|
8
|
+
|
|
9
|
+
UPPER_CASE = /[A-Z]/
|
|
10
|
+
|
|
11
|
+
def initialize yapra, pipeline_name
|
|
12
|
+
@yapra = yapra
|
|
13
|
+
@context = { 'pipeline_name' => pipeline_name }
|
|
14
|
+
|
|
15
|
+
@module_name_prefix = construct_module_name_prefix yapra.env
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def logger
|
|
19
|
+
Yapra::Runtime.logger
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def run pipeline_command, data=[]
|
|
23
|
+
pipeline_command.inject(data) do |data, command|
|
|
24
|
+
execute_plugin(command, data.clone)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def execute_plugin command, data
|
|
29
|
+
self.logger.info("exec plugin #{command["module"]}")
|
|
30
|
+
if class_based_plugin?(command['module'])
|
|
31
|
+
run_class_based_plugin command, data
|
|
32
|
+
else
|
|
33
|
+
run_legacy_plugin command, data
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
protected
|
|
38
|
+
def class_based_plugin? command_name
|
|
39
|
+
UPPER_CASE =~ command_name.split('::').last[0, 1]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def run_legacy_plugin command, data
|
|
43
|
+
self.logger.debug("evaluate plugin as legacy")
|
|
44
|
+
legacy_plugin_registry.get(command['module'])._yapra_run_as_legacy_plugin(command['config'], data)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def run_class_based_plugin command, data
|
|
48
|
+
self.logger.debug("evaluate plugin as class based")
|
|
49
|
+
plugin_class = nil
|
|
50
|
+
@module_name_prefix.each do |prefix|
|
|
51
|
+
yapra_module_name = "#{prefix}#{command['module']}"
|
|
52
|
+
plugin_class = Yapra.load_class_constant(yapra_module_name)
|
|
53
|
+
break if plugin_class
|
|
54
|
+
end
|
|
55
|
+
raise LoadError unless plugin_class
|
|
56
|
+
plugin = plugin_class.new
|
|
57
|
+
plugin.yapra = yapra if plugin.respond_to?('yapra=')
|
|
58
|
+
plugin.pipeline = self if plugin.respond_to?('pipeline=')
|
|
59
|
+
plugin.plugin_config = command['config'] if plugin.respond_to?('plugin_config=')
|
|
60
|
+
plugin.run(data)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def construct_module_name_prefix env
|
|
64
|
+
module_name_prefix = [ 'Yapra::Plugin::', '' ]
|
|
65
|
+
if env['module_name_prefix']
|
|
66
|
+
if env['module_name_prefix'].kind_of?(Array)
|
|
67
|
+
module_name_prefix = env['module_name_prefix']
|
|
68
|
+
else
|
|
69
|
+
module_name_prefix = [ env['module_name_prefix'] ]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
module_name_prefix
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'yapra/plugin'
|
|
2
|
+
require 'yapra/plugin/context_aware'
|
|
3
|
+
require 'yapra/plugin/erb_applier'
|
|
4
|
+
require 'yapra/plugin/feed_item_operator'
|
|
5
|
+
|
|
6
|
+
class Yapra::Plugin::Base
|
|
7
|
+
include Yapra::Plugin::ContextAware
|
|
8
|
+
include Yapra::Plugin::FeedItemOperator
|
|
9
|
+
include Yapra::Plugin::ErbApplier
|
|
10
|
+
|
|
11
|
+
def logger
|
|
12
|
+
Yapra::Runtime.logger
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'yapra/plugin'
|
|
2
|
+
|
|
3
|
+
module Yapra::Plugin::ContextAware
|
|
4
|
+
attr_accessor :yapra, :pipeline, :plugin_config
|
|
5
|
+
|
|
6
|
+
def config
|
|
7
|
+
@config ||= nil
|
|
8
|
+
unless @config
|
|
9
|
+
@config = {}.update(yapra.env).update(pipeline.context)
|
|
10
|
+
@config.update(plugin_config) if plugin_config
|
|
11
|
+
end
|
|
12
|
+
@config
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'yapra/plugin'
|
|
2
|
+
require 'erb'
|
|
3
|
+
require 'uri'
|
|
4
|
+
|
|
5
|
+
module Yapra::Plugin::ErbApplier
|
|
6
|
+
def apply_template template, apply_binding=binding
|
|
7
|
+
if template.index('file://') == 0
|
|
8
|
+
path = URI.parse(template).path
|
|
9
|
+
open(path) do |io|
|
|
10
|
+
template = io.read
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
ERB.new(template).result(apply_binding)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'yapra/plugin'
|
|
2
|
+
|
|
3
|
+
module Yapra::Plugin::FeedItemOperator
|
|
4
|
+
LOCAL_VAL_RE = /[a-z_][0-9A-Za-z_]/
|
|
5
|
+
|
|
6
|
+
def set_attribute_to item, k, value
|
|
7
|
+
raise NameError unless LOCAL_VAL_RE =~ k
|
|
8
|
+
unless item.respond_to?("#{k}=")
|
|
9
|
+
item.instance_eval %Q{
|
|
10
|
+
def #{k}
|
|
11
|
+
@#{k}
|
|
12
|
+
end
|
|
13
|
+
def #{k}= v
|
|
14
|
+
@#{k} = v
|
|
15
|
+
end
|
|
16
|
+
}, __FILE__, __LINE__
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
item.__send__("#{k}=", value)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'mechanize'
|
|
2
|
+
require 'kconv'
|
|
3
|
+
require 'yapra/plugin/base'
|
|
4
|
+
|
|
5
|
+
class Yapra::Plugin::MechanizeBase < Yapra::Plugin::Base
|
|
6
|
+
def agent
|
|
7
|
+
pipeline.context['mechanize_agent'] ||= WWW::Mechanize.new
|
|
8
|
+
pipeline.context['mechanize_agent']
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def extract_attribute_from element, item
|
|
12
|
+
if config['extract_xpath']
|
|
13
|
+
config['extract_xpath'].each do |k, v|
|
|
14
|
+
value = element.search(v).to_html.toutf8
|
|
15
|
+
set_attribute_to item, k, value
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
if config['apply_template_after_extracted']
|
|
20
|
+
config['apply_template_after_extracted'].each do |k, template|
|
|
21
|
+
value = apply_template template, binding
|
|
22
|
+
set_attribute_to item, k, value
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/yapra/plugin.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
require 'yapra'
|
|
2
|
+
require 'yapra/pipeline'
|
|
3
|
+
require 'yapra/config'
|
|
4
|
+
require 'yapra/inflector'
|
|
5
|
+
|
|
6
|
+
class Yapra::Runtime
|
|
7
|
+
attr_reader :env
|
|
8
|
+
attr_reader :legacy_plugin_registry_factory
|
|
9
|
+
|
|
10
|
+
def initialize env={}, legacy_plugin_registry_factory=nil
|
|
11
|
+
@env = env
|
|
12
|
+
|
|
13
|
+
@legacy_plugin_registry_factory = legacy_plugin_registry_factory
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def execute pipeline_commands
|
|
17
|
+
pipeline_commands.each do |k, v|
|
|
18
|
+
execute_pipeline k, v, []
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def execute_pipeline pipeline_name, command_array, data=[]
|
|
23
|
+
self.class.logger.info("# pipeline '#{pipeline_name}' is started...")
|
|
24
|
+
pipeline = Yapra::Pipeline.new(self, pipeline_name)
|
|
25
|
+
legacy_plugin_registory = legacy_plugin_registry_factory.create(pipeline) if legacy_plugin_registry_factory
|
|
26
|
+
pipeline.run(command_array, data)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.logger
|
|
30
|
+
@@logger
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.logger=logger
|
|
34
|
+
@@logger = logger
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/yapra.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2008 fraction.jp. Yuanying, Some rights reserved.
|
|
3
|
+
# Original from 2008-06-12 http://pragger.ikejisoft.com/
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
# a copy of this software and associated documentation files (the
|
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
# the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be
|
|
14
|
+
# included in all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
#++
|
|
24
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
|
25
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
|
26
|
+
|
|
27
|
+
module Yapra
|
|
28
|
+
extend self
|
|
29
|
+
|
|
30
|
+
# TODO create util class, and move this method.
|
|
31
|
+
def load_class_constant module_name
|
|
32
|
+
require Yapra::Inflector.underscore(module_name)
|
|
33
|
+
Yapra::Inflector.constantize(module_name)
|
|
34
|
+
rescue LoadError
|
|
35
|
+
nil
|
|
36
|
+
rescue NameError
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
require 'rss/1.0'
|
|
41
|
+
require 'rss/2.0'
|
|
42
|
+
require 'rss/dublincore'
|
|
43
|
+
require 'rss/maker'
|
|
44
|
+
require 'rubygems'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
## Yapra::Config::Agent -- Yuanying
|
|
2
|
+
##
|
|
3
|
+
## add WWW::Mechanize agent to context.
|
|
4
|
+
##
|
|
5
|
+
## - module: Config::Agent
|
|
6
|
+
## config:
|
|
7
|
+
## user_agent_alias: Windows IE 6
|
|
8
|
+
## proxy:
|
|
9
|
+
## addr: localhost
|
|
10
|
+
## port: 8080
|
|
11
|
+
## user: username
|
|
12
|
+
## password: password
|
|
13
|
+
##
|
|
14
|
+
require 'yapra/plugin/mechanize_base'
|
|
15
|
+
|
|
16
|
+
module Yapra::Plugin::Config
|
|
17
|
+
class Agent < Yapra::Plugin::MechanizeBase
|
|
18
|
+
|
|
19
|
+
def run(data)
|
|
20
|
+
|
|
21
|
+
agent.user_agent_alias = config['user_agent_alias'] || 'Windows IE 6'
|
|
22
|
+
if config['proxy']
|
|
23
|
+
agent.set_proxy(
|
|
24
|
+
config['proxy']['addr'],
|
|
25
|
+
config['proxy']['port'],
|
|
26
|
+
config['proxy']['user'],
|
|
27
|
+
config['proxy']['password']
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
return data
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## Config::BasicAuth -- Yuanying
|
|
2
|
+
##
|
|
3
|
+
## post to web page with WWW::Mechanize agent.
|
|
4
|
+
##
|
|
5
|
+
## - module: Config::BasicAuth
|
|
6
|
+
## config:
|
|
7
|
+
## user: yuanying
|
|
8
|
+
## password: password-dayo
|
|
9
|
+
##
|
|
10
|
+
require 'yapra/plugin/mechanize_base'
|
|
11
|
+
|
|
12
|
+
module Yapra::Plugin::Config
|
|
13
|
+
class BasicAuth < Yapra::Plugin::MechanizeBase
|
|
14
|
+
def run(data)
|
|
15
|
+
agent.basic_auth(config['user'], config['password'])
|
|
16
|
+
data
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Config::WebPost -- Yuanying
|
|
2
|
+
##
|
|
3
|
+
## post to web page with WWW::Mechanize agent.
|
|
4
|
+
##
|
|
5
|
+
## - module: Config::WebPost
|
|
6
|
+
## config:
|
|
7
|
+
## url: http://www.pixiv.net/index.php
|
|
8
|
+
## params:
|
|
9
|
+
## pixiv_id: yuanying
|
|
10
|
+
## pass: password-dayo
|
|
11
|
+
##
|
|
12
|
+
require 'yapra/plugin/mechanize_base'
|
|
13
|
+
|
|
14
|
+
module Yapra::Plugin::Config
|
|
15
|
+
class WebPost < Yapra::Plugin::MechanizeBase
|
|
16
|
+
def run(data)
|
|
17
|
+
agent.post(config['url'], config['params'])
|
|
18
|
+
data
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
## - module: Feed::Custom
|
|
2
|
+
## config:
|
|
3
|
+
## url: 'http://www.fraction.jp/'
|
|
4
|
+
## extract_xpath:
|
|
5
|
+
## capture: '//div'
|
|
6
|
+
## split: '//div[@class="test"]'
|
|
7
|
+
## description: '//div'
|
|
8
|
+
## link: '//li[2]'
|
|
9
|
+
## title: '//p'
|
|
10
|
+
## apply_template_after_extracted:
|
|
11
|
+
## content_encoded: '<div><%= title %></div>'
|
|
12
|
+
##
|
|
13
|
+
require 'yapra/plugin/mechanize_base'
|
|
14
|
+
|
|
15
|
+
module Yapra::Plugin::Feed
|
|
16
|
+
class Custom < Yapra::Plugin::MechanizeBase
|
|
17
|
+
def run(data)
|
|
18
|
+
page = agent.get(config['url'])
|
|
19
|
+
root = page.root
|
|
20
|
+
|
|
21
|
+
xconfig = config['extract_xpath']
|
|
22
|
+
|
|
23
|
+
if xconfig['capture']
|
|
24
|
+
root = root.at(xconfig['capture'])
|
|
25
|
+
end
|
|
26
|
+
split = xconfig['split']
|
|
27
|
+
xconfig.delete('capture')
|
|
28
|
+
xconfig.delete('split')
|
|
29
|
+
|
|
30
|
+
root.search(split).each do |element|
|
|
31
|
+
item = RSS::RDF::Item.new
|
|
32
|
+
|
|
33
|
+
extract_attribute_from element, item
|
|
34
|
+
|
|
35
|
+
data << item
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
data
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|