-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathircpp.cpp
213 lines (191 loc) · 7.47 KB
/
ircpp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include "ircpp.hpp"
#include <cassert>
#include <cstring>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>
#include <map>
IRCSession::IRCSession(char const* servername,
unsigned int port,
char const* password,
const char* nick,
const char* username,
const char* realname)
: session{nullptr}
{
session = irc_create_session(&IRC::callbacks);
if (session == nullptr)
throw std::runtime_error{"Could not create IRC session."};
irc_option_set( session, LIBIRC_OPTION_STRIPNICKS );
if (irc_connect(session, servername, port, password, nick,
username, realname))
throw std::runtime_error{"Could not initiate connection to server."};
IRC::session_map[session] = this;
}
IRCSession::~IRCSession() {
irc_disconnect(session);
IRC::session_map.erase(session);
}
// Methods to be overloaded by subclasses
void IRCSession::on_connect() { }
void IRCSession::on_nick(string_t origin, string_t nick) { }
void IRCSession::on_quit(string_t origin, string_t reason) { }
void IRCSession::on_join(string_t origin, string_t channel) { }
void IRCSession::on_part(string_t origin, string_t channel, string_t reason) { }
void IRCSession::on_channel(string_t origin, string_t channel, string_t msg) { }
void IRCSession::on_privmsg(string_t origin, string_t yourname, string_t msg) { }
void IRCSession::on_numeric(unsigned int event, char const * origin,
char const ** params, unsigned int count) {}
// methods used by subclasses
void IRCSession::join(string_t channel) {
if (irc_cmd_join( session, channel, 0 ))
throw std::runtime_error{"Could not join channel."};
}
void IRCSession::join(string_t channel, string_t password) {
if (irc_cmd_join( session, channel, password))
throw std::runtime_error{"Could not join channel."};
}
void IRCSession::part(string_t channel) {
if (irc_cmd_part( session, channel))
throw std::runtime_error{"Could not part channel."};
}
void IRCSession::msg(string_t target, string_t m) {
if (irc_cmd_msg( session, target, m))
throw std::runtime_error{"Could not send message."};
}
void IRCSession::notice(string_t target, string_t m) {
if (irc_cmd_notice( session, target, m))
throw std::runtime_error{"Could not send notice."};
}
void IRCSession::me(string_t target, string_t m) {
if (irc_cmd_me( session, target, m))
throw std::runtime_error{"Could not send me."};
}
void IRCSession::invite(string_t nick, string_t channel) {
if (irc_cmd_invite( session, nick, channel))
throw std::runtime_error{"Could not send invite."};
}
void IRCSession::names(string_t channel) {
if (irc_cmd_names( session, channel))
throw std::runtime_error{"Could not get names."};
}
void IRCSession::disconnect() {
irc_disconnect(session);
}
// Used when there is only one session and we want the default handler
void IRCSession::run() {
if (irc_run(session))
throw std::runtime_error{"Could not start main irc listening loop."};
}
// Functions wrapping select statements
void IRCSession::add_select_descriptors(fd_set* in_set, fd_set* out_set, int* maxfd) {
if (irc_add_select_descriptors(session, in_set, out_set, maxfd))
throw std::runtime_error{"Could not add select descriptors; session not connected."};
}
void IRCSession::process_select_descriptors(fd_set* in_set, fd_set* out_set) {
if (irc_process_select_descriptors(session, in_set, out_set))
resolve_errno();
}
// Handle errors
void IRCSession::resolve_errno() {
int err = irc_errno(session);
const char* msg = irc_strerror(err);
std::stringstream ss;
ss << "Irc errno " << err << ": " << msg;
throw std::runtime_error{ss.str()};
}
// All the callbacks.... :<
void IRC::event_connect(struct irc_session_s* sess, char const *
event, char const * origin, char const **
params, unsigned int count)
{
auto irc_s = session_map.find(sess);
if (irc_s != session_map.end())
irc_s->second->on_connect();
}
void IRC::event_nick(struct irc_session_s* sess, char const *
event, char const * origin, char const **
params, unsigned int count)
{
assert(count == 1);
auto irc_s = session_map.find(sess);
if (irc_s != session_map.end())
irc_s->second->on_nick(origin, params[0]);
}
void IRC::event_quit(struct irc_session_s* sess, char const *
event, char const * origin, char const **
params, unsigned int count)
{
auto irc_s = session_map.find(sess);
if (irc_s != session_map.end()) {
if (count == 1)
irc_s->second->on_quit(origin, params[0]);
else
irc_s->second->on_quit(origin, "");
}
}
void IRC::event_join(struct irc_session_s* sess, char const *
event, char const * origin, char const **
params, unsigned int count)
{
auto irc_s = session_map.find(sess);
if (irc_s != session_map.end())
irc_s->second->on_join(origin, params[0]);
}
void IRC::event_channel(struct irc_session_s* sess, char const *
event, char const * origin, char const **
params, unsigned int count)
{
auto irc_s = session_map.find(sess);
if (irc_s != session_map.end()) {
if (count == 2)
irc_s->second->on_channel(origin, params[0], params[1]);
else
irc_s->second->on_channel(origin, params[0], "");
}
}
void IRC::event_privmsg(struct irc_session_s* sess, char const *
event, char const * origin, char const **
params, unsigned int count)
{
auto irc_s = session_map.find(sess);
if (irc_s != session_map.end()) {
if (count == 2)
irc_s->second->on_privmsg(origin, params[0], params[1]);
else
irc_s->second->on_privmsg(origin, params[0], "");
}
}
void IRC::event_numeric(struct irc_session_s* sess, unsigned int
event, char const * origin, char const **
params, unsigned int count)
{
auto irc_s = session_map.find(sess);
if (irc_s != session_map.end())
irc_s->second->on_numeric(event, origin, params, count);
}
irc_callbacks_t IRC::callbacks{
IRC::event_connect, // irc_event_callback_t event_connect;
IRC::event_nick, // irc_event_callback_t event_nick;
IRC::event_quit, // irc_event_callback_t event_quit;
IRC::event_join, // irc_event_callback_t event_join;
IRC::event_part, // irc_event_callback_t event_part;
IRC::event_mode, // irc_event_callback_t event_mode;
IRC::event_umode, // irc_event_callback_t event_umode;
IRC::event_topic, // irc_event_callback_t event_topic;
IRC::event_kick, // irc_event_callback_t event_kick;
IRC::event_channel, // irc_event_callback_t event_channel;
IRC::event_privmsg, // irc_event_callback_t event_privmsg;
IRC::event_notice, // irc_event_callback_t event_notice;
IRC::event_channel_notice, // irc_event_callback_t event_channel_notice;
IRC::event_invite, // irc_event_callback_t event_invite;
IRC::event_ctcp_req, // irc_event_callback_t event_ctcp_req;
IRC::event_ctcp_rep, // irc_event_callback_t event_ctcp_rep;
IRC::event_ctcp_action, // irc_event_callback_t event_ctcp_action;
IRC::event_unknown, // irc_event_callback_t event_unknown;
IRC::event_numeric, // irc_eventcode_callback_t event_numeric;
IRC::event_dcc_chat_req, // irc_event_dcc_chat_t event_dcc_chat_req;
IRC::event_dcc_send_req // irc_event_dcc_send_t event_dcc_send_req;
};
IRC::session_map_t IRC::session_map{};