automatic 14.12.2 → 26.08

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.
Files changed (172) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +635 -83
  3. data/VERSION +1 -1
  4. data/automatic.gemspec +109 -248
  5. data/bin/automatic +20 -139
  6. data/config/feed2console.yml +10 -4
  7. data/config/feed2markdown.yml +41 -0
  8. data/doc/AI_TUTORIAL.md +518 -0
  9. data/doc/BASIC_DESIGN.md +516 -0
  10. data/doc/COPYING.LESSER +165 -0
  11. data/doc/DEPLOYMENT.md +824 -0
  12. data/doc/LICENSE.md +14 -0
  13. data/doc/PLUGINS.md +1875 -0
  14. data/doc/PLUGIN_DEVELOPMENT.md +86 -0
  15. data/doc/POLICY.md +857 -0
  16. data/doc/QUICKSTART.md +256 -0
  17. data/doc/RELEASING.md +381 -0
  18. data/doc/REQUIREMENTS.md +526 -0
  19. data/doc/VERSIONS +208 -0
  20. data/lib/automatic/cli.rb +248 -0
  21. data/lib/automatic/environment.rb +31 -5
  22. data/lib/automatic/feed_maker.rb +10 -9
  23. data/lib/automatic/feed_parser.rb +51 -35
  24. data/lib/automatic/http.rb +107 -0
  25. data/lib/automatic/log.rb +49 -18
  26. data/lib/automatic/opml.rb +3 -1
  27. data/lib/automatic/pipeline.rb +63 -32
  28. data/lib/automatic/recipe.rb +56 -17
  29. data/lib/automatic/version.rb +14 -1
  30. data/lib/automatic.rb +78 -20
  31. data/plugins/custom_feed/svn_log.rb +73 -32
  32. data/plugins/custom_feed/web.rb +348 -0
  33. data/plugins/filter/absolute_uri.rb +43 -27
  34. data/plugins/filter/accept.rb +38 -45
  35. data/plugins/filter/claude.rb +217 -0
  36. data/plugins/filter/clear.rb +12 -8
  37. data/plugins/filter/description_link.rb +49 -51
  38. data/plugins/filter/full_feed.rb +158 -52
  39. data/plugins/filter/gemini.rb +216 -0
  40. data/plugins/filter/github_feed.rb +38 -26
  41. data/plugins/filter/ignore.rb +33 -44
  42. data/plugins/filter/image.rb +36 -25
  43. data/plugins/filter/image_source.rb +58 -52
  44. data/plugins/filter/join.rb +107 -0
  45. data/plugins/filter/one.rb +19 -26
  46. data/plugins/filter/open_ai.rb +198 -0
  47. data/plugins/filter/rand.rb +16 -17
  48. data/plugins/filter/sakura_ai.rb +205 -0
  49. data/plugins/filter/sanitize.rb +29 -34
  50. data/plugins/filter/sort.rb +20 -27
  51. data/plugins/filter/tumblr_resize.rb +31 -23
  52. data/plugins/notify/ikachan.rb +86 -48
  53. data/plugins/provide/fluentd.rb +43 -24
  54. data/plugins/publish/amazon_s3.rb +73 -40
  55. data/plugins/publish/console.rb +19 -16
  56. data/plugins/publish/console_link.rb +20 -17
  57. data/plugins/publish/eject.rb +48 -26
  58. data/plugins/publish/fluentd.rb +50 -30
  59. data/plugins/publish/hatena_bookmark.rb +88 -71
  60. data/plugins/publish/instapaper.rb +69 -59
  61. data/plugins/publish/markdown.rb +278 -0
  62. data/plugins/publish/memcached.rb +35 -29
  63. data/plugins/store/database.rb +50 -48
  64. data/plugins/store/digest.rb +212 -0
  65. data/plugins/store/file.rb +99 -68
  66. data/plugins/store/full_text.rb +32 -25
  67. data/plugins/store/permalink.rb +18 -22
  68. data/plugins/subscription/feed.rb +34 -21
  69. data/plugins/subscription/link.rb +31 -32
  70. data/plugins/subscription/text.rb +32 -46
  71. data/plugins/subscription/tumblr.rb +55 -44
  72. data/plugins/subscription/xml.rb +40 -36
  73. metadata +108 -321
  74. data/Gemfile +0 -38
  75. data/Rakefile +0 -59
  76. data/doc/ChangeLog +0 -303
  77. data/doc/PLUGINS +0 -750
  78. data/doc/PLUGINS.ja +0 -753
  79. data/doc/README +0 -511
  80. data/doc/README.ja +0 -519
  81. data/plugins/filter/google_news.rb +0 -50
  82. data/plugins/publish/google_calendar.rb +0 -84
  83. data/plugins/publish/hipchat.rb +0 -46
  84. data/plugins/publish/pocket.rb +0 -45
  85. data/plugins/publish/twitter.rb +0 -58
  86. data/plugins/subscription/chan_toru.rb +0 -57
  87. data/plugins/subscription/g_guide.rb +0 -57
  88. data/plugins/subscription/pocket.rb +0 -51
  89. data/plugins/subscription/twitter.rb +0 -69
  90. data/plugins/subscription/twitter_search.rb +0 -50
  91. data/plugins/subscription/weather.rb +0 -33
  92. data/script/build +0 -84
  93. data/spec/fixtures/sampleFeeds.tsv +0 -1
  94. data/spec/fixtures/sampleFeeds2.tsv +0 -2
  95. data/spec/fixtures/sampleRecipe.yml +0 -24
  96. data/spec/lib/automatic/log_spec.rb +0 -32
  97. data/spec/lib/automatic/pipeline_spec.rb +0 -68
  98. data/spec/lib/automatic/recipe_spec.rb +0 -40
  99. data/spec/lib/automatic_spec.rb +0 -99
  100. data/spec/plugins/custom_feed/svn_log_spec.rb +0 -31
  101. data/spec/plugins/filter/absolute_uri_spec.rb +0 -61
  102. data/spec/plugins/filter/accept_spec.rb +0 -331
  103. data/spec/plugins/filter/clear_spec.rb +0 -49
  104. data/spec/plugins/filter/description_link_spec.rb +0 -138
  105. data/spec/plugins/filter/full_feed_spec.rb +0 -129
  106. data/spec/plugins/filter/github_feed_spec.rb +0 -55
  107. data/spec/plugins/filter/google_news_spec.rb +0 -69
  108. data/spec/plugins/filter/ignore_spec.rb +0 -328
  109. data/spec/plugins/filter/image_source_spec.rb +0 -89
  110. data/spec/plugins/filter/image_spec.rb +0 -65
  111. data/spec/plugins/filter/one_spec.rb +0 -71
  112. data/spec/plugins/filter/rand_spec.rb +0 -52
  113. data/spec/plugins/filter/sanitize_spec.rb +0 -153
  114. data/spec/plugins/filter/sort_spec.rb +0 -189
  115. data/spec/plugins/filter/tumblr_resize_spec.rb +0 -109
  116. data/spec/plugins/notify/ikachan_spec.rb +0 -58
  117. data/spec/plugins/provide/fluentd_spec.rb +0 -49
  118. data/spec/plugins/publish/amazon_s3_spec.rb +0 -40
  119. data/spec/plugins/publish/console_spec.rb +0 -30
  120. data/spec/plugins/publish/eject_spec.rb +0 -40
  121. data/spec/plugins/publish/fluentd_spec.rb +0 -40
  122. data/spec/plugins/publish/google_calendar_spec.rb +0 -83
  123. data/spec/plugins/publish/hatena_bookmark_spec.rb +0 -134
  124. data/spec/plugins/publish/hipchat_spec.rb +0 -69
  125. data/spec/plugins/publish/instapaper_spec.rb +0 -82
  126. data/spec/plugins/publish/memcached_spec.rb +0 -63
  127. data/spec/plugins/publish/pocket_spec.rb +0 -51
  128. data/spec/plugins/publish/twitter_spec.rb +0 -73
  129. data/spec/plugins/store/file_spec.rb +0 -58
  130. data/spec/plugins/store/full_text_spec.rb +0 -152
  131. data/spec/plugins/store/permalink_spec.rb +0 -206
  132. data/spec/plugins/subscription/chan_toru_spec.rb +0 -56
  133. data/spec/plugins/subscription/feed_spec.rb +0 -71
  134. data/spec/plugins/subscription/g_guide_spec.rb +0 -82
  135. data/spec/plugins/subscription/link_spec.rb +0 -72
  136. data/spec/plugins/subscription/pocket_spec.rb +0 -57
  137. data/spec/plugins/subscription/text_spec.rb +0 -84
  138. data/spec/plugins/subscription/tumblr_spec.rb +0 -74
  139. data/spec/plugins/subscription/twitter_search_spec.rb +0 -57
  140. data/spec/plugins/subscription/twitter_spec.rb +0 -73
  141. data/spec/plugins/subscription/weather_spec.rb +0 -44
  142. data/spec/plugins/subscription/xml_spec.rb +0 -84
  143. data/spec/spec_helper.rb +0 -106
  144. data/spec/user_dir/plugins/store/mock.rb +0 -16
  145. data/test/fixtures/sampleOPML.xml +0 -11
  146. data/test/integration/test_absoluteurl.yml +0 -25
  147. data/test/integration/test_activerecord.yml +0 -24
  148. data/test/integration/test_add_pocket.yml +0 -26
  149. data/test/integration/test_chan_toru.yml +0 -21
  150. data/test/integration/test_descriptionlink.yml +0 -21
  151. data/test/integration/test_fluentd.yml +0 -22
  152. data/test/integration/test_fulltext.yml +0 -30
  153. data/test/integration/test_google_news.yml +0 -21
  154. data/test/integration/test_googlealert.yml +0 -21
  155. data/test/integration/test_hatenabookmark.yml +0 -30
  156. data/test/integration/test_ignore.yml +0 -25
  157. data/test/integration/test_ignore2.yml +0 -22
  158. data/test/integration/test_image2local.yml +0 -33
  159. data/test/integration/test_instapaper.yml +0 -26
  160. data/test/integration/test_link2local.yml +0 -34
  161. data/test/integration/test_one.yml +0 -23
  162. data/test/integration/test_pocket.yml +0 -22
  163. data/test/integration/test_rand.yml +0 -21
  164. data/test/integration/test_sanitize.yml +0 -23
  165. data/test/integration/test_sort.yml +0 -36
  166. data/test/integration/test_svnlog.yml +0 -15
  167. data/test/integration/test_text2feed.yml +0 -36
  168. data/test/integration/test_tumblr2local.yml +0 -43
  169. data/test/integration/test_twitter_search.yml +0 -22
  170. data/test/integration/test_weather.yml +0 -19
  171. data/test/integration/test_xml2fluentd.yml +0 -21
  172. data/vendor/.gitkeep +0 -0
data/VERSION CHANGED
@@ -1 +1 @@
1
- 14.12.2
1
+ 26.08
data/automatic.gemspec CHANGED
@@ -1,254 +1,115 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
- # stub: automatic 14.12.2 ruby lib
1
+ # -*- coding: utf-8 -*-
2
+ # Name:: automatic.gemspec
3
+ # Author: id774 (More info: http://id774.net)
4
+ # Source Code:: https://github.com/id774/automaticruby
5
+ # License:: The GPL version 3, or LGPL version 3 (Dual License).
6
+ # Contact:: idnanashi@gmail.com
7
+ # Created:: Mar 7, 2012
8
+ # Updated:: Aug 14, 2026
9
+ # Copyright:: Copyright (c) 2012-2026 Automatic Ruby Developers.
10
+ #
11
+ # This file is maintained by hand. It was generated by Jeweler until v14.12.2;
12
+ # the generator is no longer maintained and the file is now source. See
13
+ # doc/POLICY.md section 9.4.
6
14
 
7
- Gem::Specification.new do |s|
8
- s.name = "automatic"
9
- s.version = "14.12.2"
15
+ Gem::Specification.new do |spec|
16
+ spec.name = 'automatic'
17
+ spec.version = File.read(File.expand_path('VERSION', __dir__)).strip
18
+ spec.authors = ['id774']
19
+ spec.email = ['idnanashi@gmail.com']
10
20
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
- s.authors = ["id774"]
14
- s.date = "2015-01-04"
15
- s.description = "Ruby framework for the general-purpose automatic processing"
16
- s.email = "idnanashi@gmail.com"
17
- s.executables = ["automatic"]
18
- s.extra_rdoc_files = [
19
- "README.md"
20
- ]
21
- s.files = [
22
- "Gemfile",
23
- "README.md",
24
- "Rakefile",
25
- "VERSION",
26
- "assets/siteinfo/items_all.json",
27
- "automatic.gemspec",
28
- "bin/automatic",
29
- "config/feed2console.yml",
30
- "db/.gitkeep",
31
- "doc/AUTHORS",
32
- "doc/COPYING",
33
- "doc/ChangeLog",
34
- "doc/PLUGINS",
35
- "doc/PLUGINS.ja",
36
- "doc/README",
37
- "doc/README.ja",
38
- "lib/automatic.rb",
39
- "lib/automatic/environment.rb",
40
- "lib/automatic/feed_maker.rb",
41
- "lib/automatic/feed_parser.rb",
42
- "lib/automatic/log.rb",
43
- "lib/automatic/opml.rb",
44
- "lib/automatic/pipeline.rb",
45
- "lib/automatic/recipe.rb",
46
- "lib/automatic/version.rb",
47
- "plugins/custom_feed/svn_log.rb",
48
- "plugins/filter/absolute_uri.rb",
49
- "plugins/filter/accept.rb",
50
- "plugins/filter/clear.rb",
51
- "plugins/filter/description_link.rb",
52
- "plugins/filter/full_feed.rb",
53
- "plugins/filter/github_feed.rb",
54
- "plugins/filter/google_news.rb",
55
- "plugins/filter/ignore.rb",
56
- "plugins/filter/image.rb",
57
- "plugins/filter/image_source.rb",
58
- "plugins/filter/one.rb",
59
- "plugins/filter/rand.rb",
60
- "plugins/filter/sanitize.rb",
61
- "plugins/filter/sort.rb",
62
- "plugins/filter/tumblr_resize.rb",
63
- "plugins/notify/ikachan.rb",
64
- "plugins/provide/fluentd.rb",
65
- "plugins/publish/amazon_s3.rb",
66
- "plugins/publish/console.rb",
67
- "plugins/publish/console_link.rb",
68
- "plugins/publish/eject.rb",
69
- "plugins/publish/fluentd.rb",
70
- "plugins/publish/google_calendar.rb",
71
- "plugins/publish/hatena_bookmark.rb",
72
- "plugins/publish/hipchat.rb",
73
- "plugins/publish/instapaper.rb",
74
- "plugins/publish/memcached.rb",
75
- "plugins/publish/pocket.rb",
76
- "plugins/publish/twitter.rb",
77
- "plugins/store/database.rb",
78
- "plugins/store/file.rb",
79
- "plugins/store/full_text.rb",
80
- "plugins/store/permalink.rb",
81
- "plugins/subscription/chan_toru.rb",
82
- "plugins/subscription/feed.rb",
83
- "plugins/subscription/g_guide.rb",
84
- "plugins/subscription/link.rb",
85
- "plugins/subscription/pocket.rb",
86
- "plugins/subscription/text.rb",
87
- "plugins/subscription/tumblr.rb",
88
- "plugins/subscription/twitter.rb",
89
- "plugins/subscription/twitter_search.rb",
90
- "plugins/subscription/weather.rb",
91
- "plugins/subscription/xml.rb",
92
- "script/build",
93
- "spec/fixtures/sampleFeeds.tsv",
94
- "spec/fixtures/sampleFeeds2.tsv",
95
- "spec/fixtures/sampleRecipe.yml",
96
- "spec/lib/automatic/log_spec.rb",
97
- "spec/lib/automatic/pipeline_spec.rb",
98
- "spec/lib/automatic/recipe_spec.rb",
99
- "spec/lib/automatic_spec.rb",
100
- "spec/plugins/custom_feed/svn_log_spec.rb",
101
- "spec/plugins/filter/absolute_uri_spec.rb",
102
- "spec/plugins/filter/accept_spec.rb",
103
- "spec/plugins/filter/clear_spec.rb",
104
- "spec/plugins/filter/description_link_spec.rb",
105
- "spec/plugins/filter/full_feed_spec.rb",
106
- "spec/plugins/filter/github_feed_spec.rb",
107
- "spec/plugins/filter/google_news_spec.rb",
108
- "spec/plugins/filter/ignore_spec.rb",
109
- "spec/plugins/filter/image_source_spec.rb",
110
- "spec/plugins/filter/image_spec.rb",
111
- "spec/plugins/filter/one_spec.rb",
112
- "spec/plugins/filter/rand_spec.rb",
113
- "spec/plugins/filter/sanitize_spec.rb",
114
- "spec/plugins/filter/sort_spec.rb",
115
- "spec/plugins/filter/tumblr_resize_spec.rb",
116
- "spec/plugins/notify/ikachan_spec.rb",
117
- "spec/plugins/provide/fluentd_spec.rb",
118
- "spec/plugins/publish/amazon_s3_spec.rb",
119
- "spec/plugins/publish/console_spec.rb",
120
- "spec/plugins/publish/eject_spec.rb",
121
- "spec/plugins/publish/fluentd_spec.rb",
122
- "spec/plugins/publish/google_calendar_spec.rb",
123
- "spec/plugins/publish/hatena_bookmark_spec.rb",
124
- "spec/plugins/publish/hipchat_spec.rb",
125
- "spec/plugins/publish/instapaper_spec.rb",
126
- "spec/plugins/publish/memcached_spec.rb",
127
- "spec/plugins/publish/pocket_spec.rb",
128
- "spec/plugins/publish/twitter_spec.rb",
129
- "spec/plugins/store/file_spec.rb",
130
- "spec/plugins/store/full_text_spec.rb",
131
- "spec/plugins/store/permalink_spec.rb",
132
- "spec/plugins/subscription/chan_toru_spec.rb",
133
- "spec/plugins/subscription/feed_spec.rb",
134
- "spec/plugins/subscription/g_guide_spec.rb",
135
- "spec/plugins/subscription/link_spec.rb",
136
- "spec/plugins/subscription/pocket_spec.rb",
137
- "spec/plugins/subscription/text_spec.rb",
138
- "spec/plugins/subscription/tumblr_spec.rb",
139
- "spec/plugins/subscription/twitter_search_spec.rb",
140
- "spec/plugins/subscription/twitter_spec.rb",
141
- "spec/plugins/subscription/weather_spec.rb",
142
- "spec/plugins/subscription/xml_spec.rb",
143
- "spec/spec_helper.rb",
144
- "spec/user_dir/plugins/store/mock.rb",
145
- "test/fixtures/sampleOPML.xml",
146
- "test/integration/test_absoluteurl.yml",
147
- "test/integration/test_activerecord.yml",
148
- "test/integration/test_add_pocket.yml",
149
- "test/integration/test_chan_toru.yml",
150
- "test/integration/test_descriptionlink.yml",
151
- "test/integration/test_fluentd.yml",
152
- "test/integration/test_fulltext.yml",
153
- "test/integration/test_google_news.yml",
154
- "test/integration/test_googlealert.yml",
155
- "test/integration/test_hatenabookmark.yml",
156
- "test/integration/test_ignore.yml",
157
- "test/integration/test_ignore2.yml",
158
- "test/integration/test_image2local.yml",
159
- "test/integration/test_instapaper.yml",
160
- "test/integration/test_link2local.yml",
161
- "test/integration/test_one.yml",
162
- "test/integration/test_pocket.yml",
163
- "test/integration/test_rand.yml",
164
- "test/integration/test_sanitize.yml",
165
- "test/integration/test_sort.yml",
166
- "test/integration/test_svnlog.yml",
167
- "test/integration/test_text2feed.yml",
168
- "test/integration/test_tumblr2local.yml",
169
- "test/integration/test_twitter_search.yml",
170
- "test/integration/test_weather.yml",
171
- "test/integration/test_xml2fluentd.yml",
172
- "vendor/.gitkeep"
173
- ]
174
- s.homepage = "http://github.com/automaticruby/automaticruby"
175
- s.licenses = ["GPL"]
176
- s.rubygems_version = "2.4.5"
177
- s.summary = "Automatic Ruby"
21
+ spec.summary = 'Automatic Ruby'
22
+ spec.description = <<~DESC
23
+ A Ruby framework for general-purpose automatic processing. A job is
24
+ described in a YAML file called a Recipe, which names plugins in order;
25
+ each plugin receives the previous one's output and returns the next one's
26
+ input. Subscribing, filtering, storing and publishing are all plugins, and
27
+ a plugin is found by name on a search path rather than registered.
28
+ DESC
178
29
 
179
- if s.respond_to? :specification_version then
180
- s.specification_version = 4
30
+ spec.homepage = 'https://github.com/id774/automaticruby'
31
+ spec.licenses = ['GPL-3.0-only', 'LGPL-3.0-only']
181
32
 
182
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
183
- s.add_runtime_dependency(%q<json>, ["~> 1.8.1"])
184
- s.add_runtime_dependency(%q<sqlite3>, ["~> 1.3.10"])
185
- s.add_runtime_dependency(%q<activesupport>, ["~> 4.1.8"])
186
- s.add_runtime_dependency(%q<activerecord>, ["~> 4.1.8"])
187
- s.add_runtime_dependency(%q<hashie>, ["~> 3.3.2"])
188
- s.add_runtime_dependency(%q<gcalapi>, ["~> 0.1.2"])
189
- s.add_runtime_dependency(%q<xml-simple>, ["~> 1.1.4"])
190
- s.add_runtime_dependency(%q<feedbag>, ["~> 0.9.5"])
191
- s.add_runtime_dependency(%q<nokogiri>, ["~> 1.6.5"])
192
- s.add_runtime_dependency(%q<sanitize>, ["~> 3.1.0"])
193
- s.add_runtime_dependency(%q<faraday>, ["~> 0.8.9"])
194
- s.add_runtime_dependency(%q<twitter>, ["~> 4.8.0"])
195
- s.add_runtime_dependency(%q<pocket-ruby>, ["~> 0.0.5"])
196
- s.add_runtime_dependency(%q<weather_hacker>, ["~> 0.1.7"])
197
- s.add_runtime_dependency(%q<hipchat>, ["~> 1.4.0"])
198
- s.add_runtime_dependency(%q<fluent-logger>, ["~> 0.4.7"])
199
- s.add_runtime_dependency(%q<dalli>, ["~> 2.7.2"])
200
- s.add_runtime_dependency(%q<aws-sdk>, ["~> 1.60.2"])
201
- s.add_development_dependency(%q<cucumber>, [">= 0"])
202
- s.add_development_dependency(%q<bundler>, [">= 0"])
203
- s.add_development_dependency(%q<builder>, [">= 0"])
204
- s.add_development_dependency(%q<jeweler>, [">= 0"])
205
- else
206
- s.add_dependency(%q<json>, ["~> 1.8.1"])
207
- s.add_dependency(%q<sqlite3>, ["~> 1.3.10"])
208
- s.add_dependency(%q<activesupport>, ["~> 4.1.8"])
209
- s.add_dependency(%q<activerecord>, ["~> 4.1.8"])
210
- s.add_dependency(%q<hashie>, ["~> 3.3.2"])
211
- s.add_dependency(%q<gcalapi>, ["~> 0.1.2"])
212
- s.add_dependency(%q<xml-simple>, ["~> 1.1.4"])
213
- s.add_dependency(%q<feedbag>, ["~> 0.9.5"])
214
- s.add_dependency(%q<nokogiri>, ["~> 1.6.5"])
215
- s.add_dependency(%q<sanitize>, ["~> 3.1.0"])
216
- s.add_dependency(%q<faraday>, ["~> 0.8.9"])
217
- s.add_dependency(%q<twitter>, ["~> 4.8.0"])
218
- s.add_dependency(%q<pocket-ruby>, ["~> 0.0.5"])
219
- s.add_dependency(%q<weather_hacker>, ["~> 0.1.7"])
220
- s.add_dependency(%q<hipchat>, ["~> 1.4.0"])
221
- s.add_dependency(%q<fluent-logger>, ["~> 0.4.7"])
222
- s.add_dependency(%q<dalli>, ["~> 2.7.2"])
223
- s.add_dependency(%q<aws-sdk>, ["~> 1.60.2"])
224
- s.add_dependency(%q<cucumber>, [">= 0"])
225
- s.add_dependency(%q<bundler>, [">= 0"])
226
- s.add_dependency(%q<builder>, [">= 0"])
227
- s.add_dependency(%q<jeweler>, [">= 0"])
33
+ spec.metadata = {
34
+ 'source_code_uri' => spec.homepage,
35
+ 'bug_tracker_uri' => "#{spec.homepage}/issues",
36
+ 'changelog_uri' => "#{spec.homepage}/blob/master/doc/VERSIONS",
37
+ 'documentation_uri' => "#{spec.homepage}/blob/master/README.md",
38
+ 'rubygems_mfa_required' => 'true'
39
+ }
40
+
41
+ # Ruby 3.3 is the floor: the oldest maintained release the dependencies are
42
+ # resolved and tested against. The code is written for Ruby 3.3 through 4.0.
43
+ #
44
+ # A lower bound only, and deliberately so. An upper bound would refuse a Ruby
45
+ # this code has every reason to work on, on the day it is released, and the
46
+ # only way to lift it would be a new release of this gem. What CI validates
47
+ # is a separate and narrower statement; see doc/REQUIREMENTS.md section 20.
48
+ spec.required_ruby_version = '>= 3.3.0'
49
+
50
+ # Shipped files. Derived from what Git sees, so that the list cannot drift
51
+ # from the repository; the Dir fallback is for building outside a checkout.
52
+ #
53
+ # --others --exclude-standard includes a file that has been created but not
54
+ # yet added, while still honouring .gitignore. Listing only --cached silently
55
+ # omits a new file from the built gem, which is a trap worth avoiding.
56
+ tracked =
57
+ begin
58
+ Dir.chdir(__dir__) {
59
+ `git ls-files -z --cached --others --exclude-standard`.split("\x0")
60
+ }
61
+ rescue StandardError
62
+ []
228
63
  end
229
- else
230
- s.add_dependency(%q<json>, ["~> 1.8.1"])
231
- s.add_dependency(%q<sqlite3>, ["~> 1.3.10"])
232
- s.add_dependency(%q<activesupport>, ["~> 4.1.8"])
233
- s.add_dependency(%q<activerecord>, ["~> 4.1.8"])
234
- s.add_dependency(%q<hashie>, ["~> 3.3.2"])
235
- s.add_dependency(%q<gcalapi>, ["~> 0.1.2"])
236
- s.add_dependency(%q<xml-simple>, ["~> 1.1.4"])
237
- s.add_dependency(%q<feedbag>, ["~> 0.9.5"])
238
- s.add_dependency(%q<nokogiri>, ["~> 1.6.5"])
239
- s.add_dependency(%q<sanitize>, ["~> 3.1.0"])
240
- s.add_dependency(%q<faraday>, ["~> 0.8.9"])
241
- s.add_dependency(%q<twitter>, ["~> 4.8.0"])
242
- s.add_dependency(%q<pocket-ruby>, ["~> 0.0.5"])
243
- s.add_dependency(%q<weather_hacker>, ["~> 0.1.7"])
244
- s.add_dependency(%q<hipchat>, ["~> 1.4.0"])
245
- s.add_dependency(%q<fluent-logger>, ["~> 0.4.7"])
246
- s.add_dependency(%q<dalli>, ["~> 2.7.2"])
247
- s.add_dependency(%q<aws-sdk>, ["~> 1.60.2"])
248
- s.add_dependency(%q<cucumber>, [">= 0"])
249
- s.add_dependency(%q<bundler>, [">= 0"])
250
- s.add_dependency(%q<builder>, [">= 0"])
251
- s.add_dependency(%q<jeweler>, [">= 0"])
252
- end
253
- end
254
64
 
65
+ tracked = Dir.chdir(__dir__) {
66
+ Dir.glob(
67
+ [
68
+ 'bin/*', 'lib/**/*.rb', 'plugins/**/*.rb', 'config/*.yml',
69
+ 'assets/**/*', 'doc/*', 'README.md', 'VERSION', 'automatic.gemspec'
70
+ ]
71
+ )
72
+ } if tracked.empty?
73
+
74
+ # Gemfile and Rakefile are development files and are deliberately not
75
+ # shipped: lib/automatic/environment.rb treats the presence of a Gemfile
76
+ # beside lib/ as "this is a source checkout", so shipping one would make an
77
+ # installed gem impose its own bundle on the program requiring it.
78
+ excluded = %w[.gitignore .github Gemfile Rakefile script spec test vendor]
79
+ spec.files = tracked.reject { |path|
80
+ path.end_with?('.gem') ||
81
+ excluded.any? { |prefix| path == prefix || path.start_with?("#{prefix}/") }
82
+ }.select { |path| File.file?(File.join(__dir__, path)) }
83
+
84
+ spec.bindir = 'bin'
85
+ spec.executables = ['automatic']
86
+ spec.require_paths = ['lib']
87
+ spec.extra_rdoc_files = ['README.md', 'doc/LICENSE.md']
88
+
89
+ # Runtime dependencies: what the framework in lib/ requires, and nothing
90
+ # else. Requiring `automatic`, loading a Recipe, loading a plugin, running a
91
+ # pipeline and the CLI's own work are what these four are for.
92
+ #
93
+ # A gem needed by a plugin is NOT declared here, however useful that plugin
94
+ # is. It is required inside the plugin's own file and installed by the
95
+ # operator who uses the plugin: `gem install automatic` therefore installs no
96
+ # HTML parser, no database and no service client. The optional gems, which
97
+ # plugin needs which, and how to install them are in the Gemfile's optional
98
+ # groups, doc/DEPLOYMENT.md and doc/POLICY.md section 9.1.
99
+ #
100
+ # rexml and rss left the standard library and became gems over the 3.x
101
+ # series. Each gem listed here is listed because a file in lib/ requires it,
102
+ # and a library's move out of the standard library is not by itself a reason
103
+ # to declare it: a library only a plugin needs goes in the Gemfile's optional
104
+ # groups instead.
105
+ spec.add_dependency 'activesupport', '>= 7.1', '< 9.0' # plugin loader, XML subscription
106
+ spec.add_dependency 'hashie', '>= 4.0', '< 6.0' # Recipe
107
+ spec.add_dependency 'rexml', '>= 3.2', '< 4.0' # OPML parser
108
+ spec.add_dependency 'rss', '>= 0.3', '< 1.0' # the pipeline value
109
+
110
+ spec.add_development_dependency 'rake', '~> 13.0'
111
+ spec.add_development_dependency 'rspec', '~> 3.13'
112
+ spec.add_development_dependency 'rspec-collection_matchers', '~> 1.2'
113
+ spec.add_development_dependency 'rspec-its', '>= 1.3', '< 3.0'
114
+ spec.add_development_dependency 'simplecov', '>= 0.22', '< 2.0'
115
+ end
data/bin/automatic CHANGED
@@ -1,141 +1,22 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- coding: utf-8 -*-
3
- # Name:: Automatic::Ruby
4
- # Author:: 774 <http://id774.net>
5
- # Created:: Feb 18, 2012
6
- # Updated:: Feb 21, 2014
7
- # Copyright:: Copyright (c) 2012-2014 Automatic Ruby Developers.
8
- # License:: Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.0.
9
-
10
- root_dir = File.expand_path("..", File.dirname(__FILE__))
11
- $:.unshift root_dir
12
- $:.unshift root_dir + '/lib'
13
-
14
- require 'automatic'
15
- require 'rubygems'
16
- require 'optparse'
17
- require 'fileutils'
18
- require 'feedbag'
19
- require 'pp'
20
-
21
- recipe_path = ""
22
-
23
- def abort_with_usage(subcommand, message)
24
- top_filename = File.basename($0)
25
- abort("Usage: #{top_filename} #{subcommand} #{message}")
26
- end
27
-
28
- subparsers = {
29
- 'scaffold' => lambda {|argv|
30
- Dir::entries(root_dir + '/plugins').sort.each {|path|
31
- dir = (File.expand_path('~/.automatic/plugins/' + path))
32
- unless File.exist?(dir)
33
- FileUtils.mkdir_p(dir)
34
- puts "Creating #{dir}"
35
- end
36
- }
37
- dir = (File.expand_path('~/.automatic/assets'))
38
- unless File.exist?(dir)
39
- FileUtils.mkdir_p(dir)
40
- FileUtils.cp_r(root_dir + '/assets/siteinfo', dir + '/siteinfo')
41
- puts "Creating #{dir}"
42
- end
43
- dir = (File.expand_path('~/.automatic/config'))
44
- unless File.exist?(dir)
45
- FileUtils.mkdir_p(dir)
46
- FileUtils.cp_r(root_dir + '/config', dir + '/example')
47
- puts "Creating #{dir}"
48
- end
49
- dir = (File.expand_path('~/.automatic/db'))
50
- unless File.exist?(dir)
51
- FileUtils.mkdir_p(dir)
52
- puts "Creating #{dir}"
53
- end
54
- },
55
- 'unscaffold' => lambda {|argv|
56
- dir = (File.expand_path('~/.automatic'))
57
- if File.directory?(dir)
58
- puts "Removing #{dir}"
59
- FileUtils.rm_r(dir)
60
- end
61
- },
62
- 'autodiscovery' => lambda {|argv|
63
- url = argv.shift || abort_with_usage("autodiscovery", "<url>")
64
- pp Feedbag.find(url)
65
- },
66
- 'feedparser' => lambda {|argv|
67
- require 'automatic/feed_parser'
68
- url = argv.shift || abort_with_usage("feedparser", "<url>")
69
- rss_results = Automatic::FeedParser.get_url(url)
70
- pp rss_results
71
- },
72
- 'inspect' => lambda {|argv|
73
- require 'automatic/feed_parser'
74
- url = argv.shift || abort_with_usage("inspect", "<url>")
75
- feeds = Feedbag.find(url)
76
- pp feeds
77
- rss_results = Automatic::FeedParser.get_url(feeds.pop)
78
- pp rss_results
79
- },
80
- 'opmlparser' => lambda {|argv|
81
- require 'automatic/opml'
82
- path = argv.shift
83
- if path.nil?
84
- abort_with_usage("opmlparser", "<opml path>")
85
- end
86
- parser = Automatic::OPML::Parser.new(File.read(path))
87
- parser.each_outline {|opml, o|
88
- puts "#{o.xmlUrl}"
89
- }
90
- },
91
- 'log' => lambda {|argv|
92
- require 'automatic/log'
93
- level = argv.shift || abort_with_usage("log", "<level> <message>")
94
- message = ARGV.shift
95
- Automatic::Log.puts(level, message)
96
- }
97
- }
98
-
99
- parser = OptionParser.new {|parser|
100
- parser.version = Automatic.const_get(:VERSION)
101
- parser.banner = "Automatic #{parser.version}
102
- Usage: automatic [options] [subcommand]"
103
- parser.separator "SubCommands:"
104
- subparsers.keys.each {|key|
105
- parser.separator " " + key
106
- }
107
- #{subparsers.keys.join(", ")}"
108
- parser.separator "Options:"
109
- parser.on('-c', '--config FILE', String,
110
- "recipe YAML file"){|c| recipe_path = c}
111
- parser.on('-h', '--help', "show this message") {
112
- puts parser
113
- exit 1
114
- }
115
- }
116
-
117
- begin
118
- Automatic::Log.puts("info", "Loading #{recipe_path}") unless recipe_path.empty?
119
- parser.parse!
120
- rescue OptionParser::ParseError => err
121
- $stderr.puts err.message
122
- $stderr.puts parser.help
123
- exit 2
124
- end
125
-
126
- unless recipe_path.to_s.empty?
127
- recipe = Automatic::Recipe.new(recipe_path)
128
- Automatic.run(:recipe => recipe,
129
- :root_dir => root_dir)
130
- else
131
- parser.order!(ARGV)
132
- unless ARGV.empty?
133
- Hash.new {|h, k|
134
- puts "No such subcommand: #{k}"
135
- exit 1
136
- }.update(subparsers)[ARGV.shift].call(ARGV)
137
- else
138
- puts parser
139
- exit 1
140
- end
141
- end
3
+ # Name:: automatic
4
+ # Author: id774 (More info: http://id774.net)
5
+ # Source Code:: https://github.com/id774/automaticruby
6
+ # License:: The GPL version 3, or LGPL version 3 (Dual License).
7
+ # Contact:: idnanashi@gmail.com
8
+ # Created:: Feb 18, 2012
9
+ # Updated:: Aug 14, 2026
10
+ # Copyright:: Copyright (c) 2012-2026 Automatic Ruby Developers.
11
+ #
12
+ # The process entry point, and deliberately almost empty: everything that can
13
+ # be tested lives in Automatic::CLI, which returns a status instead of exiting.
14
+ # See doc/BASIC_DESIGN.md section 4.1.
15
+
16
+ root_dir = File.expand_path('..', __dir__)
17
+ lib_dir = File.join(root_dir, 'lib')
18
+ $LOAD_PATH.unshift(lib_dir) if File.directory?(lib_dir) && !$LOAD_PATH.include?(lib_dir)
19
+
20
+ require 'automatic/cli'
21
+
22
+ exit Automatic::CLI.run(ARGV, root_dir: root_dir)
@@ -1,7 +1,13 @@
1
+ # Print a public feed to the terminal.
2
+ #
3
+ # automatic -c ~/.automatic/config/example/feed2console.yml
4
+ #
5
+ # The same pipeline as feed2markdown.yml with a different last plugin, which
6
+ # is the plugin to end a Recipe with while you are still writing it. Nothing
7
+ # here needs an account, a credential or a gem beyond the ones
8
+ # `gem install automatic` brings.
9
+
1
10
  global:
2
- timezone: Asia/Tokyo
3
- cache:
4
- base: /tmp
5
11
  log:
6
12
  level: info
7
13
 
@@ -9,6 +15,6 @@ plugins:
9
15
  - module: SubscriptionFeed
10
16
  config:
11
17
  feeds:
12
- - http://blog.id774.net/post/feed/
18
+ - https://www.ruby-lang.org/en/feeds/news.rss
13
19
 
14
20
  - module: PublishConsole
@@ -0,0 +1,41 @@
1
+ # Collect public information and leave the result as a Markdown document.
2
+ #
3
+ # automatic -c ~/.automatic/config/example/feed2markdown.yml
4
+ #
5
+ # The document is readable as it stands, searchable with grep, worth keeping in
6
+ # version control, and ready to hand to a program that takes text as input.
7
+ # Nothing here needs an account, a credential, a service or a gem beyond the
8
+ # ones `gem install automatic` brings: the Recipe is the framework's core and
9
+ # two plugins that need nothing of their own.
10
+ #
11
+ # Running it twice appends the same items twice. To collect only what is new,
12
+ # put a store plugin in front of the publisher -- it records what has already
13
+ # been written, which is also what makes a Recipe safe to run from cron:
14
+ #
15
+ # - module: StorePermalink
16
+ # config:
17
+ # db: feed2markdown.db
18
+ #
19
+ # The store plugins keep their records in SQLite through ActiveRecord, which is
20
+ # an optional dependency rather than a framework one:
21
+ #
22
+ # gem install activerecord sqlite3
23
+ #
24
+ # See doc/DEPLOYMENT.md for the optional plugin dependencies, and
25
+ # doc/QUICKSTART.md for a first run taken step by step.
26
+ #
27
+ # To send the document to standard output instead, drop the PublishMarkdown
28
+ # config and set the log level to none, so that only the document is written:
29
+ #
30
+ # automatic -c feed2markdown.yml > today.md
31
+
32
+ plugins:
33
+ - module: SubscriptionFeed
34
+ config:
35
+ feeds:
36
+ - https://www.ruby-lang.org/en/feeds/news.rss
37
+
38
+ - module: PublishMarkdown
39
+ config:
40
+ file: ~/.automatic/markdown/feeds.md
41
+ mode: append