Newer
Older
junbireport / junbi.cgi
#!/usr/local/bin/python
## -*- coding: utf-8 -*-
from __future__ import unicode_literals
from random import choice
import json
import sys
from datetime import datetime, timedelta
from datetime import date as Date
import codecs

user = 'whaov'
password = 'Tey12ufw'

intent = None
date   = None
period = None
machine_name = None
DEBUG=True

def _log(mes):
    if DEBUG:
        with open("log.txt", "a") as f:
            f.write(str(datetime.now()) + ":" + str(mes) + "\n")

def get_parameters(): # {{{
    global intent, date, period, machine_name
    today = Date.today()
    inp = json.load(sys.stdin)
    try:
        _result     = inp['result']
        _metadata   = _result['metadata']
        _params     = _result['parameters']

        intent = _metadata['intentName']
        date   = _params.get('date', "")
        period = _params.get('date-period', "")
        machine_name = _params.get('machine-name', "")
    except:
        pass

    with open("foo.txt", "w") as f:
        f.write(str((intent, date, period, machine_name)))

    if date:
        d = datetime.strptime(date, "%Y-%m-%d")
        date = Date(d.year, d.month, d.day)
        if date > today: # no future. people always wants "PAST" event
            date = Date(d.year-1, d.month, d.day)
    elif not period:  # if there were no date infos, a good guess is "TODAY"
        date = today
# }}}

def _dec(s): # {{{
    return codecs.decode(s,'rot13')
# }}}
def _weekdiff(d): # {{{
    _, cday, _ = d.isocalendar()
    _, tday, _ = (Date.today()+timedelta(1)).isocalendar()
    if tday >= cday:
        return tday - cday
    else:
        return 52+ tday -cday
# }}}

def machine(date, period): # {{{
    import urllib2
    import lxml.html
    import re
    week = ""
    if period:
        sfrom, _ = period.split('/')
        d = datetime.strptime(sfrom, "%Y-%m-%d")
        f = Date(d.year, d.month, d.day)
        diff = _weekdiff(f)
        if diff > 0:
            week = "?week=%d" % diff
    if date:
        diff = _weekdiff(date)
        if diff > 0:
            week = "?week=%d" % diff
        today = date.strftime("%-m/%-d")
    else:
        today = ""

    url = 'http://ist.ksc.kwansei.ac.jp/~tutimura/cgi-bin/lab/' + week
    headers ={}
    headers["authorization"] = "Basic " + (_dec(user) + ":" + _dec(password)).encode("base64")[:-1]
    req = urllib2.Request(url=url, headers=headers)
    res = urllib2.urlopen(req)

    tree = lxml.html.etree.HTML(res.read().decode('utf-8'))
    table = tree[1][-4]
    days = table[0][1:]

    line = ""
    for i in range(len(days)):
        _log(days[i].text[:len(today)] + ":" + today)
        if today and days[i].text[:len(today)] != today:
            continue
        tmp = ""
        for j in table[1:]:
            if j[0].text == "二重排除":
                if j[i+1].findall('a'):
                    tmp += ",二重排除が何件かでているようです。"
            else:
                entries = [l.text[0] + " " + l.text[1] + " " + l.text[2:] for l in j[i+1].findall('a')]
                s = u"と".join(entries)
                if s != '':
                    tmp += u"," + s + u"が" + j[0].text + u"のようです。"
        if tmp:
            day = re.sub('/', u'月', days[i].text)
            day = re.sub('\(', u'日(', day)
            tmp = day + tmp
        line += tmp

    if line == "":
        if period != "":
            day = re.sub('/', u'月', days[0].text)
            day = re.sub('\(', u'日(', day)
            day2 = re.sub('/', u'月', days[-1].text)
            day2 = re.sub('\(', u'日(', day2)
            day = day + u"から" + day2

        else:
            day = _formatdate(date)
        line = day + choice((
            "なにもありません。平和でなによりです",
            "異常ありません. よかった",
            "報告事項なしです。",
              ))
    
    return line
# }}}

def ondotori(date, period): # {{{
    import csv
    if date == "": 
        date = Date.today()
    today = date.strftime("%Y/%m/%d")
    comlog = csv.reader(open("ComLog.txt"))
    ok = {}
    for row in comlog:
        if row[0].startswith(today):
            data = [x.decode('shiftjis') for x in row]
            if data[1] in ok and ok[data[1]] == u'成功':
                continue
            ok[data[1]] = data[3]

    s = u""
    for x in ok:
        if ok[x] != u'成功':
            s +=  x+ u"番,"
    if s == u"":
        if ok:
            s = choice((
                "全部成功です。やったー!",
                "問題ありません。ラッキー!",
            )) 
        else:
            s = "データがまだ無いようです"
    else:
        s += "が失敗しています"

    return s
# }}}

def _search(name): # {{{
    return [
            ("f", "w", 1), ("f", "w", 1), ("f", "w", 2), ("f", "w", 2), ("f", "w", 3), ("f", "w", 3),
            ("b", "w", 5), ("b", "w", 5), ("b", "w", 6), ("b", "w", 6), 
            # 11
            ("f", "w", 1), ("f", "w", 1), ("f", "w", 2), ("f", "w", 2), ("f", "w", 3), ("f", "w", 3),
            ("b", "w", 5), ("b", "w", 5), ("b", "w", 6), ("b", "w", 6), 
            #21
            ("f", "m", 1), ("f", "m", 1), ("f", "m", 2), ("f", "m", 2), ("f", "m", 3), ("f", "m", 3),
            ("b", "m", 4), ("b", "m", 4), ("b", "m", 5), ("b", "m", 5), 
            #31
            ("f", "m", 1), ("f", "m", 1), ("f", "m", 2), ("f", "m", 2), ("f", "m", 3), ("f", "m", 3),
            ("b", "m", 4), ("b", "m", 4), ("b", "m", 5), ("b", "m", 5), 
            #41
            ("f", "c", 2), ("f", "c", 2), ("f", "c", 3), ("f", "c", 3),
            ("b", "c", 4), ("b", "c", 4), ("b", "c", 5), ("b", "c", 5), 
            ("b", "m", 6), ("b", "m", 6),
            #51
            ("f", "c", 2), ("f", "c", 2), ("f", "c", 3), ("f", "c", 3),
            ("b", "c", 4), ("b", "c", 4), ("b", "c", 5), ("b", "c", 5), 
            ("b", "m", 6), ("b", "m", 6),

            ("b", "m", 6), ("b", "m", 6),
            ("j", "m", 6), ("j", "m", 6),
            ][int(name)-1]
# }}}
def location(name): #{{{
    name = name[3:]
    
    if int(name) > 63:
        return ""

    room, col, n = _search(name)

    s = ""
    if room == "f":
        s += "前側の部屋,"
    elif room == "b":
        s += "後側の部屋,"

    if col == "w":
        s += "窓側"
    elif col == "c":
        s += "廊下側"
    elif col == "m":
        s += "真ん中"

    s += "前から" + str(n) + "番目の島です"
    if room == "j":
        s = "準備室ですよ。ボケてるんですか?"

    return s
# }}}

def _formatdate(date): # {{{
    week="月火水木金土日"
    return str(date.month) + "月"+ str(date.day) +"日("+week[date.weekday()] + ")"
# }}}
def log(name): # {{{
    import os
    import re
    import locale

    name = name[3:]
    logdir = "/var/log/httpd/"
    logfiles = [fname for fname in os.listdir(logdir) if fname.startswith("access_log-")]

    logfiles.sort()
    logfiles.append('access_log')

    ipaddr = "172.29.119." + str(int(name)+150)

    errlog = []
    error_count = 0
    lines = []
    for fname in logfiles[-8:]:
        with open(logdir + fname) as f:
            line = [l for l in f.readlines() if "logonoff" in l and l.startswith(ipaddr)]
            line = [re.match(r'.*\[(\d+/\w+/\d+:\d+:\d+:\d+).*logonoff\?(.*) HTTP', l).groups() for l in line]
            lines += [(datetime.strptime(date, '%d/%b/%Y:%H:%M:%S'), action) for date, action in line]

    w_up_flag, l_up_flag, on_flag = False, False, True
    dailyerr = u""

    date, action = lines[0]
    if action == "shutdownL":
        lines = lines[1:]

    prev = ""
    for datet, action in lines:
        date = Date(*datet.timetuple()[:3])
        if prev != date:
            if prev:
                if not on_flag:
                    dailyerr = "反応なし." + dailyerr
                if l_up_flag or w_up_flag:
                    dailyerr = "ONのみ." + dailyerr
                if dailyerr:
                    errlog.append(_formatdate(prev)+ dailyerr)
                prev += timedelta(1)
                while prev != date:
                    if prev.weekday() != 6:
                        errlog.append(_formatdate(prev) + u"に反応なし.")
                    prev += timedelta(1)
            prev = date
            w_up_flag, l_up_flag, on_flag = False, False, False
            dailyerr = ""

        if   action == "amt"     and not u"AMT"  in dailyerr: dailyerr += u"AMT動作."
        elif action == "cleanup" and not u"電源" in dailyerr: dailyerr += u"電源落ち."
        elif action == "novga"   and not u"VGA"  in dailyerr: dailyerr += u"VGA喪失."
        elif action == "shutdownL":
            if not l_up_flag:
                dailyerr += u"OFFのみ."
            l_up_flag = False
        elif action == "shutdown":
            if not w_up_flag:
                dailyerr += u"OFFのみ."
            w_up_flag = False
        elif action == "startupL":
            l_up_flag = True
            on_flag = True
        elif action == "startup":
            w_up_flag = True
            on_flag = True

    errlog.reverse()
    s = " ".join(errlog)
    if not s:
        s = "最近は何もないようです"
    return s
#}}}

def slack(context):
    pass

##
## vvv  main sequence  vvv
##

get_parameters()

answer = ""
if intent == "ondotoriIntent":
    answer += ondotori(date, period)
elif intent == "machineIntent":
    answer += machine(date, period)
elif intent == "locationIntent":
    answer += location(machine_name)
elif intent == "logIntent":
    answer += log(machine_name)
elif intent == "slackIntent":
    answer += slack(context)

if answer == "":
    answer = choice((
        u"よくわかりませんでした",
        u"困っちゃいました",
        u"すみません、、もう一度お願いします",
        u"残念です",
        u"えっ?",
        u"ええええっ?",
        u"聞き取れませんでしたー "))


output = {"speech": answer, 
          "contextOut": [
            {"name": "monimoni", 
             "parameters": {
                    "text": answer, 
             },
             "lifespan": 1
            }
          ]}
d = json.dumps(output, ensure_ascii=False)

print "Content-Type: application/json; charset=UTF-8\n"
print d.encode("utf-8")

# vim:foldmethod=marker:ts=4:sw=4:expandtab: