Initial changes for multiple solutions per submission
This commit is contained in:
@@ -16,9 +16,8 @@ from . import config, database, level, reply
|
|||||||
USER_AGENT = 'PointsBot (by u/GlipGlorp7)'
|
USER_AGENT = 'PointsBot (by u/GlipGlorp7)'
|
||||||
|
|
||||||
# The pattern that determines whether a post is marked as solved
|
# The pattern that determines whether a post is marked as solved
|
||||||
# Could also use re.IGNORECASE flag instead
|
SOLVED_PATTERN = re.compile('![Hh]elped')
|
||||||
SOLVED_PATTERN = re.compile('![Ss]olved')
|
MOD_SOLVED_PATTERN = re.compile('/[Hh]elped')
|
||||||
MOD_SOLVED_PATTERN = re.compile('/[Ss]olved')
|
|
||||||
MOD_REMOVE_PATTERN = re.compile('/[Rr]emove[Pp]oint')
|
MOD_REMOVE_PATTERN = re.compile('/[Rr]emove[Pp]oint')
|
||||||
|
|
||||||
### Main Function ###
|
### Main Function ###
|
||||||
@@ -51,19 +50,11 @@ def run():
|
|||||||
logging.info('Connected to Reddit as %s', reddit.user.me())
|
logging.info('Connected to Reddit as %s', reddit.user.me())
|
||||||
access_type = 'read-only' if reddit.read_only else 'write'
|
access_type = 'read-only' if reddit.read_only else 'write'
|
||||||
logging.info(f'Has {access_type} access to Reddit')
|
logging.info(f'Has {access_type} access to Reddit')
|
||||||
# if not reddit.read_only:
|
|
||||||
# logging.info('Has write access to Reddit')
|
|
||||||
# else:
|
|
||||||
# logging.warning('Has read-only access to Reddit')
|
|
||||||
|
|
||||||
subreddit = reddit.subreddit(cfg.subreddit)
|
subreddit = reddit.subreddit(cfg.subreddit)
|
||||||
logging.info('Watching subreddit %s', subreddit.title)
|
logging.info('Watching subreddit %s', subreddit.title)
|
||||||
is_mod = subreddit.moderator(redditor=reddit.user.me())
|
is_mod = subreddit.moderator(redditor=reddit.user.me())
|
||||||
logging.info(f'Is {"" if is_mod else "NOT "} moderator for subreddit')
|
logging.info(f'Is {"" if is_mod else "NOT "} moderator for subreddit')
|
||||||
# if subreddit.moderator(redditor=reddit.user.me()):
|
|
||||||
# logging.info('Is moderator for monitored subreddit')
|
|
||||||
# else:
|
|
||||||
# logging.warning('Is NOT moderator for monitored subreddit')
|
|
||||||
|
|
||||||
monitor_comments(reddit, subreddit, db, levels, cfg)
|
monitor_comments(reddit, subreddit, db, levels, cfg)
|
||||||
|
|
||||||
@@ -94,8 +85,6 @@ def monitor_comments(reddit, subreddit, db, levels, cfg):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
logging.info('Found comment')
|
logging.info('Found comment')
|
||||||
|
|
||||||
# TODO more debug info about comment
|
|
||||||
logging.debug('Comment author: "%s"', comm.author.name)
|
logging.debug('Comment author: "%s"', comm.author.name)
|
||||||
logging.debug('Comment text: "%s"', comm.body)
|
logging.debug('Comment text: "%s"', comm.body)
|
||||||
|
|
||||||
@@ -111,21 +100,29 @@ def monitor_comments(reddit, subreddit, db, levels, cfg):
|
|||||||
|
|
||||||
if is_mod_command:
|
if is_mod_command:
|
||||||
logging.info('Comment was submitted by mod')
|
logging.info('Comment was submitted by mod')
|
||||||
elif is_valid_tag(comm, cfg.tags) and is_valid_flair(comm):
|
elif is_valid_tag(comm, cfg.tags):
|
||||||
logging.info('Comment has a valid tag and is not already marked as solved')
|
logging.info('Comment has a valid tag')
|
||||||
else:
|
# elif is_valid_tag(comm, cfg.tags) and is_valid_flair(comm):
|
||||||
# Skip this "!solved" comment
|
# logging.info('Comment has a valid tag and is not already marked as solved')
|
||||||
logging.info('Comment is NOT the first to mark the issue as solved')
|
# else:
|
||||||
continue
|
# # Skip this "!solved" comment
|
||||||
|
# logging.info('Comment is NOT the first to mark the issue as solved')
|
||||||
|
# continue
|
||||||
if not remove_point:
|
if not remove_point:
|
||||||
log_solution_info(comm)
|
log_solution_info(comm)
|
||||||
|
|
||||||
solver = find_solver(comm)
|
# solver = find_solver(comm)
|
||||||
|
solver, solution_comment = find_solver_and_comment(comm)
|
||||||
if remove_point:
|
if remove_point:
|
||||||
db.remove_point(solver)
|
# db.remove_point(solver)
|
||||||
|
# db.remove_point_for_solution(submission, solver, solution_comment, remover, removed_by_comment)
|
||||||
|
# db.remove_point_for_solution(comm.submission, )
|
||||||
|
db.soft_remove_point_for_solution(comm.submission, solver, comm.author, comm)
|
||||||
logging.info('Removed point for user "%s"', solver.name)
|
logging.info('Removed point for user "%s"', solver.name)
|
||||||
else:
|
else:
|
||||||
db.add_point(solver)
|
# db.add_point(solver)
|
||||||
|
# db.add_point_for_solution(submission, solver, solution_comment, chooser, chosen_by_comment)
|
||||||
|
db.add_point_for_solution(comm.submission, solver, solution_comment, comm.author, comm)
|
||||||
logging.info('Added point for user "%s"', solver.name)
|
logging.info('Added point for user "%s"', solver.name)
|
||||||
|
|
||||||
points = db.get_points(solver)
|
points = db.get_points(solver)
|
||||||
@@ -149,10 +146,12 @@ def monitor_comments(reddit, subreddit, db, levels, cfg):
|
|||||||
except praw.exceptions.APIException as e:
|
except praw.exceptions.APIException as e:
|
||||||
logging.error('Unable to reply to comment: %s', e)
|
logging.error('Unable to reply to comment: %s', e)
|
||||||
if remove_point:
|
if remove_point:
|
||||||
db.add_point(solver)
|
# db.add_point(solver)
|
||||||
|
db.add_back_point_for_solution(comm.submission, solver)
|
||||||
logging.error('Re-added point that was just removed from user "%s"', solver.name)
|
logging.error('Re-added point that was just removed from user "%s"', solver.name)
|
||||||
else:
|
else:
|
||||||
db.remove_point(solver)
|
# db.remove_point(solver)
|
||||||
|
db.remove_point_and_delete_solution(comm.submission, solver)
|
||||||
logging.error('Removed point that was just awarded to user "%s"', solver.name)
|
logging.error('Removed point that was just awarded to user "%s"', solver.name)
|
||||||
logging.error('Skipping comment')
|
logging.error('Skipping comment')
|
||||||
continue
|
continue
|
||||||
@@ -244,7 +243,6 @@ MOD_REMOVE_RULES = [
|
|||||||
'author is mod',
|
'author is mod',
|
||||||
'Comment author is a mod',
|
'Comment author is a mod',
|
||||||
'Comment author is not a mod',
|
'Comment author is not a mod',
|
||||||
# functions
|
|
||||||
lambda c: is_mod_comment(c),
|
lambda c: is_mod_comment(c),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
@@ -300,17 +298,20 @@ def is_valid_tag(solved_comment, valid_tags):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def is_valid_flair(solved_comment):
|
# def is_valid_flair(solved_comment):
|
||||||
"""Return True if this comment's post doesn't already have the Solved flair, False otherwise."""
|
# """Return True if this comment's post doesn't already have the Solved flair, False otherwise."""
|
||||||
submission = solved_comment.submission
|
# submission = solved_comment.submission
|
||||||
|
|
||||||
return submission.link_flair_text.lower() != "solved"
|
# return submission.link_flair_text.lower() != "solved"
|
||||||
|
|
||||||
|
|
||||||
def find_solver(solved_comment):
|
# def find_solver(solved_comment):
|
||||||
|
def find_solver_and_comment(solved_comment)
|
||||||
"""Determine the redditor responsible for solving the question."""
|
"""Determine the redditor responsible for solving the question."""
|
||||||
# TODO plz make this better someday
|
# TODO plz make this better someday
|
||||||
return solved_comment.parent().author
|
# return solved_comment.parent().author
|
||||||
|
solution_comment = solved_comment.parent()
|
||||||
|
return solution_comment.author, solution_comment
|
||||||
|
|
||||||
|
|
||||||
### Print & Logging Functions ###
|
### Print & Logging Functions ###
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ CONFIGPATH = os.path.join(DATADIR, 'pointsbot.toml')
|
|||||||
|
|
||||||
# Path to the sample config file
|
# Path to the sample config file
|
||||||
# Unused for now
|
# Unused for now
|
||||||
SAMPLEPATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
# SAMPLEPATH = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||||
'..',
|
# '..',
|
||||||
'pointsbot.sample.toml'))
|
# 'pointsbot.sample.toml'))
|
||||||
|
|
||||||
### Primary Functions ###
|
### Primary Functions ###
|
||||||
|
|
||||||
@@ -115,7 +115,6 @@ class Config:
|
|||||||
def save(self):
|
def save(self):
|
||||||
obj = deepcopy(vars(self))
|
obj = deepcopy(vars(self))
|
||||||
orig_levels, obj['levels'] = obj['levels'], []
|
orig_levels, obj['levels'] = obj['levels'], []
|
||||||
# obj['levels'] = []
|
|
||||||
for level in orig_levels:
|
for level in orig_levels:
|
||||||
obj['levels'].append({
|
obj['levels'].append({
|
||||||
'name': level.name,
|
'name': level.name,
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
|
import datetime
|
||||||
import functools
|
import functools
|
||||||
import os.path
|
import os.path
|
||||||
import sqlite3 as sqlite
|
import sqlite3 as sqlite
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
### Decorators ###
|
### Decorators ###
|
||||||
|
|
||||||
|
|
||||||
def transaction(func):
|
def transaction(func):
|
||||||
|
"""Use this decorator on any methods that needs to query the database to
|
||||||
|
ensure that connections are properly opened and closed.
|
||||||
|
"""
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def newfunc(self, *args, **kwargs):
|
def newfunc(self, *args, **kwargs):
|
||||||
created_conn = False
|
created_conn = False
|
||||||
@@ -31,15 +36,68 @@ def transaction(func):
|
|||||||
|
|
||||||
### Classes ###
|
### Classes ###
|
||||||
|
|
||||||
|
DatabaseVersion = namedtuple('DatabaseVersion', 'major minor patch pre_release_name pre_release_number')
|
||||||
|
|
||||||
|
|
||||||
class Database:
|
class Database:
|
||||||
|
|
||||||
|
VERSION = DatabaseVersion(0, 2, 0, None, None)
|
||||||
|
|
||||||
SCHEMA = '''
|
SCHEMA = '''
|
||||||
|
---------------------------
|
||||||
|
-- Schema version: 0.1.0 --
|
||||||
|
---------------------------
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS redditor_points (
|
CREATE TABLE IF NOT EXISTS redditor_points (
|
||||||
id TEXT UNIQUE NOT NULL,
|
id TEXT UNIQUE NOT NULL,
|
||||||
name TEXT UNIQUE NOT NULL,
|
name TEXT UNIQUE NOT NULL,
|
||||||
points INTEGER DEFAULT 0
|
points INTEGER DEFAULT 0
|
||||||
)
|
);
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
-- Schema version: 0.2.0 --
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
-- Tracking bot/db version for potential future use in migrations et al.
|
||||||
|
CREATE TABLE IF NOT EXISTS bot_version (
|
||||||
|
major INTEGER NOT NULL,
|
||||||
|
minor INTEGER NOT NULL,
|
||||||
|
patch INTEGER NOT NULL,
|
||||||
|
pre_release_name TEXT,
|
||||||
|
pre_release_number INTEGER
|
||||||
|
);
|
||||||
|
INSERT OR IGNORE INTO bot_version (major, minor, patch) VALUES (0, 2, 0);
|
||||||
|
|
||||||
|
ALTER TABLE redditor_points RENAME TO redditor;
|
||||||
|
-- TODO rename "id" columns to "reddit_id" for consistency/clarity?
|
||||||
|
-- ALTER TABLE redditor RENAME COLUMN id TO reddit_id;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS submission (
|
||||||
|
id TEXT UNIQUE NOT NULL,
|
||||||
|
author_id TEXT UNIQUE NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS comment (
|
||||||
|
id TEXT UNIQUE NOT NULL,
|
||||||
|
author_id TEXT NOT NULL,
|
||||||
|
author_rowid INTEGER, -- May be NULL **for now**
|
||||||
|
created_at_datetime TEXT NOT NULL,
|
||||||
|
FOREIGN KEY (author_rowid) REFERENCES redditor (rowid) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS solution (
|
||||||
|
submission_rowid INTEGER NOT NULL,
|
||||||
|
author_rowid INTEGER NOT NULL,
|
||||||
|
comment_rowid INTEGER NOT NULL,
|
||||||
|
chosen_by_comment_rowid INTEGER NOT NULL,
|
||||||
|
removed_by_comment_rowid INTEGER,
|
||||||
|
FOREIGN KEY (submission_rowid) REFERENCES submission (rowid) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (author_rowid) REFERENCES redditor (rowid) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (comment_rowid) REFERENCES comment (rowid) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (chosen_by_comment_rowid) REFERENCES comment (rowid) ON DELETE SET NULL,
|
||||||
|
FOREIGN KEY (removed_by_comment_rowid) REFERENCES comment (rowid) ON DELETE SET NULL,
|
||||||
|
PRIMARY KEY (submission_rowid, author_rowid) ON DELETE CASCADE
|
||||||
|
);
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, dbpath):
|
def __init__(self, dbpath):
|
||||||
@@ -49,15 +107,34 @@ class Database:
|
|||||||
|
|
||||||
if not os.path.exists(self.path):
|
if not os.path.exists(self.path):
|
||||||
self._create()
|
self._create()
|
||||||
|
else:
|
||||||
|
self._migrate_if_necessary()
|
||||||
|
|
||||||
@transaction
|
@transaction
|
||||||
def _create(self):
|
def _create(self):
|
||||||
self.cursor.execute(self.SCHEMA)
|
self.cursor.execute(self.SCHEMA)
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def _migrate_if_necessary(self):
|
||||||
|
self.cursor.execute("SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'bot_version'")
|
||||||
|
has_version_table = (self.cursor.rowcount == 1)
|
||||||
|
has_outdated_version = False
|
||||||
|
if has_version_table:
|
||||||
|
self.cursor.execute('SELECT major, minor, patch, pre_release_name, pre_release_number FROM bot_version')
|
||||||
|
row = self.cursor.fetchone()
|
||||||
|
pre_release_number = int(row['pre_release_number']) if row['pre_release_number'] else None
|
||||||
|
current_version = DatabaseVersion(int(row['major']), int(row['minor']), int(row['patch']), row['pre_release_name'], pre_release_number)
|
||||||
|
has_outdated_version = (current_version == self.VERSION)
|
||||||
|
|
||||||
|
if not has_version_table or has_outdated_version:
|
||||||
|
self.cursor.execute(self.SCHEMA)
|
||||||
|
|
||||||
|
### Public Methods ###
|
||||||
|
|
||||||
@transaction
|
@transaction
|
||||||
def add_redditor(self, redditor):
|
def add_redditor(self, redditor):
|
||||||
insert_stmt = '''
|
insert_stmt = '''
|
||||||
INSERT OR IGNORE INTO redditor_points (id, name)
|
INSERT OR IGNORE INTO redditor (id, name)
|
||||||
VALUES (:id, :name)
|
VALUES (:id, :name)
|
||||||
'''
|
'''
|
||||||
self.cursor.execute(insert_stmt, {'id': redditor.id, 'name': redditor.name})
|
self.cursor.execute(insert_stmt, {'id': redditor.id, 'name': redditor.name})
|
||||||
@@ -66,18 +143,201 @@ class Database:
|
|||||||
@transaction
|
@transaction
|
||||||
def remove_redditor(self, redditor):
|
def remove_redditor(self, redditor):
|
||||||
insert_stmt = '''
|
insert_stmt = '''
|
||||||
DELETE FROM redditor_points
|
DELETE FROM redditor
|
||||||
WHERE id = :id
|
WHERE id = :id
|
||||||
AND name = :name
|
AND name = :name
|
||||||
'''
|
'''
|
||||||
self.cursor.execute(insert_stmt, {'id': redditor.id, 'name': redditor.name})
|
self.cursor.execute(insert_stmt, {'id': redditor.id, 'name': redditor.name})
|
||||||
return self.cursor.rowcount
|
return self.cursor.rowcount
|
||||||
|
|
||||||
def add_point(self, redditor):
|
@transaction
|
||||||
return self._update_points(redditor, 1)
|
# def has_already_solved_once(self, solver, submission):
|
||||||
|
def has_already_solved_once(self, submission, solver):
|
||||||
|
# author_id = self._get_rowid_from_reddit_id('redditor', solver)
|
||||||
|
select_stmt = '''
|
||||||
|
SELECT count(solution.rowid) AS num_solutions
|
||||||
|
FROM solution
|
||||||
|
JOIN submission ON (solution.submission_rowid = submission.rowid)
|
||||||
|
JOIN redditor ON (solution.author_rowid = redditor.rowid)
|
||||||
|
-- JOIN comment ON (solution.comment_rowid = comment.rowid)
|
||||||
|
WHERE submission.id = :submission_id
|
||||||
|
AND redditor.id = :author_id
|
||||||
|
-- AND comment.author_id = :author_id
|
||||||
|
'''
|
||||||
|
self.cursor.execute(select_stmt, {'submission_id': submission.id, 'author_id': solver.id})
|
||||||
|
row = self.cursor.fetchone()
|
||||||
|
return row and row['num_solutions'] > 0
|
||||||
|
|
||||||
|
def add_point_for_solution(self, submission, solver, solution_comment, chooser, chosen_by_comment):
|
||||||
|
self._add_submission(submission)
|
||||||
|
self._add_comment(solution_comment, solver)
|
||||||
|
self._add_comment(chosen_by_comment, chooser)
|
||||||
|
|
||||||
def remove_point(self, redditor):
|
self._update_points(solver, 1)
|
||||||
return self._update_points(redditor, -1)
|
# rowcount = self._add_solution(submission, solution_comment, chosen_by_comment)
|
||||||
|
rowcount = self._add_solution(submission, solver, solution_comment, chosen_by_comment)
|
||||||
|
if rowcount == 0:
|
||||||
|
# Was not able to add solution, probably because user has already solved this submission
|
||||||
|
self._update_points(solver, -1)
|
||||||
|
# if rowcount > 0:
|
||||||
|
# rowcount = self._update_points(solver, 1)
|
||||||
|
# # TODO update author_rowid for comment?
|
||||||
|
return rowcount
|
||||||
|
|
||||||
|
# def remove_point_for_solution(self, submission, solver, solution_comment, remover, removed_by_comment):
|
||||||
|
# def remove_point_for_solution(self, submission, solver, remover, removed_by_comment):
|
||||||
|
def soft_remove_point_for_solution(self, submission, solver, remover, removed_by_comment):
|
||||||
|
# submission = removed_by_comment.submission
|
||||||
|
self._add_comment(removed_by_comment, remover)
|
||||||
|
# rowcount = self._soft_remove_solution(submission, solution_comment, removed_by_comment)
|
||||||
|
rowcount = self._soft_remove_solution(submission, solver, removed_by_comment)
|
||||||
|
if rowcount > 0:
|
||||||
|
rowcount = self._update_points(solver, -1)
|
||||||
|
# TODO move "remove redditor" logic here since it doesn't need to be considered when adding points?
|
||||||
|
return rowcount
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def add_back_point_for_solution(self, submission, solver):
|
||||||
|
self._update_points(solver, 1)
|
||||||
|
# submission_rowid = self._get_submission_rowid(submission)
|
||||||
|
submission_rowid = self._get_rowid_from_reddit_id('submission', submission)
|
||||||
|
author_rowid = self._get_rowid_from_reddit_id('redditor', solver)
|
||||||
|
params = {'submission_rowid': submission_rowid, 'author_rowid': author_rowid}
|
||||||
|
update_stmt = '''
|
||||||
|
UPDATE solution
|
||||||
|
SET removed_by_comment_rowid = NULL
|
||||||
|
WHERE submission_rowid = :submission_rowid
|
||||||
|
AND author_rowid = :author_rowid
|
||||||
|
'''
|
||||||
|
return self.cursor.execute(update_stmt, params)
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def remove_point_and_delete_solution(self, submission, solver):
|
||||||
|
params = {
|
||||||
|
'submission_rowid': self._get_rowid_from_reddit_id('submission', submission),
|
||||||
|
'author_rowid': self._get_rowid_from_reddit_id('redditor', solver)
|
||||||
|
}
|
||||||
|
delete_stmt = '''
|
||||||
|
DELETE FROM solution
|
||||||
|
WHERE submission_rowid = :submission_rowid
|
||||||
|
AND author_rowid = :author_rowid
|
||||||
|
'''
|
||||||
|
self.cursor.execute(delete_stmt, params)
|
||||||
|
return self._update_points(solver, -1)
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def get_points(self, redditor, add_if_none=False):
|
||||||
|
params = {'id': redditor.id, 'name': redditor.name}
|
||||||
|
select_stmt = '''
|
||||||
|
SELECT points
|
||||||
|
FROM redditor
|
||||||
|
WHERE id = :id AND name = :name
|
||||||
|
'''
|
||||||
|
self.cursor.execute(select_stmt, params)
|
||||||
|
row = self.cursor.fetchone()
|
||||||
|
points = 0
|
||||||
|
if row:
|
||||||
|
points = row['points']
|
||||||
|
elif add_if_none:
|
||||||
|
self.add_redditor(redditor)
|
||||||
|
|
||||||
|
return points
|
||||||
|
|
||||||
|
### Private Methods ###
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def _get_rowid_from_reddit_id(self, table_name, reddit_object):
|
||||||
|
params = {'table_name': table_name, 'reddit_id': reddit_object.id}
|
||||||
|
self.cursor.execute('SELECT rowid FROM :table_name WHERE id = :reddit_id', params)
|
||||||
|
row = self.cursor.fetchone()
|
||||||
|
return row['rowid'] if row else None
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def _add_comment(self, comment, author):
|
||||||
|
params = {
|
||||||
|
'id': comment.id,
|
||||||
|
'author_id': author.id,
|
||||||
|
'created_at_datetime': reddit_datetime_to_iso(comment.created_utc)
|
||||||
|
}
|
||||||
|
insert_stmt = '''
|
||||||
|
INSERT INTO comment (id, author_id, created_at_datetime)
|
||||||
|
VALUES (:id, :author_id, :created_at_datetime)
|
||||||
|
'''
|
||||||
|
self.cursor.execute(insert_stmt, params)
|
||||||
|
return self.cursor.rowcount
|
||||||
|
|
||||||
|
# @transaction
|
||||||
|
# def _get_comment_rowid(self, comment):
|
||||||
|
# self.cursor.execute('SELECT rowid FROM comment WHERE id = :id', {'id': comment.id})
|
||||||
|
# row = self.cursor.fetchone()
|
||||||
|
# return row['rowid'] if row else None
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def _add_submission(self, submission):
|
||||||
|
insert_stmt = '''
|
||||||
|
INSERT OR IGNORE INTO submission (id, author_id)
|
||||||
|
VALUES (:id, :author_id)
|
||||||
|
'''
|
||||||
|
self.cursor.execute(insert_stmt, {'id': submission.id, 'author_id': submission.author.id})
|
||||||
|
return self.cursor.rowcount
|
||||||
|
|
||||||
|
# @transaction
|
||||||
|
# def _get_submission_rowid(self, submission):
|
||||||
|
# self.cursor.execute('SELECT rowid FROM submission WHERE id = :id', {'id': submission.id})
|
||||||
|
# row = self.cursor.fetchone()
|
||||||
|
# return row['rowid'] if row else None
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
def _add_solution(self, submission, solver, comment, chosen_by_comment):
|
||||||
|
# submission_rowid = self._get_submission_rowid(submission)
|
||||||
|
# comment_rowid = self._get_comment_rowid(comment)
|
||||||
|
# chosen_by_comment_rowid = self._get_comment_rowid(chosen_by_comment)
|
||||||
|
submission_rowid = self._get_rowid_from_reddit_id('submission', submission)
|
||||||
|
author_rowid = self._get_rowid_from_reddit_id('redditor', solver)
|
||||||
|
comment_rowid = self._get_rowid_from_reddit_id('comment', comment)
|
||||||
|
chosen_by_comment_rowid = self._get_rowid_from_reddit_id('comment', chosen_by_comment)
|
||||||
|
params = {
|
||||||
|
'submission_rowid': submission_rowid,
|
||||||
|
'author_rowid': author_rowid,
|
||||||
|
'comment_rowid': comment_rowid,
|
||||||
|
'chosen_by_comment_rowid': chosen_by_comment_rowid
|
||||||
|
}
|
||||||
|
insert_stmt = '''
|
||||||
|
INSERT INTO solution (submission_rowid, author_rowid, comment_rowid, chosen_by_comment_rowid)
|
||||||
|
VALUES (:submission_rowid, :author_rowid, :comment_rowid, :chosen_by_comment_rowid)
|
||||||
|
'''
|
||||||
|
self.cursor.execute(insert_stmt, params)
|
||||||
|
return self.cursor.rowcount
|
||||||
|
|
||||||
|
@transaction
|
||||||
|
# def _soft_remove_solution(self, submission, comment, removed_by_comment):
|
||||||
|
def _soft_remove_solution(self, submission, solver, removed_by_comment):
|
||||||
|
# submission_rowid = self._get_submission_rowid(submission)
|
||||||
|
# comment_rowid = self._get_comment_rowid(comment)
|
||||||
|
# removed_by_comment_rowid = self._get_comment_rowid(removed_by_comment)
|
||||||
|
submission_rowid = self._get_rowid_from_reddit_id('submission', submission)
|
||||||
|
author_rowid = self._get_rowid_from_reddit_id('redditor', solver)
|
||||||
|
# comment_rowid = self._get_rowid_from_reddit_id('comment', comment)
|
||||||
|
removed_by_comment_rowid = self._get_rowid_from_reddit_id('comment', removed_by_comment)
|
||||||
|
params = {
|
||||||
|
'submission_rowid': submission_rowid,
|
||||||
|
# 'comment_rowid': comment_rowid,
|
||||||
|
'author_rowid': author_rowid,
|
||||||
|
'removed_by_comment_rowid': removed_by_comment_rowid,
|
||||||
|
}
|
||||||
|
update_stmt = '''
|
||||||
|
UPDATE solution
|
||||||
|
SET removed_by_comment_rowid = :removed_by_comment_rowid
|
||||||
|
WHERE submission_rowid = :submission_rowid AND author_rowid = :author_rowid
|
||||||
|
'''
|
||||||
|
self.cursor.execute(update_stmt, params)
|
||||||
|
return self.cursor.rowcount
|
||||||
|
|
||||||
|
# @transaction
|
||||||
|
# def _get_redditor_rowid(self, redditor):
|
||||||
|
# self.cursor.execute('SELECT rowid FROM redditor WHERE id = :id', {'id': redditor.id})
|
||||||
|
# row = self.cursor.fetchone()
|
||||||
|
# return row['rowid'] if row else None
|
||||||
|
|
||||||
@transaction
|
@transaction
|
||||||
def _update_points(self, redditor, points_modifier):
|
def _update_points(self, redditor, points_modifier):
|
||||||
@@ -92,30 +352,17 @@ class Database:
|
|||||||
'points': points + points_modifier,
|
'points': points + points_modifier,
|
||||||
}
|
}
|
||||||
update_stmt = '''
|
update_stmt = '''
|
||||||
UPDATE redditor_points
|
UPDATE redditor
|
||||||
SET points = :points
|
SET points = :points
|
||||||
WHERE id = :id AND name = :name
|
WHERE id = :id AND name = :name
|
||||||
'''
|
'''
|
||||||
self.cursor.execute(update_stmt, params)
|
self.cursor.execute(update_stmt, params)
|
||||||
return self.cursor.rowcount
|
return self.cursor.rowcount
|
||||||
|
|
||||||
@transaction
|
|
||||||
def get_points(self, redditor, add_if_none=False):
|
|
||||||
params = {'id': redditor.id, 'name': redditor.name}
|
|
||||||
select_stmt = '''
|
|
||||||
SELECT points
|
|
||||||
FROM redditor_points
|
|
||||||
WHERE id = :id AND name = :name
|
|
||||||
'''
|
|
||||||
self.cursor.execute(select_stmt, params)
|
|
||||||
row = self.cursor.fetchone()
|
|
||||||
if row:
|
|
||||||
points = row['points']
|
|
||||||
elif add_if_none:
|
|
||||||
points = 0
|
|
||||||
self.add_redditor(redditor)
|
|
||||||
else:
|
|
||||||
points = 0
|
|
||||||
|
|
||||||
return points
|
### Utility ###
|
||||||
|
|
||||||
|
|
||||||
|
def reddit_datetime_to_iso(datetime):
|
||||||
|
return datetime.datetime.utcfromtimestamp(datetime).isoformat()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user