# Path: txircd/modbase.py
# class Command(object):
#     def hook(self, base):
#         self.ircd = base
#         return self
#     def onUse(self, user, data):
#         pass
#     def processParams(self, user, params):
#         return {
#             "user": user,
#             "params": params
#         }
#     def updateActivity(self, user):
#         user.lastactivity = now()
# 
# Path: txircd/utils.py
# def epoch(utc_datetime):
#     delta = utc_datetime - UNIX_EPOCH
#     return int(delta.total_seconds())
# 
# def now():
#     return datetime.datetime.utcnow().replace(microsecond=0)
# 
# def irc_lower(str):
#     return str.lower().replace("[","{").replace("]","}").replace("/","|").replace("~","^")
# 
# def parse_duration(duration_string):
#     """
#     Parses a string duration given in 1y2w3d4h5m6s format
#     returning the total number of seconds
#     """
#     try: # attempt to parse as a number of seconds if we get just a number before we go through the parsing process
#         return int(duration_string)
#     except ValueError:
#         pass
#     timeparts = DURATION_REGEX.match(duration_string).groupdict()
# 
#     duration = 0
#     for unit, amount in timeparts.iteritems():
#         if amount is not None:
#             try:
#                 duration += int(amount) * time_lengths[unit]
#             except ValueError:
#                 pass
#     return duration
# 
# class CaseInsensitiveDictionary(MutableMapping):
#     def __init__(self):
#         self._data = {}
# 
#     def __repr__(self):
#         return repr(self._data)
# 
#     def __delitem__(self, key):
#         try:
#             del self._data[irc_lower(key)]
#         except KeyError:
#             raise KeyError(key)
# 
#     def __getitem__(self, key):
#         try:
#             return self._data[irc_lower(key)]
#         except KeyError:
#             raise KeyError(key)
# 
#     def __iter__(self):
#         return iter(self._data)
# 
#     def __len__(self):
#         return len(self._data)
# 
#     def __setitem__(self, key, value):
#         self._data[irc_lower(key)] = value


from twisted.words.protocols import irc
from txircd.modbase import Command
from txircd.utils import epoch, now, irc_lower, parse_duration, CaseInsensitiveDictionary
from fnmatch import fnmatch
    def statsList(self, user, statsType):
        if statsType != "G":
            return
        self.expire_glines()
        for mask, linedata in self.banList.iteritems():
            user.sendMessage(irc.RPL_STATSGLINE, ":{} {} {} {} :{}".format(mask, linedata["created"], linedata["duration"], linedata["setter"], linedata["reason"]))
    
    def register_check(self, user):
        result = self.match_gline(user)
        if not result:
            if result == None:
                return True
            return "again"
        user.sendMessage("NOTICE", ":{}".format(self.ircd.servconfig["client_ban_msg"]))
        user.sendMessage("ERROR", ":Closing Link: {} [G:Lined: {}]".format(user.hostname, result), to=None, prefix=None)
        return False
    
    def match_gline(self, user):
        if "o" in user.mode:
            return None # don't allow bans to affect opers
        if "except_line" not in user.cache:
            if "gline_match" in user.cache:
                return user.cache["gline_match"]
            # Determine whether the user matches
            self.expire_glines()
            match_against = irc_lower("{}@{}".format(user.username, user.hostname))
            for mask, linedata in self.banList.iteritems():
                if fnmatch(match_against, mask):
                    user.cache["gline_match"] = linedata["reason"]
                    return ""

# Path: txircd/modbase.py
# class Command(object):
#     def hook(self, base):
#         self.ircd = base
#         return self
#     def onUse(self, user, data):
#         pass
#     def processParams(self, user, params):
#         return {
#             "user": user,
#             "params": params
#         }
#     def updateActivity(self, user):
#         user.lastactivity = now()
# 
# Path: txircd/utils.py
# def epoch(utc_datetime):
#     delta = utc_datetime - UNIX_EPOCH
#     return int(delta.total_seconds())
# 
# def now():
#     return datetime.datetime.utcnow().replace(microsecond=0)
# 
# def irc_lower(str):
#     return str.lower().replace("[","{").replace("]","}").replace("/","|").replace("~","^")
# 
# def parse_duration(duration_string):
#     """
#     Parses a string duration given in 1y2w3d4h5m6s format
#     returning the total number of seconds
#     """
#     try: # attempt to parse as a number of seconds if we get just a number before we go through the parsing process
#         return int(duration_string)
#     except ValueError:
#         pass
#     timeparts = DURATION_REGEX.match(duration_string).groupdict()
# 
#     duration = 0
#     for unit, amount in timeparts.iteritems():
#         if amount is not None:
#             try:
#                 duration += int(amount) * time_lengths[unit]
#             except ValueError:
#                 pass
#     return duration
# 
# class CaseInsensitiveDictionary(MutableMapping):
#     def __init__(self):
#         self._data = {}
# 
#     def __repr__(self):
#         return repr(self._data)
# 
#     def __delitem__(self, key):
#         try:
#             del self._data[irc_lower(key)]
#         except KeyError:
#             raise KeyError(key)
# 
#     def __getitem__(self, key):
#         try:
#             return self._data[irc_lower(key)]
#         except KeyError:
#             raise KeyError(key)
# 
#     def __iter__(self):
#         return iter(self._data)
# 
#     def __len__(self):
#         return len(self._data)
# 
#     def __setitem__(self, key, value):
#         self._data[irc_lower(key)] = value


# Path: txircd/modules/cmd_gline.py
from twisted.words.protocols import irc
from txircd.modbase import Command
from txircd.utils import epoch, now, irc_lower, parse_duration, CaseInsensitiveDictionary
from fnmatch import fnmatch

    def statsList(self, user, statsType):
        if statsType != "G":
            return
        self.expire_glines()
        for mask, linedata in self.banList.iteritems():
            user.sendMessage(irc.RPL_STATSGLINE, ":{} {} {} {} :{}".format(mask, linedata["created"], linedata["duration"], linedata["setter"], linedata["reason"]))
    
    def register_check(self, user):
        result = self.match_gline(user)
        if not result:
            if result == None:
                return True
            return "again"
        user.sendMessage("NOTICE", ":{}".format(self.ircd.servconfig["client_ban_msg"]))
        user.sendMessage("ERROR", ":Closing Link: {} [G:Lined: {}]".format(user.hostname, result), to=None, prefix=None)
        return False
    
    def match_gline(self, user):
        if "o" in user.mode:
            return None # don't allow bans to affect opers
        if "except_line" not in user.cache:
            if "gline_match" in user.cache:
                return user.cache["gline_match"]
            # Determine whether the user matches
            self.expire_glines()
            match_against = irc_lower("{}@{}".format(user.username, user.hostname))
            for mask, linedata in self.banList.iteritems():
                if fnmatch(match_against, mask):
                    user.cache["gline_match"] = linedata["reason"]
                    return ""

            match_against = irc_lower("{}@{}".format(user.username, user.ip))