tumblr_autofixer 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a18737fe7b0fb91a113773ec90fbeda392143412
4
+ data.tar.gz: 970f4f5303a3137a2df386d7615b290494d09ecc
5
+ SHA512:
6
+ metadata.gz: c94e3ff20eab1b4d230b26fd90ffe419ff14344d2363b57b2216561ba4baaca3ecc95e63e36eb58b66da3ed5c3c8c4862647cc40efff3f12bf83251527e2659b
7
+ data.tar.gz: 29217d34b0bb4157ef8bdff68368ec3b69724a472817bebe5a88651a71a420dc4511e670f2c514cd7a02968068bcd604d9e2460ea8f30ca576d5858c8a06d2a6
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # About
2
+ \- tumblr_autofix is a configurable comment generator for Tumblr.
3
+ \- Two configuration files are created in your home directory: taf_data.yml & taf_summary.yml
4
+ \- Careful when editing configuration files, as with all YAML files, indentation is crucial!
5
+
6
+ # Using ~/config_md/taf/data.yml
7
+ no_names [Array] - Blogs listed here will be ignored during processing
8
+ summary [Array] - Will apply capitalization, add prefix and postfix strings
9
+ last_tag [Array] - Use the last available tag as your comment
10
+ tag_idx [[Array]] - Indicated which tag to use as the new comment
11
+ - Blogs listed in the first tag_idx[0] will use the first tag
12
+ - Blogs listed in tag_idx[1] will use the second
13
+
14
+
15
+ # Using ~/config_md/taf/summary.yml
16
+ ## Available variables
17
+ \- `summary` - the plain text of the current post's caption
18
+ \- `res` - lower case version of summary, useful for simplified text searching
19
+ \- `from` - the blog name of the user you reblogged the post from
20
+ \- `lines` - original summary text, split into lines
21
+
22
+ ## Returning
23
+ \- using `return <value>` in your summary.yml will make that string your new comment
24
+ \- storing your new comment in the `res` variable, without explicitly returning it, will subject it to a couple more modifications:
25
+ 1. capitalization - each word in the string will be capitalized
26
+ 2. prefix - a string passed via the `-p <PREFIX>` option will be prepended to `res`
27
+ 3. postfix - a string passed via the `-P <POSTFIX>` option will be appended to `res`
28
+
29
+ ## Summary Example
30
+
31
+ ### Get the title from the first line, then add the author
32
+ Update ~/config_md/taf/summary.yml with the following
33
+ ```
34
+ :angulargeometry:
35
+ - title = summary.split("\n")[0]
36
+ - return "#{title} by Angular Geometry"
37
+ ```
38
+
39
+ ### Add prefix & postfix to formatted strings
40
+ 1 - Update ~/config_md/taf/summary.yml
41
+ note: string must be stored in the `res` variable for pre/postfixing to work
42
+ ```
43
+ :kazu721010:
44
+ - title, architect = lines[0].split('/')
45
+ - photographer = lines[2].split("©").last
46
+ - res = "project: #{title}\narchitect: #{architect}\nphotographer: #{photographer}"
47
+ ```
48
+ 2 - Run Autofixer with options: `taf -p '**\n' -P '\n--'`
49
+
50
+
51
+ 3 - Resulting caption for kazu721010 posts:
52
+ ```
53
+ **
54
+ Project: Project Title
55
+ Architect: Architect Or Firm Name
56
+ Photographer: Photographers Name
57
+ --
58
+ ```
data/bin/taf ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'tumblr_draftking'
4
+ require_relative '../lib/tumblr_autofixer'
5
+ # require File.join(Dir.home, '/coding/ruby/tumblr_autofixer/lib/tumblr_autofixer') # DEV ONLY - Run development source using system installed cli
6
+
7
+ DK::Idable.new(ARGV)
@@ -0,0 +1,14 @@
1
+ module DK
2
+ class Idable
3
+ def open_results(args)
4
+ return unless args.include?('open')
5
+ file = confile('needs_review.html')
6
+ `open #{file}` && exit(0) if File.exist?(file)
7
+ puts
8
+ puts 'Error:'
9
+ puts ' No results have been generated yet.'
10
+ puts
11
+ exit(0)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ module DK
2
+ class Idable
3
+ def show_help(args, opts)
4
+ return unless (args.include?('help') || opts.find_index('-h'))
5
+ puts 'Usage: '
6
+ puts ' $ taf <command?> [options?]'
7
+ puts
8
+ puts ' Commands:'
9
+ puts ' help Show this menu.'
10
+ puts ' show Open a webpage with the latest taf results.'
11
+ puts
12
+ puts ' Options:'
13
+ puts ' -s Simulate Run (no changes saved)'
14
+ puts ' -p [STRING] Prefix for generated comments'
15
+ puts ' -P [STRING] Prefix for generated comments'
16
+ puts ' -S [STRING] Separator used between prefix/postfix and generated comment text.'
17
+ puts ' -l [INTEGER] Number of Drafts to select for processing.'
18
+ puts ' --clear Clear unprocessible Drafts by adding the given prefix (-p [STRING])'
19
+ puts ' causing these posts to show as "Already Processed" in future runs.'
20
+ puts ' --show Open the results webpage after processing is complete.'
21
+ exit(0)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ module DK
2
+ class Idable
3
+ def show_version(opts)
4
+ return unless opts.include?('-v')
5
+ puts "\ntumblr_autofixer v#{VERSION}"
6
+ puts
7
+ exit(0)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,46 @@
1
+ module DK
2
+ class Idable
3
+ private
4
+
5
+ def store(dstore, key, value)
6
+ dstore.transaction do
7
+ dstore[key] = value
8
+ end
9
+ end
10
+
11
+ def restore(dstore, key, default=nil)
12
+ dstore.transaction do
13
+ dstore[key] || default
14
+ end
15
+ end
16
+
17
+ def prep_user_data_files
18
+ ex_blog_name = 'example-blog-name'
19
+ keys = [:no_names, :last_tag, :tag_idx, :summary]
20
+ keys.each do |key|
21
+ unless restore(@ystore, key)
22
+ value = []
23
+ case key
24
+ when :no_names
25
+ value << 'Ignore the following blogs during processing.'
26
+ value << ex_blog_name
27
+ when :last_tag
28
+ value << 'Use the last available tag for these blogs.'
29
+ value << ex_blog_name
30
+ when :tag_idx
31
+ value = [
32
+ ['Use tag #1 for these blogs.', ex_blog_name],
33
+ ['Use tag #2 for these blogs.', ex_blog_name],
34
+ ['Use tag #3 for these blogs.', ex_blog_name]
35
+ ]
36
+ when :summary
37
+ value << 'Capitalize, add prefix and postfix to existing summary text'
38
+ value << ex_blog_name
39
+ end
40
+ store(@ystore, key, value)
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,41 @@
1
+ module DK
2
+ class Idable
3
+ private
4
+
5
+ def dk_opts
6
+ { simulate: @simulate, limit: @limit }
7
+ end
8
+
9
+ def capitalize(s)
10
+ return if s.nil?
11
+ res = s.gsub(/\d/,'').split(' ').map(&:strip).map(&:capitalize)
12
+ return res[0] if res.size < 2
13
+ res.join(' ')
14
+ end
15
+
16
+ def prefix(s)
17
+ "#{@prefix}#{' ' + @spliter + ' ' if @spliter}#{s}#{@postfix}"
18
+ end
19
+
20
+ def link_to_edit(post)
21
+ id = post.id rescue post['id']
22
+ "https://www.tumblr.com/edit/#{id}"
23
+ end
24
+
25
+ def pad(value, reference, prefix=nil)
26
+ s = value.to_s
27
+ r = reference.to_s.length
28
+ if prefix
29
+ s = ' ' + s while (s.length < r)
30
+ else
31
+ s += ' ' while (s.length < r)
32
+ end
33
+ s
34
+ end
35
+
36
+ def home_file(file)
37
+ DK::Config.home_path_file(file)
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,134 @@
1
+ module DK
2
+ class Idable
3
+ private
4
+
5
+ def bfrom(post)
6
+ post.trail.first.blog.name rescue '-no trail-'
7
+ end
8
+
9
+ def show_results
10
+ cli_header
11
+
12
+ fname1 = confile('already_processed.html')
13
+ fname2 = confile('need_review.html')
14
+ fname3 = confile('updated.html')
15
+
16
+ @file_index = [
17
+ ["Needs Review (#{@need_review.size})", fname2],
18
+ ["Updated (#{@updated.size})", fname3],
19
+ ["Already Processed (#{@already_processed.size})", fname1]
20
+ ]
21
+
22
+ msg1 = "(#{@already_processed.size}) Drafts are ready to be queued."
23
+ msg2 = "(#{@need_review.size}) Drafts need visual review."
24
+ msg3 = "(#{@updated.size}) Drafts were Autofixed."
25
+
26
+
27
+ # Already Processed
28
+ @already_processed.sort_by!{ |x| x.id }
29
+ generate_review_webpage(@already_processed, fname1, msg1)
30
+
31
+ # Need Review
32
+ @need_review.sort_by! do |x|
33
+ bname = bfrom(x)
34
+ [bname, x.id]
35
+ end
36
+ generate_review_webpage(@need_review, fname2, msg2)
37
+
38
+ # updated
39
+ @updated.sort_by!{ |x| bfrom(x)}
40
+ generate_review_webpage(@updated, fname3, msg3)
41
+
42
+ puts
43
+ puts
44
+ `open #{@file_index.first.last}` if @showres
45
+ end
46
+
47
+ def generate_review_webpage(post_info, fname, msg1='')
48
+ page = "<html><head>#{style}</head><body>"
49
+ page += page_nav
50
+ page += '<table>'
51
+ page += '<caption>'
52
+ page += "<p>***** SIMULATION RUN *****</p>" if @simulate
53
+ page += "<p>#{msg1}</p>"
54
+ page += "<p>Click a photo to be taken to it's edit page.</p>"
55
+ page += '</caption>'
56
+ page += table_header
57
+ post_info.each_slice(1) do |posts|
58
+ page += '<tr>'
59
+ posts.each{|post| page += post_image_code(post)}
60
+ page += '</tr>'
61
+ end
62
+ page += '</table>'
63
+ page += "</body></html>"
64
+
65
+ # Create directory structure and file if it doesn't exist
66
+ # FileUtils::mkdir_p File.dirname(fname) unless File.exist?(fname)
67
+ File.open(fname, 'w'){|f| f.puts page}
68
+ puts "** Updated file: #{fname} **:\n"
69
+ end
70
+
71
+ def post_image_code(post)
72
+ # Alt Sizes (0 - 6) Large to Small
73
+ photo = post.photos.first.alt_sizes[4].url
74
+ count = post.photos.size
75
+ res = "<td><a target='_blank' href='#{link_to_edit(post)}'>"
76
+ res += "<img src='#{photo}'>#{' (' + count.to_s + ')' if count > 1}</a></td>"
77
+ res += "<td><p>#{bfrom(post)}</p></td>"
78
+ res += "<td><p>#{post.comment.empty? ? '-no comment-' : post.comment}</p></td>"
79
+ res += "<td><p>#{post.tags.empty? ? '-no tags-' : post.tags.join(', ')}</p></td>"
80
+ end
81
+
82
+ def cli_header
83
+ puts ' '*80 + "\r\n" # Clear any lingering text
84
+ if @simulate
85
+ puts '*'*40
86
+ puts '*'*14 + ' SIMULATION ' + '*'*14
87
+ puts '*'*40
88
+ puts
89
+ end
90
+ puts '_'*40
91
+ puts
92
+ puts "#{@total} drafts were retrieved."
93
+ puts "#{pad(@updated.size, @total, 1)} drafts were Autofixed."
94
+ puts "#{pad(@already_processed.size, @total, 1)} drafts were marked 'already processed'."
95
+ puts "#{pad(@need_review.size, @total, 1)} drafts require visual review."
96
+ puts '_'*40
97
+ puts
98
+ end
99
+
100
+ def page_nav
101
+ res = '<nav><ul>'
102
+ @file_index.each do |text, file|
103
+ res += %(<li><a href='#{file}'>#{text}</a></li>)
104
+ end
105
+ res += '</ul></nav>'
106
+ end
107
+
108
+ def table_header
109
+ res = '<thead><tr>'
110
+ res += '<th>Photo</th>'
111
+ res += '<th>Source</th>'
112
+ res += '<th>Caption</th>'
113
+ res += '<th>Tags</th>'
114
+ res += '</tr></thead>'
115
+ end
116
+
117
+ def style
118
+ %q(
119
+ <style>
120
+ table, tr, nav { width: 100%; text-align: center; vertical-align: middle; }
121
+ th { background-color: grey; border: 1px solid black; color: white; }
122
+ td { width: 25%; border: 1px solid gainsboro; }
123
+ table caption { background-color: rgb(43, 171, 171); }
124
+ nav { height: 100px; background-color: black; color: white; }
125
+ nav ul li { display: inline-block; width: 30%}
126
+ nav ul li a { display: inline-block; width: 100%; }
127
+ nav ul li:hover { background-color: rgb(43, 171, 171); }
128
+ a, a:visited { color: white; vertical-align: middle; line-height: 100px; }
129
+ </style>
130
+ )
131
+ end
132
+
133
+ end
134
+ end
@@ -0,0 +1,5 @@
1
+ module DK
2
+ class Idable
3
+ VERSION = '0.0.1'
4
+ end
5
+ end
@@ -0,0 +1,179 @@
1
+ require 'tumblr_draftking'
2
+ require 'yaml/store'
3
+ require 'sanitize'
4
+ require 'fileutils'
5
+ 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
+ check_for_command(ARGV, opts)
14
+ extract_opts(opts)
15
+
16
+ @config_dir = home_file('/config_md/taf/')
17
+ @dk = DK::Client.new(dk_opts)
18
+
19
+ # Ensure my latest config files are in place.
20
+ `cp data.yml.bak #{confile('data.yml')}` if File.exist?('data.yml.bak')
21
+ `cp summary.yml #{confile('summary.yml')}` if File.exist?('summary.yml')
22
+
23
+ read_configuration
24
+ @already_processed, @need_review, @updated = [], [], []
25
+
26
+ autofixer(get_informative_posts)
27
+ @need_review = clear(@need_review) if @clear
28
+ show_results
29
+ end
30
+
31
+ private
32
+
33
+ def read_configuration
34
+ # Ensure directory structure exists
35
+ FileUtils::makedirs @config_dir unless Dir.exist?(@config_dir)
36
+
37
+ # Ensure configuration files are present
38
+ @ystore = YAML::Store.new("#{confile('data.yml')}")
39
+ @sstore = YAML::Store.new("#{confile('summary.yml')}")
40
+ prep_user_data_files
41
+
42
+ # Cache config data
43
+ @last_tag = restore(@ystore, :last_tag)
44
+ @tag_idx = restore(@ystore, :tag_idx)
45
+ @summary = restore(@ystore, :summary)
46
+ @ignore = restore(@ystore, :ignore)
47
+ end
48
+
49
+ def check_for_command(args, opts)
50
+ show_help(args, opts)
51
+ show_version(opts)
52
+ open_results(args)
53
+ end
54
+
55
+ def confile(fname)
56
+ @config_dir + fname
57
+ end
58
+
59
+ def extract_opts(opts)
60
+ @simulate = opts.include?('-s')
61
+ @limit = opts[opts.find_index('-l') + 1].to_i rescue nil
62
+ @spliter = opts[opts.find_index('-S') + 1] rescue ' '
63
+ @prefix = opts[opts.find_index('-p') + 1] rescue ''
64
+ @postfix = opts[opts.find_index('-P') + 1] rescue ''
65
+ @showres = opts.find_index('--show')
66
+ @clear = opts.find_index('--clear')
67
+ end
68
+
69
+ def get_informative_posts
70
+ drafts = @dk.get_posts.map{|post| DK::Post.new(post)}
71
+ @total = drafts.size
72
+ drafts.select do |draft|
73
+ ((@already_processed << draft) && next) if post_already_processed?(draft)
74
+ ((@need_review << draft) && next) unless post_has_info?(draft)
75
+ ((@need_review << draft) && next) unless post_has_trail?(draft)
76
+ true
77
+ end
78
+ end
79
+
80
+ # Post already has prefix?
81
+ def post_already_processed?(post)
82
+ summary = post.summary.chomp.strip
83
+ user_c = Sanitize.fragment(post.comment).strip
84
+
85
+ user_c.start_with?(@prefix) || summary.start_with?(@prefix)
86
+ end
87
+
88
+ # Post has a summary or tags?
89
+ def post_has_info?(post)
90
+ summary = post.summary.chomp.strip
91
+ !summary.empty? || !post.tags.empty?
92
+ end
93
+
94
+ # Do we know where it was reblogged from?
95
+ def post_has_trail?(post)
96
+ !post.trail.empty?
97
+ end
98
+
99
+
100
+ def autofixer(posts)
101
+ posts.each_with_index do |post, idx|
102
+ tags = post.tags
103
+ trail_name = post.trail.first.blog.name
104
+ post_summary = post.summary
105
+
106
+ ((@need_review << post) && next) if @ignore.include?(trail_name)
107
+ if fix_from_tag(post, trail_name)
108
+ next # Successfully used a tag-index to process post
109
+ elsif commands = restore(@sstore, trail_name.to_sym)
110
+ # Has custom processing of post.summary data defined
111
+ new_comment = special_summary(post_summary, trail_name, commands)
112
+ elsif @summary.include?(trail_name)
113
+ # Use default processing of post.summary data
114
+ new_comment = special_summary(post_summary, trail_name, [])
115
+ elsif @last_tag.include?(trail_name)
116
+ # Use the last available post.tags
117
+ new_comment = autofix(tags.last, trail_name)
118
+ else
119
+ # Don't know what to do with it.
120
+ new_comment = ERROR_STRING
121
+ end
122
+
123
+ ((@need_review << post) && next) if new_comment.eql?(ERROR_STRING)
124
+
125
+ success = update_post_comment(post, new_comment)
126
+ (success ? @updated : @need_review) << post
127
+ end
128
+ end
129
+
130
+ def fix_from_tag(post, blog_name)
131
+ @tag_idx.each_with_index do |names, idx|
132
+ next unless names.include?(blog_name)
133
+ new_comment = autofix(post.tags[idx])
134
+ if new_comment.eql?(ERROR_STRING)
135
+ # No tag at the expected tag-index
136
+ @need_review << post
137
+ return false
138
+ end
139
+ success = update_post_comment(post, new_comment)
140
+ (success ? @updated : @need_review) << post
141
+ return true
142
+ end
143
+ false
144
+ end
145
+
146
+ def autofix(tag, from='')
147
+ return ERROR_STRING if tag.nil?
148
+ prefix(capitalize(tag))
149
+ end
150
+
151
+ def update_post_comment(post, comment)
152
+ post.replace_comment_with(comment)
153
+ post.save(client: @dk.client, simulate: @dk.simulate)
154
+ end
155
+
156
+ def special_summary(summary, from, commands)
157
+ return '' if summary.nil? || from.nil?
158
+ lines = summary.split("\n")
159
+ res = summary.downcase
160
+ b = binding
161
+ commands.each{ |x| eval(x, b) }
162
+ prefix(capitalize(res))
163
+ end
164
+
165
+ def clear(posts)
166
+ error = []
167
+ posts.each do |post|
168
+ success = update_post_comment(post, @prefix)
169
+ (success ? @updated : error) << post
170
+ end
171
+ error
172
+ end
173
+
174
+ end # end of DK::Idable
175
+ end # end of DK
176
+
177
+ if __FILE__ == $0
178
+ DK::Idable.new(ARGV)
179
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tumblr_autofixer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Meissa Dia
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: tumblr_draftking
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sanitize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 4.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 4.5.0
41
+ description: "\n Customizable automated comment generator!\n "
42
+ email:
43
+ - meissadia@gmail.com
44
+ executables:
45
+ - taf
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - README.md
50
+ - bin/taf
51
+ - lib/autofixer/commands/open_results.rb
52
+ - lib/autofixer/commands/show_help.rb
53
+ - lib/autofixer/commands/show_version.rb
54
+ - lib/autofixer/data_store.rb
55
+ - lib/autofixer/helpers.rb
56
+ - lib/autofixer/results.rb
57
+ - lib/autofixer/version.rb
58
+ - lib/tumblr_autofixer.rb
59
+ homepage: https://github.com/meissadia/tumblr_autofixer
60
+ licenses:
61
+ - Apache-2.0
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 2.1.0
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.6.10
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Customizable automated comment generator.
83
+ test_files: []