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.
- checksums.yaml +7 -0
- data/.yardopts +12 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +8 -0
- data/LICENSE +28 -0
- data/README.md +104 -0
- data/Rakefile +30 -0
- data/WINDOWS.md +64 -0
- data/bin/syndi +102 -0
- data/bin/syndi-conf +47 -0
- data/conf/example.yml +101 -0
- data/docs/Events.md +103 -0
- data/docs/Upgrade.md +16 -0
- data/ext/csyndi/events.c +50 -0
- data/ext/csyndi/extconf.rb +20 -0
- data/ext/csyndi/integer.c +53 -0
- data/ext/csyndi/libauto.c +37 -0
- data/ext/csyndi/logger.c +229 -0
- data/include/syndi.h +22 -0
- data/include/syndi/csyndi.h +38 -0
- data/include/syndi/events.h +19 -0
- data/include/syndi/integer.h +17 -0
- data/include/syndi/logger.h +56 -0
- data/lib/csyndi.so +0 -0
- data/lib/syndi.rb +137 -0
- data/lib/syndi/actress.rb +12 -0
- data/lib/syndi/api.rb +7 -0
- data/lib/syndi/api/object.rb +29 -0
- data/lib/syndi/bot.rb +266 -0
- data/lib/syndi/config.rb +113 -0
- data/lib/syndi/dsl/base.rb +74 -0
- data/lib/syndi/dsl/irc.rb +13 -0
- data/lib/syndi/events.rb +130 -0
- data/lib/syndi/irc.rb +8 -0
- data/lib/syndi/irc/common.rb +63 -0
- data/lib/syndi/irc/library.rb +89 -0
- data/lib/syndi/irc/object/channel.rb +21 -0
- data/lib/syndi/irc/object/entity.rb +90 -0
- data/lib/syndi/irc/object/message.rb +99 -0
- data/lib/syndi/irc/object/user.rb +139 -0
- data/lib/syndi/irc/protocol.rb +161 -0
- data/lib/syndi/irc/protocol/numerics.rb +60 -0
- data/lib/syndi/irc/sasl/diffie_hellman.rb +36 -0
- data/lib/syndi/irc/sasl/mech.rb +7 -0
- data/lib/syndi/irc/sasl/mech/dh_blowfish.rb +83 -0
- data/lib/syndi/irc/sasl/mech/plain.rb +39 -0
- data/lib/syndi/irc/server.rb +301 -0
- data/lib/syndi/irc/state/channel_manager.rb +6 -0
- data/lib/syndi/irc/state/support.rb +142 -0
- data/lib/syndi/irc/state/user_manager.rb +6 -0
- data/lib/syndi/irc/std/commands.rb +99 -0
- data/lib/syndi/irc/std/numerics.rb +216 -0
- data/lib/syndi/jewel.rb +5 -0
- data/lib/syndi/jewel/specification.rb +121 -0
- data/lib/syndi/jewel/util.rb +27 -0
- data/lib/syndi/rubyext/string.rb +10 -0
- data/lib/syndi/verbosity.rb +10 -0
- data/lib/syndi/version.rb +38 -0
- data/spec/helper.rb +37 -0
- data/spec/syndi/events_spec.rb +89 -0
- data/tasks/compile.rake +15 -0
- data/tasks/install.rake +10 -0
- data/tasks/package.rake +13 -0
- data/tasks/spec.rake +12 -0
- metadata +243 -0
data/lib/syndi/config.rb
ADDED
@@ -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:
|
data/lib/syndi/events.rb
ADDED
@@ -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,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:
|