memotoo 1.0.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,19 +2,21 @@
2
2
 
3
3
  <b>This is not an official gem from the provider of memotoo !!!</b>
4
4
 
5
- The memotoo-gem is a soap(savon)-wrapper to (easy) access your {memotoo}[http://www.memotoo.com/index-saleshype.php] contacts.
5
+ The memotoo-gem is a soap(savon)-wrapper to (easy) access your {memotoo}[https://www.memotoo.com/index-saleshype.php] contacts.
6
6
 
7
- Add, get, search, modify and delete your memotoo contacts.
7
+ Add, get, search, modify and delete your memotoo contacts, contact-groups and bookmarks.
8
8
 
9
9
  == You need
10
10
  you need a memotoo-credential (username/passwd) to use this gem
11
11
 
12
- <b>get a free account here: {www.memotoo.com}[http://www.memotoo.com/index-saleshype.php]</b>
12
+ <b>get a free account here: {www.memotoo.com}[https://www.memotoo.com/index-saleshype.php]</b>
13
13
 
14
14
 
15
15
  ==Install
16
16
 
17
- if you use <b>bundler</b> add gem 'memotoo' to your Gemfile run
17
+ if you use <b>bundler</b> add
18
+ gem 'memotoo'
19
+ to your Gemfile run
18
20
  bundle install
19
21
  else put it in your <b>environment.rb</b> and run
20
22
  rake gems:install
@@ -23,6 +25,9 @@ else put it in your <b>environment.rb</b> and run
23
25
 
24
26
  give a first try in ./script/console
25
27
 
28
+ @connect=Memotoo.new("myusername","mypassword")
29
+
30
+ Changelog: (prev V 2.0 I wrapped it in a Module )
26
31
  @connect=Memotoo::Connect.new("myusername","mypassword")
27
32
 
28
33
  add a contact:
@@ -70,11 +75,44 @@ bookmarks:
70
75
  @connect.modifyBookmark({:id=>response[:id], :url=>"www.google.com", :description => "nice"})
71
76
 
72
77
  @connect.deleteBookmark(12345)
73
-
78
+
79
+
80
+ Requirements:
81
+
82
+ for the objects:
83
+
84
+ Contact:: :lastname
85
+ ContactGroup:: :name
86
+ Bookmark:: :url
87
+ BookmarkFolder:: :name
88
+ Note:: :description
89
+ CalendarCategory:: :name
90
+ Event:: :title, :dateBegin, :dateEnd
91
+ Holiday:: :description, :dateBegin, :dateEnd
92
+ Task:: :title
93
+
94
+ for the methods:
95
+
96
+ searchmethod:: {search=>" "}, a hash
97
+ id:: id of record, integer
98
+ get...Sync:: datetime, format YYYY-MM-DD HH:MM:SS - "2010-02-23 10:00:00"
99
+ modify:: id of record, integer
100
+ add and modify:: need always the object requirements
101
+
102
+ hint:
103
+
104
+ Holiday::
105
+ dateBegin:: "2011-01-01", Format: YYYY-MM-DD
106
+ dateEnd:: "2011-01-01", Format: YYYY-MM-DD
107
+
108
+ Task and Event::
109
+ dateBegin:: "2011-06-18T10:00:00", Format: YYYY-MM-DDTHH:II:SS - ISO8601 time format GMT
110
+ dateEnd:: "2011-06-18T10:00:00", Format: YYYY-MM-DDTHH:II:SS - ISO8601 time format GMT
111
+
74
112
  ==Testing
75
113
 
76
114
  I added tests for all implemented functions. (rcov 100%)
77
- You can add your own credential to /test/test_memotoo.rb
115
+ You can add your own credential to /test/helper.rb
78
116
 
79
117
  I also added support for {http://test.rubygems.org}[http://test.rubygems.org]
80
118
 
@@ -82,19 +120,35 @@ You can now use the gem rubygems-test for easy testing this gem.
82
120
 
83
121
  gem test memotoo
84
122
 
85
- See my testresult here: http://test.rubygems.org/gems/memotoo/v/1.0.6/test_results/1655
123
+ See my testresult here: http://test.rubygems.org/gems/memotoo/v/2.0.0/test_results/1663
124
+
125
+ (To make a fast functional test only contact will be tested - goto test_soapobjects.rb line 8 and uncomment for all soapobject-tests)
86
126
 
87
127
  ==Documentation
88
128
 
89
129
  see rdoc
90
130
 
91
- ==To-Dos
131
+ and memotoo api-documentation
132
+
133
+ https://www.memotoo.com/index.php?rub=api#SOAP-server.php
134
+
135
+ == Changelog V. 2.0.0
136
+
137
+ I create all methods now dynamically. This reduced the code dramatically.
138
+ I give up using a module to wrap the namespace. Now it's a class.
139
+
140
+ == Hint
141
+
142
+ Be careful with following methods due to a problem at memotoo's api:
143
+
144
+ searchBookmarkFolder:: (possible workaround: search for all -> " " and then go ahead)
92
145
 
93
- 1. Exception handling should be done - fetched problems are written to console
94
- 2. I only implemented contacts, contact's group and bookmark - these soap-objects are missing: bookmark's folder, event, holiday, task, note
146
+ getHoliday:: (possible workaround: search and use the result)
147
+ getHolidaySync (no workaround known)
95
148
 
96
- It would be nice if *someone* could help me with the missing parts .
149
+ All three methods seems not to be really important - just fyi
97
150
 
151
+ I will remove this hint when the soap-api is repaired.
98
152
 
99
153
  == Contributing to memotoo-gem
100
154
 
data/Rakefile CHANGED
@@ -15,7 +15,16 @@ Jeweler::Tasks.new do |gem|
15
15
  gem.homepage = "http://github.com/kredmer/memotoo"
16
16
  gem.license = "MIT"
17
17
  gem.summary = "Unofficial gem for connecting to memotoo.com with their given soap-api"
18
- gem.description = "Unofficial gem for connecting to memotoo.com with their soap-api and handle your contact needs. Memotoo lets your synchronize all your contacts, events and tasks with yahoo, gmail, facebook, xing, outlook, your mobile-phone and more. You can also get your e-mails in one place."
18
+ gem.description = "Unofficial gem for connecting to memotoo.com with their soap-api and handle your contact needs. Memotoo lets your synchronize all your contacts, events and tasks with yahoo, gmail, facebook, xing, outlook, your mobile-phone and more. You can also get your e-mails in one place.Features of memotoo:
19
+ New mobile? Transfer all your data to your new device!
20
+ Synchronise your data with your mobile phone (with SyncML)
21
+ Access all your e-mail in a single page from Google, Yahoo, Hotmail / MSN, ...!
22
+ View your data on your mobile phone (WAP / XHTML)
23
+ Access your contacts using a LDAP directory
24
+ Access your files via a Web Folder
25
+ Access your files via FTP
26
+ Add Memotoo widgets to iGoogle, Netvibes, Windows Vista, Apple Dashboard, ...
27
+ Memotoo plugins for your browser"
19
28
  gem.email = "k.redmer@yahoo.de"
20
29
  gem.authors = ["Karsten Redmer"]
21
30
  gem.add_dependency 'savon'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.6
1
+ 2.0.0
@@ -1,8 +1,75 @@
1
- require "memotoo/connect"
2
1
  require 'rubygems'
3
2
  require 'active_support/inflector'
3
+ require "savon"
4
+ require "memotoo/main"
5
+ require "memotoo/core-ext/hash"
6
+ require "memotoo/core-ext/kernel"
4
7
 
8
+ class Memotoo
5
9
 
6
- module Memotoo
10
+ # will hold username and password in a hash style (used for all requests)
11
+ attr_accessor :opts #:nodoc:
12
+
13
+ SEARCHDEFAULTS = { :limit_start => '0', :limit_nb => '100' }
14
+
15
+ # requirement for the objects - for validation
16
+ NEEDS = { :contact => [:lastname],
17
+ :contact_group => [:name],
18
+ :bookmark => [:url],
19
+ :bookmark_folder => [:name],
20
+ :note => [:description],
21
+ :calendar_category => [:name],
22
+ :event => [:title, :dateBegin, :dateEnd],
23
+ :holiday => [:description, :dateBegin, :dateEnd],
24
+ :task => [:title]}
25
+
26
+ #[https] default:true for the SOAP service. Use false to use http-connection
27
+ # example:(use https)
28
+ # @connect=Memotoo::Connect.new("myusername","mypassword")
29
+ # example:(use http)
30
+ # @connect=Memotoo::Connect.new("myusername","mypassword", false)
31
+ def initialize(username, password, https=true)
7
32
 
33
+ # we will need it for every request - will be merged in
34
+ self.opts= { :param => { :login => username, :password => password}}
35
+
36
+ # build dynamically all methods - some magic :-)
37
+ make_methods
38
+
39
+ # creates client with memotoo settings
40
+ client(https)
41
+ end
8
42
  end
43
+
44
+ # stop savon logging
45
+
46
+ module Savon # :nodoc: all
47
+ module Global
48
+ def log?
49
+ false
50
+ end
51
+ def raise_errors?
52
+ @raise_errors = true
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+ #Finished in 12.361502 seconds.
59
+
60
+ #14 tests, 14 assertions, 0 failures, 0 errors
61
+ #+----------------------------------------------------+-------+-------+--------+
62
+ #| File | Lines | LOC | COV |
63
+ #+----------------------------------------------------+-------+-------+--------+
64
+ #|lib/memotoo.rb | 59 | 34 | 100.0% |
65
+ #|lib/memotoo/core-ext/hash.rb | 41 | 25 | 100.0% |
66
+ #|lib/memotoo/core-ext/kernel.rb | 10 | 6 | 100.0% |
67
+ #|lib/memotoo/main.rb | 280 | 77 | 100.0% |
68
+ #+----------------------------------------------------+-------+-------+--------+
69
+ #|Total | 390 | 142 | 100.0% |
70
+ #+----------------------------------------------------+-------+-------+--------+
71
+ #100.0% 4 file(s) 390 Lines 142 LOC
72
+
73
+ #Generated on Sun Jun 12 07:03:59 +0200 2011 with rcov 0.9.8
74
+
75
+
@@ -26,8 +26,8 @@ class Hash # :nodoc: all
26
26
 
27
27
  # Returns a new Hash with +self+ and +other_hash+ merged recursively.
28
28
  # Modifies the receiver in place.
29
- # => already in savon gem
30
- # => in case a time come and it will be away - just uncomment it
29
+ # => see this function also in savon gem
30
+ # got problems in my test and had to include it here...
31
31
  def deep_merge_me!(other_hash)
32
32
  other_hash.each_pair do |k,v|
33
33
  tv = self[k]
@@ -1,4 +1,4 @@
1
- module Kernel
1
+ module Kernel # :nodoc: all
2
2
  private
3
3
  # def this_method
4
4
  # caller[0] =~ /`([^']*)'/ and $1
@@ -0,0 +1,280 @@
1
+ class Memotoo
2
+
3
+ private
4
+
5
+ # Creates the <tt>Savon::Client</tt>.
6
+ def client(https=true)
7
+ #--
8
+ # in any case problems switch back to receiving the wsdl file from memotoo
9
+ # https: wsdl.document = "https://www.memotoo.com/SOAP-server.php?wsdl"
10
+ # http: wsdl.document = "http://www.memotoo.com/SOAP-server.php?wsdl"
11
+ #++
12
+
13
+ @client ||= Savon::Client.new do
14
+ wsdl.namespace="urn:memotooSoap"
15
+ if https
16
+ wsdl.endpoint="https://www.memotoo.com/SOAP-server.php"
17
+ http.auth.ssl.verify_mode = :none
18
+ else
19
+ wsdl.endpoint="http://www.memotoo.com/SOAP-server.php"
20
+ end
21
+ http.auth.basic self.opts[:param][:login], self.opts[:param][:password]
22
+ end
23
+ end
24
+
25
+ def selfclass
26
+ (class << self; self; end)
27
+ end
28
+
29
+ # builds for every soap-object six methods (add, search, get, get..Sync,modify, delete )
30
+ # on-the-fly :-)
31
+ def make_methods
32
+
33
+ # the accessible soap objects
34
+ soapobjects = %w{Contact ContactGroup Bookmark BookmarkFolder Note CalendarCategory Event Holiday Task}
35
+
36
+ soapobjects.each do |soapobject|
37
+ symbol=soapobject.underscore.to_sym
38
+
39
+ # add method
40
+ methodname="add"+soapobject
41
+ selfclass.send(:define_method, methodname) { |details| output(detailsApicall({symbol => details}), :id) if fields?(details, NEEDS[symbol]) }
42
+
43
+ # search
44
+ methodname="search"+soapobject
45
+ selfclass.send(:define_method, methodname) { |params| output(searchApiCall(params), :return, symbol) if fields?(params, [:search]) }
46
+
47
+ # get
48
+ methodname="get"+soapobject
49
+ selfclass.send(:define_method, methodname) { |id| output(idApicall(id), :return, symbol) }
50
+
51
+ # get...Sync
52
+ methodname="get"+soapobject+"Sync"
53
+ selfclass.send(:define_method, methodname) { |datetime| output(getSyncApiCall(datetime), :return, symbol) }
54
+
55
+ # modify
56
+ methodname="modify"+soapobject
57
+ selfclass.send(:define_method, methodname) { |details| output(detailsApicall({symbol => details}), :ok) if fields?(details, [NEEDS[symbol], :id].flatten!) }
58
+
59
+ # delete
60
+ methodname="delete"+soapobject
61
+ selfclass.send(:define_method, methodname) { |id| output(idApicall(id), :ok) }
62
+
63
+ end
64
+ end
65
+
66
+ def searchApiCall(searchparameter)
67
+ search = SEARCHDEFAULTS.merge!(searchparameter)
68
+ apicall(calling_method.to_sym, search)
69
+ end
70
+
71
+ def getSyncApiCall(datetime)
72
+ date2time=Time.mktime(*ParseDate.parsedate(datetime))
73
+ formated_date=date2time.strftime("%Y-%m-%d %H:%M:%S")
74
+ apicall(calling_method.to_sym, { :date => formated_date })
75
+ end
76
+
77
+ def idApicall(id)
78
+ apicall(calling_method.to_sym, { :id => id })
79
+ end
80
+
81
+ def detailsApicall(details)
82
+ apicall(calling_method.to_sym, details )
83
+ end
84
+
85
+ # used internally for a request
86
+ def apicall(action, parameter)
87
+ response=@client.request :wsdl, action do
88
+ soap.body = { :param => parameter }.deep_merge_me!(self.opts)
89
+ end
90
+ response
91
+ rescue Savon::Error => error
92
+ raise ArgumentError, "Memotoo::Connect #invalid username/password" if error.message.nil?
93
+ end
94
+
95
+ def output(response, *_keys_)
96
+ output_key = [(calling_method.underscore+"_response").to_sym] | _keys_
97
+ response.nil? ? nil : response.to_hash.seek(output_key)
98
+ end
99
+
100
+ def go_home(message)
101
+ raise ArgumentError, "Memotoo::Connect #missing fields: " + message.to_s
102
+ end
103
+
104
+ def fields?(thehash, args=[])
105
+ valid=true
106
+ retarr=[]
107
+ args.each do |arg_item|
108
+ unless thehash.has_key?(arg_item)
109
+ valid = false
110
+ retarr << arg_item
111
+ end
112
+ end
113
+ valid ? true : go_home(retarr.join(", "))
114
+ end
115
+
116
+ # ---------------------
117
+ # :section: memotoo soap actions
118
+ # === bookmark - ready implemented
119
+ # * searchBookmark(searchparams={})
120
+ # * addBookmark(params={})
121
+ # * getBookmark(id)
122
+ # * getBookmarkSync(datetime)
123
+ # * modifyBookmark(params={})
124
+ # * deleteBookmark(id)
125
+ #
126
+ # === bookmarkfolder - ready implemented - API problem with search
127
+ # * searchBookmarkFolder(searchparams={})
128
+ # * addBookmarkFolder(params={})
129
+ # * getBookmarkFolder(id)
130
+ # * getBookmarkFolderSync(datetime)
131
+ # * modifyBookmarkFolder(params={})
132
+ # * deleteBookmarkFolder(id)
133
+ #
134
+ # === calendar_category - ready implemented
135
+ # * searchCalendarCategory
136
+ # * addCalendarCategory
137
+ # * getCalendarCategory
138
+ # * getCalendarCategorySync
139
+ # * modifyCalendarCategory
140
+ # * deleteCalendarCategory
141
+ #
142
+ # === contact - ready implemented
143
+ # * searchContact
144
+ # * add_contact
145
+ # * getContact
146
+ # * getContactSync
147
+ # * modifyContact
148
+ # * deleteContact
149
+ #
150
+ # === contact-group - ready implemented
151
+ # * searchContactGroup
152
+ # * addContactGroup
153
+ # * getContactGroup
154
+ # * getContactGroupSync
155
+ # * modifyContactGroup
156
+ # * deleteContactGroup
157
+ #
158
+ # === event - ready implemented
159
+ # * searchEvent
160
+ # * addEvent
161
+ # * getEvent
162
+ # * getEventSync
163
+ # * modifyEvent
164
+ # * deleteEvent
165
+ #
166
+ # === holiday - ready implemented - API problem with get and getSync
167
+ # * searchHoliday
168
+ # * addHoliday
169
+ # * getHoliday
170
+ # * getHolidaySync
171
+ # * modifyHoliday
172
+ # * deleteHoliday
173
+ #
174
+ # === note - ready implemented
175
+ # * searchNote
176
+ # * addNote
177
+ # * getNote
178
+ # * getNoteSync
179
+ # * modifyNote
180
+ # * deleteNote
181
+ #
182
+ # === task - ready implemented
183
+ # * searchTask
184
+ # * addTask
185
+ # * getTask
186
+ # * getTaskSync
187
+ # * modifyTask
188
+ # * deleteTask
189
+ #
190
+ # ---------------------
191
+
192
+ # ---------------------
193
+ # :section: Bookmark fields
194
+ #
195
+ # id:: "2531368"
196
+ # url(*):: "http://www.google.com"
197
+ # description:: "google"
198
+ # rank:: "0"
199
+ # tags:: nil
200
+ # id_bookmark_folder:: "363174"
201
+ # ---------------------
202
+
203
+ # ---------------------
204
+ # :section: BookmarkFolder fields
205
+ #
206
+ # id:: "2531368"
207
+ # name(*):: "Download applications"
208
+ # id_bookmark_folder_parent:: "363174"
209
+ # ---------------------
210
+
211
+
212
+
213
+ # ---------------------
214
+ # :section: Contact fields
215
+ # all contacts fields
216
+ # :id
217
+ # :title => 'Mr.',
218
+ # :lastname => 'test',
219
+ # :firstname => 'user',
220
+ # :middlename => '',
221
+ # :nickname => 'bob',
222
+ # :suffix => '',
223
+ # :birthday => '1975-02-14', // Format YYYY-MM-DD
224
+ # :homeaddress => '',
225
+ # :homecity => 'new york',
226
+ # :homepostalcode => '',
227
+ # :homestate => '',
228
+ # :homecountry => 'usa',
229
+ # :homeemail => '',
230
+ # :homephone => '',
231
+ # :homemobile => '',
232
+ # :homefax => '',
233
+ # :homewebpage => '',
234
+ # :businessaddress => '',
235
+ # :businesscity => '',
236
+ # :businesspostalcode => '',
237
+ # :businessstate => '',
238
+ # :businesscountry => '',
239
+ # :businessemail => '',
240
+ # :businessphone => '',
241
+ # :businessmobile => '',
242
+ # :businessfax => '',
243
+ # :businesswebpage => '',
244
+ # :company => '',
245
+ # :department => '',
246
+ # :jobtitle => '',
247
+ # :notes => '',
248
+ # :otheraddress => '',
249
+ # :othercity => '',
250
+ # :otherpostalcode => '',
251
+ # :otherstate => '',
252
+ # :othercountry => '',
253
+ # :otheremail => '',
254
+ # :otherphone => '',
255
+ # :othermobile => '',
256
+ # :otherfax => '',
257
+ # :skypeid => '',
258
+ # :msnid => '',
259
+ # :aimid => '',
260
+ # :pager => '',
261
+ # :carphone => '',
262
+ # :managersname => '',
263
+ # :assistantsname => '',
264
+ # :assistantsphone => '',
265
+ # :parent => '',
266
+ # :spouse => '',
267
+ # :children => '',
268
+ # :custom1 => '',
269
+ # :custom2 => '',
270
+ # :custom3 => '',
271
+ # :custom4 => '',
272
+ # :group => '0',
273
+ # :photo => '', // Photo encoded with Base64
274
+ # ---------------------
275
+
276
+ end
277
+
278
+
279
+
280
+