Exemple #1
0
        public void VerifyAndCompile()
        {
            if (Identity == null)
            {
                throw new JsonException("Missing identity field");
            }

            if (!Permissions.Any())
            {
                throw new JsonException(string.Format("Permission list for '{0}' is empty.", Identity));
            }

            foreach (var channel in Permissions)
            {
                if (channel.Key != "*" && !IrcValidation.IsChannelName(channel.Key))
                {
                    throw new JsonException(string.Format("Invalid channel '{0}' for user '{1}'", channel.Key, Identity));
                }

                if (!channel.Value.Any())
                {
                    throw new JsonException(string.Format("Permission list for '{0}' in channel '{1}' is empty.", Identity, channel.Key));
                }

                var pattern = @"^(" + string.Join("|", channel.Value.Select(Regex.Escape)).Replace(@"\*", @".*") + @")$";

                CompiledPermissionsMatch.Add(channel.Key, new Regex(pattern, RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture));
            }
        }
Exemple #2
0
        public BaseClient()
        {
            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config", "settings.json");

            if (File.Exists(path))
            {
                var data = File.ReadAllText(path);

                try
                {
                    Settings = JsonConvert.DeserializeObject <Settings>(data, new JsonSerializerSettings {
                        MissingMemberHandling = MissingMemberHandling.Error
                    });

                    if (!IrcValidation.IsNickname(Settings.Nickname))
                    {
                        throw new JsonException("Nickname is not valid.");
                    }

                    if (!IrcValidation.IsChannelName(Settings.RedirectChannel))
                    {
                        throw new JsonException("Redirect channel is not valid.");
                    }

                    foreach (var channel in Settings.Channels)
                    {
                        if (!IrcValidation.IsChannelName(channel))
                        {
                            throw new JsonException($"Channel '{channel}' is not valid.");
                        }
                    }
                }
                catch (JsonException e)
                {
                    Log.WriteError("IRC", "Failed to parse settings.json file: {0}", e.Message);

                    Environment.Exit(1);
                }
            }
            else
            {
                Log.WriteWarn("IRC", "File config/settings.json doesn't exist");

                Environment.Exit(1);
            }

            Client = new IrcClient
            {
                ClientVersion = "Wendy# -- https://github.com/xPaw/WendySharp"
            };

            Client.Connected += OnConnected;
            Client.Closed    += OnDisconnected;

            Permissions  = new Permissions();
            Commands     = new Commands(Client);
            LinkExpander = new LinkExpander(Client);
            ChannelList  = new Channels(Client);
            Whois        = new Whois(Client);
        }
Exemple #3
0
        /// <summary>
        /// Tries to parse a string to get an IRC identity.
        ///
        /// IRC identities are formatted as nickname!username@hostname.
        /// </summary>
        /// <param name="string">The string to parse.</param>
        /// <param name="identity">The identity, or <c>null</c> if parsing fails.</param>
        /// <returns><c>true</c> if parsing completed successfully.</returns>
        public static bool TryParse(IrcString @string, out IrcIdentity identity)
        {
            IrcString[] parts; identity = null;
            if (@string == null)
            {
                goto invalid;
            }
            identity = new IrcIdentity();

            parts = @string.Split((byte)'@');
            if (parts.Length >= 2)
            {
                identity.Hostname = parts[1]; @string = parts[0];
            }

            parts = @string.Split((byte)'!');
            if (parts.Length >= 2)
            {
                identity.Username = parts[1]; @string = parts[0];
            }

            identity.Nickname = @string;

            string errorMessage;

            if (!IrcValidation.ValidateIdentity(identity, out errorMessage))
            {
                goto invalid;
            }
            return(true);

invalid:
            identity = null; return(false);
        }
        private void Reply(string message, bool notice)
        {
            string recipient        = Event.Recipient;
            var    isChannelMessage = IrcValidation.IsChannelName(recipient);

            if (isChannelMessage)
            {
                if (!notice)
                {
                    message = string.Format("{0}: {1}", Event.Sender.Nickname, message);
                }
                else
                {
                    recipient = Event.Sender.Nickname.ToString();
                }
            }
            else
            {
                notice = false;

                recipient = Event.Sender.Nickname.ToString();
            }

            Bootstrap.Client.SendReply(recipient, message, notice);
        }
Exemple #5
0
        public override void OnCommand(CommandArguments command)
        {
            var target = command.Arguments.Groups["target"].Value;
            var text   = command.Arguments.Groups["text"].Value;

            if (!IrcValidation.IsChannelName(target) && !IrcValidation.IsNickname(target))
            {
                command.Reply("That doesn't look like a valid channel or nickname.");

                return;
            }

            Log.WriteInfo("Say", "'{0}' said to '{1}': {2}", command.Event.Sender, target, text);

            Bootstrap.Client.Client.Message(target, text);
        }
Exemple #6
0
        public override void OnCommand(CommandArguments command)
        {
            var channel = command.Arguments.Groups["channel"].Value;

            if (!IrcValidation.IsChannelName(channel))
            {
                command.Reply("That doesn't look like a valid channel name.");

                return;
            }

            Log.WriteInfo("Join", "'{0}' made us join channel {1}", command.Event.Sender, channel);

            Bootstrap.Client.Client.Join(channel);

            command.Reply("See you in {0}!", channel);
        }
Exemple #7
0
        /// <summary>
        /// Converts an IRC identity into an IRC string.
        /// </summary>
        /// <returns>The IRC string.</returns>
        public IrcString ToIrcString()
        {
            string errorMessage;

            if (!IrcValidation.ValidateIdentity(this, out errorMessage))
            {
                throw new InvalidOperationException(errorMessage);
            }

            var @string = Nickname;

            if (Username != null)
            {
                @string += "!" + Username;
            }
            if (Hostname != null)
            {
                @string += "@" + Hostname;
            }
            return(@string);
        }
        protected virtual void OnCtcpCommandReceived(IrcIdentity sender, IrcString recipient, IrcString command,
                                                     IrcString[] parameters, IrcString rawParameter)
        {
            switch ((string)command)
            {
            case "ACTION":
                OnGotChatAction(new ChatMessageEventArgs(sender, recipient, rawParameter));
                break;

            case "DCC":
                if (parameters.Length >= 1)
                {
                    OnDccCommandReceived(sender, recipient, parameters[0], parameters.Skip(1).ToArray());
                }
                break;

            case "PING":
                if (parameters.Length >= 1 && !IrcValidation.IsChannelName(recipient))
                {
                    CtcpReply(sender.Nickname, "PING", new IrcString[] { parameters[0] });
                }
                break;

            case "TIME":
                if (!IrcValidation.IsChannelName(recipient))
                {
                    CtcpReply(sender.Nickname, "TIME", new IrcString[] { CtcpTimeGetNow().ToString
                                                                             ("ddd MMM dd HH:mm:ss yyyy", DateTimeFormatInfo.InvariantInfo) });
                }
                break;

            case "VERSION":
                if (!IrcValidation.IsChannelName(recipient))
                {
                    CtcpReply(sender.Nickname, "VERSION", new[] { ClientVersion });
                }
                break;
            }
        }
Exemple #9
0
        public override void OnCommand(CommandArguments command)
        {
            var nick = command.Arguments.Groups["nick"].Value;

            if (!IrcIdentity.TryParse(nick, out var ident))
            {
                command.Reply("Invalid identity.");

                return;
            }

            var channel = Bootstrap.Client.ChannelList.GetChannel(command.Event.Recipient);

            if (!channel.WeAreOpped)
            {
                if (channel.HasChanServ)
                {
                    Bootstrap.Client.Client.Message("ChanServ", string.Format("op {0}", channel.Name));
                }
                else
                {
                    command.Reply("I'm not opped, send help.");

                    return;
                }
            }

            Bootstrap.Client.Whois.Query(ident,
                                         whoisData =>
            {
                if (whoisData.Identity.Nickname != null)
                {
                    ident = whoisData.Identity;
                }

                var nickname = ident.Nickname;

                if (nickname.ToString().ToLowerInvariant() == Bootstrap.Client.TrueNickname.ToLowerInvariant())
                {
                    command.Reply("Don't you even dare.");

                    return;
                }

                if (whoisData.Identity.Nickname != null)
                {
                    Whois.NormalizeIdentity(ident);
                }
                else
                {
                    if (ident.Username == null)
                    {
                        ident.Username = "******";
                    }

                    if (ident.Hostname == null)
                    {
                        ident.Hostname = "*";
                    }
                }

                var targetChannel = command.Arguments.Groups["channel"].Value.Trim();

                if (targetChannel.Length == 0)
                {
                    targetChannel = Bootstrap.Client.Settings.RedirectChannel;
                }
                else if (!IrcValidation.IsChannelName(targetChannel))
                {
                    command.Reply("Invalid target channel.");

                    return;
                }

                if (Bootstrap.Client.ModeList.Find(command.Event.Recipient, ident.ToString(), "-b") != null)
                {
                    command.Reply("{0} is already banned in this channel.", ident);

                    return;
                }

                Log.WriteInfo("Redirect", "'{0}' redirected '{1}' from {2} to {3}", command.Event.Sender, ident, command.Event.Recipient, targetChannel);

                var reason = string.Format("Redirected to {0} by {1} for 2 hours", targetChannel, command.Event.Sender.Nickname);

                Bootstrap.Client.Client.Mode(command.Event.Recipient, "+b", ident + "$" + targetChannel);

                if (channel.HasUser(nickname))
                {
                    Bootstrap.Client.Client.Kick(nickname, command.Event.Recipient, reason);
                }

                command.ReplyAsNotice("Redirected {0} to {1} for 2 hours", ident, targetChannel);

                Bootstrap.Client.ModeList.AddLateModeRequest(
                    new LateModeRequest
                {
                    Channel   = command.Event.Recipient,
                    Recipient = ident.ToString(),
                    Sender    = command.Event.Sender.ToString(),
                    Mode      = "-b",
                    Time      = DateTime.UtcNow.AddHours(2),
                    Reason    = reason
                }
                    );
            }
                                         );
        }
Exemple #10
0
        public LinkExpander(IrcClient client)
        {
            TwitterToChannels = new Dictionary <long, List <string> >();

            var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config", "services.json");

            if (!File.Exists(path))
            {
                Log.WriteWarn("Twitter", "File config/services.json doesn't exist");

                return;
            }

            var data = File.ReadAllText(path);

            try
            {
                Config = JsonConvert.DeserializeObject <LinkExpanderConfig>(data, new JsonSerializerSettings {
                    MissingMemberHandling = MissingMemberHandling.Error
                });

                if (Config.Twitter.AccessSecret == null ||
                    Config.Twitter.AccessToken == null ||
                    Config.Twitter.ConsumerKey == null ||
                    Config.Twitter.ConsumerSecret == null)
                {
                    throw new JsonException("Twitter keys cannot be null");
                }

                if (Config.Channels == null)
                {
                    Config.Channels = new List <string>();
                }
                else
                {
                    foreach (var channel in Config.Channels)
                    {
                        if (!IrcValidation.IsChannelName(channel))
                        {
                            throw new JsonException($"Invalid channel '{channel}'");
                        }
                    }
                }
            }
            catch (JsonException e)
            {
                Log.WriteError("Twitter", "Failed to parse services.json file: {0}", e.Message);

                Environment.Exit(1);
            }

            LastMatches = new FixedSizedQueue <string>
            {
                Limit = Config.DontRepeatLastCount
            };

            TwitterCompiledMatch = new Regex(@"(^|/|\.)twitter\.com/(.+?)/status/(?<status>[0-9]+)", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);

            client.GotMessage += OnMessage;

            TweetinviConfig.ApplicationSettings.TweetMode = TweetMode.Extended;

            // lul per thread or application credentials
            Auth.ApplicationCredentials = new TwitterCredentials(
                Config.Twitter.ConsumerKey,
                Config.Twitter.ConsumerSecret,
                Config.Twitter.AccessToken,
                Config.Twitter.AccessSecret
                );

            if (Config.Twitter.AccountsToFollow.Count > 0)
            {
                var thread = new Thread(StartTwitterStream)
                {
                    Name = "TwitterStream"
                };
                thread.Start();
            }
        }
Exemple #11
0
        private void OnMessage(object obj, ChatMessageEventArgs e)
        {
            // Don't do anything in a private message
            if (!IrcValidation.IsChannelName(e.Recipient))
            {
                return;
            }

            var message = e.Message.ToString().TrimEnd();

            if (string.IsNullOrEmpty(message))
            {
                return;
            }

            var isDirect = false;

            if (message.StartsWith(Bootstrap.Client.TrueNickname, StringComparison.InvariantCulture))
            {
                var length = Bootstrap.Client.TrueNickname.Length; // "Wendy: "

                // Allow pinging with any character following bots name
                if (message.Length < length + 2 || message[length] == ' ' || message[length + 1] != ' ')
                {
                    return;
                }

                message = message.Substring(length + 2);

                isDirect = true;
            }
            else if (message[0] == Bootstrap.Client.Settings.Prefix && Bootstrap.Client.Settings.Channels.Contains(e.Recipient))
            {
                message = message.Substring(1);
            }
            else
            {
                return;
            }

            var match = CompiledCommandMatch.Match(message);

            if (!match.Success)
            {
                return;
            }

            var i = 1;

            while (match.Groups[i].Value.Length == 0)
            {
                i++;
            }

            var command = RegisteredCommands[i - 1];

            Log.WriteInfo("CommandHandler", "Matched command '{0}' (as {2}) for {1}", command.Match.First(), e.Sender, match.Value);

            var arguments = new CommandArguments
            {
                IsDirect       = isDirect,
                MatchedCommand = match.Value.Trim(),
                Event          = e
            };

            if (command.Permission != null)
            {
                // If there is no such user, don't pass
                if (!Users.TryGetUser(e.Sender, out var user))
                {
                    Log.WriteInfo("CommandHandler", "'{0}' is not a user I know of, can't perform '{1}' ({2})", e.Sender, arguments.MatchedCommand, command.Permission);

                    return;
                }

                // If this user doesn't have required permission, don't pass
                if (!user.HasPermission(e.Recipient, command.Permission))
                {
                    Log.WriteInfo("CommandHandler", "'{0}' has no permission to perform '{1}' ({2})", e.Sender, arguments.MatchedCommand, command.Permission);

                    return;
                }

                Log.WriteInfo("CommandHandler", "'{0}' is authorized to perform '{1}' ({2})", e.Sender, arguments.MatchedCommand, command.Permission);
            }

            if (command.CompiledMatch != null)
            {
                arguments.Arguments = command.CompiledMatch.Match(message);

                if (!arguments.Arguments.Success)
                {
                    Help.PrintUsage(arguments, command);

                    return;
                }
            }

            command.OnCommand(arguments);
        }