Advertisement
Guest User

Untitled

a guest
Apr 24th, 2019
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.88 KB | None | 0 0
  1. #---------------------------------------
  2. #   Import Libraries
  3. #---------------------------------------
  4. import sys
  5. import clr
  6. # import urllib2
  7. import time
  8. import datetime
  9. import os
  10. import json
  11. import cgi
  12. import codecs
  13. import os
  14.  
  15.  
  16. #---------------------------------------
  17. #   [Required]  Script Information
  18. #---------------------------------------
  19. ScriptName = "TTS Announcer"
  20. Website = "https://burnysc2.github.io"
  21. Creator = "Brain & Burny"
  22. Version = "1.1.0"
  23. Description = "Text-to-Speech Announcer"
  24.  
  25. #---------------------------------------
  26. #   Set Variables
  27. #---------------------------------------
  28. configFile = "TTSAnnouncer.json"
  29. users = {}
  30. settings = {}
  31.  
  32. convertPowerLevelToInt = {
  33.     "Everyone": 0,
  34.     "Regular": 1,
  35.     "Sub": 2,
  36.     "Mod": 3,
  37.     "Streamer": 4,
  38. }
  39.  
  40. responseVariables = {
  41.     "$user": "", # user name
  42.     "$userPoints": "", # amount of currency the user has
  43.     "$streamer": "", # name of the streamer
  44.     "$currencyName": "", # channel currency
  45.     "$pointsCost": "", # how many points tts command costs
  46.     "$maxUserQueue": "", # how many tts entries per user there can be in a queue
  47.     "$maxGlobalQueue": "", # how many tts entries totally there can be in a queue
  48.     "$waitSeconds": "", # how many seconds have to pass before a user can queue a new tts command
  49.     "$characterLimit": "", # max length of a tts entry
  50. }
  51.  
  52. tts = {
  53.     "queue": [],
  54.     "timeUntilReady": 0,
  55.     "timeOfLastTick": time.time(),
  56.     "globalCooldownUntil": 1,
  57.     "generateKeyButtonClicked": 0,
  58.     "pathUniqueKey": os.path.join(os.path.dirname(__file__), "uniqueKey.json"),
  59.     "uniqueKey": "",
  60. }
  61.  
  62. # https://warp.world/scripts/tts-message
  63. voices = {  # https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes
  64.     "af": "Afrikaans Male",
  65.     "sq": "Albanian Male",
  66.     "ar": "Arabic Female",
  67.     "hy": "Armenian Male",
  68.     "aus": "Australian Female",
  69.     "bs": "Bosnian Male",
  70.     "pt2": "Brazilian Portuguese Female",
  71.     "ca": "Catalan Male",
  72.     "zh": "Chinese Female",
  73.     "tai": "Chinese Taiwan Female",
  74.     "hr": "Croatian Male",
  75.     "cs": "Czech Female",
  76.     "da": "Danish Female",
  77.     "de": "Deutsch Female",
  78.     "nl": "Dutch Female",
  79.     "eo": "Esperanto Male",
  80.     "fi": "Finnish Female",
  81.     "fr": "French Female",
  82.     "el": "Greek Female",
  83.     "hi": "Hindi Female",
  84.     "hu": "Hungarian Female",
  85.     "is": "Icelandic Male",
  86.     "id": "Indonesian Female",
  87.     "it": "Italian Female",
  88.     "ja": "Japanese Female",
  89.     "ko": "Korean Female",
  90.     "la": "Latin Female",
  91.     "lv": "Latvian Male",
  92.     "mk": "Macedonian Male",
  93.     "ro": "Moldavian Male",
  94.     "mo": "Montenegrin Male",
  95.     "no": "Norwegian Female", # disabled because it was super loud compared to the other voices
  96.     "pl": "Polish Female",
  97.     "pt": "Portuguese Female",
  98.     "ro": "Romanian Male",
  99.     "ru": "Russian Female",
  100.     "sr": "Serbian Male",
  101.     "srhr": "Serbo-Croatian Male",
  102.     "sk": "Slovak Female",
  103.     "es": "Spanish Female",
  104.     "es2": "Spanish Latin American Female",
  105.     "sw": "Swahili Male",
  106.     "sv": "Swedish Female",
  107.     "ta": "Tamil Male",
  108.     "th": "Thai Female",
  109.     "tr": "Turkish Female",
  110.     "en": "UK English Female",
  111.     "us": "US English Female",
  112.     "vi": "Vietnamese Male",
  113.     "cy": "Welsh Male",
  114. }
  115.  
  116. #---------------------------------------
  117. #   [Required] Intialize Data (Only called on Load)
  118. #---------------------------------------
  119.  
  120.  
  121. def Init():
  122.     global settings, voices, responseVariables, convertPowerLevelToInt, tts
  123.     path = os.path.dirname(__file__)
  124.  
  125.     try:
  126.         with codecs.open(os.path.join(path, configFile), encoding='utf-8-sig', mode='r') as file:
  127.             settings = json.load(file, encoding='utf-8-sig')
  128.         settings.update({
  129.             "messageColor": "ffffff",
  130.             "fontColor": "4141f4",
  131.             "fontSize": "32",
  132.             "fontOutlineColor": "42f47d",
  133.             "googleFont": "Roboto",
  134.             # "defaultVoice": "US English Female",
  135.             "playAlert": "false",
  136.         })
  137.         voices[""] = settings["defaultVoice"]
  138.         # settings["randomKey"] = settings["randomKey"].strip() #removes whitespace left and right
  139.         settings["powerLevelInt"] = convertPowerLevelToInt[settings["minPowerLevel"]]
  140.         settings["volume"] = int(settings.get("volume", 25))
  141.         settings["blackWordFilter"] = settings["blackWordFilter"].replace(" ","").split(",")
  142.         if settings["blackWordFilter"] == [""]:
  143.             settings["blackWordFilter"] = []
  144.         # settings["userPointsCost"] = max(0, settings["userPointsCost"])
  145.         # settings["userCooldown"] = max(0, settings["userCooldown"])
  146.         # settings["userMaxQueues"] = max(0, settings["userMaxQueues"])
  147.  
  148.         settings["enabledVoices"] = {"": settings["defaultVoice"]}
  149.         for key, value in voices.items():
  150.             if settings.get("language" + key, False):
  151.                 settings["enabledVoices"][key] = value
  152.  
  153.         responseVariables["$streamer"] = Parent.GetDisplayName(Parent.GetChannelName())
  154.         responseVariables["$currencyName"] = Parent.GetCurrencyName()
  155.         responseVariables["$pointsCost"] = settings["userPointsCost"]
  156.         responseVariables["$maxUserQueue"] = settings["userMaxQueues"]
  157.         responseVariables["$maxGlobalQueue"] = settings["globalMaxQueues"]
  158.         responseVariables["$waitSeconds"] = settings["userCooldown"]
  159.         responseVariables["$characterLimit"] = settings["userMaxMessageLength"]
  160.         responseVariables["$helpCommand"] = settings["helpCommand"]
  161.         settings["settingsLoaded"] = True
  162.     except:
  163.         pass
  164.  
  165.     try:
  166.         with codecs.open(tts["pathUniqueKey"], encoding='utf-8-sig', mode='r') as file:
  167.             tts["uniqueKey"] = json.load(file)["uniqueKey"]
  168.     except:
  169.         tts["uniqueKey"] = ""
  170.         pass
  171.        
  172.     return
  173.  
  174. #---------------------------------------
  175. # Reload Settings on Save
  176. #---------------------------------------
  177. def ReloadSettings(jsonData):
  178.     Init()
  179.     return
  180.  
  181. #---------------------------------------
  182. #   [Required] Execute Data / Process Messages
  183. #---------------------------------------
  184. def Execute(data):
  185.     global tts, settings
  186.    
  187.     # if settings["enabledTTS"]:
  188.     if settings.get("settingsLoaded", False):
  189.         if data.IsChatMessage():
  190.             responseVariables["$user"] = Parent.GetDisplayName(data.User)
  191.             responseVariables["$userPoints"] = Parent.GetPoints(data.User)
  192.            
  193.             messagesOfUser = [x for x in tts["queue"] if data.User == x["user"]]
  194.  
  195.             responseVariables["$maxUserQueue"] = len(messagesOfUser)
  196.  
  197.            
  198.  
  199.             # lists all languages when command "!ttshelp" is written
  200.             if settings["helpCommand"].lower() == data.GetParam(0).lower():
  201.                 languages = "Available languages / voices are: "
  202.                 for key, value in settings["enabledVoices"].items():
  203.                     languages += "{} ({}{})".format(value, settings["command"], key)
  204.                     # languages += value + "(" + key +  ")"
  205.                     languages += ", "
  206.                
  207.                 # for key, value in voices.items():
  208.                 #   languages += "{} ({})".format(value, key)
  209.                 #   # languages += value + "(" + key +  ")"
  210.                 #   languages += ", "
  211.                 languages = languages.rstrip(" ").rstrip(",")
  212.                 for i in range(len(languages) // 490 + 1):
  213.                     Parent.SendStreamMessage(languages[i*490:490*(i+1)])
  214.  
  215.             elif settings["command"].lower() in data.GetParam(0).lower():
  216.                 message = " ".join(data.Message.split(" ")[1:])
  217.  
  218.                 # applies black list word filter - message will be purged if it contains a bad word
  219.                 for word in settings["blackWordFilter"]:
  220.                     if word.lower() in message.lower():
  221.                         Parent.SendStreamMessage("/timeout {} 1 TTS Announcer: Message contains a bad word.".format(data.User))
  222.                         return
  223.  
  224.                 # check power levels - everyone, regular, sub, mod, streamer
  225.                 userPowerLevel = 0
  226.                 userPowerLevel = 1 if Parent.HasPermission(data.User, "regular", "") else userPowerLevel
  227.                 userPowerLevel = 2 if Parent.HasPermission(data.User, "subscriber", "") else userPowerLevel
  228.                 userPowerLevel = 3 if Parent.HasPermission(data.User, "moderator", "") else userPowerLevel
  229.                 userPowerLevel = 4 if Parent.HasPermission(data.User, "caster", "") else userPowerLevel
  230.                 if settings["powerLevelInt"] > userPowerLevel:
  231.                     Parent.Log("TTS Announcer", "A request has been declined because the user does not have high enough power level.")
  232.                     return
  233.  
  234.                 # unique key not available
  235.                 if tts["uniqueKey"] == "":
  236.                     SendMessage(settings["responseKeyMissing"])
  237.                     return
  238.  
  239.                 # message too long
  240.                 if len(message) > settings["userMaxMessageLength"]:
  241.                     SendMessage(settings["responseMessageTooLong"])
  242.                     return
  243.                
  244.                 # global TTS queue cooldown is active
  245.                 globalLastUsage = tts.get("globalCooldownUntil", 1)
  246.                 if ConvertDatetimeToEpoch(datetime.datetime.now()) < globalLastUsage:
  247.                     responseVariables["$waitSeconds"] = int(globalLastUsage - ConvertDatetimeToEpoch(datetime.datetime.now()))
  248.                     SendMessage(settings["responseGlobalQueueActive"])
  249.                     return
  250.  
  251.                 # too many entries in global TTS queue
  252.                 if len(tts["queue"]) >= settings["globalMaxQueues"]:
  253.                     SendMessage(settings["responseGloballyTooManyInQueue"])
  254.                     return
  255.  
  256.                 # user has to wait to use TTS again
  257.                 lastUsage = users.get(data.User, 1)
  258.                 if ConvertDatetimeToEpoch(datetime.datetime.now()) < lastUsage:
  259.                     responseVariables["$waitSeconds"] = int(lastUsage - ConvertDatetimeToEpoch(datetime.datetime.now()))
  260.                     SendMessage(settings["responseUserSpamming"])
  261.                     return
  262.  
  263.                 # user has too many TTS in queue
  264.                 if len(messagesOfUser) >= settings["userMaxQueues"]:
  265.                     SendMessage(settings["responseUserTooManyInQueue"])
  266.                     return
  267.  
  268.  
  269.                 # if user doesnt have enough points
  270.                 if Parent.GetPoints(data.User) < settings["userPointsCost"]:
  271.                     SendMessage(settings["responseUserNotEnoughPoints"])
  272.                     return
  273.                
  274.                 # try to find voice
  275.                 voiceFound = False
  276.                
  277.                 # for key, voiceName in voices.items():
  278.                 for key, voiceName in settings["enabledVoices"].items():   
  279.                     if settings["command"].lower() + key == data.GetParam(0).lower():
  280.                         voice = voiceName
  281.                         voiceFound = True
  282.                         break
  283.  
  284.                 # if voice hasnt been found
  285.                 if not voiceFound:
  286.                     SendMessage(settings["responseUserLanguageNotFound"])
  287.                     return
  288.  
  289.                 users[data.User] = ConvertDatetimeToEpoch(datetime.datetime.now()) + int(settings["userCooldown"]) # set last usage to "now"
  290.                 tts["globalCooldownUntil"] = ConvertDatetimeToEpoch(datetime.datetime.now()) + int(settings["globalCooldown"]) # set last usage to "now"
  291.                 Parent.RemovePoints(data.User, data.UserName, settings["userPointsCost"])
  292.                 tts["queue"].append({
  293.                     "user": data.User,
  294.                     "voice": voice.replace(" ", "%20"),
  295.                     "message": " ".join(data.Message.split(" ")[1:]).replace(" ", "%20"),
  296.                     # "voice": voice.replace(" ", "\%20"),
  297.                     # "message": " ".join(data.Message.split(" ")[1:]).replace(" ", "\%20"),
  298.                 })
  299.                
  300.                 Parent.Log("TTS Announcer", "Success! Message: {}".format(" ".join(data.Message.split(" ")[1:]))) #.replace(" ", "%20")))
  301.     return
  302.  
  303. #---------------------------------------
  304. #   [Required] Tick Function
  305. #---------------------------------------
  306. def Tick():
  307.     global tts, settings, voices
  308.  
  309.     if settings.get("settingsLoaded", False):
  310.         t1 = time.time()
  311.         if tts["timeUntilReady"] < 0:
  312.             if len(tts["queue"]) > 0:
  313.                 current = tts["queue"].pop(0)
  314.                 if len(current["message"]) != "" and tts["uniqueKey"] != "":
  315.                     response = Parent.GetRequest("https://warp.world/scripts/tts-message?streamer={0}&key={1}&viewer={2}&bar={3}&font={4}&sfont={5}&bfont={6}&gfont={7}&voice={8}&vol={9}&alert=false&message={10}".format(\
  316.                         Parent.GetChannelName(), tts["uniqueKey"], current["user"], settings["messageColor"], settings["fontColor"], settings["fontSize"], settings["fontOutlineColor"],\
  317.                         settings["googleFont"], cgi.escape(current["voice"]), str(settings["volume"]), cgi.escape(current["message"])), {})
  318.                     # Parent.Log("TTS Announcer", "Logging: {}".format(cgi.escape(current["message"])))
  319.                 tts["timeUntilReady"] = len(current["message"]) / 8
  320.  
  321.         else:
  322.             tts["timeUntilReady"] -= t1 - tts["timeOfLastTick"]
  323.             tts["timeOfLastTick"] = t1
  324.     return
  325.  
  326. #---------------------------------------
  327. #   Buttons on the UI
  328. #---------------------------------------
  329.  
  330. def ClearQueue():
  331.     global tts
  332.     tts["queue"] = []
  333.     tts["timeUntilReady"] = 0
  334.  
  335. def GenerateAndWhisperKey():
  336.     global tts
  337.     if time.time() - tts["generateKeyButtonClicked"] > 10:
  338.         tts["generateKeyButtonClicked"] = time.time()
  339.         response = json.loads(Parent.GetRequest("https://warp.world/scripts/tts-user?streamer=" + Parent.GetChannelName(), {}))
  340.         if response["status"] == 200:
  341.             newLink = response["response"]
  342.             # Parent.Log("TTS", "response: {}".format(newLink))
  343.             key = newLink.split("/")[-2]
  344.             tts["uniqueKey"] = key
  345.             with codecs.open(tts["pathUniqueKey"], encoding='utf-8-sig', mode='w+') as file:
  346.                 json.dump({"uniqueKey": key}, file)
  347.             # Parent.Log("TTS", "key: {}".format(key))
  348.             Parent.SendStreamWhisper(Parent.GetChannelName(), "OBS Browser Source URL: {}".format(newLink))
  349.  
  350.  
  351. def OpenWebsiteForBrowserSource():
  352.     global tts
  353.     if time.time() - tts["generateKeyButtonClicked"] > 10:
  354.         tts["generateKeyButtonClicked"] = time.time()
  355.         response = json.loads(Parent.GetRequest("https://warp.world/scripts/tts-user?streamer=" + Parent.GetChannelName(), {}))
  356.         if response["status"] == 200:
  357.             newLink = response["response"]
  358.             key = newLink.split("/")[-2]
  359.             tts["uniqueKey"] = key
  360.             with codecs.open(tts["pathUniqueKey"], encoding='utf-8-sig', mode='w+') as file:
  361.                 json.dump({"uniqueKey": key}, file)            
  362.             os.startfile(newLink)
  363.  
  364. #---------------------------------------
  365. #   Helper Functinos
  366. #--------------------------------------
  367.        
  368. def ConvertDatetimeToEpoch(datetimeObject=datetime.datetime.now()):
  369.     # converts a datetime object to seconds in python 2.7
  370.     return time.mktime(datetimeObject.timetuple())
  371.  
  372. def AddSecondsToDatetime(datetimeObject, seconds):
  373.     # returns a new datetime object by adding x seconds to a datetime object
  374.     return datetimeObject + datetime.timedelta(seconds=seconds)
  375.  
  376. def ConvertEpochToDatetime(seconds=0):
  377.     # 0 seconds as input would return 1970, 1, 1, 1, 0
  378.     seconds = max(0, seconds)
  379.     return datetime.datetime.fromtimestamp(seconds)
  380.  
  381. def SendMessage(string):
  382.     global responseVariables
  383.     for variable, text in responseVariables.items():
  384.         if type(text) == type(0.1):
  385.             string = string.replace(variable, str(int(text)))
  386.         else:
  387.             string = string.replace(variable, str(text))
  388.     Parent.SendStreamMessage(string[:490])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement