Source

pinyomi / pinyin / views.py

# -*- coding: utf-8 -*-
#----------------------------------------------------------------------------#
# views.py
# Lars Yencken <lars.yencken@gmail.com>
# vim: ts=4 sw=4 sts=4 et tw=78:
# Mon Dec 11 14:00:54 2006
#
#----------------------------------------------------------------------------#

"""
Views for the pinyin lookup app.
"""

#----------------------------------------------------------------------------#

import time
import datetime
import urllib
import re

from django.shortcuts import render_to_response
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from django.db import connection
from django.template import RequestContext
from django.core.urlresolvers import reverse
from cjktools.enum import Enum

from pinyin.common import Language
from pinyin import models, queries
from www import settings

#----------------------------------------------------------------------------#
# PUBLIC
#----------------------------------------------------------------------------#

def index(request):
    return render_to_response('pinyin_index.html', {},
            context_instance=RequestContext(request))

#----------------------------------------------------------------------------#

def japaneseLookup(request):
    """
    Render the pinyin search page, including the results of any subsequent
    searches.
    """
    context = {}

    # If we don't have a query, render the search page.
    if not request.REQUEST.has_key('query'):
        return render_to_response('pinyin_pinyin.html', context,
                context_instance=RequestContext(request))

    # If they clicked "Clear", redirect to a blank page.
    if request.REQUEST.has_key('action') and \
            request.REQUEST['action'] == 'Clear':
        return HttpResponseRedirect(reverse('pinyin_pinyin'))

    # We have a query to search.
    startTime = time.time()
    query = request.REQUEST['query'].strip()

    # Check for a preceding query.

    if query:
        successQuery = _checkForSuccess(request, query)
        if not successQuery:
            logObj = models.LookupLog(
                    query=query,
                    ipAddress=request.META['REMOTE_ADDR'],
                    targetLanguage='jp',
                    testing=request.REQUEST.has_key('testing'),
                )
            logObj.save()
            context['lastLog'] = logObj.id

        # We have a non-empty query.
        context['query'] = query

        try:
            results = queries.findJapaneseWord(query)
            context['results'] = results

        except Exception, message:
            if settings.DEBUG:
                raise
            else:
                context['error'] = message

        context['time'] = time.time() - startTime

    return render_to_response('pinyin_pinyin.html', context,
            context_instance=RequestContext(request))

#----------------------------------------------------------------------------#

def chineseLookup(request):
    """
    Render the kana search page.
    """
    context = {}

    # If we don't have a query, render the search page.
    if not request.REQUEST.has_key('query'):
        return render_to_response('pinyin_kana.html', context,
                context_instance=RequestContext(request))

    # If they clicked "Clear", redirect to a blank page.
    if request.REQUEST.has_key('action') and request.REQUEST['action'] == 'Clear':
        return HttpResponseRedirect(reverse('pinyin_kana'))

    startTime = time.time()
    query = request.REQUEST['query'].strip()

    if query:
        context['query'] = query

        # Check if this is the success query for a previous reading query.
        successQuery = _checkForSuccess(request, query)

        # If not, store the details.
        if not successQuery:
            logObj = models.LookupLog(
                    query=query,
                    ipAddress=request.META['REMOTE_ADDR'],
                    targetLanguage='cn',
                    testing=request.REQUEST.has_key('testing'),
                )
            logObj.save()
            context['lastLog'] = logObj.id

        try:
            context['results'] = queries.findChineseWord(query)

        except Exception, message:
            if settings.DEBUG:
                raise
            context['error'] = message

        context['time'] = time.time() - startTime

    return render_to_response('pinyin_kana.html', context,
            context_instance=RequestContext(request))

#----------------------------------------------------------------------------#

def japaneseResult(request):
    """
    Attempt to find the translation on a 3rd-party site, then redirect them
    directly to that site.
    """
    try:
        query = request.REQUEST['query'].strip()
        lastLogId = int(request.REQUEST['lastLog'])
        lastLog = models.LookupLog.objects.get(id=lastLogId)

    except (ValueError, KeyError, ObjectDoesNotExist):
        # Send them packing back to the base page.
        return HttpResponseRedirect(reverse('pinyin_pinyin'))

    _storeLogResult(query, lastLog, request)

    redirectUrl = _fetchExciteWordId(Language.Japanese, query)

    return HttpResponseRedirect(redirectUrl)

#----------------------------------------------------------------------------#

def chineseResult(request):
    """
    Attempt to find the translation on a 3rd-party site, then redirect them
    directly to that site.
    """
    try:
        query = request.REQUEST['query'].strip()
        lastLogId = int(request.REQUEST['lastLog'])
        lastLog = models.LookupLog.objects.get(id=lastLogId)

    except (ValueError, KeyError):
        # Send them packing back to the base page.
        return HttpResponseRedirect(reverse('pinyin_kana'))

    _storeLogResult(query, lastLog, request)

    redirectUrl = _fetchExciteWordId(Language.Chinese, query)

    return HttpResponseRedirect(redirectUrl)

#----------------------------------------------------------------------------#

def _checkForSuccess(request, query):
    if request.REQUEST.has_key('lastLog'):
        # See if there's a matching previous log number.
        try:
            lastLogId = int(request.REQUEST['lastLog'])
            lastLog = models.LookupLog.objects.get(id=lastLogId)
        except ValueError:
            pass
        except ObjectDoesNotExist:
            pass

        # Do some error checking, to make sure someone malicious doesn't
        # manipulate our logs.
        # 1. Update must be from the same IP address.
        # 2. Update must be the first time this has changed.
        # 3. Update must be within n minutes (currently 2).
        if lastLog.ipAddress == request.META['REMOTE_ADDR'] and \
                lastLog.target is None and \
                _inLastNMinutes(lastLog.timestamp, 2):
            lastLog.target = query
            lastLog.save()
            return True

    return False

#----------------------------------------------------------------------------#

def _inLastNMinutes(timestamp, n=2):
    """ Returns true if the time
    """
    timeDiff = datetime.datetime.now() - timestamp
    if timeDiff.days > 0 or timeDiff.seconds > n*60*60:
        return False
    else:
        return True

#----------------------------------------------------------------------------#

def _fetchExciteWordId(language, query):
    """
    Try to fetch the word itself on excite.
    """
    url = _makeExciteSearchUrl(language, query)
    iStream = urllib.urlopen(url)
    data = iStream.read()
    iStream.close()

    if language == Language.Chinese:
        dictType = 'chinese_japanese'
    else:
        dictType = 'japanese_chinese'
    
    match = re.search(r'a href="(/dictionary/%s\/.*id=[0-9]+)"' % dictType,
            data)

    if match != None:
        return 'http://www.excite.co.jp' + match.group(1)
    else:
        return url

#----------------------------------------------------------------------------#

def _makeExciteSearchUrl(language, word):
    """
    Makes a url for an excite search for the given word.
    """
    searchDict = {
                'search':   word,
                'match':    'beginswith',
            }
    encodedPart = urllib.urlencode(searchDict)
    if language == Language.Chinese:
        return 'http://www.excite.co.jp/dictionary/chinese_japanese/?%s' % encodedPart
    elif language == Language.Japanese:
        return 'http://www.excite.co.jp/dictionary/japanese_chinese/?%s' % encodedPart
    else:
        raise Exception, "Unknown language specified"

#----------------------------------------------------------------------------#

def _storeLogResult(query, lastLog, request):
    # Do some error checking, to make sure someone malicious doesn't
    # manipulate our logs.
    # 1. Update must be from the same IP address.
    # 2. Update must be the first time this has changed.
    # 3. Update must be within n minutes (currently 2).
    if lastLog.ipAddress == request.META['REMOTE_ADDR'] and \
            lastLog.target is None and \
            _inLastNMinutes(lastLog.timestamp, 2):
        lastLog.target = query
        lastLog.save()

    return

#----------------------------------------------------------------------------#
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.