Ruby4Skype 0.2.3 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +3 -0
- data/README +14 -0
- data/Rakefile +67 -0
- data/lib/skypeapi.rb +570 -509
- data/lib/skypeapi/application.rb +79 -77
- data/lib/skypeapi/call.rb +243 -230
- data/lib/skypeapi/chat.rb +162 -172
- data/lib/skypeapi/chatmember.rb +26 -28
- data/lib/skypeapi/chatmessage.rb +81 -65
- data/lib/skypeapi/error.rb +8 -0
- data/lib/skypeapi/event.rb +25 -26
- data/lib/skypeapi/filetransfer.rb +47 -28
- data/lib/skypeapi/group.rb +72 -73
- data/lib/skypeapi/menuitem.rb +44 -44
- data/lib/skypeapi/message.rb +39 -41
- data/lib/skypeapi/object.rb +246 -82
- data/lib/skypeapi/os/etc.rb +48 -98
- data/lib/skypeapi/os/mac.rb +92 -4
- data/lib/skypeapi/os/notifier.rb +31 -0
- data/lib/skypeapi/os/window_event_queue.rb +198 -0
- data/lib/skypeapi/os/window_messagehandler.rb +120 -0
- data/lib/skypeapi/os/windows.rb +170 -306
- data/lib/skypeapi/profile.rb +190 -120
- data/lib/skypeapi/sharefunctions.rb +31 -23
- data/lib/skypeapi/sms.rb +87 -67
- data/lib/skypeapi/user.rb +159 -99
- data/lib/skypeapi/version.rb +3 -3
- data/lib/skypeapi/voicemail.rb +59 -52
- data/spec/matcher_be_boolean.rb +10 -0
- data/spec/skypeapi/application_spec.rb +76 -0
- data/spec/skypeapi/chat_spec.rb +356 -0
- data/spec/skypeapi/chatmember_spec.rb +42 -0
- data/spec/skypeapi/chatmessage_spec.rb +89 -0
- data/spec/skypeapi/event_spec.rb +31 -0
- data/spec/skypeapi/filetransfer_spec.rb +67 -0
- data/spec/skypeapi/group_spec.rb +16 -0
- data/spec/skypeapi/menuitem_spec.rb +37 -0
- data/spec/skypeapi/os/windows_spec.rb +305 -0
- data/spec/skypeapi/profile_spec.rb +22 -0
- data/spec/skypeapi/user_spec.rb +25 -0
- data/spec/skypeapi_spec.rb +528 -0
- metadata +32 -12
- data/lib/skypeapi/os/timer.rb +0 -108
data/lib/skypeapi/event.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
module SkypeAPI
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
def
|
2
|
+
class Event < AbstractObject
|
3
|
+
OBJECT_NAME = "EVENT"
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def create id, caption, hint, block=Proc.new
|
7
7
|
res = SkypeAPI.invoke "CREATE EVENT #{id} CAPTION #{caption} HINT #{hint}"
|
8
8
|
res == "EVENT #{id} CREATED"
|
9
9
|
instance = new id
|
10
10
|
instance.setNotify block if block
|
11
11
|
instance
|
12
12
|
end
|
13
|
-
|
14
|
-
def
|
13
|
+
|
14
|
+
def set_notify id=nil, block=Proc.new
|
15
15
|
@notify[id] = block
|
16
16
|
end
|
17
|
-
|
18
|
-
|
17
|
+
alias setNotify set_notify
|
18
|
+
|
19
|
+
def notified msg
|
19
20
|
if msg =~ /^([^ ]+) CLICKED$/m
|
20
21
|
id = $1
|
21
22
|
instance = new $1
|
@@ -24,27 +25,25 @@ module SkypeAPI
|
|
24
25
|
@@instance[self][id].notified if @@instance[self][id]
|
25
26
|
end
|
26
27
|
end
|
27
|
-
|
28
|
-
def
|
29
|
-
@notify.call self if @notify
|
30
|
-
end
|
31
|
-
|
32
|
-
def setNotify block=Proc.new
|
33
|
-
@notify = block
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.delete id
|
28
|
+
|
29
|
+
def delete id
|
37
30
|
new(id).delete
|
38
31
|
end
|
39
|
-
|
40
|
-
def delete
|
41
|
-
res = invoke "DELETE EVENT #{@id}"
|
42
|
-
res == "DELETE EVENT #{@id}"
|
43
|
-
end
|
44
32
|
|
45
|
-
|
46
|
-
|
33
|
+
end
|
34
|
+
|
35
|
+
def notified
|
36
|
+
@notify.call self if @notify
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_notify block=Proc.new
|
40
|
+
@notify = block
|
41
|
+
end
|
42
|
+
alias setNotify set_notify
|
47
43
|
|
44
|
+
def delete
|
45
|
+
res = invoke "DELETE EVENT #{@id}"
|
46
|
+
res == "DELETE EVENT #{@id}"
|
48
47
|
end
|
49
48
|
end
|
50
49
|
end
|
@@ -1,31 +1,50 @@
|
|
1
1
|
module SkypeAPI
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
2
|
+
class FileTransfer < AbstractObject
|
3
|
+
OBJECT_NAME = "FILETRANSFER"
|
4
|
+
|
5
|
+
def get_type() invoke_get("TYPE") end
|
6
|
+
def_parser(:type)
|
7
|
+
alias getType get_type
|
8
|
+
|
9
|
+
def get_status() invoke_get("STATUS") end
|
10
|
+
def_parser(:status)
|
11
|
+
alias getStatus get_status
|
12
|
+
|
13
|
+
def get_failure_reason() invoke_get("FAILUREREASON") end
|
14
|
+
def_parser(:failure_reason, "FAILUREREASON")
|
15
|
+
alias getFailureReason get_failure_reason
|
16
|
+
|
17
|
+
def get_partner() parse :partner, invoke_get("PARTNER_HANDLE") end
|
18
|
+
def_parser(:partner, 'PARTNER_HANDLE'){|str| SkypeAPI::User.new str}
|
19
|
+
alias getPartner get_partner
|
20
|
+
|
21
|
+
def get_partner_dispname() invoke_get("PARTNER_DISPNAME") end
|
22
|
+
def_parser(:partner_dispname)
|
23
|
+
alias getPartnerDispname get_partner_dispname
|
24
|
+
|
25
|
+
def get_start_time() parse :start_time, invoke_get("STARTTIME") end
|
26
|
+
def_parser(:start_time,'STARTTIME'){|str| str.empty? ? nil : Time.at(str.to_i)}
|
27
|
+
alias getStartTime get_start_time
|
28
|
+
|
29
|
+
def get_finish_time() parse :finish_time, invoke_get("FINISHTIME") end
|
30
|
+
def_parser(:finish_time, 'FINISHTIME'){|str| str.empty? ? nil : Time.at(str.to_i)}
|
31
|
+
alias getFinishTime get_finish_time
|
32
|
+
|
33
|
+
def get_file_path() invoke_get("FILEPATH") end
|
34
|
+
def_parser(:file_path, 'FILEPATH')
|
35
|
+
alias getFilePath get_file_path
|
36
|
+
|
37
|
+
def get_file_size() parse :file_size, invoke_get("FILESIZE") end
|
38
|
+
def_parser(:file_size, 'FILESIZE'){|str| str.to_i}
|
39
|
+
alias getFileSize get_file_size
|
40
|
+
|
41
|
+
def get_bytes_per_second() parse :bytes_per_second, invoke_get("BYTESPERSECOND") end
|
42
|
+
def_parser(:bytes_per_second, 'BYTEPERSECOND'){|str| str.to_i}
|
43
|
+
alias getBytesPerSecond get_bytes_per_second
|
44
|
+
|
45
|
+
def get_bytes_transferred() parse :bytes_transferred, invoke_get("BYTESTRANSFERRED") end
|
46
|
+
def_parser(:bytes_transferred, 'BYTETRASFERRED'){|str| str.to_i}
|
47
|
+
alias getBytesTransferred get_bytes_transferred
|
48
|
+
|
30
49
|
end
|
31
50
|
end
|
data/lib/skypeapi/group.rb
CHANGED
@@ -1,81 +1,80 @@
|
|
1
1
|
module SkypeAPI
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
@@skypeApi.Group.setNotify :DisplayName, displayName do |g|
|
14
|
-
group = g
|
15
|
-
end
|
16
|
-
until group
|
17
|
-
@@skypeApi.polling
|
18
|
-
sleep 0.0123
|
19
|
-
end
|
20
|
-
if tmp
|
21
|
-
@@skypeApi.Group.setNotify :DisplayName, displayName, tmp
|
22
|
-
tmp.call group
|
23
|
-
else
|
24
|
-
@@skypeApi.Group.notify[:displayname][displayName] = nil
|
25
|
-
end
|
26
|
-
group
|
27
|
-
#ThreadSafe ����ς��낤�Ȃ��B�B�B
|
2
|
+
class Group < AbstractObject
|
3
|
+
OBJECT_NAME = "GROUP"
|
4
|
+
|
5
|
+
#FASdfklasjidfojsdlkjljfaslkdjf!!!!!!!!!!!!!!!!!!!!
|
6
|
+
def self.create displayName
|
7
|
+
SkypeAPI.invoke("CREATE GROUP #{displayName}")
|
8
|
+
group = nil
|
9
|
+
tmp = nil
|
10
|
+
if SkypeAPI::Group.notify[:displayname] and SkypeAPI::Group.notify[:displayname][displayName]
|
11
|
+
tmp = SkypeAPI::Group.notify[:displayname][displayName]
|
28
12
|
end
|
29
|
-
|
30
|
-
|
31
|
-
getter :CustomGroupID, 'CUSTOM_GROUP_ID' do |str|
|
32
|
-
str.to_i
|
13
|
+
SkypeAPI::Group.setNotify :DisplayName, displayName do |g|
|
14
|
+
group = g
|
33
15
|
end
|
34
|
-
|
35
|
-
|
36
|
-
|
16
|
+
until group
|
17
|
+
SkypeAPI.polling
|
18
|
+
sleep 0.0123
|
37
19
|
end
|
38
|
-
|
39
|
-
|
20
|
+
if tmp
|
21
|
+
SkypeAPI::Group.setNotify :DisplayName, displayName, tmp
|
22
|
+
tmp.call group
|
23
|
+
else
|
24
|
+
SkypeAPI::Group.notify[:displayname][displayName] = nil
|
40
25
|
end
|
41
|
-
|
42
|
-
|
43
|
-
end
|
44
|
-
getter :Visible, 'VISIBLE' do |str|
|
45
|
-
str._flag
|
46
|
-
end
|
47
|
-
getter :Expanded, 'EXPANDED' do |str|
|
48
|
-
str._flag
|
49
|
-
end
|
50
|
-
|
51
|
-
def setDisplayName dispname
|
52
|
-
invoke_set "DISPLAYNAME", dispname
|
53
|
-
end
|
54
|
-
|
55
|
-
def delete
|
56
|
-
invoke_echo "DELETE GROUP #{@id}"
|
57
|
-
end
|
58
|
-
|
59
|
-
def addUser user
|
60
|
-
invoke_alter "ADDUSER", user
|
61
|
-
end
|
62
|
-
|
63
|
-
def removeUser user
|
64
|
-
invoke_alter "REMOVEUSER", user
|
65
|
-
end
|
66
|
-
|
67
|
-
def share msg=''
|
68
|
-
invoke_alter "Share", msg
|
69
|
-
end
|
70
|
-
|
71
|
-
def accept
|
72
|
-
invoke_alter "ACCEPT"
|
73
|
-
end
|
74
|
-
|
75
|
-
def decline
|
76
|
-
invoke_alter "DECLINE"
|
77
|
-
end
|
78
|
-
|
26
|
+
group
|
27
|
+
#ThreadSafe ����ς��낤�Ȃ��B�B�B
|
79
28
|
end
|
29
|
+
|
30
|
+
def get_type() invoke_get("TYPE") end
|
31
|
+
def_parser(:type)
|
32
|
+
alias getType get_type
|
33
|
+
|
34
|
+
def get_custom_group_id() parse :custom_group_id, invoke_get("CUSTOM_GROUP_ID") end
|
35
|
+
def_parser(:custom_group_id){|str| str.to_i}
|
36
|
+
alias getCustomGroupID get_custom_group_id
|
37
|
+
|
38
|
+
def get_displayname() invoke_get("DISPLAYNAME") end
|
39
|
+
def_parser(:displayname)
|
40
|
+
alias getDisplayname get_displayname
|
41
|
+
|
42
|
+
def get_nrof_users() parse :nrof_users, invoke_get("NROFUSERS") end
|
43
|
+
def_parser(:nrof_users,"NROFUSERS"){|str| str.to_i}
|
44
|
+
alias getNrofUsers get_nrof_users
|
45
|
+
|
46
|
+
def get_nrof_users_online() parse :nrof_users_online, invoke_get("NROFUSERS_ONLINE") end
|
47
|
+
def_parser(:nrof_users_online,"NROFUSERS_ONLINE"){|str| str.to_i}
|
48
|
+
alias getNrofUsersOnline get_nrof_users_online
|
49
|
+
|
50
|
+
def get_users() parse :users, invoke_get("USERS") end
|
51
|
+
def_parser(:users){|str| str.split('./')}
|
52
|
+
alias getUsers get_users
|
53
|
+
|
54
|
+
def get_visible() parse :visible, invoke_get("VISIBLE") end
|
55
|
+
def_parser(:visible){|str| str._flag}
|
56
|
+
alias getVisible get_visible
|
57
|
+
|
58
|
+
def get_expanded() parse :expanded, invoke_get("EXPANDED") end
|
59
|
+
def_parser(:expanded){|str| str._flag}
|
60
|
+
alias getExpanded get_expanded
|
61
|
+
|
62
|
+
def set_displayname(dispname) invoke_set "DISPLAYNAME", dispname end
|
63
|
+
alias setDisplayname set_displayname
|
64
|
+
|
65
|
+
def delete() invoke_echo "DELETE GROUP #{@id}" end
|
66
|
+
|
67
|
+
def add_user(user) invoke_alter "ADDUSER", user end
|
68
|
+
alias addUser add_user
|
69
|
+
|
70
|
+
def remove_user(user) invoke_alter "REMOVEUSER", user end
|
71
|
+
alias removeUser remove_user
|
72
|
+
|
73
|
+
def share(msg='') invoke_alter "Share", msg end
|
74
|
+
|
75
|
+
def accept() invoke_alter "ACCEPT" end
|
76
|
+
|
77
|
+
def decline() invoke_alter "DECLINE" end
|
78
|
+
|
80
79
|
end
|
81
80
|
end
|
data/lib/skypeapi/menuitem.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module SkypeAPI
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
def
|
2
|
+
class MenuItem < AbstractObject
|
3
|
+
OBJECT_NAME = 'MENU_ITEM'
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def create h, block=Proc.new
|
7
7
|
raise ArgumentError unless h[:id] and h[:context] and h[:caption]
|
8
8
|
#id, context, caption, hint=nil, icon=nil, enabled=nil, enableMultipleContacts=nil, &block
|
9
9
|
res = SkypeAPI.invoke "CREATE MENU_ITEM #{h[:id]} CONTEXT #{h[:context]} CAPTION #{h[:caption]}#{h[:hint].nil? ? '' : " HINT #{h[:hint]}"}#{h[:icon].nil? ? '' : " ICON #{h[:icon]}"}#{h[:enable].nil? ? '' : " ENABLED #{h[:enabled]}"}#{h[:enableMultipleContacts].nil? ? '' : " ENABLE_MULTIPLE_CONTACTS #{h[:enableMultipleContacts]}"}"
|
@@ -13,11 +13,11 @@ module SkypeAPI
|
|
13
13
|
instance
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def set_notify sym=nil, block=Proc.new
|
17
17
|
@notify[sym] = block
|
18
18
|
end
|
19
|
-
|
20
|
-
def
|
19
|
+
|
20
|
+
def notified msg
|
21
21
|
if msg =~ /^([^ ]+) CLICKED( ([^ ]+))? CONTEXT ([^ ]+)( CONTEXT_ID (.+))?$/m
|
22
22
|
id = $1; context = $4; userID = $3; contextID = $6
|
23
23
|
user = userID ? SkypeAPI.user(userID) : nil
|
@@ -27,44 +27,44 @@ module SkypeAPI
|
|
27
27
|
@@instance[self][id].notified instance, context, user, contextID if @@instance[self][id]
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
31
|
-
def
|
32
|
-
@notify.call instance, context, user, contextID if @notify
|
33
|
-
end
|
34
|
-
|
35
|
-
def setNotify block=Proc.new
|
36
|
-
@notify = block
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.delete id
|
30
|
+
|
31
|
+
def delete id
|
40
32
|
new(id).delete
|
41
33
|
end
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
def setCaption caption
|
49
|
-
res = invoke "SET MENU_ITEM #{@id} CAPTION #{caption}"
|
50
|
-
res == "MENU_ITEM #{@id} CAPTION \"#{caption}\""
|
51
|
-
end
|
52
|
-
|
53
|
-
def setHint hint
|
54
|
-
res = invoke "SET MENU_ITEM #{@id} HINT #{hint}"
|
55
|
-
res == "MENU_ITEM #{@id} HINT \"#{hint}\""
|
56
|
-
end
|
57
|
-
|
58
|
-
def setEnabled flag
|
59
|
-
res = invoke "SET MENU_ITEM #{@id} ENABLED #{flag._str}"
|
60
|
-
res == "MENU_ITEM #{@id} ENABLED #{flag._str}"
|
61
|
-
end
|
62
|
-
|
63
|
-
alias set_notify setNotify
|
64
|
-
#alias del_notify delNotify
|
65
|
-
alias set_caption setCaption
|
66
|
-
alias set_hint setHint
|
67
|
-
alias set_enabled setEnabled
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def notified instance, context, user, contextID
|
38
|
+
@notify.call instance, context, user, contextID if @notify
|
68
39
|
end
|
40
|
+
|
41
|
+
def set_notify block=Proc.new
|
42
|
+
@notify = block
|
43
|
+
end
|
44
|
+
alias setNotify set_notify
|
45
|
+
|
46
|
+
def delete
|
47
|
+
res = SkypeAPI.invoke "DELETE MENU_ITEM #{@id}"
|
48
|
+
res == "DELETE MENU_ITEM #{@id}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def set_caption caption
|
52
|
+
res = invoke "SET MENU_ITEM #{@id} CAPTION #{caption}"
|
53
|
+
res == "MENU_ITEM #{@id} CAPTION \"#{caption}\""
|
54
|
+
end
|
55
|
+
alias setCaption set_caption
|
56
|
+
|
57
|
+
def set_hint hint
|
58
|
+
res = invoke "SET MENU_ITEM #{@id} HINT #{hint}"
|
59
|
+
res == "MENU_ITEM #{@id} HINT \"#{hint}\""
|
60
|
+
end
|
61
|
+
alias setHint set_hint
|
62
|
+
|
63
|
+
def set_enabled flag
|
64
|
+
res = invoke "SET MENU_ITEM #{@id} ENABLED #{flag._str}"
|
65
|
+
res == "MENU_ITEM #{@id} ENABLED #{flag._str}"
|
66
|
+
end
|
67
|
+
alias setEnabled set_enabled
|
68
|
+
|
69
69
|
end
|
70
70
|
end
|
data/lib/skypeapi/message.rb
CHANGED
@@ -1,46 +1,44 @@
|
|
1
1
|
module SkypeAPI
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
raise #????
|
29
|
-
end
|
2
|
+
class Message < AbstractObject
|
3
|
+
OBJECT_NAME = "MESSAGE"
|
4
|
+
|
5
|
+
PROPERTY2METHOD = {
|
6
|
+
'TIMESTAMP' => :timestamp,
|
7
|
+
'PARTNER_HANDLE' => :partnerHandle,
|
8
|
+
'PARTNER_DISPNAME' => :partnerDispname,
|
9
|
+
'CONF_ID' => :confIdD,
|
10
|
+
'TYPE' => :type,
|
11
|
+
'STATUS' => :status,
|
12
|
+
'FAILUREREASON' => :failureReason,
|
13
|
+
'BODY' => :body,
|
14
|
+
}
|
15
|
+
|
16
|
+
def self.create target,text
|
17
|
+
if defined? target.getHandle
|
18
|
+
target = target.getHandle
|
19
|
+
elsif target.class == String
|
20
|
+
else
|
21
|
+
raise target
|
22
|
+
end
|
23
|
+
res = @skypeApi.invoke_one "MESSAGE #{target} #{text}","MESSAGE"
|
24
|
+
if res =~ /^(\d+) STATUS (.+)$/
|
25
|
+
return @skypeApi.getMessage($1),"getStatus",$2
|
26
|
+
else
|
27
|
+
raise #????
|
30
28
|
end
|
31
|
-
|
32
|
-
def timestamp() invoke_get('TIMESTAMP'); end
|
33
|
-
def partnerHandle() invoke_get('PARTNER_HANDLE'); end
|
34
|
-
def partnerDispname() invoke_get('PARTNER_DISPNAME'); end
|
35
|
-
def confIdD() invoke_get('CONF_ID'); end
|
36
|
-
def type() invoke_get('TYPE'); end
|
37
|
-
def status() invoke_get('STATUS'); end
|
38
|
-
def failureReason() invoke_get('FAILUREREASON'); end
|
39
|
-
def body() invoke_get('BODY'); end
|
40
|
-
|
41
|
-
#def setSeen
|
42
|
-
# str2object invoke_one("SET MESSAGE #{@id} SEEN","SET MESSAGE #{@id} STATUS")
|
43
|
-
#end
|
44
29
|
end
|
30
|
+
|
31
|
+
def timestamp() invoke_get('TIMESTAMP'); end
|
32
|
+
def partnerHandle() invoke_get('PARTNER_HANDLE'); end
|
33
|
+
def partnerDispname() invoke_get('PARTNER_DISPNAME'); end
|
34
|
+
def confIdD() invoke_get('CONF_ID'); end
|
35
|
+
def type() invoke_get('TYPE'); end
|
36
|
+
def status() invoke_get('STATUS'); end
|
37
|
+
def failureReason() invoke_get('FAILUREREASON'); end
|
38
|
+
def body() invoke_get('BODY'); end
|
39
|
+
|
40
|
+
#def setSeen
|
41
|
+
# str2object invoke_one("SET MESSAGE #{@id} SEEN","SET MESSAGE #{@id} STATUS")
|
42
|
+
#end
|
45
43
|
end
|
46
44
|
end
|