Quantcast

SVN to Git conversion

Erik L. Vonderscheer [10-19-10 - 06:46]
SVN to Git conversion
4.0.1 compatibility
Fix Keyword substitutions
Expand on GetParty() to include raid members
Add Exempt list to GUI
Filename
.docmeta
.pkgmeta
Docs/changelog.txt
Docs/main.txt
TradeFilter3.lua
TradeFilter3.toc
TradeFilter3Locale.lua
TradeFilter3Options.lua
diff --git a/.docmeta b/.docmeta
index 40d3517..76a157b 100644
--- a/.docmeta
+++ b/.docmeta
@@ -1,20 +1,20 @@
--
-  type: creole
-  input-file: Docs/main.txt
-  output-page: "Main"
--
-  type: creole
-  input-file: Docs/changelog.txt
-  output-page: "ChangeLog"
--
-  type: creole
-  input-file: Docs/flow.txt
-  output-page: "Flow"
--
-  type: creole
-  input-file: Docs/default-filters.txt
-  output-page: "default-filters"
--
-  type: creole
-  input-file: Docs/default-lists.txt
-  output-page: "default-lists"
+-
+  type: creole
+  input-file: Docs/main.txt
+  output-page: "Main"
+-
+  type: creole
+  input-file: Docs/changelog.txt
+  output-page: "ChangeLog"
+-
+  type: creole
+  input-file: Docs/flow.txt
+  output-page: "Flow"
+-
+  type: creole
+  input-file: Docs/default-filters.txt
+  output-page: "default-filters"
+-
+  type: creole
+  input-file: Docs/default-lists.txt
+  output-page: "default-lists"
diff --git a/.pkgmeta b/.pkgmeta
index 3a9dc38..510d3c8 100644
--- a/.pkgmeta
+++ b/.pkgmeta
@@ -1,60 +1,60 @@
-package-as: TradeFilter3
-
-license-output: LICENSE.txt
-
-enable-nolib-creation: yes
-
-ignore:
- - .pkgmeta
- - .docmeta
- - Docs
-
-tools-used:
- - fprof
-
-externals:
- libs/LibStub:
-  url: svn://svn.wowace.com/wow/libstub/mainline/trunk
-  tag: latest
- libs/CallbackHandler-1.0:
-  url: svn://svn.wowace.com/wow/callbackhandler/mainline/trunk/CallbackHandler-1.0
-  tag: latest
- libs/AceLocale-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceLocale-3.0
-  tag: latest
- libs/AceConfig-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConfig-3.0
-  tag: latest
- libs/AceConsole-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConsole-3.0
-  tag: latest
- libs/AceDBOptions-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDBOptions-3.0
-  tag: latest
- libs/AceEvent-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceEvent-3.0
-  tag: latest
- libs/AceDB-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0
-  tag: latest
- libs/AceGUI-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceGUI-3.0
-  tag: latest
- libs/AceTimer-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceTimer-3.0
-  tag: latest
- libs/AceAddon-3.0:
-  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0
-  tag: latest
- libs/LibFriends-1.0:
-  url: svn://svn.wowace.com/wow/libfriends-1-0/mainline/trunk/LibFriends-1.0
-  tag: latest
- libs/LibAboutPanel:
-  url: git://git.curseforge.net/wow/libaboutpanel/mainline.git
-  tag: latest
- libs/LibDataBroker-1.1:
-  url: git://git.wowace.com/wow/libdatabroker-1-1/mainline.git
-  tag: latest
- libs/LibDBIcon-1.0:
-  url: svn://svn.wowace.com/wow/libdbicon-1-0/mainline/trunk
-  tag: latest
+package-as: TradeFilter3
+
+license-output: LICENSE.txt
+
+enable-nolib-creation: yes
+
+ignore:
+ - .pkgmeta
+ - .docmeta
+ - Docs
+
+tools-used:
+ - fprof
+
+externals:
+ libs/LibStub:
+  url: svn://svn.wowace.com/wow/libstub/mainline/trunk
+  tag: latest
+ libs/CallbackHandler-1.0:
+  url: svn://svn.wowace.com/wow/callbackhandler/mainline/trunk/CallbackHandler-1.0
+  tag: latest
+ libs/AceLocale-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceLocale-3.0
+  tag: latest
+ libs/AceConfig-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConfig-3.0
+  tag: latest
+ libs/AceConsole-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceConsole-3.0
+  tag: latest
+ libs/AceDBOptions-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDBOptions-3.0
+  tag: latest
+ libs/AceEvent-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceEvent-3.0
+  tag: latest
+ libs/AceDB-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceDB-3.0
+  tag: latest
+ libs/AceGUI-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceGUI-3.0
+  tag: latest
+ libs/AceTimer-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceTimer-3.0
+  tag: latest
+ libs/AceAddon-3.0:
+  url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0
+  tag: latest
+ libs/LibFriends-1.0:
+  url: svn://svn.wowace.com/wow/libfriends-1-0/mainline/trunk/LibFriends-1.0
+  tag: latest
+ libs/LibAboutPanel:
+  url: git://git.curseforge.net/wow/libaboutpanel/mainline.git
+  tag: latest
+ libs/LibDataBroker-1.1:
+  url: git://git.wowace.com/wow/libdatabroker-1-1/mainline.git
+  tag: latest
+ libs/LibDBIcon-1.0:
+  url: svn://svn.wowace.com/wow/libdbicon-1-0/mainline/trunk
+  tag: latest
diff --git a/Docs/changelog.txt b/Docs/changelog.txt
index 62a39bd..923d5df 100644
--- a/Docs/changelog.txt
+++ b/Docs/changelog.txt
@@ -1,68 +1,81 @@
-== ChangeLog
-*r204
-**++Limit function calls if CHAT_MSG event conditions are not met++\\
-**++Fix repeat detection... for good++\\
-*r203
-**++SPAM and DEBUG frames now auto created++\\
-**++Various bugs swatted++\\
-**++Minor cleanup++\\
-*r202
-**++Fix Special Channel names never matching++\\
-*r200
-**++Fix Recycle Timer configuration option that would produce a AceTimer callback error++\\
-*r199
-**++Added configuration for repeat recycling(Advanced)++\\
-**++Added achievement links to defualt Whitelist++\\
-**++Removed defunct default Whitelist entry that produced a bug in new entries++\\
-*r198
-**++Let's not check for repeats twice++\\
-*r196
-**++Fix repeat counter++\\
-**++Fix error in localization (r195)++\\
-*r195
-**++Fix repeat detection++\\
-**++GUI typo++\\
-*r192
-**++Added BG Filters++\\
-**++Config GUI reorganization++\\
-*r167
-**++Added simple duel spam block++\\
-*r159
-**++Keep lists sorted!++\\
-*r155
-**++LDB support for Repeats Blocked++\\
-**++Ability for Whitelist to bypass repeat filter++\\
-**++GUI layout changed a little++\\
-*r148
-**++Minor code cleanup++\\
-**++AceTimer lib added for repeat table recycling++\\
-*r145
-**++Rewrite on DB functions, Repeat Function and Friends functions++\\
-**++Show repeat count with ability to reset count++\\
-**++Ability to enable/disable Black and White list checking++\\
-**++Debug: Black and White list debugging messages contain whitespaces++\\
-**++Debug: Black and White list debugging messages now show what they matched in your pattern list++\\
-**++Debug: Option to strip "Checking for Match" when debugging++\\
-*r144
-**++Debug: Further Debug output cleanup++\\
-**++Better repeat detection++\\
-**++Whitelisted strings still have to pass repeat test++\\
-**++Whitelisted strings also needs to pass Blacklist++\\
-*r132
-**++Typo causing reset buttons to error out fixed++\\
-**++Added all strings to locale++\\
-**++Keys are no longer necessary when adding filter or list patterns++\\
-**++Debug: Cleaned up debugging output, will now show what pattern that was matched to allow it to not be filtered++\\
-*r131
-**++Repeat filtration++\\
-**++Configurable number of repeats before filtered++\\
-**++Configurable time required between repeats in seconds++\\
-*r126
-**++Option: Reset to default filters++\\
-*r122
-**++Distinguish between Trade channel and LFG/General for the ability to have differant filter tables for pattern matching.++\\
-**++Ability to edit entire filter tables rather than having static lists.++\\
-*r111
-**++ TradeFilter now contains a Black/White list, though not yet configurable through the GUI.++\\
-*r82
-**++ TradeFilter also will not filter any messages from your friends, they must be on your current characters friends list for this functionality to work.++\\
+== ChangeLog
+*r216
+**++TOC to 40000++\\
+**++Add current party members to exempt list for say/yell++\\
+**++Temporary Current Party Members output in options GUI++\\
+**++Wipe party table after leaving group++\\
+**++Version/Revision recognition++\\
+*r211
+**++Switch to WowAce LibDataBroker-1.1++\\
+**++Small configuration GUI update++\\
+*r209
+**++Overhead reduction++\\
+**++Docs update++\\
+**++4.0.1 compatibility++\\
+*r204
+**++Limit function calls if CHAT_MSG event conditions are not met++\\
+**++Fix repeat detection... for good++\\
+*r203
+**++SPAM and DEBUG frames now auto created++\\
+**++Various bugs swatted++\\
+**++Minor cleanup++\\
+*r202
+**++Fix Special Channel names never matching++\\
+*r200
+**++Fix Recycle Timer configuration option that would produce a AceTimer callback error++\\
+*r199
+**++Added configuration for repeat recycling(Advanced)++\\
+**++Added achievement links to defualt Whitelist++\\
+**++Removed defunct default Whitelist entry that produced a bug in new entries++\\
+*r198
+**++Let's not check for repeats twice++\\
+*r196
+**++Fix repeat counter++\\
+**++Fix error in localization (r195)++\\
+*r195
+**++Fix repeat detection++\\
+**++GUI typo++\\
+*r192
+**++Added BG Filters++\\
+**++Config GUI reorganization++\\
+*r167
+**++Added simple duel spam block++\\
+*r159
+**++Keep lists sorted!++\\
+*r155
+**++LDB support for Repeats Blocked++\\
+**++Ability for Whitelist to bypass repeat filter++\\
+**++GUI layout changed a little++\\
+*r148
+**++Minor code cleanup++\\
+**++AceTimer lib added for repeat table recycling++\\
+*r145
+**++Rewrite on DB functions, Repeat Function and Friends functions++\\
+**++Show repeat count with ability to reset count++\\
+**++Ability to enable/disable Black and White list checking++\\
+**++Debug: Black and White list debugging messages contain whitespaces++\\
+**++Debug: Black and White list debugging messages now show what they matched in your pattern list++\\
+**++Debug: Option to strip "Checking for Match" when debugging++\\
+*r144
+**++Debug: Further Debug output cleanup++\\
+**++Better repeat detection++\\
+**++Whitelisted strings still have to pass repeat test++\\
+**++Whitelisted strings also needs to pass Blacklist++\\
+*r132
+**++Typo causing reset buttons to error out fixed++\\
+**++Added all strings to locale++\\
+**++Keys are no longer necessary when adding filter or list patterns++\\
+**++Debug: Cleaned up debugging output, will now show what pattern that was matched to allow it to not be filtered++\\
+*r131
+**++Repeat filtration++\\
+**++Configurable number of repeats before filtered++\\
+**++Configurable time required between repeats in seconds++\\
+*r126
+**++Option: Reset to default filters++\\
+*r122
+**++Distinguish between Trade channel and LFG/General for the ability to have differant filter tables for pattern matching.++\\
+**++Ability to edit entire filter tables rather than having static lists.++\\
+*r111
+**++ TradeFilter now contains a Black/White list, though not yet configurable through the GUI.++\\
+*r82
+**++ TradeFilter also will not filter any messages from your friends, they must be on your current characters friends list for this functionality to work.++\\
diff --git a/Docs/main.txt b/Docs/main.txt
index 8abbf07..a782ac8 100644
--- a/Docs/main.txt
+++ b/Docs/main.txt
@@ -1,26 +1,26 @@
-== Not just any old filter!
-//Please help localize this project// [[http://www.wowace.com/projects/trade-filter/localization/|HERE]]\\
-
-TradeFilter does not only filter trade but has the ability to filter General, LookingforGroup, Say and Yell channels all which are configurable through the blizzard options panel.
-
-=== Channel Filters
-TradeFilter has a set of patterns for trade channel and separate set of patterns for all other channels, or "base" channels as we will call them. This allows the user to define what patterns may be good for trade but not other channels and vise versa. The user also has the ability to add patterns of their own to be matched against for both trade and "base" channel filters.\\
-
-[[http://www.wowace.com/projects/trade-filter/pages/default-filters/|Default Channel Filters]]\\
-
-=== Black and White Lists
-TradeFilter also has a built in Black and White list. Refer to the [[http://www.wowace.com/addons/trade-filter/pages/flow/|flowchart]] for how Black and White lists are checked.
-
-[[http://www.wowace.com/projects/trade-filter/pages/default-lists/|Default Black/White Lists]]\\
-
-=== Configuration
-<<code php>>/tf or /filter<</code>>
-
-=== To Do ===
-Nothing planned
-
-==== ChangeLog
-[[http://www.wowace.com/addons/trade-filter/pages/change-log/|ChangeLog Page]]\\
-
-=== Supported Translations
-//Please help localize this project// [[http://www.wowace.com/projects/trade-filter/localization/|HERE]]\\
+== Not just any old filter!
+//Please help localize this project// [[http://www.wowace.com/projects/trade-filter/localization/|HERE]]\\
+
+TradeFilter does not only filter trade but has the ability to filter General, LookingforGroup, Say and Yell channels all which are configurable through the blizzard options panel.
+
+=== Channel Filters
+TradeFilter has a set of patterns for trade channel and separate set of patterns for all other channels, or "base" channels as we will call them. This allows the user to define what patterns may be good for trade but not other channels and vise versa. The user also has the ability to add patterns of their own to be matched against for both trade and "base" channel filters.\\
+
+[[http://www.wowace.com/projects/trade-filter/pages/default-filters/|Default Channel Filters]]\\
+
+=== Black and White Lists
+TradeFilter also has a built in Black and White list. Refer to the [[http://www.wowace.com/addons/trade-filter/pages/flow/|flowchart]] for how Black and White lists are checked.
+
+[[http://www.wowace.com/projects/trade-filter/pages/default-lists/|Default Black/White Lists]]\\
+
+=== Configuration
+<<code php>>/tf or /filter<</code>>
+
+=== To Do ===
+Nothing planned
+
+==== ChangeLog
+[[http://www.wowace.com/addons/trade-filter/pages/change-log/|ChangeLog Page]]\\
+
+=== Supported Translations
+//Please help localize this project// [[http://www.wowace.com/projects/trade-filter/localization/|HERE]]\\
diff --git a/TradeFilter3.lua b/TradeFilter3.lua
index 4702054..a6af746 100644
--- a/TradeFilter3.lua
+++ b/TradeFilter3.lua
@@ -1,879 +1,931 @@
---[[
-TradeFilter3
-		Filter that shit!
-
-File Author: @file-author@
-File Revision: @file-revision@
-File Date: @file-date-iso@
-
-* Copyright (c) 2008, Evonder
-* All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are met:
-*     * Redistributions of source code must retain the above copyright
-*       notice, this list of conditions and the following disclaimer.
-*     * Redistributions in binary form must reproduce the above copyright
-*       notice, this list of conditions and the following disclaimer in the
-*       documentation and/or other materials provided with the distribution.
-*     * Neither the name of the <organization> nor the
-*       names of its contributors may be used to endorse or promote products
-*       derived from this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
-* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
-* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---]]
-
-TradeFilter3 = LibStub("AceAddon-3.0"):NewAddon("TradeFilter3", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0")
-local L =  LibStub("AceLocale-3.0"):GetLocale("TradeFilter3", true)
-local friends = LibStub("LibFriends-1.0")
-local LDB = LibStub("LibDataBroker-1.1", true)
-local TF3 = TradeFilter3
-
---[[ Locals ]]--
-local ipairs = ipairs
-local pairs = pairs
-local find = string.find
-local sub = string.sub
-local gsub = string.gsub
-local lower = string.lower
-local format = string.format
-local insert = table.insert
-local sort = table.sort
-local floor = math.floor
-local power = math.pow
-local timerCount = 0
-local currentFriend
-local redirectFrame = L["redirectFrame"]
-local debugFrame = L["debugFrame"]
-local repeatFrame = L["repeatFrame"]
-local lastmsgID
-local lastmsg
-local rptmsg
-local rptmsgID
-local lastuserID
-local rptdone
-
---[[  Globals  ]]--
-repeatdata = {}
-
-local MAJOR_VERSION = "@project-version@"
-local PATCH_VERSION = "@project-revision@"
-if (find(MAJOR_VERSION, "release" or "beta")) then
-	TF3.version = MAJOR_VERSION
-else
-	TF3.version = "r" .. PATCH_VERSION .. " DEV"
-end
-TF3.date = "@file-date-iso@"
-
---[[ Database Defaults ]]--
-defaults = {
-	profile = {
-		turnOn = true,
-		firstlogin = true,
-		redirect = false,
-		debug = false,
-		filterSAY = false,
-		filterYELL = false,
-		filterGAC = false,
-		filterSELF = false,
-		filterLFG = false,
-		filterBG = false,
-		filterGeneral = false,
-		filterTrade = true,
-		editfilterTRADE_enable = false,
-		editfilterBASE_enable = false,
-		editfilterBG_enable = false,
-		ebl = false,
-		ewl = false,
-		blacklist_enable = true,
-		whitelist_enable = true,
-		redirect_blacklist = false,
-		wlbp = false,
-		wlblbp = false,
-		repeat_enable = true,
-		special_enable = false,
-		num_repeats = "2",
-		time_repeats = "30",
-		repeat_recycle_time = "1800",
-		repeat_recycle_size = "50",
-		repeats_blocked =  0,
-		friendslist = {},
-		whitelist = {},
-		blacklist = {},
-		filters = {},
-	},
-}
-
-function TF3:OnInitialize()
-	--[[ Libraries ]]--
-	local ACD = LibStub("AceConfigDialog-3.0")
-	local LAP = LibStub("LibAboutPanel")
-
-	self.db = LibStub("AceDB-3.0"):New("TradeFilter3DB", defaults);
-
-	local ACP = LibStub("AceDBOptions-3.0"):GetOptionsTable(TradeFilter3.db);
-
-	local AC = LibStub("AceConsole-3.0")
-	AC:RegisterChatCommand("tf", function() TF3:OpenOptions() end)
-	AC:RegisterChatCommand("filter", function() TF3:OpenOptions() end)
-	AC:Print(L.TOC.Title .. " " .. TF3.version .. " " .. L["ENABLED"])
-
-	local ACR = LibStub("AceConfigRegistry-3.0")
-	ACR:RegisterOptionsTable("TradeFilter3", options)
-	ACR:RegisterOptionsTable("TradeFilter3P", ACP)
-
-	-- Set up options panels.
-	self.OptionsPanel = ACD:AddToBlizOptions(self.name, L["TFR"], nil, "generalGroup")
-	self.OptionsPanel.profiles = ACD:AddToBlizOptions("TradeFilter3P", L["Profiles"], self.name)
-	self.OptionsPanel.about = LAP.new(self.name, self.name)
-
-	if (TF3.db.profile.firstlogin == true) then
-		TF3:FirstLogin()
-		TF3.db.profile.firstlogin = false
-	end
-
-	if IsLoggedIn() then
-		self:IsLoggedIn()
-	else
-		self:RegisterEvent("PLAYER_LOGIN", "IsLoggedIn")
-	end
-end
-
--- :OpenOptions(): Opens the options window.
-function TF3:OpenOptions()
-	InterfaceOptionsFrame_OpenToCategory(self.OptionsPanel.profiles)
-	InterfaceOptionsFrame_OpenToCategory(self.OptionsPanel)
-end
-
-function TF3:FirstLogin()
-	TF3.db.profile.whitelist = L.WHITELIST
-	TF3.db.profile.blacklist = L.BLACKLIST
-	TF3.db.profile.filters = L.FILTERS
-end
-
-local function OnTooltipShow(self)
-	local hint = L["|cffeda55fRight Click|r to open config GUI.\n|cffeda55fLeft Click|r reset repeat count."]
-	self:AddLine(TF3.db.profile.repeats_blocked .. L[" Repeats Blocked"])
-	self:AddLine(" ")
-	self:AddLine(hint, 0.2, 1, 0.2, 1)
-end
-
-local function OnEnter(self)
-	GameTooltip:SetOwner(self, "ANCHOR_NONE")
-	GameTooltip:SetPoint("TOPLEFT", self, "BOTTOMLEFT")
-	GameTooltip:ClearLines()
-	OnTooltipShow(GameTooltip)
-	GameTooltip:Show()
-end
-
-local function OnLeave(self)
-	GameTooltip:Hide()
-end
-
-local function OnClick(clickedframe, button)
-	if (button == "RightButton") then
-		TF3:OpenOptions()
-	else
-		TF3.db.profile.repeats_blocked = 0
-		TF3Frame.Blocked.text = TF3.db.profile.repeats_blocked .. L[" Repeats Blocked"]
-		TF3Frame.Blocked.value = TF3.db.profile.repeats_blocked
-	end
-end
-
-function TF3:IsLoggedIn()
-	self:RegisterEvent("FRIENDLIST_UPDATE", "GetFriends")
-	friends.RegisterCallback(self, "Added")
-	friends.RegisterCallback(self, "Removed")
-	self:ScheduleRepeatingTimer("RecycleTables", tonumber(TF3.db.profile.repeat_recycle_time), repeatdata)
-	self:UnregisterEvent("PLAYER_LOGIN")
-	TF3:DuelFilter()
-
-	if (LDB) then
-		TF3Frame = CreateFrame("Frame", "LDB_TradeFilter3")
-		TF3Frame.Blocked = LDB:NewDataObject(L["TFR"], {
-			type = "data source",
-			icon = "Interface\\Icons\\Ability_Warrior_RallyingCry",
-			text = L["0 Repeats Blocked"],
-			value = TF3.db.profile.repeats_blocked,
-			suffix = L[" Repeats Blocked"],
-			OnClick = OnClick,
-			OnEnter = OnEnter,
-			OnLeave = OnLeave,
-			OnTooltipShow = OnTooltipShow,
-		})
-	end
-end
-
---[[ Helper Functions ]]--
-function TF3:WipeTable(t)
-	if (t ~= nil and type(t) == "table") then
-		wipe(t)
-	end
-end
-
-function TF3:CopyTable(t)
-  local new_t = {}
-  for k, v in pairs(t) do
-    if (type(v) == "table") then
-      new_t[k] = TF3:CopyTable(v)
-    else
-			new_t[k] = v
-    end
-  end
-  return new_t
-end
-
-function TF3:GetNumElements(t)
- local count = 0
- for _ in pairs(t) do
-  count = count + 1
- end
- return count
-end
-
-function TF3:getnHash(t)
-   local count = 0;
-   if not t then return 0; end
-   if (type(t)) ~= "table" then return 0; end
-   for i,_ in pairs(t) do
-      count = count + 1;
-   end
-   return count;
-end
-
-function TF3:RecycleTables(t, state)
-	local gtime = floor(GetTime()*power(10,0)+0.5) / power(10,0)
-	if (t ~= nil and type(t) == "table" and TF3:GetNumElements(t) >= tonumber(TF3.db.profile.repeat_recycle_size)) then
-		local key, value = next(t, state)
-		if key then
-			for k,v in pairs(value) do
-				if(k == "lastIndex" and gtime - v > tonumber(TF3.db.profile.repeat_recycle_time)) then
-					if (TF3.db.profile.debug) then
-						TF3:FindFrame(debugFrame, "|cFFFFFF80" .. L["RMVRT1"] .. "|r |cFF33FF99" .. key .. "|r |cFFFFFF80" .. L["RMVRT2"] .. "|r")
-					end
-					t[key] = nil
-				end
-			end
-			return value, TF3:RecycleTables(t, key)
-		end
-		timerCount = timerCount + 1
-		if (TF3.db.profile.debug) then
-			TF3:FindFrame(debugFrame, ("%d " .. L["SECPSD"]):format(tonumber(TF3.db.profile.repeat_recycle_time) * timerCount))
-		end
-	end
-end
-
-function TF3:GetColoredName(userID, cName)
-	if (cName ~= "") then
-		local localizedClass, englishClass, localizedRace, englishRace, sex = GetPlayerInfoByGUID(cName)
-		if (englishClass) then
-			local classColorTable = RAID_CLASS_COLORS[englishClass]
-			if (not classColorTable) then
-				return userID;
-			end
-				return string.format("\124cff%.2x%.2x%.2x", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255)..userID.."\124r"
-		end
-	end
-	return userID;
-end
-
---[[ Friends Functions ]]--
-function TF3:GetFriends()
-	local friends = TF3.db.profile.friendslist
-	local numFriends = GetNumFriends()
-	if (#friends ~= numFriends) then
-		print("|cFF33FF99" .. L["TFFR"] .. "|r")
-		TF3:WipeTable(friends)
-		for i=1, numFriends do
-			local name = GetFriendInfo(i)
-			if name then
-				friends[i] = name
-				if (TF3.db.profile.debug) then
-					TF3:FindFrame(debugFrame, "|cFFFFFF80" .. name .. " " .. L["FADD"] .. "|r")
-				end
-			end
-		end
-		print("|cFF33FF99" .. L["TFFRC"] .. "|r")
-	end
-	self:UnregisterEvent("FRIENDLIST_UPDATE")
-end
-
-function TF3:Added(event, name)
-	local friends = TF3.db.profile.friendslist
-	if name ~= UnitName("player") then
-		friends[#friends + 1] = name
-		if (TF3.db.profile.debug) then
-			TF3:FindFrame(debugFrame, "|cFFFFFF80" .. name .. " " .. L["FADD"] .. "|r")
-		end
-	end
-	if currentFriend then
-		self:GetFriends()
-	end
-end
-
-function TF3:Removed(event, name)
-	local friends = TF3.db.profile.friendslist
-	if friends ~= nil then
-		for k,v in ipairs(friends) do
-			if find(name,v) then
-				friends[k] = nil
-				if (TF3.db.profile.debug) then
-					TF3:FindFrame(debugFrame, "|cFFFFFF80" .. name .. " " .. L["FREM"] .. "|r")
-				end
-			end
-		end
-	end
-	if currentFriend then
-		self:GetFriends()
-	end
-end
-
-function TF3:IsFriend(userID)
-	local friends = TF3.db.profile.friendslist
-	for _,name in ipairs(friends) do
-		if find(userID,name) then
-			return true
-		end
-	end
-	return false
-end
-
---[[ Duel Spam Functions ]]--
-function TF3:DuelFilter()
-	if (TF3.db.profile.filterDuelSpam) then
-		DUEL_WINNER_KNOCKOUT, DUEL_WINNER_RETREAT = "", ""
-	else
-		DUEL_WINNER_KNOCKOUT, DUEL_WINNER_RETREAT = L["DUEL_WINNER_KNOCKOUT"], L["DUEL_WINNER_RETREAT"]
-	end
-end
-
---[[ BlackList Func ]]--
---[[ Base blacklist words from BadBoy(Funkydude) ]]--
-function TF3:BlackList(msg, userID, msgID, coloredName, arg)
-	local blword = TF3.db.profile.blacklist
-	local msg = lower(msg)
-	if (arg == whitelist and TF3.db.profile.wlblbp == true) then
-		return false
-	else
-		if (TF3.db.profile.blacklist_enable) then
-			for _,word in pairs(blword) do
-				if (find(msg,word)) then
-					if (TF3.db.profile.debug) then
-						if (msgID ~= lastmsgID) then
-							TF3:FindFrame(debugFrame, "|cFFFF0000[" .. L["bLists"] .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
-							TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cFFFF0000" .. word .. "|r")
-							if not (TF3.db.profile.redirect_blacklist) then
-								lastmsgID = msgID
-							end
-						end
-					end
-					if (TF3.db.profile.redirect_blacklist) then
-						if (msgID ~= lastmsgID) then
-							TF3:FindFrame(redirectFrame, "|cFFFF0000[" .. L["bLists"] .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
-							TF3:FindFrame(redirectFrame, L["MATCHED"] .. " |cFFFF0000" .. word .. "|r")
-							lastmsgID = msgID
-						end
-					end
-					return true
-				end
-			end
-		end
-		return false
-	end
-end
-
---[[ WhiteList Func ]]--
-function TF3:WhiteList(msg, userID, msgID, coloredName)
-	local wlword = TF3.db.profile.whitelist
-	local msg = lower(msg)
-	if (TF3.db.profile.whitelist_enable) then
-		for _,word in pairs(wlword) do
-			if (find(msg,word) and TF3:FindRepeat(msg, userID, msgID, coloredName, whitelist) == false and TF3:BlackList(msg, userID, msgID, coloredName, whitelist) == false) then
-				if (TF3.db.profile.debug) then
-					if (msgID ~= lastmsgID) then
-						TF3:FindFrame(debugFrame, "|cFFFFFF80[" .. L["wLists"] .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
-						TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cFFFFFF80" .. word .. "|r")
-						lastmsgID = msgID
-					end
-				end
-				return true
-			end
-		end
-	end
-	return false
-end
-
---[[ Special Channels Func ]]--
-function TF3:SpecialChans(chanName)
-	local schans = TF3.db.profile.filters.SPECIAL
-	local chanName = lower(chanName)
-	if (schans == nil) then
-		schans = L.FILTERS.SPECIAL
-	end
-	for _,names in pairs(schans) do
-		if (find(chanName,lower(names)) and names ~= "") then
-			return true
-		end
-	end
-	return false
-end
-
---[[ Repeat Func ]]--
-function TF3:FindRepeat(msg, userID, msgID, coloredName, arg)
-	local gtime = floor(GetTime()*power(10,0)+0.5) / power(10,0)
-	if (arg == whitelist and TF3.db.profile.wlbp == true) then
-		return false
-	elseif (TF3.db.profile.repeat_enable == false) then
-		return false
-	else
-		if (msgID ~= repeatdata[userID].lastmsgID and msg == repeatdata[userID].lastmsg and gtime - repeatdata[userID].lastIndex < tonumber(TF3.db.profile.time_repeats)) then
-			repeatdata[userID].repeats = repeatdata[userID].repeats + 1
-			if (repeatdata[userID].repeats >= tonumber(TF3.db.profile.num_repeats)) then
-				if (msg ~= rptmsg or msg == rptmsg and msgID ~= rptmsgID) then
-					if (TF3.db.profile.debug) then
-						if rptmsg ~= nil then
-							TF3:FindFrame(repeatFrame, "|cFFFF8C00[" .. L["#RPT"] .. "]|r |cFFD9D9D9[" .. msgID .. "(" .. rptmsgID .. ")" .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080" .. msg .. "(" .. rptmsg .. ")" .. "|r")
-						else
-							TF3:FindFrame(repeatFrame, "|cFFFF8C00[" .. L["#RPT"] .. "]|r |cFFD9D9D9[" .. msgID .. "(" .. repeatdata[userID].lastmsgID .. ")" .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080" .. msg .. "(" .. repeatdata[userID].lastmsg .. ")" .. "|r")
-						end
-					end
-					TF3.db.profile.repeats_blocked = TF3.db.profile.repeats_blocked + 1
-					if (LDB) then
-						TF3Frame.Blocked.text = TF3.db.profile.repeats_blocked .. L[" Repeats Blocked"]
-						TF3Frame.Blocked.value = TF3.db.profile.repeats_blocked
-					end
-					rptmsg = msg
-					rptmsgID = msgID
-				end
-				rptdone = 1 + msgID
-				return true
-			end
-		elseif (msg ~= repeatdata[userID].lastmsg) then
-			repeatdata[userID].repeats = 1
-		end
-		repeatdata[userID].lastmsg = msg
-		repeatdata[userID].lastmsgID = msgID
-		repeatdata[userID].lastIndex  = gtime
-		return false
-	end
-end
-
---[[ Window and Chat Functions ]]--
-function TF3:FindFrame(toFrame, msg)
-	for i=1,FCF_GetNumActiveChatFrames() do
-		local name = GetChatWindowInfo(i)
-		if (toFrame == name) then
-			local msgFrame = _G["ChatFrame" .. i]
-			msgFrame:AddMessage(msg)
-			return
-		end
-	end
-	if (toFrame ~= name) then
-		TF3:CreateFrame(toFrame, msg)
-	end
-end
-
-function TF3:CreateFrame(newFrame, msg)
-  local newFrame = FCF_OpenNewWindow(newFrame)
-	newFrame:AddMessage(msg)
-end
-
---[[ PreFilter Functions ]]--
---[[----------------------------------------------------------------------------------
-Taken from SpamMeNot
-			arg1:	chat message
-			arg2:	author
-			arg7:	zone ID used for generic system channels (1 for General,
-					2 for Trade, 22 for LocalDefense, 23 for WorldDefense and
-					26 for LFG)	not used for custom channels or if you joined
-					an Out-Of-Zone channel ex: "General - Stormwind City"
-			arg8:	channel number
-	the arguments a1..a9 are all nil until Blizzard actually passes them
-	we're expected to use global variables which is generally a bad idea
-	global variables may not be available in a later patch so we have to do this:
-------------------------------------------------------------------------------------]]
-
---[[ Check for AddOn Channel and User setting ]]--
-local function PreFilterFunc_Addon(self, event, ...)
-	local filtered = false
-	local prefix = arg1 or select(1, ...)
-	local msg = arg2 or select(2, ...)
-	local distType = arg3 or select(3, ...)
-	local userID = arg4 or select(4, ...)
-	local msgID = arg11 or select(11, ...)
-	local cName = arg12 or select(12, ...)
-	local coloredName = TF3:GetColoredName(userID, cName)
-	if (repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
-		repeatdata[userID] = {}
-		repeatdata[userID].lastmsg = msg
-		repeatdata[userID].lastmsgID = msgID
-		repeatdata[userID].lastIndex = 1
-		repeatdata[userID].repeats = 1
-		rptdone = msgID
-	end
-	if (TF3.db.profile.filterGAC) then
-		if (find(prefix,"ET") and distType == "GUILD") then
-			if (TF3:IsFriend(userID) == false) then
-				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
-					filtered = false
-				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
-					filtered = true
-				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
-					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
-						filtered = true
-					else
-						filtered = TF3:FilterFunc(...)
-					end
-				else
-					filtered = TF3:FilterFunc(...)
-				end
-			else
-				filtered = false
-			end
-		end
-	end
-	return filtered
-end
-
---[[ Check for SAY Channel and User setting ]]--
-local function PreFilterFunc_Say(self, event, ...)
-	local filtered = false
-	local msg = arg1 or select(1, ...)
-	local userID = arg2 or select(2, ...)
-	local chanName = arg9 or select(9, ...)
-	local msgID = arg11 or select(11, ...)
-	local cName = arg12 or select(12, ...)
-	local coloredName = TF3:GetColoredName(userID, cName)
-	if (repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
-		repeatdata[userID] = {}
-		repeatdata[userID].lastmsg = msg
-		repeatdata[userID].lastmsgID = msgID
-		repeatdata[userID].lastIndex = 1
-		repeatdata[userID].repeats = 1
-		rptdone = msgID
-	end
-	if (TF3.db.profile.filterSAY) then
-		if (event == "CHAT_MSG_SAY") then
-			if (TF3:IsFriend(userID) == false) then
-				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
-					filtered = false
-				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
-					filtered = true
-				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
-					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
-						filtered = true
-					else
-						filtered = TF3:FilterFunc("0. " .. L["Say/Yell"], ...)
-					end
-				else
-					filtered = TF3:FilterFunc("0. " .. L["Say/Yell"], ...)
-				end
-			elseif (event == "CHAT_MSG_SAY" and not TF3.db.profile.filterSAY) then
-				filtered = false
-			end
-		end
-	end
-	return filtered
-end
-
---[[ Check for YELL Channel and User setting ]]--
-local function PreFilterFunc_Yell(self, event, ...)
-	local filtered = false
-	local msg = arg1 or select(1, ...)
-	local userID = arg2 or select(2, ...)
-	local msgID = arg11 or select(11, ...)
-	local cName = arg12 or select(12, ...)
-	local coloredName = TF3:GetColoredName(userID, cName)
-	if (repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
-		repeatdata[userID] = {}
-		repeatdata[userID].lastmsg = msg
-		repeatdata[userID].lastmsgID = msgID
-		repeatdata[userID].lastIndex = 1
-		repeatdata[userID].repeats = 1
-		rptdone = msgID
-	end
-	if (TF3.db.profile.filterYELL) then
-		if (event == "CHAT_MSG_YELL") then
-			if (TF3:IsFriend(userID) == false) then
-				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
-					filtered = false
-				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
-					filtered = true
-				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
-					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
-						filtered = true
-					else
-						filtered = TF3:FilterFunc("0. " .. L["Say/Yell"], ...)
-					end
-				else
-					filtered = TF3:FilterFunc("0. " .. L["Say/Yell"], ...)
-				end
-			elseif (event == "CHAT_MSG_YELL" and not TF3.db.profile.filterYELL) then
-				filtered = false
-			end
-		end
-	end
-	return filtered
-end
-
---[[ Check for Battleground Channel and User setting ]]--
-local function PreFilterFunc_BG(self, event, ...)
-	local filtered = false
-	local msg = arg1 or select(1, ...)
-	local userID = arg2 or select(2, ...)
-	local msgID = arg11 or select(11, ...)
-	local cName = arg12 or select(12, ...)
-	local coloredName = TF3:GetColoredName(userID, cName)
-	if (repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
-		repeatdata[userID] = {}
-		repeatdata[userID].lastmsg = msg
-		repeatdata[userID].lastmsgID = msgID
-		repeatdata[userID].lastIndex = 1
-		repeatdata[userID].repeats = 1
-		rptdone = msgID
-	end
-	if (TF3.db.profile.filterBG) then
-		if (event == "CHAT_MSG_BATTLEGROUND" or event == "CHAT_MSG_BATTLEGROUND_LEADER") then
-			if (TF3:IsFriend(userID) == false) then
-				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
-					filtered = false
-				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
-					filtered = true
-				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
-					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
-						filtered = true
-					else
-						filtered = TF3:FilterFunc("0. BG", ...)
-					end
-				else
-					filtered = TF3:FilterFunc("0. BG", ...)
-				end
-			elseif (not TF3.db.profile.filterBG and event == "CHAT_MSG_BATTLEGROUND" or event == "CHAT_MSG_BATTLEGROUND_LEADER") then
-				filtered = false
-			end
-		end
-	end
-	return filtered
-end
-
---[[ Check for Trade/General/LFG Channel and User setting ]]--
-local function PreFilterFunc(self, event, ...)
-	local filtered = false
-	local msg = arg1 or select(1, ...)
-	local userID = arg2 or select(2, ...)
-	local zoneID = arg7 or select(7, ...)
-	local chanID = arg8 or select(8, ...)
-	local chanName = arg9 or select(9, ...)
-	local msgID = arg11 or select(11, ...)
-	local cName = arg12 or select(12, ...)
-	local coloredName = TF3:GetColoredName(userID, cName)
-	if (repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
-		repeatdata[userID] = {}
-		repeatdata[userID].lastmsg = msg
-		repeatdata[userID].lastmsgID = msgID
-		repeatdata[userID].lastIndex = 1
-		repeatdata[userID].repeats = 1
-		rptdone = msgID
-	end
-	--[[ Check for Trade Channel and User setting ]]--
-	if (zoneID == 2) then
-		if (TF3.db.profile.filtertrade) then
-			if (TF3:IsFriend(userID) == false) then
-				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
-					filtered = false
-				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
-					filtered = true
-				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
-					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
-						filtered = true
-					else
-						filtered = TF3:FilterFunc("2. " .. L["Trade"], ...)
-					end
-				else
-					filtered = TF3:FilterFunc("2. " .. L["Trade"], ...)
-				end
-			elseif (zoneID == 2 and not TF3.db.profile.filterTrade) then
-				filtered = false
-			end
-		end
---~ 	end
-	--[[ Check for General Channel and User setting ]]--
-	elseif (chanID == 1) then
-		if (TF3.db.profile.filtergeneral) then
-			if (TF3:IsFriend(userID) == false) then
-				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
-					filtered = false
-				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
-					filtered = true
-				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
-					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
-						filtered = true
-					else
-						filtered = TF3:FilterFunc("1. " .. L["General"], ...)
-					end
-				else
-					filtered = TF3:FilterFunc("1. " .. L["General"], ...)
-				end
-			elseif (chanID == 1 and not TF3.db.profile.filterGeneral) then
-				filtered = false
-			end
-		end
---~ 	end
-	--[[ Check for LFG Channel and User setting ]]--
-	elseif (zoneID == 26) then
-		if (TF3.db.profile.filterLFG) then
-			if (TF3:IsFriend(userID) == false) then
-				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
-					filtered = false
-				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
-					filtered = true
-				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
-					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
-						filtered = true
-					else
-						filtered = TF3:FilterFunc("26. " .. L["LFG"], ...)
-					end
-				else
-					filtered = TF3:FilterFunc("26. " .. L["LFG"], ...)
-				end
-			elseif (chanID == 26 and not TF3.db.profile.filterLFG) then
-				filtered = false
-			end
-		end
---~ 	end
-	--[[ Check for Special Channel and User setting ]]--
-	elseif (TF3:SpecialChans(chanName) == true) then
-		if (TF3.db.profile.special_enable) then
-			if (TF3:IsFriend(userID) == false) then
-				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
-					filtered = false
-				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
-					filtered = true
-				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
-					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
-						filtered = true
-					else
-						filtered = TF3:FilterFunc("X. " .. chanName, ...)
-					end
-				else
-					filtered = TF3:FilterFunc("X. " .. chanName, ...)
-				end
-			elseif (TF3:SpecialChans(chanName) == true and not TF3.db.profile.special_enable) then
-				filtered = false
-			end
-		end
-	end
-	return filtered
-end
-
---[[ Filter Func ]]--
-function TF3:FilterFunc(chan, ...)
-	local filterFuncList = ChatFrame_GetMessageEventFilters("CHAT_MSG_CHANNEL")
-	local msg = arg1 or select(1, ...)
-	local userID = arg2 or select(2, ...)
-	local zoneID = arg7 or select(7, ...)
-	local chanID = arg8 or select(8, ...)
-	local chanName = arg9 or select(9, ...)
-	local msgID = arg11 or select(11, ...)
-	local cName = arg12 or select(12, ...)
-	local coloredName = TF3:GetColoredName(userID, cName)
-	local msg = lower(msg)
-	if (filterFuncList and TF3.db.profile.turnOn) then
-		filtered = true
-		if (TF3.db.profile.debug) then
-			if (lastmsg ~= msg or lastuserID ~= userID) then
-				TF3:FindFrame(debugFrame, "|cFFC08080[" .. chan .. "]|r |cFFD9D9D9[" .. msgID .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
-			end
-		end
-		if (zoneID == 2) then
-			if (TF3.db.profile.filters.TRADE == nil) then
-				TF3.db.profile.filters.TRADE = L.FILTERS.TRADE
-			end
-			for k,v in pairs(TF3.db.profile.filters.TRADE) do
-				if (TF3.db.profile.debug and not TF3.db.profile.debug_checking) then
-					if (lastmsg ~= msg or lastuserID ~= userID) then
-						TF3:FindFrame(debugFrame, L["CFM"] .. " " .. v)
-					end
-				end
-				if (find(msg,v)) then
-					if (TF3.db.profile.debug) then
-						if (lastmsg ~= msg or lastuserID ~= userID) then
-							TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cffff8080" .. v .. "|r")
-							lastmsg, lastuserID = msg, userID
-						end
-					end
-					filtered = false
-				end
-			end
-		elseif (chan == "0. BG") then
-			if (TF3.db.profile.filters.BG == nil) then
-				TF3.db.profile.filters.BG = L.FILTERS.BG
-			end
-			for k,v in pairs(TF3.db.profile.filters.BG) do
-				if (TF3.db.profile.debug and not TF3.db.profile.debug_checking) then
-					if (lastmsg ~= msg or lastuserID ~= userID) then
-						TF3:FindFrame(debugFrame, L["CFM"] .. " " .. v)
-					end
-				end
-				if (find(msg,v)) then
-					if (TF3.db.profile.debug) then
-						if (lastmsg ~= msg or lastuserID ~= userID) then
-							TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cffff8080" .. v .. "|r")
-							lastmsg, lastuserID = msg, userID
-						end
-					end
-					filtered = false
-				end
-			end
-		else
-			if (TF3.db.profile.filters.BASE == nil) then
-				TF3.db.profile.filters.BASE = L.FILTERS.BASE
-			end
-			for k,v in pairs(TF3.db.profile.filters.BASE) do
-				if (TF3.db.profile.debug and not TF3.db.profile.debug_checking) then
-					if (lastmsg ~= msg or lastuserID ~= userID) then
-						TF3:FindFrame(debugFrame, L["CFM"] .. " " .. v)
-					end
-				end
-				if (find(msg,v)) then
-					if (TF3.db.profile.debug) then
-						if (lastmsg ~= msg or lastuserID ~= userID) then
-							TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cffff8080" .. v .. "|r")
-							lastmsg, lastuserID = msg, userID
-						end
-					end
-					filtered = false
-					end
-				end
-			end
-		if (filtered == true) then
-			if (lastmsg ~= msg or lastuserID ~= userID) then
-				if (TF3.db.profile.debug) then
-					TF3:FindFrame(debugFrame, L["NOMATCH"])
-				end
-				if (TF3.db.profile.redirect) then
-					TF3:FindFrame(redirectFrame, "|cFFC08080[" .. chan .. "]|r |cFFD9D9D9[" .. msgID .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
-				end
-				lastmsg, lastuserID = msg, userID
-			end
-		end
-	end
-	return filtered
-end
-
---[[ Pass ALL chat messages to PreFilter function ]]--
-ChatFrame_AddMessageEventFilter("CHAT_MSG_SAY", PreFilterFunc_Say)
-ChatFrame_AddMessageEventFilter("CHAT_MSG_YELL", PreFilterFunc_Yell)
-ChatFrame_AddMessageEventFilter("CHAT_MSG_ADDON", PreFilterFunc_Addon)
-ChatFrame_AddMessageEventFilter("CHAT_MSG_BATTLEGROUND", PreFilterFunc_BG)
-ChatFrame_AddMessageEventFilter("CHAT_MSG_BATTLEGROUND_LEADER", PreFilterFunc_BG)
-ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL", PreFilterFunc)
+--[[
+TradeFilter3
+		Filter that shit!
+
+File Author: @file-author@
+File Revision: @file-abbreviated-hash@
+File Date: @file-date-iso@
+
+* Copyright (c) 2008, Evonder
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+*     * Redistributions of source code must retain the above copyright
+*       notice, this list of conditions and the following disclaimer.
+*     * Redistributions in binary form must reproduce the above copyright
+*       notice, this list of conditions and the following disclaimer in the
+*       documentation and/or other materials provided with the distribution.
+*     * Neither the name of the <organization> nor the
+*       names of its contributors may be used to endorse or promote products
+*       derived from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
+* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+--]]
+
+TradeFilter3 = LibStub("AceAddon-3.0"):NewAddon("TradeFilter3", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0")
+local L =  LibStub("AceLocale-3.0"):GetLocale("TradeFilter3", true)
+local friends = LibStub("LibFriends-1.0")
+local LDB = LibStub("LibDataBroker-1.1", true)
+local TF3 = TradeFilter3
+
+--[[ Locals ]]--
+local ipairs = ipairs
+local pairs = pairs
+local find = string.find
+local sub = string.sub
+local gsub = string.gsub
+local lower = string.lower
+local format = string.format
+local insert = table.insert
+local sort = table.sort
+local floor = math.floor
+local power = math.pow
+local timerCount = 0
+local currentFriend
+local redirectFrame = L["redirectFrame"]
+local debugFrame = L["debugFrame"]
+local repeatFrame = L["repeatFrame"]
+local lastmsgID
+local lastmsg
+local rptmsg
+local rptmsgID
+local lastuserID
+local rptdone
+
+TF3.repeatdata = {}
+TF3.currentPartyMembers = {}
+
+local MAJOR_VERSION = "@project-version@"
+if (find(MAJOR_VERSION, "release" or "beta")) then
+	TF3.version = MAJOR_VERSION
+else
+	TF3.version = MAJOR_VERSION .. " DEV"
+end
+TF3.date = "@file-date-iso@"
+
+--[[ Database Defaults ]]--
+defaults = {
+	profile = {
+		turnOn = true,
+		firstlogin = true,
+		redirect = false,
+		debug = false,
+		filterSAY = false,
+		filterYELL = false,
+		filterGAC = false,
+		filterSELF = false,
+		filterLFG = false,
+		filterBG = false,
+		filterGeneral = false,
+		filterTrade = true,
+		editfilterTRADE_enable = false,
+		editfilterBASE_enable = false,
+		editfilterBG_enable = false,
+		ebl = false,
+		ewl = false,
+		blacklist_enable = true,
+		whitelist_enable = true,
+		redirect_blacklist = false,
+		wlbp = false,
+		wlblbp = false,
+		repeat_enable = true,
+		special_enable = false,
+		num_repeats = "2",
+		time_repeats = "30",
+		repeat_recycle_time = "1800",
+		repeat_recycle_size = "50",
+		repeats_blocked =  0,
+		friendslist = {},
+		whitelist = {},
+		blacklist = {},
+		filters = {},
+	},
+}
+
+function TF3:OnInitialize()
+	--[[ Libraries ]]--
+	local ACD = LibStub("AceConfigDialog-3.0")
+	local LAP = LibStub("LibAboutPanel")
+
+	self.db = LibStub("AceDB-3.0"):New("TradeFilter3DB", defaults);
+
+	local ACP = LibStub("AceDBOptions-3.0"):GetOptionsTable(TradeFilter3.db);
+
+	local AC = LibStub("AceConsole-3.0")
+	AC:RegisterChatCommand("tf", function() TF3:OpenOptions() end)
+	AC:RegisterChatCommand("filter", function() TF3:OpenOptions() end)
+	AC:Print(L.TOC.Title .. " " .. TF3.version .. " " .. L["ENABLED"])
+
+	local ACR = LibStub("AceConfigRegistry-3.0")
+	ACR:RegisterOptionsTable("TradeFilter3", options)
+	ACR:RegisterOptionsTable("TradeFilter3P", ACP)
+
+	-- Set up options panels.
+	self.OptionsPanel = ACD:AddToBlizOptions(self.name, L["TFR"], nil, "generalGroup")
+	self.OptionsPanel.profiles = ACD:AddToBlizOptions("TradeFilter3P", L["Profiles"], self.name)
+	self.OptionsPanel.about = LAP.new(self.name, self.name)
+
+	if (TF3.db.profile.firstlogin == true) then
+		TF3:FirstLogin()
+		TF3.db.profile.firstlogin = false
+	end
+
+	if IsLoggedIn() then
+		self:IsLoggedIn()
+	else
+		self:RegisterEvent("PLAYER_LOGIN", "IsLoggedIn")
+	end
+end
+
+-- :OpenOptions(): Opens the options window.
+function TF3:OpenOptions()
+	InterfaceOptionsFrame_OpenToCategory(self.OptionsPanel.profiles)
+	InterfaceOptionsFrame_OpenToCategory(self.OptionsPanel)
+end
+
+function TF3:FirstLogin()
+	TF3.db.profile.whitelist = L.WHITELIST
+	TF3.db.profile.blacklist = L.BLACKLIST
+	TF3.db.profile.filters = L.FILTERS
+end
+
+local function OnTooltipShow(self)
+	local hint = L["|cffeda55fRight Click|r to open config GUI.\n|cffeda55fLeft Click|r reset repeat count."]
+	self:AddLine(TF3.db.profile.repeats_blocked .. L[" Repeats Blocked"])
+	self:AddLine(" ")
+	self:AddLine(hint, 0.2, 1, 0.2, 1)
+end
+
+local function OnEnter(self)
+	GameTooltip:SetOwner(self, "ANCHOR_NONE")
+	GameTooltip:SetPoint("TOPLEFT", self, "BOTTOMLEFT")
+	GameTooltip:ClearLines()
+	OnTooltipShow(GameTooltip)
+	GameTooltip:Show()
+end
+
+local function OnLeave(self)
+	GameTooltip:Hide()
+end
+
+local function OnClick(clickedframe, button)
+	if (button == "RightButton") then
+		TF3:OpenOptions()
+	else
+		TF3.db.profile.repeats_blocked = 0
+		TF3Frame.Blocked.text = TF3.db.profile.repeats_blocked .. L[" Repeats Blocked"]
+		TF3Frame.Blocked.value = TF3.db.profile.repeats_blocked
+	end
+end
+
+function TF3:IsLoggedIn()
+	self:RegisterEvent("FRIENDLIST_UPDATE", "GetFriends")
+	self:RegisterEvent("PARTY_MEMBERS_CHANGED", "GetParty")
+	friends.RegisterCallback(self, "Added")
+	friends.RegisterCallback(self, "Removed")
+	self:ScheduleRepeatingTimer("RecycleTables", tonumber(TF3.db.profile.repeat_recycle_time), TF3.repeatdata)
+	self:UnregisterEvent("PLAYER_LOGIN")
+	TF3:DuelFilter()
+
+	if (LDB) then
+		TF3Frame = CreateFrame("Frame", "LDB_TradeFilter3")
+		TF3Frame.Blocked = LDB:NewDataObject(L["TFR"], {
+			type = "data source",
+			icon = "Interface\\Icons\\Ability_Warrior_RallyingCry",
+			text = L["0 Repeats Blocked"],
+			value = TF3.db.profile.repeats_blocked,
+			suffix = L[" Repeats Blocked"],
+			OnClick = OnClick,
+			OnEnter = OnEnter,
+			OnLeave = OnLeave,
+			OnTooltipShow = OnTooltipShow,
+		})
+	end
+end
+
+--[[ Helper Functions ]]--
+function TF3:WipeTable(t)
+	if (t ~= nil and type(t) == "table") then
+		wipe(t)
+	end
+end
+
+function TF3:CopyTable(t)
+  local new_t = {}
+  for k, v in pairs(t) do
+    if (type(v) == "table") then
+      new_t[k] = TF3:CopyTable(v)
+    else
+			new_t[k] = v
+    end
+  end
+  return new_t
+end
+
+function TF3:GetNumElements(t)
+	local count = 0
+	if not (t or type(t) ~= "table") then
+		return 0
+	end
+	for _ in pairs(t) do
+		count = count + 1
+	end
+	return count
+end
+
+function TF3:RecycleTables(t, state)
+	local gtime = floor(GetTime()*power(10,0)+0.5) / power(10,0)
+	if (t ~= nil and type(t) == "table" and TF3:GetNumElements(t) >= tonumber(TF3.db.profile.repeat_recycle_size)) then
+		local key, value = next(t, state)
+		if key then
+			for k,v in pairs(value) do
+				if(k == "lastIndex" and gtime - v > tonumber(TF3.db.profile.repeat_recycle_time)) then
+					if (TF3.db.profile.debug) then
+						TF3:FindFrame(debugFrame, "|cFFFFFF80" .. L["RMVRT1"] .. "|r |cFF33FF99" .. key .. "|r |cFFFFFF80" .. L["RMVRT2"] .. "|r")
+					end
+					t[key] = nil
+				end
+			end
+			return value, TF3:RecycleTables(t, key)
+		end
+		timerCount = timerCount + 1
+		if (TF3.db.profile.debug) then
+			TF3:FindFrame(debugFrame, ("%d " .. L["SECPSD"]):format(tonumber(TF3.db.profile.repeat_recycle_time) * timerCount))
+		end
+	end
+end
+
+function TF3:GetColoredName(userID, cName)
+	if (cName ~= "") then
+		local localizedClass, englishClass, localizedRace, englishRace, sex = GetPlayerInfoByGUID(cName)
+		if (englishClass) then
+			local classColorTable = RAID_CLASS_COLORS[englishClass]
+			if (not classColorTable) then
+				return userID;
+			end
+				return string.format("\124cff%.2x%.2x%.2x", classColorTable.r*255, classColorTable.g*255, classColorTable.b*255)..userID.."\124r"
+		end
+	end
+	return userID;
+end
+
+--[[ Party Functions ]]--
+function TF3:GetParty()
+	local currentParty = TF3.currentPartyMembers
+	local numPartyMembers = GetNumPartyMembers()
+	local numRaidMembers = GetNumRaidMembers()
+	local function partytype()
+		if(numRaidMembers ~= 0) then
+			if (TF3.db.profile.debug) then
+				TF3:FindFrame(debugFrame, "|cFFFF0000".."inRaid".."|r")
+			end
+			return 1
+		elseif(numPartyMembers ~= 0) then
+			if (TF3.db.profile.debug) then
+				TF3:FindFrame(debugFrame, "|cFFFF0000".."inParty".."|r")
+			end
+			return 2
+		end
+	end
+	if (partytype() == 1) then
+		if (#currentParty ~= numPartyMembers) then
+			TF3:WipeTable(TF3.currentPartyMembers)
+			for i=1, numRaidMembers do
+				local partymember = UnitName("raid"..i)
+				if partymember then
+					TF3.currentPartyMembers[i] = partymember
+					if (TF3.db.profile.debug) then
+						TF3:FindFrame(debugFrame, "|cFFFFFF80" .. partymember .. " " .. L["PADD"] .. "|r")
+					end
+				end
+			end
+		end
+	elseif (partytype() == 2) then
+		if (#currentParty ~= numPartyMembers) then
+			TF3:WipeTable(TF3.currentPartyMembers)
+			for i=1, numPartyMembers do
+				local partymember = UnitName("party"..i)
+				if partymember then
+					TF3.currentPartyMembers[i] = partymember
+					if (TF3.db.profile.debug) then
+						TF3:FindFrame(debugFrame, "|cFFFFFF80" .. partymember .. " " .. L["PADD"] .. "|r")
+					end
+				end
+			end
+		end
+	else
+		TF3:WipeTable(TF3.currentPartyMembers)
+	end
+end
+
+function TF3:IsParty(userID)
+	local currentParty = TF3.currentPartyMembers
+	for _,partymember in ipairs(currentParty) do
+		if find(userID,partymember) then
+			return true
+		end
+	end
+	return false
+end
+
+--[[ Friends Functions ]]--
+function TF3:GetFriends()
+	local friends = TF3.db.profile.friendslist
+	local numFriends = GetNumFriends()
+	if (#friends ~= numFriends) then
+		print("|cFF33FF99" .. L["TFFR"] .. "|r")
+		TF3:WipeTable(friends)
+		for i=1, numFriends do
+			local name = GetFriendInfo(i)
+			if name then
+				friends[i] = name
+				if (TF3.db.profile.debug) then
+					TF3:FindFrame(debugFrame, "|cFFFFFF80" .. name .. " " .. L["FADD"] .. "|r")
+				end
+			end
+		end
+		print("|cFF33FF99" .. L["TFFRC"] .. "|r")
+	end
+	self:UnregisterEvent("FRIENDLIST_UPDATE")
+end
+
+function TF3:Added(event, name)
+	local friends = TF3.db.profile.friendslist
+	if name ~= UnitName("player") then
+		friends[#friends + 1] = name
+		if (TF3.db.profile.debug) then
+			TF3:FindFrame(debugFrame, "|cFFFFFF80" .. name .. " " .. L["FADD"] .. "|r")
+		end
+	end
+	if currentFriend then
+		self:GetFriends()
+	end
+end
+
+function TF3:Removed(event, name)
+	local friends = TF3.db.profile.friendslist
+	if friends ~= nil then
+		for k,v in ipairs(friends) do
+			if find(name,v) then
+				friends[k] = nil
+				if (TF3.db.profile.debug) then
+					TF3:FindFrame(debugFrame, "|cFFFFFF80" .. name .. " " .. L["FREM"] .. "|r")
+				end
+			end
+		end
+	end
+	if currentFriend then
+		self:GetFriends()
+	end
+end
+
+function TF3:IsFriend(userID)
+	local friends = TF3.db.profile.friendslist
+	for _,name in ipairs(friends) do
+		if find(userID,name) then
+			return true
+		end
+	end
+	return false
+end
+
+--[[ Duel Spam Functions ]]--
+function TF3:DuelFilter()
+	if (TF3.db.profile.filterDuelSpam) then
+		DUEL_WINNER_KNOCKOUT, DUEL_WINNER_RETREAT = "", ""
+	else
+		DUEL_WINNER_KNOCKOUT, DUEL_WINNER_RETREAT = L["DUEL_WINNER_KNOCKOUT"], L["DUEL_WINNER_RETREAT"]
+	end
+end
+
+--[[ BlackList Func ]]--
+--[[ Base blacklist words from BadBoy(Funkydude) ]]--
+function TF3:BlackList(msg, userID, msgID, coloredName, arg)
+	local blword = TF3.db.profile.blacklist
+	local msg = lower(msg)
+	if (arg == whitelist and TF3.db.profile.wlblbp == true) then
+		return false
+	else
+		if (TF3.db.profile.blacklist_enable) then
+			for _,word in pairs(blword) do
+				if (find(msg,word)) then
+					if (TF3.db.profile.debug) then
+						if (msgID ~= lastmsgID) then
+							TF3:FindFrame(debugFrame, "|cFFFF0000[" .. L["bLists"] .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
+							TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cFFFF0000" .. word .. "|r")
+							if not (TF3.db.profile.redirect_blacklist) then
+								lastmsgID = msgID
+							end
+						end
+					end
+					if (TF3.db.profile.redirect_blacklist) then
+						if (msgID ~= lastmsgID) then
+							TF3:FindFrame(redirectFrame, "|cFFFF0000[" .. L["bLists"] .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
+							TF3:FindFrame(redirectFrame, L["MATCHED"] .. " |cFFFF0000" .. word .. "|r")
+							lastmsgID = msgID
+						end
+					end
+					return true
+				end
+			end
+		end
+		return false
+	end
+end
+
+--[[ WhiteList Func ]]--
+function TF3:WhiteList(msg, userID, msgID, coloredName)
+	local wlword = TF3.db.profile.whitelist
+	local msg = lower(msg)
+	if (TF3.db.profile.whitelist_enable) then
+		for _,word in pairs(wlword) do
+			if (find(msg,word) and TF3:FindRepeat(msg, userID, msgID, coloredName, whitelist) == false and TF3:BlackList(msg, userID, msgID, coloredName, whitelist) == false) then
+				if (TF3.db.profile.debug) then
+					if (msgID ~= lastmsgID) then
+						TF3:FindFrame(debugFrame, "|cFFFFFF80[" .. L["wLists"] .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
+						TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cFFFFFF80" .. word .. "|r")
+						lastmsgID = msgID
+					end
+				end
+				return true
+			end
+		end
+	end
+	return false
+end
+
+--[[ Special Channels Func ]]--
+function TF3:SpecialChans(chanName)
+	local schans = TF3.db.profile.filters.SPECIAL
+	local chanName = lower(chanName)
+	if (schans == nil) then
+		schans = L.FILTERS.SPECIAL
+	end
+	for _,names in pairs(schans) do
+		if (find(chanName,lower(names)) and names ~= "") then
+			return true
+		end
+	end
+	return false
+end
+
+--[[ Repeat Func ]]--
+function TF3:FindRepeat(msg, userID, msgID, coloredName, arg)
+	local gtime = floor(GetTime()*power(10,0)+0.5) / power(10,0)
+	if (arg == whitelist and TF3.db.profile.wlbp == true) then
+		return false
+	elseif (TF3.db.profile.repeat_enable == false) then
+		return false
+	else
+		if (msgID ~= TF3.repeatdata[userID].lastmsgID and msg == TF3.repeatdata[userID].lastmsg and gtime - TF3.repeatdata[userID].lastIndex < tonumber(TF3.db.profile.time_repeats)) then
+			TF3.repeatdata[userID].repeats = TF3.repeatdata[userID].repeats + 1
+			if (TF3.repeatdata[userID].repeats >= tonumber(TF3.db.profile.num_repeats)) then
+				if (msg ~= rptmsg or msg == rptmsg and msgID ~= rptmsgID) then
+					if (TF3.db.profile.debug) then
+						if rptmsg ~= nil then
+							TF3:FindFrame(repeatFrame, "|cFFFF8C00[" .. L["#RPT"] .. "]|r |cFFD9D9D9[" .. msgID .. "(" .. rptmsgID .. ")" .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080" .. msg .. "(" .. rptmsg .. ")" .. "|r")
+						else
+							TF3:FindFrame(repeatFrame, "|cFFFF8C00[" .. L["#RPT"] .. "]|r |cFFD9D9D9[" .. msgID .. "(" .. TF3.repeatdata[userID].lastmsgID .. ")" .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080" .. msg .. "(" .. TF3.repeatdata[userID].lastmsg .. ")" .. "|r")
+						end
+					end
+					TF3.db.profile.repeats_blocked = TF3.db.profile.repeats_blocked + 1
+					if (LDB) then
+						TF3Frame.Blocked.text = TF3.db.profile.repeats_blocked .. L[" Repeats Blocked"]
+						TF3Frame.Blocked.value = TF3.db.profile.repeats_blocked
+					end
+					rptmsg = msg
+					rptmsgID = msgID
+				end
+				rptdone = 1 + msgID
+				return true
+			end
+		elseif (msg ~= TF3.repeatdata[userID].lastmsg) then
+			TF3.repeatdata[userID].repeats = 1
+		end
+		TF3.repeatdata[userID].lastmsg = msg
+		TF3.repeatdata[userID].lastmsgID = msgID
+		TF3.repeatdata[userID].lastIndex  = gtime
+		return false
+	end
+end
+
+--[[ Window and Chat Functions ]]--
+function TF3:FindFrame(toFrame, msg)
+	for i=1,FCF_GetNumActiveChatFrames() do
+		local name = GetChatWindowInfo(i)
+		if (toFrame == name) then
+			local msgFrame = _G["ChatFrame" .. i]
+			msgFrame:AddMessage(msg)
+			return
+		end
+	end
+	if (toFrame ~= name) then
+		TF3:CreateFrame(toFrame, msg)
+	end
+end
+
+function TF3:CreateFrame(newFrame, msg)
+  local newFrame = FCF_OpenNewWindow(newFrame)
+	newFrame:AddMessage(msg)
+end
+
+--[[ PreFilter Functions ]]--
+--[[----------------------------------------------------------------------------------
+Taken from SpamMeNot
+			arg1:	chat message
+			arg2:	author
+			arg7:	zone ID used for generic system channels (1 for General,
+					2 for Trade, 22 for LocalDefense, 23 for WorldDefense and
+					26 for LFG)	not used for custom channels or if you joined
+					an Out-Of-Zone channel ex: "General - Stormwind City"
+			arg8:	channel number
+	the arguments a1..a9 are all nil until Blizzard actually passes them
+	we're expected to use global variables which is generally a bad idea
+	global variables may not be available in a later patch so we have to do this:
+------------------------------------------------------------------------------------]]
+
+--[[ Check for AddOn Channel and User setting ]]--
+local function PreFilterFunc_Addon(self, event, ...)
+	local filtered = false
+	local prefix = arg1 or select(1, ...)
+	local msg = arg2 or select(2, ...)
+	local distType = arg3 or select(3, ...)
+	local userID = arg4 or select(4, ...)
+	local msgID = arg11 or select(11, ...)
+	local cName = arg12 or select(12, ...)
+	local coloredName = TF3:GetColoredName(userID, cName)
+	if (TF3.repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
+		TF3.repeatdata[userID] = {}
+		TF3.repeatdata[userID].lastmsg = msg
+		TF3.repeatdata[userID].lastmsgID = msgID
+		TF3.repeatdata[userID].lastIndex = 1
+		TF3.repeatdata[userID].repeats = 1
+		rptdone = msgID
+	end
+	if (TF3.db.profile.filterGAC) then
+		if (find(prefix,"ET") and distType == "GUILD") then
+			if (TF3:IsFriend(userID) == false) then
+				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
+					filtered = false
+				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
+					filtered = true
+				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
+					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
+						filtered = true
+					else
+						filtered = TF3:FilterFunc(...)
+					end
+				else
+					filtered = TF3:FilterFunc(...)
+				end
+			else
+				filtered = false
+			end
+		end
+	end
+	return filtered
+end
+
+--[[ Check for SAY Channel and User setting ]]--
+local function PreFilterFunc_Say(self, event, ...)
+	local filtered = false
+	local msg = arg1 or select(1, ...)
+	local userID = arg2 or select(2, ...)
+	local chanName = arg9 or select(9, ...)
+	local msgID = arg11 or select(11, ...)
+	local cName = arg12 or select(12, ...)
+	local coloredName = TF3:GetColoredName(userID, cName)
+	if (TF3.repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
+		TF3.repeatdata[userID] = {}
+		TF3.repeatdata[userID].lastmsg = msg
+		TF3.repeatdata[userID].lastmsgID = msgID
+		TF3.repeatdata[userID].lastIndex = 1
+		TF3.repeatdata[userID].repeats = 1
+		rptdone = msgID
+	end
+	if (TF3.db.profile.filterSAY) then
+		if (event == "CHAT_MSG_SAY") then
+			if (TF3:IsFriend(userID) == false and TF3:IsParty(userID) == false) then
+				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
+					filtered = false
+				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
+					filtered = true
+				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
+					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
+						filtered = true
+					else
+						filtered = TF3:FilterFunc("0. " .. L["Say/Yell"], ...)
+					end
+				else
+					filtered = TF3:FilterFunc("0. " .. L["Say/Yell"], ...)
+				end
+			elseif (event == "CHAT_MSG_SAY" and not TF3.db.profile.filterSAY) then
+				filtered = false
+			end
+		end
+	end
+	return filtered
+end
+
+--[[ Check for YELL Channel and User setting ]]--
+local function PreFilterFunc_Yell(self, event, ...)
+	local filtered = false
+	local msg = arg1 or select(1, ...)
+	local userID = arg2 or select(2, ...)
+	local msgID = arg11 or select(11, ...)
+	local cName = arg12 or select(12, ...)
+	local coloredName = TF3:GetColoredName(userID, cName)
+	if (TF3.repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
+		TF3.repeatdata[userID] = {}
+		TF3.repeatdata[userID].lastmsg = msg
+		TF3.repeatdata[userID].lastmsgID = msgID
+		TF3.repeatdata[userID].lastIndex = 1
+		TF3.repeatdata[userID].repeats = 1
+		rptdone = msgID
+	end
+	if (TF3.db.profile.filterYELL) then
+		if (event == "CHAT_MSG_YELL") then
+			if (TF3:IsFriend(userID) == false and TF3:IsParty(userID) == false) then
+				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
+					filtered = false
+				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
+					filtered = true
+				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
+					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
+						filtered = true
+					else
+						filtered = TF3:FilterFunc("0. " .. L["Say/Yell"], ...)
+					end
+				else
+					filtered = TF3:FilterFunc("0. " .. L["Say/Yell"], ...)
+				end
+			elseif (event == "CHAT_MSG_YELL" and not TF3.db.profile.filterYELL) then
+				filtered = false
+			end
+		end
+	end
+	return filtered
+end
+
+--[[ Check for Battleground Channel and User setting ]]--
+local function PreFilterFunc_BG(self, event, ...)
+	local filtered = false
+	local msg = arg1 or select(1, ...)
+	local userID = arg2 or select(2, ...)
+	local msgID = arg11 or select(11, ...)
+	local cName = arg12 or select(12, ...)
+	local coloredName = TF3:GetColoredName(userID, cName)
+	if (TF3.repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
+		TF3.repeatdata[userID] = {}
+		TF3.repeatdata[userID].lastmsg = msg
+		TF3.repeatdata[userID].lastmsgID = msgID
+		TF3.repeatdata[userID].lastIndex = 1
+		TF3.repeatdata[userID].repeats = 1
+		rptdone = msgID
+	end
+	if (TF3.db.profile.filterBG) then
+		if (event == "CHAT_MSG_BATTLEGROUND" or event == "CHAT_MSG_BATTLEGROUND_LEADER") then
+			if (TF3:IsFriend(userID) == false) then
+				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
+					filtered = false
+				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
+					filtered = true
+				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
+					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
+						filtered = true
+					else
+						filtered = TF3:FilterFunc("0. BG", ...)
+					end
+				else
+					filtered = TF3:FilterFunc("0. BG", ...)
+				end
+			elseif (not TF3.db.profile.filterBG and event == "CHAT_MSG_BATTLEGROUND" or event == "CHAT_MSG_BATTLEGROUND_LEADER") then
+				filtered = false
+			end
+		end
+	end
+	return filtered
+end
+
+--[[ Check for Trade/General/LFG Channel and User setting ]]--
+local function PreFilterFunc(self, event, ...)
+	local filtered = false
+	local msg = arg1 or select(1, ...)
+	local userID = arg2 or select(2, ...)
+	local zoneID = arg7 or select(7, ...)
+	local chanID = arg8 or select(8, ...)
+	local chanName = arg9 or select(9, ...)
+	local msgID = arg11 or select(11, ...)
+	local cName = arg12 or select(12, ...)
+	local coloredName = TF3:GetColoredName(userID, cName)
+	if (TF3.repeatdata[userID] ~= type(table) and TF3.db.profile.repeat_enable) then
+		TF3.repeatdata[userID] = {}
+		TF3.repeatdata[userID].lastmsg = msg
+		TF3.repeatdata[userID].lastmsgID = msgID
+		TF3.repeatdata[userID].lastIndex = 1
+		TF3.repeatdata[userID].repeats = 1
+		rptdone = msgID
+	end
+	--[[ Check for Trade Channel and User setting ]]--
+	if (zoneID == 2) then
+		if (TF3.db.profile.filtertrade) then
+			if (TF3:IsFriend(userID) == false) then
+				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
+					filtered = false
+				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
+					filtered = true
+				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
+					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
+						filtered = true
+					else
+						filtered = TF3:FilterFunc("2. " .. L["Trade"], ...)
+					end
+				else
+					filtered = TF3:FilterFunc("2. " .. L["Trade"], ...)
+				end
+			elseif (zoneID == 2 and not TF3.db.profile.filterTrade) then
+				filtered = false
+			end
+		end
+--~ 	end
+	--[[ Check for General Channel and User setting ]]--
+	elseif (chanID == 1) then
+		if (TF3.db.profile.filtergeneral) then
+			if (TF3:IsFriend(userID) == false) then
+				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
+					filtered = false
+				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
+					filtered = true
+				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
+					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
+						filtered = true
+					else
+						filtered = TF3:FilterFunc("1. " .. L["General"], ...)
+					end
+				else
+					filtered = TF3:FilterFunc("1. " .. L["General"], ...)
+				end
+			elseif (chanID == 1 and not TF3.db.profile.filterGeneral) then
+				filtered = false
+			end
+		end
+--~ 	end
+	--[[ Check for LFG Channel and User setting ]]--
+	elseif (zoneID == 26) then
+		if (TF3.db.profile.filterLFG) then
+			if (TF3:IsFriend(userID) == false) then
+				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
+					filtered = false
+				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
+					filtered = true
+				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
+					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
+						filtered = true
+					else
+						filtered = TF3:FilterFunc("26. " .. L["LFG"], ...)
+					end
+				else
+					filtered = TF3:FilterFunc("26. " .. L["LFG"], ...)
+				end
+			elseif (chanID == 26 and not TF3.db.profile.filterLFG) then
+				filtered = false
+			end
+		end
+--~ 	end
+	--[[ Check for Special Channel and User setting ]]--
+	elseif (TF3:SpecialChans(chanName) == true) then
+		if (TF3.db.profile.special_enable) then
+			if (TF3:IsFriend(userID) == false) then
+				if (userID == UnitName("Player") and TF3.db.profile.filterSELF == false or TF3:WhiteList(msg, userID, msgID, coloredName) == true) then
+					filtered = false
+				elseif (TF3:BlackList(msg, userID, msgID, coloredName) == true) then
+					filtered = true
+				elseif (TF3.db.profile.repeat_enable and rptdone ~= msgID) then
+					if (TF3:FindRepeat(msg, userID, msgID, coloredName) == true) then
+						filtered = true
+					else
+						filtered = TF3:FilterFunc("X. " .. chanName, ...)
+					end
+				else
+					filtered = TF3:FilterFunc("X. " .. chanName, ...)
+				end
+			elseif (TF3:SpecialChans(chanName) == true and not TF3.db.profile.special_enable) then
+				filtered = false
+			end
+		end
+	end
+	return filtered
+end
+
+--[[ Filter Func ]]--
+function TF3:FilterFunc(chan, ...)
+	local filterFuncList = ChatFrame_GetMessageEventFilters("CHAT_MSG_CHANNEL")
+	local msg = arg1 or select(1, ...)
+	local userID = arg2 or select(2, ...)
+	local zoneID = arg7 or select(7, ...)
+	local chanID = arg8 or select(8, ...)
+	local chanName = arg9 or select(9, ...)
+	local msgID = arg11 or select(11, ...)
+	local cName = arg12 or select(12, ...)
+	local coloredName = TF3:GetColoredName(userID, cName)
+	local msg = lower(msg)
+	if (filterFuncList and TF3.db.profile.turnOn) then
+		filtered = true
+		if (TF3.db.profile.debug) then
+			if (lastmsg ~= msg or lastuserID ~= userID) then
+				TF3:FindFrame(debugFrame, "|cFFC08080[" .. chan .. "]|r |cFFD9D9D9[" .. msgID .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
+			end
+		end
+		if (zoneID == 2) then
+			if (TF3.db.profile.filters.TRADE == nil) then
+				TF3.db.profile.filters.TRADE = L.FILTERS.TRADE
+			end
+			for k,v in pairs(TF3.db.profile.filters.TRADE) do
+				if (TF3.db.profile.debug and not TF3.db.profile.debug_checking) then
+					if (lastmsg ~= msg or lastuserID ~= userID) then
+						TF3:FindFrame(debugFrame, L["CFM"] .. " " .. v)
+					end
+				end
+				if (find(msg,v)) then
+					if (TF3.db.profile.debug) then
+						if (lastmsg ~= msg or lastuserID ~= userID) then
+							TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cffff8080" .. v .. "|r")
+							lastmsg, lastuserID = msg, userID
+						end
+					end
+					filtered = false
+				end
+			end
+		elseif (chan == "0. BG") then
+			if (TF3.db.profile.filters.BG == nil) then
+				TF3.db.profile.filters.BG = L.FILTERS.BG
+			end
+			for k,v in pairs(TF3.db.profile.filters.BG) do
+				if (TF3.db.profile.debug and not TF3.db.profile.debug_checking) then
+					if (lastmsg ~= msg or lastuserID ~= userID) then
+						TF3:FindFrame(debugFrame, L["CFM"] .. " " .. v)
+					end
+				end
+				if (find(msg,v)) then
+					if (TF3.db.profile.debug) then
+						if (lastmsg ~= msg or lastuserID ~= userID) then
+							TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cffff8080" .. v .. "|r")
+							lastmsg, lastuserID = msg, userID
+						end
+					end
+					filtered = false
+				end
+			end
+		else
+			if (TF3.db.profile.filters.BASE == nil) then
+				TF3.db.profile.filters.BASE = L.FILTERS.BASE
+			end
+			for k,v in pairs(TF3.db.profile.filters.BASE) do
+				if (TF3.db.profile.debug and not TF3.db.profile.debug_checking) then
+					if (lastmsg ~= msg or lastuserID ~= userID) then
+						TF3:FindFrame(debugFrame, L["CFM"] .. " " .. v)
+					end
+				end
+				if (find(msg,v)) then
+					if (TF3.db.profile.debug) then
+						if (lastmsg ~= msg or lastuserID ~= userID) then
+							TF3:FindFrame(debugFrame, L["MATCHED"] .. " |cffff8080" .. v .. "|r")
+							lastmsg, lastuserID = msg, userID
+						end
+					end
+					filtered = false
+					end
+				end
+			end
+		if (filtered == true) then
+			if (lastmsg ~= msg or lastuserID ~= userID) then
+				if (TF3.db.profile.debug) then
+					TF3:FindFrame(debugFrame, L["NOMATCH"])
+				end
+				if (TF3.db.profile.redirect) then
+					TF3:FindFrame(redirectFrame, "|cFFC08080[" .. chan .. "]|r |cFFD9D9D9[" .. msgID .. "]|r |Hplayer:" .. userID .. ":" .. msgID .. "|h[" .. coloredName .. "]|h |cFFC08080: " .. msg .. "|r")
+				end
+				lastmsg, lastuserID = msg, userID
+			end
+		end
+	end
+	return filtered
+end
+
+--[[ Pass ALL chat messages to PreFilter function ]]--
+ChatFrame_AddMessageEventFilter("CHAT_MSG_SAY", PreFilterFunc_Say)
+ChatFrame_AddMessageEventFilter("CHAT_MSG_YELL", PreFilterFunc_Yell)
+ChatFrame_AddMessageEventFilter("CHAT_MSG_ADDON", PreFilterFunc_Addon)
+ChatFrame_AddMessageEventFilter("CHAT_MSG_BATTLEGROUND", PreFilterFunc_BG)
+ChatFrame_AddMessageEventFilter("CHAT_MSG_BATTLEGROUND_LEADER", PreFilterFunc_BG)
+ChatFrame_AddMessageEventFilter("CHAT_MSG_CHANNEL", PreFilterFunc)
diff --git a/TradeFilter3.toc b/TradeFilter3.toc
index 6790515..da0fe14 100644
--- a/TradeFilter3.toc
+++ b/TradeFilter3.toc
@@ -1,61 +1,60 @@
-## Interface: 30300
-## X-Compatible-With: 40000
-#@alpha@
-## Title: @localization(locale="enUS", key="Title", namespace="ToC")@ SVN: @project-revision@
-#@end-alpha@
-## Title: @localization(locale="enUS", key="Title", namespace="ToC")@
-## Title-deDE: @localization(locale="deDE", key="Title", namespace="TOC")@
-## Title-zhCN: @localization(locale="zhCN", key="Title", namespace="TOC")@
-## Title-zhTW: @localization(locale="zhTW", key="Title", namespace="TOC")@
-## Title-frFR: @localization(locale="frFR", key="Title", namespace="TOC")@
-#@alpha@
-## Notes: @localization(locale="enUS", key="Notes", namespace="TOC")@ SVN: @project-revision@
-#@end-alpha@
-## Notes: @localization(locale="enUS", key="Notes", namespace="TOC")@
-## Notes-deDE: @localization(locale="deDE", key="Notes", namespace="TOC")@
-## Notes-zhCN: @localization(locale="zhCN", key="Notes", namespace="TOC")@
-## Notes-zhTW: @localization(locale="zhTW", key="Notes", namespace="TOC")@
-## Notes-frFR: @localization(locale="frFR", key="Notes", namespace="TOC")@
-## Author: @project-author@
-## X-Date: @project-date-iso@
-## X-Credits: Inspiration: crashmstr  Translations: Contiki
-## X-eMail: evonder AT gmail DOT com
-## X-Website: http://www.wowace.com/projects/trade-filter/
-## X-Category: Chat & Communication
-## X-Localizations: enUS, frFR, zhCN, zhTW, deDE, koKR, ruRU
-## OptionalDeps: Ace3, LibAboutPanel, LibDataBroker-1.1, LibFriends-1.0
-#@no-lib-strip@
-## X-Embeds: Ace3, LibAboutPanel, LibDataBroker-1.1, LibFriends-1.0
-#@end-no-lib-strip@
-## X-License: BSD
-## Version: @project-version@
-## Revision: @project-revision@
-## X-WoWI-ID: 13784
-## SavedVariables: TradeFilter3DB
-
-## LoadManagers: AddonLoader
-## X-LoadOn-Always: delayed
-
-#@no-lib-strip@
-libs\LibStub\LibStub.lua
-libs\CallbackHandler-1.0\CallbackHandler-1.0.xml
-libs\AceAddon-3.0\AceAddon-3.0.xml
-libs\AceConsole-3.0\AceConsole-3.0.xml
-libs\AceDB-3.0\AceDB-3.0.xml
-libs\AceDBOptions-3.0\AceDBOptions-3.0.xml
-libs\AceEvent-3.0\AceEvent-3.0.xml
-libs\AceTimer-3.0\AceTimer-3.0.xml
-libs\AceGUI-3.0\AceGUI-3.0.xml
-libs\AceLocale-3.0\AceLocale-3.0.xml
-libs\AceConfig-3.0\AceConfig-3.0.xml
-libs\LibFriends-1.0\lib.xml
-libs\LibAboutPanel\LibAboutPanel.lua
-#@end-no-lib-strip@
-libs\LibDataBroker-1.1\LibDataBroker-1.1.lua
-
-## Locale ##
-TradeFilter3Locale.lua
-
-## Core ##
-TradeFilter3.lua
-TradeFilter3Options.lua
+## Interface: 40000
+## X-Compatible-With: 30300
+#@alpha@
+## Title: @localization(locale="enUS", key="Title", namespace="ToC")@ SVN: @project-version@
+#@end-alpha@
+## Title: @localization(locale="enUS", key="Title", namespace="ToC")@
+## Title-deDE: @localization(locale="deDE", key="Title", namespace="TOC")@
+## Title-zhCN: @localization(locale="zhCN", key="Title", namespace="TOC")@
+## Title-zhTW: @localization(locale="zhTW", key="Title", namespace="TOC")@
+## Title-frFR: @localization(locale="frFR", key="Title", namespace="TOC")@
+#@alpha@
+## Notes: @localization(locale="enUS", key="Notes", namespace="TOC")@ SVN: @project-version@
+#@end-alpha@
+## Notes: @localization(locale="enUS", key="Notes", namespace="TOC")@
+## Notes-deDE: @localization(locale="deDE", key="Notes", namespace="TOC")@
+## Notes-zhCN: @localization(locale="zhCN", key="Notes", namespace="TOC")@
+## Notes-zhTW: @localization(locale="zhTW", key="Notes", namespace="TOC")@
+## Notes-frFR: @localization(locale="frFR", key="Notes", namespace="TOC")@
+## Author: @project-author@
+## X-Date: @project-date-iso@
+## X-Credits: Inspiration: crashmstr  Translations: Contiki
+## X-eMail: evonder AT gmail DOT com
+## X-Website: http://www.wowace.com/projects/trade-filter/
+## X-Category: Chat & Communication
+## X-Localizations: enUS, frFR, zhCN, zhTW, deDE, koKR, ruRU
+## OptionalDeps: Ace3, LibAboutPanel, LibDataBroker-1.1, LibFriends-1.0
+#@no-lib-strip@
+## X-Embeds: Ace3, LibAboutPanel, LibDataBroker-1.1, LibFriends-1.0
+#@end-no-lib-strip@
+## X-License: BSD
+## Version: @project-version@
+## X-WoWI-ID: 13784
+## SavedVariables: TradeFilter3DB
+
+## LoadManagers: AddonLoader
+## X-LoadOn-Always: delayed
+
+#@no-lib-strip@
+libs\LibStub\LibStub.lua
+libs\CallbackHandler-1.0\CallbackHandler-1.0.xml
+libs\AceAddon-3.0\AceAddon-3.0.xml
+libs\AceConsole-3.0\AceConsole-3.0.xml
+libs\AceDB-3.0\AceDB-3.0.xml
+libs\AceDBOptions-3.0\AceDBOptions-3.0.xml
+libs\AceEvent-3.0\AceEvent-3.0.xml
+libs\AceTimer-3.0\AceTimer-3.0.xml
+libs\AceGUI-3.0\AceGUI-3.0.xml
+libs\AceLocale-3.0\AceLocale-3.0.xml
+libs\AceConfig-3.0\AceConfig-3.0.xml
+libs\LibFriends-1.0\lib.xml
+libs\LibAboutPanel\LibAboutPanel.lua
+#@end-no-lib-strip@
+libs\LibDataBroker-1.1\LibDataBroker-1.1.lua
+
+## Locale ##
+TradeFilter3Locale.lua
+
+## Core ##
+TradeFilter3.lua
+TradeFilter3Options.lua
diff --git a/TradeFilter3Locale.lua b/TradeFilter3Locale.lua
index 8bfdba6..5d311b2 100644
--- a/TradeFilter3Locale.lua
+++ b/TradeFilter3Locale.lua
@@ -1,51 +1,51 @@
---[[
-File Author: @file-author@
-File Revision: @file-revision@
-File Date: @file-date-iso@
-]]--
-local debug = false
---@debug@
-debug = true
---@end-debug@
-
-local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "enUS", true)
-if L then
---@localization(locale="enUS", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
-if GetLocale() == "enUS" then return end
-end
-
-local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "deDE")
-if L then
---@localization(locale="deDE", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
-if GetLocale() == "deDE" then return end
-end
-
-local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "zhCN")
-if L then
---@localization(locale="zhCN", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
-if GetLocale() == "zhCN" then return end
-end
-
-local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "zhTW")
-if L then
---@localization(locale="zhTW", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
-if GetLocale() == "zhTW" then return end
-end
-
-local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "koKR")
-if L then
---@localization(locale="koKR", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
-if GetLocale() == "koKR" then return end
-end
-
-local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "frFR")
-if L then
---@localization(locale="frFR", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
-if GetLocale() == "frFR" then return end
-end
-
-local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "ruRU")
-if L then
---@localization(locale="ruRU", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
-if GetLocale() == "ruRU" then return end
-end
+--[[
+File Author: @file-author@
+File Revision: @file-abbreviated-hash@
+File Date: @file-date-iso@
+]]--
+local debug = false
+--@debug@
+debug = true
+--@end-debug@
+
+local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "enUS", true)
+if L then
+--@localization(locale="enUS", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
+if GetLocale() == "enUS" then return end
+end
+
+local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "deDE")
+if L then
+--@localization(locale="deDE", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
+if GetLocale() == "deDE" then return end
+end
+
+local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "zhCN")
+if L then
+--@localization(locale="zhCN", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
+if GetLocale() == "zhCN" then return end
+end
+
+local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "zhTW")
+if L then
+--@localization(locale="zhTW", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
+if GetLocale() == "zhTW" then return end
+end
+
+local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "koKR")
+if L then
+--@localization(locale="koKR", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
+if GetLocale() == "koKR" then return end
+end
+
+local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "frFR")
+if L then
+--@localization(locale="frFR", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
+if GetLocale() == "frFR" then return end
+end
+
+local L =  LibStub("AceLocale-3.0"):NewLocale("TradeFilter3", "ruRU")
+if L then
+--@localization(locale="ruRU", format="lua_additive_table", same-key-is-true=true, handle-subnamespaces="subtable")@
+if GetLocale() == "ruRU" then return end
+end
diff --git a/TradeFilter3Options.lua b/TradeFilter3Options.lua
index e92f6bc..3f147df 100644
--- a/TradeFilter3Options.lua
+++ b/TradeFilter3Options.lua
@@ -1,935 +1,1002 @@
---[[
-File Author: @file-author@
-File Revision: @file-revision@
-File Date: @file-date-iso@
-]]--
-
-local TradeFilter3 = LibStub("AceAddon-3.0"):GetAddon("TradeFilter3")
-local L = LibStub("AceLocale-3.0"):GetLocale("TradeFilter3")
-local TF3 = TradeFilter3
-
---[[ Locals ]]--
-local ipairs = ipairs
-local pairs = pairs
-local format = string.format
-local insert = table.insert
-local sort = table.sort
-
---[[ Options Table ]]--
-options = {
-	type="group",
-	name = TF3.name,
-	handler = TF3,
-	childGroups = "tab",
-	args = {
-		generalGroup = {
-			type = "group",
-			name = TF3.name,
-			args = {
-				mainHeader = {
-					type = "description",
-					name = "  " .. L["NJAOF"] .. "\n  Version " .. TF3.version .. "\n  " .. string.sub(TF3.date,6,7) .. "-" .. string.sub(TF3.date,9,10) .. "-" .. string.sub(TF3.date,1,4),
-					order = 1,
-					image = "Interface\\Icons\\Ability_Warrior_RallyingCry",
-					imageWidth = 32, imageHeight = 32,
-				},
-				turnOn = {
-					type = 'toggle',
-					order = 2,
-					width = "double",
-					name = L["TurnOn"],
-					desc = L["TurnOnDesc"],
-					get = function() return TF3.db.profile.turnOn end,
-					set = function()
-						if (TF3.db.profile.turnOn == false) then
-							print(L.TOC.Title .. " " .. TF3.version .. " " .. L["ENABLED"])
-							TF3.db.profile.turnOn = not TF3.db.profile.turnOn
-						else
-							print(L.TOC.Title .. " " .. TF3.version .. " " .. L["DISABLED"])
-							TF3.db.profile.turnOn = not TF3.db.profile.turnOn
-						end
-					end,
-				},
-				channelGroup = {
-					type = "group",
-					handler = TF3,
-					order = 1,
-					disabled = function()
-						return not TF3.db.profile.turnOn
-					end,
-					name = L["channelGroup"],
-					desc = L["channelGroup"],
-					args = {
-						optionsHeader1 = {
-							type	= "header",
-							order	= 1,
-							name	= L["channelGroup"],
-						},
-						tradeChannel = {
-							type = 'toggle',
-							order = 2,
-							width = "double",
-							disabled = false,
-							name = L["TC"],
-							desc = L["TCD"],
-							get = function() return TF3.db.profile.filtertrade end,
-							set = function() TF3.db.profile.filtertrade = not TF3.db.profile.filtertrade end,
-						},
-						generalChannel = {
-							type = 'toggle',
-							order = 3,
-							width = "double",
-							disabled = false,
-							name = L["GC"],
-							desc = L["GCD"],
-							get = function() return TF3.db.profile.filtergeneral end,
-							set = function() TF3.db.profile.filtergeneral = not TF3.db.profile.filtergeneral end,
-						},
-						LFGChannel = {
-							type = 'toggle',
-							order = 4,
-							width = "double",
-							disabled = false,
-							name = L["LFGC"],
-							desc = L["LFGCD"],
-							get = function() return TF3.db.profile.filterLFG end,
-							set = function() TF3.db.profile.filterLFG = not TF3.db.profile.filterLFG end,
-						},
-						Battlegrounds = {
-							type = 'toggle',
-							order = 4,
-							width = "double",
-							disabled = false,
-							name = L["BGC"],
-							desc = L["BGCD"],
-							get = function() return TF3.db.profile.filterBG end,
-							set = function() TF3.db.profile.filterBG = not TF3.db.profile.filterBG end,
-						},
-						SAYChannel = {
-							type = 'toggle',
-							order = 5,
-							width = "double",
-							disabled = false,
-							name = L["SAYC"],
-							desc = L["SAYCD"],
-							get = function() return TF3.db.profile.filterSAY end,
-							set = function() TF3.db.profile.filterSAY = not TF3.db.profile.filterSAY end,
-						},
-						YELLChannel = {
-							type = 'toggle',
-							order = 6,
-							width = "double",
-							disabled = false,
-							name = L["YELLC"],
-							desc = L["YELLCD"],
-							get = function() return TF3.db.profile.filterYELL end,
-							set = function() TF3.db.profile.filterYELL = not TF3.db.profile.filterYELL end,
-						},
-						optionsHeader1a = {
-							type	= "header",
-							order	= 7,
-							name	= L["FDS"],
-						},
-						filterDuelSpam = {
-							type = 'toggle',
-							order = 8,
-							width = "double",
-							disabled = false,
-							name = L["FDS"],
-							desc = L["FDSD"],
-							get = function() return TF3.db.profile.filterDuelSpam end,
-							set = function() TF3.db.profile.filterDuelSpam = not TF3.db.profile.filterDuelSpam; TF3:DuelFilter()end,
-						},
-						optionsHeader1b = {
-							type	= "header",
-							order	= 9,
-							name	= L["SPCS"],
-						},
-						GuildAddOnsChannel = {
-							type = 'toggle',
-							order = 10,
-							width = "double",
-							disabled = false,
-							name = L["GAC"],
-							desc = L["GACD"],
-							get = function() return TF3.db.profile.filterGAC end,
-							set = function() TF3.db.profile.filterGAC = not TF3.db.profile.filterGAC end,
-						},
-						special_enable = {
-							type = 'toggle',
-							order = 11,
-							width = "double",
-							disabled = false,
-							name = L["SPCST"],
-							desc = L["SPCSTD"],
-							get = function() return TF3.db.profile.special_enable end,
-							set = function() TF3.db.profile.special_enable = not TF3.db.profile.special_enable end,
-						},
-						specialfilters = {
-							type = 'input',
-							disabled = function()
-								return not TF3.db.profile.special_enable
-							end,
-							multiline = 4,
-							order = 12,
-							width = "full",
-							name = L["SPCST"],
-							desc = L["SPCSTD"],
-							usage = L["INPUSAGE"],
-							get = function(info)
-								local a = {}
-								local ret = ""
-								if (TF3.db.profile.filters.SPECIAL == nil) then
-									TF3.db.profile.filters.SPECIAL = L.FILTERS.SPECIAL
-								end
-								for _,v in pairs(TF3.db.profile.filters.SPECIAL) do
-									insert(a, v)
-								end
-								sort(a)
-								for _,v in ipairs(a) do
-									if ret == "" then
-										ret = v
-									else
-										ret = ret .. "\n" .. v
-									end
-								end
-								return ret
-							end,
-							set = function(info, value)
-								TF3:WipeTable(TF3.db.profile.filters.SPECIAL)
-								local tbl = { strsplit("\n", value) }
-								for k, v in pairs(tbl) do
-									key = "FILTER"
-									TF3.db.profile.filters.SPECIAL[key..k] = v
-								end
-							end,
-						},
-						reset_specialfilters = {
-							type = 'execute',
-							disabled = function()
-								return not TF3.db.profile.special_enable
-							end,
-							order = 13,
-							name = L["RSF"],
-							desc = L["RSF"],
-							func = function() TF3.db.profile.filters.SPECIAL = TF3:CopyTable(L.FILTERS.SPECIAL) end,
-						},
-					},
-				},
-				editFilterGroup = {
-					type = "group",
-					childGroups = "tab",
-					handler = TF3,
-					order = 2,
-					disabled = function()
-						return not TF3.db.profile.turnOn
-					end,
-					name = L["EditFilterGroup"],
-					desc = L["EditFilterGD"],
-					args = {
-						editFilterGroupTRADE = {
-							type = "group",
-							handler = TF3,
-							order = 1,
-							disabled = function()
-								return not TF3.db.profile.turnOn
-							end,
-							name = "TRADE Filters",
-							desc = "TRADE Filters",
-							args = {
-								optionsHeader1 = {
-									type	= "header",
-									order	= 1,
-									name	= L["EditFilter"],
-								},
-								editfilter_enable = {
-									type = 'toggle',
-									order = 2,
-									width = "double",
-									name = L["EditFilter"],
-									desc = L["EditFilterD"],
-									get = function() return TF3.db.profile.addfilterTRADE_enable end,
-									set = function() TF3.db.profile.addfilterTRADE_enable = not TF3.db.profile.addfilterTRADE_enable end,
-								},
-								optionsHeader2 = {
-									type	= "header",
-									order	= 3,
-									name	= L["BTF"],
-								},
-								tradefilters = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.addfilterTRADE_enable
-									end,
-									multiline = 10,
-									order = 4,
-									width = "full",
-									name = L["BTF"],
-									desc = L["BTFD"],
-									usage = L["INPUSAGE"],
-									get = function(info)
-										local a = {}
-										local ret = ""
-										if (TF3.db.profile.filters.TRADE == nil) then
-											TF3.db.profile.filters.TRADE = L.FILTERS.TRADE
-										end
-										for _,v in pairs(TF3.db.profile.filters.TRADE) do
-											insert(a, v)
-										end
-										sort(a)
-										for _,v in ipairs(a) do
-											if ret == "" then
-												ret = v
-											else
-												ret = ret .. "\n" .. v
-											end
-										end
-										return ret
-									end,
-									set = function(info, value)
-										TF3:WipeTable(TF3.db.profile.filters.TRADE)
-										local tbl = { strsplit("\n", value) }
-										for k, v in pairs(tbl) do
-											key = "FILTER"
-											TF3.db.profile.filters.TRADE[key..k] = v
-										end
-									end,
-								},
-								reset_tradefilters = {
-									type = 'execute',
-									disabled = function()
-										return not TF3.db.profile.addfilterTRADE_enable
-									end,
-									order = 5,
-									name = L["RTF"],
-									desc = L["RTF"],
-									func = function() TF3.db.profile.filters.TRADE = TF3:CopyTable(L.FILTERS.TRADE) end,
-								},
-							},
-						},
-						editFilterGroupBASE = {
-							type = "group",
-							handler = TF3,
-							order = 2,
-							disabled = function()
-								return not TF3.db.profile.turnOn
-							end,
-							name = "BASE Filters",
-							desc = "BASE Filters",
-							args = {
-								optionsHeader1 = {
-									type	= "header",
-									order	= 1,
-									name	= L["EditFilter"],
-								},
-								editfilter_enable = {
-									type = 'toggle',
-									order = 2,
-									width = "double",
-									name = L["EditFilter"],
-									desc = L["EditFilterD"],
-									get = function() return TF3.db.profile.addfilterBASE_enable end,
-									set = function() TF3.db.profile.addfilterBASE_enable = not TF3.db.profile.addfilterBASE_enable end,
-								},
-								optionsHeader2 = {
-									type	= "header",
-									order	= 6,
-									name	= L["BCF"],
-								},
-								basefilters = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.addfilterBASE_enable
-									end,
-									multiline = 10,
-									order = 7,
-									width = "full",
-									name = L["BCF"],
-									desc = L["BCFD"],
-									usage = L["INPUSAGE"],
-									get = function(info)
-										local a = {}
-										local ret = ""
-										if (TF3.db.profile.filters.BASE == nil) then
-											TF3.db.profile.filters.BASE = L.FILTERS.BASE
-										end
-										for _,v in pairs(TF3.db.profile.filters.BASE) do
-											insert(a, v)
-										end
-										sort(a)
-										for _,v in ipairs(a) do
-											if ret == "" then
-												ret = v
-											else
-												ret = ret .. "\n" .. v
-											end
-										end
-										return ret
-									end,
-									set = function(info, value)
-										TF3:WipeTable(TF3.db.profile.filters.BASE)
-										local tbl = { strsplit("\n", value) }
-										for k, v in pairs(tbl) do
-											key = "FILTER"
-											TF3.db.profile.filters.BASE[key..k] = v
-										end
-									end,
-								},
-								reset_basefilters = {
-									type = 'execute',
-									disabled = function()
-										return not TF3.db.profile.addfilterBASE_enable
-									end,
-									order = 8,
-									name = L["RBF"],
-									desc = L["RBF"],
-									func = function() TF3.db.profile.filters.BASE = TF3:CopyTable(L.FILTERS.BASE) end,
-								},
-							},
-						},
-						editFilterGroupBG = {
-							type = "group",
-							handler = TF3,
-							order = 3,
-							disabled = function()
-								return not TF3.db.profile.turnOn
-							end,
-							name = "BG Filters",
-							desc = "BG Filters",
-							args = {
-								optionsHeader1 = {
-									type	= "header",
-									order	= 1,
-									name	= L["EditFilter"],
-								},
-								editfilter_enable = {
-									type = 'toggle',
-									order = 2,
-									width = "double",
-									name = L["EditFilter"],
-									desc = L["EditFilterD"],
-									get = function() return TF3.db.profile.addfilterBG_enable end,
-									set = function() TF3.db.profile.addfilterBG_enable = not TF3.db.profile.addfilterBG_enable end,
-								},
-								optionsHeader2 = {
-									type	= "header",
-									order	= 6,
-									name	= L["BG"],
-								},
-								bgfilters = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.addfilterBG_enable
-									end,
-									multiline = 10,
-									order = 7,
-									width = "full",
-									name = L["BG"],
-									desc = L["BGD"],
-									usage = L["INPUSAGE"],
-									get = function(info)
-										local a = {}
-										local ret = ""
-										if (TF3.db.profile.filters.BG == nil) then
-											TF3.db.profile.filters.BG = L.FILTERS.BG
-										end
-										for _,v in pairs(TF3.db.profile.filters.BG) do
-											insert(a, v)
-										end
-										sort(a)
-										for _,v in ipairs(a) do
-											if ret == "" then
-												ret = v
-											else
-												ret = ret .. "\n" .. v
-											end
-										end
-										return ret
-									end,
-									set = function(info, value)
-										TF3:WipeTable(TF3.db.profile.filters.BG)
-										local tbl = { strsplit("\n", value) }
-										for k, v in pairs(tbl) do
-											key = "FILTER"
-											TF3.db.profile.filters.BG[key..k] = v
-										end
-									end,
-								},
-								reset_bgfilters = {
-									type = 'execute',
-									disabled = function()
-										return not TF3.db.profile.addfilterBG_enable
-									end,
-									order = 8,
-									name = L["RBF"],
-									desc = L["RBF"],
-									func = function() TF3.db.profile.filters.BG = TF3:CopyTable(L.FILTERS.BG) end,
-								},
-							},
-						},
-					},
-				},
-				listsGroup = {
-					type = "group",
-					childGroups = "tab",
-					handler = TF3,
-					order = 3,
-					disabled = function()
-						return not TF3.db.profile.turnOn
-					end,
-					name = L["listsGroup"],
-					desc = L["listsGD"],
-					args = {
-						listsGroupBlack = {
-							type = "group",
-							handler = TF3,
-							order = 1,
-							disabled = function()
-								return not TF3.db.profile.turnOn
-							end,
-							name = L["bLists"],
-							desc = L["listsGD"],
-							args = {
-								optionsHeader1 = {
-									type	= "header",
-									order	= 1,
-									name	= L["bLists"],
-								},
-								blacklist_enable = {
-									type = 'toggle',
-									order = 2,
-									width = "double",
-									name = L["BLE"],
-									desc = L["BLE"],
-									get = function() return TF3.db.profile.blacklist_enable end,
-									set = function() TF3.db.profile.blacklist_enable = not TF3.db.profile.blacklist_enable end,
-								},
-								editblacklist = {
-									type = 'toggle',
-									order = 3,
-									disabled = function()
-										return not TF3.db.profile.blacklist_enable
-									end,
-									width = "double",
-									name = L["EBL"],
-									desc = L["EBL"],
-									get = function() return TF3.db.profile.ebl end,
-									set = function() TF3.db.profile.ebl = not TF3.db.profile.ebl end,
-								},
-								blist = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.ebl
-									end,
-									multiline = 10,
-									order = 4,
-									width = "full",
-									name = L["bLists"],
-									usage = L["INPUSAGE"],
-									get = function(info)
-										local a = {}
-										local ret = ""
-										if (TF3.db.profile.blacklist == nil) then
-											TF3.db.profile.blacklist = L.BLACKLIST
-										end
-										for _,v in pairs(TF3.db.profile.blacklist) do
-											insert(a, v)
-										end
-										sort(a)
-										for _,v in ipairs(a) do
-											if ret == "" then
-												ret = v
-											else
-												ret = ret .. "\n" .. v
-											end
-										end
-										return ret
-									end,
-									set = function(info, value)
-										TF3:WipeTable(TF3.db.profile.blacklist)
-										local tbl = { strsplit("\n", value) }
-										for k, v in pairs(tbl) do
-											key = "BLIST"
-											TF3.db.profile.blacklist[key..k] = v
-										end
-									end,
-								},
-								reset_blist = {
-									type = 'execute',
-									disabled = function()
-										return not TF3.db.profile.ebl
-									end,
-									order = 5,
-									name = L["RBLS"],
-									desc = L["RBLS"],
-									func = function() TF3.db.profile.blacklist = TF3:CopyTable(L.BLACKLIST) end,
-								},
-							},
-						},
-						listsGroupWhite = {
-							type = "group",
-							handler = TF3,
-							order = 2,
-							disabled = function()
-								return not TF3.db.profile.turnOn
-							end,
-							name = L["wLists"],
-							desc = L["listsGD"],
-							args = {
-								optionsHeader3b = {
-									type	= "header",
-									order	= 1,
-									name	= L["wLists"],
-								},
-								whitelist_enable = {
-									type = 'toggle',
-									order = 2,
-									width = "double",
-									name = L["WLE"],
-									desc = L["WLE"],
-									get = function() return TF3.db.profile.whitelist_enable end,
-									set = function() TF3.db.profile.whitelist_enable = not TF3.db.profile.whitelist_enable end,
-								},
-								editwhitelist = {
-									type = 'toggle',
-									order = 3,
-									disabled = function()
-										return not TF3.db.profile.whitelist_enable
-									end,
-									width = "double",
-									name = L["EWL"],
-									desc = L["EWL"],
-									get = function() return TF3.db.profile.ewl end,
-									set = function() TF3.db.profile.ewl = not TF3.db.profile.ewl end,
-								},
-								whitelist_repeat_bypass = {
-									type = 'toggle',
-									order = 4,
-									disabled = function()
-										return not TF3.db.profile.whitelist_enable
-									end,
-									width = "double",
-									name = L["RPTBYPASS"],
-									desc = L["RPTBYPASSD"],
-									get = function() return TF3.db.profile.wlbp end,
-									set = function() TF3.db.profile.wlbp = not TF3.db.profile.wlbp end,
-								},
-								whitelist_blacklist_bypass = {
-									type = 'toggle',
-									order = 5,
-									disabled = function()
-										return not TF3.db.profile.whitelist_enable
-									end,
-									width = "double",
-									name = L["BLBYPASS"],
-									desc = L["BLBYPASSD"],
-									get = function() return TF3.db.profile.wlblbp end,
-									set = function() TF3.db.profile.wlblbp = not TF3.db.profile.wlblbp end,
-								},
-								wlist = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.ewl
-									end,
-									multiline = 10,
-									order = 6,
-									width = "full",
-									name = L["wLists"],
-									usage = L["INPUSAGE"],
-									get = function(info)
-										local a = {}
-										local ret = ""
-										if (TF3.db.profile.whitelist == nil) then
-											TF3.db.profile.whitelist = L.WHITELIST
-										end
-										for _,v in pairs(TF3.db.profile.whitelist) do
-											insert(a, v)
-										end
-										sort(a)
-										for _,v in ipairs(a) do
-											if ret == "" then
-												ret = v
-											else
-												ret = ret .. "\n" .. v
-											end
-										end
-										return ret
-									end,
-									set = function(info, value)
-										TF3:WipeTable(TF3.db.profile.whitelist)
-										local tbl = { strsplit("\n", value) }
-										for k, v in pairs(tbl) do
-											key = "WLIST"
-											TF3.db.profile.whitelist[key..k] = v
-										end
-									end,
-								},
-								reset_wlist = {
-									type = 'execute',
-									disabled = function()
-										return not TF3.db.profile.ewl
-									end,
-									order = 7,
-									name = L["RWLS"],
-									desc = L["RWLS"],
-									func = function() TF3.db.profile.whitelist = TF3:CopyTable(L.WHITELIST) end,
-								},
-							},
-						},
-					},
-				},
-				repeatGroupMain = {
-					type = "group",
-					handler = TF3,
-					childGroups = "tab",
-					order = 4,
-					disabled = function()
-						return not TF3.db.profile.turnOn
-					end,
-					name = L["REPEAT"],
-					desc = L["REPEAT"],
-					args = {
-						repeat_enable = {
-							type = 'toggle',
-							order = 1,
-							width = "double",
-							name = L["RPTENABLE"],
-							desc = L["RPTENABLED"],
-							get = function() return TF3.db.profile.repeat_enable end,
-							set = function() TF3.db.profile.repeat_enable = not TF3.db.profile.repeat_enable end,
-						},
-						repeatGroup = {
-							type = "group",
-							handler = TF3,
-							order = 2,
-							disabled = function()
-								return not TF3.db.profile.repeat_enable
-							end,
-							name = L["REPEAT"],
-							desc = L["REPEAT"],
-							args = {
-								num_repeats = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.repeat_enable
-									end,
-									order = 3,
-									width = "full",
-									name = L["#RPT"],
-									desc = L["#RPTD"],
-									usage = L["RPTU"],
-									get = function(info) return TF3.db.profile.num_repeats end,
-									set = function(info, value) TF3.db.profile.num_repeats = value end,
-								},
-								time_repeats = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.repeat_enable
-									end,
-									order = 4,
-									width = "full",
-									name = L["TRPT"],
-									desc = L["TRPTD"],
-									usage = L["RPTU"],
-									get = function(info) return TF3.db.profile.time_repeats end,
-									set = function(info, value) TF3.db.profile.time_repeats = value end,
-								},
-								repeats_blocked = {
-									type = 'input',
-									disabled = true,
-									order = 5,
-									width = "half",
-									name = L["RPTBLOCKED"],
-									desc = L["RPTBLOCKEDD"],
-									get = function(info) return format("%d",TF3.db.profile.repeats_blocked) end,
-								},
-								reset_repeats_blocked = {
-									type = 'execute',
-									order = 6,
-									width = "half",
-									name = L["RPTRESET"],
-									desc = L["RPTRESETD"],
-									func = function()
-										TF3.db.profile.repeats_blocked = 0
-										if (LibStub("LibDataBroker-1.1", true)) then
-											TF3Frame.Blocked.text = TF3.db.profile.repeats_blocked .. "Repeats Blocked"
-											TF3Frame.Blocked.value = TF3.db.profile.repeats_blocked
-										end
-									end,
-								},
-							},
-						},
-						repeatGroupAdv = {
-							type = "group",
-							handler = TF3,
-							order = 3,
-							disabled = function()
-								return not TF3.db.profile.repeat_enable
-							end,
-							name = L["RPTA"],
-							desc = L["RPTAD"],
-							args = {
-								repeat_recycle_time = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.repeat_enable
-									end,
-									order = 1,
-									width = "full",
-									name = L["RPTRT"],
-									desc = L["RPTRTD"],
-									usage = L["RPTRTSU"],
-									get = function(info) return TF3.db.profile.repeat_recycle_time end,
-									set = function(info, value)
-										TF3.db.profile.repeat_recycle_time = value
-										TF3:ScheduleRepeatingTimer("RecycleTables", tonumber(TF3.db.profile.repeat_recycle_time), repeatdata)
-									end,
-								},
-								repeat_recycle_size = {
-									type = 'input',
-									disabled = function()
-										return not TF3.db.profile.repeat_enable
-									end,
-									order = 2,
-									width = "full",
-									name = L["RPTRS"],
-									desc = L["RPTRSD"],
-									usage = L["RPTRTSU"],
-									get = function(info) return TF3.db.profile.repeat_recycle_size end,
-									set = function(info, value) TF3.db.profile.repeat_recycle_size = value end,
-								},
-								repeats_table_size = {
-									type = 'input',
-									disabled = true,
-									order = 3,
-									name = L["RPTTS"],
-									get = function() return format("%d",TF3:getnHash(repeatdata)) end,
-								},
-								blank_space1 = {
-									type = 'description',
-									order = 4,
-									name = "",
-								},
-								options_header5 = {
-									type	= "header",
-									order	= 5,
-									name	= L["RPTTC"],
-								},
-								reset_repeat_table_content = {
-									type = 'execute',
-									disabled = function()
-										return not TF3.db.profile.repeat_enable
-									end,
-									order = 6,
-									name = L["RPTTT"],
-									desc = L["RPTTTD"],
-									func = function() TF3:RecycleTables(repeatdata) end,
-								},
-								repeats_table_content = {
-									type = 'description',
-									fontSize = "medium",
-									disabled = true,
-									order = 7,
-									name = function()
-										local ret = ""
-										for k,v in pairs(repeatdata) do
-											if ret == "" then
-												ret = k
-											else
-												ret = ret .. "\n" .. k
-											end
-										end
-										return ret
-									end,
-								},
-								blank_space2 = {
-									type = 'description',
-									order = 8,
-									name = "",
-								},
-							},
-						},
-					},
-				},
-				outputGroup = {
-					type = "group",
-					handler = TF3,
-					order = 5,
-					disabled = function()
-						return not TF3.db.profile.turnOn
-					end,
-					name = L["OUTPUT"],
-					desc = L["OUTPUT"],
-					args = {
-						optionsHeader5 = {
-							type	= "header",
-							order	= 1,
-							name	= L["OUTPUT"],
-						},
-						redirect = {
-							type = 'toggle',
-							order = 2,
-							width = "full",
-							name = L["Redir"],
-							desc = L["RedirDesc"],
-							get = function() return TF3.db.profile.redirect end,
-							set = function() TF3.db.profile.redirect = not TF3.db.profile.redirect end,
-						},
-						redirect_blacklist = {
-							type = 'toggle',
-							order = 3,
-							width = "full",
-							name = L["RedirBL"],
-							desc = L["RedirDesc"],
-							get = function() return TF3.db.profile.redirect_blacklist end,
-							set = function() TF3.db.profile.redirect_blacklist = not TF3.db.profile.redirect_blacklist end,
-						},
-						optionsHeader6 = {
-							type	= "header",
-							order	= 4,
-							name	= L["DEBUGGING"],
-						},
-						debug = {
-							type = 'toggle',
-							order = 5,
-							width = "full",
-							disabled = false,
-							hidden = false,
-							name = L["Debug"],
-							desc = L["DebugDesc"],
-							get = function() return TF3.db.profile.debug end,
-							set = function() TF3.db.profile.debug = not TF3.db.profile.debug end,
-						},
-						debug_checking = {
-							type = 'toggle',
-							order = 6,
-							width = "full",
-							disabled = false,
-							hidden = false,
-							name = L["DebugChecking"],
-							desc = L["DebugCheckingD"],
-							get = function() return TF3.db.profile.debug_checking end,
-							set = function() TF3.db.profile.debug_checking = not TF3.db.profile.debug_checking end,
-						},
-						optionsHeader4 = {
-							type	= "header",
-							order	= 7,
-							name	= L["FSELF"],
-							desc = L["FSELFD"],
-						},
-						filterSELF = {
-							type = 'toggle',
-							order = 8,
-							width = "double",
-							disabled = false,
-							name = L["FSELF"],
-							desc = L["FSELFD"],
-							get = function() return TF3.db.profile.filterSELF end,
-							set = function() TF3.db.profile.filterSELF = not TF3.db.profile.filterSELF end,
-						},
-					},
-				},
-			},
-		},
-	},
-}
+--[[
+File Author: @file-author@
+File Revision: @file-abbreviated-hash@
+File Date: @file-date-iso@
+]]--
+
+local TradeFilter3 = LibStub("AceAddon-3.0"):GetAddon("TradeFilter3")
+local L = LibStub("AceLocale-3.0"):GetLocale("TradeFilter3")
+local TF3 = TradeFilter3
+
+--[[ Locals ]]--
+local ipairs = ipairs
+local pairs = pairs
+local format = string.format
+local insert = table.insert
+local sort = table.sort
+local sub = string.sub
+
+--[[ Options Table ]]--
+options = {
+	type="group",
+	name = TF3.name,
+	handler = TF3,
+	childGroups = "tab",
+	args = {
+		generalGroup = {
+			type = "group",
+			name = TF3.name,
+			args = {
+				mainHeader = {
+					type = "description",
+					name = "  " .. L["NJAOF"] .. "\n  " .. TF3.version .. "\n  " .. sub(TF3.date,6,7) .. "-" .. sub(TF3.date,9,10) .. "-" .. sub(TF3.date,1,4),
+					order = 1,
+					image = "Interface\\Icons\\Ability_Warrior_RallyingCry",
+					imageWidth = 32, imageHeight = 32,
+				},
+				turnOn = {
+					type = 'toggle',
+					order = 2,
+					width = "double",
+					name = L["TurnOn"],
+					desc = L["TurnOnDesc"],
+					get = function() return TF3.db.profile.turnOn end,
+					set = function()
+						if (TF3.db.profile.turnOn == false) then
+							print(L.TOC.Title .. " " .. TF3.version .. " " .. L["ENABLED"])
+							TF3.db.profile.turnOn = not TF3.db.profile.turnOn
+						else
+							print(L.TOC.Title .. " " .. TF3.version .. " " .. L["DISABLED"])
+							TF3.db.profile.turnOn = not TF3.db.profile.turnOn
+						end
+					end,
+				},
+				channelGroup = {
+					type = "group",
+					handler = TF3,
+					order = 1,
+					disabled = function()
+						return not TF3.db.profile.turnOn
+					end,
+					name = L["channelGroup"],
+					desc = L["channelGroup"],
+					args = {
+						optionsHeader1 = {
+							type	= "header",
+							order	= 1,
+							name	= L["channelGroup"],
+						},
+						tradeChannel = {
+							type = 'toggle',
+							order = 2,
+							width = "double",
+							disabled = false,
+							name = L["TC"],
+							desc = L["TCD"],
+							get = function() return TF3.db.profile.filtertrade end,
+							set = function() TF3.db.profile.filtertrade = not TF3.db.profile.filtertrade end,
+						},
+						generalChannel = {
+							type = 'toggle',
+							order = 3,
+							width = "double",
+							disabled = false,
+							name = L["GC"],
+							desc = L["GCD"],
+							get = function() return TF3.db.profile.filtergeneral end,
+							set = function() TF3.db.profile.filtergeneral = not TF3.db.profile.filtergeneral end,
+						},
+						LFGChannel = {
+							type = 'toggle',
+							order = 4,
+							width = "double",
+							disabled = false,
+							name = L["LFGC"],
+							desc = L["LFGCD"],
+							get = function() return TF3.db.profile.filterLFG end,
+							set = function() TF3.db.profile.filterLFG = not TF3.db.profile.filterLFG end,
+						},
+						Battlegrounds = {
+							type = 'toggle',
+							order = 4,
+							width = "double",
+							disabled = false,
+							name = L["BGC"],
+							desc = L["BGCD"],
+							get = function() return TF3.db.profile.filterBG end,
+							set = function() TF3.db.profile.filterBG = not TF3.db.profile.filterBG end,
+						},
+						SAYChannel = {
+							type = 'toggle',
+							order = 5,
+							width = "double",
+							disabled = false,
+							name = L["SAYC"],
+							desc = L["SAYCD"],
+							get = function() return TF3.db.profile.filterSAY end,
+							set = function() TF3.db.profile.filterSAY = not TF3.db.profile.filterSAY end,
+						},
+						YELLChannel = {
+							type = 'toggle',
+							order = 6,
+							width = "double",
+							disabled = false,
+							name = L["YELLC"],
+							desc = L["YELLCD"],
+							get = function() return TF3.db.profile.filterYELL end,
+							set = function() TF3.db.profile.filterYELL = not TF3.db.profile.filterYELL end,
+						},
+						optionsHeader1a = {
+							type	= "header",
+							order	= 7,
+							name	= L["FDS"],
+						},
+						filterDuelSpam = {
+							type = 'toggle',
+							order = 8,
+							width = "double",
+							disabled = false,
+							name = L["FDS"],
+							desc = L["FDSD"],
+							get = function() return TF3.db.profile.filterDuelSpam end,
+							set = function() TF3.db.profile.filterDuelSpam = not TF3.db.profile.filterDuelSpam; TF3:DuelFilter()end,
+						},
+						optionsHeader1b = {
+							type	= "header",
+							order	= 9,
+							name	= L["SPCS"],
+						},
+						GuildAddOnsChannel = {
+							type = 'toggle',
+							order = 10,
+							width = "double",
+							disabled = false,
+							name = L["GAC"],
+							desc = L["GACD"],
+							get = function() return TF3.db.profile.filterGAC end,
+							set = function() TF3.db.profile.filterGAC = not TF3.db.profile.filterGAC end,
+						},
+						special_enable = {
+							type = 'toggle',
+							order = 11,
+							width = "double",
+							disabled = false,
+							name = L["SPCST"],
+							desc = L["SPCSTD"],
+							get = function() return TF3.db.profile.special_enable end,
+							set = function() TF3.db.profile.special_enable = not TF3.db.profile.special_enable end,
+						},
+						specialfilters = {
+							type = 'input',
+							disabled = function()
+								return not TF3.db.profile.special_enable
+							end,
+							multiline = 4,
+							order = 12,
+							width = "full",
+							name = L["SPCST"],
+							desc = L["SPCSTD"],
+							usage = L["INPUSAGE"],
+							get = function(info)
+								local a = {}
+								local ret = ""
+								if (TF3.db.profile.filters.SPECIAL == nil) then
+									TF3.db.profile.filters.SPECIAL = L.FILTERS.SPECIAL
+								end
+								for _,v in pairs(TF3.db.profile.filters.SPECIAL) do
+									insert(a, v)
+								end
+								sort(a)
+								for _,v in ipairs(a) do
+									if ret == "" then
+										ret = v
+									else
+										ret = ret .. "\n" .. v
+									end
+								end
+								return ret
+							end,
+							set = function(info, value)
+								TF3:WipeTable(TF3.db.profile.filters.SPECIAL)
+								local tbl = { strsplit("\n", value) }
+								for k, v in pairs(tbl) do
+									key = "FILTER"
+									TF3.db.profile.filters.SPECIAL[key..k] = v
+								end
+							end,
+						},
+						reset_specialfilters = {
+							type = 'execute',
+							disabled = function()
+								return not TF3.db.profile.special_enable
+							end,
+							order = 13,
+							name = L["RSF"],
+							desc = L["RSF"],
+							func = function() TF3.db.profile.filters.SPECIAL = TF3:CopyTable(L.FILTERS.SPECIAL) end,
+						},
+					},
+				},
+				editFilterGroup = {
+					type = "group",
+					childGroups = "tab",
+					handler = TF3,
+					order = 2,
+					disabled = function()
+						return not TF3.db.profile.turnOn
+					end,
+					name = L["EditFilterGroup"],
+					desc = L["EditFilterGD"],
+					args = {
+						editFilterGroupTRADE = {
+							type = "group",
+							handler = TF3,
+							order = 1,
+							disabled = function()
+								return not TF3.db.profile.turnOn
+							end,
+							name = "TRADE Filters",
+							desc = "TRADE Filters",
+							args = {
+								optionsHeader1 = {
+									type	= "header",
+									order	= 1,
+									name	= L["EditFilter"],
+								},
+								editfilter_enable = {
+									type = 'toggle',
+									order = 2,
+									width = "double",
+									name = L["EditFilter"],
+									desc = L["EditFilterD"],
+									get = function() return TF3.db.profile.addfilterTRADE_enable end,
+									set = function() TF3.db.profile.addfilterTRADE_enable = not TF3.db.profile.addfilterTRADE_enable end,
+								},
+								optionsHeader2 = {
+									type	= "header",
+									order	= 3,
+									name	= L["BTF"],
+								},
+								tradefilters = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.addfilterTRADE_enable
+									end,
+									multiline = 10,
+									order = 4,
+									width = "full",
+									name = L["BTF"],
+									desc = L["BTFD"],
+									usage = L["INPUSAGE"],
+									get = function(info)
+										local a = {}
+										local ret = ""
+										if (TF3.db.profile.filters.TRADE == nil) then
+											TF3.db.profile.filters.TRADE = L.FILTERS.TRADE
+										end
+										for _,v in pairs(TF3.db.profile.filters.TRADE) do
+											insert(a, v)
+										end
+										sort(a)
+										for _,v in ipairs(a) do
+											if ret == "" then
+												ret = v
+											else
+												ret = ret .. "\n" .. v
+											end
+										end
+										return ret
+									end,
+									set = function(info, value)
+										TF3:WipeTable(TF3.db.profile.filters.TRADE)
+										local tbl = { strsplit("\n", value) }
+										for k, v in pairs(tbl) do
+											key = "FILTER"
+											TF3.db.profile.filters.TRADE[key..k] = v
+										end
+									end,
+								},
+								reset_tradefilters = {
+									type = 'execute',
+									disabled = function()
+										return not TF3.db.profile.addfilterTRADE_enable
+									end,
+									order = 5,
+									name = L["RTF"],
+									desc = L["RTF"],
+									func = function() TF3.db.profile.filters.TRADE = TF3:CopyTable(L.FILTERS.TRADE) end,
+								},
+							},
+						},
+						editFilterGroupBASE = {
+							type = "group",
+							handler = TF3,
+							order = 2,
+							disabled = function()
+								return not TF3.db.profile.turnOn
+							end,
+							name = "BASE Filters",
+							desc = "BASE Filters",
+							args = {
+								optionsHeader1 = {
+									type	= "header",
+									order	= 1,
+									name	= L["EditFilter"],
+								},
+								editfilter_enable = {
+									type = 'toggle',
+									order = 2,
+									width = "double",
+									name = L["EditFilter"],
+									desc = L["EditFilterD"],
+									get = function() return TF3.db.profile.addfilterBASE_enable end,
+									set = function() TF3.db.profile.addfilterBASE_enable = not TF3.db.profile.addfilterBASE_enable end,
+								},
+								optionsHeader2 = {
+									type	= "header",
+									order	= 6,
+									name	= L["BCF"],
+								},
+								basefilters = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.addfilterBASE_enable
+									end,
+									multiline = 10,
+									order = 7,
+									width = "full",
+									name = L["BCF"],
+									desc = L["BCFD"],
+									usage = L["INPUSAGE"],
+									get = function(info)
+										local a = {}
+										local ret = ""
+										if (TF3.db.profile.filters.BASE == nil) then
+											TF3.db.profile.filters.BASE = L.FILTERS.BASE
+										end
+										for _,v in pairs(TF3.db.profile.filters.BASE) do
+											insert(a, v)
+										end
+										sort(a)
+										for _,v in ipairs(a) do
+											if ret == "" then
+												ret = v
+											else
+												ret = ret .. "\n" .. v
+											end
+										end
+										return ret
+									end,
+									set = function(info, value)
+										TF3:WipeTable(TF3.db.profile.filters.BASE)
+										local tbl = { strsplit("\n", value) }
+										for k, v in pairs(tbl) do
+											key = "FILTER"
+											TF3.db.profile.filters.BASE[key..k] = v
+										end
+									end,
+								},
+								reset_basefilters = {
+									type = 'execute',
+									disabled = function()
+										return not TF3.db.profile.addfilterBASE_enable
+									end,
+									order = 8,
+									name = L["RBF"],
+									desc = L["RBF"],
+									func = function() TF3.db.profile.filters.BASE = TF3:CopyTable(L.FILTERS.BASE) end,
+								},
+							},
+						},
+						editFilterGroupBG = {
+							type = "group",
+							handler = TF3,
+							order = 3,
+							disabled = function()
+								return not TF3.db.profile.turnOn
+							end,
+							name = "BG Filters",
+							desc = "BG Filters",
+							args = {
+								optionsHeader1 = {
+									type	= "header",
+									order	= 1,
+									name	= L["EditFilter"],
+								},
+								editfilter_enable = {
+									type = 'toggle',
+									order = 2,
+									width = "double",
+									name = L["EditFilter"],
+									desc = L["EditFilterD"],
+									get = function() return TF3.db.profile.addfilterBG_enable end,
+									set = function() TF3.db.profile.addfilterBG_enable = not TF3.db.profile.addfilterBG_enable end,
+								},
+								optionsHeader2 = {
+									type	= "header",
+									order	= 6,
+									name	= L["BG"],
+								},
+								bgfilters = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.addfilterBG_enable
+									end,
+									multiline = 10,
+									order = 7,
+									width = "full",
+									name = L["BG"],
+									desc = L["BGD"],
+									usage = L["INPUSAGE"],
+									get = function(info)
+										local a = {}
+										local ret = ""
+										if (TF3.db.profile.filters.BG == nil) then
+											TF3.db.profile.filters.BG = L.FILTERS.BG
+										end
+										for _,v in pairs(TF3.db.profile.filters.BG) do
+											insert(a, v)
+										end
+										sort(a)
+										for _,v in ipairs(a) do
+											if ret == "" then
+												ret = v
+											else
+												ret = ret .. "\n" .. v
+											end
+										end
+										return ret
+									end,
+									set = function(info, value)
+										TF3:WipeTable(TF3.db.profile.filters.BG)
+										local tbl = { strsplit("\n", value) }
+										for k, v in pairs(tbl) do
+											key = "FILTER"
+											TF3.db.profile.filters.BG[key..k] = v
+										end
+									end,
+								},
+								reset_bgfilters = {
+									type = 'execute',
+									disabled = function()
+										return not TF3.db.profile.addfilterBG_enable
+									end,
+									order = 8,
+									name = L["RBF"],
+									desc = L["RBF"],
+									func = function() TF3.db.profile.filters.BG = TF3:CopyTable(L.FILTERS.BG) end,
+								},
+							},
+						},
+					},
+				},
+				listsGroup = {
+					type = "group",
+					childGroups = "tab",
+					handler = TF3,
+					order = 3,
+					disabled = function()
+						return not TF3.db.profile.turnOn
+					end,
+					name = L["listsGroup"],
+					desc = L["listsGD"],
+					args = {
+						listsGroupBlack = {
+							type = "group",
+							handler = TF3,
+							order = 1,
+							disabled = function()
+								return not TF3.db.profile.turnOn
+							end,
+							name = L["bLists"],
+							desc = L["listsGD"],
+							args = {
+								optionsHeader1 = {
+									type	= "header",
+									order	= 1,
+									name	= L["bLists"],
+								},
+								blacklist_enable = {
+									type = 'toggle',
+									order = 2,
+									width = "double",
+									name = L["BLE"],
+									desc = L["BLE"],
+									get = function() return TF3.db.profile.blacklist_enable end,
+									set = function() TF3.db.profile.blacklist_enable = not TF3.db.profile.blacklist_enable end,
+								},
+								editblacklist = {
+									type = 'toggle',
+									order = 3,
+									disabled = function()
+										return not TF3.db.profile.blacklist_enable
+									end,
+									width = "double",
+									name = L["EBL"],
+									desc = L["EBL"],
+									get = function() return TF3.db.profile.ebl end,
+									set = function() TF3.db.profile.ebl = not TF3.db.profile.ebl end,
+								},
+								blist = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.ebl
+									end,
+									multiline = 10,
+									order = 4,
+									width = "full",
+									name = L["bLists"],
+									usage = L["INPUSAGE"],
+									get = function(info)
+										local a = {}
+										local ret = ""
+										if (TF3.db.profile.blacklist == nil) then
+											TF3.db.profile.blacklist = L.BLACKLIST
+										end
+										for _,v in pairs(TF3.db.profile.blacklist) do
+											insert(a, v)
+										end
+										sort(a)
+										for _,v in ipairs(a) do
+											if ret == "" then
+												ret = v
+											else
+												ret = ret .. "\n" .. v
+											end
+										end
+										return ret
+									end,
+									set = function(info, value)
+										TF3:WipeTable(TF3.db.profile.blacklist)
+										local tbl = { strsplit("\n", value) }
+										for k, v in pairs(tbl) do
+											key = "BLIST"
+											TF3.db.profile.blacklist[key..k] = v
+										end
+									end,
+								},
+								reset_blist = {
+									type = 'execute',
+									disabled = function()
+										return not TF3.db.profile.ebl
+									end,
+									order = 5,
+									name = L["RBLS"],
+									desc = L["RBLS"],
+									func = function() TF3.db.profile.blacklist = TF3:CopyTable(L.BLACKLIST) end,
+								},
+							},
+						},
+						listsGroupWhite = {
+							type = "group",
+							handler = TF3,
+							order = 2,
+							disabled = function()
+								return not TF3.db.profile.turnOn
+							end,
+							name = L["wLists"],
+							desc = L["listsGD"],
+							args = {
+								optionsHeader3b = {
+									type	= "header",
+									order	= 1,
+									name	= L["wLists"],
+								},
+								whitelist_enable = {
+									type = 'toggle',
+									order = 2,
+									width = "double",
+									name = L["WLE"],
+									desc = L["WLE"],
+									get = function() return TF3.db.profile.whitelist_enable end,
+									set = function() TF3.db.profile.whitelist_enable = not TF3.db.profile.whitelist_enable end,
+								},
+								editwhitelist = {
+									type = 'toggle',
+									order = 3,
+									disabled = function()
+										return not TF3.db.profile.whitelist_enable
+									end,
+									width = "double",
+									name = L["EWL"],
+									desc = L["EWL"],
+									get = function() return TF3.db.profile.ewl end,
+									set = function() TF3.db.profile.ewl = not TF3.db.profile.ewl end,
+								},
+								whitelist_repeat_bypass = {
+									type = 'toggle',
+									order = 4,
+									disabled = function()
+										return not TF3.db.profile.whitelist_enable
+									end,
+									width = "double",
+									name = L["RPTBYPASS"],
+									desc = L["RPTBYPASSD"],
+									get = function() return TF3.db.profile.wlbp end,
+									set = function() TF3.db.profile.wlbp = not TF3.db.profile.wlbp end,
+								},
+								whitelist_blacklist_bypass = {
+									type = 'toggle',
+									order = 5,
+									disabled = function()
+										return not TF3.db.profile.whitelist_enable
+									end,
+									width = "double",
+									name = L["BLBYPASS"],
+									desc = L["BLBYPASSD"],
+									get = function() return TF3.db.profile.wlblbp end,
+									set = function() TF3.db.profile.wlblbp = not TF3.db.profile.wlblbp end,
+								},
+								wlist = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.ewl
+									end,
+									multiline = 10,
+									order = 6,
+									width = "full",
+									name = L["wLists"],
+									usage = L["INPUSAGE"],
+									get = function(info)
+										local a = {}
+										local ret = ""
+										if (TF3.db.profile.whitelist == nil) then
+											TF3.db.profile.whitelist = L.WHITELIST
+										end
+										for _,v in pairs(TF3.db.profile.whitelist) do
+											insert(a, v)
+										end
+										sort(a)
+										for _,v in ipairs(a) do
+											if ret == "" then
+												ret = v
+											else
+												ret = ret .. "\n" .. v
+											end
+										end
+										return ret
+									end,
+									set = function(info, value)
+										TF3:WipeTable(TF3.db.profile.whitelist)
+										local tbl = { strsplit("\n", value) }
+										for k, v in pairs(tbl) do
+											key = "WLIST"
+											TF3.db.profile.whitelist[key..k] = v
+										end
+									end,
+								},
+								reset_wlist = {
+									type = 'execute',
+									disabled = function()
+										return not TF3.db.profile.ewl
+									end,
+									order = 7,
+									name = L["RWLS"],
+									desc = L["RWLS"],
+									func = function() TF3.db.profile.whitelist = TF3:CopyTable(L.WHITELIST) end,
+								},
+							},
+						},
+					},
+				},
+				repeatGroupMain = {
+					type = "group",
+					handler = TF3,
+					childGroups = "tab",
+					order = 4,
+					disabled = function()
+						return not TF3.db.profile.turnOn
+					end,
+					name = L["REPEAT"],
+					desc = L["REPEAT"],
+					args = {
+						repeat_enable = {
+							type = 'toggle',
+							order = 1,
+							width = "double",
+							name = L["RPTENABLE"],
+							desc = L["RPTENABLED"],
+							get = function() return TF3.db.profile.repeat_enable end,
+							set = function() TF3.db.profile.repeat_enable = not TF3.db.profile.repeat_enable end,
+						},
+						repeatGroup = {
+							type = "group",
+							handler = TF3,
+							order = 2,
+							disabled = function()
+								return not TF3.db.profile.repeat_enable
+							end,
+							name = L["REPEAT"],
+							desc = L["REPEAT"],
+							args = {
+								num_repeats = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.repeat_enable
+									end,
+									order = 3,
+									width = "full",
+									name = L["#RPT"],
+									desc = L["#RPTD"],
+									usage = L["RPTU"],
+									get = function(info) return TF3.db.profile.num_repeats end,
+									set = function(info, value) TF3.db.profile.num_repeats = value end,
+								},
+								time_repeats = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.repeat_enable
+									end,
+									order = 4,
+									width = "full",
+									name = L["TRPT"],
+									desc = L["TRPTD"],
+									usage = L["RPTU"],
+									get = function(info) return TF3.db.profile.time_repeats end,
+									set = function(info, value) TF3.db.profile.time_repeats = value end,
+								},
+								repeats_blocked = {
+									type = 'input',
+									disabled = true,
+									order = 5,
+									width = "half",
+									name = L["RPTBLOCKED"],
+									desc = L["RPTBLOCKEDD"],
+									get = function(info) return format("%d",TF3.db.profile.repeats_blocked) end,
+								},
+								reset_repeats_blocked = {
+									type = 'execute',
+									order = 6,
+									width = "half",
+									name = L["RPTRESET"],
+									desc = L["RPTRESETD"],
+									func = function()
+										TF3.db.profile.repeats_blocked = 0
+										if (LibStub("LibDataBroker-1.1", true)) then
+											TF3Frame.Blocked.text = TF3.db.profile.repeats_blocked .. "Repeats Blocked"
+											TF3Frame.Blocked.value = TF3.db.profile.repeats_blocked
+										end
+									end,
+								},
+							},
+						},
+						repeatGroupAdv = {
+							type = "group",
+							handler = TF3,
+							order = 3,
+							disabled = function()
+								return not TF3.db.profile.repeat_enable
+							end,
+							name = L["RPTA"],
+							desc = L["RPTAD"],
+							args = {
+								repeat_recycle_time = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.repeat_enable
+									end,
+									order = 1,
+									width = "full",
+									name = L["RPTRT"],
+									desc = L["RPTRTD"],
+									usage = L["RPTRTSU"],
+									get = function(info) return TF3.db.profile.repeat_recycle_time end,
+									set = function(info, value)
+										TF3.db.profile.repeat_recycle_time = value
+										TF3:ScheduleRepeatingTimer("RecycleTables", tonumber(TF3.db.profile.repeat_recycle_time), TF3.repeatdata)
+									end,
+								},
+								repeat_recycle_size = {
+									type = 'input',
+									disabled = function()
+										return not TF3.db.profile.repeat_enable
+									end,
+									order = 2,
+									width = "full",
+									name = L["RPTRS"],
+									desc = L["RPTRSD"],
+									usage = L["RPTRTSU"],
+									get = function(info) return TF3.db.profile.repeat_recycle_size end,
+									set = function(info, value) TF3.db.profile.repeat_recycle_size = value end,
+								},
+								repeats_table_size = {
+									type = 'input',
+									disabled = true,
+									order = 3,
+									name = L["RPTTS"],
+									get = function() return format("%d",TF3:GetNumElements(TF3.repeatdata)) end,
+								},
+								blank_space1 = {
+									type = 'description',
+									order = 4,
+									name = "",
+								},
+								options_header5 = {
+									type	= "header",
+									order	= 5,
+									name	= L["RPTTC"],
+								},
+								reset_repeat_table_content = {
+									type = 'execute',
+									disabled = function()
+										return not TF3.db.profile.repeat_enable
+									end,
+									order = 6,
+									name = L["RPTTT"],
+									desc = L["RPTTTD"],
+									func = function() TF3:RecycleTables(TF3.repeatdata) end,
+								},
+								repeats_table_content = {
+									type = 'description',
+									fontSize = "medium",
+									disabled = true,
+									order = 7,
+									name = function()
+										local ret = ""
+										for k,v in pairs(TF3.repeatdata) do
+											if ret == "" then
+												ret = k
+											else
+												ret = ret .. "\n" .. k
+											end
+										end
+										return ret
+									end,
+								},
+								blank_space2 = {
+									type = 'description',
+									order = 8,
+									name = "\n",
+								},
+							},
+						},
+					},
+				},
+				outputGroup = {
+					type = "group",
+					handler = TF3,
+					order = 5,
+					disabled = function()
+						return not TF3.db.profile.turnOn
+					end,
+					name = L["OUTPUT"],
+					desc = L["OUTPUT"],
+					args = {
+						optionsHeader5 = {
+							type	= "header",
+							order	= 1,
+							name	= L["OUTPUT"],
+						},
+						redirect = {
+							type = 'toggle',
+							order = 2,
+							width = "full",
+							name = L["Redir"],
+							desc = L["RedirDesc"],
+							get = function() return TF3.db.profile.redirect end,
+							set = function() TF3.db.profile.redirect = not TF3.db.profile.redirect end,
+						},
+						redirect_blacklist = {
+							type = 'toggle',
+							order = 3,
+							width = "full",
+							name = L["RedirBL"],
+							desc = L["RedirDesc"],
+							get = function() return TF3.db.profile.redirect_blacklist end,
+							set = function() TF3.db.profile.redirect_blacklist = not TF3.db.profile.redirect_blacklist end,
+						},
+						optionsHeader6 = {
+							type	= "header",
+							order	= 4,
+							name	= L["DEBUGGING"],
+						},
+						debug = {
+							type = 'toggle',
+							order = 5,
+							width = "full",
+							disabled = false,
+							hidden = false,
+							name = L["Debug"],
+							desc = L["DebugDesc"],
+							get = function() return TF3.db.profile.debug end,
+							set = function() TF3.db.profile.debug = not TF3.db.profile.debug end,
+						},
+						debug_checking = {
+							type = 'toggle',
+							order = 6,
+							width = "full",
+							disabled = false,
+							hidden = false,
+							name = L["DebugChecking"],
+							desc = L["DebugCheckingD"],
+							get = function() return TF3.db.profile.debug_checking end,
+							set = function() TF3.db.profile.debug_checking = not TF3.db.profile.debug_checking end,
+						},
+						optionsHeader4 = {
+							type	= "header",
+							order	= 7,
+							name	= L["FSELF"],
+							desc = L["FSELFD"],
+						},
+						filterSELF = {
+							type = 'toggle',
+							order = 8,
+							width = "double",
+							disabled = false,
+							name = L["FSELF"],
+							desc = L["FSELFD"],
+							get = function() return TF3.db.profile.filterSELF end,
+							set = function() TF3.db.profile.filterSELF = not TF3.db.profile.filterSELF end,
+						},
+					},
+				},
+				tableGroup = {
+					type = "group",
+					handler = TF3,
+					order = 6,
+					disabled = function()
+						return not TF3.db.profile.turnOn
+					end,
+					name = "Exempt List",
+					desc = "Current Exempt List",
+					args = {
+						optionsHeader7 = {
+							type = 'header',
+							order = 1,
+							name = "Exempt Party Members",
+						},
+						currentPartyMembers_table_content = {
+							type = 'description',
+							fontSize = "medium",
+							disabled = true,
+							order = 2,
+							name = function()
+								local ret = ""
+								for k,v in pairs(TF3.currentPartyMembers) do
+									if ret == "" then
+										ret = v
+									else
+										ret = ret .. "\n" .. v
+									end
+								end
+								return ret
+							end,
+						},
+						blank_space3 = {
+							type = 'description',
+							order = 3,
+							name = "\n",
+						},
+						optionsHeader8 = {
+							type = 'header',
+							order = 4,
+							name = "Exempt Friend List",
+						},
+						currentFriends_table_content = {
+							type = 'description',
+							fontSize = "medium",
+							disabled = true,
+							order = 5,
+							name = function()
+								local ret = ""
+								for k,v in pairs(TF3.db.profile.friendslist) do
+									if ret == "" then
+										ret = v
+									else
+										ret = ret .. "\n" .. v
+									end
+								end
+								return ret
+							end,
+						},
+						blank_space4 = {
+							type = 'description',
+							order = 6,
+							name = "\n",
+						},
+					},
+				},
+			},
+		},
+	},
+}