Lots of goodies in this one. More work on the default web front page, a few extra utility functions for functions_db as well. Some cleanup in the session code to use some of the new abstraction I added a while back. Player's last login time is now also set on the User object. Issue 28: Forward slashes causing crashes, found by Kuros, fixed by me.

This commit is contained in:
Greg Taylor 2007-06-06 13:38:13 +00:00
parent 270db06820
commit e2cc754441
7 changed files with 57 additions and 25 deletions

View file

@ -8,6 +8,7 @@ from django.contrib.auth.models import User
from django.utils import simplejson from django.utils import simplejson
from apps.news.models import NewsEntry from apps.news.models import NewsEntry
import functions_db
""" """
This file contains the generic, assorted views that don't fall under one of This file contains the generic, assorted views that don't fall under one of
@ -23,6 +24,9 @@ def page_index(request):
pagevars = { pagevars = {
"page_title": "Front Page", "page_title": "Front Page",
"news_entries": news_entries, "news_entries": news_entries,
"players_connected": functions_db.num_connected_players(),
"players_registered": functions_db.num_total_players(),
"players_connected_recent": functions_db.num_recently_connected_players(),
} }
context_instance = RequestContext(request) context_instance = RequestContext(request)

View file

@ -61,7 +61,7 @@ def handle(cdat):
# This will hold the reference to the command's function. # This will hold the reference to the command's function.
cmd = None cmd = None
if session.logged_in: if session.logged_in:
# Store the timestamp of the user's last command. # Store the timestamp of the user's last command.
session.cmd_last = time.time() session.cmd_last = time.time()
@ -75,6 +75,10 @@ def handle(cdat):
# Player-visible idle time, not used in idle timeout calcs. # Player-visible idle time, not used in idle timeout calcs.
session.cmd_last_visible = time.time() session.cmd_last_visible = time.time()
# Just in case. Prevents some really funky-case crashes.
if len(parsed_input['root_cmd']) == 0:
raise UnknownCommand
# Shortened say alias. # Shortened say alias.
if parsed_input['root_cmd'][0] == '"': if parsed_input['root_cmd'][0] == '"':
parsed_input['splitted'].insert(0, "say") parsed_input['splitted'].insert(0, "say")

View file

@ -89,9 +89,9 @@ def cmd_inventory(cdat):
money = int(pobject.get_attribute_value("MONEY", default=0)) money = int(pobject.get_attribute_value("MONEY", default=0))
if money == 1: if money == 1:
money_name = functions_db.get_server_config("MONEY_NAME_SINGULAR") money_name = gameconf.get_configvalue("MONEY_NAME_SINGULAR")
else: else:
money_name = functions_db.get_server_config("MONEY_NAME_PLURAL") money_name = gameconf.get_configvalue("MONEY_NAME_PLURAL")
session.msg("You have %d %s." % (money,money_name)) session.msg("You have %d %s." % (money,money_name))

View file

@ -22,7 +22,7 @@ def cmd_connect(cdat):
password = cdat['uinput']['splitted'][2] password = cdat['uinput']['splitted'][2]
# Match an email address to an account. # Match an email address to an account.
email_matches = functions_db.get_dbref_from_email(uemail) email_matches = functions_db.get_user_from_email(uemail)
autherror = "Specified email does not match any accounts!" autherror = "Specified email does not match any accounts!"
# No username match # No username match
@ -36,7 +36,6 @@ def cmd_connect(cdat):
if not user.check_password(password): if not user.check_password(password):
session.msg(autherror) session.msg(autherror)
else: else:
user = email_matches[0]
uname = user.username uname = user.username
session.login(user) session.login(user)
@ -70,7 +69,7 @@ def cmd_create(cdat):
# Search for a user object with the specified username. # Search for a user object with the specified username.
account = User.objects.filter(username=uname) account = User.objects.filter(username=uname)
# Match an email address to an account. # Match an email address to an account.
email_matches = functions_db.get_dbref_from_email(email) email_matches = functions_db.get_user_from_email(email)
if not account.count() == 0: if not account.count() == 0:
session.msg("There is already a player with that name!") session.msg("There is already a player with that name!")
@ -79,8 +78,8 @@ def cmd_create(cdat):
elif len(password) < 3: elif len(password) < 3:
session.msg("Your password must be 3 characters or longer.") session.msg("Your password must be 3 characters or longer.")
else: else:
functions_db.create_user(cdat, uname, email, password) functions_db.create_user(cdat, uname, email, password)
def cmd_quit(cdat): def cmd_quit(cdat):
""" """
We're going to maintain a different version of the quit command We're going to maintain a different version of the quit command

View file

@ -1,20 +1,42 @@
import sets import sets
from datetime import datetime, timedelta
from django.db import connection from django.db import connection
from django.contrib.auth.models import User from django.contrib.auth.models import User
from apps.objects.models import Object, Attribute from apps.objects.models import Object, Attribute
from apps.config.models import ConfigValue
import defines_global as defines_global import defines_global as defines_global
import gameconf import gameconf
""" """
Common database functions. Common database functions.
""" """
def get_server_config(configname): def num_total_players():
""" """
Returns a server config value. Returns the total number of registered players.
""" """
return ConfigValue.objects.get(conf_key__iexact=configname).conf_value return User.objects.count()
def get_connected_players():
"""
Returns the a QuerySet containing the currently connected players.
"""
return Object.objects.filter(nosave_flags__contains="CONNECTED")
def num_connected_players():
"""
Returns the number of connected players.
"""
return get_connected_players().count()
def num_recently_connected_players(days=7):
"""
Returns a QuerySet containing the player User accounts that have been
connected within the last <days> days.
"""
end_date = datetime.now()
tdelta = timedelta(days)
start_date = end_date - tdelta
return User.objects.filter(last_login__range=(start_date, end_date)).count()
def is_unsavable_flag(flagname): def is_unsavable_flag(flagname):
""" """
@ -211,9 +233,9 @@ def is_dbref(dbstring):
else: else:
return True return True
def get_dbref_from_email(uemail): def get_user_from_email(uemail):
""" """
Returns a player's dbref when given an email address. Returns a player's User object when given an email address.
""" """
return User.objects.filter(email__iexact=uemail) return User.objects.filter(email__iexact=uemail)

View file

@ -1,4 +1,5 @@
import time, sys import time, sys
from datetime import datetime
import cPickle as pickle import cPickle as pickle
from twisted.conch.telnet import StatefulTelnetProtocol from twisted.conch.telnet import StatefulTelnetProtocol
@ -147,11 +148,16 @@ class SessionProtocol(StatefulTelnetProtocol):
session_mgr.disconnect_duplicate_session(self) session_mgr.disconnect_duplicate_session(self)
self.msg("You are now logged in as %s." % (self.name,)) self.msg("You are now logged in as %s." % (self.name,))
pobject.get_location().emit_to_contents("%s has connected." % (pobject.get_name(),), exclude=pobject) pobject.get_location().emit_to_contents("%s has connected." % (pobject.get_name(),), exclude=pobject)
cdat = {"session": self, "uinput":'look', "server": self.factory.server} self.execute_cmd("look")
cmdhandler.handle(cdat)
functions_general.log_infomsg("Login: %s" % (self,)) functions_general.log_infomsg("Login: %s" % (self,))
# Update their account's last login time.
user.last_login = datetime.now()
user.save
pobject.set_attribute("Last", "%s" % (time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()),)) pobject.set_attribute("Last", "%s" % (time.strftime("%a %b %d %H:%M:%S %Y", time.localtime()),))
pobject.set_attribute("Lastsite", "%s" % (self.address[0],)) pobject.set_attribute("Lastsite", "%s" % (self.address[0],))
# Load their channel selection from a pickled attribute.
self.load_user_channels() self.load_user_channels()
def msg(self, message): def msg(self, message):

View file

@ -77,15 +77,12 @@
<div class="rowOfBoxes dividingBorderAbove"> <div class="rowOfBoxes dividingBorderAbove">
<div class="quarter noBorderOnLeft"> <div class="quarter noBorderOnLeft">
<h1>Standards</h1>
<p><span lang="la">Prosimii</span> is 100% compliant with <h1>Players</h1>
<acronym title="eXtensible HyperText Markup Language">XHTML</acronym> 1.0 Strict and <p>
uses <acronym title="Cascading Style Sheets">CSS</acronym>. There are currently <strong>{{players_connected}}</strong> connected,
<span class="doNotPrint">[Validate and a total of <strong>{{players_registered}}</strong> registered. Of these, {{players_recent}} were created this week, and <strong>{{players_connected_recent}}</strong> have connected within the last seven days.
<a href="http://validator.w3.org/check/referer">XHTML</a>]</span></p> </p>
<p>Unlike this design&rsquo;s inspiration, no tables have been used to layout elements
and text.</p>
</div> </div>
<div class="quarter"> <div class="quarter">