gliffy 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,25 @@
1
+ Gliffy API wrapper
2
+ ==================
3
+
4
+ Basic usage
5
+ -----------
6
+
7
+ ### Initialization
8
+
9
+ api = Gliffy::API.new(ACCOUNT_ID, API_KEY, API_SECRET)
10
+ api.impersonate('user@domain.com')
11
+ api.account.root.documents
12
+
13
+ ### Working with documents
14
+
15
+ doc = account.document(DOCUMENT_ID)
16
+ doc.name
17
+ doc.editor(RETURN_TO, RETURN_BUTTON_TEXT)
18
+ doc.png.full
19
+
20
+ ### Navigating folders
21
+
22
+ root = account.root
23
+ root.folders[0].documents
24
+ root.folders[1].name
25
+ root.folders[1].path
data/lib/gliffy.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'date'
2
+
3
+ require 'gliffy/api'
4
+ require 'gliffy/api/facade'
5
+ require 'gliffy/api/response'
6
+ require 'gliffy/account'
7
+ require 'gliffy/document'
8
+ require 'gliffy/document_png'
9
+ require 'gliffy/folder'
10
+
11
+ require 'gliffy/oauth/helper'
12
+
13
+ module Gliffy
14
+ class << self
15
+ def default_application_name
16
+ "Gliffy Ruby Gem"
17
+ end
18
+
19
+ # some calls (e.g. OAuth token generation) should be done through
20
+ # secure HTTPS; other calls (e.g. actions performed by
21
+ # non-privileged accounts) should be done though plain HTTP
22
+ #
23
+ # We're using protocol-relative URL here.
24
+ def api_root
25
+ '//www.gliffy.com/api/1.0'
26
+ end
27
+
28
+ # We're using protocol-relative (//hosrname/path/ format) URL here.
29
+ def web_root
30
+ '//www.gliffy.com'
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,59 @@
1
+ module Gliffy
2
+ class Account
3
+ TYPE_BUSINESS = "Business"
4
+
5
+ attr_reader :api
6
+ attr_reader :id
7
+ attr_reader :name
8
+ attr_reader :max_users, :type, :terms_accepted
9
+ attr_reader :expiration_date
10
+
11
+ def self.load(api, response)
12
+ Gliffy::Account.new(
13
+ api,
14
+ :id => response.integer('//g:account/@id'),
15
+ :name => response.string('//g:account/g:name'),
16
+ :max_users => response.integer('//g:account/@max-users'),
17
+ :type => response.string('//g:account/@account-type'),
18
+ :terms_accepted => response.string('//g:account/@terms') == "true",
19
+ :expiration_date => response.timestamp('//g:account/g:expiration-date')
20
+ )
21
+ end
22
+
23
+ def root
24
+ @root ||= load_root
25
+ end
26
+
27
+ def document(document_id)
28
+ response = api.get("/accounts/#{id}/documents/#{document_id}/meta-data.xml",
29
+ :action => 'get')
30
+
31
+ Gliffy::Document.load(
32
+ self,
33
+ response.node('//g:document')
34
+ )
35
+ end
36
+
37
+ private
38
+
39
+ def initialize(api, params)
40
+ @api = api
41
+
42
+ @id = params[:id]
43
+ @name = params[:name]
44
+ @max_users = params[:max_users]
45
+ @type = params[:type]
46
+ @terms_accepted = params[:terms_accepted]
47
+ @expiration_date = params[:expiration_date]
48
+ end
49
+
50
+ def load_root
51
+ response = api.get_folders(id)
52
+
53
+ Gliffy::Folder.load(
54
+ self,
55
+ response.node("/g:response/g:folders/g:folder")
56
+ )
57
+ end
58
+ end
59
+ end
data/lib/gliffy/api.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'uri'
2
+ require 'oauth'
3
+ require 'nokogiri'
4
+ require 'cgi'
5
+
6
+ module Gliffy
7
+ class API
8
+ attr_reader :consumer
9
+ attr_reader :account_id
10
+ attr_accessor :application_name
11
+
12
+ def initialize(account_id, key, secret)
13
+ @consumer = init_consumer(key, secret)
14
+ @account_id = account_id
15
+ @application_name = Gliffy.default_application_name
16
+ end
17
+
18
+ def plain
19
+ Gliffy::API::Facade.http(self)
20
+ end
21
+
22
+ def secure
23
+ Gliffy::API::Facade.https(self)
24
+ end
25
+
26
+ def get(url, params = {})
27
+ Gliffy::API::Response.new(Nokogiri.XML(raw(url, params)))
28
+ end
29
+
30
+ def raw(url, params = {})
31
+ r = token.get(url + '?' + query(params))
32
+ r.body
33
+ end
34
+
35
+ def post(url, params)
36
+ r = token.post(url, params)
37
+ Gliffy::API::Response.new(Nokogiri.XML(r.body))
38
+ end
39
+
40
+ def web(url, params)
41
+ consumer.create_signed_request(
42
+ :get,
43
+ url + '?' + query(params),
44
+ token
45
+ ).path
46
+ end
47
+
48
+ def account
49
+ @account ||= load_account
50
+ end
51
+
52
+ def impersonate(user)
53
+ escaped_id = URI.escape @account_id.to_s
54
+ escaped_user = URI.escape user
55
+
56
+ response = secure.post(
57
+ "/accounts/#{escaped_id}/users/#{escaped_user}/oauth_token.xml",
58
+ :action => 'create',
59
+ :description => application_name
60
+ )
61
+
62
+ token.token = response.string('//g:oauth-token')
63
+ token.secret = response.string('//g:oauth-token-secret')
64
+ end
65
+
66
+ private
67
+
68
+ def query(params)
69
+ params.map {|k, v| "#{CGI.escape k.to_s}=#{CGI.escape v.to_s}" }.join('&')
70
+ end
71
+
72
+ def token
73
+ @token ||= OAuth::AccessToken.new @consumer
74
+ end
75
+
76
+ def load_account
77
+ response = plain.get("/accounts/#{account_id}.xml",
78
+ { :action => 'get' })
79
+ Gliffy::Account.load(plain, response)
80
+ end
81
+
82
+ def init_consumer(key, secret)
83
+ OAuth::Consumer.new(key,
84
+ secret,
85
+ :site => Gliffy.web_root,
86
+ :scheme => :query_string)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,49 @@
1
+ module Gliffy
2
+ class API
3
+ class Facade
4
+ def self.http(api)
5
+ Facade.new("http", api)
6
+ end
7
+
8
+ def self.https(api)
9
+ Facade.new("https", api)
10
+ end
11
+
12
+ def raw(partial_url, params = {})
13
+ @api.raw(api_root + partial_url, params)
14
+ end
15
+
16
+ def get(partial_url, params)
17
+ @api.get(api_root + partial_url, params)
18
+ end
19
+
20
+ def post(partial_url, params)
21
+ @api.post(api_root + partial_url, params)
22
+ end
23
+
24
+ def web(partial_url, params)
25
+ @api.web(web_root + partial_url, params)
26
+ end
27
+
28
+ def get_folders(account_id)
29
+ get("/accounts/#{account_id}/folders.xml",
30
+ :action => 'get')
31
+ end
32
+
33
+ private
34
+
35
+ def initialize(protocol, api)
36
+ @protocol = protocol
37
+ @api = api
38
+ end
39
+
40
+ def api_root
41
+ @protocol + ":" + Gliffy.api_root
42
+ end
43
+
44
+ def web_root
45
+ @protocol + ":" + Gliffy.web_root
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,49 @@
1
+ module Gliffy
2
+ class API::Response
3
+ def initialize(base)
4
+ @base = base
5
+ end
6
+
7
+ def content
8
+ @base.content
9
+ end
10
+
11
+ def nodes(path)
12
+ @base.xpath(path, namespaces).map { |n| Gliffy::API::Response.new(n) }
13
+ end
14
+
15
+ def node(path)
16
+ Gliffy::API::Response.new(@base.at_xpath(path, namespaces))
17
+ end
18
+
19
+ def string(path)
20
+ node(path).content
21
+ end
22
+
23
+ def integer(path)
24
+ string(path).to_i
25
+ end
26
+
27
+ def timestamp(path)
28
+ parse_timestamp(string(path))
29
+ end
30
+
31
+ def exists(path)
32
+ !@base.at_xpath(path, namespaces).nil?
33
+ end
34
+
35
+ private
36
+
37
+ # Gliffy XML namespace to be used in XPath expressions
38
+ def namespaces
39
+ { "g" => "http://www.gliffy.com" }
40
+ end
41
+
42
+ # As opposed to UNIX timestamp, timestamps returned by Gliffy API
43
+ # are in milliseconds, so we should divide them by 1000 before
44
+ # converting to real datetime objectsq
45
+ def parse_timestamp(value)
46
+ Time.at(value.to_i / 1000).to_datetime
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,69 @@
1
+ module Gliffy
2
+ class Document
3
+ attr_reader :owner
4
+ attr_reader :id
5
+ attr_reader :is_public
6
+ attr_reader :versions
7
+ attr_reader :name
8
+ attr_reader :modified, :created, :published
9
+
10
+ def self.load(owner, node)
11
+ @loaded ||= {}
12
+
13
+ id = node.integer('@id')
14
+ if not @loaded.has_key? id then
15
+ @loaded[id] = Gliffy::Document.new(
16
+ owner,
17
+ id,
18
+ :is_public => node.exists('@is-public'),
19
+ :versions => node.integer('@num-versions'),
20
+ :name => node.string('g:name'),
21
+ :modified => node.timestamp('g:mod-date'),
22
+ :created => node.timestamp('g:create-date'),
23
+ :published => node.timestamp('g:published-date')
24
+ )
25
+ end
26
+
27
+ @loaded[id]
28
+ end
29
+
30
+ def self.clear_cache
31
+ @loaded = {}
32
+ end
33
+
34
+ def editor(return_url, return_text)
35
+ api.web(
36
+ "/gliffy/",
37
+ :launchDiagramId => id,
38
+ :returnURL => return_url,
39
+ :returnButtonText => return_text
40
+ )
41
+ end
42
+
43
+ def png
44
+ Document::PNG.new(self)
45
+ end
46
+
47
+ def public?
48
+ is_public
49
+ end
50
+
51
+ def api
52
+ owner.api
53
+ end
54
+
55
+ private
56
+
57
+ def initialize(owner, id, params)
58
+ @owner = owner
59
+ @id = id
60
+
61
+ @is_public = params[:is_public]
62
+ @versions = params[:versions]
63
+ @name = params[:name]
64
+ @modified = params[:modified]
65
+ @created = params[:created]
66
+ @published = params[:published]
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,56 @@
1
+ module Gliffy
2
+ class Document::PNG
3
+ attr_reader :document
4
+
5
+ SIZE_THUMBNAIL = "T"
6
+ SIZE_SMALL = "S"
7
+ SIZE_MEDIUM = "M"
8
+ SIZE_FULL = "L"
9
+
10
+ def initialize(document)
11
+ @document = document
12
+ end
13
+
14
+ def content(size)
15
+ api.raw(
16
+ "/accounts/#{account_id}/documents/#{document_id}.png",
17
+ :action => 'get',
18
+ :size => size
19
+ )
20
+ end
21
+
22
+ def thumbnail
23
+ content(SIZE_THUMBNAIL)
24
+ end
25
+
26
+ def small
27
+ content(SIZE_SMALL)
28
+ end
29
+
30
+ def medium
31
+ content(SIZE_MEDIUM)
32
+ end
33
+
34
+ def full
35
+ content(SIZE_FULL)
36
+ end
37
+
38
+ private
39
+
40
+ def api
41
+ document.api
42
+ end
43
+
44
+ def account
45
+ document.owner
46
+ end
47
+
48
+ def document_id
49
+ document.id
50
+ end
51
+
52
+ def account_id
53
+ account.id
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,71 @@
1
+ require 'uri'
2
+
3
+ module Gliffy
4
+ class Folder
5
+ attr_reader :name, :path
6
+ attr_reader :owner, :parent
7
+ attr_reader :folders
8
+
9
+ def self.load(owner, node)
10
+ Gliffy::Folder.new(
11
+ owner,
12
+ node.string('g:name'),
13
+ node.string('g:path'),
14
+ node.nodes('g:folder').map {|n| Gliffy::Folder.load(owner, n)}
15
+ )
16
+ end
17
+
18
+ def initialize(owner, name, path, folders)
19
+ @owner = owner
20
+ @name = name
21
+ @path = path
22
+
23
+ @folders = folders
24
+ @folders.each do |f|
25
+ f.parent = self
26
+ end
27
+ end
28
+
29
+ def parent=(parent)
30
+ if path != parent.path + "/" + name then
31
+ raise "Invalid parent"
32
+ end
33
+
34
+ @parent = parent
35
+ end
36
+
37
+ def documents
38
+ @documents ||= load_documents
39
+ end
40
+
41
+ def root?
42
+ path == "ROOT"
43
+ end
44
+
45
+ private
46
+
47
+ def api
48
+ owner.api
49
+ end
50
+
51
+ def account_id
52
+ owner.id
53
+ end
54
+
55
+ def escaped_path
56
+ path.gsub(' ', '+')
57
+ end
58
+
59
+ def load_documents
60
+ # Path is alphanumeric + spaces and '/'. Spaces should be
61
+ # escaped; slashes should NOT be escaped.
62
+ url = "/accounts/#{account_id}/folders/#{escaped_path}/documents.xml"
63
+ response = api.get(url,
64
+ :action => "get")
65
+
66
+ response
67
+ .nodes('//g:document')
68
+ .map { |n| Gliffy::Document.load(owner, n) }
69
+ end
70
+ end
71
+ end