cinchrb / cinch

The IRC Bot Building Framework
http://www.rubydoc.info/gems/cinch
MIT License
1k stars 180 forks source link

Using Cinch::Channel.new() instead of Channel() won't sync attributes #203

Closed simmel closed 8 years ago

simmel commented 9 years ago

Trying to use Cinch from Lita but I can reproduce it by using a modified version of the example:

#/usr/bin/env ruby
require 'cinch'
require 'pp'

bot = Cinch::Bot.new do
  configure do |c|
    c.server = "localhost"
    c.channels = ["#marvintesting"]
  end

  on :message, "hello" do |m|
    pp Cinch::Channel.new("#marvintesting", bot).users
  end
end

bot.start
$ ./bot.rb
[2015/06/29 19:57:59.993] !! [on handler] Registering handler with pattern `#<Cinch::Pattern:0x9bbb134 @prefix=/^/, @pattern=/hello/, @suffix=/$/>`, reacting on `message`
[2015/06/29 19:57:59.994] !! [on handler] Registering handler with pattern `#<Cinch::Pattern:0x9bba248 @prefix=nil, @pattern=//, @suffix=nil>`, reacting on `connect`
[2015/06/29 19:57:59.995] !! [on handler] Registering handler with pattern `#<Cinch::Pattern:0x9bb97bc @prefix=nil, @pattern=//, @suffix=nil>`, reacting on `disconnect`
[2015/06/29 19:57:59.995] II Connecting to localhost:6667
[2015/06/29 19:58:00.001] << CAP LS
[2015/06/29 19:58:00.002] << NICK cinch
[2015/06/29 19:58:00.004] << USER cinch 0 * :cinch
[2015/06/29 19:58:00.005] >> :irc.example.net CAP * LS :multi-prefix
[2015/06/29 19:58:00.008] << CAP REQ :multi-prefix
[2015/06/29 19:58:00.041] >> :irc.example.net CAP cinch ACK :multi-prefix
[2015/06/29 19:58:00.043] << CAP END
[2015/06/29 19:58:00.045] >> :irc.example.net 001 cinch :Welcome to the Internet Relay Network cinch!~cinch@localhost
[2015/06/29 19:58:00.048] >> :irc.example.net 002 cinch :Your host is irc.example.net, running version ngircd-21 (i686/pc/linux-gnu)
[2015/06/29 19:58:00.051] II Detected IRCd: ngircd
[2015/06/29 19:58:00.052] >> :irc.example.net 003 cinch :This server has been started Tue Jun 23 2015 at 17:47:14 (CEST)
[2015/06/29 19:58:00.055] >> :irc.example.net 004 cinch irc.example.net ngircd-21 abBcCioqrRswx abehiIklmMnoOPqQrRstvVz
[2015/06/29 19:58:00.068] >> :irc.example.net 005 cinch RFC2812 IRCD=ngIRCd CHARSET=UTF-8 CASEMAPPING=ascii PREFIX=(qaohv)~&@%+ CHANTYPES=#&+ CHANMODES=beI,,imMnOPQRstVz CHANLIMIT=#&+:10 :are supported on this server
[2015/06/29 19:58:00.073] !! [New thread] For #<Cinch::Handler @event=:connect pattern=#<Cinch::Pattern:0x9bba248 @prefix=nil, @pattern=//, @suffix=nil>>: #<Thread:0x9b3d978> -- 1 in total.
[2015/06/29 19:58:00.075] >> :irc.example.net 005 cinch CHANNELLEN=50 NICKLEN=9 TOPICLEN=490 AWAYLEN=127 KICKLEN=400 MODES=5 MAXLIST=beI:50 EXCEPTS=e INVEX=I PENALTY :are supported on this server
[2015/06/29 19:58:00.079] !! [timer] Starting timer <Cinch::Timer 0/1 shots, 0s interval, threaded, not started, block: #<Proc:0x9bba518@/var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/bot.rb:264>>
[2015/06/29 19:58:00.083] !! [Thread done] For #<Cinch::Handler @event=:connect pattern=#<Cinch::Pattern:0x9bba248 @prefix=nil, @pattern=//, @suffix=nil>>: #<Thread:0x9b3d978> -- 0 remaining.
[2015/06/29 19:58:00.087] >> :irc.example.net 251 cinch :There are 2 users and 0 services on 1 servers
[2015/06/29 19:58:00.088] << JOIN #marvintesting
[2015/06/29 19:58:00.089] >> :irc.example.net 254 cinch 2 :channels formed
[2015/06/29 19:58:00.091] >> :irc.example.net 255 cinch :I have 2 users, 0 services and 0 servers
[2015/06/29 19:58:00.092] >> :irc.example.net 265 cinch 2 2 :Current local users: 2, Max: 2
[2015/06/29 19:58:00.094] >> :irc.example.net 266 cinch 2 2 :Current global users: 2, Max: 2
[2015/06/29 19:58:00.095] >> :irc.example.net 250 cinch :Highest connection count: 2 (69 connections received)
[2015/06/29 19:58:00.097] >> :irc.example.net 375 cinch :- irc.example.net message of the day
[2015/06/29 19:58:00.098] >> :irc.example.net 372 cinch :- **************************************************
[2015/06/29 19:58:00.099] >> :irc.example.net 372 cinch :- *             H    E    L    L    O              *
[2015/06/29 19:58:00.101] >> :irc.example.net 372 cinch :- *  This is a private irc server. Please contact  *
[2015/06/29 19:58:00.102] >> :irc.example.net 372 cinch :- *  the admin of the server for any questions or  *
[2015/06/29 19:58:00.104] >> :irc.example.net 372 cinch :- *  issues.                                       *
[2015/06/29 19:58:00.105] >> :irc.example.net 372 cinch :- **************************************************
[2015/06/29 19:58:00.107] >> :irc.example.net 372 cinch :- *  The software was provided as a package of     *
[2015/06/29 19:58:00.111] >> :irc.example.net 372 cinch :- *  Debian GNU/Linux <http://www.debian.org/>.    *
[2015/06/29 19:58:00.113] >> :irc.example.net 372 cinch :- *  However, Debian has no control over this      *
[2015/06/29 19:58:00.114] >> :irc.example.net 372 cinch :- *  server.                                       *
[2015/06/29 19:58:00.116] >> :irc.example.net 372 cinch :- **************************************************
[2015/06/29 19:58:00.117] >> :irc.example.net 376 cinch :End of MOTD command
[2015/06/29 19:58:01.046] >> :cinch!~cinch@localhost JOIN :#marvintesting
[2015/06/29 19:58:01.049] >> :irc.example.net 353 cinch = #marvintesting :cinch @simmel
[2015/06/29 19:58:01.053] << WHO #marvintesting
[2015/06/29 19:58:01.054] << MODE #marvintesting +b
[2015/06/29 19:58:01.055] >> :irc.example.net 366 cinch #marvintesting :End of NAMES list
[2015/06/29 19:58:01.056] << MODE #marvintesting
[2015/06/29 19:58:01.057] >> :irc.example.net 352 cinch #marvintesting ~cinch localhost irc.example.net cinch H :0 cinch
[2015/06/29 19:58:01.058] >> :irc.example.net 352 cinch #marvintesting ~simmel localhost irc.example.net simmel H@ :0 Simon Lundström
[2015/06/29 19:58:01.059] >> :irc.example.net 315 cinch #marvintesting :End of WHO list
[2015/06/29 19:58:03.056] >> :irc.example.net 368 cinch #marvintesting :End of channel ban list
[2015/06/29 19:58:04.057] >> :irc.example.net 324 cinch #marvintesting +
[2015/06/29 19:58:04.059] >> :irc.example.net 329 cinch #marvintesting 1435261954
[2015/06/29 19:58:19.835] >> :simmel!~simmel@localhost PRIVMSG #marvintesting :hello
[2015/06/29 19:58:19.837] !! [New thread] For #<Cinch::Handler @event=:message pattern=#<Cinch::Pattern:0x9bbb134 @prefix=/^/, @pattern=/hello/, @suffix=/$/>>: #<Thread:0x9b4a86c> -- 1 in total.
[2015/06/29 19:58:19.839] << NAMES #marvintesting
[2015/06/29 19:58:19.841] >> :irc.example.net 353 cinch = #marvintesting :cinch @simmel
[2015/06/29 19:58:19.843] >> :irc.example.net 366 cinch #marvintesting :End of NAMES list
[2015/06/29 19:58:29.758] !! A synced attribute ('users' for #<Channel name="#marvintesting">) has not been available for 10 seconds, still waiting
[2015/06/29 19:58:29.759] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/syncable.rb:67:in `attr'
[2015/06/29 19:58:29.760] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/rubyext/module.rb:10:in `block in synced_attr_reader'
[2015/06/29 19:58:29.760] !!   ./bot.rb:12:in `block (2 levels) in <main>'
[2015/06/29 19:58:29.760] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/handler.rb:97:in `instance_exec'
[2015/06/29 19:58:29.761] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/handler.rb:97:in `block in call'
[2015/06/29 19:58:39.782] !! A synced attribute ('users' for #<Channel name="#marvintesting">) has not been available for 20 seconds, still waiting
[2015/06/29 19:58:39.782] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/syncable.rb:67:in `attr'
[2015/06/29 19:58:39.783] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/rubyext/module.rb:10:in `block in synced_attr_reader'
[2015/06/29 19:58:39.783] !!   ./bot.rb:12:in `block (2 levels) in <main>'
[2015/06/29 19:58:39.783] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/handler.rb:97:in `instance_exec'
[2015/06/29 19:58:39.784] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/handler.rb:97:in `block in call'
[2015/06/29 19:58:49.804] !! A synced attribute ('users' for #<Channel name="#marvintesting">) has not been available for 30 seconds, still waiting
[2015/06/29 19:58:49.804] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/syncable.rb:67:in `attr'
[2015/06/29 19:58:49.805] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/rubyext/module.rb:10:in `block in synced_attr_reader'
[2015/06/29 19:58:49.805] !!   ./bot.rb:12:in `block (2 levels) in <main>'
[2015/06/29 19:58:49.805] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/handler.rb:97:in `instance_exec'
[2015/06/29 19:58:49.806] !!   /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/handler.rb:97:in `block in call'
[2015/06/29 19:58:49.806] !!   Giving up...
[2015/06/29 19:58:49.807] !! /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/syncable.rb:21:in `wait_until_synced': 'users' for #<Channel name="#marvintesting"> (Cinch::Exceptions::SyncedAttributeNotAvailable)
[2015/06/29 19:58:49.807] !!    /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/syncable.rb:67:in `attr'
[2015/06/29 19:58:49.807] !!    /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/rubyext/module.rb:10:in `block in synced_attr_reader'
[2015/06/29 19:58:49.808] !!    ./bot.rb:12:in `block (2 levels) in <main>'
[2015/06/29 19:58:49.808] !!    /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/handler.rb:97:in `instance_exec'
[2015/06/29 19:58:49.808] !!    /var/lib/gems/2.0.0/gems/cinch-2.2.5/lib/cinch/handler.rb:97:in `block in call'
[2015/06/29 19:58:49.809] !! [Thread done] For #<Cinch::Handler @event=:message pattern=#<Cinch::Pattern:0x9bbb134 @prefix=/^/, @pattern=/hello/, @suffix=/$/>>: #<Thread:0x9b4a86c> -- 0 remaining.

here it's connected to ngircd but I get the same problem when connecting to freenode.

$ gem list
bundler (1.9.8)
byebug (4.0.5)
cinch (2.2.5)
coderay (1.1.0)
columnize (0.9.0)
diff-lcs (1.2.5)
faraday (0.9.1)
htmlentities (4.3.3)
http_router (0.11.1)
i18n (0.7.0)
ice_nine (0.11.1)
lita (4.4.1, 4.3.2)
method_source (0.8.2)
multi_json (1.11.1, 1.11.0)
multipart-post (2.0.0)
pry (0.10.1)
pry-byebug (3.1.0)
puma (2.11.3, 2.11.2)
rack (1.6.1)
rack-test (0.6.3)
rake (10.4.2)
rb-readline (0.5.3, 0.5.2)
redis (3.2.1)
redis-namespace (1.5.2)
rspec (3.2.0)
rspec-core (3.2.3)
rspec-expectations (3.2.1)
rspec-mocks (3.2.1)
rspec-support (3.2.2)
slop (3.6.0)
thor (0.19.1)
url_mount (0.2.1)
dominikh commented 9 years ago

You're not supposed to use Channel.new. The correct alternative to the Channel() helper would be ChannelList#find_ensured, so e.g. bot.channel_list.find_ensured("#foo").

The attribute syncing relies on the multiton pattern. It assumes that for each channel, there is only exactly one instance. Whether or not that's a wart in Cinch's design can be argued, but that's the way it is.

This is probably a documentation issue.

simmel commented 9 years ago

On Mon, 2015-06-29 at 11:36:25 -0700, Dominik Honnef wrote:

You're not supposed to use Channel.new. The correct alternative to the Channel() helper would be ChannelList#find_ensured, so e.g. bot.channel_list.find_ensured("#foo").

OIC, that works perfectly! I'm guessing that User.new vs. bot.user_list.find_ensured("nick") works the same way?

The attribute syncing relies on the multiton pattern. It assumes that for each channel, there is only exactly one instance.

Can't you make classes or initialization method private (not that it matters much in Ruby but hey. Atleast it's some kind of indication that you shouldn't use them).

This is probably a documentation issue.

Agreed. Any idea where to document it? Common {tasks,mistakes}? I can take a stab at a documentation PR if you'd like?

dominikh commented 9 years ago

Yes, the same applies to users. Making new private wouldn't really work; then nobody could create the required instances (without resorting to send).

The best place to document this are probably the docstrings for User#initialize and Channel#initialize, as well as the documentation for the classes themselves.

simmel commented 9 years ago

How's that? I didn't quite understand what you meant by "as well as the documentation for the classes themselves" though, please elaborate.

How do you generate the docs? rdoc didn't get all the tags correct so I haven't really checked if it works.

dominikh commented 9 years ago

This is what I meant:

# This is the documentation of Channel.
class Channel
  # This is the documentation of #initialize.
  def initialize; end
end

The documentation is generated by YARD

simmel commented 9 years ago

How does that look?