syndi 0.1.1-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +12 -0
  3. data/CHANGELOG.md +0 -0
  4. data/Gemfile +8 -0
  5. data/LICENSE +28 -0
  6. data/README.md +104 -0
  7. data/Rakefile +30 -0
  8. data/WINDOWS.md +64 -0
  9. data/bin/syndi +102 -0
  10. data/bin/syndi-conf +47 -0
  11. data/conf/example.yml +101 -0
  12. data/docs/Events.md +103 -0
  13. data/docs/Upgrade.md +16 -0
  14. data/ext/csyndi/events.c +50 -0
  15. data/ext/csyndi/extconf.rb +20 -0
  16. data/ext/csyndi/integer.c +53 -0
  17. data/ext/csyndi/libauto.c +37 -0
  18. data/ext/csyndi/logger.c +229 -0
  19. data/include/syndi.h +22 -0
  20. data/include/syndi/csyndi.h +38 -0
  21. data/include/syndi/events.h +19 -0
  22. data/include/syndi/integer.h +17 -0
  23. data/include/syndi/logger.h +56 -0
  24. data/lib/csyndi.so +0 -0
  25. data/lib/syndi.rb +137 -0
  26. data/lib/syndi/actress.rb +12 -0
  27. data/lib/syndi/api.rb +7 -0
  28. data/lib/syndi/api/object.rb +29 -0
  29. data/lib/syndi/bot.rb +266 -0
  30. data/lib/syndi/config.rb +113 -0
  31. data/lib/syndi/dsl/base.rb +74 -0
  32. data/lib/syndi/dsl/irc.rb +13 -0
  33. data/lib/syndi/events.rb +130 -0
  34. data/lib/syndi/irc.rb +8 -0
  35. data/lib/syndi/irc/common.rb +63 -0
  36. data/lib/syndi/irc/library.rb +89 -0
  37. data/lib/syndi/irc/object/channel.rb +21 -0
  38. data/lib/syndi/irc/object/entity.rb +90 -0
  39. data/lib/syndi/irc/object/message.rb +99 -0
  40. data/lib/syndi/irc/object/user.rb +139 -0
  41. data/lib/syndi/irc/protocol.rb +161 -0
  42. data/lib/syndi/irc/protocol/numerics.rb +60 -0
  43. data/lib/syndi/irc/sasl/diffie_hellman.rb +36 -0
  44. data/lib/syndi/irc/sasl/mech.rb +7 -0
  45. data/lib/syndi/irc/sasl/mech/dh_blowfish.rb +83 -0
  46. data/lib/syndi/irc/sasl/mech/plain.rb +39 -0
  47. data/lib/syndi/irc/server.rb +301 -0
  48. data/lib/syndi/irc/state/channel_manager.rb +6 -0
  49. data/lib/syndi/irc/state/support.rb +142 -0
  50. data/lib/syndi/irc/state/user_manager.rb +6 -0
  51. data/lib/syndi/irc/std/commands.rb +99 -0
  52. data/lib/syndi/irc/std/numerics.rb +216 -0
  53. data/lib/syndi/jewel.rb +5 -0
  54. data/lib/syndi/jewel/specification.rb +121 -0
  55. data/lib/syndi/jewel/util.rb +27 -0
  56. data/lib/syndi/rubyext/string.rb +10 -0
  57. data/lib/syndi/verbosity.rb +10 -0
  58. data/lib/syndi/version.rb +38 -0
  59. data/spec/helper.rb +37 -0
  60. data/spec/syndi/events_spec.rb +89 -0
  61. data/tasks/compile.rake +15 -0
  62. data/tasks/install.rake +10 -0
  63. data/tasks/package.rake +13 -0
  64. data/tasks/spec.rake +12 -0
  65. metadata +243 -0
@@ -0,0 +1,113 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ require 'psych'
5
+ require 'syndi/verbosity'
6
+ require 'csyndi'
7
+
8
+ # Namespace: Syndi
9
+ module Syndi
10
+
11
+ # A class which provides a functional, simple configuration interface. It uses
12
+ # YAML by means of Psych.
13
+ #
14
+ # @api Syndi
15
+ # @since 4.0.0
16
+ # @author noxgirl
17
+ # @author swarley
18
+ #
19
+ # @!attribute conf
20
+ # @return [Hash{}] This is the hash which contains the data parsed from
21
+ # the configuration file.
22
+ # @see #[]
23
+ class Config
24
+
25
+ attr_reader :conf, :type
26
+
27
+ # Produce a new instance, and attempt to parse.
28
+ #
29
+ # @param [String] filepath Path to configuration file.
30
+ def initialize filepath
31
+ $m.verbose("Trying to initialize configuration from '#{filepath}'...", VSIMPLE) do
32
+ @path = filepath
33
+ parse
34
+ end # verbose
35
+ end
36
+
37
+ # Rehash the configuration.
38
+ #
39
+ # If an error occurs, it will revert the configuration to its prior state
40
+ # so that everything can continue to function.
41
+ def rehash!
42
+
43
+ $m.debug("Configuration file is rehashing.")
44
+
45
+ # Keep the old configuration in case of issues.
46
+ oldconf = @conf
47
+ @conf = {}
48
+
49
+ # Rehash
50
+ parse!
51
+
52
+ # Ensure it really succeeded.
53
+ if @conf.empty? or !@conf.instance_of? Hash
54
+ # Nope. Restore old configuration.
55
+ @conf = oldconf
56
+ $m.error 'Failed to rehash the configuration file (parser produced empty config)! Reverting to old configuration.'
57
+ return 0
58
+ end
59
+
60
+ $m.events.call :rehash
61
+
62
+ # This rescue is applicable to anything that happens in here, since if it is reached, there really was an error in general.
63
+ rescue => e
64
+ $m.error 'Failed to rehash configuration file! Reverting to old configuration.', false, e.backtrace
65
+ @conf = oldconf
66
+ return 0
67
+ end
68
+
69
+ # Return value of @conf[key].
70
+ #
71
+ # @return [Object] Value of @conf[key].
72
+ # @see @conf
73
+ def [] key
74
+ @conf[key]
75
+ end
76
+
77
+ #######
78
+ private
79
+ #######
80
+
81
+ # Parse the configuration file, and output the data to {#x}.
82
+ #
83
+ # @raise [ConfigError] If the file does not exist.
84
+ # @raise [ConfigError] If the file cannot be processed.
85
+ def parse
86
+
87
+ # Ensure foremost that the configuration file exists.
88
+ unless File.exists? @path
89
+ raise ConfigError, "Configuration file '#@path' does not exist!"
90
+ end
91
+
92
+ # Get the data from the file.
93
+ f = File.open(@path)
94
+ data = f.read
95
+ f.close
96
+
97
+ conf = {}
98
+ # Process the YAML.
99
+ begin
100
+ conf = Psych.load data
101
+ rescue => e
102
+ raise ConfigError, "Failed to process the YAML in '#@path'", e.backtrace
103
+ end
104
+
105
+ @conf = conf
106
+
107
+ end # def parse
108
+
109
+ end # class Config
110
+
111
+ end # module Syndi
112
+
113
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,74 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ # Namespace: Syndi
5
+ module Syndi
6
+
7
+ # Namespace: DSL
8
+ module DSL
9
+
10
+ # A domain-specific language (DSL) wrapper mixin for simple usage of the events
11
+ # system, {Syndi::API::Events}, and the timers system, {Syndi::API::Timers}.
12
+ #
13
+ # @api DSL
14
+ # @author noxgirl
15
+ # @since 4.0.0
16
+ #
17
+ # @see Syndi::API::Events
18
+ # @see Syndi::API::Timers
19
+ module Base
20
+
21
+ # @see Syndi::API::Timers#spawn
22
+ def clock_do(*args); $m.clock.spawn(*args); end
23
+ # @see Syndi::API::Timers#del
24
+ def clock_stop(*args); $m.clock.del(*args); end
25
+
26
+ # Hook onto an event.
27
+ #
28
+ # @param [Symbol] system The events system to access.
29
+ # @param [Symbol] event The event onto which to hook.
30
+ #
31
+ # @see Syndi::API::Events#on
32
+ def on(sys, event, &prc)
33
+ if sys == :syndi # central system
34
+ $m.events.on(event, prc)
35
+ else
36
+ $m.send(sys).events.on(event, prc) if $m.respond_to? sys
37
+ end
38
+ end
39
+
40
+ # Emit an event.
41
+ #
42
+ # @param [Symbol] system The events system to access.
43
+ # @param [Symbol] event The event onto which to hook.
44
+ #
45
+ # @see Syndi::API::Events#call
46
+ def emit(sys, event, *args)
47
+ if sys == :syndi # central system
48
+ $m.events.call(event, *args)
49
+ else
50
+ $m.send(sys).events.call(event, *args) if $m.respond_to? sys
51
+ end
52
+ end
53
+
54
+ # Delete a hook.
55
+ #
56
+ # @param [Symbol] system The events system to access.
57
+ # @param [Array(Symbol, Integer, String)] hook The identification data of the hook.
58
+ #
59
+ # @see Syndi::API::Events#del
60
+ def undo_on(sys, hook)
61
+ if sys == :syndi # central system
62
+ $m.events.del(hook)
63
+ else
64
+ $m.send(sys).events.del(hook) if $m.respond_to? sys
65
+ end
66
+ end
67
+
68
+ end # module Base
69
+
70
+ end # module DSL
71
+
72
+ end # module Syndi
73
+
74
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ module Syndi
5
+ module DSL
6
+ module IRC
7
+ # ok
8
+ end
9
+ end
10
+ end
11
+
12
+
13
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,130 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ require 'syndi/verbosity'
5
+
6
+ module Syndi
7
+
8
+ # A simple event management system, designed particularly for Syndi.
9
+ #
10
+ # @!attribute [r] events
11
+ # @return [Hash{Symbol => Array<Syndi::Events::Listener>}] The collection of events and associated listeners.
12
+ class Events
13
+
14
+ attr_reader :events
15
+
16
+ def initialize
17
+ @events = Hash.new
18
+ end
19
+
20
+ # Create a new listener on a given +event+, which will have the given
21
+ # block attached and executed upon the event's occurrence.
22
+ #
23
+ # @param [Symbol] event The event which to await.
24
+ # @param [Integer] priority The priority this listener should have in the hook
25
+ # execution procedure. Must be 1-5 with 1 being of utmost priority.
26
+ #
27
+ # @yield [...] The parameters passed when the event was broadcasted. This varies
28
+ # by event. See the official event reference for Syndi events.
29
+ #
30
+ # @return [Syndi::Events::Listener] The listener.
31
+ def on event, priority = 3, &prc
32
+ @events[event] ||= Array.new
33
+
34
+ if priority < 1 || priority > 5
35
+ raise ArgumentError, "invalid event priority specified"
36
+ end
37
+
38
+ hook = Listener.new self, event, priority, prc
39
+ @events[event] << hook
40
+ hook
41
+ end
42
+
43
+ # This will broadcast the given +event+, executing each listener and passing
44
+ # to it the parameters supplied here, respecting priority and operating in a
45
+ # thread.
46
+ #
47
+ # @param [Symbol] event
48
+ # @param [...] parameters The arguments to be passed to each listener.
49
+ def emit event, *parameters
50
+ if @events[event]
51
+
52
+ # collect the listeners with respect to priority
53
+ one, two, three, four, five = gather @events[event]
54
+
55
+ Syndi.log.verbose "event *#{event}* is being broadcasted on #{self}", VNOISY
56
+
57
+ # spawn a thread and perform the executions
58
+ Thread.new do
59
+ begin
60
+ # cease if status ever becomes false/nil
61
+ status = true
62
+
63
+ one.each { |code| status = code.call *parameters if status }
64
+ two.each { |code| status = code.call *parameters if status }
65
+ three.each { |code| status = code.call *parameters if status }
66
+ four.each { |code| status = code.call *parameters if status }
67
+ five.each { |code| status = code.call *parameters if status }
68
+ rescue => e
69
+ # catch thread errors
70
+ Syndi.log.error "A listener to a broadcast of #{event} on #{self} caused an exception to rise (#{e})", true
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+
77
+ def inspect
78
+ "<#Syndi::Events: obj_id=#{object_id} event_count=#{@events.length}>"
79
+ end
80
+ alias_method :to_s, :inspect
81
+
82
+ private
83
+
84
+ # Gather hooks.
85
+ def gather list
86
+ [list.collect { |hook| (hook.priority == 1 ? hook : nil) }.compact,
87
+ list.collect { |hook| (hook.priority == 2 ? hook : nil) }.compact,
88
+ list.collect { |hook| (hook.priority == 3 ? hook : nil) }.compact,
89
+ list.collect { |hook| (hook.priority == 4 ? hook : nil) }.compact,
90
+ list.collect { |hook| (hook.priority == 5 ? hook : nil) }.compact]
91
+ end
92
+
93
+ public
94
+
95
+ # A class which represents a listener.
96
+ class Listener
97
+ attr_reader :event, :priority, :code
98
+
99
+ # Spawn a new listener object.
100
+ def initialize sys, event, priority, prc
101
+ @sys = sys
102
+ @event = event
103
+ @priority = priority
104
+ @code = prc
105
+
106
+ Syndi.log.verbose "new listener spawned and attached to #{event}: #{self}", VNOISY
107
+ end
108
+
109
+ # Terminate this object.
110
+ def deaf
111
+ @sys.events[event].delete self
112
+ end
113
+
114
+ # Execute this listener.
115
+ def call *args
116
+ @code.call *args
117
+ end
118
+
119
+ def inspect
120
+ "<#Syndi::Events::Listener: sys=#@sys event=#@event priority=#@priority>"
121
+ end
122
+ alias_method :to_s, :inspect
123
+
124
+ end
125
+
126
+ end
127
+
128
+ end
129
+
130
+ # vim: set ts=4 sts=2 sw=2 et:
data/lib/syndi/irc.rb ADDED
@@ -0,0 +1,8 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ require 'syndi/irc/library'
5
+
6
+ LIBRARY_IRC = Syndi::IRC::Library.new
7
+
8
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ module Syndi
5
+
6
+ module IRC
7
+
8
+ # A class which manages such common IRC functions as syndijoining channels,
9
+ # and identifying to services the traditional PRIVMSG way.
10
+ class Common
11
+
12
+ # Construct a new common function handler.
13
+ #
14
+ # @param [Syndi::IRC::Library] lib The IRC library instance.
15
+ def initialize lib
16
+ @lib = lib
17
+ $m.events.on :die, &method(:do_die)
18
+ @lib.events.on :connected, &method(:do_syndijoin)
19
+ end
20
+
21
+ # Automatically identify with services the traditional way, which is
22
+ # to say by a /msg.
23
+ #
24
+ # @param [Syndi::IRC::Server] irc The IRC connection.
25
+ def do_identify irc
26
+ if $m.conf['irc'][irc.s]['nickIdentify']
27
+
28
+ # Assume the service is NickServ if not specified
29
+ service = $m.conf['irc'][irc.s]['nickIdentify']['service'] || 'NickServ'
30
+ # and assume the command is IDENTIFY if not specified
31
+ command = $m.conf['irc'][irc.s]['nickIdentify']['command'] || 'IDENTIFY'
32
+
33
+ # we can't actually /msg anyone yet.....
34
+ end
35
+ end
36
+
37
+ # Automatically join IRC channels upon connection.
38
+ #
39
+ # @param [Syndi::IRC::Server] irc The IRC connection.
40
+ def do_syndijoin irc
41
+ if $m.conf['irc'][irc.s]['syndijoin']
42
+
43
+ $m.conf['irc'][irc.s]['syndijoin'].each do |chan|
44
+ irc.join(chan['name'], chan['key']||nil)
45
+ end
46
+
47
+ end
48
+ end
49
+
50
+ # Disconnect from servers on termination.
51
+ #
52
+ # @param [String] reason Reason for termination.
53
+ def do_die reason
54
+ @lib.connections.each { |net, irc| irc.disconnect reason }
55
+ end
56
+
57
+ end # class Common
58
+
59
+ end # module IRC
60
+
61
+ end # module Syndi
62
+
63
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,89 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (see LICENSE).
3
+
4
+ require 'syndi/irc/server'
5
+ require 'syndi/irc/object/entity'
6
+ require 'syndi/irc/object/channel'
7
+ require 'syndi/irc/object/user'
8
+ require 'syndi/irc/protocol'
9
+ require 'syndi/irc/common'
10
+
11
+ module Syndi
12
+
13
+ module IRC
14
+
15
+ # The base of the IRC framework.
16
+ #
17
+ # @!attribute [r] events
18
+ # @return [Syndi::API::Events] The IRC event system.
19
+ #
20
+ # @!attribute [r] connections
21
+ # @return [Hash{String => Syndi::IRC::Server}] Collection of IRC connections.
22
+ class Library
23
+
24
+ attr_reader :events, :connections
25
+
26
+ def initialize
27
+
28
+ # Initialize our event system.
29
+ @events = Syndi::API::Events.new
30
+ # Prepare our collection of IRC server connections.
31
+ @connections = Hash.new
32
+
33
+ # Be ready to accept data.
34
+ $m.events.on :net_receive, 1, &method(:receive)
35
+
36
+ # Start connections when Syndi is started.
37
+ $m.events.on :start, &method(:start)
38
+
39
+ # Parse data.
40
+ @parser = Syndi::IRC::Protocol.new self
41
+
42
+ # Handle common functions.
43
+ @common = Syndi::IRC::Common.new self
44
+
45
+ end # def initialize
46
+
47
+ # Process incoming network data.
48
+ #
49
+ # @param [Object] socket_object The socket object, which in the case of
50
+ # ourselves should be an {Syndi::IRC::Server}, or we won't handle it.
51
+ def receive socket_object
52
+ if socket_object.instance_of? Syndi::IRC::Server
53
+ socket_object.recv
54
+ end
55
+ end
56
+
57
+ # Initiate IRC connections.
58
+ def start
59
+
60
+ # Iterate through each IRC server in the config, and connect to it.
61
+ $m.conf['irc'].each do |name, hash|
62
+ begin
63
+ # Configure the IRC instance.
64
+ @connections[name] = Syndi::IRC::Server.new(name) do |c|
65
+ c.address = hash['address']
66
+ c.port = hash['port']
67
+ c.nick = hash['nickname'][0]
68
+ c.user = hash['username']
69
+ c.real = hash['realName']
70
+ c.ssl = hash['useSSL']
71
+ end
72
+
73
+ # Connect.
74
+ $m.sockets << @connections[name]
75
+ @connections[name].connect
76
+ rescue => e
77
+ $m.error("Connection to #{name} failed: #{e}", false, e.backtrace)
78
+ end
79
+ end
80
+
81
+ end # def start
82
+
83
+ end # class Library
84
+
85
+ end # module IRC
86
+
87
+ end # module Syndi
88
+
89
+ # vim: set ts=4 sts=2 sw=2 et: