Explorar el Código

first post

master
achmizs hace 10 años
padre
commit
ec6b85968b

+ 30
- 0
IRCClient.xcodeproj/project.pbxproj Ver fichero

@@ -8,12 +8,26 @@

/* Begin PBXBuildFile section */
86F2EFEA1C21F73600B033A4 /* IRCClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F2EFE91C21F73600B033A4 /* IRCClient.h */; settings = {ATTRIBUTES = (Public, ); }; };
86F2EFF81C21F81900B033A4 /* IRCClientChannel_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F2EFF11C21F81900B033A4 /* IRCClientChannel_Private.h */; };
86F2EFF91C21F81900B033A4 /* IRCClientChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F2EFF21C21F81900B033A4 /* IRCClientChannel.h */; };
86F2EFFA1C21F81900B033A4 /* IRCClientChannel.m in Sources */ = {isa = PBXBuildFile; fileRef = 86F2EFF31C21F81900B033A4 /* IRCClientChannel.m */; };
86F2EFFB1C21F81900B033A4 /* IRCClientChannelDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F2EFF41C21F81900B033A4 /* IRCClientChannelDelegate.h */; };
86F2EFFC1C21F81900B033A4 /* IRCClientSession.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F2EFF51C21F81900B033A4 /* IRCClientSession.h */; };
86F2EFFD1C21F81900B033A4 /* IRCClientSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 86F2EFF61C21F81900B033A4 /* IRCClientSession.m */; };
86F2EFFE1C21F81900B033A4 /* IRCClientSessionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 86F2EFF71C21F81900B033A4 /* IRCClientSessionDelegate.h */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
86F2EFE61C21F73600B033A4 /* IRCClient.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IRCClient.framework; sourceTree = BUILT_PRODUCTS_DIR; };
86F2EFE91C21F73600B033A4 /* IRCClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IRCClient.h; sourceTree = "<group>"; };
86F2EFEB1C21F73600B033A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
86F2EFF11C21F81900B033A4 /* IRCClientChannel_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRCClientChannel_Private.h; sourceTree = "<group>"; };
86F2EFF21C21F81900B033A4 /* IRCClientChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRCClientChannel.h; sourceTree = "<group>"; };
86F2EFF31C21F81900B033A4 /* IRCClientChannel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IRCClientChannel.m; sourceTree = "<group>"; };
86F2EFF41C21F81900B033A4 /* IRCClientChannelDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRCClientChannelDelegate.h; sourceTree = "<group>"; };
86F2EFF51C21F81900B033A4 /* IRCClientSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRCClientSession.h; sourceTree = "<group>"; };
86F2EFF61C21F81900B033A4 /* IRCClientSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IRCClientSession.m; sourceTree = "<group>"; };
86F2EFF71C21F81900B033A4 /* IRCClientSessionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRCClientSessionDelegate.h; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
@@ -46,6 +60,13 @@
86F2EFE81C21F73600B033A4 /* IRCClient */ = {
isa = PBXGroup;
children = (
86F2EFF11C21F81900B033A4 /* IRCClientChannel_Private.h */,
86F2EFF21C21F81900B033A4 /* IRCClientChannel.h */,
86F2EFF31C21F81900B033A4 /* IRCClientChannel.m */,
86F2EFF41C21F81900B033A4 /* IRCClientChannelDelegate.h */,
86F2EFF51C21F81900B033A4 /* IRCClientSession.h */,
86F2EFF61C21F81900B033A4 /* IRCClientSession.m */,
86F2EFF71C21F81900B033A4 /* IRCClientSessionDelegate.h */,
86F2EFE91C21F73600B033A4 /* IRCClient.h */,
86F2EFEB1C21F73600B033A4 /* Info.plist */,
);
@@ -59,6 +80,11 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
86F2EFFE1C21F81900B033A4 /* IRCClientSessionDelegate.h in Headers */,
86F2EFF91C21F81900B033A4 /* IRCClientChannel.h in Headers */,
86F2EFFB1C21F81900B033A4 /* IRCClientChannelDelegate.h in Headers */,
86F2EFFC1C21F81900B033A4 /* IRCClientSession.h in Headers */,
86F2EFF81C21F81900B033A4 /* IRCClientChannel_Private.h in Headers */,
86F2EFEA1C21F73600B033A4 /* IRCClient.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -130,6 +156,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
86F2EFFD1C21F81900B033A4 /* IRCClientSession.m in Sources */,
86F2EFFA1C21F81900B033A4 /* IRCClientChannel.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -233,6 +261,7 @@
INFOPLIST_FILE = IRCClient/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.6;
PRODUCT_BUNDLE_IDENTIFIER = saidachmiz.IRCClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
@@ -251,6 +280,7 @@
INFOPLIST_FILE = IRCClient/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.6;
PRODUCT_BUNDLE_IDENTIFIER = saidachmiz.IRCClient;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;

+ 138
- 0
IRCClient/IRCClientChannel.h Ver fichero

@@ -0,0 +1,138 @@
/*
* Modified IRCClient Copyright 2015 Said Achmiz (www.saidachmiz.net)
*
* Original IRCClient Copyright (C) 2009 Nathan Ollerenshaw chrome@stupendous.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*/

/**
* @file IRCClientChannel.h
* @author Nathan Ollerenshaw
* @version 1.0
* @date 01.2009
* @brief Represents a connected IRC Channel.
*/

#import <Cocoa/Cocoa.h>
#import "IRCClientChannelDelegate.h"
#import "libircclient.h"

/** \class IRCClientChannel
* @brief Represents a connected IRC Channel.
*
* IRCClientChannel objects are created by the IRCClientSession object
* for a given session when the client joins an IRC channel.
*/

@class IRCClientSession;

#pragma mark IRCClientChannel class declaration

@interface IRCClientChannel : NSObject

/************************/
#pragma mark - Properties
/************************/

/** Delegate to send events to */
@property (assign) id <IRCClientChannelDelegate> delegate;

/** Name of the channel */
@property (nonatomic, retain) NSData *name;

/** Encoding used by, and in, this channel */
@property (assign) NSStringEncoding encoding;

/** Topic of the channel
*
* You can (attempt to) set the topic by using setChannelTopic:, not by
* changing this property (which is readonly). If the connected user has the
* privileges to set the channel topic, the channel's delegate will receive a
* topicSet:by: message (and the topic property of the channel object will be
* updated automatically).
*/
@property (nonatomic, readonly) NSData *topic;

/** Modes of the channel */
@property (nonatomic, retain) NSString *modes;

/** An array of nicknames stored as NSStrings that list the connected users
for the channel */
@property (nonatomic, readonly) NSArray *nicks;

/**************************/
#pragma mark - IRC commands
/**************************/

/** Parts the channel. */
- (int)part;

/** Invites another IRC client to the channel.
*
* @param nick the nickname of the client to invite.
*/
- (int)invite:(NSString *)nick;

/** Sets the topic of the channel.
*
* Note that not all users on a channel have permission to change the topic; if you fail
* to set the topic, then you will not see an onTopic event on the IRCClientChannelDelegate.
*
* @param aTopic the topic the client wishes to set for the channel.
*/
- (void)setChannelTopic:(NSString *)newTopic;

/** Sets the mode of the channel.
*
* Note that not all users on a channel have permission to change the mode; if you fail
* to set the mode, then you will not see a modeSet event on the IRCClientChannelDelegate.
*
* @param mode the mode to set the channel to
*/
- (int)setMode:(NSString *)mode params:(NSString *)params;

/** Sends a public PRIVMSG to the channel. If you try to send more than can fit on an IRC
buffer, it will be truncated.
@param message the message to send to the channel.
*/
- (int)message:(NSString *)message;

/** Sends a public CTCP ACTION to the channel.
*
* @param action action to send to the channel.
*/
- (int)action:(NSString *)action;

/** Sends a public NOTICE to the channel.
*
* @param notice message to send to the channel.
*/
- (int)notice:(NSString *)notice;

/** Kicks someone from a channel.
*
* @param nick the IRC client to kick from the channel.
* @param reason the message to give to the channel and the IRC client for the kick.
*/
- (int)kick:(NSString *)nick reason:(NSString *)reason;

/** Sends a CTCP request to the channel.
*
* It is perfectly legal to send a CTCP request to an IRC channel, however many clients
* decline to respond to them, and often they are percieved as annoying.
*
* @param request the string of the request, in CTCP format.
*/
- (int)ctcpRequest:(NSData *)request;

@end

+ 189
- 0
IRCClient/IRCClientChannel.m Ver fichero

@@ -0,0 +1,189 @@
/*
* Modified IRCClient Copyright 2015 Said Achmiz (www.saidachmiz.net)
*
* Original IRCClient Copyright (C) 2009 Nathan Ollerenshaw chrome@stupendous.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*/

#import "IRCClientChannel.h"
#import "IRCClientSession.h"
#import "IRCClientChannel_Private.h"

#pragma mark IRCClientChannel private category

@interface IRCClientChannel()
{
NSData *name;
irc_session_t *irc_session;
NSStringEncoding encoding;
NSData *topic;
NSString *modes;
NSMutableArray *nicks;
}

@property (nonatomic, retain) NSMutableArray *nicks;

@end

#pragma mark - IRCClientChannel class implementation

@implementation IRCClientChannel

#pragma mark - Property synthesis

@synthesize delegate;
@synthesize name;
@synthesize encoding;
@synthesize topic;
@synthesize modes;

#pragma mark - Custom accessors

-(NSArray *)nicks
{
NSArray* nicksCopy = [nicks copy];
return nicksCopy;
}

-(void)setNicks:(NSArray *)newNicks
{
nicks = [newNicks mutableCopy];
}

/**************************/
#pragma mark - Initializers
/**************************/

-(instancetype)initWithName:(NSData *)aName andIRCSession:(irc_session_t *)session
{
if ((self = [super init])) {
name = aName;
irc_session = session;
topic = [NSData dataWithBytes:@"".UTF8String length:1];
encoding = NSUTF8StringEncoding;
}
return self;
}

/**************************/
#pragma mark - IRC commands
/**************************/

- (int)part
{
return irc_cmd_part(irc_session, name.bytes);
}

- (int)invite:(NSString *)nick
{
return irc_cmd_invite(irc_session, nick.UTF8String, name.bytes);
}

- (int)refreshNames
{
return irc_cmd_names(irc_session, name.bytes);
}

- (void)setChannelTopic:(NSString *)newTopic
{
irc_cmd_topic(irc_session, name.bytes, [newTopic cStringUsingEncoding:encoding]);
}

- (int)setMode:(NSString *)mode params:(NSString *)params
{
NSMutableString* modeString = [mode mutableCopy];
if(params != nil && params.length > 0)
[modeString appendFormat:@" %@", params];
return irc_cmd_channel_mode(irc_session, name.bytes, modeString.UTF8String);
}

- (int)message:(NSString *)message
{
return irc_cmd_msg(irc_session, name.bytes, [message cStringUsingEncoding:encoding]);
}

- (int)action:(NSString *)action
{
return irc_cmd_me(irc_session, name.bytes, [action cStringUsingEncoding:encoding]);
}

- (int)notice:(NSString *)notice
{
return irc_cmd_notice(irc_session, name.bytes, [notice cStringUsingEncoding:encoding]);
}

- (int)kick:(NSString *)nick reason:(NSString *)reason
{
return irc_cmd_kick(irc_session, nick.UTF8String, name.bytes, [reason cStringUsingEncoding:encoding]);
}

- (int)ctcpRequest:(NSData *)request
{
return irc_cmd_ctcp_request(irc_session, name.bytes, request.bytes);
}

/****************************/
#pragma mark - Event handlers
/****************************/

- (void)userJoined:(NSString *)nick
{
[delegate userJoined:nick];
}

- (void)userParted:(NSString *)nick withReason:(NSData *)reason us:(BOOL)wasItUs
{
NSString* reasonString = [[NSString alloc] initWithData:reason encoding:encoding];
[delegate userParted:nick withReason:reasonString us:wasItUs];
}

- (void)modeSet:(NSString *)mode withParams:(NSString *)params by:(NSString *)nick
{
[delegate modeSet:mode withParams:params by:nick];
}

- (void)topicSet:(NSData *)newTopic by:(NSString *)nick
{
topic = newTopic;
NSString* topicString = [[NSString alloc] initWithData:topic encoding:encoding];
[delegate topicSet:topicString by:nick];
}

- (void)userKicked:(NSString *)nick withReason:(NSData *)reason by:(NSString *)byNick us:(BOOL)wasItUs
{
NSString* reasonString = [[NSString alloc] initWithData:reason encoding:encoding];
[delegate userKicked:nick withReason:reasonString by:byNick us:wasItUs];
}

- (void)messageSent:(NSData *)message byUser:(NSString *)nick
{
NSString* messageString = [[NSString alloc] initWithData:message encoding:encoding];
[delegate messageSent:messageString byUser:nick];
}

- (void)noticeSent:(NSData *)notice byUser:(NSString *)nick
{
NSString* noticeString = [[NSString alloc] initWithData:notice encoding:encoding];
[delegate noticeSent:noticeString byUser:nick];
}

- (void)actionPerformed:(NSData *)action byUser:(NSString *)nick
{
NSString* actionString = [[NSString alloc] initWithData:action encoding:encoding];
[delegate actionPerformed:actionString byUser:nick];
}

@end

+ 110
- 0
IRCClient/IRCClientChannelDelegate.h Ver fichero

@@ -0,0 +1,110 @@
/*
* Modified IRCClient Copyright 2015 Said Achmiz (www.saidachmiz.net)
*
* Original IRCClient Copyright (C) 2009 Nathan Ollerenshaw chrome@stupendous.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*/

/**
* @file IRCClientChannelDelegate.h
* @author Nathan Ollerenshaw
* @version 1.0
* @date 01.2009
* @brief Receives delegate messages from an IRCClientChannel.
* @protocol IRCClientChannelDelegate
*/

#import <Cocoa/Cocoa.h>

/** @brief Receives delegate messages from an IRCClientChannel.
*
* Each IRCClientChannel object needs a delegate. Delegate methods are called
* for each event that occurs on an IRC channel that the client is current on.
*
* Note that for any given parameter, it may be optional, in which case a nil
* object may be supplied instead of the given parameter.
*/

@protocol IRCClientChannelDelegate <NSObject>

/** When a client joins this channel, the userJoined event is fired. Note that
* the nickname is most likely in nick!user\@host format, but may simply be a
* nickname, depending on the server implementation.
*
* You should also expect to see this event when the client first joins a channel,
* with a parameter of the client's nickname.
*
* @param nick The nickname of the user that joined the channel.
*/
- (void)userJoined:(NSString *)nick;

/** When an IRC client parts a channel you are connect to, you will see
* an onPart event. You will also see this event when you part a channel.
*
* @param nick (required) The nickname of the user that left the channel.
* @param reason (optional) The reason, if any, that the user gave for leaving.
* @param wasItUs (required) Was it us who parted, or another user?
*/
- (void)userParted:(NSString *)nick withReason:(NSString *)reason us:(BOOL)wasItUs;

/** Received when an IRC client changes the channel mode. What modes are available
* for a given channel is an implementation detail for each server.
*
* @param mode the new channel mode.
* @param params any parameters with the mode (such as channel key).
* @param nick the nickname of the IRC client that changed the mode.
*/
- (void)modeSet:(NSString *)mode withParams:(NSString *)params by:(NSString *)nick;

/** Received when the topic is changed for the channel.
*
* @param aTopic The new topic of the channel.
* @param nick Nickname of the IRC client that changed the topic.
*/
- (void)topicSet:(NSString *)newTopic by:(NSString *)nick;

/** Received when an IRC client is kicked from a channel.
*
* @param nick nickname of the client that was kicked
* @param reason reason message given for the kick
* @param byNick nickname of the client that performed the kick command
* @param wasItUs Was it us who got kicked, or another user?
*/
- (void)userKicked:(NSString *)nick withReason:(NSString *)reason by:(NSString *)byNick us:(BOOL)wasItUs;

/** Received when an IRC client sends a public PRIVMSG to the channel. Note that the
* user may not necessarily be required to be on the channel to send a message
* to it.
*
* @param message the message sent to the channel.
* @param nick the nickname of the IRC client that sent the message.
*/
- (void)messageSent:(NSString *)message byUser:(NSString *)nick;

/** Received when an IRC client sends a public NOTICE to the channel. Note that
* the user may not necessarily be required to be on the channel to send a notice to
* it. Furthermore, the RFC states that the only difference between PRIVMSG and
* NOTICE is that a NOTICE may never be responded to automatically.
*
* @param notice the notice sent to the channel.
* @param nick the nickname of the IRC client that sent the notice.
*/
- (void)noticeSent:(NSString *)notice byUser:(NSString *)nick;

/** Received when an IRC client sends a CTCP ACTION message to the channel.
*
* @param action the action message sent to the channel.
* @param nick the nickname of the IRC client that sent the message.
*/
- (void)actionPerformed:(NSString *)action byUser:(NSString *)nick;

@end

+ 48
- 0
IRCClient/IRCClientChannel_Private.h Ver fichero

@@ -0,0 +1,48 @@
//
// IRCClientChannel_Private.h
// Meil
//
// Copyright 2015 Said Achmiz (www.saidachmiz.net)
//

#import "IRCClientChannel.h"

@interface IRCClientChannel ()

/** initWithName:andIRCSession:
*
* Returns an initialised IRCClientChannel with a given channel name, associated
* with the given irc_session_t object. You are not expected to initialise your
* own IRCClientChannel objects; if you wish to join a channel you should send a
* [IRCClientSession join:key:] message to your IRCClientSession object.
*
* @param aName Name of the channel.
*/
-(instancetype)initWithName:(NSData *)aName andIRCSession:(irc_session_t *)session;

/****************************/
#pragma mark - Event handlers
/****************************/

/* NOTE: These methods are not to be called by classes that use IRCClient;
* they are for the framework's internal use only. Do not import this header
* in files that make use of the IRCClientChannel class.
*/

- (void)userJoined:(NSString *)nick;

- (void)userParted:(NSString *)nick withReason:(NSData *)reason us:(BOOL)wasItUs;

- (void)modeSet:(NSString *)mode withParams:(NSString *)params by:(NSString *)nick;

- (void)topicSet:(NSData *)newTopic by:(NSString *)nick;

- (void)userKicked:(NSString *)nick withReason:(NSData *)reason by:(NSString *)byNick us:(BOOL)wasItUs;

- (void)messageSent:(NSData *)message byUser:(NSString *)nick;

- (void)noticeSent:(NSData *)notice byUser:(NSString *)nick;

- (void)actionPerformed:(NSData *)action byUser:(NSString *)nick;

@end

+ 254
- 0
IRCClient/IRCClientSession.h Ver fichero

@@ -0,0 +1,254 @@
/*! \mainpage IRCClient - a Cocoa IRC Framework to create IRC clients
*
* \section intro_sec Introduction
*
* IRCClient is a Cocoa Framework that uses the excellent libircclient library
* written by Georgy Yunaev.
*
* \section usage Basic Usage
*
* To use this framework, you will need to write an IRCClientSessionDelegate to
* handle all of the events generated by the server, and an IRCClientChannelDelegate
* to handle all of the events generated by channels on that server.
*
* You then create an IRCClientSession object in your code, assign the required
* properties, and call connect: to connect to the server and run: to create
* the new thread and start receiving events. For example:
*
* \code
* IRCClientSession *session = [[IRCClientSession alloc] init];
* MyIRCClientSessionDelegate *controller = [[MyIRCClientSessionDelegate alloc] init];
*
* [session setDelegate:controller];
* [controller setSession:session];
*
* [session setServer:@"irc.dal.net"];
* [session setPort:@"6667"];
* [session setNickname:@"test"];
* [session setUsername:@"test"];
* [session setRealname:@"test"];
* [session connect];
*
* [session run]; //starts the thread
* \endcode
*
* \section author Author, copyright, support.
*
* If you have any questions, bug reports, suggestions regarding libircclient
* or the IRCClient framework, please visit http://libircclient.sourceforge.net
*
* <PRE>
* libircclient Copyright (C) 2004-2009 Georgy Yunaev gyunaev@ulduzsoft.com
* Original IRCClient Copyright (C) 2009 Nathan Ollerenshaw chrome@stupendous.net
* Modified IRCClient Copyright 2015 Said Achmiz (www.saidachmiz.net)
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
* </PRE>
*/

/**
* @file IRCClientSession.h
* @author Nathan Ollerenshaw
* @version 1.0
* @date 01.2009
* @brief Represents a connected IRC Session.
*/

#import <Cocoa/Cocoa.h>
#import "IRCClientSessionDelegate.h"
#include "libircclient.h"

/** @class IRCClientSession
* @brief Represents a connected IRC Session.
*
* IRCClientSession represents a single connection to an IRC server. On initialising
* the object, and setting the delegate, server, port, password, nickname, username and realname
* properties, you call the connect: and run: methods to connect to the IRC server
* and start a new thread.
*
* This thread then sends messages back to the main runloop to the IRC server delegate,
* or to the IRCClientChannel delegate as required.
*/

@class IRCClientChannel;

#pragma mark IRCClientSession class declaration

@interface IRCClientSession : NSObject

/************************/
#pragma mark - Properties
/************************/

/** delegate to send events to. */
@property (assign) id <IRCClientSessionDelegate> delegate;

/** User-defined session ID (for one delegate to keep track of multiple sessions,
if desired).
*/
@property NSUInteger sessionID;

/** The version string for the client to send back on CTCP VERSION requests */
@property (copy) NSString *version;

/** IRC server to connect to */
@property (copy) NSString *server;

/** IRC port to connect to */
@property NSUInteger port;

/** Server password to provide on connect (may be left empty or nil) */
@property (copy) NSData *password;

/** Nickname of the connected client. Note that setting this after connection will
not result in the client renaming on IRC. You need to send a nick: message instead.
*/
@property (copy) NSString *nickname;

/** Username of the connected client. Also known as the ident.
Setting this after connection does nothing.
*/
@property (copy) NSString *username;

/** Realname of the connected client.
Setting this after connection does nothing.
*/
@property (copy) NSString *realname;

/** An NSDictionary of channels that the client is currently connected to. */
@property (retain, readonly) NSDictionary *channels;

/** The default text encoding for messages on this server.
This concerns messages received via PRIVMSG and NOTICE, and TOPIC in a channel.
It also affects what encoding reasons given for QUIT messages are assumed to be in.
You may change this at any time.
*/
@property (assign) NSStringEncoding encoding;

/** returns YES if the server is currently connected successfully, and NO if
it is not. */
@property (nonatomic, readonly) bool connected;

/***************************/
#pragma mark - Class methods
/***************************/

/** Connect to the IRC server.
Note that this performs the initial DNS lookup and the TCP connection, so if
there are any problems you will be notified via the return code of the message.
Look at the libircclient documentation for the different return codes.
*/
- (int)connect;

/** Disconnect from the IRC server.
This always works, as it simply shuts down the socket. If you want to disconnect
in a friendly way, you should use the quit: message.
*/
- (void)disconnect;

/** Starts a new thread and starts the libircclient runloop, processing events and
firing messages back to the main runloop as required. Calling this again will
do nothing other than raise a warning in your logs.
*/
- (void)run;

/**************************/
#pragma mark - IRC commands
/**************************/

/** Sends a raw message to the IRC server. Please consult rfc1459 for the format
of IRC commands. */
- (int)sendRaw:(NSData *)message;

/** quits the IRC server with the given reason. On success, an onQuit event will be
sent to the IRCClientSessionDelegate with the nickname of the IRC client.
*/
- (int)quit:(NSData *)reason;

/** Joins a channel with a given name and key
@param channel the channel to join
@param key they key for the channel (may be nil)
*/
- (int)join:(NSData *)channel key:(NSData *)key;

/** lists channels on the IRC server.
@param channel a channel name or string to pass to the LIST command. Implementation specific.
*/
- (int)list:(NSData *)channel;

/** sets the user mode for the IRC client
@param mode string to set
*/
- (int)userMode:(NSString *)mode;

/** sets the IRC client nickname. On success, an onNick event will be sent to the delegate
@param newnick new nickname to set.
*/
- (int)nick:(NSString *)newnick;

/** sends a WHOIS request to the IRC server
@param nick nickname of the irc client to whois.
*/
- (int)whois:(NSString *)nick;

/** send a PRIVMSG to another IRC client
@param message message to send
@param target the other IRC client to send the message to.
*/
- (int)message:(NSData *)message to:(NSString *)target;

/** send a CTCP ACTION to another IRC client
@param action the action message to send
@param target the nickname of the irc client to send the message to.
*/
- (int)action:(NSData *)action to:(NSString *)target;

/** send a NOTICE to another IRC client
@param notice the message text to send
@param target the nickname of the irc client to send the notice to.
*/
- (int)notice:(NSData *)notice to:(NSString *)target;

/** send a CTCP request to another IRC client
@param request the CTCP request string to send
@param target the nickname of the IRC client to send the request to.
*/
- (int)ctcpRequest:(NSData *)request target:(NSString *)target;

/** send a CTCP reply to another IRC client
@param reply the CTCP reply string to send
@param target the nickname of the IRC client to send the reply to.
*/
- (int)ctcpReply:(NSData *)reply target:(NSString *)target;

@end

NSString* getNickFromNickUserHost(NSString *nuh);

NSString* getUserFromNickUserHost(NSString *nuh);

NSString* getHostFromNickUserHost(NSString *nuh);

+ 948
- 0
IRCClient/IRCClientSession.m Ver fichero

@@ -0,0 +1,948 @@
/*
* Modified IRCClient Copyright 2015 Said Achmiz (www.saidachmiz.net)
*
* Original IRCClient Copyright (C) 2009 Nathan Ollerenshaw chrome@stupendous.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*/

#pragma mark Defines and includes

#define IRCCLIENTVERSION "1.0"

#import "IRCClientSession.h"
#import "IRCClientChannel.h"
#import "IRCClientChannel_Private.h"
#include "string.h"

#pragma mark - Callback function declarations

static void onConnect(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onNick(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onQuit(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onJoinChannel(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onPartChannel(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onMode(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onUserMode(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onTopic(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onKick(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onChannelPrvmsg(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onPrivmsg(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onNotice(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onChannelNotice(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onInvite(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onCtcpRequest(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onCtcpReply(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onCtcpAction(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onUnknownEvent(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count);
static void onNumericEvent(irc_session_t *session, unsigned int event, const char *origin, const char **params, unsigned int count);

#pragma mark - IRCClientSession private category declaration

@interface IRCClientSession()
{
irc_callbacks_t callbacks;
irc_session_t *irc_session;
NSThread *thread;
NSString *version;
NSString *server;
NSUInteger port;
NSData *password;
NSString *nickname;
NSString *username;
NSString *realname;
NSMutableDictionary *channels;
NSStringEncoding encoding;
}

@property (nonatomic, retain) NSMutableDictionary *channels;

@end

#pragma mark - IRCClientSession class implementation

@implementation IRCClientSession

#pragma mark - Property synthesis

@synthesize delegate;
@synthesize sessionID;
@synthesize version;
@synthesize server;
@synthesize port;
@synthesize password;
@synthesize nickname;
@synthesize username;
@synthesize realname;
@synthesize encoding;

#pragma mark - Custom accessors

-(NSDictionary*)channels
{
NSDictionary* channelsCopy = [channels copy];
return channelsCopy;
}

-(void)setChannels:(NSMutableDictionary *)newChannels
{
channels = newChannels;
}

- (bool)connected
{
return irc_is_connected(irc_session);
}

/************************************/
#pragma mark - Class methods
/************************************/

-(instancetype)init
{
if ((self = [super init])) {
callbacks.event_connect = onConnect;
callbacks.event_nick = onNick;
callbacks.event_quit = onQuit;
callbacks.event_join = onJoinChannel;
callbacks.event_part = onPartChannel;
callbacks.event_mode = onMode;
callbacks.event_umode = onUserMode;
callbacks.event_topic = onTopic;
callbacks.event_kick = onKick;
callbacks.event_channel = onChannelPrvmsg;
callbacks.event_privmsg = onPrivmsg;
callbacks.event_notice = onNotice;
callbacks.event_channel_notice = onChannelNotice;
callbacks.event_invite = onInvite;
callbacks.event_ctcp_req = onCtcpRequest;
callbacks.event_ctcp_rep = onCtcpReply;
callbacks.event_ctcp_action = onCtcpAction;
callbacks.event_unknown = onUnknownEvent;
callbacks.event_numeric = onNumericEvent;
callbacks.event_dcc_chat_req = NULL;
callbacks.event_dcc_send_req = NULL;
irc_session = irc_create_session(&callbacks);
if (!irc_session) {
NSLog(@"Could not create irc_session.");
return nil;
}
// Strip server info from nicks.
// irc_option_set(irc_session, LIBIRC_OPTION_STRIPNICKS);
irc_set_ctx(irc_session, (__bridge void *)(self));
unsigned int high, low;
irc_get_version (&high, &low);
version = [NSString stringWithFormat:@"IRCClient Framework v%s (Nathan Ollerenshaw) - libirc v%d.%d (Georgy Yunaev)", IRCCLIENTVERSION, high, low];
channels = [[NSMutableDictionary alloc] init];
}
return self;
}

-(void)dealloc
{
if (irc_is_connected(irc_session))
NSLog(@"Warning: IRC Session is not disconnected on dealloc");
irc_destroy_session(irc_session);
}

- (int)connect;
{
unsigned short sPort = port;
return irc_connect(irc_session, server.UTF8String, sPort, (password.length > 0 ? password.bytes : NULL), nickname.UTF8String, username.UTF8String, realname.UTF8String);
}

- (void)disconnect
{
irc_disconnect(irc_session);
}

- (void)startThread
{
@autoreleasepool {
irc_run(irc_session);
}
}

- (void)run
{
if (thread) {
NSLog(@"Thread already running!");
return;
}
thread = [[NSThread alloc] initWithTarget:self selector:@selector(startThread) object:nil];
[thread start];
}

/**************************/
#pragma mark - IRC commands
/**************************/

- (int)sendRaw:(NSData *)message
{
return irc_send_raw(irc_session, message.bytes);
}

- (int)quit:(NSData *)reason
{
return irc_cmd_quit(irc_session, reason.bytes);
}

- (int)join:(NSData *)channel key:(NSData *)key
{
NSLog(@"Joining %@", channel);
if (!key || !key.length > 0)
return irc_cmd_join(irc_session, channel.bytes, NULL);

return irc_cmd_join(irc_session, channel.bytes, key.bytes);
}

- (int)list:(NSData *)channel
{
return irc_cmd_list(irc_session, channel.bytes);
}

- (int)userMode:(NSString *)mode
{
return irc_cmd_user_mode(irc_session, mode.UTF8String);
}

- (int)nick:(NSString *)newnick
{
return irc_cmd_nick(irc_session, newnick.UTF8String);
}

- (int)whois:(NSString *)nick
{
return irc_cmd_whois(irc_session, nick.UTF8String);
}

- (int)message:(NSData *)message to:(NSString *)target
{
return irc_cmd_msg(irc_session, target.UTF8String, message.bytes);
}

- (int)action:(NSData *)action to:(NSString *)target
{
return irc_cmd_me(irc_session, target.UTF8String, action.bytes);
}

- (int)notice:(NSData *)notice to:(NSString *)target
{
return irc_cmd_notice(irc_session, target.UTF8String, notice.bytes);
}

- (int)ctcpRequest:(NSData *)request target:(NSString *)target
{
return irc_cmd_ctcp_request(irc_session, target.UTF8String, request.bytes);
}

- (int)ctcpReply:(NSData *)reply target:(NSString *)target
{
return irc_cmd_ctcp_reply(irc_session, target.UTF8String, reply.bytes);
}

/****************************/
#pragma mark - Event handlers
/****************************/

- (void)connectionSucceeded
{
[delegate connectionSucceeded];
}

- (void)nickChangedFrom:(NSString *)oldNick to:(NSString *)newNick
{
if ([nickname isEqualToString:oldNick])
{
nickname = newNick;
[delegate nickChangedFrom:oldNick to:newNick own:YES];
}
else
{
[delegate nickChangedFrom:oldNick to:newNick own:NO];
}
}

- (void)userQuit:(NSString *)nick withReason:(NSData *)reason
{
NSString* reasonString;
if(reason)
{
reasonString = [[NSString alloc] initWithData:reason encoding:encoding];
}
[delegate userQuit:nick withReason:reasonString];
}

- (void)userJoined:(NSString *)nick channel:(NSData *)channelName
{
NSString* nickOnly = getNickFromNickUserHost(nick);
if ([nickname isEqualToString:nickOnly])
{
// We just joined a channel; allocate an IRCClientChannel object and send it
// to the main thread.
IRCClientChannel* newChannel = [[IRCClientChannel alloc] initWithName:channelName andIRCSession:irc_session];
channels[channelName] = newChannel;
[delegate joinedNewChannel:newChannel];
}
else
{
// Someone joined a channel we're on.
IRCClientChannel* channel = channels[channelName];
[channel userJoined:nick];
}
}

- (void)userParted:(NSString *)nick channel:(NSData *)channelName withReason:(NSData *)reason
{
IRCClientChannel* channel = channels[channelName];
NSString* nickOnly = getNickFromNickUserHost(nick);
if ([nickname isEqualToString:nickOnly])
{
// We just left a channel; remove it from the channels dict.
[channels removeObjectForKey:channelName];
[channel userParted:nick withReason:reason us:YES];
}
else
{
[channel userParted:nick withReason:reason us:NO];
}
}

- (void)modeSet:(NSString* )mode withParams:(NSString *)params forChannel:(NSData *)channelName by:(NSString *)nick
{
IRCClientChannel *channel = channels[channelName];
[channel modeSet:mode withParams:params by:nick];
}

- (void)modeSet:(NSString *)mode by:(NSString *)nick
{
[delegate modeSet:mode by:nick];
}

- (void)topicSet:(NSData *)newTopic forChannel:(NSData *)channelName by:(NSString *)nick
{
IRCClientChannel *channel = channels[channelName];
[channel topicSet:newTopic by:nick];
}

- (void)userKicked:(NSString *)nick fromChannel:(NSData *)channelName by:(NSString *)byNick withReason:(NSData *)reason
{
IRCClientChannel* channel = channels[channelName];

if (nick == nil)
{
// we got kicked from a channel we're on
[channels removeObjectForKey:channelName];
[channel userKicked:nickname withReason:reason by:byNick us:YES];
}
else
{
// someone else got booted from a channel we're on
[channel userKicked:nick withReason:reason by:byNick us:NO];
}
}

- (void)messageSent:(NSData *)message toChannel:(NSData *)channelName byUser:(NSString *)nick
{
IRCClientChannel *channel = channels[channelName];
[channel messageSent:message byUser:nick];
}

- (void)privateMessageReceived:(NSData *)message fromUser:(NSString *)nick
{
NSString* messageString = [[NSString alloc] initWithData:message encoding:encoding];
[delegate privateMessageReceived:messageString fromUser:nick];
}

- (void)noticeSent:(NSData *)notice toChannel:(NSData *)channelName byUser:(NSString *)nick
{
IRCClientChannel *channel = channels[channelName];
[channel noticeSent:notice byUser:nick];
}

- (void)privateNoticeReceived:(NSData *)notice fromUser:(NSString *)nick
{
NSString* noticeString = [[NSString alloc] initWithData:notice encoding:encoding];
[delegate privateNoticeReceived:noticeString fromUser:nick];
}

- (void)invitedToChannel:(NSData *)channelName by:(NSString *)nick
{
[delegate invitedToChannel:channelName by:nick];
}

- (void)CTCPRequestReceived:(NSData *)request fromUser:(NSString *)nick
{
const char* the_nick = getNickFromNickUserHost(nick).UTF8String;
const char* the_request = request.bytes;
if (strstr(the_request, "PING") == the_request)
{
irc_cmd_ctcp_reply(irc_session, the_nick, the_request);
}
else if (!strcmp (the_request, "VERSION"))
{
irc_cmd_ctcp_reply (irc_session, the_nick, [NSString stringWithFormat:@"VERSION %@", version].UTF8String);
}
else if (!strcmp (the_request, "FINGER"))
{
irc_cmd_ctcp_reply (irc_session, the_nick, [NSString stringWithFormat:@"FINGER %@ (%@) Idle 0 seconds", username, realname].UTF8String);
}
else if (!strcmp (the_request, "TIME"))
{
irc_cmd_ctcp_reply(irc_session, the_nick, [[NSDate dateWithTimeIntervalSinceNow:0] descriptionWithCalendarFormat:@"TIME %a %b %e %H:%M:%S %Z %Y" timeZone:nil locale:[[NSUserDefaults standardUserDefaults] dictionaryRepresentation]].UTF8String);
}
else
{
if ([delegate respondsToSelector:@selector(CTCPRequestReceived:ofType:fromUser:)])
{
char* request_string = malloc(request.length);
[request getBytes:request_string length:request.length];
char* request_type = strtok(request_string, " ");
char* request_body = strtok(NULL, " " );
[delegate CTCPRequestReceived:[NSData dataWithBytes:request_body length:strlen(request_body)+1] ofType:[NSData dataWithBytes:request_type length:strlen(request_type)+1] fromUser:nick];
}
}
}

- (void)CTCPReplyReceived:(NSData *)reply fromUser:(NSString *)nick
{
[delegate CTCPReplyReceived:reply fromUser:nick];
}

- (void)CTCPActionPerformed:(NSData *)action byUser:(NSString *)nick atTarget:(NSData *)target
{
IRCClientChannel* channel = channels[target];
if(channel != nil)
{
// An action on a channel we're on
[channel actionPerformed:action byUser:nick];
}
else
{
// An action in a private message
NSString* actionString = [[NSString alloc] initWithData:action encoding:encoding];
[delegate privateCTCPActionReceived:actionString fromUser:nick];
}
}

- (void)unknownEventReceived:(NSData *)event from:(NSString *)origin params:(NSArray *)params
{
[delegate unknownEventReceived:event from:origin params:params];
}

-(void)numericEventReceived:(NSUInteger)event from:(NSString *)origin params:(NSArray *)params
{
[delegate numericEventReceived:event from:origin params:params];
}

@end

#pragma mark - Useful helper functions

NSString* getNickFromNickUserHost(NSString *nuh)
{
NSArray *nuhArray = [nuh componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"!@"]];
if (nuhArray.count == 3)
{
return [NSString stringWithString:nuhArray[0]];
}
else
{
return [NSString stringWithString:nuh];
}
}

NSString* getUserFromNickUserHost(NSString *nuh)
{
NSArray *nuhArray = [nuh componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"!@"]];
if (nuhArray.count == 3)
{
return [NSString stringWithString:nuhArray[1]];
}
else
{
return nil;
}
}

NSString* getHostFromNickUserHost(NSString *nuh)
{
NSArray *nuhArray = [nuh componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"!@"]];
if (nuhArray.count == 3)
{
return [NSString stringWithString:nuhArray[2]];
}
else
{
return nil;
}
}

/***********************************************/
#pragma mark - Callback function implementations
/***********************************************/

/*!
* The "on_connect" event is triggered when the client successfully
* connects to the server, and could send commands to the server.
* No extra params supplied; \a params is 0.
*/
static void onConnect(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession* clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
[clientSession connectionSucceeded];
}

/*!
* The "nick" event is triggered when the client receives a NICK message,
* meaning that someone (including you) on a channel with the client has
* changed their nickname.
*
* \param origin the person, who changes the nick. Note that it can be you!
* \param params[0] mandatory, contains the new nick.
*/
static void onNick(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession* clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *oldNick = @(origin);
NSString *newNick = @(params[0]);
[clientSession nickChangedFrom:oldNick to:newNick];
}

/*!
* The "quit" event is triggered upon receipt of a QUIT message, which
* means that someone on a channel with the client has disconnected.
*
* \param origin the person, who is disconnected
* \param params[0] optional, contains the reason message (user-specified).
*/
static void onQuit(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *reason = nil;
if(count > 0)
{
reason = [[NSData alloc] initWithBytes:params[0] length:strlen(params[0])];
}

[clientSession userQuit:nick withReason:reason];
}

/*!
* The "join" event is triggered upon receipt of a JOIN message, which
* means that someone has entered a channel that the client is on.
*
* \param origin the person, who joins the channel. By comparing it with
* your own nickname, you can check whether your JOIN
* command succeed.
* \param params[0] mandatory, contains the channel name.
*/
static void onJoinChannel(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession* clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0])];
[clientSession userJoined:nick channel:channelName];
}

/*!
* The "part" event is triggered upon receipt of a PART message, which
* means that someone has left a channel that the client is on.
*
* \param origin the person, who leaves the channel. By comparing it with
* your own nickname, you can check whether your PART
* command succeed.
* \param params[0] mandatory, contains the channel name.
* \param params[1] optional, contains the reason message (user-defined).
*/
static void onPartChannel(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0])];
NSData *reason = nil;
if (count > 1)
{
reason = [NSData dataWithBytes:params[1] length:strlen(params[1])+1];
}
[clientSession userParted:nick channel:channelName withReason:reason];
}

/*!
* The "mode" event is triggered upon receipt of a channel MODE message,
* which means that someone on a channel with the client has changed the
* channel's parameters.
*
* \param origin the person, who changed the channel mode.
* \param params[0] mandatory, contains the channel name.
* \param params[1] mandatory, contains the changed channel mode, like
* '+t', '-i' and so on.
* \param params[2] optional, contains the mode argument (for example, a
* key for +k mode, or user who got the channel operator status for
* +o mode)
*/
static void onMode(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0])];
NSString *mode = @(params[1]);
NSString *modeParams = nil;
if (count > 2)
{
modeParams = @(params[2]);
}
[clientSession modeSet:mode withParams:modeParams forChannel:channelName by:nick];
}

/*!
* The "umode" event is triggered upon receipt of a user MODE message,
* which means that your user mode has been changed.
*
* \param origin the person, who changed the channel mode.
* \param params[0] mandatory, contains the user changed mode, like
* '+t', '-i' and so on.
*/
static void onUserMode(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString* nick = @(origin);
NSString *mode = @(params[0]);
[clientSession modeSet:mode by:nick];
}

/*!
* The "topic" event is triggered upon receipt of a TOPIC message, which
* means that someone on a channel with the client has changed the
* channel's topic.
*
* \param origin the person, who changes the channel topic.
* \param params[0] mandatory, contains the channel name.
* \param params[1] optional, contains the new topic.
*/
static void onTopic(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0])];
NSData *topic = nil;
if (count > 1)
{
topic = [NSData dataWithBytes:params[1] length:strlen(params[1])];
}
[clientSession topicSet:topic forChannel:channelName by:nick];
}

/*!
* The "kick" event is triggered upon receipt of a KICK message, which
* means that someone on a channel with the client (or possibly the
* client itself!) has been forcibly ejected.
*
* \param origin the person, who kicked the poor.
* \param params[0] mandatory, contains the channel name.
* \param params[1] optional, contains the nick of kicked person.
* \param params[2] optional, contains the kick text
*/
static void onKick(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *byNick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0])];
NSString *nick = nil;
NSData *reason = nil;
if (count > 1)
{
nick = @(params[1]);
}
if (count > 2)
{
reason = [NSData dataWithBytes:params[2] length:strlen(params[2])];
}
[clientSession userKicked:nick fromChannel:channelName by:byNick withReason:reason];
}

/*!
* The "channel" event is triggered upon receipt of a PRIVMSG message
* to an entire channel, which means that someone on a channel with
* the client has said something aloud. Your own messages don't trigger
* PRIVMSG event.
*
* \param origin the person, who generates the message.
* \param params[0] mandatory, contains the channel name.
* \param params[1] optional, contains the message text
*/
static void onChannelPrvmsg(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0])];
NSData *message = nil;
if (count > 1)
{
message = [NSData dataWithBytes:params[1] length:strlen(params[1])];
}

NSLog(@"onChannelPrvmsg");
[clientSession messageSent:message toChannel:channelName byUser:nick];
}

/*!
* The "privmsg" event is triggered upon receipt of a PRIVMSG message
* which is addressed to one or more clients, which means that someone
* is sending the client a private message.
*
* \param origin the person, who generates the message.
* \param params[0] mandatory, contains your nick.
* \param params[1] optional, contains the message text
*/
static void onPrivmsg(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *message = nil;

if (count > 1)
{
message = [NSData dataWithBytes:params[1] length:strlen(params[1])];
}
[clientSession privateMessageReceived:message fromUser:nick];
}

/*!
* The "notice" event is triggered upon receipt of a NOTICE message
* which means that someone has sent the client a public or private
* notice. According to RFC 1459, the only difference between NOTICE
* and PRIVMSG is that you should NEVER automatically reply to NOTICE
* messages. Unfortunately, this rule is frequently violated by IRC
* servers itself - for example, NICKSERV messages require reply, and
* are NOTICEs.
*
* \param origin the person, who generates the message.
* \param params[0] mandatory, contains your nick.
* \param params[1] optional, contains the message text
*/
static void onNotice(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *notice = nil;
if (count > 1)
{
notice = [NSData dataWithBytes:params[1] length:strlen(params[1])];
}
[clientSession privateNoticeReceived:notice fromUser:nick];
}

/*!
* The "notice" event is triggered upon receipt of a NOTICE message
* which means that someone has sent the client a public or private
* notice. According to RFC 1459, the only difference between NOTICE
* and PRIVMSG is that you should NEVER automatically reply to NOTICE
* messages. Unfortunately, this rule is frequently violated by IRC
* servers itself - for example, NICKSERV messages require reply, and
* are NOTICEs.
*
* \param origin the person, who generates the message.
* \param params[0] mandatory, contains the target channel name.
* \param params[1] optional, contains the message text.
*/
static void onChannelNotice(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[0] length:strlen(params[0])];
NSData *notice = nil;
if (count > 1)
{
notice = [NSData dataWithBytes:params[1] length:strlen(params[1])];
}

[clientSession noticeSent:notice toChannel:channelName byUser:nick];
}

/*!
* The "invite" event is triggered upon receipt of an INVITE message,
* which means that someone is permitting the client's entry into a +i
* channel.
*
* \param origin the person, who INVITEs you.
* \param params[0] mandatory, contains your nick.
* \param params[1] mandatory, contains the channel name you're invited into.
*
* \sa irc_cmd_invite irc_cmd_chanmode_invite
*/
static void onInvite(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *channelName = [NSData dataWithBytes:params[1] length:strlen(params[1])];
[clientSession invitedToChannel:channelName by:nick];
}

/*!
* The "ctcp" event is triggered when the client receives the CTCP
* request. By default, the built-in CTCP request handler is used. The
* build-in handler automatically replies on most CTCP messages, so you
* will rarely need to override it.
*
* \param origin the person, who generates the message.
* \param params[0] mandatory, the complete CTCP message, including its
* arguments.
*
* Mirc generates PING, FINGER, VERSION, TIME and ACTION messages,
* check the source code of \c libirc_event_ctcp_internal function to
* see how to write your own CTCP request handler. Also you may find
* useful this question in FAQ: \ref faq4
*/
static void onCtcpRequest(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData* request = [NSData dataWithBytes:params[0] length:strlen(params[0])];
[clientSession CTCPRequestReceived:request fromUser:nick];
}

/*!
* The "ctcp" event is triggered when the client receives the CTCP reply.
*
* \param origin the person, who generates the message.
* \param params[0] mandatory, the CTCP message itself with its arguments.
*/
static void onCtcpReply(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *reply = [NSData dataWithBytes:params[0] length:strlen(params[0])];
[clientSession CTCPReplyReceived:reply fromUser:nick];
}

/*!
* The "action" event is triggered when the client receives the CTCP
* ACTION message. These messages usually looks like:\n
* \code
* [23:32:55] * Tim gonna sleep.
* \endcode
*
* \param origin the person, who generates the message.
* \param params[0] mandatory, the target of the message.
* \param params[1] mandatory, the ACTION message.
*/
static void onCtcpAction(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSString *nick = @(origin);
NSData *target = [NSData dataWithBytes:params[0] length:strlen(params[0])];
NSData *action = [NSData dataWithBytes:params[1] length:strlen(params[1])];
[clientSession CTCPActionPerformed:action byUser:nick atTarget:target];
}

/*!
* The "unknown" event is triggered upon receipt of any number of
* unclassifiable miscellaneous messages, which aren't handled by the
* library.
*/
static void onUnknownEvent(irc_session_t *session, const char *event, const char *origin, const char **params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSData *eventString = [NSData dataWithBytes:event length:strlen(event)];
NSString *sender = nil;
if (origin != NULL)
sender = @(origin);
NSMutableArray *paramsArray = [[NSMutableArray alloc] init];
for (unsigned int i = 0; i < count; i++)
[paramsArray addObject:[NSData dataWithBytes:params[i] length:strlen(params[i])]];
[clientSession unknownEventReceived:eventString from:sender params:[paramsArray copy]];
}

/*!
* The "numeric" event is triggered upon receipt of any numeric response
* from the server. There is a lot of such responses, see the full list
* here: \ref rfcnumbers.
*
* See the params in ::irc_eventcode_callback_t specification.
*/
static void onNumericEvent(irc_session_t * session, unsigned int event, const char * origin, const char ** params, unsigned int count)
{
IRCClientSession *clientSession = (__bridge IRCClientSession *) irc_get_ctx(session);
NSUInteger eventNumber = event;
NSString *sender = @(origin);
NSMutableArray *paramsArray = [[NSMutableArray alloc] init];
for (unsigned int i = 0; i < count; i++)
[paramsArray addObject:[NSData dataWithBytes:params[i] length:strlen(params[i])]];
[clientSession numericEventReceived:eventNumber from:sender params:[paramsArray copy]];
}

+ 152
- 0
IRCClient/IRCClientSessionDelegate.h Ver fichero

@@ -0,0 +1,152 @@
/*
* Modified IRCClient Copyright 2015 Said Achmiz (www.saidachmiz.net)
*
* Original IRCClient Copyright (C) 2009 Nathan Ollerenshaw chrome@stupendous.net
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*/

#import <Cocoa/Cocoa.h>
#include "libircclient.h"

/**
* @file IRCClientSessionDelegate.h
* @author Nathan Ollerenshaw
* @version 1.0
* @date 01.2009
* @brief Receives delegate messages from an IRCClientSession.
* @protocol IRCClientSessionDelegate
*/

@class IRCClientChannel;

/** @brief Receives delegate messages from an IRCClientSession.
*
* Each IRCClientSession object needs a single delegate. Methods are called
* for each event that occurs on an IRC server that the client is connected to.
*
* Note that for any given parameter, it may be optional, in which case a nil
* object may be supplied instead of the given parameter.
*/

@protocol IRCClientSessionDelegate <NSObject>

/** The client has successfully connected to the IRC server. */
- (void)connectionSucceeded;

/** An IRC client on a channel that this client is connected to has changed nickname,
* or this IRC client has changed nicknames.
*
* @param nick the new nickname
* @param oldNick the old nickname
* @param wasItUs did our nick change, or someone else's?
*/
- (void)nickChangedFrom:(NSString *)oldNick to:(NSString *)newNick own:(BOOL)wasItUs;

/** An IRC client on a channel that this client is connected to has quit IRC.
*
* @param nick the nickname of the client that quit.
* @param reason (optional) the quit message, if any.
*/
- (void)userQuit:(NSString *)nick withReason:(NSString *)reason;

/** The IRC client has joined (connected) successfully to a new channel. This
* event creates an IRCClientChannel object, which you are expected to assign a
* delegate to, to handle events from the channel.
*
* For example, on receipt of this message, a graphical IRC client would most
* likely open a new window, create an IRCClientChannelDelegate for the window,
* set the new IRCClientChannel's delegate to the new delegate, and then hook
* it up so that new events sent to the IRCClientChannelDelegate are sent to
* the window.
*
* @param channel the IRCClientChannel object for the newly joined channel.
*/
- (void)joinedNewChannel:(IRCClientChannel *)channel;

/** The client has changed it's user mode.
*
* @param mode the new mode.
*/
- (void)modeSet:(NSString *)mode by:(NSString *)nick;

/** The client has received a private PRIVMSG from another IRC client.
*
* @param message the text of the message
* @param nick the other IRC Client that sent the message.
*/
- (void)privateMessageReceived:(NSString *)message fromUser:(NSString *)nick;

/** The client has received a private NOTICE from another client.
*
* @param notice the text of the message
* @param nick the nickname of the other IRC client that sent the message.
*/
- (void)privateNoticeReceived:(NSString *)notice fromUser:(NSString *)nick;

/** The IRC client has been invited to a channel.
*
* Note that the name is provided as an NSData object, because we have no idea
* what encoding the channel name is in (it needn't be the same as used by e.g.
* server messages, etc.), and it's important to attempt to join *exactly* the
* channel you're being invited to, byte for byte, otherwise you might end up
* joining the wrong channel. You should convert the name to an NSString for
* display (using the encoding set for the server is probably a sane default)
* but be aware that you might be displaying entirely wrong characters and are
* not gauranteed that the channel name will look right - only that it will be
* actually be the right name, internally.
*
* @param channel the channel for the invitation.
* @param nick the nickname of the user that sent the invitation.
*/
- (void)invitedToChannel:(NSData *)channelName by:(NSString *)nick;

/** A private CTCP request was sent to the IRC client.
*
* @param request the CTCP request string (after the type)
* @param type the CTCP request type
* @param nick the nickname of the user that sent the request.
*/
- (void)CTCPRequestReceived:(NSData *)request ofType:(NSData *)type fromUser:(NSString *)nick;

/** A private CTCP reply was sent to the IRC client.
*
* @param reply an NSData containing the raw C string of the reply.
* @param nick the nickname of the user that sent the reply.
*/
- (void)CTCPReplyReceived:(NSData *)reply fromUser:(NSString *)nick;

/** A private CTCP ACTION was sent to the IRC client.
*
* CTCP ACTION is not limited to channels; it may also be sent directly to other users.
*
* @param action the action message text.
* @param nick the nickname of the client that sent the action.
*/
- (void)privateCTCPActionReceived:(NSString *)action fromUser:(NSString *)nick;

/** An unhandled event was received from the IRC server.
*
* @param event the unknown event name
* @param origin the sender of the event
* @param params an NSArray of NSData objects that are the raw C strings of the event.
*/
- (void)unknownEventReceived:(NSData *)event from:(NSString *)origin params:(NSArray *)params;

/** An unhandled numeric was received from the IRC server
*
* @param event the unknown event number
* @param origin the sender of the event
* @param params an NSArray of NSData objects that are the raw C strings of the event.
*/
- (void)numericEventReceived:(NSUInteger)event from:(NSString *)origin params:(NSArray *)params;

@end

+ 1
- 1
IRCClient/Info.plist Ver fichero

@@ -21,7 +21,7 @@
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2015 Said Achmiz. All rights reserved.</string>
<string>Copyright © 2015 Said Achmiz.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>

Cargando…
Cancelar
Guardar