syndi 0.1.1-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|