cinch 2.0.3 → 2.0.4

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.
@@ -0,0 +1,83 @@
1
+ module Cinch
2
+ # Provide blocking access to user/channel information.
3
+ module Syncable
4
+ # Blocks until the object is synced.
5
+ #
6
+ # @return [void]
7
+ # @api private
8
+ def wait_until_synced(attr)
9
+ attr = attr.to_sym
10
+ waited = 0
11
+ while true
12
+ return if attribute_synced?(attr)
13
+ waited += 1
14
+
15
+ if waited % 100 == 0
16
+ bot.loggers.warn "A synced attribute ('%s' for %s) has not been available for %d seconds, still waiting" % [attr, self.inspect, waited / 10]
17
+ bot.loggers.warn caller.map {|s| " #{s}"}
18
+
19
+ if waited / 10 >= 30
20
+ bot.loggers.warn " Giving up..."
21
+ raise Exceptions::SyncedAttributeNotAvailable, "'%s' for %s" % [attr, self.inspect]
22
+ end
23
+ end
24
+ sleep 0.1
25
+ end
26
+ end
27
+
28
+ # @api private
29
+ # @return [void]
30
+ def sync(attribute, value, data = false)
31
+ if data
32
+ @data[attribute] = value
33
+ else
34
+ instance_variable_set("@#{attribute}", value)
35
+ end
36
+ @synced_attributes << attribute
37
+ end
38
+
39
+ # @return [Boolean]
40
+ # @api private
41
+ def attribute_synced?(attribute)
42
+ @synced_attributes.include?(attribute)
43
+ end
44
+
45
+ # @return [void]
46
+ # @api private
47
+ def unsync(attribute)
48
+ @synced_attributes.delete(attribute)
49
+ end
50
+
51
+ # @return [void]
52
+ # @api private
53
+ # @since 1.0.1
54
+ def unsync_all
55
+ @synced_attributes.clear
56
+ end
57
+
58
+ # @param [Symbol] attribute
59
+ # @param [Boolean] data
60
+ # @param [Boolean] unsync
61
+ # @api private
62
+ def attr(attribute, data = false, unsync = false)
63
+ unless unsync
64
+ if @when_requesting_synced_attribute
65
+ @when_requesting_synced_attribute.call(attribute)
66
+ end
67
+ wait_until_synced(attribute)
68
+ end
69
+
70
+ if data
71
+ return @data[attribute]
72
+ else
73
+ return instance_variable_get("@#{attribute}")
74
+ end
75
+ end
76
+
77
+ # @api private
78
+ # @return [void]
79
+ def mark_as_synced(attribute)
80
+ @synced_attributes << attribute
81
+ end
82
+ end
83
+ end
@@ -90,7 +90,8 @@ module Cinch
90
90
  # of IO or String).
91
91
  #
92
92
  # @param [#<<] io The object to write the data to.
93
- # @return [void]
93
+ # @return [Boolean] True if the transfer finished
94
+ # successfully, false otherwise.
94
95
  # @note This method blocks.
95
96
  # @example Saving to a file
96
97
  # f = File.open("/tmp/foo", "w")
@@ -103,12 +104,28 @@ module Cinch
103
104
  def accept(io)
104
105
  socket = TCPSocket.new(@ip, @port)
105
106
  total = 0
106
- while buf = socket.read(1024)
107
+
108
+ while buf = socket.readpartial(8192)
107
109
  total += buf.bytesize
108
110
 
109
- socket.write [total].pack("N")
111
+ begin
112
+ socket.write_nonblock [total].pack("N")
113
+ rescue Errno::EWOULDBLOCK, Errno::AGAIN
114
+ # Nobody cares about ACKs, really. And if the sender
115
+ # couldn't receive it at this point, he probably doesn't
116
+ # care, either.
117
+ end
110
118
  io << buf
119
+
120
+ # Break here in case the sender doesn't close the
121
+ # connection on the final ACK.
122
+ break if total == @size
111
123
  end
124
+
125
+ socket.close
126
+ return true
127
+ rescue EOFError
128
+ return false
112
129
  end
113
130
 
114
131
  # @return [Boolean] True if the DCC originates from a private ip
@@ -544,8 +544,8 @@ module Cinch
544
544
  end
545
545
 
546
546
 
547
- if msg.message =~ /^\001DCC SEND (\S+) (\d+) (\d+)(?: (\d+))?\001$/
548
- process_dcc_send($1, $2, $3, $4, msg, events)
547
+ if msg.message =~ /^\001DCC SEND (?:"([^"]+)"|(\S+)) (\d+) (\d+)(?: (\d+))?\001$/
548
+ process_dcc_send($1 || $2, $3, $4, $5, msg, events)
549
549
  end
550
550
  end
551
551
 
@@ -24,6 +24,9 @@ module Cinch
24
24
 
25
25
  # @since 2.0.0
26
26
  def unregister_plugins(plugins)
27
+ if plugins == self
28
+ plugins = self.dup
29
+ end
27
30
  plugins.each { |plugin| unregister_plugin(plugin) }
28
31
  end
29
32
 
@@ -26,7 +26,7 @@ class String
26
26
  self.tr("a-z", "A-Z")
27
27
  when :rfc1459
28
28
  self.tr("a-z{}|~", "A-Z[]\\\\^")
29
- when :strict-rfc1459
29
+ when :"strict-rfc1459"
30
30
  self.tr("a-z{}|", "A-Z[]\\\\")
31
31
  end
32
32
  end
@@ -35,6 +35,12 @@ module Cinch
35
35
  # @param [String] payload
36
36
  # @return [String]
37
37
  def generate(user, password, payload)
38
+ # duplicate the passed strings because we are modifying them
39
+ # later and they might come from the configuration store or
40
+ # similar
41
+ user = user.dup
42
+ password = password.dup
43
+
38
44
  data = Base64.decode64(payload).force_encoding("ASCII-8BIT")
39
45
 
40
46
  p, g, y = unpack_payload(data)
@@ -294,7 +294,7 @@ module Cinch
294
294
  if @bot.irc.isupport["MONITOR"] > 0
295
295
  @bot.irc.send "MONITOR - #@name"
296
296
  else
297
- @monitored_timer.stop
297
+ @monitored_timer.stop if @monitored_timer
298
298
  end
299
299
 
300
300
  @monitored = false
@@ -1,4 +1,4 @@
1
1
  module Cinch
2
2
  # Version of the library
3
- VERSION = '2.0.3'
3
+ VERSION = '2.0.4'
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cinch
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-27 00:00:00.000000000 Z
12
+ date: 2013-02-05 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A simple, friendly DSL for creating IRC bots
15
15
  email:
@@ -47,6 +47,7 @@ files:
47
47
  - lib/cinch/isupport.rb
48
48
  - lib/cinch/helpers.rb
49
49
  - lib/cinch/handler.rb
50
+ - lib/cinch/#syncable.rb#
50
51
  - lib/cinch/handler_list.rb
51
52
  - lib/cinch/rubyext/module.rb
52
53
  - lib/cinch/rubyext/float.rb