update
This commit is contained in:
parent
1d18414148
commit
d94fe1204f
0
Torchlight/AccessManager.py
Normal file → Executable file
0
Torchlight/AccessManager.py
Normal file → Executable file
2
Torchlight/AsyncClient.py
Normal file → Executable file
2
Torchlight/AsyncClient.py
Normal file → Executable file
@ -61,7 +61,6 @@ class AsyncClient():
|
|||||||
|
|
||||||
def OnReceive(self, data):
|
def OnReceive(self, data):
|
||||||
Obj = json.loads(data)
|
Obj = json.loads(data)
|
||||||
print(Obj)
|
|
||||||
|
|
||||||
if "method" in Obj and Obj["method"] == "publish":
|
if "method" in Obj and Obj["method"] == "publish":
|
||||||
self.Master.OnPublish(Obj)
|
self.Master.OnPublish(Obj)
|
||||||
@ -80,7 +79,6 @@ class AsyncClient():
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
Data = json.dumps(obj, ensure_ascii = False, separators = (',', ':')).encode("UTF-8")
|
Data = json.dumps(obj, ensure_ascii = False, separators = (',', ':')).encode("UTF-8")
|
||||||
print(obj)
|
|
||||||
|
|
||||||
with (await self.SendLock):
|
with (await self.SendLock):
|
||||||
if not self.Protocol:
|
if not self.Protocol:
|
||||||
|
97
Torchlight/AudioManager.py
Normal file → Executable file
97
Torchlight/AudioManager.py
Normal file → Executable file
@ -23,6 +23,7 @@ class AudioPlayerFactory():
|
|||||||
if _type == self.AUDIOPLAYER_FFMPEG:
|
if _type == self.AUDIOPLAYER_FFMPEG:
|
||||||
return self.FFmpegAudioPlayerFactory.NewPlayer()
|
return self.FFmpegAudioPlayerFactory.NewPlayer()
|
||||||
|
|
||||||
|
|
||||||
class AntiSpam():
|
class AntiSpam():
|
||||||
def __init__(self, master):
|
def __init__(self, master):
|
||||||
self.Logger = logging.getLogger(__class__.__name__)
|
self.Logger = logging.getLogger(__class__.__name__)
|
||||||
@ -31,6 +32,7 @@ class AntiSpam():
|
|||||||
|
|
||||||
self.LastClips = dict()
|
self.LastClips = dict()
|
||||||
self.DisabledTime = None
|
self.DisabledTime = None
|
||||||
|
self.SaidHint = False
|
||||||
|
|
||||||
def CheckAntiSpam(self, player):
|
def CheckAntiSpam(self, player):
|
||||||
if self.DisabledTime and self.DisabledTime > self.Torchlight().Master.Loop.time() and \
|
if self.DisabledTime and self.DisabledTime > self.Torchlight().Master.Loop.time() and \
|
||||||
@ -42,10 +44,7 @@ class AntiSpam():
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def RegisterClip(self, clip):
|
def SpamCheck(self, Delta):
|
||||||
self.LastClips[hash(clip)] = dict({"timestamp": None, "duration": 0.0, "dominant": False, "active": True})
|
|
||||||
|
|
||||||
def SpamCheck(self):
|
|
||||||
Now = self.Torchlight().Master.Loop.time()
|
Now = self.Torchlight().Master.Loop.time()
|
||||||
Duration = 0.0
|
Duration = 0.0
|
||||||
|
|
||||||
@ -53,7 +52,7 @@ class AntiSpam():
|
|||||||
if not Clip["timestamp"]:
|
if not Clip["timestamp"]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if Clip["timestamp"] + self.Torchlight().Config["AntiSpam"]["MaxUsageSpan"] < Now:
|
if Clip["timestamp"] + Clip["duration"] + self.Torchlight().Config["AntiSpam"]["MaxUsageSpan"] < Now:
|
||||||
if not Clip["active"]:
|
if not Clip["active"]:
|
||||||
del self.LastClips[Key]
|
del self.LastClips[Key]
|
||||||
continue
|
continue
|
||||||
@ -73,7 +72,8 @@ class AntiSpam():
|
|||||||
self.LastClips.clear()
|
self.LastClips.clear()
|
||||||
|
|
||||||
def OnPlay(self, clip):
|
def OnPlay(self, clip):
|
||||||
self.LastClips[hash(clip)]["timestamp"] = self.Torchlight().Master.Loop.time()
|
Now = self.Torchlight().Master.Loop.time()
|
||||||
|
self.LastClips[hash(clip)] = dict({"timestamp": Now, "duration": 0.0, "dominant": False, "active": True})
|
||||||
|
|
||||||
HasDominant = False
|
HasDominant = False
|
||||||
for Key, Clip in self.LastClips.items():
|
for Key, Clip in self.LastClips.items():
|
||||||
@ -84,6 +84,9 @@ class AntiSpam():
|
|||||||
self.LastClips[hash(clip)]["dominant"] = not HasDominant
|
self.LastClips[hash(clip)]["dominant"] = not HasDominant
|
||||||
|
|
||||||
def OnStop(self, clip):
|
def OnStop(self, clip):
|
||||||
|
if hash(clip) not in self.LastClips:
|
||||||
|
return
|
||||||
|
|
||||||
self.LastClips[hash(clip)]["active"] = False
|
self.LastClips[hash(clip)]["active"] = False
|
||||||
|
|
||||||
if self.LastClips[hash(clip)]["dominant"]:
|
if self.LastClips[hash(clip)]["dominant"]:
|
||||||
@ -102,7 +105,79 @@ class AntiSpam():
|
|||||||
return
|
return
|
||||||
|
|
||||||
Clip["duration"] += Delta
|
Clip["duration"] += Delta
|
||||||
self.SpamCheck()
|
self.SpamCheck(Delta)
|
||||||
|
|
||||||
|
|
||||||
|
class Advertiser():
|
||||||
|
def __init__(self, master):
|
||||||
|
self.Logger = logging.getLogger(__class__.__name__)
|
||||||
|
self.Master = master
|
||||||
|
self.Torchlight = self.Master.Torchlight
|
||||||
|
|
||||||
|
self.LastClips = dict()
|
||||||
|
self.AdStop = 0
|
||||||
|
self.NextAdStop = 0
|
||||||
|
|
||||||
|
def Think(self, Delta):
|
||||||
|
Now = self.Torchlight().Master.Loop.time()
|
||||||
|
Duration = 0.0
|
||||||
|
|
||||||
|
for Key, Clip in list(self.LastClips.items()):
|
||||||
|
if not Clip["timestamp"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if Clip["timestamp"] + Clip["duration"] + self.Torchlight().Config["Advertiser"]["MaxSpan"] < Now:
|
||||||
|
if not Clip["active"]:
|
||||||
|
del self.LastClips[Key]
|
||||||
|
continue
|
||||||
|
|
||||||
|
Duration += Clip["duration"]
|
||||||
|
|
||||||
|
self.NextAdStop -= Delta
|
||||||
|
CeilDur = math.ceil(Duration)
|
||||||
|
if CeilDur > self.AdStop and self.NextAdStop <= 0 and CeilDur % self.Torchlight().Config["Advertiser"]["AdStop"] == 0:
|
||||||
|
self.Torchlight().SayChat("Hint: Type \x07FF0000!stop\x01 to stop all currently playing sounds.")
|
||||||
|
self.AdStop = CeilDur
|
||||||
|
self.NextAdStop = 0
|
||||||
|
elif CeilDur < self.AdStop:
|
||||||
|
self.AdStop = 0
|
||||||
|
self.NextAdStop = self.Torchlight().Config["Advertiser"]["AdStop"] / 2
|
||||||
|
|
||||||
|
def OnPlay(self, clip):
|
||||||
|
Now = self.Torchlight().Master.Loop.time()
|
||||||
|
self.LastClips[hash(clip)] = dict({"timestamp": Now, "duration": 0.0, "dominant": False, "active": True})
|
||||||
|
|
||||||
|
HasDominant = False
|
||||||
|
for Key, Clip in self.LastClips.items():
|
||||||
|
if Clip["dominant"]:
|
||||||
|
HasDominant = True
|
||||||
|
break
|
||||||
|
|
||||||
|
self.LastClips[hash(clip)]["dominant"] = not HasDominant
|
||||||
|
|
||||||
|
def OnStop(self, clip):
|
||||||
|
if hash(clip) not in self.LastClips:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.LastClips[hash(clip)]["active"] = False
|
||||||
|
|
||||||
|
if self.LastClips[hash(clip)]["dominant"]:
|
||||||
|
for Key, Clip in self.LastClips.items():
|
||||||
|
if Clip["active"]:
|
||||||
|
Clip["dominant"] = True
|
||||||
|
break
|
||||||
|
|
||||||
|
self.LastClips[hash(clip)]["dominant"] = False
|
||||||
|
|
||||||
|
def OnUpdate(self, clip, old_position, new_position):
|
||||||
|
Delta = new_position - old_position
|
||||||
|
Clip = self.LastClips[hash(clip)]
|
||||||
|
|
||||||
|
if not Clip["dominant"]:
|
||||||
|
return
|
||||||
|
|
||||||
|
Clip["duration"] += Delta
|
||||||
|
self.Think(Delta)
|
||||||
|
|
||||||
|
|
||||||
class AudioManager():
|
class AudioManager():
|
||||||
@ -110,6 +185,7 @@ class AudioManager():
|
|||||||
self.Logger = logging.getLogger(__class__.__name__)
|
self.Logger = logging.getLogger(__class__.__name__)
|
||||||
self.Torchlight = torchlight
|
self.Torchlight = torchlight
|
||||||
self.AntiSpam = AntiSpam(self)
|
self.AntiSpam = AntiSpam(self)
|
||||||
|
self.Advertiser = Advertiser(self)
|
||||||
self.AudioPlayerFactory = AudioPlayerFactory(self)
|
self.AudioPlayerFactory = AudioPlayerFactory(self)
|
||||||
self.AudioClips = []
|
self.AudioClips = []
|
||||||
|
|
||||||
@ -153,7 +229,7 @@ class AudioManager():
|
|||||||
if extra and not extra.lower() in AudioClip.Player.Name.lower():
|
if extra and not extra.lower() in AudioClip.Player.Name.lower():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not Level or Level < AudioClip.Level:
|
if not Level or (Level < AudioClip.Level and Level < self.Torchlight().Config["AntiSpam"]["StopLevel"]):
|
||||||
AudioClip.Stops.add(player.UserID)
|
AudioClip.Stops.add(player.UserID)
|
||||||
|
|
||||||
if len(AudioClip.Stops) >= 3:
|
if len(AudioClip.Stops) >= 3:
|
||||||
@ -188,11 +264,14 @@ class AudioManager():
|
|||||||
self.AudioClips.append(Clip)
|
self.AudioClips.append(Clip)
|
||||||
|
|
||||||
if not player.Access or player.Access["level"] < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]:
|
if not player.Access or player.Access["level"] < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]:
|
||||||
self.AntiSpam.RegisterClip(Clip)
|
|
||||||
Clip.AudioPlayer.AddCallback("Play", lambda *args: self.AntiSpam.OnPlay(Clip, *args))
|
Clip.AudioPlayer.AddCallback("Play", lambda *args: self.AntiSpam.OnPlay(Clip, *args))
|
||||||
Clip.AudioPlayer.AddCallback("Stop", lambda *args: self.AntiSpam.OnStop(Clip, *args))
|
Clip.AudioPlayer.AddCallback("Stop", lambda *args: self.AntiSpam.OnStop(Clip, *args))
|
||||||
Clip.AudioPlayer.AddCallback("Update", lambda *args: self.AntiSpam.OnUpdate(Clip, *args))
|
Clip.AudioPlayer.AddCallback("Update", lambda *args: self.AntiSpam.OnUpdate(Clip, *args))
|
||||||
|
|
||||||
|
Clip.AudioPlayer.AddCallback("Play", lambda *args: self.Advertiser.OnPlay(Clip, *args))
|
||||||
|
Clip.AudioPlayer.AddCallback("Stop", lambda *args: self.Advertiser.OnStop(Clip, *args))
|
||||||
|
Clip.AudioPlayer.AddCallback("Update", lambda *args: self.Advertiser.OnUpdate(Clip, *args))
|
||||||
|
|
||||||
return Clip
|
return Clip
|
||||||
|
|
||||||
def OnDisconnect(self, player):
|
def OnDisconnect(self, player):
|
||||||
|
0
Torchlight/CommandHandler.py
Normal file → Executable file
0
Torchlight/CommandHandler.py
Normal file → Executable file
426
Torchlight/Commands.py
Normal file → Executable file
426
Torchlight/Commands.py
Normal file → Executable file
@ -16,10 +16,26 @@ class BaseCommand():
|
|||||||
self.Triggers = []
|
self.Triggers = []
|
||||||
self.Level = 0
|
self.Level = 0
|
||||||
|
|
||||||
|
def check_chat_cooldown(self, player):
|
||||||
|
if player.ChatCooldown > self.Torchlight().Master.Loop.time():
|
||||||
|
cooldown = player.ChatCooldown - self.Torchlight().Master.Loop.time()
|
||||||
|
self.Torchlight().SayPrivate(player, "You're on cooldown for the next {0:.1f} seconds.".format(cooldown))
|
||||||
|
return True
|
||||||
|
|
||||||
|
def check_disabled(self, player):
|
||||||
|
Level = 0
|
||||||
|
if player.Access:
|
||||||
|
Level = player.Access["level"]
|
||||||
|
|
||||||
|
Disabled = self.Torchlight().Disabled
|
||||||
|
if Disabled and (Disabled > Level or Disabled == Level and Level < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]):
|
||||||
|
self.Torchlight().SayPrivate(player, "Torchlight is currently disabled!")
|
||||||
|
return True
|
||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name)
|
self.Logger.debug(sys._getframe().f_code.co_name)
|
||||||
|
|
||||||
### FILTER COMMANDS ###
|
|
||||||
class URLFilter(BaseCommand):
|
class URLFilter(BaseCommand):
|
||||||
Order = 1
|
Order = 1
|
||||||
import re
|
import re
|
||||||
@ -49,11 +65,16 @@ class URLFilter(BaseCommand):
|
|||||||
if TimeStr:
|
if TimeStr:
|
||||||
Time = Utils.ParseTime(TimeStr)
|
Time = Utils.ParseTime(TimeStr)
|
||||||
|
|
||||||
Proc = await asyncio.create_subprocess_exec("youtube-dl", "--dump-json", "-xg", url,
|
Proc = await asyncio.create_subprocess_exec("youtube-dl", "--dump-json", "-g", url,
|
||||||
stdout = asyncio.subprocess.PIPE)
|
stdout = asyncio.subprocess.PIPE)
|
||||||
Out, _ = await Proc.communicate()
|
Out, _ = await Proc.communicate()
|
||||||
|
|
||||||
url, Info = Out.split(b'\n', maxsplit = 1)
|
parts = Out.split(b'\n')
|
||||||
|
parts.pop() # trailing new line
|
||||||
|
|
||||||
|
Info = parts.pop()
|
||||||
|
url = parts.pop()
|
||||||
|
|
||||||
url = url.strip().decode("ascii")
|
url = url.strip().decode("ascii")
|
||||||
Info = self.json.loads(Info)
|
Info = self.json.loads(Info)
|
||||||
|
|
||||||
@ -119,16 +140,8 @@ class URLFilter(BaseCommand):
|
|||||||
asyncio.ensure_future(self.URLInfo(Url))
|
asyncio.ensure_future(self.URLInfo(Url))
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
### FILTER COMMANDS ###
|
|
||||||
|
|
||||||
### LEVEL 0 COMMANDS ###
|
def FormatAccess(Torchlight, player):
|
||||||
class Access(BaseCommand):
|
|
||||||
def __init__(self, torchlight):
|
|
||||||
super().__init__(torchlight)
|
|
||||||
self.Triggers = ["!access"] #, "!who", "!whois"]
|
|
||||||
self.Level = 0
|
|
||||||
|
|
||||||
def FormatAccess(self, player):
|
|
||||||
Answer = "#{0} \"{1}\"({2}) is ".format(player.UserID, player.Name, player.UniqueID)
|
Answer = "#{0} \"{1}\"({2}) is ".format(player.UserID, player.Name, player.UniqueID)
|
||||||
Level = str(0)
|
Level = str(0)
|
||||||
if player.Access:
|
if player.Access:
|
||||||
@ -137,9 +150,9 @@ class Access(BaseCommand):
|
|||||||
else:
|
else:
|
||||||
Answer += "not authenticated."
|
Answer += "not authenticated."
|
||||||
|
|
||||||
if Level in self.Torchlight().Config["AudioLimits"]:
|
if Level in Torchlight().Config["AudioLimits"]:
|
||||||
Uses = self.Torchlight().Config["AudioLimits"][Level]["Uses"]
|
Uses = Torchlight().Config["AudioLimits"][Level]["Uses"]
|
||||||
TotalTime = self.Torchlight().Config["AudioLimits"][Level]["TotalTime"]
|
TotalTime = Torchlight().Config["AudioLimits"][Level]["TotalTime"]
|
||||||
|
|
||||||
if Uses >= 0:
|
if Uses >= 0:
|
||||||
Answer += " Uses: {0}/{1}".format(player.Storage["Audio"]["Uses"], Uses)
|
Answer += " Uses: {0}/{1}".format(player.Storage["Audio"]["Uses"], Uses)
|
||||||
@ -148,20 +161,41 @@ class Access(BaseCommand):
|
|||||||
|
|
||||||
return Answer
|
return Answer
|
||||||
|
|
||||||
|
class Access(BaseCommand):
|
||||||
|
def __init__(self, torchlight):
|
||||||
|
super().__init__(torchlight)
|
||||||
|
self.Triggers = ["!access"]
|
||||||
|
self.Level = 0
|
||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
|
if self.check_chat_cooldown(player):
|
||||||
|
return -1
|
||||||
|
|
||||||
Count = 0
|
Count = 0
|
||||||
if message[0] == "!access":
|
if message[0] == "!access":
|
||||||
if message[1]:
|
if message[1]:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
self.Torchlight().SayChat(self.FormatAccess(player))
|
self.Torchlight().SayChat(FormatAccess(self.Torchlight, player), player)
|
||||||
|
|
||||||
elif message[0] == "!who":
|
return 0
|
||||||
|
|
||||||
|
class Who(BaseCommand):
|
||||||
|
def __init__(self, torchlight):
|
||||||
|
super().__init__(torchlight)
|
||||||
|
self.Triggers = ["!who", "!whois"]
|
||||||
|
self.Level = 1
|
||||||
|
|
||||||
|
async def _func(self, message, player):
|
||||||
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
|
Count = 0
|
||||||
|
if message[0] == "!who":
|
||||||
for Player in self.Torchlight().Players:
|
for Player in self.Torchlight().Players:
|
||||||
if Player.Name.lower().find(message[1].lower()) != -1:
|
if Player.Name.lower().find(message[1].lower()) != -1:
|
||||||
self.Torchlight().SayChat(self.FormatAccess(Player))
|
self.Torchlight().SayChat(FormatAccess(self.Torchlight, Player))
|
||||||
|
|
||||||
Count += 1
|
Count += 1
|
||||||
if Count >= 3:
|
if Count >= 3:
|
||||||
@ -172,7 +206,7 @@ class Access(BaseCommand):
|
|||||||
if Access["name"].lower().find(message[1].lower()) != -1:
|
if Access["name"].lower().find(message[1].lower()) != -1:
|
||||||
Player = self.Torchlight().Players.FindUniqueID(UniqueID)
|
Player = self.Torchlight().Players.FindUniqueID(UniqueID)
|
||||||
if Player:
|
if Player:
|
||||||
self.Torchlight().SayChat(self.FormatAccess(Player))
|
self.Torchlight().SayChat(FormatAccess(self.Torchlight, Player))
|
||||||
else:
|
else:
|
||||||
self.Torchlight().SayChat("#? \"{0}\"({1}) is level {2!s} is currently offline.".format(Access["name"], UniqueID, Access["level"]))
|
self.Torchlight().SayChat("#? \"{0}\"({1}) is level {2!s} is currently offline.".format(Access["name"], UniqueID, Access["level"]))
|
||||||
|
|
||||||
@ -181,34 +215,6 @@ class Access(BaseCommand):
|
|||||||
break
|
break
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
class Calculate(BaseCommand):
|
|
||||||
import urllib.parse
|
|
||||||
import aiohttp
|
|
||||||
import json
|
|
||||||
def __init__(self, torchlight):
|
|
||||||
super().__init__(torchlight)
|
|
||||||
self.Triggers = ["!c"]
|
|
||||||
self.Level = 0
|
|
||||||
|
|
||||||
async def Calculate(self, Params):
|
|
||||||
async with self.aiohttp.ClientSession() as session:
|
|
||||||
Response = await asyncio.wait_for(session.get("http://math.leftforliving.com/query", params=Params), 5)
|
|
||||||
if not Response:
|
|
||||||
return 1
|
|
||||||
|
|
||||||
Data = await asyncio.wait_for(Response.json(content_type = "text/json"), 5)
|
|
||||||
if not Data:
|
|
||||||
return 2
|
|
||||||
|
|
||||||
if not Data["error"]:
|
|
||||||
self.Torchlight().SayChat(Data["answer"])
|
|
||||||
return 0
|
|
||||||
|
|
||||||
async def _func(self, message, player):
|
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
|
||||||
Params = dict({"question": message[1]})
|
|
||||||
Ret = await self.Calculate(Params)
|
|
||||||
return Ret
|
|
||||||
|
|
||||||
class WolframAlpha(BaseCommand):
|
class WolframAlpha(BaseCommand):
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
@ -218,12 +224,12 @@ class WolframAlpha(BaseCommand):
|
|||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
super().__init__(torchlight)
|
super().__init__(torchlight)
|
||||||
self.Triggers = ["!cc"]
|
self.Triggers = ["!cc"]
|
||||||
self.Level = 0
|
self.Level = 3
|
||||||
|
|
||||||
def Clean(self, Text):
|
def Clean(self, Text):
|
||||||
return self.re.sub("[ ]{2,}", " ", Text.replace(' | ', ': ').replace('\n', ' | ').replace('~~', ' ≈ ')).strip()
|
return self.re.sub("[ ]{2,}", " ", Text.replace(' | ', ': ').replace('\n', ' | ').replace('~~', ' ≈ ')).strip()
|
||||||
|
|
||||||
async def Calculate(self, Params):
|
async def Calculate(self, Params, player):
|
||||||
async with self.aiohttp.ClientSession() as session:
|
async with self.aiohttp.ClientSession() as session:
|
||||||
Response = await asyncio.wait_for(session.get("http://api.wolframalpha.com/v2/query", params=Params), 10)
|
Response = await asyncio.wait_for(session.get("http://api.wolframalpha.com/v2/query", params=Params), 10)
|
||||||
if not Response:
|
if not Response:
|
||||||
@ -246,7 +252,7 @@ class WolframAlpha(BaseCommand):
|
|||||||
# no support for future stuff yet, TODO?
|
# no support for future stuff yet, TODO?
|
||||||
if not Didyoumeans:
|
if not Didyoumeans:
|
||||||
# If there's no pods, the question clearly wasn't understood
|
# If there's no pods, the question clearly wasn't understood
|
||||||
self.Torchlight().SayChat("Sorry, couldn't understand the question.")
|
self.Torchlight().SayChat("Sorry, couldn't understand the question.", player)
|
||||||
return 3
|
return 3
|
||||||
|
|
||||||
Options = []
|
Options = []
|
||||||
@ -254,39 +260,128 @@ class WolframAlpha(BaseCommand):
|
|||||||
Options.append("\"{0}\"".format(Didyoumean.text))
|
Options.append("\"{0}\"".format(Didyoumean.text))
|
||||||
Line = " or ".join(Options)
|
Line = " or ".join(Options)
|
||||||
Line = "Did you mean {0}?".format(Line)
|
Line = "Did you mean {0}?".format(Line)
|
||||||
self.Torchlight().SayChat(Line)
|
self.Torchlight().SayChat(Line, player)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# If there's only one pod with text, it's probably the answer
|
# If there's only one pod with text, it's probably the answer
|
||||||
# example: "integral x²"
|
# example: "integral x²"
|
||||||
if len(Pods) == 1:
|
if len(Pods) == 1:
|
||||||
Answer = self.Clean(Pods[0])
|
Answer = self.Clean(Pods[0])
|
||||||
self.Torchlight().SayChat(Answer)
|
self.Torchlight().SayChat(Answer, player)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
# If there's multiple pods, first is the question interpretation
|
# If there's multiple pods, first is the question interpretation
|
||||||
Question = self.Clean(Pods[0].replace(' | ', ' ').replace('\n', ' '))
|
Question = self.Clean(Pods[0].replace(' | ', ' ').replace('\n', ' '))
|
||||||
# and second is the best answer
|
# and second is the best answer
|
||||||
Answer = self.Clean(Pods[1])
|
Answer = self.Clean(Pods[1])
|
||||||
self.Torchlight().SayChat("{0} = {1}".format(Question, Answer))
|
self.Torchlight().SayChat("{0} = {1}".format(Question, Answer), player)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
Level = 0
|
if self.check_chat_cooldown(player):
|
||||||
if player.Access:
|
return -1
|
||||||
Level = player.Access["level"]
|
|
||||||
|
|
||||||
Disabled = self.Torchlight().Disabled
|
if self.check_disabled(player):
|
||||||
if Disabled and (Disabled > Level or Disabled == Level and Level < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]):
|
return -1
|
||||||
self.Torchlight().SayPrivate(player, "Torchlight is currently disabled!")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
Params = dict({"input": message[1], "appid": self.Torchlight().Config["WolframAPIKey"]})
|
Params = dict({"input": message[1], "appid": self.Torchlight().Config["WolframAPIKey"]})
|
||||||
Ret = await self.Calculate(Params)
|
Ret = await self.Calculate(Params, player)
|
||||||
return Ret
|
return Ret
|
||||||
|
|
||||||
|
|
||||||
|
class UrbanDictionary(BaseCommand):
|
||||||
|
import aiohttp
|
||||||
|
def __init__(self, torchlight):
|
||||||
|
super().__init__(torchlight)
|
||||||
|
self.Triggers = ["!define", "!ud"]
|
||||||
|
self.Level = 0
|
||||||
|
|
||||||
|
async def _func(self, message, player):
|
||||||
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
|
if self.check_chat_cooldown(player):
|
||||||
|
return -1
|
||||||
|
|
||||||
|
if self.check_disabled(player):
|
||||||
|
return -1
|
||||||
|
|
||||||
|
async with self.aiohttp.ClientSession() as session:
|
||||||
|
Response = await asyncio.wait_for(session.get("https://api.urbandictionary.com/v0/define?term={0}".format(message[1])), 5)
|
||||||
|
if not Response:
|
||||||
|
return 1
|
||||||
|
|
||||||
|
Data = await asyncio.wait_for(Response.json(), 5)
|
||||||
|
if not Data:
|
||||||
|
return 3
|
||||||
|
|
||||||
|
if not 'list' in Data or not Data["list"]:
|
||||||
|
self.Torchlight().SayChat("[UB] No definition found for: {}".format(message[1]), player)
|
||||||
|
return 4
|
||||||
|
|
||||||
|
def print_item(item):
|
||||||
|
self.Torchlight().SayChat("[UD] {word} ({thumbs_up}/{thumbs_down}): {definition}\n{example}".format(**item), player)
|
||||||
|
|
||||||
|
print_item(Data["list"][0])
|
||||||
|
|
||||||
|
|
||||||
|
class OpenWeather(BaseCommand):
|
||||||
|
import aiohttp
|
||||||
|
import geoip2.database
|
||||||
|
def __init__(self, torchlight):
|
||||||
|
super().__init__(torchlight)
|
||||||
|
self.GeoIP = self.geoip2.database.Reader("/usr/share/GeoIP/GeoLite2-City.mmdb")
|
||||||
|
self.Triggers = ["!w", "!vv"]
|
||||||
|
self.Level = 0
|
||||||
|
|
||||||
|
async def _func(self, message, player):
|
||||||
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
|
if self.check_chat_cooldown(player):
|
||||||
|
return -1
|
||||||
|
|
||||||
|
if self.check_disabled(player):
|
||||||
|
return -1
|
||||||
|
|
||||||
|
if not message[1]:
|
||||||
|
# Use GeoIP location
|
||||||
|
info = self.GeoIP.city(player.Address.split(":")[0])
|
||||||
|
Search = "lat={}&lon={}".format(info.location.latitude, info.location.longitude)
|
||||||
|
else:
|
||||||
|
Search = "q={}".format(message[1])
|
||||||
|
|
||||||
|
async with self.aiohttp.ClientSession() as session:
|
||||||
|
Response = await asyncio.wait_for(session.get("https://api.openweathermap.org/data/2.5/weather?APPID={0}&units=metric&{1}".format(
|
||||||
|
self.Torchlight().Config["OpenWeatherAPIKey"], Search)), 5)
|
||||||
|
if not Response:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
Data = await asyncio.wait_for(Response.json(), 5)
|
||||||
|
if not Data:
|
||||||
|
return 3
|
||||||
|
|
||||||
|
if Data["cod"] != 200:
|
||||||
|
self.Torchlight().SayPrivate(player, "[OW] {0}".format(Data["message"]))
|
||||||
|
return 5
|
||||||
|
|
||||||
|
degToCardinal = lambda d: ["N", "NE", "E", "SE", "S", "SW", "W", "NW"][int(((d + 22.5)/45.0) % 8)]
|
||||||
|
if "deg" in Data["wind"]:
|
||||||
|
windDir = degToCardinal(Data["wind"]["deg"])
|
||||||
|
else:
|
||||||
|
windDir = "?"
|
||||||
|
|
||||||
|
timezone = "{}{}".format('+' if Data["timezone"] > 0 else '', int(Data["timezone"] / 3600))
|
||||||
|
if Data["timezone"] % 3600 != 0:
|
||||||
|
timezone += ":{}".format((Data["timezone"] % 3600) / 60)
|
||||||
|
|
||||||
|
self.Torchlight().SayChat("[{}, {}](UTC{}) {}°C ({}/{}) {}: {} | Wind {} {}kph | Clouds: {}%% | Humidity: {}%%".format(Data["name"], Data["sys"]["country"], timezone,
|
||||||
|
Data["main"]["temp"], Data["main"]["temp_min"], Data["main"]["temp_max"], Data["weather"][0]["main"], Data["weather"][0]["description"],
|
||||||
|
windDir, Data["wind"]["speed"], Data["clouds"]["all"], Data["main"]["humidity"]), player)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
'''
|
||||||
class WUnderground(BaseCommand):
|
class WUnderground(BaseCommand):
|
||||||
import aiohttp
|
import aiohttp
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
@ -352,6 +447,7 @@ class WUnderground(BaseCommand):
|
|||||||
Observation["relative_humidity"]))
|
Observation["relative_humidity"]))
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
'''
|
||||||
|
|
||||||
class VoteDisable(BaseCommand):
|
class VoteDisable(BaseCommand):
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
@ -361,6 +457,7 @@ class VoteDisable(BaseCommand):
|
|||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
if self.Torchlight().Disabled:
|
if self.Torchlight().Disabled:
|
||||||
self.Torchlight().SayPrivate(player, "Torchlight is already disabled for the duration of this map.")
|
self.Torchlight().SayPrivate(player, "Torchlight is already disabled for the duration of this map.")
|
||||||
return
|
return
|
||||||
@ -375,70 +472,118 @@ class VoteDisable(BaseCommand):
|
|||||||
else:
|
else:
|
||||||
self.Torchlight().SayPrivate(player, "Torchlight needs {0} more disable votes to be disabled.".format(needed - have))
|
self.Torchlight().SayPrivate(player, "Torchlight needs {0} more disable votes to be disabled.".format(needed - have))
|
||||||
|
|
||||||
### LEVEL 0 COMMANDS ###
|
|
||||||
|
|
||||||
### LIMITED LEVEL 0 COMMANDS ###
|
|
||||||
class VoiceCommands(BaseCommand):
|
class VoiceCommands(BaseCommand):
|
||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
super().__init__(torchlight)
|
super().__init__(torchlight)
|
||||||
self.Triggers = ["!random"]
|
self.Triggers = ["!random", "!search"]
|
||||||
self.Level = 0
|
self.Level = 0
|
||||||
|
|
||||||
def LoadTriggers(self):
|
def LoadTriggers(self):
|
||||||
try:
|
try:
|
||||||
with open("triggers.json", "r") as fp:
|
with open("triggers.json", "r") as fp:
|
||||||
self.VoiceTriggers = self.json.load(fp)
|
Triggers = self.json.load(fp)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.Logger.error(sys._getframe().f_code.co_name + ' ' + str(e))
|
self.Logger.error(sys._getframe().f_code.co_name + ' ' + str(e))
|
||||||
self.Torchlight().SayChat(str(e))
|
self.Torchlight().SayChat(str(e))
|
||||||
|
|
||||||
|
self.VoiceTriggers = dict()
|
||||||
|
for Line in Triggers:
|
||||||
|
for Trigger in Line["names"]:
|
||||||
|
self.VoiceTriggers[Trigger] = Line["sound"]
|
||||||
|
|
||||||
def _setup(self):
|
def _setup(self):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name)
|
self.Logger.debug(sys._getframe().f_code.co_name)
|
||||||
self.LoadTriggers()
|
self.LoadTriggers()
|
||||||
for Triggers in self.VoiceTriggers:
|
for Trigger in self.VoiceTriggers.keys():
|
||||||
for Trigger in Triggers["names"]:
|
|
||||||
self.Triggers.append(Trigger)
|
self.Triggers.append(Trigger)
|
||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
|
if self.check_disabled(player):
|
||||||
|
return -1
|
||||||
|
|
||||||
Level = 0
|
Level = 0
|
||||||
if player.Access:
|
if player.Access:
|
||||||
Level = player.Access["level"]
|
Level = player.Access["level"]
|
||||||
|
|
||||||
Disabled = self.Torchlight().Disabled
|
message[0] = message[0].lower()
|
||||||
if Disabled and (Disabled > Level or Disabled == Level and Level < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]):
|
message[1] = message[1].lower()
|
||||||
self.Torchlight().SayPrivate(player, "Torchlight is currently disabled!")
|
if message[0][0] != '!' and Level < 2:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if message[0][0] == '_' and Level < 2:
|
if message[0] == "!search":
|
||||||
|
res = []
|
||||||
|
for key in self.VoiceTriggers.keys():
|
||||||
|
if message[1] in key.lower():
|
||||||
|
res.append(key)
|
||||||
|
self.Torchlight().SayPrivate(player, "{} results: {}".format(len(res), ", ".join(res)))
|
||||||
|
return 0
|
||||||
|
elif Level < 2:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if message[0] == "!random":
|
||||||
|
Trigger = self.random.choice(list(self.VoiceTriggers.values()))
|
||||||
|
if isinstance(Trigger, list):
|
||||||
|
Sound = self.random.choice(Trigger)
|
||||||
|
else:
|
||||||
|
Sound = Trigger
|
||||||
|
else:
|
||||||
|
Sounds = self.VoiceTriggers[message[0]]
|
||||||
|
|
||||||
|
try:
|
||||||
|
Num = int(message[1])
|
||||||
|
except ValueError:
|
||||||
|
Num = None
|
||||||
|
|
||||||
|
if isinstance(Sounds, list):
|
||||||
|
if Num and Num > 0 and Num <= len(Sounds):
|
||||||
|
Sound = Sounds[Num - 1]
|
||||||
|
|
||||||
|
elif message[1]:
|
||||||
|
searching = message[1].startswith('?')
|
||||||
|
search = message[1][1:] if searching else message[1]
|
||||||
|
Sound = None
|
||||||
|
names = []
|
||||||
|
matches = []
|
||||||
|
for sound in Sounds:
|
||||||
|
name = os.path.splitext(os.path.basename(sound))[0]
|
||||||
|
names.append(name)
|
||||||
|
|
||||||
|
if search and search in name.lower():
|
||||||
|
matches.append((name, sound))
|
||||||
|
|
||||||
|
if matches:
|
||||||
|
matches.sort(key=lambda t: len(t[0]))
|
||||||
|
mlist = [t[0] for t in matches]
|
||||||
|
if searching:
|
||||||
|
self.Torchlight().SayPrivate(player, "{} results: {}".format(len(mlist), ", ".join(mlist)))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
Sound = matches[0][1]
|
||||||
|
if len(matches) > 1:
|
||||||
|
self.Torchlight().SayPrivate(player, "Multiple matches: {}".format(", ".join(mlist)))
|
||||||
|
|
||||||
|
if not Sound and not Num:
|
||||||
|
if not searching:
|
||||||
|
self.Torchlight().SayPrivate(player, "Couldn't find {} in list of sounds.".format(message[1]))
|
||||||
|
self.Torchlight().SayPrivate(player, ", ".join(names))
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if message[0].lower() == "!random":
|
elif Num:
|
||||||
Trigger = self.random.choice(self.VoiceTriggers)
|
self.Torchlight().SayPrivate(player, "Number {} is out of bounds, max {}.".format(Num, len(Sounds)))
|
||||||
if isinstance(Trigger["sound"], list):
|
return 1
|
||||||
Sound = self.random.choice(Trigger["sound"])
|
|
||||||
else:
|
|
||||||
Sound = Trigger["sound"]
|
|
||||||
else:
|
|
||||||
for Trigger in self.VoiceTriggers:
|
|
||||||
for Name in Trigger["names"]:
|
|
||||||
if message[0].lower() == Name:
|
|
||||||
Num = Utils.GetNum(message[1])
|
|
||||||
if Num:
|
|
||||||
Num = int(Num)
|
|
||||||
|
|
||||||
if isinstance(Trigger["sound"], list):
|
|
||||||
if Num and Num > 0 and Num <= len(Trigger["sound"]):
|
|
||||||
Sound = Trigger["sound"][Num - 1]
|
|
||||||
else:
|
else:
|
||||||
Sound = self.random.choice(Trigger["sound"])
|
Sound = self.random.choice(Sounds)
|
||||||
else:
|
else:
|
||||||
Sound = Trigger["sound"]
|
Sound = Sounds
|
||||||
|
|
||||||
break
|
if not Sound:
|
||||||
|
return 1
|
||||||
|
|
||||||
Path = os.path.abspath(os.path.join("sounds", Sound))
|
Path = os.path.abspath(os.path.join("sounds", Sound))
|
||||||
AudioClip = self.Torchlight().AudioManager.AudioClip(player, "file://" + Path)
|
AudioClip = self.Torchlight().AudioManager.AudioClip(player, "file://" + Path)
|
||||||
@ -447,23 +592,21 @@ class VoiceCommands(BaseCommand):
|
|||||||
|
|
||||||
return AudioClip.Play()
|
return AudioClip.Play()
|
||||||
|
|
||||||
|
|
||||||
class YouTube(BaseCommand):
|
class YouTube(BaseCommand):
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
super().__init__(torchlight)
|
super().__init__(torchlight)
|
||||||
self.Triggers = ["!yt"]
|
self.Triggers = ["!yt"]
|
||||||
self.Level = 2
|
self.Level = 3
|
||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
Level = 0
|
if self.check_disabled(player):
|
||||||
if player.Access:
|
return -1
|
||||||
Level = player.Access["level"]
|
|
||||||
|
|
||||||
Disabled = self.Torchlight().Disabled
|
if self.Torchlight().LastUrl:
|
||||||
if Disabled and (Disabled > Level or Disabled == Level and Level < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]):
|
message[1] = message[1].replace("!last", self.Torchlight().LastUrl)
|
||||||
self.Torchlight().SayPrivate(player, "Torchlight is currently disabled!")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
Temp = DataHolder()
|
Temp = DataHolder()
|
||||||
Time = None
|
Time = None
|
||||||
@ -485,19 +628,13 @@ class YouTubeSearch(BaseCommand):
|
|||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
super().__init__(torchlight)
|
super().__init__(torchlight)
|
||||||
self.Triggers = ["!yts"]
|
self.Triggers = ["!yts"]
|
||||||
self.Level = 2
|
self.Level = 3
|
||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
Level = 0
|
if self.check_disabled(player):
|
||||||
if player.Access:
|
return -1
|
||||||
Level = player.Access["level"]
|
|
||||||
|
|
||||||
Disabled = self.Torchlight().Disabled
|
|
||||||
if Disabled and (Disabled > Level or Disabled == Level and Level < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]):
|
|
||||||
self.Torchlight().SayPrivate(player, "Torchlight is currently disabled!")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
Temp = DataHolder()
|
Temp = DataHolder()
|
||||||
Time = None
|
Time = None
|
||||||
@ -518,7 +655,7 @@ class YouTubeSearch(BaseCommand):
|
|||||||
|
|
||||||
if Info["extractor_key"] == "Youtube":
|
if Info["extractor_key"] == "Youtube":
|
||||||
self.Torchlight().SayChat("\x07E52D27[YouTube]\x01 {0} | {1} | {2}/5.00 | {3:,}".format(
|
self.Torchlight().SayChat("\x07E52D27[YouTube]\x01 {0} | {1} | {2}/5.00 | {3:,}".format(
|
||||||
Info["title"], str(self.datetime.timedelta(seconds = Info["duration"])), round(Info["average_rating"], 2), int(Info["view_count"])))
|
Info["title"], str(self.datetime.timedelta(seconds = Info["duration"])), round(Info["average_rating"] or 0, 2), int(Info["view_count"])))
|
||||||
|
|
||||||
AudioClip = self.Torchlight().AudioManager.AudioClip(player, url)
|
AudioClip = self.Torchlight().AudioManager.AudioClip(player, url)
|
||||||
if not AudioClip:
|
if not AudioClip:
|
||||||
@ -528,6 +665,7 @@ class YouTubeSearch(BaseCommand):
|
|||||||
|
|
||||||
return AudioClip.Play(Time)
|
return AudioClip.Play(Time)
|
||||||
|
|
||||||
|
|
||||||
class Say(BaseCommand):
|
class Say(BaseCommand):
|
||||||
import gtts
|
import gtts
|
||||||
import tempfile
|
import tempfile
|
||||||
@ -535,7 +673,7 @@ class Say(BaseCommand):
|
|||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
super().__init__(torchlight)
|
super().__init__(torchlight)
|
||||||
self.Triggers = [("!say", 4)]
|
self.Triggers = [("!say", 4)]
|
||||||
self.Level = 0
|
self.Level = 2
|
||||||
|
|
||||||
async def Say(self, player, language, message):
|
async def Say(self, player, language, message):
|
||||||
GTTS = self.gtts.gTTS(text = message, lang = language)
|
GTTS = self.gtts.gTTS(text = message, lang = language)
|
||||||
@ -559,14 +697,8 @@ class Say(BaseCommand):
|
|||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
Level = 0
|
if self.check_disabled(player):
|
||||||
if player.Access:
|
return -1
|
||||||
Level = player.Access["level"]
|
|
||||||
|
|
||||||
Disabled = self.Torchlight().Disabled
|
|
||||||
if Disabled and (Disabled > Level or Disabled == Level and Level < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]):
|
|
||||||
self.Torchlight().SayPrivate(player, "Torchlight is currently disabled!")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if not message[1]:
|
if not message[1]:
|
||||||
return 1
|
return 1
|
||||||
@ -581,6 +713,7 @@ class Say(BaseCommand):
|
|||||||
asyncio.ensure_future(self.Say(player, Language, message[1]))
|
asyncio.ensure_future(self.Say(player, Language, message[1]))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
'''
|
||||||
class DECTalk(BaseCommand):
|
class DECTalk(BaseCommand):
|
||||||
import tempfile
|
import tempfile
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
@ -612,20 +745,15 @@ class DECTalk(BaseCommand):
|
|||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
Level = 0
|
if self.check_disabled(player):
|
||||||
if player.Access:
|
return -1
|
||||||
Level = player.Access["level"]
|
|
||||||
|
|
||||||
Disabled = self.Torchlight().Disabled
|
|
||||||
if Disabled and (Disabled > Level or Disabled == Level and Level < self.Torchlight().Config["AntiSpam"]["ImmunityLevel"]):
|
|
||||||
self.Torchlight().SayPrivate(player, "Torchlight is currently disabled!")
|
|
||||||
return 1
|
|
||||||
|
|
||||||
if not message[1]:
|
if not message[1]:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
asyncio.ensure_future(self.Say(player, message[1]))
|
asyncio.ensure_future(self.Say(player, message[1]))
|
||||||
return 0
|
return 0
|
||||||
|
'''
|
||||||
|
|
||||||
class Stop(BaseCommand):
|
class Stop(BaseCommand):
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
@ -639,18 +767,7 @@ class Stop(BaseCommand):
|
|||||||
self.Torchlight().AudioManager.Stop(player, message[1])
|
self.Torchlight().AudioManager.Stop(player, message[1])
|
||||||
return True
|
return True
|
||||||
|
|
||||||
### LIMITED LEVEL 0 COMMANDS ###
|
|
||||||
|
|
||||||
|
|
||||||
### LEVEL 1 COMMANDS ###
|
|
||||||
### LEVEL 1 COMMANDS ###
|
|
||||||
|
|
||||||
|
|
||||||
### LEVEL 2 COMMANDS ###
|
|
||||||
### LEVEL 2 COMMANDS ###
|
|
||||||
|
|
||||||
|
|
||||||
### LEVEL 3 COMMANDS ###
|
|
||||||
class EnableDisable(BaseCommand):
|
class EnableDisable(BaseCommand):
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
super().__init__(torchlight)
|
super().__init__(torchlight)
|
||||||
@ -659,24 +776,24 @@ class EnableDisable(BaseCommand):
|
|||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
|
||||||
if message[0] == "!enable":
|
if message[0] == "!enable":
|
||||||
if self.Torchlight().Disabled:
|
if self.Torchlight().Disabled:
|
||||||
if self.Torchlight().Disabled > player.Access["level"]:
|
if self.Torchlight().Disabled > player.Access["level"]:
|
||||||
self.Torchlight().SayPrivate(player, "You don't have access to enable torchlight since it was disabled by a higher level user.")
|
self.Torchlight().SayPrivate(player, "You don't have access to enable torchlight, since it was disabled by a higher level user.")
|
||||||
return 1
|
return 1
|
||||||
self.Torchlight().SayChat("Torchlight has been enabled for the duration of this map - Type !disable to disable it again.")
|
self.Torchlight().SayChat("Torchlight has been enabled for the duration of this map - Type !disable to disable it again.")
|
||||||
|
|
||||||
self.Torchlight().Disabled = False
|
self.Torchlight().Disabled = False
|
||||||
|
|
||||||
elif message[0] == "!disable":
|
elif message[0] == "!disable":
|
||||||
if not self.Torchlight().Disabled:
|
if self.Torchlight().Disabled > player.Access["level"]:
|
||||||
|
self.Torchlight().SayPrivate(player, "You don't have access to disable torchlight, since it was already disabled by a higher level user.")
|
||||||
|
return 1
|
||||||
self.Torchlight().SayChat("Torchlight has been disabled for the duration of this map - Type !enable to enable it again.")
|
self.Torchlight().SayChat("Torchlight has been disabled for the duration of this map - Type !enable to enable it again.")
|
||||||
|
|
||||||
self.Torchlight().Disabled = player.Access["level"]
|
self.Torchlight().Disabled = player.Access["level"]
|
||||||
### LEVEL 3 COMMANDS ###
|
|
||||||
|
|
||||||
|
|
||||||
### LEVEL 4 COMMANDS ###
|
|
||||||
class AdminAccess(BaseCommand):
|
class AdminAccess(BaseCommand):
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
@ -782,15 +899,24 @@ class AdminAccess(BaseCommand):
|
|||||||
del self.Torchlight().Access[Player.UniqueID]
|
del self.Torchlight().Access[Player.UniqueID]
|
||||||
Player.Access = None
|
Player.Access = None
|
||||||
return 0
|
return 0
|
||||||
### LEVEL 4 COMMANDS ###
|
|
||||||
|
class Reload(BaseCommand):
|
||||||
|
def __init__(self, torchlight):
|
||||||
|
super().__init__(torchlight)
|
||||||
|
self.Triggers = ["!reload"]
|
||||||
|
self.Level = 4
|
||||||
|
|
||||||
|
async def _func(self, message, player):
|
||||||
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
|
self.Torchlight().Reload()
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
### LEVEL X COMMANDS ###
|
|
||||||
class Exec(BaseCommand):
|
class Exec(BaseCommand):
|
||||||
def __init__(self, torchlight):
|
def __init__(self, torchlight):
|
||||||
super().__init__(torchlight)
|
super().__init__(torchlight)
|
||||||
self.Triggers = ["!exec"]
|
self.Triggers = ["!exec"]
|
||||||
self.Level = 9
|
self.Level = 100
|
||||||
|
|
||||||
async def _func(self, message, player):
|
async def _func(self, message, player):
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
||||||
@ -801,15 +927,3 @@ class Exec(BaseCommand):
|
|||||||
return 1
|
return 1
|
||||||
self.Torchlight().SayChat(str(Response))
|
self.Torchlight().SayChat(str(Response))
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
class Reload(BaseCommand):
|
|
||||||
def __init__(self, torchlight):
|
|
||||||
super().__init__(torchlight)
|
|
||||||
self.Triggers = ["!reload"]
|
|
||||||
self.Level = 6
|
|
||||||
|
|
||||||
async def _func(self, message, player):
|
|
||||||
self.Logger.debug(sys._getframe().f_code.co_name + ' ' + str(message))
|
|
||||||
self.Torchlight().Reload()
|
|
||||||
return 0
|
|
||||||
### LEVEL X COMMANDS ###
|
|
||||||
|
7
Torchlight/Config.py
Normal file → Executable file
7
Torchlight/Config.py
Normal file → Executable file
@ -2,16 +2,21 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
class Config():
|
class Config():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.Logger = logging.getLogger(__class__.__name__)
|
self.Logger = logging.getLogger(__class__.__name__)
|
||||||
self.Config = dict()
|
self.Config = dict()
|
||||||
|
if len(sys.argv) >= 2:
|
||||||
|
self.ConfigPath = sys.argv[1]
|
||||||
|
else:
|
||||||
|
self.ConfigPath = "config.json"
|
||||||
self.Load()
|
self.Load()
|
||||||
|
|
||||||
def Load(self):
|
def Load(self):
|
||||||
try:
|
try:
|
||||||
with open("config.json", "r") as fp:
|
with open(self.ConfigPath, "r") as fp:
|
||||||
self.Config = json.load(fp)
|
self.Config = json.load(fp)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
self.Logger.error(sys._getframe().f_code.co_name + ' ' + str(e))
|
self.Logger.error(sys._getframe().f_code.co_name + ' ' + str(e))
|
||||||
|
0
Torchlight/Constants.py
Normal file → Executable file
0
Torchlight/Constants.py
Normal file → Executable file
4
Torchlight/FFmpegAudioPlayer.py
Normal file → Executable file
4
Torchlight/FFmpegAudioPlayer.py
Normal file → Executable file
@ -60,9 +60,9 @@ class FFmpegAudioPlayer():
|
|||||||
def PlayURI(self, uri, position, *args):
|
def PlayURI(self, uri, position, *args):
|
||||||
if position:
|
if position:
|
||||||
PosStr = str(datetime.timedelta(seconds = position))
|
PosStr = str(datetime.timedelta(seconds = position))
|
||||||
Command = ["/usr/bin/ffmpeg", "-ss", PosStr, "-i", uri, "-acodec", "pcm_s16le", "-ac", "1", "-ar", str(int(self.SampleRate)), "-f", "s16le", *args, "-"]
|
Command = ["/usr/bin/ffmpeg", "-ss", PosStr, "-i", uri, "-acodec", "pcm_s16le", "-ac", "1", "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn", *args, "-"]
|
||||||
else:
|
else:
|
||||||
Command = ["/usr/bin/ffmpeg", "-i", uri, "-acodec", "pcm_s16le", "-ac", "1", "-ar", str(int(self.SampleRate)), "-f", "s16le", *args, "-"]
|
Command = ["/usr/bin/ffmpeg", "-i", uri, "-acodec", "pcm_s16le", "-ac", "1", "-ar", str(int(self.SampleRate)), "-f", "s16le", "-vn", *args, "-"]
|
||||||
|
|
||||||
print(Command)
|
print(Command)
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
class GameEvents():
|
class GameEvents():
|
||||||
def __init__(self, master):
|
def __init__(self, master):
|
||||||
|
21
Torchlight/PlayerManager.py
Normal file → Executable file
21
Torchlight/PlayerManager.py
Normal file → Executable file
@ -15,6 +15,7 @@ class PlayerManager():
|
|||||||
|
|
||||||
self.Torchlight().GameEvents.HookEx("player_connect", self.Event_PlayerConnect)
|
self.Torchlight().GameEvents.HookEx("player_connect", self.Event_PlayerConnect)
|
||||||
self.Torchlight().GameEvents.HookEx("player_activate", self.Event_PlayerActivate)
|
self.Torchlight().GameEvents.HookEx("player_activate", self.Event_PlayerActivate)
|
||||||
|
self.Torchlight().Forwards.HookEx("OnClientPostAdminCheck", self.OnClientPostAdminCheck)
|
||||||
self.Torchlight().GameEvents.HookEx("player_info", self.Event_PlayerInfo)
|
self.Torchlight().GameEvents.HookEx("player_info", self.Event_PlayerInfo)
|
||||||
self.Torchlight().GameEvents.HookEx("player_disconnect", self.Event_PlayerDisconnect)
|
self.Torchlight().GameEvents.HookEx("player_disconnect", self.Event_PlayerDisconnect)
|
||||||
self.Torchlight().GameEvents.HookEx("server_spawn", self.Event_ServerSpawn)
|
self.Torchlight().GameEvents.HookEx("server_spawn", self.Event_ServerSpawn)
|
||||||
@ -23,7 +24,8 @@ class PlayerManager():
|
|||||||
index += 1
|
index += 1
|
||||||
self.Logger.info("OnConnect(name={0}, index={1}, userid={2}, networkid={3}, address={4}, bot={5})"
|
self.Logger.info("OnConnect(name={0}, index={1}, userid={2}, networkid={3}, address={4}, bot={5})"
|
||||||
.format(name, index, userid, networkid, address, bot))
|
.format(name, index, userid, networkid, address, bot))
|
||||||
assert self.Players[index] == None
|
if self.Players[index] != None:
|
||||||
|
self.Logger.error("!!! Player already exists, overwriting !!!")
|
||||||
|
|
||||||
self.Players[index] = self.Player(self, index, userid, networkid, address, name)
|
self.Players[index] = self.Player(self, index, userid, networkid, address, name)
|
||||||
self.Players[index].OnConnect()
|
self.Players[index].OnConnect()
|
||||||
@ -35,6 +37,11 @@ class PlayerManager():
|
|||||||
|
|
||||||
self.Players[index].OnActivate()
|
self.Players[index].OnActivate()
|
||||||
|
|
||||||
|
def OnClientPostAdminCheck(self, client):
|
||||||
|
self.Logger.info("OnClientPostAdminCheck(client={0})".format(client))
|
||||||
|
|
||||||
|
asyncio.ensure_future(self.Players[client].OnClientPostAdminCheck())
|
||||||
|
|
||||||
def Event_PlayerInfo(self, name, index, userid, networkid, bot):
|
def Event_PlayerInfo(self, name, index, userid, networkid, bot):
|
||||||
index += 1
|
index += 1
|
||||||
self.Logger.info("OnInfo(name={0}, index={1}, userid={2}, networkid={3}, bot={4})"
|
self.Logger.info("OnInfo(name={0}, index={1}, userid={2}, networkid={3}, bot={4})"
|
||||||
@ -157,6 +164,7 @@ class PlayerManager():
|
|||||||
self.Admin = self.PlayerManager.Admin()
|
self.Admin = self.PlayerManager.Admin()
|
||||||
self.Storage = None
|
self.Storage = None
|
||||||
self.Active = False
|
self.Active = False
|
||||||
|
self.ChatCooldown = 0
|
||||||
|
|
||||||
def OnConnect(self):
|
def OnConnect(self):
|
||||||
self.Storage = self.PlayerManager.Storage[self.UniqueID]
|
self.Storage = self.PlayerManager.Storage[self.UniqueID]
|
||||||
@ -168,17 +176,22 @@ class PlayerManager():
|
|||||||
|
|
||||||
def OnActivate(self):
|
def OnActivate(self):
|
||||||
self.Active = True
|
self.Active = True
|
||||||
asyncio.ensure_future(self.OnPostActivate())
|
|
||||||
|
|
||||||
async def OnPostActivate(self):
|
async def OnClientPostAdminCheck(self):
|
||||||
self.Admin._FlagBits = (await self.Torchlight().API.GetUserFlagBits(self.Index))["result"]
|
self.Admin._FlagBits = (await self.Torchlight().API.GetUserFlagBits(self.Index))["result"]
|
||||||
self.PlayerManager.Logger.info("#{0} \"{1}\"({2}) FlagBits: {3}".format(self.UserID, self.Name, self.UniqueID, self.Admin._FlagBits))
|
self.PlayerManager.Logger.info("#{0} \"{1}\"({2}) FlagBits: {3}".format(self.UserID, self.Name, self.UniqueID, self.Admin._FlagBits))
|
||||||
if not self.Access:
|
if not self.Access:
|
||||||
if self.Admin.Generic():
|
if self.Admin.RCON():
|
||||||
|
self.Access = dict({"level": 6, "name": "SAdmin"})
|
||||||
|
elif self.Admin.Generic():
|
||||||
self.Access = dict({"level": 3, "name": "Admin"})
|
self.Access = dict({"level": 3, "name": "Admin"})
|
||||||
elif self.Admin.Custom1():
|
elif self.Admin.Custom1():
|
||||||
self.Access = dict({"level": 1, "name": "VIP"})
|
self.Access = dict({"level": 1, "name": "VIP"})
|
||||||
|
|
||||||
|
if self.PlayerManager.Torchlight().Config["DefaultLevel"]:
|
||||||
|
if self.Access and self.Access["level"] < self.PlayerManager.Torchlight().Config["DefaultLevel"]:
|
||||||
|
self.Access = dict({"level": self.PlayerManager.Torchlight().Config["DefaultLevel"], "name": "Default"})
|
||||||
|
|
||||||
def OnInfo(self, name):
|
def OnInfo(self, name):
|
||||||
self.Name = name
|
self.Name = name
|
||||||
|
|
||||||
|
0
Torchlight/SourceModAPI.py
Normal file → Executable file
0
Torchlight/SourceModAPI.py
Normal file → Executable file
0
Torchlight/SourceRCONServer.py
Normal file → Executable file
0
Torchlight/SourceRCONServer.py
Normal file → Executable file
159
Torchlight/Subscribe.py
Executable file
159
Torchlight/Subscribe.py
Executable file
@ -0,0 +1,159 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
class SubscribeBase():
|
||||||
|
def __init__(self, master, module):
|
||||||
|
self.Logger = logging.getLogger(__class__.__name__)
|
||||||
|
self.Torchlight = master
|
||||||
|
self.Module = module
|
||||||
|
|
||||||
|
self.Callbacks = {}
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if not len(self.Callbacks) or not self.Torchlight():
|
||||||
|
return
|
||||||
|
|
||||||
|
Obj = {
|
||||||
|
"method": "unsubscribe",
|
||||||
|
"module": self.Module,
|
||||||
|
"events": self.Callbacks.keys()
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncio.ensure_future(self.Torchlight().Send(Obj))
|
||||||
|
|
||||||
|
async def _Register(self, events):
|
||||||
|
if type(events) is not list:
|
||||||
|
events = [ events ]
|
||||||
|
|
||||||
|
Obj = {
|
||||||
|
"method": "subscribe",
|
||||||
|
"module": self.Module,
|
||||||
|
"events": events
|
||||||
|
}
|
||||||
|
|
||||||
|
Res = await self.Torchlight().Send(Obj)
|
||||||
|
|
||||||
|
Ret = []
|
||||||
|
for i, ret in enumerate(Res["events"]):
|
||||||
|
if ret >= 0:
|
||||||
|
Ret.append(True)
|
||||||
|
if not events[i] in self.Callbacks:
|
||||||
|
self.Callbacks[events[i]] = set()
|
||||||
|
else:
|
||||||
|
Ret.append(False)
|
||||||
|
|
||||||
|
if len(Ret) == 1:
|
||||||
|
Ret = Ret[0]
|
||||||
|
return Ret
|
||||||
|
|
||||||
|
async def _Unregister(self, events):
|
||||||
|
if type(events) is not list:
|
||||||
|
events = [ events ]
|
||||||
|
|
||||||
|
Obj = {
|
||||||
|
"method": "unsubscribe",
|
||||||
|
"module": self.Module,
|
||||||
|
"events": events
|
||||||
|
}
|
||||||
|
|
||||||
|
Res = await self.Torchlight().Send(Obj)
|
||||||
|
|
||||||
|
Ret = []
|
||||||
|
for i, ret in enumerate(Res["events"]):
|
||||||
|
if ret >= 0:
|
||||||
|
Ret.append(True)
|
||||||
|
if events[i] in self.Callbacks:
|
||||||
|
del self.Callbacks[events[i]]
|
||||||
|
else:
|
||||||
|
Ret.append(False)
|
||||||
|
|
||||||
|
if len(Ret) == 1:
|
||||||
|
Ret = Ret[0]
|
||||||
|
return Ret
|
||||||
|
|
||||||
|
def HookEx(self, event, callback):
|
||||||
|
asyncio.ensure_future(self.Hook(event, callback))
|
||||||
|
|
||||||
|
def UnhookEx(self, event, callback):
|
||||||
|
asyncio.ensure_future(self.Unhook(event, callback))
|
||||||
|
|
||||||
|
def ReplayEx(self, events):
|
||||||
|
asyncio.ensure_future(self.Replay(events))
|
||||||
|
|
||||||
|
async def Hook(self, event, callback):
|
||||||
|
if not event in self.Callbacks:
|
||||||
|
if not await self._Register(event):
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.Callbacks[event].add(callback)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def Unhook(self, event, callback):
|
||||||
|
if not event in self.Callbacks:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if not callback in self.Callbacks[event]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.Callbacks[event].discard(callback)
|
||||||
|
|
||||||
|
if len(a) == 0:
|
||||||
|
return await self._Unregister(event)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def Replay(self, events):
|
||||||
|
if type(events) is not list:
|
||||||
|
events = [ events ]
|
||||||
|
|
||||||
|
for event in events[:]:
|
||||||
|
if not event in self.Callbacks:
|
||||||
|
events.remove(event)
|
||||||
|
|
||||||
|
Obj = {
|
||||||
|
"method": "replay",
|
||||||
|
"module": self.Module,
|
||||||
|
"events": events
|
||||||
|
}
|
||||||
|
|
||||||
|
Res = await self.Torchlight().Send(Obj)
|
||||||
|
|
||||||
|
Ret = []
|
||||||
|
for i, ret in enumerate(Res["events"]):
|
||||||
|
if ret >= 0:
|
||||||
|
Ret.append(True)
|
||||||
|
else:
|
||||||
|
Ret.append(False)
|
||||||
|
|
||||||
|
if len(Ret) == 1:
|
||||||
|
Ret = Ret[0]
|
||||||
|
return Ret
|
||||||
|
|
||||||
|
def OnPublish(self, obj):
|
||||||
|
Event = obj["event"]
|
||||||
|
|
||||||
|
if not Event["name"] in self.Callbacks:
|
||||||
|
return False
|
||||||
|
|
||||||
|
Callbacks = self.Callbacks[Event["name"]]
|
||||||
|
|
||||||
|
for Callback in Callbacks:
|
||||||
|
try:
|
||||||
|
Callback(**Event["data"])
|
||||||
|
except Exception as e:
|
||||||
|
self.Logger.error(traceback.format_exc())
|
||||||
|
self.Logger.error(Event)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class GameEvents(SubscribeBase):
|
||||||
|
def __init__(self, master):
|
||||||
|
super().__init__(master, "gameevents")
|
||||||
|
|
||||||
|
class Forwards(SubscribeBase):
|
||||||
|
def __init__(self, master):
|
||||||
|
super().__init__(master, "forwards")
|
28
Torchlight/Torchlight.py
Normal file → Executable file
28
Torchlight/Torchlight.py
Normal file → Executable file
@ -12,7 +12,7 @@ import textwrap
|
|||||||
from .AsyncClient import AsyncClient
|
from .AsyncClient import AsyncClient
|
||||||
|
|
||||||
from .SourceModAPI import SourceModAPI
|
from .SourceModAPI import SourceModAPI
|
||||||
from .GameEvents import GameEvents
|
from .Subscribe import GameEvents, Forwards
|
||||||
|
|
||||||
from .Utils import Utils
|
from .Utils import Utils
|
||||||
from .Config import Config
|
from .Config import Config
|
||||||
@ -30,6 +30,7 @@ class Torchlight():
|
|||||||
|
|
||||||
self.API = SourceModAPI(self.WeakSelf)
|
self.API = SourceModAPI(self.WeakSelf)
|
||||||
self.GameEvents = GameEvents(self.WeakSelf)
|
self.GameEvents = GameEvents(self.WeakSelf)
|
||||||
|
self.Forwards = Forwards(self.WeakSelf)
|
||||||
|
|
||||||
self.DisableVotes = set()
|
self.DisableVotes = set()
|
||||||
self.Disabled = 0
|
self.Disabled = 0
|
||||||
@ -49,7 +50,7 @@ class Torchlight():
|
|||||||
self.GameEvents.HookEx("server_spawn", self.Event_ServerSpawn)
|
self.GameEvents.HookEx("server_spawn", self.Event_ServerSpawn)
|
||||||
self.GameEvents.HookEx("player_say", self.Event_PlayerSay)
|
self.GameEvents.HookEx("player_say", self.Event_PlayerSay)
|
||||||
|
|
||||||
def SayChat(self, message):
|
def SayChat(self, message, player=None):
|
||||||
message = "\x0700FFFA[Torchlight]: \x01{0}".format(message)
|
message = "\x0700FFFA[Torchlight]: \x01{0}".format(message)
|
||||||
if len(message) > 976:
|
if len(message) > 976:
|
||||||
message = message[:973] + "..."
|
message = message[:973] + "..."
|
||||||
@ -57,8 +58,25 @@ class Torchlight():
|
|||||||
for line in lines:
|
for line in lines:
|
||||||
asyncio.ensure_future(self.API.PrintToChatAll(line))
|
asyncio.ensure_future(self.API.PrintToChatAll(line))
|
||||||
|
|
||||||
|
if player:
|
||||||
|
Level = 0
|
||||||
|
if player.Access:
|
||||||
|
Level = player.Access["level"]
|
||||||
|
|
||||||
|
if Level < self.Config["AntiSpam"]["ImmunityLevel"]:
|
||||||
|
cooldown = len(lines) * self.Config["AntiSpam"]["ChatCooldown"]
|
||||||
|
if player.ChatCooldown > self.Master.Loop.time():
|
||||||
|
player.ChatCooldown += cooldown
|
||||||
|
else:
|
||||||
|
player.ChatCooldown = self.Master.Loop.time() + cooldown
|
||||||
|
|
||||||
def SayPrivate(self, player, message):
|
def SayPrivate(self, player, message):
|
||||||
asyncio.ensure_future(self.API.PrintToChat(player.Index, "\x0700FFFA[Torchlight]: \x01{0}".format(message)))
|
message = "\x0700FFFA[Torchlight]: \x01{0}".format(message)
|
||||||
|
if len(message) > 976:
|
||||||
|
message = message[:973] + "..."
|
||||||
|
lines = textwrap.wrap(message, 244, break_long_words = True)
|
||||||
|
for line in lines:
|
||||||
|
asyncio.ensure_future(self.API.PrintToChat(player.Index, line))
|
||||||
|
|
||||||
def Reload(self):
|
def Reload(self):
|
||||||
self.Config.Load()
|
self.Config.Load()
|
||||||
@ -70,6 +88,8 @@ class Torchlight():
|
|||||||
def OnPublish(self, obj):
|
def OnPublish(self, obj):
|
||||||
if obj["module"] == "gameevents":
|
if obj["module"] == "gameevents":
|
||||||
self.GameEvents.OnPublish(obj)
|
self.GameEvents.OnPublish(obj)
|
||||||
|
elif obj["module"] == "forwards":
|
||||||
|
self.Forwards.OnPublish(obj)
|
||||||
|
|
||||||
def Event_ServerSpawn(self, hostname, address, ip, port, game, mapname, maxplayers, os, dedicated, password):
|
def Event_ServerSpawn(self, hostname, address, ip, port, game, mapname, maxplayers, os, dedicated, password):
|
||||||
self.DisableVotes = set()
|
self.DisableVotes = set()
|
||||||
@ -105,11 +125,13 @@ class TorchlightHandler():
|
|||||||
|
|
||||||
# Pre Hook for late load
|
# Pre Hook for late load
|
||||||
await self.Torchlight.GameEvents._Register(["player_connect", "player_activate"])
|
await self.Torchlight.GameEvents._Register(["player_connect", "player_activate"])
|
||||||
|
await self.Torchlight.Forwards._Register(["OnClientPostAdminCheck"])
|
||||||
|
|
||||||
self.Torchlight.InitModules()
|
self.Torchlight.InitModules()
|
||||||
|
|
||||||
# Late load
|
# Late load
|
||||||
await self.Torchlight.GameEvents.Replay(["player_connect", "player_activate"])
|
await self.Torchlight.GameEvents.Replay(["player_connect", "player_activate"])
|
||||||
|
await self.Torchlight.Forwards.Replay(["OnClientPostAdminCheck"])
|
||||||
|
|
||||||
async def Send(self, data):
|
async def Send(self, data):
|
||||||
return await self._Client.Send(data)
|
return await self._Client.Send(data)
|
||||||
|
0
Torchlight/Utils.py
Normal file → Executable file
0
Torchlight/Utils.py
Normal file → Executable file
0
Torchlight/__init__.py
Normal file → Executable file
0
Torchlight/__init__.py
Normal file → Executable file
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"[U:1:51174697]": {
|
"[U:1:51174697]": {
|
||||||
"name": "BotoX",
|
"name": "BotoX",
|
||||||
"level": 10
|
"level": 100
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,7 +3,7 @@
|
|||||||
{
|
{
|
||||||
"Host": "10.0.0.101",
|
"Host": "10.0.0.101",
|
||||||
"Port": 27020,
|
"Port": 27020,
|
||||||
"SampleRate": 48000
|
"SampleRate": 22050
|
||||||
},
|
},
|
||||||
"SMAPIServer":
|
"SMAPIServer":
|
||||||
{
|
{
|
||||||
@ -30,10 +30,12 @@
|
|||||||
},
|
},
|
||||||
"AntiSpam":
|
"AntiSpam":
|
||||||
{
|
{
|
||||||
|
"ImmunityLevel": 5,
|
||||||
"MaxUsageSpan": 60,
|
"MaxUsageSpan": 60,
|
||||||
"MaxUsageTime": 10,
|
"MaxUsageTime": 10,
|
||||||
"PunishDelay": 60,
|
"PunishDelay": 60,
|
||||||
"ImmunityLevel": 4
|
"StopLevel": 3,
|
||||||
|
"ChatCooldown": 15
|
||||||
},
|
},
|
||||||
|
|
||||||
"TorchRCON":
|
"TorchRCON":
|
||||||
@ -44,5 +46,6 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"WolframAPIKey": "***",
|
"WolframAPIKey": "***",
|
||||||
"WundergroundAPIKey": "***"
|
"WundergroundAPIKey": "***",
|
||||||
|
"OpenWeatherAPIKey": "***"
|
||||||
}
|
}
|
||||||
|
6
main.py
6
main.py
@ -15,7 +15,11 @@ import Torchlight.Torchlight
|
|||||||
from Torchlight.SourceRCONServer import SourceRCONServer
|
from Torchlight.SourceRCONServer import SourceRCONServer
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
logging.basicConfig(level = logging.DEBUG)
|
logging.basicConfig(
|
||||||
|
level = logging.DEBUG,
|
||||||
|
format = "[%(asctime)s] %(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s",
|
||||||
|
datefmt = "%H:%M:%S"
|
||||||
|
)
|
||||||
|
|
||||||
Loop = asyncio.get_event_loop()
|
Loop = asyncio.get_event_loop()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user