confluence_helper 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: 871a0cbe9392a85d9fbcc1dbee5d85ccad98f8da
4
+ data.tar.gz: 1089c0962a376f79dc98dfb6d2b7d4c8ee930e56
5
+ SHA512:
6
+ metadata.gz: 51355352fd4557663437a81280ce8ded2507b538b282df80699c60a264a5b54a35caead2d117fa90f3684c6009422725ff4dec7368e1acfddca4e5619d99d0d1
7
+ data.tar.gz: 4d8414608b8f4be1d5af6563ac8b87077cd2cb48a16ba0122b791c34238dac19f612decba21a6321cde889b0a352df1e26d7aab1a05575797b979a3e163b1c38
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in confluence_helper.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Nigel Thorne
2
+
3
+ MIT License
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.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # ConfluenceHelper
2
+
3
+ Confluence Helper wraps up some conflience API operations.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'confluence_helper'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install confluence_helper
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/confluence_helper/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'confluence_helper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "confluence_helper"
8
+ spec.version = ConfluenceHelper::VERSION
9
+ spec.authors = ["Nigel Thorne"]
10
+ spec.email = ["github@nigelthorne.com"]
11
+ spec.summary = %q{Helper for accessing data from within your Confluence wiki}
12
+ spec.description = %q{I needed to pull data from Confluence for several internal web services. This is intended to pull together all helper logic I need to get the data I want.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_runtime_dependency "nokogiri", "~> 1.6.4"
24
+ spec.add_runtime_dependency "envied", "~> 0.8.1"
25
+ end
@@ -0,0 +1,220 @@
1
+ require "confluence_helper/version"
2
+
3
+ module ConfluenceHelper
4
+
5
+ class HtmlTable
6
+ def initialize(node)
7
+ @node = node
8
+ end
9
+
10
+ def has_columns?(columns:)
11
+ column_names.sort == columns.sort
12
+ end
13
+
14
+ def column_names
15
+ @column_names ||= @node.xpath('.//tr/th').map{|n| n.text.strip}
16
+ end
17
+
18
+ def data
19
+ @data ||=
20
+ @node
21
+ .xpath('.//tr')
22
+ .map{|r| r.xpath('.//td').map{|cell| cell_value(cell)} }
23
+ .reject{|r| r.empty? }
24
+ .map{|r| column_names
25
+ .each
26
+ .with_index
27
+ .with_object({}){ |(c,i),o| o[c] = r[i] }
28
+ }
29
+ end
30
+
31
+ private
32
+
33
+ def cell_value(cell)
34
+ (cell.xpath(".//a").empty? ? cell.text : cell.inner_html).gsub("\u00C2", " ").gsub("\u00A0", " ").strip
35
+ end
36
+ end
37
+
38
+
39
+ class Confluence
40
+
41
+ def get_labels_for_each_child_page(rootpageid)
42
+ child_pages_in_space(rootpageid, {:expand => "metadata.labels"} ).
43
+ each_with_object({}) do |page, hash|
44
+ hash[page["title"]] =
45
+ page.
46
+ fetch("metadata", {}).
47
+ fetch("labels",{}).
48
+ fetch("results",[]).
49
+ map{|l| l["name"]}
50
+ end
51
+ end
52
+
53
+ def find_url_by_title_and_space(spacekey, title)
54
+ page_by_title_in_space(spacekey, title, {})["_links"]["self"]
55
+ end
56
+
57
+ def save_page_attachment( spacekey, page_title, attachment_name, destination )
58
+ response = query_rest_api( get_attachment_url( spacekey, page_title, attachment_name ) )
59
+ File.open(destination, 'wb') { |fp| fp.write(response.body) }
60
+ end
61
+
62
+ def deliverables_pages(rootpageid)
63
+ child_pages_in_space(rootpageid, {:expand => "metadata.labels,body.export_view"} ).
64
+ each_with_object({}) do |page, hash|
65
+ hash[page["title"]] = DeliverablePage.new(
66
+ labels: page.fetch("metadata", {}).fetch("labels", {}).fetch("results",[]).map{|l| l["name"]},
67
+ body: page.fetch("body", {}).fetch("export_view", {}).fetch("value", "")
68
+ )
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ @@url = {}
75
+
76
+ class DeliverablePage
77
+ def initialize(labels:, body:)
78
+ @node = Nokogiri::HTML(body)
79
+ end
80
+
81
+ def tables
82
+ @tables ||= @node.xpath('//table').map{|t| HtmlTable.new(t) }
83
+ end
84
+
85
+ def deliverables
86
+ tables.select{|t| is_deliverables_table? t } .map{|table| table.data }.flatten
87
+ end
88
+
89
+ #Name DHFR Status Location Comments
90
+ def is_deliverables_table?(table)
91
+ table.has_columns? columns: %w{Name DHFR Status Location Comments}
92
+ end
93
+
94
+ end
95
+
96
+ def get_attachment_url(spacekey, page_title, attachment_name)
97
+ "#{ENVied.CONSTASH_URL}#{ get_attachment_data(spacekey, page_title, attachment_name)["_links"]["download"]}"
98
+ end
99
+
100
+ def get_attachment_data(spacekey, page_title, attachment_name)
101
+ get_attachments_data(spacekey, page_title).find{|x| x["title"] == attachment_name}
102
+ end
103
+
104
+ def get_attachments_data(spacekey, page_title)
105
+ page_by_title_in_space(spacekey, page_title, {expand:"children.attachment"})["children"]["attachment"]["results"]
106
+ end
107
+
108
+ def page_by_title_in_space(spacekey, page_title, options)
109
+ all_pages = pages_in_space(spacekey, options).lazy
110
+ all_pages.find {|p| p['title'] == page_title}.
111
+ tap{|page| raise "Can't find page with title #{page_title} in that space #{spacekey}\n\tFound pages: #{all_pages.map{|p| p['title']}.join("\n\t")}" unless page }
112
+ end
113
+
114
+ def pages_in_space(spacekey, options)
115
+ enum_for(:for_all_pages_of_results, "rest/api/space/#{spacekey}/content/page", options)
116
+ end
117
+
118
+ def child_pages_in_space(pageid, options)
119
+ enum_for(:for_all_pages_of_results, "rest/api/content/#{pageid}/child/page", options)
120
+ end
121
+
122
+ def for_all_pages_of_results(url, options, &block)
123
+ full_options = {start:0, limit:25}.merge(options)
124
+ response = query_rest_api(url, full_options)
125
+ if response && response.success?
126
+ results = response.body.fetch('results',[])
127
+ results.each{ |p| block.call(p) }
128
+ if(results.count == full_options[:limit])
129
+ start = full_options[:start] + results.count
130
+ for_all_pages_of_results(url, options.merge({start:start}), &block)
131
+ end
132
+ end
133
+ end
134
+
135
+ def get_logged_in_connection(request = :json)
136
+ # TODO: move to memcache
137
+ # store = ActiveSupport::Cache.lookup_store(:mem_cache_store, ['localhost:11211'])
138
+
139
+ return Faraday.new(:url => ENVied.CONSTASH_URL) do |faraday|
140
+ faraday.use :http_cache # , store: store
141
+ faraday.request :url_encoded # form-encode POST params
142
+ faraday.basic_auth(ENVied.CONSTASH_USERNAME, ENVied.CONSTASH_PASSWORD)
143
+ faraday.request request
144
+
145
+ faraday.response :json, :content_type => /\bjson$/
146
+ # faraday.response :logger # log requests to STDOUT
147
+
148
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
149
+ end
150
+ end
151
+
152
+ def query_rest_api(url, options = {})
153
+ puts "-->#{url} #{options.inspect}"
154
+ get_logged_in_connection().
155
+ get(url, options).
156
+ tap{ |response|
157
+ raise "Error while attempting to query '#{ENVied.CONSTASH_URL}/#{url}'\n Status: #{response.status} \n #{response.body}" unless [200, 302].include? response.status
158
+ }
159
+ end
160
+
161
+ def get_url(space, title)
162
+ @@url[ [space,title] ] ||= find_url_by_title_and_space(space, title)
163
+ end
164
+ end
165
+
166
+ class WikiPage < Confluence
167
+
168
+ def initialize(spacekey, title)
169
+ @spacekey, @title = spacekey, title
170
+ end
171
+
172
+ def to_nodes
173
+ parse_wiki_table(doc)
174
+ end
175
+
176
+ def attachment(title)
177
+ page = query_rest_api( url , {expand:"children.attachment"})
178
+ results = page.body["children"]["attachment"]["results"]
179
+ result = results.find{|x| x["title"] == title}
180
+ attachment_url = "#{ENVied.CONSTASH_URL}#{result["_links"]["download"]}"
181
+ query_rest_api(attachment_url, options = {}).body
182
+ end
183
+
184
+ private
185
+
186
+ def url
187
+ @url ||= get_url(@spacekey, @title)
188
+ end
189
+
190
+ def doc
191
+ @doc ||= get_page_body()
192
+ end
193
+
194
+ def get_page_body()
195
+ page = query_rest_api( url , {expand:"body.export_view"} )
196
+ return Nokogiri::HTML( page.body["body"]["export_view"]["value"] )
197
+ end
198
+
199
+
200
+ def parse_wiki_table(doc)
201
+ rows = doc.xpath("//table/tbody/tr")
202
+ headers = rows.xpath("th").map{|n| n.content}
203
+ rows = rows - rows.xpath("th/..")
204
+ documents = rows.map{ | row | row_to_hash(row, headers) } #convert to hashes
205
+ documents.each_with_object({}){|doc, o| o[doc["ID"].to_i] = doc } # index by id
206
+ end
207
+
208
+ def row_to_hash(row, headers)
209
+ row.xpath( "td" ).
210
+ to_a.
211
+ each.
212
+ with_index.
213
+ with_object( {} ) { | (cell , index) , row_hash |
214
+ row_hash[ headers[ index ] ] = cell.content.gsub( /\u00A0/,"" )
215
+ }
216
+ end
217
+
218
+ end
219
+
220
+ end
@@ -0,0 +1,3 @@
1
+ module ConfluenceHelper
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: confluence_helper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Nigel Thorne
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.6.4
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.6.4
55
+ - !ruby/object:Gem::Dependency
56
+ name: envied
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.1
69
+ description: I needed to pull data from Confluence for several internal web services.
70
+ This is intended to pull together all helper logic I need to get the data I want.
71
+ email:
72
+ - github@nigelthorne.com
73
+ executables: []
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - confluence_helper.gemspec
83
+ - lib/confluence_helper.rb
84
+ - lib/confluence_helper/version.rb
85
+ homepage: ''
86
+ licenses:
87
+ - MIT
88
+ metadata: {}
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 2.4.2
106
+ signing_key:
107
+ specification_version: 4
108
+ summary: Helper for accessing data from within your Confluence wiki
109
+ test_files: []