Merge pull request #6 from evennia/develop

Update Develop
This commit is contained in:
FlutterSprite 2017-12-16 17:29:13 -08:00 committed by GitHub
commit be8cf70621
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 188 additions and 79 deletions

View file

@ -5,11 +5,11 @@
# install `docker` (http://docker.com)
#
# Usage:
# cd to a folder where you want your game data to be (or where it already is).
# cd to a folder where you want your game data to be (or where it already is).
#
# docker run -it -p 4000:4000 -p 4001:4001 -p 4005:4005 -v $PWD:/usr/src/game evennia/evennia
#
# (If your OS does not support $PWD, replace it with the full path to your current
#
# (If your OS does not support $PWD, replace it with the full path to your current
# folder).
#
# You will end up in a shell where the `evennia` command is available. From here you
@ -30,10 +30,10 @@ RUN apk update && apk add python py-pip python-dev py-setuptools gcc musl-dev jp
ADD . /usr/src/evennia
# install dependencies
RUN pip install -e /usr/src/evennia --trusted-host pypi.python.org
RUN pip install --upgrade pip && pip install /usr/src/evennia --trusted-host pypi.python.org
# add the game source when rebuilding a new docker image from inside
# a game dir
# a game dir
ONBUILD ADD . /usr/src/game
# make the game source hierarchy persistent with a named volume.
@ -48,7 +48,7 @@ WORKDIR /usr/src/game
ENV PS1 "evennia|docker \w $ "
# startup a shell when we start the container
ENTRYPOINT ["bash"]
ENTRYPOINT bash -c "source /usr/src/evennia/bin/unix/evennia-docker-start.sh"
# expose the telnet, webserver and websocket client ports
EXPOSE 4000 4001 4005

View file

@ -0,0 +1,13 @@
#! /bin/bash
# called by the Dockerfile to start the server in docker mode
# remove leftover .pid files (such as from when dropping the container)
rm /usr/src/game/server/*.pid >& /dev/null || true
# start evennia server; log to server.log but also output to stdout so it can
# be viewed with docker-compose logs
exec 3>&1; evennia start 2>&1 1>&3 | tee /usr/src/game/server/logs/server.log; exec 3>&-
# start a shell to keep the container running
bash

View file

@ -301,7 +301,7 @@ class CmdDelAccount(COMMAND_DEFAULT_CLASS):
# one single match
account = accounts.pop()
account = accounts.first()
if not account.access(caller, 'delete'):
string = "You don't have the permissions to delete that account."

View file

@ -1087,7 +1087,7 @@ class CmdSetHome(CmdLink):
set an object's home location
Usage:
@home <obj> [= <home_location>]
@sethome <obj> [= <home_location>]
The "home" location is a "safety" location for objects; they
will be moved there if their current location ceases to exist. All
@ -1098,13 +1098,13 @@ class CmdSetHome(CmdLink):
"""
key = "@sethome"
locks = "cmd:perm(@home) or perm(Builder)"
locks = "cmd:perm(@sethome) or perm(Builder)"
help_category = "Building"
def func(self):
"""implement the command"""
if not self.args:
string = "Usage: @home <obj> [= <home_location>]"
string = "Usage: @sethome <obj> [= <home_location>]"
self.caller.msg(string)
return

View file

@ -53,10 +53,11 @@ class ChannelAdmin(admin.ModelAdmin):
list_display = ('id', 'db_key', 'db_lock_storage', "subscriptions")
list_display_links = ("id", 'db_key')
ordering = ["db_key"]
search_fields = ['id', 'db_key', 'db_aliases']
search_fields = ['id', 'db_key', 'db_tags__db_key']
save_as = True
save_on_top = True
list_select_related = True
raw_id_fields = ('db_object_subscriptions', 'db_account_subscriptions',)
fieldsets = (
(None, {'fields': (('db_key',), 'db_lock_storage', 'db_account_subscriptions', 'db_object_subscriptions')}),
)

View file

@ -21,30 +21,30 @@ in the game in various ways:
Usage:
```python
from evennia.contrib import rplanguages
from evennia.contrib import rplanguage
# need to be done once, here we create the "default" lang
rplanguages.add_language()
rplanguage.add_language()
say = "This is me talking."
whisper = "This is me whispering.
print rplanguages.obfuscate_language(say, level=0.0)
print rplanguage.obfuscate_language(say, level=0.0)
<<< "This is me talking."
print rplanguages.obfuscate_language(say, level=0.5)
print rplanguage.obfuscate_language(say, level=0.5)
<<< "This is me byngyry."
print rplanguages.obfuscate_language(say, level=1.0)
print rplanguage.obfuscate_language(say, level=1.0)
<<< "Daly ly sy byngyry."
result = rplanguages.obfuscate_whisper(whisper, level=0.0)
result = rplanguage.obfuscate_whisper(whisper, level=0.0)
<<< "This is me whispering"
result = rplanguages.obfuscate_whisper(whisper, level=0.2)
result = rplanguage.obfuscate_whisper(whisper, level=0.2)
<<< "This is m- whisp-ring"
result = rplanguages.obfuscate_whisper(whisper, level=0.5)
result = rplanguage.obfuscate_whisper(whisper, level=0.5)
<<< "---s -s -- ---s------"
result = rplanguages.obfuscate_whisper(whisper, level=0.7)
result = rplanguage.obfuscate_whisper(whisper, level=0.7)
<<< "---- -- -- ----------"
result = rplanguages.obfuscate_whisper(whisper, level=1.0)
result = rplanguage.obfuscate_whisper(whisper, level=1.0)
<<< "..."
```
@ -71,7 +71,7 @@ Usage:
manual_translations = {"the":"y'e", "we":"uyi", "she":"semi", "he":"emi",
"you": "do", 'me':'mi','i':'me', 'be':"hy'e", 'and':'y'}
rplanguages.add_language(key="elvish", phonemes=phonemes, grammar=grammar,
rplanguage.add_language(key="elvish", phonemes=phonemes, grammar=grammar,
word_length_variance=word_length_variance,
noun_postfix=noun_postfix, vowels=vowels,
manual_translations=manual_translations
@ -96,6 +96,7 @@ import re
from random import choice, randint
from collections import defaultdict
from evennia import DefaultScript
from evennia.utils import logger
#------------------------------------------------------------
@ -105,21 +106,26 @@ from evennia import DefaultScript
#------------------------------------------------------------
# default language grammar
_PHONEMES = "ea oh ae aa eh ah ao aw ai er ey ow ia ih iy oy ua uh uw a e i u y p b t d f v t dh s z sh zh ch jh k ng g m n l r w"
_PHONEMES = "ea oh ae aa eh ah ao aw ai er ey ow ia ih iy oy ua uh uw a e i u y p b t d f v t dh " \
"s z sh zh ch jh k ng g m n l r w"
_VOWELS = "eaoiuy"
# these must be able to be constructed from phonemes (so for example,
# if you have v here, there must exixt at least one single-character
# if you have v here, there must exist at least one single-character
# vowel phoneme defined above)
_GRAMMAR = "v cv vc cvv vcc vcv cvcc vccv cvccv cvcvcc cvccvcv vccvccvc cvcvccvv cvcvcvcvv"
_RE_FLAGS = re.MULTILINE + re.IGNORECASE + re.UNICODE
_RE_GRAMMAR = re.compile(r"vv|cc|v|c", _RE_FLAGS)
_RE_WORD = re.compile(r'\w+', _RE_FLAGS)
_RE_EXTRA_CHARS = re.compile(r'\s+(?=\W)|[,.?;](?=[,.?;]|\s+[,.?;])', _RE_FLAGS)
class LanguageExistsError(Exception):
message = "Language is already created. Re-adding it will re-build" \
" its dictionary map. Use 'force=True' keyword if you are sure."
class LanguageError(RuntimeError):
pass
class LanguageExistsError(LanguageError):
pass
class LanguageHandler(DefaultScript):
@ -156,8 +162,11 @@ class LanguageHandler(DefaultScript):
self.db.language_storage = {}
def add(self, key="default", phonemes=_PHONEMES,
grammar=_GRAMMAR, word_length_variance=0, noun_prefix="",
noun_postfix="", vowels=_VOWELS, manual_translations=None,
grammar=_GRAMMAR, word_length_variance=0,
noun_translate=False,
noun_prefix="",
noun_postfix="",
vowels=_VOWELS, manual_translations=None,
auto_translations=None, force=False):
"""
Add a new language. Note that you generally only need to do
@ -170,14 +179,21 @@ class LanguageHandler(DefaultScript):
will be used as an identifier for the language so it
should be short and unique.
phonemes (str, optional): Space-separated string of all allowed
phonemes in this language.
phonemes in this language. If either of the base phonemes
(c, v, cc, vv) are present in the grammar, the phoneme list must
at least include one example of each.
grammar (str): All allowed consonant (c) and vowel (v) combinations
allowed to build up words. For example cvv would be a consonant
followed by two vowels (would allow for a word like 'die').
allowed to build up words. Grammars are broken into the base phonemes
(c, v, cc, vv) prioritizing the longer bases. So cvv would be a
the c + vv (would allow for a word like 'die' whereas
cvcvccc would be c+v+c+v+cc+c (a word like 'galosch').
word_length_variance (real): The variation of length of words.
0 means a minimal variance, higher variance may mean words
have wildly varying length; this strongly affects how the
language "looks".
noun_translate (bool, optional): If a proper noun, identified as a
capitalized word, should be translated or not. By default they
will not, allowing for e.g. the names of characters to be understandable.
noun_prefix (str, optional): A prefix to go before every noun
in this language (if any).
noun_postfix (str, optuonal): A postfix to go after every noun
@ -213,21 +229,28 @@ class LanguageHandler(DefaultScript):
"""
if key in self.db.language_storage and not force:
raise LanguageExistsError
# allowed grammar are grouped by length
gramdict = defaultdict(list)
for gram in grammar.split():
gramdict[len(gram)].append(gram)
grammar = dict(gramdict)
raise LanguageExistsError(
"Language is already created. Re-adding it will re-build"
" its dictionary map. Use 'force=True' keyword if you are sure.")
# create grammar_component->phoneme mapping
# {"vv": ["ea", "oh", ...], ...}
grammar2phonemes = defaultdict(list)
for phoneme in phonemes.split():
if re.search("\W", phoneme):
raise LanguageError("The phoneme '%s' contains an invalid character" % phoneme)
gram = "".join(["v" if char in vowels else "c" for char in phoneme])
grammar2phonemes[gram].append(phoneme)
# allowed grammar are grouped by length
gramdict = defaultdict(list)
for gram in grammar.split():
if re.search("\W|(!=[cv])", gram):
raise LanguageError("The grammar '%s' is invalid (only 'c' and 'v' are allowed)" % gram)
gramdict[len(gram)].append(gram)
grammar = dict(gramdict)
# create automatic translation
translation = {}
@ -261,6 +284,7 @@ class LanguageHandler(DefaultScript):
"grammar": grammar,
"grammar2phonemes": dict(grammar2phonemes),
"word_length_variance": word_length_variance,
"noun_translate": noun_translate,
"noun_prefix": noun_prefix,
"noun_postfix": noun_postfix}
self.db.language_storage[key] = storage
@ -282,34 +306,63 @@ class LanguageHandler(DefaultScript):
"""
word = match.group()
lword = len(word)
if len(word) <= self.level:
# below level. Don't translate
new_word = word
else:
# translate the word
# try to translate the word from dictionary
new_word = self.language["translation"].get(word.lower(), "")
if not new_word:
if word.istitle():
# capitalized word we don't have a translation for -
# treat as a name (don't translate)
new_word = "%s%s%s" % (self.language["noun_prefix"], word, self.language["noun_postfix"])
else:
# make up translation on the fly. Length can
# vary from un-translated word.
wlen = max(0, lword + sum(randint(-1, 1) for i
in range(self.language["word_length_variance"])))
grammar = self.language["grammar"]
if wlen not in grammar:
# no dictionary translation. Generate one
# find out what preceeded this word
wpos = match.start()
preceeding = match.string[:wpos].strip()
start_sentence = preceeding.endswith(".") or not preceeding
# make up translation on the fly. Length can
# vary from un-translated word.
wlen = max(0, lword + sum(randint(-1, 1) for i
in range(self.language["word_length_variance"])))
grammar = self.language["grammar"]
if wlen not in grammar:
if randint(0, 1) == 0:
# this word has no direct translation!
return ""
wlen = 0
new_word = ''
else:
# use random word length
wlen = choice(grammar.keys())
if wlen:
structure = choice(grammar[wlen])
grammar2phonemes = self.language["grammar2phonemes"]
for match in _RE_GRAMMAR.finditer(structure):
# there are only four combinations: vv,cc,c,v
new_word += choice(grammar2phonemes[match.group()])
if word.istitle():
# capitalize words the same way
new_word = new_word.capitalize()
try:
new_word += choice(grammar2phonemes[match.group()])
except KeyError:
logger.log_trace("You need to supply at least one example of each of "
"the four base phonemes (c, v, cc, vv)")
# abort translation here
new_word = ''
break
if word.istitle():
title_word = ''
if not start_sentence and not self.language.get("noun_translate", False):
# don't translate what we identify as proper nouns (names)
title_word = word
elif new_word:
title_word = new_word
if title_word:
# Regardless of if we translate or not, we will add the custom prefix/postfixes
new_word = "%s%s%s" % (self.language["noun_prefix"],
title_word.capitalize(),
self.language["noun_postfix"])
if len(word) > 1 and word.isupper():
# keep LOUD words loud also when translated
new_word = new_word.upper()
@ -341,7 +394,9 @@ class LanguageHandler(DefaultScript):
# configuring the translation
self.level = int(10 * (1.0 - max(0, min(level, 1.0))))
return _RE_WORD.sub(self._translate_sub, text)
translation = _RE_WORD.sub(self._translate_sub, text)
# the substitution may create too long empty spaces, remove those
return _RE_EXTRA_CHARS.sub("", translation)
# Language access functions

View file

@ -18,7 +18,7 @@ from evennia.contrib import rplanguage
mtrans = {"testing": "1", "is": "2", "a": "3", "human": "4"}
atrans = ["An", "automated", "advantageous", "repeatable", "faster"]
text = "Automated testing is advantageous for a number of reasons:" \
text = "Automated testing is advantageous for a number of reasons: " \
"tests may be executed Continuously without the need for human " \
"intervention, They are easily repeatable, and often faster."
@ -33,6 +33,11 @@ class TestLanguage(EvenniaTest):
manual_translations=mtrans,
auto_translations=atrans,
force=True)
rplanguage.add_language(key="binary",
phonemes="oo ii a ck w b d t",
grammar="cvvv cvv cvvcv cvvcvv cvvvc cvvvcvv cvvc",
noun_prefix='beep-',
word_length_variance=4)
def tearDown(self):
super(TestLanguage, self).tearDown()
@ -44,22 +49,36 @@ class TestLanguage(EvenniaTest):
self.assertEqual(result0, text)
result1 = rplanguage.obfuscate_language(text, level=1.0, language="testlang")
result2 = rplanguage.obfuscate_language(text, level=1.0, language="testlang")
result3 = rplanguage.obfuscate_language(text, level=1.0, language='binary')
self.assertNotEqual(result1, text)
self.assertNotEqual(result3, text)
result1, result2 = result1.split(), result2.split()
self.assertEqual(result1[:4], result2[:4])
self.assertEqual(result1[1], "1")
self.assertEqual(result1[2], "2")
self.assertEqual(result2[-1], result2[-1])
def test_faulty_language(self):
self.assertRaises(
rplanguage.LanguageError,
rplanguage.add_language,
key='binary2',
phonemes="w b d t oe ee, oo e o a wh dw bw", # erroneous comma
grammar="cvvv cvv cvvcv cvvcvvo cvvvc cvvvcvv cvvc c v cc vv ccvvc ccvvccvv ",
vowels="oea",
word_length_variance=4)
def test_available_languages(self):
self.assertEqual(rplanguage.available_languages(), ["testlang"])
self.assertEqual(rplanguage.available_languages(), ["testlang", "binary"])
def test_obfuscate_whisper(self):
self.assertEqual(rplanguage.obfuscate_whisper(text, level=0.0), text)
assert (rplanguage.obfuscate_whisper(text, level=0.1).startswith(
'-utom-t-d t-sting is -dv-nt-g-ous for - numb-r of r--sons:t-sts m-y b- -x-cut-d Continuously'))
'-utom-t-d t-sting is -dv-nt-g-ous for - numb-r of r--sons: t-sts m-y b- -x-cut-d Continuously'))
assert(rplanguage.obfuscate_whisper(text, level=0.5).startswith(
'--------- --s---- -s -----------s f-- - ------ -f ---s--s:--s-s '))
'--------- --s---- -s -----------s f-- - ------ -f ---s--s: --s-s '))
self.assertEqual(rplanguage.obfuscate_whisper(text, level=1.0), "...")
# Testing of emoting / sdesc / recog system

View file

@ -1685,10 +1685,10 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
msg_type = 'whisper'
msg_self = '{self} whisper to {all_receivers}, "{speech}"' if msg_self is True else msg_self
msg_receivers = '{object} whispers: "{speech}"'
msg_receivers = msg_receivers or '{object} whispers: "{speech}"'
msg_location = None
else:
msg_self = '{self} say, "{speech}"' if msg_self is True else msg_self
msg_receivers = None
msg_location = msg_location or '{object} says, "{speech}"'
custom_mapping = kwargs.get('mapping', {})
@ -1729,13 +1729,18 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
location_mapping = {"self": "You",
"object": self,
"location": location,
"all_receivers": ", ".join(recv for recv in receivers) if receivers else None,
"all_receivers": ", ".join(str(recv) for recv in receivers) if receivers else None,
"receiver": None,
"speech": message}
location_mapping.update(custom_mapping)
exclude = []
if msg_self:
exclude.append(self)
if receivers:
exclude.extend(receivers)
self.location.msg_contents(text=(msg_location, {"type": msg_type}),
from_obj=self,
exclude=(self, ) if msg_self else None,
exclude=exclude,
mapping=location_mapping)

View file

@ -13,8 +13,13 @@ try:
except ImportError as error:
errstr = """
{err}
SSL requires the PyOpenSSL library:
pip install pyopenssl
SSL requires the PyOpenSSL library and dependencies:
pip install pyopenssl pycrypto enum pyasn1 service_identity
Stop and start Evennia again. If no certificate can be generated, you'll
get a suggestion for a (linux) command to generate this locally.
"""
raise ImportError(errstr.format(err=error))

View file

@ -25,7 +25,6 @@ _RE_LINEBREAK = re.compile(r"\n\r|\r\n|\n|\r", re.DOTALL + re.MULTILINE)
_RE_SCREENREADER_REGEX = re.compile(r"%s" % settings.SCREENREADER_REGEX_STRIP, re.DOTALL + re.MULTILINE)
_IDLE_COMMAND = settings.IDLE_COMMAND + "\n"
class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
"""
Each player connecting over telnet (ie using most traditional mud
@ -50,6 +49,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
# when it reaches 0 the portal/server syncs their data
self.handshakes = 8 # suppress-go-ahead, naws, ttype, mccp, mssp, msdp, gmcp, mxp
self.init_session(self.protocol_name, client_address, self.factory.sessionhandler)
# change encoding to ENCODINGS[0] which reflects Telnet default encoding
self.protocol_flags["ENCODING"] = settings.ENCODINGS[0] if settings.ENCODINGS else 'utf-8'
# suppress go-ahead
self.sga = suppress_ga.SuppressGA(self)

View file

@ -7,7 +7,6 @@ from builtins import object
import time
#------------------------------------------------------------
# Server Session
#------------------------------------------------------------

View file

@ -83,15 +83,20 @@ WEBCLIENT_ENABLED = True
# default webclient will use this and only use the ajax version if the browser
# is too old to support websockets. Requires WEBCLIENT_ENABLED.
WEBSOCKET_CLIENT_ENABLED = True
# Server-side websocket port to open for the webclient.
# Server-side websocket port to open for the webclient. Note that this value will
# be dynamically encoded in the webclient html page to allow the webclient to call
# home. If the external encoded value needs to be different than this, due to
# working through a proxy or docker port-remapping, the environment variable
# WEBCLIENT_CLIENT_PROXY_PORT can be used to override this port only for the
# front-facing client's sake.
WEBSOCKET_CLIENT_PORT = 4005
# Interface addresses to listen to. If 0.0.0.0, listen to all. Use :: for IPv6.
WEBSOCKET_CLIENT_INTERFACE = '0.0.0.0'
# Actual URL for webclient component to reach the websocket. You only need
# to set this if you know you need it, like using some sort of proxy setup.
# If given it must be on the form "ws://hostname" (WEBSOCKET_CLIENT_PORT will
# be automatically appended). If left at None, the client will itself
# figure out this url based on the server's hostname.
# If given it must be on the form "ws[s]://hostname[:port]". If left at None,
# the client will itself figure out this url based on the server's hostname.
# e.g. ws://external.example.com or wss://external.example.com:443
WEBSOCKET_CLIENT_URL = None
# This determine's whether Evennia's custom admin page is used, or if the
# standard Django admin is used.
@ -166,6 +171,7 @@ IDLE_COMMAND = "idle"
# given, this list is tried, in order, aborting on the first match.
# Add sets for languages/regions your accounts are likely to use.
# (see http://en.wikipedia.org/wiki/Character_encoding)
# Telnet default encoding, unless specified by the client, will be ENCODINGS[0].
ENCODINGS = ["utf-8", "latin-1", "ISO-8859-1"]
# Regular expression applied to all output to a given session in order
# to strip away characters (usually various forms of decorations) for the benefit
@ -636,8 +642,6 @@ RSS_UPDATE_INTERVAL = 60 * 10 # 10 minutes
# browser to display. Note however that this will leak memory when
# active, so make sure to turn it off for a production server!
DEBUG = False
# While true, show "pretty" error messages for template syntax errors.
TEMPLATE_DEBUG = DEBUG
# Emails are sent to these people if the above DEBUG value is False. If you'd
# rather prefer nobody receives emails, leave this commented out or empty.
ADMINS = () # 'Your Name', 'your_email@domain.com'),)
@ -730,7 +734,9 @@ TEMPLATES = [{
'django.template.context_processors.media',
'django.template.context_processors.debug',
'sekizai.context_processors.sekizai',
'evennia.web.utils.general_context.general_context']
'evennia.web.utils.general_context.general_context'],
# While true, show "pretty" error messages for template syntax errors.
"debug": DEBUG
}
}]

View file

@ -6,6 +6,7 @@
# tuple.
#
import os
from django.conf import settings
from evennia.utils.utils import get_evennia_version
@ -52,7 +53,11 @@ def set_webclient_settings():
global WEBCLIENT_ENABLED, WEBSOCKET_CLIENT_ENABLED, WEBSOCKET_PORT, WEBSOCKET_URL
WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED
WEBSOCKET_CLIENT_ENABLED = settings.WEBSOCKET_CLIENT_ENABLED
WEBSOCKET_PORT = settings.WEBSOCKET_CLIENT_PORT
# if we are working through a proxy or uses docker port-remapping, the webclient port encoded
# in the webclient should be different than the one the server expects. Use the environment
# variable WEBSOCKET_CLIENT_PROXY_PORT if this is the case.
WEBSOCKET_PORT = int(os.environ.get("WEBSOCKET_CLIENT_PROXY_PORT", settings.WEBSOCKET_CLIENT_PORT))
# this is determined dynamically by the client and is less of an issue
WEBSOCKET_URL = settings.WEBSOCKET_CLIENT_URL
set_webclient_settings()

View file

@ -51,9 +51,9 @@ class TestGeneralContext(TestCase):
mock_settings.WEBCLIENT_ENABLED = "webclient"
mock_settings.WEBSOCKET_CLIENT_URL = "websocket_url"
mock_settings.WEBSOCKET_CLIENT_ENABLED = "websocket_client"
mock_settings.WEBSOCKET_CLIENT_PORT = "websocket_port"
mock_settings.WEBSOCKET_CLIENT_PORT = 5000
general_context.set_webclient_settings()
self.assertEqual(general_context.WEBCLIENT_ENABLED, "webclient")
self.assertEqual(general_context.WEBSOCKET_URL, "websocket_url")
self.assertEqual(general_context.WEBSOCKET_CLIENT_ENABLED, "websocket_client")
self.assertEqual(general_context.WEBSOCKET_PORT, "websocket_port")
self.assertEqual(general_context.WEBSOCKET_PORT, 5000)

View file

@ -44,7 +44,7 @@ JQuery available.
{% endif %}
{% if websocket_url %}
var wsurl = "{{websocket_url}}:{{websocket_port}}";
var wsurl = "{{websocket_url}}";
{% else %}
var wsurl = "ws://" + this.location.hostname + ":{{websocket_port}}";
{% endif %}