Newer
Older
attend-cgi / call_refactored.cgi
#!/usr/bin/env python3
# encoding: utf-8
"""
Refactored attendance tracking CGI script.

This script parses Apache access logs to track computer lab attendance.
"""
import os
import sys
import cgi
import json
from datetime import datetime

# Add the parent directory to the path to import our modules
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

from attendance_app.log_parser import get_log_files, parse_log_files
from attendance_app.database import SQLiteUserDatabase
from attendance_app.processor import AttendanceProcessor
from attendance_app.excel_output import ExcelGenerator


def parse_form_parameters(form):
    """
    Parse CGI form parameters.

    Args:
        form: CGI FieldStorage object

    Returns:
        Dictionary with parsed parameters
    """
    params = {
        'date': form.getvalue('date'),
        'from': form.getvalue('from'),
        'to': form.getvalue('to'),
        'excel': 'excel' in form,
        'rooms': {
            'GRL': 'GRL' in form,
            'ML1': 'ML1' in form,
            'ML2': 'ML2' in form,
            'IML': 'IML' in form,
            'IML-A': 'IML-A' in form,
            'IML-B': 'IML-B' in form,
        }
    }
    return params


def main():
    """Main CGI entry point."""
    # Determine log directory based on test mode
    if sys.argv[-1] == "--test":
        logdir = "./"
        db_path = "./kguid_test.sqlite3"  # Use test DB in test mode
        template_path = "./attendancebook_template.xlsx"
    else:
        logdir = "/var/log/httpd/"
        db_path = "/var/www/etc/kguid.sqlite3"
        template_path = "./attendancebook_template.xlsx"

    # Parse form parameters
    form = cgi.FieldStorage()
    params = parse_form_parameters(form)

    # Parse date/time parameters
    try:
        from_time = datetime.strptime(
            params['date'] + " " + params['from'],
            "%Y/%m/%d %H:%M"
        )
        to_time = datetime.strptime(
            params['date'] + " " + params['to'],
            "%Y/%m/%d %H:%M"
        )
    except (ValueError, TypeError) as e:
        print("Content-Type: text/plain")
        print("Status: 400 Bad Request")
        print("")
        print(f"Invalid date/time parameters: {e}")
        return

    # Get relevant log files
    logfiles = get_log_files(logdir, from_time)

    # Parse log files
    db = parse_log_files(logdir, logfiles)

    # Process attendance records
    with SQLiteUserDatabase(db_path) as user_db:
        processor = AttendanceProcessor(user_db.lookup_user)
        records = processor.process_events(db, from_time, to_time)

    # Output results
    if not params['excel']:
        # JSON output
        print("Content-Type: application/json")
        print("")
        json.dump(records, sys.stdout)
    else:
        # Excel output
        try:
            # Add openpyxl to path if in production
            if sys.argv[-1] != "--test":
                sys.path.append("/home/tkuro/.local/lib/python3.9/site-packages/")

            generator = ExcelGenerator(template_path)
            temp_file = generator.generate(records, from_time, to_time, params['rooms'])

            # Send Excel file
            filename = "attendancebook" + from_time.strftime("%Y%m%d%H%M") + ".xlsx"
            with open(temp_file, "rb") as f:
                finfo = os.stat(temp_file)
                sys.stdout.buffer.write(
                    b"Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\n"
                )
                sys.stdout.buffer.write(
                    f'Content-Disposition: attachment; filename="{filename}"\n'.encode("ascii")
                )
                sys.stdout.buffer.write(
                    f'Content-Length: {finfo.st_size}\n\n'.encode("ascii")
                )
                sys.stdout.buffer.write(f.read())

            # Clean up temp file
            os.unlink(temp_file)

        except ImportError as e:
            print("Content-Type: text/plain")
            print("Status: 500 Internal Server Error")
            print("")
            print(f"Excel generation not available: {e}")
        except Exception as e:
            print("Content-Type: text/plain")
            print("Status: 500 Internal Server Error")
            print("")
            print(f"Error generating Excel: {e}")


if __name__ == "__main__":
    main()