<commit_before>// Copyright (c) 2012-2014 <NAME>
// Copyright (c) 2014-2015 <NAME>
// Copyright (c) 2016-2017 <NAME> <<EMAIL>>
// released under the MIT license

package irc

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/oragono/oragono/irc/modes"
	"github.com/oragono/oragono/irc/sno"
	"github.com/oragono/oragono/irc/utils"
)

var (
	// DefaultChannelModes are enabled on brand new channels when they're created.
	// this can be overridden in the `channels` config, with the `default-modes` key
	DefaultChannelModes = modes.Modes{
		modes.NoOutside, modes.OpOnlyTopic,
	}

	// DefaultUserModes are set on all users when they login.
	// this can be overridden in the `accounts` config, with the `default-user-modes` key
	DefaultUserModes = modes.Modes{}
)

// ApplyUserModeChanges applies the given changes, and returns the applied changes.
// `oper` is the operclass of the client gaining +o, when applicable (this is just
// to confirm that the client actually has a valid operclass)
func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool, oper *Oper) modes.ModeChanges {
	applied := make(modes.ModeChanges, 0)

	for _, change := range changes {
		if change.Mode != modes.ServerNotice {
			switch change.Op {
			case modes.Add:
				if (change.Mode == modes.Operator) && !(force && oper != nil) {
					continue
				}

				if client.SetMode(change.Mode, true) {
					if change.Mode == modes.Invisible {
						client.server.stats.ChangeInvisible(1)
					} else if change.Mode == modes.Operator {
						client.server.stats.ChangeOperators(1)
					}
					applied = append(applied, change)
				}

			case modes.Remove:
				var removedSnomasks string
				if client.SetMode(change.Mode, false) {
					if change.Mode == modes.Invisible {
						client.server.stats.ChangeInvisible(-1)
					} else if change.Mode == modes.Operator {
						removedSnomasks = client.server.snomasks.String(client)
						client.server.stats.ChangeOperators(-1)
						applyOper(client, nil, nil)
						if removedSnomasks != "" {
							client.server.snomasks.RemoveClient(client)
						}
					}
					applied = append(applied, change)
					if removedSnomasks != "" {
						applied = append(applied, modes.ModeChange{
							Mode: modes.ServerNotice,
							Op:   modes.Remove,
							Arg:  removedSnomasks,
						})
					}
				}
			}
		} else {
			// server notices are weird
			if !client.HasMode(modes.Operator) || change.Op == modes.List {
				continue
			}

			currentMasks := client.server.snomasks.MasksEnabled(client)
			addMasks, removeMasks, newArg := sno.EvaluateSnomaskChanges(change.Op == modes.Add, change.Arg, currentMasks)

			success := false
			if len(addMasks) != 0 {
				oper := client.Oper()
				// #1176: require special operator privileges to subscribe to snomasks
				if oper.HasRoleCapab("snomasks") || oper.HasRoleCapab("ban") {
					success = true
					client.server.snomasks.AddMasks(client, addMasks...)
				}
			}
			if len(removeMasks) != 0 {
				success = true
				client.server.snomasks.RemoveMasks(client, removeMasks...)
			}
			if success {
				change.Arg = newArg
				applied = append(applied, change)
			}
		}
	}

	if len(applied) != 0 {
		client.markDirty(IncludeUserModes)
	}<commit_msg>fix #1618<commit_after>// Copyright (c) 2012-2014 <NAME>
// Copyright (c) 2014-2015 <NAME>
// Copyright (c) 2016-2017 <NAME> <<EMAIL>>
// released under the MIT license

package irc

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/oragono/oragono/irc/modes"
	"github.com/oragono/oragono/irc/sno"
	"github.com/oragono/oragono/irc/utils"
)

var (
	// DefaultChannelModes are enabled on brand new channels when they're created.
	// this can be overridden in the `channels` config, with the `default-modes` key
	DefaultChannelModes = modes.Modes{
		modes.NoOutside, modes.OpOnlyTopic,
	}

	// DefaultUserModes are set on all users when they login.
	// this can be overridden in the `accounts` config, with the `default-user-modes` key
	DefaultUserModes = modes.Modes{}
)

// ApplyUserModeChanges applies the given changes, and returns the applied changes.
// `oper` is the operclass of the client gaining +o, when applicable (this is just
// to confirm that the client actually has a valid operclass)
func ApplyUserModeChanges(client *Client, changes modes.ModeChanges, force bool, oper *Oper) modes.ModeChanges {
	applied := make(modes.ModeChanges, 0)

	for _, change := range changes {
		if change.Mode != modes.ServerNotice {
			switch change.Op {
			case modes.Add:
				if (change.Mode == modes.Operator) && !(force && oper != nil) {
					continue
				}

				if client.SetMode(change.Mode, true) {
					if change.Mode == modes.Invisible {
						client.server.stats.ChangeInvisible(1)
					} else if change.Mode == modes.Operator {
						client.server.stats.ChangeOperators(1)
					}
					applied = append(applied, change)
				}

			case modes.Remove:
				var removedSnomasks string
				if client.SetMode(change.Mode, false) {
					if change.Mode == modes.Invisible {
						client.server.stats.ChangeInvisible(-1)
					} else if change.Mode == modes.Operator {
						removedSnomasks = client.server.snomasks.String(client)
						client.server.stats.ChangeOperators(-1)
						applyOper(client, nil, nil)
						if removedSnomasks != "" {
							client.server.snomasks.RemoveClient(client)
						}
					}
					applied = append(applied, change)
					if removedSnomasks != "" {
						applied = append(applied, modes.ModeChange{
							Mode: modes.ServerNotice,
							Op:   modes.Remove,
							Arg:  removedSnomasks,
						})
					}
				}
			}
		} else {
			// server notices are weird
			if !client.HasMode(modes.Operator) || change.Op == modes.List {
				continue
			}

			currentMasks := client.server.snomasks.MasksEnabled(client)
			addMasks, removeMasks, newArg := sno.EvaluateSnomaskChanges(change.Op == modes.Add, change.Arg, currentMasks)

			success := false
			if len(addMasks) != 0 {
				oper := client.Oper()
				// #1176: require special operator privileges to subscribe to snomasks
				if force || oper.HasRoleCapab("snomasks") || oper.HasRoleCapab("ban") {
					success = true
					client.server.snomasks.AddMasks(client, addMasks...)
				}
			}
			if len(removeMasks) != 0 {
				success = true
				client.server.snomasks.RemoveMasks(client, removeMasks...)
			}
			if success {
				change.Arg = newArg
				applied = append(applied, change)
			}
		}
	}

	if len(applied) != 0 {
		client.markDirty(IncludeUserModes)
	}
{'fraction_non_alphanumeric': 0.11936832326985601, 'fraction_numerical': 0.011766527326211487, 'mean_word_length': 3.1041931385006354, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5233080', 'n_tokens_mistral': 2624, 'n_tokens_neox': 2052, 'n_words': 516}