Quantcast

Added more facts and made some other improvements.

F16Gaming [02-03-13 - 23:05]
Added more facts and made some other improvements.
Filename
ChatManager.lua
CommandManager.lua
FactsLoader.xml
FactsManager.lua
PlayerManager.lua
facts/chuck.lua
facts/rules.lua
locales/enUS.lua
diff --git a/ChatManager.lua b/ChatManager.lua
index f076fa6..7c8da42 100644
--- a/ChatManager.lua
+++ b/ChatManager.lua
@@ -50,7 +50,7 @@ C.ChatManager = {
 		CHAT_MSG_BATTLEGROUND			= "BATTLEGROUND",
 		CHAT_MSG_BATTLEGROUND_LEADER	= "BATTLEGROUND",
 		CHAT_MSG_CHANNEL				= "CHANNEL",
-		CHAT_MSG_GUILD					= "WHISPER",
+		CHAT_MSG_GUILD					= "GUILD",
 		CHAT_MSG_OFFICER				= "WHISPER",
 		CHAT_MSG_PARTY					= "PARTY",
 		CHAT_MSG_PARTY_LEADER			= "PARTY",
diff --git a/CommandManager.lua b/CommandManager.lua
index 0741392..f073b40 100644
--- a/CommandManager.lua
+++ b/CommandManager.lua
@@ -192,7 +192,7 @@ function CM:HandleCommand(command, args, isChat, player, bnetInfo)
 		end
 		local result, arg, errArg = cmd.Call(args, player, isChat, bnetInfo)
 		if type(result) == "nil" then
-			return "CM_ERR_UNKNOWN"
+			return nil
 		end
 		return result, arg, errArg
 	else
@@ -675,7 +675,7 @@ CM:Register({"invite", "inv"}, PM.Access.Groups.User.Level, function(args, sende
 	if bnetInfo then pID = bnetInfo.PresenceID end
 	if type(args[1]) == "string" then
 		local player = PM:GetOrCreatePlayer(args[1])
-		return PM:Invite(player, sender, pID)
+		return PM:Invite(player, sender, pID, tostring(args[2]):lower():match("^f"))
 	else
 		return PM:Invite(sender, sender, pID)
 	end
@@ -687,7 +687,7 @@ CM:Register({"inviteme", "invme"}, PM.Access.Groups.User.Level, function(args, s
 	end
 	local pID
 	if bnetInfo then pID = bnetInfo.PresenceID end
-	return PM:Invite(sender, sender, pID)
+	return PM:Invite(sender, sender, pID, tostring(args[2]):lower():match("^f"))
 end, "CM_INVITEME_HELP")

 CM:Register({"blockinvites", "blockinvite", "denyinvites", "denyinvite"}, PM.Access.Groups.User.Level, function(args, sender, isChat, bnetInfo)
@@ -1213,14 +1213,21 @@ CM:Register({"fact", "facts"}, PM.Access.Groups.User.Level, function(args, sende
 	if #args < 1 then
 		return false, "CM_FACT_USAGE"
 	end
-	return FM:AnnounceFact(args[1])
+	return FM:AnnounceFact(args[1], tonumber(args[2]))
 end, "CM_FACT_HELP")

 -- Alias for !fact cat
 CM:Register({"cat", "c", "meow"}, PM.Access.Groups.User.Level, function(args, sender, isChat, bnetInfo)
-	return FM:AnnounceFact("cat")
+	return FM:AnnounceFact("cat", tonumber(args[1]))
 end, "CM_CAT_HELP")

+CM:Register({"factstats", "factstat", "fstat", "fs"}, PM.Access.Groups.User.Level, function(args, sender, isChat, bnetInfo)
+	if #args < 1 then
+		return FM:AnnounceLoadedTopics()
+	end
+	return FM:AnnounceTopicInfo(args[1])
+end, "CM_FACTSTATS_HELP")
+
 CM:Register({"factsettings", "factsetting", "factset"}, PM.Access.Groups.Admin.Level, function(args, sender, isChat, bnetInfo)
 	if #args < 1 then
 		if FM:IsEnabled() then
diff --git a/FactsLoader.xml b/FactsLoader.xml
index e59c8b9..b9e9bab 100644
--- a/FactsLoader.xml
+++ b/FactsLoader.xml
@@ -21,4 +21,6 @@
 ..\FrameXML\UI.xsd">
 	<Script file="FactsManager.lua" />
 	<Script file="facts\cat.lua" />
+	<Script file="facts\rules.lua" />
+	<Script file="facts\chuck.lua" />
 </Ui>
diff --git a/FactsManager.lua b/FactsManager.lua
index 0d407d2..283726f 100644
--- a/FactsManager.lua
+++ b/FactsManager.lua
@@ -22,9 +22,11 @@
 -- API Upvalues

 local C = Command
+local L = C.LocaleManager

 C.FactsManager = {
 	Facts = {},
+	AliasFacts = {},
 	UsedFacts = {}
 }

@@ -40,6 +42,11 @@ local FactFormat = "%s fact #%d: %s"
 function FM:Init()
 	for k,_ in pairs(self.Facts) do
 		factMapping[k:lower()] = k
+		if self.AliasFacts[k] then
+			for _,v in pairs(self.AliasFacts[k]) do
+				factMapping[v:lower()] = k
+			end
+		end
 		self.UsedFacts[k] = {}
 	end

@@ -61,19 +68,25 @@ function FM:LoadSavedVars()
 	end
 end

-function FM:GetFact(topic)
+function FM:GetFact(topic, index)
 	if topic then -- Specific topic
 		if not factMapping[topic] then
-			return false, "FM_ERR_TOPIC_NOT_FOUND"
+			return false, "FM_ERR_TOPIC_NOT_FOUND", {topic}
 		elseif #self.Facts[factMapping[topic]] == 0 then
-			return false, "FM_ERR_TOPIC_EMPTY"
+			return false, "FM_ERR_TOPIC_EMPTY", {topic}
 		end
 		topic = factMapping[topic]
-		if self.Settings.NODUPE then
+		if index then -- Specific index
+			local fact = self.Facts[topic][index]
+			if not fact then
+				return false, "FM_ERR_FACT_NOT_FOUND", {topic, index}
+			end
+			return FactFormat:format(topic, index, fact)
+		elseif self.Settings.NODUPE then
 			if #self.UsedFacts[topic] >= #self.Facts[topic] then
 				wipe(self.UsedFacts[topic])
 			end
-			local index = math.random(1, #self.Facts[topic])
+			index = math.random(1, #self.Facts[topic])
 			while self.UsedFacts[topic][index] do
 				index = math.random(1, #self.Facts[topic])
 			end
@@ -92,29 +105,57 @@ function FM:GetFact(topic)
 		i = i + 1
 	end
 	if not topicName then
-		return false, "FM_ERR_NO_TOPIC_FOUND"
+		return false, "FM_ERR_NO_TOPICS_FOUND"
 	elseif #self.Facts[topicName] == 0 then
-		return false, "FM_ERR_TOPIC_EMPTY"
+		return false, "FM_ERR_TOPIC_EMPTY", {topicName}
 	end
 	local factIndex = math.random(1, #self.Facts[topicName])
 	return FactFormat:format(topicName, factIndex, self.Facts[topicName][factIndex])
 end

-function FM:AnnounceFact(topic)
+function FM:AnnounceFact(topic, index)
 	if not self:IsEnabled() then
 		return false, "FM_ERR_DISABLED"
 	end

-	local fact, err, args = self:GetFact(topic)
+	local fact, err, args = self:GetFact(topic, index)
 	if not fact then
 		return false, err, args
 	end
-	if fact:len() > 250 then
+	if fact:len() > 240 then
 		return CM.SpecialOutput.RawTable, CES:Fit(fact, 240)
 	end
 	return CM.SpecialOutput.Raw, fact
 end

+function FM:AnnounceLoadedTopics()
+	if CET:GetRealLength(self.Facts) == 0 then
+		return false, "FM_ERR_NO_TOPICS_FOUND"
+	end
+	local topics = ""
+	for k,_ in pairs(self.Facts) do
+		topics = topics .. k .. " "
+	end
+	topics = CES:Trim(topics)
+	topics = L("FM_LOADED_FORMAT"):format(topics)
+	if topics:len() > 240 then
+		return CM.SpecialOutput.RawTable, CES:Fit(topics, 240)
+	end
+	return CM.SpecialOutput.Raw, topics
+end
+
+function FM:AnnounceTopicInfo(topic)
+	topic = topic:lower()
+	local topicName = factMapping[topic]
+	if not topicName then
+		return false, "FM_ERR_TOPIC_NOT_FOUND"
+	elseif #self.Facts[topicName] == 0 then
+		return false, "FM_ERR_TOPIC_EMPTY", {topic}
+	end
+	local factCount = #self.Facts[topicName]
+	return "FM_INFO_FORMAT", {topicName, factCount}
+end
+
 function FM:IsEnabled()
 	return self.Settings.ENABLED
 end
diff --git a/PlayerManager.lua b/PlayerManager.lua
index a5db8ee..d87829c 100644
--- a/PlayerManager.lua
+++ b/PlayerManager.lua
@@ -267,6 +267,13 @@ function PM:ParseMessage(message)
 		CM:SendMessage(L("PM_INVITE_DECLINED"):format(name), "WHISPER", self.Invites[name][1])
 		self.Invites[name] = nil
 	end
+	name = message:match(L("PM_MATCH_NOTFOUND"))
+	if not name then name = message:match(L("PM_MATCH_NOTPLAYING")) end
+	if name then
+		if not self.Invites[name] then return end
+		CM:SendMessage(L("PM_INVITE_NOTFOUND"):format(name), "WHISPER", self.Invites[name][1])
+		self.Invites[name] = nil
+	end
 end

 --- Get or create a player.
@@ -618,10 +625,11 @@ end
 -- @param player Player object of player to invite.
 -- @param sender Player object of the inviting player.
 -- @param pID Presence ID if this was an Invite(Me) command from B.Net chat
+-- @param force Force an invite call, used when the active invite system fails
 -- @return String stating the result of the invite, false if error.
 -- @return Error message if unsuccessful, nil otherwise.
 --
-function PM:Invite(player, sender, pID)
+function PM:Invite(player, sender, pID, force)
 	if not sender then sender = self:GetOrCreatePlayer(UnitName("player")) end
 	if player.Info.Name == UnitName("player") then
 		return false, "PM_INVITE_SELF"
@@ -633,7 +641,7 @@ function PM:Invite(player, sender, pID)
 		return false, "PM_INVITE_LFG"
 	end
 	if GT:IsGroupLeader() or GT:IsRaidLeaderOrAssistant() or not GT:IsGroup() then
-		if self.Invites[player.Info.Name] then
+		if self.Invites[player.Info.Name] and not force then
 			return false, "PM_INVITE_ACTIVE", {player.Info.Name}
 		elseif player.Info.Name == sender.Info.Name then
 			if player.Info.Realm == GetRealmName() or not pID then
diff --git a/facts/chuck.lua b/facts/chuck.lua
new file mode 100644
index 0000000..60f8da6
--- /dev/null
+++ b/facts/chuck.lua
@@ -0,0 +1,126 @@
+Command.FactsManager.Facts.ChuckNorris = {
+	"Chuck Norris' tears cure cancer. Too bad he has never cried.",
+	"Chuck Norris counted to infinity - twice.",
+	"Chuck Norris does not hunt because the word hunting infers the probability of failure. Chuck Norris goes killing.",
+	"If you can see Chuck Norris, he can see you. If you can't see Chuck Norris you may be only seconds away from death.",
+	"Chuck Norris sold his soul to the devil for his rugged good looks and unparalleled martial arts ability. Shortly after the transaction was finalized, Chuck roundhouse kicked the devil in the face and took his soul back. The devil, who appreciates irony, couldn't stay mad and admitted he should have seen it coming. They now play poker every second Wednesday of the month.",
+	"When the Boogeyman goes to sleep every night he checks his closet for Chuck Norris.",
+	"Chuck Norris built a time machine and went back in time to stop the JFK assassination. As Oswald shot, Chuck Norris met all three bullets with his beard, deflecting them. JFK's head exploded out of sheer amazement.",
+	"Chuck Norris has already been to Mars; that's why there are no signs of life there.",
+	"They once made a Chuck Norris toilet paper, but it wouldn't take shit from anybody.",
+	"A blind man once stepped on Chuck Norris' shoe. Chuck replied, \"Don't you know who I am? I'm Chuck Norris!\" The mere mention of his name cured this man blindness. Sadly the first, last, and only thing this man ever saw, was a fatal roundhouse delivered by Chuck Norris.",
+	"Chuck Norris is 1/8th Cherokee. This has nothing to do with ancestry, the man ate a fucking Indian.",
+	"There is no chin behind Chuck Norris' beard. There is only another fist.",
+	"In fine print on the last page of the Guinness Book of World Records it notes that all world records are held by Chuck Norris, and those listed in the book are simply the closest anyone else has ever gotten.",
+	"The chief export of Chuck Norris is pain.",
+	"Chuck Norris is currently suing NBC, claiming Law and Order are trademarked names for his left and right legs.",
+	"The Great Wall of China was originally created to keep Chuck Norris out. It failed misserably.",
+	"Crop circles are Chuck Norris' way of telling the world that sometimes corn needs to lie the fuck down.",
+	"Chuck Norris once commented, \"There are few problems in this world that cannot be solved by a swift roundhouse kick to the face. In fact, there are none.\"",
+	"Chuck Norris once ate an entire ream of rice paper and shat out origami swans and Mister Miyagi from Karate Kid.",
+	"Chuck Norris is ten feet tall, weighs two-tons, breathes fire, and could eat a hammer and take a shotgun blast standing.",
+	"Chuck Norris is a man of few words. Chuck Norris is not a man of few roundhouse kicks to the face.",
+	"The Four Horsemen of the Apocalypse actually live in Chuck Norris's nutsack.",
+	"When observing a Chuck Norris roundhouse kick in slow motion, one finds that Chuck Norris actually rapes his victim in the ass, smokes a cigarette with Dennis Leary, and then roundhouse kicks them in the face.",
+	"Chuck Norris put humpty dumpty back together again, only to roundhouse kick him in the face. Later Chuck dined on scrambled eggs with all the king's horses and all the king's men. The king himself could not attend for unspecified reasons. Coincidentally, the autopsoy revealed the cause of death to be a roundhouse kick to the face. There is only one King.",
+	"When Chuck Norris played golf for money, chuck marked down a hole in 0 every time, a pro at the golf club, said to Chuck: \"excuse me sir, but you cant score zero on a hole\". Chuck Norris turned towards the man and said, I'm Chuck Norris, the man then proceeded to pour gas over his body and set himself on fire because that would be less painful than getting roundhouse kicked by Chuck Norris, Chuck Norris roundhouse kicked him in the face anyways.",
+	"Chuck Norris made Ellen Degeneres straight.",
+	"Chuck Norris kicked Neo out of Zion , now Neo is \"The Two\"",
+	"Chuck Norris' iPod came with a real charger instead of just a USB cord",
+	"Chuck Norris knows where Carmen Sandiego is.",
+	"Rudolph has a red nose because he got lippy and Chuck Norris roundhouse kicked him across the face several times",
+	"China was once bordering the United States, until Chuck Norris roundhouse kicked it all the way through the Earth.",
+	"Chuck Norris is what Willis was talking about",
+	"If you have five dollars and Chuck Norris has five dollars, Chuck Norris has more money than you.",
+	"Chuck Norris sent Jesus a birthday card on December 25th and it wasn't Jesus’ birthday. Jesus was to scared to correct Chuck Norris and to this day December 25th is known as Jesus' birthday.",
+	"When Chuck Norris had surgery, the anesthesia was applied to the doctors.",
+	"Chuck Norris once broke the land speed record on a bicycle that was missing its chain and the back tire.",
+	"Chuck Norris once kicked a baby elephant into puberty",
+	"Multiple people have died from Chuck Norris giving them the finger.",
+	"Chuck Norris once tried to wear glasses. The result was him seeing around the world to the point where he was looking at the back of his own head.",
+	"Pee Wee Herman got arrested for masturbating in public. The same day, Chuck Norris got an award for masturbating in public.",
+	"Once a grizzly bear threatened to eat Chuck Norris. Chuck showed the bear his fist and the bear proceeded to eat himself, because it would be the less painful way to die.",
+	"If Chuck Norris is late, time better slow the fuck down",
+	"Chuck Norris sleeps with a night light. Not because Chuck Norris is afraid of the dark, but the dark is afraid of Chuck Norris",
+	"Chuck Norris can touch MC Hammer.",
+	"Chuck Norris ordered a Big Mac at Burger King, and got one.",
+	"Chuck Norris always has sex on the first date. Always.",
+	"A Handicap parking sign does not signify that this spot is for handicapped people. It is actually in fact a warning, that the spot belongs to Chuck Norris and that you will be handicapped if you park there.",
+	"Chuck Norris frequently donates blood to the Red Cross. Just never his own.",
+	"There is no such thing as tornados. Chuck Norris just hates trailer parks.",
+	"Chuck Norris never cries, because of this when he's sad he roundhouse kicks himself and it makes him feel better since he knows he is the only one who can survive the roundhouse.",
+	"Chuck Norris does not procreate, he breeds",
+	"When asked what type of vehicle he drives, Chuck Norris responded slyly with \"Don't you mean what kind of vehicle drives me?\"",
+	"Chuck Norris' evil twin brother, Richard Simmons, once approached Chuck with the hope of reconciliation, but at the sight of Richard's curly, well kept hair, Chuck Norris became so enraged that he turned green with hate and ripped Richard Simmons arms and legs off. This action was the origin of the Marvel Comic badass, The Incredible Hulk.",
+	"Chuck Norris doesn't worry about changing his clock twice a year for daylight savings time. The sun rises and sets when Chuck tells it to.",
+	"Chuck Norris only masturbates to pictures of Chuck Norris.",
+	"Filming on location for Walker: Texas Ranger, Chuck Norris brought a stillborn baby lamb back to life by giving it a prolonged beard rub. Shortly after the farm animal sprang back to life and a crowd had gathered, Chuck Norris roundhouse kicked the animal, breaking its neck, to remind the crew once more that Chuck giveth, and the good Chuck, he taketh away.",
+	"Chuck Norris was the fourth Wiseman. He brought baby Jesus the gift of \"beard\". Jesus wore it proudly to his dying day. The other Wisemen, jealous of Jesus’ obvious gift favoritism, used their combined influence to have Chuck omitted from the Bible. Shortly after all three died of roundhouse kick related deaths.",
+	"Chuck Norris used live ammunition during all shoot-outs. When a director once said he couldn’t, he replied, \"Of course I can, I’m Chuck Norris,\" and roundhouse kicked him in the face.",
+	"If paper beats rock, rock beats scissors, and scissors beats paper, what beats all 3 at the same time? Answer: Chuck Norris.",
+	"When his martial arts prowess fails to resolve a situation, Chuck Norris plays dead. When playing dead doesn’t work, he plays zombie.",
+	"Although it is not common knowledge, there are actually three sides to the Force: the light side, the dark side, and Chuck Norris.",
+	"Scientists used to believe that diamond was the world’s hardest substance. But then they met Chuck Norris, who gave them a roundhouse kick to the face so hard, and with so much heat and pressure, that the scientists turned into artificial Chuck Norris.",
+	"God offered Chuck Norris the gift to fly, which he swiftly declined for super strength roundhouse ability.",
+	"When Chuck Norris was denied a Bacon McMuffin at McDonalds because it was 10:35, he roundhouse kicked the store so hard it became a KFC.",
+	"Chuck Norris drinks napalm to quell his heartburn.",
+	"A duck’s quack does not echo. Chuck Norris is solely responsible for this phenomenon. When asked why he will simply stare at you, grimly.",
+	"Chuck Norris once tried to defeat Garry Kasparov in a game of chess. When Norris lost, he won in life by roundhouse kicking Kasparov in the side of the face.",
+	"Chuck Norris’ roundhouse kick is so powerful, it can be seen from outer space by the naked eye.",
+	"Chuck Norris doesn’t believe in Germany.",
+	"If you want a list of Chuck Norris’ enemies, just check the extinct species list.",
+	"Chuck Norris has never blinked in his entire life. Never.",
+	"Chuck Norris doesn’t need to swallow when eating food.",
+	"If Superman and The Flash were to race to the edge of space you know who would win? Chuck Norris.",
+	"Chuck Norris eats transformer toys in vehicle mode and poos them out transformed into a robot.",
+	"Ironically, Chuck Norris’ hidden talent is invisibility.",
+	"Chuck Norris owns the greatest poker face of all-time. It helped him win the 1983 world series of poker despite him holding just a joker, a 2 of clubs, a 7 of spades, and a green number 4 from Uno and a monopoly ‘get out of jail free’ card.",
+	"Chuck Norris invented water.",
+	"Chuck Norris invented a language that incorporates karate and roundhouse kicks. So next time Chuck Norris is kicking your ass, don’t be offended or hurt, he may be just trying to tell you he likes your hat.",
+	"Chuck Norris went looking for a bar but couldn’t find one. He walked to a vacant lot and sat there. Sure enough within an hour an a half someone constructed a bar around him. He then ordered a shot, drank it, and then burned the place to the ground. Chuck Norris yelled over the roar of the flames, \"always leave things the way you found em!\"",
+	"One time while sparring with Wolverine, Chuck Norris accidentally lost his left testicle. You might be familiar with it to this very day by its technical term: Jupiter.",
+	"Chuck Norris is Luke Skywalker’s real father.",
+	"Contrary to popular belief, Chuck Norris, not the box jellyfish of northern Australia, is the most venomous creature on earth. Within 3 minutes of being bitten, a human being experiences the following symptoms: fever, blurred vision, beard rash, tightness of the jeans, and the feeling of being repeatedly kicked through a car windshield.",
+	"Chuck Norris does not use spell check. If he happens to misspell a word, Oxford will simply change the actual spelling of it.",
+	"Before science was invented it was once believed that autumn occurred when Chuck Norris roundhouse kicked every tree in existence.",
+	"In the original pilot for Star Trek Next Generation, Chuck Norris can be seen powering the USS Enterprise warp drive with his roundhouse kicks.",
+	"Chuck Norris isn’t lactose intolerant. He just doesn’t put up with lactose’s shit.",
+	"Chuck Norris doesn’t eat. Rather he kicks ass until he’s full.",
+	"Scientists in Washington have recently conceded that, if there were a nuclear war, all that would remain are cockroaches and Chuck Norris.",
+	"Chuck Norris once threated to sue Burger King because they refused to make it his way. When asked what \"his way\" detailed, he replied: \"with barbed wire and nails, of course\". He then roundhouse kicked the reporter for even asking.",
+	"Chuck Norris never \"gets laid\", rather: \"laid gets Chuck\".",
+	"Playgirl magazine once asked Chuck Norris to appear naked in an issue, Chuck laughed at the opporunity saying \"there isn’t enough paper in the world to contain my bearded member\". He then killed the editors simply by unzipping his pants.",
+	"Helen Keller’s favorite color is Chuck Norris",
+	"Chuck Norris once walked down the street with a massive erection. There we no survivors.",
+	"When Chuck Norris’s wife burned the turkey one Thanksgiving, Chuck said, \"Don’t worry about it honey,\" and went into his backyard. He came back five minutes later with a live turkey, ate it whole, and when he threw it up a few seconds later it was fully cooked and came with cranberry sauce. When his wife asked him how he had done it, he gave her a roundhouse kick to the face and said, \"Never question Chuck Norris.\"",
+	"Chuck Norris doesnt have AIDS but he gives it to people anyway.",
+	"When you open a can of whoop-ass, Chuck Norris jumps out.",
+	"On June 7th 1994, Chuck Norris entered the same restaurant supermodel Cindy Crawford was eating at. Instinctively, Cindy swept everything off the table, threw herself on it in a fit of lust, and begged Chuck to ravish her. After Chuck finished his beer, he obliged her. When Chuck's magnificent lead sperm cannoned into Cindy's womb it went straight to one of her ovaries and roared, \"Which one of you servile wenches thinks you can handle getting split open by the Chuck!?\" All of the eggs cowered in the corner. The same thing happened at the other ovary. \"I didn't fucking think so!\" shouted the lead sperm which then lead the rest of the troops back into Chuck's balls. Chuck pulled out; roundhouse kicked Cindy in the face and told her, \"Don't ever waste my time again.\"",
+	"Chuck Norris can piss into gale force winds.",
+	"There are no disabled people. Only people who have met Chuck Norris.",
+	"Chuck Norris won 'Jumanji' without ever saying the word. He simply beat the living shit out of everything that was thrown at him, and the game forfeited.",
+	"Chuck Norris once bet NASA he could survive re-entry without a spacesuit. On July 19th, 1999, a naked Chuck Norris re-entered the earth's atmosphere, streaking over 14 states and reaching a temperature of 3000 degrees. An embarrassed NASA publicly claimed it was a meteor, and still owes him a beer.",
+	"Chuck Norris got a perfect score on his SAT's, simply by writing Chuck Norris for every answer.",
+	"Aliens do exist. They're just waiting for Chuck Norris to die before they attack.",
+	"Chuck Norris once ate three 72 oz. steaks in one hour. He spent the first 45 minutes having sex with his waitress.",
+	"After much debate, President Truman decided to drop the atomic bomb on Hiroshima rather than the alternative of sending Chuck Norris. It was more \"humane\".",
+	"Chuck Norris doesn't see dead people. He makes people dead.",
+	"Chuck Norris once went to a frat party, and proceeded to roundhouse every popped collar in sight. He then trank three kegs and shat on their floor, just because he's Chuck Norris.",
+	"Chuck Norris found out about Conan O'Brien's lever that shows clips from \"Walker: Texas Ranger\" and is working on a way to make it show clips of Norris having sex with Conan's wife.",
+	"Chuck Norris doesn't have normal white blood cells like you and I. His have a small black ring around them. This signifies that they are black belts in every form of martial arts and they roundhouse kick the shit out of viruses. That's why Chuck Norris never gets ill.",
+	"Chuck Norris's girlfriend once asked him how much wood a woodchuck could chuck if a woodchuck could chuck wood. He then shouted, \"HOW DARE YOU RHYME IN THE PRESENCE OF CHUCK NORRIS!\" and ripped out her throat. Holding his girlfriend's bloody throat in his hand he bellowed, \"Don't fuck with Chuck!\" Two years and five months later he realized the irony of this statement and laughed so hard that anyone within a hundred mile radius of the blast went deaf.",
+	"When Chuck Norris played Amnesia: The Dark Descent, the game got scared.",
+	"There are no races, only countries of people Chuck Norris has beaten to different shades of black and blue.",
+	"The grass is always greener on the other side, unless Chuck Norris has been there. In that case the grass is most likely soaked in blood and tears.",
+	"Chuck Norris invented his own type of karate. It's called Chuck-Will-Kill.",
+	"Chuck Norris invented black. In fact, he invented the entire spectrum of visible light. Except pink. Tom Cruise invented pink.",
+	"Nobody doesn't like Sara Lee. Except Chuck Norris.",
+	"The show Survivor had the original premise of putting people on an island with Chuck Norris. there were no survivors and the pilot episode tape has been burned.",
+	"Chuck Norris is the reason why Waldo is hiding.",
+	"Chuck Norris does not \"style\" his hair. It lays perfectly in place out of sheer terror.",
+	"Along with his black belt, Chuck Norris often chooses to wear brown shoes. No one has DARED call him on it. Ever.",
+	"When you're Chuck Norris, anything + anything is equal to 1.... 1 roundhouse kick to the face.."
+}
+
+-- Aliases
+Command.FactsManager.AliasFacts.ChuckNorris = {"Chuck", "Norris", "CN"}
diff --git a/facts/rules.lua b/facts/rules.lua
new file mode 100644
index 0000000..cf30ae2
--- /dev/null
+++ b/facts/rules.lua
@@ -0,0 +1,52 @@
+Command.FactsManager.Facts.Rules = {
+	"Do not talk about /b/",
+	"Do NOT talk about /b/",
+	"We are Anonymous",
+	"Anonymous is legion",
+	"Anonymous never forgives",
+	"Anonymous can be a horrible, senseless, uncaring monster",
+	"Anonymous is still able to deliver",
+	"There are no real rules about posting",
+	"There are no real rules about moderation either - enjoy your ban",
+	"If you enjoy any rival sites - DON'T",
+	"All your carefully picked arguments can easily be ignored",
+	"Anything you say can and will be used against you",
+	"Anything you say can be turned into something else - fixed",
+	"Do not argue with trolls - it means that they win",
+	"The harder you try the harder you will fail",
+	"If you fail in epic proportions, it may just become a winning failure",
+	"Every win fails eventually",
+	"Everything that can be labeled can be hated",
+	"The more you hate it the stronger it gets",
+	"Nothing is to be taken seriously",
+	"Original content is original only for a few seconds before getting old",
+	"Copypasta is made to ruin every last bit of originality",
+	"Copypasta is made to ruin every last bit of originality",
+	"Every repost is always a repost of a repost",
+	"Relation to the original topic decreases with every single post",
+	"Any topic can be easily turned into something totally unrelated",
+	"Always question a person's sexual preferences without any real reason",
+	"Always question a person's gender - just in case it's really a man",
+	"In the internet all girls are men and all kids are undercover FBI agents",
+	"There are no girls on the internet",
+	"TITS of GTFO - the choice is yours",
+	"You must have pictures to prove your statements",
+	"Lurk more - it's never enough",
+	"There is porn of it, no exceptions",
+	"If no porn is found at the moment, it will be made",
+	"There will always be even more fucked up shit than what you just saw",
+	"You can not divide by zero (just because the calculator says so)",
+	"No real limits of any kind apply here - not even the sky",
+	"CAPSLOCK IS CRUISE CONTROL FOR COOL",
+	"EVEN WITH CRUISE CONTROL YOU STILL HAVE TO STEER",
+	"Desu isn't funny. Seriously guys. It's worse than Chuck Norris jokes",
+	"Nothing is sacred",
+	"The more beautiful and pure a thing is - the more satisfying it is to corrupt it",
+	"Even one positive comment about Japanese things can make you a weeaboo",
+	"When one sees a lion, one must get into the car",
+	"There is always furry porn of it",
+	"The pool is always closed"
+}
+
+-- Aliases
+Command.FactsManager.AliasFacts.Rules = {"Rule"}
diff --git a/locales/enUS.lua b/locales/enUS.lua
index 256f59a..45e0855 100644
--- a/locales/enUS.lua
+++ b/locales/enUS.lua
@@ -322,6 +322,20 @@ local L = {

 	CM_SIT_HELP = "Alias for 'emote sit'",

+	CM_FACT_HELP = "Returns a random or specific fact from the specified topic",
+	CM_FACT_USAGE = "Usage: fact <topic> [index]",
+
+	CM_CAT_HELP = "Returns a random or specific cat fact (Usage: cat [index])",
+
+	CM_FACTSTATS_HELP = "Return info about all fact topics or a specific one (Usage: factstats [topic])",
+
+	CM_FACTSETTINGS_HELP = "Configure FactsManager",
+	CM_FACTSETTINGS_USAGE = "factsettings [enable|disable|toggle|nodupe [enable|disable|toggle]]",
+	CM_FACTSETTINGS_ENABLED = "FactsManager is enabled.",
+	CM_FACTSETTINGS_DISABLED = "FactsManager is disabled",
+	CM_FACTSETTINGS_NODUPE_ENABLED = "FactsManager (No Duplicates) is enabled.",
+	CM_FACTSETTINGS_NODUPE_DISABLED = "FactsManager (No Duplicates) is disabled.",
+
 	------------
 	-- Events --
 	------------
@@ -396,6 +410,8 @@ local L = {
 	PM_MATCH_INVITEACCEPTED_RAID = "(%w+) has joined the raid group.",
 	PM_MATCH_INVITEDECLINED = "(%w+) declines your group invitation.",
 	PM_MATCH_INGROUP = "(%w+) is already in a group.",
+	PM_MATCH_NOTFOUND = "Cannot find player '(%w+)'.",
+	PM_MATCH_NOTPLAYING = "No player named '(%w+)' is currently playing.",

 	PM_ACCESS_ALLOWED = "%q is now allowed for %s.",
 	PM_ACCESS_DENIED = "%q is now denied for %s.",
@@ -438,6 +454,7 @@ local L = {
 	PM_INVITE_ACTIVE = "%s already has an active invite.",
 	PM_INVITE_DECLINED = "%s has declined the group invite.",
 	PM_INVITE_INOTHERGROUP = "%s is already in a group.",
+	PM_INVITE_NOTFOUND = "Unable to find player %s.",
 	PM_INVITE_NOTIFYTARGET = "Invited you to the group.",
 	PM_INVITE_NOTIFY = "%s invited you to the group, %s. Whisper !blockinvites to block these invites.",
 	PM_INVITE_SUCCESS = "Invited %s to group.",
@@ -772,7 +789,27 @@ local L = {
 	RM_ANNOUNCE_WINITEM = "The winner is: %s! With a roll of %d for %s.",
 	RM_ANNOUNCE_MULTIPLE = "There are multiple winners:",
 	RM_ANNOUNCE_MULTIPLEITEM = "There are multiple winners for %s:",
-	RM_ANNOUNCE_WINNER = "%s with a roll of %d."
+	RM_ANNOUNCE_WINNER = "%s with a roll of %d.",
+
+	------------------
+	-- FactsManager --
+	------------------
+
+	FM_ERR_TOPIC_NOT_FOUND = "Unable to find the specified topic: %s.",
+	FM_ERR_TOPIC_EMPTY = "The specified topic, %s, is empty.",
+	FM_ERR_NO_TOPICS_FOUND = "FactsManager was unable to find any topics.",
+	FM_ERR_TOPIC_EMPTY = "The randomly selected topic, %s, is empty.",
+	FM_ERR_DISABLED = "FactsManager is disabled.",
+	FM_ERR_FACT_NOT_FOUND = "Could not find %s fact #%d.",
+
+	FM_ENABLED = "FactsManager has been enabled.",
+	FM_DISABLED = "FactsManager has been disabled.",
+
+	FM_NODUPE_ENABLED = "FactsManager (No Duplicates) has been enabled.",
+	FM_NODUPE_DISABLED = "FactsManager (No Duplicates) has been disabled.",
+
+	FM_LOADED_FORMAT = "Loaded topics: %s",
+	FM_INFO_FORMAT = "Topic %q has %d loaded facts."
 }

 Command.LocaleManager:Register("enUS", L)