#! python3
# -*- coding: utf-8 -*-
"""Searches recent reddit comments for ClashCaller! string and saves to database.

This module uses the Python Reddit API Wrapper (PRAW) to search recent reddit comments
for the ClashCaller! string. If found, the username, comment time, message, and
expiration time (if any) are parsed. The default, or provided, expiration time is
applied, then all the comment data is saved to a MySQL-compatible database."""

import configparser  # TODO: Remove configparser
import logging.config

import praw
import mysql.connector as mysql
import re


def main():
    # Logger
    logging.config.fileConfig('logging.conf', disable_existing_loggers=False)
    logging.raiseExceptions = True  # Production mode if False (no console sys.stderr output)
    logger = logging.getLogger('search')

    # Read database.ini file
    config = configparser.ConfigParser()
    config.read("database.ini")

    DB_USER = config.get("SQL", "user")
    DB_PASS = config.get("SQL", "passwd")
    DB_NAME = config.get("SQL", "name")

    # Setup MySQL-compatible database
    mysql_connection = mysql.connect(user=DB_USER, password=DB_PASS, database=DB_NAME)
    cursor = mysql_connection.cursor()

    # Generate reddit instance
    reddit = praw.Reddit('clashcaller')  # Section name in praw.ini
    subreddit = reddit.subreddit('ClashCallerBot')  # Limit scope for testing purposes

    # Search recent comments for ClashCaller! string
    clashcaller_re = re.compile(r'''
                                [!|\s]?             # prefix ! or space (optional)
                                [C|c]lash[C|c]aller # upper or lowercase ClashCaller
                                [!|\s]              # suffix ! or space (required)
                                ''', re.VERBOSE)
    for comment in subreddit.stream.comments():
        match = clashcaller_re.search(comment.body)
        if match and comment.author.name != 'ClashCallerBot':
            logger.info(f'In from {comment.author.name}')
            # TODO: If found, parse username, comment date, message, permalink, and expiration time (if any)

            # Strip everything before and including ClashCaller! string
            comment.body = comment.body[match.end():].strip()
            logger.debug(f'Stripped comment body: {comment.body}')

            # Check for expiration time
            expiration_re = re.compile(r'''
                                       (\d){1,2}(\s)? # single or double digit (space after optional)
                                       (minute(s)?\s| # minute(s) (space after required)
                                       min\s|         # minute abbr. (space after required)
                                       hour(s)?\s|    # hour(s) (space after required)
                                       hr\s           # hour abbr. (space after required)
                                       )+''', re.VERBOSE)

    # TODO: Apply default, or provided expiration time to comment date

    # TODO: Save comment data to MySQL-compatible database

    # TODO: Compose message for comment and PM

    # TODO: If not already commented, comment and send PM


# If run directly, instead of imported as a module, run main():
if __name__ == '__main__':
    main()

@@ -510,16 +510,42 @@
 g.config
+%0Aimport re%0Aimport datetime
 %0A%0Aimport
@@ -582,26 +582,16 @@
 s mysql%0A
-import re%0A
 %0A%0Adef ma
@@ -2447,16 +2447,29 @@
        (
+?P%3Cexp_digit%3E
 %5Cd)%7B1,2%7D
@@ -2562,16 +2562,28 @@
        (
+?P%3Cexp_unit%3E
 minute(s
@@ -2587,16 +2587,17 @@
 e(s)?%5Cs%7C
+ 
  # minut
@@ -2678,16 +2678,29 @@
         
+       
+      
 # minute
@@ -2779,16 +2779,29 @@
 r(s)?%5Cs%7C
+             
     # ho
@@ -2879,24 +2879,37 @@
 s           
+             
 # hour abbr.
@@ -2992,49 +2992,1013 @@
 BOSE
-)%0A%0A    # TODO: Apply default, or provided
+ %7C re.IGNORECASE)  # case-insensitive%0A            minute_tokens = ('min', 'minute', 'minutes')%0A            match = expiration_re.search(comment.body)%0A            if not match:%0A                timedelta = datetime.timedelta(hours=1)  # Default to 1 hour%0A            else:%0A                exp_digit = int(match.group('exp_digit').strip())%0A                if exp_digit == 0:  # ignore zeros%0A                    logging.error('Expiration time is zero.')%0A                    # TODO: Send message and ignore comment%0A                    continue%0A                exp_unit = match.group('exp_unit').strip().lower()%0A                if exp_unit in minute_tokens:%0A                    timedelta = datetime.timedelta(minutes=exp_digit)%0A                else:%0A                    timedelta = datetime.timedelta(hours=exp_digit)%0A                # Strip expiration time%0A                comment.body = comment.body%5Bmatch.end():%5D.strip()%0A            logger.debug(f'timedelta = %7Btimedelta.seconds%7D seconds')%0A%0A    # TODO: Apply
  exp

Update clashcallerbot_search.py added evaluate expiration time and match group names to expiration regex