syndi 0.1.1-x86-mingw32

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.
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: