tumblr_autofixer 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +64 -17
- data/bin/taf +7 -3
- data/lib/autofixer/autofixer.rb +294 -0
- data/lib/autofixer/commands/generate_tags_yml.rb +69 -0
- data/lib/autofixer/commands/open_results.rb +4 -4
- data/lib/autofixer/commands/show_config.rb +9 -0
- data/lib/autofixer/commands/show_help.rb +4 -3
- data/lib/autofixer/commands/show_version.rb +3 -3
- data/lib/autofixer/config/view_config.html.erb +40 -0
- data/lib/autofixer/config/view_config.rb +60 -0
- data/lib/autofixer/data_store.rb +1 -1
- data/lib/autofixer/helpers.rb +5 -15
- data/lib/autofixer/patches/DK_Post.rb +25 -0
- data/lib/autofixer/results.rb +36 -23
- data/lib/autofixer/version.rb +2 -2
- data/lib/tumblr_autofixer.rb +2 -172
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78babced78ceb2710811757881225b103d94eeed
|
4
|
+
data.tar.gz: fb77a09e95ac5aeb4c85ee33c3a98e5437f5d1d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6c2f0b5c7941307976ab267904738b044a845b5acd9e33682ad7fd52b863f94359823f9f711f317ee30b59128fe717d05efbd6ffe0dad9ff33f0d89d173fff7
|
7
|
+
data.tar.gz: 0334ba951d9c8a4bf7cdcfa60ad626019d38368a1ae398df94354771141246117a0a28990b207b9cc305a27e8802cf5d71ac6af7f42f2fb586a3b919889cde1c
|
data/README.md
CHANGED
@@ -1,30 +1,77 @@
|
|
1
1
|
# About
|
2
2
|
\- tumblr_autofix is a configurable comment generator for Tumblr.
|
3
|
-
\-
|
3
|
+
\- Generated files are stored in ~/config_md/taf/
|
4
4
|
\- Careful when editing configuration files, as with all YAML files, indentation is crucial!
|
5
5
|
|
6
|
+
# Version 0.1.0
|
7
|
+
- New: [Tag Matcher](#using-the-tag-matcher)! Use a whitelist of tags to improve Autofixer's ability to
|
8
|
+
- Ability to include DK::Autofixer in your programs
|
9
|
+
- Started building out the test suite
|
10
|
+
- Extensive refactoring
|
11
|
+
- Please report any [issues](https://github.com/meissadia/tumblr_autofix/issues)
|
12
|
+
|
13
|
+
# Using the Tag Matcher
|
14
|
+
In order to utilize the Tag Matcher we'll need to generate a list of acceptable tags. To do this, we'll collect the tags of your last 1,000 posts as a starting point.
|
15
|
+
|
16
|
+
## Basic
|
17
|
+
`taf g:tags`
|
18
|
+
|
19
|
+
This will generate a file in your home directory '~/config_md/taf/tags.yml'
|
20
|
+
You can edit this file and delete any lines which contain tags you do not want used to automatically generate post comments.
|
21
|
+
|
22
|
+
## Advanced
|
23
|
+
You can specify a few options for the g:tags command
|
24
|
+
|
25
|
+
| Option | Description |
|
26
|
+
| :--- | :--- |
|
27
|
+
| `-l [LIMIT]` | Maximum number of posts to scan. |
|
28
|
+
| `-b [BLOG]` | Blog name to scan. Only required if scanning a secondary blog. |
|
29
|
+
| `--source [SOURCE]` | draft, queue, or publish.|
|
30
|
+
| `--config [CONFIG]` | Autofixer uses DraftKing to connect to tumblr, specify your saved config here. |
|
31
|
+
|
32
|
+
|
33
|
+
Example:
|
34
|
+
`taf -l 200 -b secondary-blog-name --source queue`
|
35
|
+
|
6
36
|
# Using ~/config_md/taf/data.yml
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
37
|
+
data.yml allows you to configure, on a blog-by-blog basis, the source of the data used to generate new comments. You may use a specific tag index, the last tag, or simply reuse the existing summary.
|
38
|
+
|
39
|
+
| Field | Type | Description |
|
40
|
+
| :--- | :---: | :--- |
|
41
|
+
| `ignore` | Array | Blogs listed here will only be processed with the Tag Matcher
|
42
|
+
| `last_tag` | Array | Use the last available tag as your comment
|
43
|
+
| `summary` | Array | Use full text of existing post.summary
|
44
|
+
| `tag_idx` | [Array] | Indicates which tag index to use as the new comment
|
45
|
+
| | | - Blogs listed in tag_idx[0] will use the first tag
|
46
|
+
| | | - Blogs listed in tag_idx[1] will use the second
|
13
47
|
|
14
48
|
|
15
49
|
# Using ~/config_md/taf/summary.yml
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
50
|
+
The summary.yml configuration allows you to code the processing steps needed
|
51
|
+
to extract the information you want from a post's comment. This can be set up on
|
52
|
+
a blog-by-blog basis.
|
53
|
+
|
54
|
+
## Available variables
|
55
|
+
| Variable | Description |
|
56
|
+
| :--- | :--- |
|
57
|
+
| `summary` | the plain text of the current post's caption
|
58
|
+
| `res` | lower case version of summary, useful for simplified text searching
|
59
|
+
| `from` | the blog name of the user you reblogged the post from
|
60
|
+
| `lines` | original summary text, split into lines
|
61
|
+
|
62
|
+
## Available methods
|
63
|
+
| Method | Description |
|
64
|
+
| :--- | :---: |
|
65
|
+
| `normalize(string)` | Applies capitalization, adds configured prefix/postfix strings
|
21
66
|
|
22
67
|
## Returning
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
68
|
+
| Method | Description |
|
69
|
+
| :--- | :--- |
|
70
|
+
| `return <value> `| Use the <value> string as the comment for this post
|
71
|
+
| `res = 'your value'` | storing your new comment in the `res` variable, without explicitly returning it, will subject it to a couple more modifications:
|
72
|
+
| | 1. capitalization - each word in the string will be capitalized
|
73
|
+
| | 2. prefix - a string passed via the `-p <PREFIX>` option will be prepended to `res`
|
74
|
+
| | 3. postfix - a string passed via the `-P <POSTFIX>` option will be appended to `res`
|
28
75
|
|
29
76
|
## Summary Example
|
30
77
|
|
data/bin/taf
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'rubygems'
|
3
3
|
require 'tumblr_draftking'
|
4
|
-
|
5
|
-
#
|
4
|
+
if ENV['DEV_ENV']
|
5
|
+
# DEV ONLY - Run development source using system installed cli
|
6
|
+
require File.join(Dir.home, "#{ENV['DIR_RUBY']}/tumblr_autofixer/lib/tumblr_autofixer")
|
7
|
+
else
|
8
|
+
require_relative '../lib/tumblr_autofixer'
|
9
|
+
end
|
6
10
|
|
7
|
-
DK::
|
11
|
+
DK::Autofixer.new(ARGV).run
|
@@ -0,0 +1,294 @@
|
|
1
|
+
module DK
|
2
|
+
class Autofixer
|
3
|
+
ERROR = '**'
|
4
|
+
POSTS = '/Users/meis/coding/rails/autofixer/db/test.posts'
|
5
|
+
CONFIGDIR = '/config_md/taf/'
|
6
|
+
INFO = 'info'
|
7
|
+
WARN = 'warning'
|
8
|
+
ERRO = 'error'
|
9
|
+
|
10
|
+
attr_accessor :dk # DraftKing for Tumblr
|
11
|
+
attr_accessor :simulate, :limit # DraftKing Settings
|
12
|
+
attr_accessor :config_dir # Autofixer Required Structure
|
13
|
+
attr_accessor :last_tag, :summary, :tag_idx # Autofixer Tagging Config
|
14
|
+
attr_accessor :spliter, :prefix, :postfix # Autofixer Tagging Options
|
15
|
+
attr_accessor :clear, :use_test, :reprocess # Autofixer Processing Options
|
16
|
+
attr_accessor :show_results, :hide_pics # Autofixer Result Options
|
17
|
+
attr_accessor :processed, :review, :updated # Autofixer Results
|
18
|
+
|
19
|
+
def initialize(opts = {})
|
20
|
+
set_instance_vars(opts)
|
21
|
+
installed_test_configuration?
|
22
|
+
read_configuration
|
23
|
+
end
|
24
|
+
|
25
|
+
# Automated Processing
|
26
|
+
def run
|
27
|
+
perform_command? # Commands will exit(#)
|
28
|
+
process(get_filtered_posts)
|
29
|
+
@review = apply_tag_matcher_to(@review)
|
30
|
+
@review = clear(@review)
|
31
|
+
show_results
|
32
|
+
end
|
33
|
+
|
34
|
+
# Execute Command
|
35
|
+
def perform_command?
|
36
|
+
show_help
|
37
|
+
show_config
|
38
|
+
show_version
|
39
|
+
open_results
|
40
|
+
generate_tags_yml
|
41
|
+
if @options.first && !@options.first[0].eql?('-')
|
42
|
+
puts "\nCommand '#{@options.first}' not found.\n\n"
|
43
|
+
exit(1)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Load data and filter out processed or seemingly unprocessible posts
|
48
|
+
def get_filtered_posts
|
49
|
+
drafts = @usetestdata ? load_test_data : @dk.get_posts
|
50
|
+
@total = drafts.size
|
51
|
+
drafts.map do |draft|
|
52
|
+
draft = DK::Post.new draft
|
53
|
+
next if filter_processed? draft
|
54
|
+
next if filter_by_info? draft
|
55
|
+
next if filter_by_trail? draft
|
56
|
+
draft
|
57
|
+
end.compact
|
58
|
+
end
|
59
|
+
|
60
|
+
# Construct new post comments based on available configurations
|
61
|
+
def process(posts)
|
62
|
+
posts.each_with_index do |post, idx|
|
63
|
+
tags = post.tags
|
64
|
+
blog = post.trail.first.blog.name
|
65
|
+
summary = post.summary
|
66
|
+
|
67
|
+
next if ignore? blog, post
|
68
|
+
# Scan for configured tag-index
|
69
|
+
comment = use_tag_index blog, post
|
70
|
+
# Use coded configuration
|
71
|
+
comment ||= use_commands blog, summary
|
72
|
+
# Use full summary text
|
73
|
+
comment ||= use_summary blog, summary
|
74
|
+
# Use last tag
|
75
|
+
comment ||= use_tag_index blog, post, @last_tag.include?(blog)
|
76
|
+
# No automated processing
|
77
|
+
comment ||= ERROR
|
78
|
+
|
79
|
+
success = update_post_comment(post, comment)
|
80
|
+
(success ? @updated : @review) << post
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Contruct a comment using any whitelisted tags
|
85
|
+
# return: [String] Normalized Comment
|
86
|
+
def tag_matcher(tags)
|
87
|
+
return ERROR if tags.empty?
|
88
|
+
joiner = ' | '
|
89
|
+
matches = tags.select{ |tag| @gtags.include? tag.downcase }
|
90
|
+
return ERROR if matches.empty?
|
91
|
+
new_comment = matches.join(joiner)
|
92
|
+
normalize(new_comment)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Mass processing based on whitelisted tags
|
96
|
+
# return: [Array] Unmatched Posts
|
97
|
+
def apply_tag_matcher_to(posts)
|
98
|
+
return posts unless @gtags
|
99
|
+
return posts if @gtags.empty?
|
100
|
+
not_matched = []
|
101
|
+
while (post = posts.shift)
|
102
|
+
next if post.tags.empty?
|
103
|
+
new_comment = tag_matcher(post.tags)
|
104
|
+
if new_comment.eql?(ERROR)
|
105
|
+
not_matched << post
|
106
|
+
next
|
107
|
+
end
|
108
|
+
success = update_post_comment(post, new_comment)
|
109
|
+
(success ? @updated : not_matched) << post
|
110
|
+
end
|
111
|
+
not_matched
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
# **************************************************************************
|
117
|
+
# Processing Methods
|
118
|
+
# **************************************************************************
|
119
|
+
# Use the user coded processing for this blog
|
120
|
+
def use_commands(blog, summary)
|
121
|
+
commands = restore(@sstore, blog.to_sym)
|
122
|
+
special_summary(summary, blog, commands)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Normalize and use the full summary text
|
126
|
+
def use_summary(blog, summary)
|
127
|
+
return nil unless @summary.include?(blog)
|
128
|
+
special_summary(summary, blog, [])
|
129
|
+
end
|
130
|
+
|
131
|
+
# Use the tag at the configured index, if available
|
132
|
+
# return: [boolean] Success?
|
133
|
+
def use_tag_index(blog_name, post, last=nil)
|
134
|
+
return normalize post.tags.last if last
|
135
|
+
@tag_idx.each_with_index do |names, idx|
|
136
|
+
next unless names.include?(blog_name)
|
137
|
+
return normalize(post.tags[idx])
|
138
|
+
end
|
139
|
+
nil
|
140
|
+
end
|
141
|
+
|
142
|
+
def update_post_comment(post, comment)
|
143
|
+
return false if comment.eql? ERROR
|
144
|
+
post.replace_comment_with(comment)
|
145
|
+
post.save(client: @dk.client, simulate: @dk.simulate)
|
146
|
+
end
|
147
|
+
|
148
|
+
def special_summary(summary, from, commands)
|
149
|
+
return nil if summary.nil? || from.nil?
|
150
|
+
return nil unless commands
|
151
|
+
lines = summary.split("\n")
|
152
|
+
res = summary.downcase
|
153
|
+
b = binding
|
154
|
+
commands.each{ |x| eval(x, b) }
|
155
|
+
normalize(res)
|
156
|
+
endormalize(res)
|
157
|
+
end
|
158
|
+
|
159
|
+
def clear(posts)
|
160
|
+
return posts unless @clear
|
161
|
+
error = []
|
162
|
+
posts.each do |post|
|
163
|
+
success = update_post_comment(post, @prefix)
|
164
|
+
(success ? @updated : error) << post
|
165
|
+
end
|
166
|
+
error
|
167
|
+
end
|
168
|
+
|
169
|
+
def affix(s)
|
170
|
+
result = ''
|
171
|
+
result += "#{@prefix}" if @prefix
|
172
|
+
result += "#{' ' + @spliter + ' '}"
|
173
|
+
result += "#{s}"
|
174
|
+
if @postfix
|
175
|
+
result += "#{' ' + @spliter + ' '}"
|
176
|
+
result += "#{@postfix}"
|
177
|
+
end
|
178
|
+
result
|
179
|
+
end
|
180
|
+
|
181
|
+
def log(type, msg)
|
182
|
+
@messages << "#{type.capitalize}: #{msg}"
|
183
|
+
end
|
184
|
+
|
185
|
+
# **************************************************************************
|
186
|
+
# Filtration Methods
|
187
|
+
# **************************************************************************
|
188
|
+
def filter_processed?(draft)
|
189
|
+
if draft.processed?(skip: @reprocess, prefix: @prefix)
|
190
|
+
@processed << draft
|
191
|
+
return true
|
192
|
+
end
|
193
|
+
false
|
194
|
+
end
|
195
|
+
|
196
|
+
def filter_by_info?(draft)
|
197
|
+
unless draft.has_info?
|
198
|
+
@review << draft
|
199
|
+
return true
|
200
|
+
end
|
201
|
+
false
|
202
|
+
end
|
203
|
+
|
204
|
+
def filter_by_trail?(draft)
|
205
|
+
unless draft.has_trail?
|
206
|
+
@review << draft
|
207
|
+
return true
|
208
|
+
end
|
209
|
+
false
|
210
|
+
end
|
211
|
+
|
212
|
+
def ignore?(blog, post)
|
213
|
+
return false unless @ignore.include? blog
|
214
|
+
@review << post
|
215
|
+
true
|
216
|
+
end
|
217
|
+
|
218
|
+
# **************************************************************************
|
219
|
+
# Configuration Methods
|
220
|
+
# **************************************************************************
|
221
|
+
def dk_opts
|
222
|
+
{ simulate: @simulate, limit: @limit }
|
223
|
+
end
|
224
|
+
|
225
|
+
def home_file(file)
|
226
|
+
DK::Config.home_path_file(file)
|
227
|
+
end
|
228
|
+
|
229
|
+
def confile(fname)
|
230
|
+
@config_dir + fname
|
231
|
+
end
|
232
|
+
|
233
|
+
def set_instance_vars(opts)
|
234
|
+
@options = opts
|
235
|
+
@simulate = @options.include?('-s')
|
236
|
+
@limit = @options[@options.find_index('-l') + 1].to_i rescue nil
|
237
|
+
@spliter = @options[@options.find_index('-S') + 1] rescue ' '
|
238
|
+
@prefix = @options[@options.find_index('-p') + 1] rescue nil
|
239
|
+
@postfix = @options[@options.find_index('-P') + 1] rescue nil
|
240
|
+
@clear = @options.find_index('--clear')
|
241
|
+
@reprocess = @options.find_index('--reprocess')
|
242
|
+
@hide_pics = @options.find_index('--no-pics')
|
243
|
+
@usetestdata = @options.find_index('--test')
|
244
|
+
@show_results = @options.find_index('--show')
|
245
|
+
@config_dir = home_file(CONFIGDIR)
|
246
|
+
@dk = DK::Client.new(dk_opts)
|
247
|
+
@messages = []
|
248
|
+
@processed = []
|
249
|
+
@updated = []
|
250
|
+
@review = []
|
251
|
+
end
|
252
|
+
|
253
|
+
def read_configuration
|
254
|
+
# Ensure directory structure exists
|
255
|
+
FileUtils::makedirs @config_dir unless Dir.exist?(@config_dir)
|
256
|
+
|
257
|
+
# Ensure configuration files are present
|
258
|
+
@ystore = YAML::Store.new("#{confile('data.yml')}")
|
259
|
+
@sstore = YAML::Store.new("#{confile('summary.yml')}")
|
260
|
+
@tstore = YAML::Store.new("#{confile('tags.yml')}")
|
261
|
+
prep_user_data_files
|
262
|
+
|
263
|
+
# Cache config data
|
264
|
+
@last_tag = restore(@ystore, :last_tag)
|
265
|
+
@tag_idx = restore(@ystore, :tag_idx)
|
266
|
+
@summary = restore(@ystore, :summary)
|
267
|
+
@ignore = restore(@ystore, :ignore)
|
268
|
+
@gtags = restore(@tstore, :good)
|
269
|
+
end
|
270
|
+
|
271
|
+
def load_test_data
|
272
|
+
return eval(File.open(POSTS, 'r').read) if File.exist? POSTS
|
273
|
+
log INFO, "Saved post data to #{POSTS}"
|
274
|
+
posts = @dk.get_posts
|
275
|
+
File.open(POSTS, 'w') { |f| f.write posts }
|
276
|
+
posts
|
277
|
+
end
|
278
|
+
|
279
|
+
def installed_test_configuration?(result=nil)
|
280
|
+
data_yml = home_file('/coding/ruby/tumblr_autofixer/data.yml.bak')
|
281
|
+
summary_yml = home_file('/coding/ruby/tumblr_autofixer/summary.yml')
|
282
|
+
if File.exist? data_yml
|
283
|
+
`cp #{data_yml} #{confile('data.yml')}`
|
284
|
+
result = true
|
285
|
+
end
|
286
|
+
if File.exist? summary_yml
|
287
|
+
`cp #{summary_yml} #{confile('summary.yml')}`
|
288
|
+
result = true
|
289
|
+
end
|
290
|
+
result
|
291
|
+
end
|
292
|
+
|
293
|
+
end # end of DK::Autofixer
|
294
|
+
end # end of DK
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module DK
|
2
|
+
class Autofixer
|
3
|
+
# Command
|
4
|
+
def generate_tags_yml
|
5
|
+
return unless @options.include?('g:tags')
|
6
|
+
GenerateTagsYml.new(ARGV)
|
7
|
+
exit(0)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Generate tags.yml using DK
|
11
|
+
class GenerateTagsYml
|
12
|
+
def initialize(opts)
|
13
|
+
options = {}
|
14
|
+
options[:limit] = opt_val('-l') || 50
|
15
|
+
options[:blog] = opt_val('-b')
|
16
|
+
options[:config] = opt_val('--config')
|
17
|
+
options[:source] = opt_val('--source') || DK::PUBLISH
|
18
|
+
# Get Posts
|
19
|
+
dk = DK::Client.new(options)
|
20
|
+
posts = dk.get_posts.map { |post| DK::Post.new post }
|
21
|
+
posts = posts.select { |post| !post.tags.empty? }
|
22
|
+
# Collect Tags
|
23
|
+
@tags = []
|
24
|
+
posts.each { |post| @tags += post.tags }
|
25
|
+
@tstore = YAML::Store.new("#{confile('tags.yml')}")
|
26
|
+
# Preserve existing
|
27
|
+
existing = restore(@tstore, :good)
|
28
|
+
puts "Found #{existing.size} tags." if existing
|
29
|
+
@tags += existing if existing
|
30
|
+
@tags = @tags.map(&:downcase)
|
31
|
+
@tags.uniq!
|
32
|
+
@tags.sort!
|
33
|
+
# Save
|
34
|
+
puts "Saving #{@tags.size} tags"
|
35
|
+
store(@tstore, :good, @tags)
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def opt_val(opt, default=nil)
|
40
|
+
ARGV[ARGV.find_index(opt) + 1] rescue default
|
41
|
+
end
|
42
|
+
|
43
|
+
def home_file(file)
|
44
|
+
DK::Config.home_path_file(file)
|
45
|
+
end
|
46
|
+
|
47
|
+
def confile(fname)
|
48
|
+
home_file('/config_md/taf/') + fname
|
49
|
+
end
|
50
|
+
|
51
|
+
# Code to extract from summary
|
52
|
+
# unless @split = opt_val('-S')
|
53
|
+
# puts "Please provide at least one delimiter"
|
54
|
+
# puts "eg. taf g:tags -S |"
|
55
|
+
# puts "eg. taf g:tags -S ,|/\\"
|
56
|
+
# exit(1)
|
57
|
+
# end
|
58
|
+
# posts.each do |post|
|
59
|
+
# comment = post.comment
|
60
|
+
# result = nil
|
61
|
+
# @split.each do |str|
|
62
|
+
# result ||= comment.split str
|
63
|
+
# result = result.map { |str2| str2.split str }.flatten
|
64
|
+
# end
|
65
|
+
# @tags += result
|
66
|
+
# end
|
67
|
+
end # of GenerateTagsYml
|
68
|
+
end # of Autofixer
|
69
|
+
end # of DK
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module DK
|
2
|
-
|
3
|
-
def open_results
|
4
|
-
return unless
|
5
|
-
file = confile('
|
2
|
+
class Autofixer
|
3
|
+
def open_results
|
4
|
+
return unless @options.include?('open')
|
5
|
+
file = confile('updated.html')
|
6
6
|
`open #{file}` && exit(0) if File.exist?(file)
|
7
7
|
puts
|
8
8
|
puts 'Error:'
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module DK
|
2
|
-
|
3
|
-
def show_help
|
4
|
-
return unless (
|
2
|
+
class Autofixer
|
3
|
+
def show_help
|
4
|
+
return unless (@options.include?('help') || @options.find_index('-h'))
|
5
5
|
puts 'Usage: '
|
6
6
|
puts ' $ taf <command?> [options?]'
|
7
7
|
puts
|
8
8
|
puts ' Commands:'
|
9
9
|
puts ' help Show this menu.'
|
10
10
|
puts ' open Open a webpage with the latest taf results.'
|
11
|
+
puts ' g:tags <command> [options] Generate a list of tags from your latest posts to serve as a whitelist for the Tag Matcher.'
|
11
12
|
puts
|
12
13
|
puts ' Options:'
|
13
14
|
puts ' -s Simulate Run (no changes saved)'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title><%= fname %></title>
|
4
|
+
<%= style %>
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<h1>Ignore</h1>
|
8
|
+
<ul>
|
9
|
+
<% @ignore.each do |i| %>
|
10
|
+
<li><%= i %></li>
|
11
|
+
<% end %>
|
12
|
+
</ul>
|
13
|
+
|
14
|
+
<h1>Last Tag</h1>
|
15
|
+
<ul>
|
16
|
+
<% @last_tag.each do |i| %>
|
17
|
+
<li><%= i %></li>
|
18
|
+
<% end %>
|
19
|
+
</ul>
|
20
|
+
|
21
|
+
<h1>Summary</h1>
|
22
|
+
<ul>
|
23
|
+
<% @summary.each do |i| %>
|
24
|
+
<li><%= i %></li>
|
25
|
+
<% end %>
|
26
|
+
</ul>
|
27
|
+
|
28
|
+
<h1>Tag Index</h1>
|
29
|
+
<% @tag_idx.each_with_index do |blog_list, idx| %>
|
30
|
+
<h2>Tag <%= idx %></h2>
|
31
|
+
<ul>
|
32
|
+
<% blog_list.each do |blog| %>
|
33
|
+
<li><%= blog %></li>
|
34
|
+
<% end %>
|
35
|
+
</ul>
|
36
|
+
<% end %>
|
37
|
+
|
38
|
+
<footer>Updated at <%= Time.now.strftime('%d/%m/%Y') %></footer>
|
39
|
+
</body>
|
40
|
+
</html>
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'tumblr_draftking'
|
2
|
+
require 'yaml/store'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
def store(dstore, key, value)
|
7
|
+
dstore.transaction do
|
8
|
+
dstore[key] = value
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def restore(dstore, key, default=nil)
|
13
|
+
dstore.transaction do
|
14
|
+
dstore[key] || default
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def style
|
19
|
+
%q(
|
20
|
+
<style>
|
21
|
+
h1,h2 { width: 100%; background-color: rgb(140, 129, 38); color: white; text-align: center; }
|
22
|
+
ul, li { width: 100%; text-align: center; vertical-align: middle; padding: 0; margin: 0 auto;}
|
23
|
+
ul li { list-style: none; padding: 0; margin: 0 auto; }
|
24
|
+
ul li:hover { background-color: rgb(200, 200, 102); }
|
25
|
+
a, a:visited { color: white; vertical-align: middle; line-height: 100px; }
|
26
|
+
</style>
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def script
|
31
|
+
%q(
|
32
|
+
<script>
|
33
|
+
|
34
|
+
</script>
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
if $0 == __FILE__
|
39
|
+
data_yml = YAML::Store.new(DK::Config.home_path_file('/config_md/taf/data.yml'))
|
40
|
+
# special_yml = YAML::Store.new(DK::Config.home_path_file('summary.yml'))
|
41
|
+
|
42
|
+
# Cache config data
|
43
|
+
@last_tag = restore(data_yml, :last_tag)
|
44
|
+
@tag_idx = restore(data_yml, :tag_idx)
|
45
|
+
@summary = restore(data_yml, :summary)
|
46
|
+
@ignore = restore(data_yml, :ignore)
|
47
|
+
|
48
|
+
template = '.html.erb'
|
49
|
+
fname = File.basename(__FILE__, '.rb')
|
50
|
+
tname = fname + template
|
51
|
+
tdata = File.open(tname, 'rb', &:read)
|
52
|
+
result = ERB.new(tdata).result(binding)
|
53
|
+
|
54
|
+
out_file = DK::Config.home_path_file('/config_md/taf/view_config.html')
|
55
|
+
File.open(out_file, 'w') do |f|
|
56
|
+
f << result
|
57
|
+
end
|
58
|
+
|
59
|
+
`open #{out_file}`
|
60
|
+
end
|
data/lib/autofixer/data_store.rb
CHANGED
data/lib/autofixer/helpers.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
module DK
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
{ simulate: @simulate, limit: @limit }
|
2
|
+
class Autofixer
|
3
|
+
def normalize(tag, from='')
|
4
|
+
return ERROR if tag.nil?
|
5
|
+
affix(capitalize(tag))
|
7
6
|
end
|
8
7
|
|
9
8
|
def capitalize(s)
|
@@ -13,12 +12,7 @@ module DK
|
|
13
12
|
res.join(' ')
|
14
13
|
end
|
15
14
|
|
16
|
-
def
|
17
|
-
"#{@prefix}#{' ' + @spliter + ' ' if @spliter}#{s}#{@postfix}"
|
18
|
-
end
|
19
|
-
|
20
|
-
def link_to_edit(post)
|
21
|
-
id = post.id rescue post['id']
|
15
|
+
def link_to_edit(id)
|
22
16
|
"https://www.tumblr.com/edit/#{id}"
|
23
17
|
end
|
24
18
|
|
@@ -33,9 +27,5 @@ module DK
|
|
33
27
|
s
|
34
28
|
end
|
35
29
|
|
36
|
-
def home_file(file)
|
37
|
-
DK::Config.home_path_file(file)
|
38
|
-
end
|
39
|
-
|
40
30
|
end
|
41
31
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DK
|
2
|
+
class Post
|
3
|
+
# Post has a summary or tags?
|
4
|
+
def has_info?
|
5
|
+
has_summary? || !tags.empty?
|
6
|
+
end
|
7
|
+
|
8
|
+
# Do we know where it was reblogged from?
|
9
|
+
def has_trail?
|
10
|
+
!trail.empty?
|
11
|
+
end
|
12
|
+
|
13
|
+
# Post already has prefix?
|
14
|
+
def processed?(skip: false, prefix: '')
|
15
|
+
return false if skip
|
16
|
+
return false if prefix.empty?
|
17
|
+
l_comment = Sanitize.fragment(comment).strip
|
18
|
+
l_comment.start_with?(prefix) || summary.strip.start_with?(prefix)
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_summary?
|
22
|
+
summary.strip.empty?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/autofixer/results.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module DK
|
2
|
-
|
2
|
+
class Autofixer
|
3
3
|
private
|
4
4
|
|
5
5
|
def bfrom(post)
|
@@ -9,44 +9,45 @@ module DK
|
|
9
9
|
def show_results
|
10
10
|
cli_header
|
11
11
|
|
12
|
-
fname1 = confile('
|
13
|
-
fname2 = confile('
|
12
|
+
fname1 = confile('processed.html')
|
13
|
+
fname2 = confile('review.html')
|
14
14
|
fname3 = confile('updated.html')
|
15
15
|
|
16
16
|
@file_index = [
|
17
|
-
["
|
18
|
-
["Updated (#{@updated.size})",
|
19
|
-
["
|
17
|
+
["Review (#{@review.size})", fname2],
|
18
|
+
["Updated (#{@updated.size})", fname3],
|
19
|
+
["Preprocessed (#{@processed.size})", fname1]
|
20
20
|
]
|
21
21
|
|
22
|
-
msg1 = "(#{@
|
23
|
-
msg2 = "(#{@
|
22
|
+
msg1 = "(#{@processed.size}) Drafts are ready to be queued."
|
23
|
+
msg2 = "(#{@review.size}) Drafts need visual review."
|
24
24
|
msg3 = "(#{@updated.size}) Drafts were Autofixed."
|
25
25
|
|
26
26
|
|
27
27
|
# Already Processed
|
28
|
-
@
|
29
|
-
generate_review_webpage(@
|
28
|
+
@processed.sort_by!{ |x| x.id }
|
29
|
+
generate_review_webpage(@processed, fname1, msg1)
|
30
30
|
|
31
31
|
# Need Review
|
32
|
-
@
|
32
|
+
@review.sort_by! do |x|
|
33
33
|
bname = bfrom(x)
|
34
34
|
[bname, x.id]
|
35
35
|
end
|
36
|
-
generate_review_webpage(@
|
36
|
+
generate_review_webpage(@review, fname2, msg2)
|
37
37
|
|
38
|
-
#
|
38
|
+
# Updated
|
39
39
|
@updated.sort_by!{ |x| bfrom(x)}
|
40
40
|
generate_review_webpage(@updated, fname3, msg3)
|
41
41
|
|
42
42
|
puts
|
43
43
|
puts
|
44
|
-
`open #{@file_index.first.last}` if @
|
44
|
+
`open #{@file_index.first.last}` if @show_results
|
45
45
|
end
|
46
46
|
|
47
47
|
def generate_review_webpage(post_info, fname, msg1='')
|
48
48
|
page = "<html><head>#{style}</head><body>"
|
49
49
|
page += page_nav
|
50
|
+
page += messages_html unless @messages.empty?
|
50
51
|
page += '<table>'
|
51
52
|
page += '<caption>'
|
52
53
|
page += "<p>***** SIMULATION RUN *****</p>" if @simulate
|
@@ -63,19 +64,28 @@ module DK
|
|
63
64
|
page += "</body></html>"
|
64
65
|
|
65
66
|
# Create directory structure and file if it doesn't exist
|
66
|
-
# FileUtils::mkdir_p File.dirname(fname) unless File.exist?(fname)
|
67
67
|
File.open(fname, 'w'){|f| f.puts page}
|
68
68
|
puts "** Updated file: #{fname} **:\n"
|
69
69
|
end
|
70
70
|
|
71
|
+
def messages_html
|
72
|
+
msgs = @messages.map { |msg| "<p class='log'>#{msg}</p>" }
|
73
|
+
"<div>#{msgs}</div>"
|
74
|
+
end
|
75
|
+
|
71
76
|
def post_image_code(post)
|
72
77
|
# Alt Sizes (0 - 6) Large to Small
|
73
78
|
count = post.photos.size
|
74
|
-
photo =
|
75
|
-
|
79
|
+
photo = post.photos.first.alt_sizes[4].url rescue image_missing
|
80
|
+
photo = image_missing if @hide_pics
|
81
|
+
from = bfrom(post)
|
82
|
+
url = 'http://' + tumblr_url(from)
|
83
|
+
# byebug unless url
|
84
|
+
res = "<td><a target='_blank' href='#{link_to_edit(post.id)}'>"
|
76
85
|
res += "<img src='#{photo}'>#{' (' + count.to_s + ')' if count > 1}</a></td>"
|
77
|
-
res += "<td><p>#{
|
78
|
-
res += "<td><p>#{post.comment.empty? ? '
|
86
|
+
res += "<td><p><a class='blog_link' href='#{url}' target='_blank'>#{from}</a></p></td>"
|
87
|
+
res += "<td><p>#{post.comment.empty? ? '' : post.comment}</p></td>"
|
88
|
+
res += "<td><p>#{post.summary.empty? ? '' : post.summary}</p></td>"
|
79
89
|
res += "<td><p>#{post.tags.empty? ? '-no tags-' : post.tags.join(', ')}</p></td>"
|
80
90
|
end
|
81
91
|
|
@@ -91,8 +101,8 @@ module DK
|
|
91
101
|
puts
|
92
102
|
puts "#{@total} drafts were retrieved."
|
93
103
|
puts "#{pad(@updated.size, @total, 1)} drafts were Autofixed."
|
94
|
-
puts "#{pad(@
|
95
|
-
puts "#{pad(@
|
104
|
+
puts "#{pad(@processed.size, @total, 1)} drafts were marked 'already processed'."
|
105
|
+
puts "#{pad(@review.size, @total, 1)} drafts require visual review."
|
96
106
|
puts '_'*40
|
97
107
|
puts
|
98
108
|
end
|
@@ -109,7 +119,8 @@ module DK
|
|
109
119
|
res = '<thead><tr>'
|
110
120
|
res += '<th>Photo</th>'
|
111
121
|
res += '<th>Source</th>'
|
112
|
-
res += '<th>
|
122
|
+
res += '<th>Comment</th>'
|
123
|
+
res += '<th>Summary</th>'
|
113
124
|
res += '<th>Tags</th>'
|
114
125
|
res += '</tr></thead>'
|
115
126
|
end
|
@@ -126,12 +137,14 @@ module DK
|
|
126
137
|
nav ul li a { display: inline-block; width: 100%; }
|
127
138
|
nav ul li:hover { background-color: rgb(43, 171, 171); }
|
128
139
|
a, a:visited { color: white; vertical-align: middle; line-height: 100px; }
|
140
|
+
a.blog_link { color: black; }
|
141
|
+
p.log { width: 100%; background-color: rgb(56, 103, 103); color: white; text-align: center; }
|
129
142
|
</style>
|
130
143
|
)
|
131
144
|
end
|
132
145
|
|
133
146
|
def image_missing
|
134
|
-
'https://
|
147
|
+
'https://image.freepik.com/free-icon/male-user-shadow_318-34042.jpg'
|
135
148
|
end
|
136
149
|
|
137
150
|
end
|
data/lib/autofixer/version.rb
CHANGED
data/lib/tumblr_autofixer.rb
CHANGED
@@ -2,179 +2,9 @@ require 'tumblr_draftking'
|
|
2
2
|
require 'yaml/store'
|
3
3
|
require 'sanitize'
|
4
4
|
require 'fileutils'
|
5
|
+
require 'byebug'
|
5
6
|
Dir[File.join(__dir__, 'autofixer', '**', '*.rb')].each {|file| require file }
|
6
|
-
require 'pry'
|
7
|
-
|
8
|
-
module DK
|
9
|
-
class Idable
|
10
|
-
C_LEN = 25
|
11
|
-
ERROR_STRING = '**'
|
12
|
-
def initialize(opts)
|
13
|
-
@config_dir = home_file('/config_md/taf/')
|
14
|
-
|
15
|
-
check_for_command(ARGV, opts)
|
16
|
-
extract_opts(opts)
|
17
|
-
|
18
|
-
@dk = DK::Client.new(dk_opts)
|
19
|
-
|
20
|
-
# Ensure my latest config files are in place.
|
21
|
-
`cp data.yml.bak #{confile('data.yml')}` if File.exist?('data.yml.bak')
|
22
|
-
`cp summary.yml #{confile('summary.yml')}` if File.exist?('summary.yml')
|
23
|
-
|
24
|
-
read_configuration
|
25
|
-
@already_processed, @need_review, @updated = [], [], []
|
26
|
-
|
27
|
-
autofixer(get_informative_posts)
|
28
|
-
@need_review = clear(@need_review) if @clear
|
29
|
-
show_results
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def read_configuration
|
35
|
-
# Ensure directory structure exists
|
36
|
-
FileUtils::makedirs @config_dir unless Dir.exist?(@config_dir)
|
37
|
-
|
38
|
-
# Ensure configuration files are present
|
39
|
-
@ystore = YAML::Store.new("#{confile('data.yml')}")
|
40
|
-
@sstore = YAML::Store.new("#{confile('summary.yml')}")
|
41
|
-
prep_user_data_files
|
42
|
-
|
43
|
-
# Cache config data
|
44
|
-
@last_tag = restore(@ystore, :last_tag)
|
45
|
-
@tag_idx = restore(@ystore, :tag_idx)
|
46
|
-
@summary = restore(@ystore, :summary)
|
47
|
-
@ignore = restore(@ystore, :ignore)
|
48
|
-
end
|
49
|
-
|
50
|
-
def check_for_command(args, opts)
|
51
|
-
show_help(args, opts)
|
52
|
-
show_version(opts)
|
53
|
-
open_results(args)
|
54
|
-
end
|
55
|
-
|
56
|
-
def confile(fname)
|
57
|
-
@config_dir + fname
|
58
|
-
end
|
59
|
-
|
60
|
-
def extract_opts(opts)
|
61
|
-
@simulate = opts.include?('-s')
|
62
|
-
@limit = opts[opts.find_index('-l') + 1].to_i rescue nil
|
63
|
-
@spliter = opts[opts.find_index('-S') + 1] rescue ' '
|
64
|
-
@prefix = opts[opts.find_index('-p') + 1] rescue ''
|
65
|
-
@postfix = opts[opts.find_index('-P') + 1] rescue ''
|
66
|
-
@showres = opts.find_index('--show')
|
67
|
-
@clear = opts.find_index('--clear')
|
68
|
-
end
|
69
|
-
|
70
|
-
def get_informative_posts
|
71
|
-
drafts = @dk.get_posts.map{|post| DK::Post.new(post)}
|
72
|
-
@total = drafts.size
|
73
|
-
drafts.select do |draft|
|
74
|
-
((@already_processed << draft) && next) if post_already_processed?(draft)
|
75
|
-
((@need_review << draft) && next) unless post_has_info?(draft)
|
76
|
-
((@need_review << draft) && next) unless post_has_trail?(draft)
|
77
|
-
true
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Post already has prefix?
|
82
|
-
def post_already_processed?(post)
|
83
|
-
summary = post.summary.chomp.strip
|
84
|
-
user_c = Sanitize.fragment(post.comment).strip
|
85
|
-
|
86
|
-
user_c.start_with?(@prefix) || summary.start_with?(@prefix)
|
87
|
-
end
|
88
|
-
|
89
|
-
# Post has a summary or tags?
|
90
|
-
def post_has_info?(post)
|
91
|
-
summary = post.summary.chomp.strip
|
92
|
-
!summary.empty? || !post.tags.empty?
|
93
|
-
end
|
94
|
-
|
95
|
-
# Do we know where it was reblogged from?
|
96
|
-
def post_has_trail?(post)
|
97
|
-
!post.trail.empty?
|
98
|
-
end
|
99
|
-
|
100
|
-
|
101
|
-
def autofixer(posts)
|
102
|
-
posts.each_with_index do |post, idx|
|
103
|
-
tags = post.tags
|
104
|
-
trail_name = post.trail.first.blog.name
|
105
|
-
post_summary = post.summary
|
106
|
-
|
107
|
-
((@need_review << post) && next) if @ignore.include?(trail_name)
|
108
|
-
if fix_from_tag(post, trail_name)
|
109
|
-
next # Successfully used a tag-index to process post
|
110
|
-
elsif commands = restore(@sstore, trail_name.to_sym)
|
111
|
-
# Has custom processing of post.summary data defined
|
112
|
-
new_comment = special_summary(post_summary, trail_name, commands)
|
113
|
-
elsif @summary.include?(trail_name)
|
114
|
-
# Use default processing of post.summary data
|
115
|
-
new_comment = special_summary(post_summary, trail_name, [])
|
116
|
-
elsif @last_tag.include?(trail_name)
|
117
|
-
# Use the last available post.tags
|
118
|
-
new_comment = autofix(tags.last, trail_name)
|
119
|
-
else
|
120
|
-
# Don't know what to do with it.
|
121
|
-
new_comment = ERROR_STRING
|
122
|
-
end
|
123
|
-
|
124
|
-
((@need_review << post) && next) if new_comment.eql?(ERROR_STRING)
|
125
|
-
|
126
|
-
success = update_post_comment(post, new_comment)
|
127
|
-
(success ? @updated : @need_review) << post
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def fix_from_tag(post, blog_name)
|
132
|
-
@tag_idx.each_with_index do |names, idx|
|
133
|
-
next unless names.include?(blog_name)
|
134
|
-
new_comment = autofix(post.tags[idx])
|
135
|
-
if new_comment.eql?(ERROR_STRING)
|
136
|
-
# No tag at the expected tag-index
|
137
|
-
@need_review << post
|
138
|
-
return false
|
139
|
-
end
|
140
|
-
success = update_post_comment(post, new_comment)
|
141
|
-
(success ? @updated : @need_review) << post
|
142
|
-
return true
|
143
|
-
end
|
144
|
-
false
|
145
|
-
end
|
146
|
-
|
147
|
-
def autofix(tag, from='')
|
148
|
-
return ERROR_STRING if tag.nil?
|
149
|
-
prefix(capitalize(tag))
|
150
|
-
end
|
151
|
-
|
152
|
-
def update_post_comment(post, comment)
|
153
|
-
post.replace_comment_with(comment)
|
154
|
-
post.save(client: @dk.client, simulate: @dk.simulate)
|
155
|
-
end
|
156
|
-
|
157
|
-
def special_summary(summary, from, commands)
|
158
|
-
return '' if summary.nil? || from.nil?
|
159
|
-
lines = summary.split("\n")
|
160
|
-
res = summary.downcase
|
161
|
-
b = binding
|
162
|
-
commands.each{ |x| eval(x, b) }
|
163
|
-
prefix(capitalize(res))
|
164
|
-
end
|
165
|
-
|
166
|
-
def clear(posts)
|
167
|
-
error = []
|
168
|
-
posts.each do |post|
|
169
|
-
success = update_post_comment(post, @prefix)
|
170
|
-
(success ? @updated : error) << post
|
171
|
-
end
|
172
|
-
error
|
173
|
-
end
|
174
|
-
|
175
|
-
end # end of DK::Idable
|
176
|
-
end # end of DK
|
177
7
|
|
178
8
|
if __FILE__ == $0
|
179
|
-
DK::
|
9
|
+
DK::Autofixer.new(ARGV)
|
180
10
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tumblr_autofixer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Meissa Dia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tumblr_draftking
|
@@ -48,11 +48,17 @@ extra_rdoc_files: []
|
|
48
48
|
files:
|
49
49
|
- README.md
|
50
50
|
- bin/taf
|
51
|
+
- lib/autofixer/autofixer.rb
|
52
|
+
- lib/autofixer/commands/generate_tags_yml.rb
|
51
53
|
- lib/autofixer/commands/open_results.rb
|
54
|
+
- lib/autofixer/commands/show_config.rb
|
52
55
|
- lib/autofixer/commands/show_help.rb
|
53
56
|
- lib/autofixer/commands/show_version.rb
|
57
|
+
- lib/autofixer/config/view_config.html.erb
|
58
|
+
- lib/autofixer/config/view_config.rb
|
54
59
|
- lib/autofixer/data_store.rb
|
55
60
|
- lib/autofixer/helpers.rb
|
61
|
+
- lib/autofixer/patches/DK_Post.rb
|
56
62
|
- lib/autofixer/results.rb
|
57
63
|
- lib/autofixer/version.rb
|
58
64
|
- lib/tumblr_autofixer.rb
|