translator chat

A place for requesting new Source.Python plugins to be made for your server.

Please request only one plugin per thread.
cut-magic
Junior Member
Posts: 19
Joined: Thu Jan 12, 2023 7:16 am

translator chat

Postby cut-magic » Thu Jan 12, 2023 6:37 pm

before on mattie eventscripts a user had managed to create a chat translator and therefore a user could write and his message was translated for others directly but his plugin could no longer work because yahoo had changed something that was necessary I wonder if he is possible to redo it without yahoo for use with the evenscript emulator or even to redo it in python

Syntax: Select all

# SourceTranslator by David Bowland
# ./addons/eventscripts/sourcetranslator/sourcetranslator.py


# >>> To configure this addon please see sourcetranslator.cfg (created when the addon is first loaded) <<<



"""
Translates chat on-the-fly based on each player's language setting.
Requires only ES 2.0.0.250i+
"""

"""
SourceTranslator allows other ESP addons to access its translation functionality.


SourceTranslator must be loaded to use the translation function:

import es
translator = es.import_addon('sourcetranslator')


You can then request a translation using:

translator.requestTranslation(callback, text, from_lang, to_lang, a=(), kw=None)

callback - function to call when translation is complete
text - text to translate
from_lang - two-letter language abbreviation of originating language (usually returned by playerlib's myPlayer.lang)
to_lang - two-letter language abbreviation of target language
a - extra arguments to pass to the callback function (requires a tuple, similar to gamethread)
kw - keywords to pass to the callback function (requires a dictionary, also similar to gamethread)


The callback function is called with the following parameters:

callback(text, *a, **kw)

text - the result of the translation
*a - an expanded version of "a" sent to requestTranslation where tuple elements become arguments
**kw - an expanded version of "kw" sent to requestTranslation where dictionary keys/values are passed as keywords to the function as: key=value
"""

import cfglib
import cmdlib
import es
import gamethread
import playerlib
import re
import sys
import time
import urllib.request, urllib.parse, urllib.error

from path import path
from queue import Queue
from usermsg import saytext2 as saytext
from threadpool import *


import psyco
psyco.full()


info = es.AddonInfo()
info.name = 'SourceTranslator'
info.version = '2'
info.basename = 'sourcetranslator'
info.url = 'http://addons.eventscripts.com/addons/view/' + info.basename
info.author = 'SuperDave'
info.poweredby = "Yahoo! translator: http://babelfish.yahoo.com"

addonpath = path(__file__).dirname()

###

MAX_THREAD_COUNT = 1 # Number of threads to create

###

config = cfglib.AddonCFG(addonpath.joinpath(info.basename + '.cfg'))

config.text(info.name + ' release %s options' % info.version)
config.text('./addons/eventscripts/%(basename)s/%(basename)s.cfg' % {'basename': info.basename})
config.text(info.url)
config.text('')
config.text('Load this addon with: es_load ' + info.basename)
config.text('\n')
config.text('To configure language settings for %s please see %s_languages.ini' % (info.name, info.basename))
config.text('\n')
config.text('Translations provided by: Yahoo! translator (http://babelfish.yahoo.com/)')
config.text('\n')

config.text('***** A word about translations *****')
config.text('')
config.text('Translations are not perfect!')
config.text(' - Translation is performed by Yahoo! translator and as such does not provide perfect translations.')
config.text('')
config.text('Translations are not instant!')
config.text(' - The process of connecting to the translator, having the text translated, and retrieving the result is')
config.text(' not an instant process. When text is translated the time taken to translate will be displayed so players')
config.text(' know when the original message was sent.')
config.text('')
config.text('Translations cannot always be displayed properly!')
config.text(' - Some translation results contain characters unrecognized by the Source engine. SourceTranslator will attempt')
config.text(' to display those characters using the 26 letter, a-z alphabet.')
config.text('\n')

config.text('***** Ignore prefix options *****')
cvar_ignoreprefix = config.cvar('sourcetranslator_ignoreprefix', '@!', 'Chat prefixes that mark text as not to be translated')
config.text('\n')

config.text('***** Say command options *****')
config.text('')
config.text('Use the following server command to specify say commands to be ignored:')
config.text('')
config.text('sourcetranslator_addsaycmd <"command">')
config.text('\n')

config.text('Place your sourcetranslator_addsaycmd commands below:')
config.command('sourcetranslator_addsaycmd')
config.text('\n')

config.text('Uncomment the following example options if you wish to use them:')
config.text('')
config.text('sourcetranslator_addsaycmd "!rank"')
config.text(' Uncomment the above line to ignore lines that start with "!rank"')
config.text('sourcetranslator_addsaycmd "!admin"')
config.text(' Uncomment the above line to ignore lines that start with "!admin"')
config.text('\n')

config.text('Designated say commands can be removed with the following server command:')
config.text('')
config.text('sourcetranslator_removesaycmd <"command">')
config.text('')
config.text('Due to the fact say commands can be added or removed removed above, this command will not be used by most users.')
config.text('\n')

config.text('***** ESP functionality documentation *****')
config.text('')
config.text(' SourceTranslator allows other ESP addons to access its translation functionality.')
config.text('\n')

config.text(' SourceTranslator must be loaded to use the translation function:')
config.text('')
config.text('import es')
config.text("translator = es.import_addon('sourcetranslator')")
config.text('\n')

config.text(' You can then request a translation using:')
config.text('')
config.text('translator.requestTranslation(callback, text, from_lang, to_lang, a=(), kw=None)')
config.text('')
config.text(' callback - function to call when translation is complete')
config.text(' text - text to translate')
config.text(" from_lang - two-letter language abbreviation of originating language (usually returned by playerlib's myPlayer.lang)")
config.text(' to_lang - two-letter language abbreviation of target language')
config.text(' a - extra arguments to pass to the callback function (requires a tuple, similar to gamethread)')
config.text(' kw - keywords to pass to the callback function (requires a dictionary, also similar to gamethread)')
config.text('\n')

config.text(' The callback function is called with the following parameters:')
config.text('')
config.text('callback(text, *a, **kw)')
config.text('')
config.text(' text - the result of the translation')
config.text(' *a - an expanded version of "a" sent to requestTranslation where tuple elements become arguments')
config.text(' **kw - an expanded version of "kw" sent to requestTranslation where dictionary keys/values are passed as keywords to the function as: key=value')

config.write()


cvar_deadchat = es.ServerVar('sv_deadchat') # We will query this cvar more than once

###

def compileReplacementChars():
"""
Compiles the database of replacement characters into a dictionary
for easy character replacement.
"""
with addonpath.joinpath('sourcetranslator_replacechars.db').open() as f:
for line in f.readlines():
line = line.strip()
if line:
# File is in the format:
# <characters to replace> <replacement characters>
chars, replacement = line.split(' ')
for c in chars:
# For each character to replace we store the replacement characters
# Using this method we can query the dictionary by character
# to see if said character needs to be replaced.
yield c, replacement

replacechars = dict(compileReplacementChars())


def replaceCharacters(text):
""" Replaces characters Source is unable to display with Source-friendly characters """
# We need to accept the annoying HTML/quote quirk
text = text.replace('&quot ;', '"').replace('&#039 ;', "'").replace('&amp ;', '&')
# Recreate the string using replacement characters when necessary
result = ''
for c in text:
result += replacechars.get(c, c)
return result

###

# Regular expressions for finding the translation in the result webpage
RE_STEP1 = re.compile(r'\<div\ id\=\"result\"\>.+\<\/div\>')
RE_STEP2 = re.compile(r'\>.+\<')

@threaded(MAX_THREAD_COUNT)
def requestTranslation(callback, text, from_lang, to_lang, a=(), kw=None):
# We require "a" to be a tuple
if not isinstance(a, tuple):
a = (a,)

try:
# Contact the website to send the text to be translated and the to and from langauges
u = urllib.request.urlopen('http://babelfish.yahoo.com/translate_txt',
data=urllib.parse.urlencode({'lp': from_lang + '_' + to_lang, 'trtext': text}))
# Read the translation result page
result = u.read()
u.close()

# Find the translation in the result page and return it
result = RE_STEP1.findall(result)[0].replace('<div id="result">', '', 1)
result = RE_STEP2.findall(result)[0][1:~6]
threadSafeCall(callback, (replaceCharacters(result),) + a, kw)

except:
# We raised an exception so go ahead and output it
threadSafeCall(sys.excepthook, sys.exc_info())
# We didn't get a usuable translation so we send back the original text
threadSafeCall(callback, (text,) + a, kw)

###

class Translator(object):
""" Class for handling interface with translation thread """

def __init__(self):
# Register a say filter to capture chat text
es.addons.registerSayFilter(self.translate)

def unregisterSayFilter(self):
""" Unregisters the say filter """
es.addons.unregisterSayFilter(self.translate)

def translate(self, userid, text, teamonly):
""" Displays the translation of the given text """
# Check the first two characters to see if we should ignore the line
if set(str(cvar_ignoreprefix)).intersection(text[:2]):
return userid, text, teamonly
# Strip the text of quotes if necessary
if text[0] == text[~0] == '"':
text = text[1:~0]
# If a say command was used we also want to ignore the text
if text.split(' ', 1)[0] in saycommands:
return userid, text, teamonly

# Compile a list of teams allowed to see the text
from_player = playerlib.getPlayer(userid)
if teamonly:
teams = (0, 1, from_player.team)
else:
teams = (0, 1, 2, 3)
# Remember whether the talking player is dead
isdead = int(from_player.isdead)
# Remember the talking player's language
from_lang = from_player.lang

# This will hold the different language and who should receive each one
recipients = {}
# Loop through each player and determine whether he or she should receive the message
for player in playerlib.getPlayerList():
if (player.steamid != "BOT" and player.team in teams and
(cvar_deadchat or isdead <= int(player.isdead))):
lang = player.lang
recipients[lang] = recipients.get(lang, []) + [player]

# Create a translate query for each language
# We need to send the speaking player's current state so we send the player instance
for lang in recipients:
if lang == from_lang:
# If the language is the same we don't need to bother translating
self.displayText(text, from_player, None, recipients[lang], teamonly)

else:
# Translate the text by putting it on the queue
# callback, player, text, from_lang, to_lang, recipients = qdata
requestTranslation(self.displayText, text, from_lang, lang, (from_player, time.time(), recipients[lang], teamonly))

return 0, text, teamonly

@staticmethod
def displayText(text, player, starttime, recipients, teamonly):
""" Displays the translated text to the appropriate players """
# Calculate the time taken to complete the translation
if starttime is None:
resolvetime = ''
else:
resolvetime = ' \x04[-%i:%02i]' % divmod(round(time.time() - starttime), 60)
# Add the player's name and team color to the text
text = '\x03' + player.name + resolvetime + '\x01 : '+ text

# Determine the team text
teamtext = ''
if teamonly:
if player.team == 2:
teamtext = '(Terrorist)'
elif player.team == 3:
teamtext = '(Counter-Terrorist)'

# Add *SPEC* to the text if the player is a spectator
if player.team not in (2, 3):
text = '\x01*SPEC* ' + text
# Add to the text "*DEAD*" if the player is dead
elif player.isdead:
text = '\x01*DEAD*' + teamtext + ' ' + text
# Add team text to the message if this is a team chat message
elif teamtext:
text = '\x01' + teamtext + ' ' + text

# We only want to send the message to connected players
recipients = [target for target in recipients if target.isOnline()]
# Send the message
saytext(list(map(int, recipients)), player.index, text)

translator = Translator()

###

class SayCommandManager(set):
""" Class containing say commands registered with the addon """

def __init__(self):
super(SayCommandManager, self).__init__()
cmdlib.registerServerCommand('sourcetranslator_addsaycmd', self.addCallback,
'Syntax: sourcetranslator_addsaycmd <"command">\nRegisteres a say command with SourceTranslator')
cmdlib.registerServerCommand('sourcetranslator_removesaycmd', self.removeCallback,
'Syntax: sourcetranslator_removesaycmd <"command">\nUnregisteres a say command with SourceTranslator')

def addCallback(self, args):
"""
sourcetranslator_addsaycmd <"command">
"""
self.addCommand(es.getargs())

def removeCallback(self, args):
"""
sourcetranslator_removesaycmd <"command">
"""
self.removeCommand(es.getargs())

def addCommand(self, command):
""" Adds the supplied say command to the say command set """
if command[0] == command[~0] == '"':
command = command[1:~0]
self.add(command)

def removeCommand(self, command):
""" Removes the supplied say command from the say command set """
if command[0] == command[~0] == '"':
command = command[1:~0]
self.discard(command)

def unregisterCommands(self):
""" Unregisters the server commands used to designate ignored say commands """
cmdlib.unregisterServerCommand('sourcetranslator_addsaycmd')
cmdlib.unregisterServerCommand('sourcetranslator_removesaycmd')

saycommands = SayCommandManager()

###

def load():
config.execute()


def unload():
saycommands.unregisterCommands()
translator.unregisterSayFilter()

for cvar in config.getCvars():
es.ServerVar(cvar).set(0)
Last edited by Ayuto on Thu Jan 12, 2023 9:56 pm, edited 1 time in total.
Reason: Syntax Highlighting

Return to “Plugin Requests”

Who is online

Users browsing this forum: No registered users and 21 guests