Allowed mods to comment /solved in any scenario
This commit is contained in:
5
docs/TESTS.md
Normal file
5
docs/TESTS.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# TESTS
|
||||||
|
|
||||||
|
## End-to-end Testing Scenarios
|
||||||
|
|
||||||
|
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
- https://developer.github.com/v3/repos/contents/#get-archive-link
|
- https://developer.github.com/v3/repos/contents/#get-archive-link
|
||||||
- https://developer.github.com/v3/repos/commits/
|
- https://developer.github.com/v3/repos/commits/
|
||||||
- https://developer.github.com/v3/repos/releases/
|
- https://developer.github.com/v3/repos/releases/
|
||||||
|
- https://developer.github.com/v3/#timezones
|
||||||
- Webhooks:
|
- Webhooks:
|
||||||
- https://developer.github.com/webhooks/
|
- https://developer.github.com/webhooks/
|
||||||
- https://developer.github.com/v3/repos/hooks/
|
- https://developer.github.com/v3/repos/hooks/
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
|
|
||||||
### bot.py
|
### bot.py
|
||||||
|
|
||||||
|
* [ ] Allow mods to use "/[Ss]olved" in any context
|
||||||
* [ ] Allow mods and/or bot owner to add or remove points from specific users
|
* [ ] Allow mods and/or bot owner to add or remove points from specific users
|
||||||
* [ ] Make the algorithm for determining the problem solver more sophisticated
|
* [ ] Make the algorithm for determining the problem solver more sophisticated
|
||||||
- e.g. check entire comment tree instead of just ignoring if the OP also
|
- e.g. check entire comment tree instead of just ignoring if the OP also
|
||||||
@@ -79,18 +81,19 @@
|
|||||||
|
|
||||||
### database.py
|
### database.py
|
||||||
|
|
||||||
|
* [ ] Store date for each "!solved" comment
|
||||||
* [ ] Possibly refactor for a datastore type thing instead of database
|
* [ ] Possibly refactor for a datastore type thing instead of database
|
||||||
- Maybe even make models like Redditor to combine data storage/access with
|
- Maybe even make models like Redditor to combine data storage/access with
|
||||||
logic, e.g. determining current level
|
logic, e.g. determining current level
|
||||||
|
|
||||||
### reply.py
|
### reply.py
|
||||||
|
|
||||||
* [ ] For the footer section of the reply comment regarding the bot, could have the
|
* [X] Fix progress bar
|
||||||
|
* ~~For the footer section of the reply comment regarding the bot, could have the
|
||||||
bot make a post on its account explaining itself, and link to that (and then
|
bot make a post on its account explaining itself, and link to that (and then
|
||||||
also link to the source code separately, and perhaps in that post, too).
|
also link to the source code separately, and perhaps in that post, too).
|
||||||
Could even have the bot make this post automatically if it doesn't have a
|
Could even have the bot make this post automatically if it doesn't have a
|
||||||
link to the post in its config, and then store the link for future use.
|
link to the post in its config, and then store the link for future use.~~
|
||||||
* [X] Fix progress bar
|
|
||||||
|
|
||||||
## Ideas
|
## Ideas
|
||||||
|
|
||||||
|
|||||||
104
pointsbot/bot.py
104
pointsbot/bot.py
@@ -13,8 +13,6 @@ USER_AGENT = 'PointsBot (by u/GlipGlorp7)'
|
|||||||
SOLVED_PAT = re.compile('![Ss]olved')
|
SOLVED_PAT = re.compile('![Ss]olved')
|
||||||
MOD_SOLVED_PAT = re.compile('/[Ss]olved')
|
MOD_SOLVED_PAT = re.compile('/[Ss]olved')
|
||||||
|
|
||||||
TEST_COMMENTS = False
|
|
||||||
|
|
||||||
### Main Function ###
|
### Main Function ###
|
||||||
|
|
||||||
|
|
||||||
@@ -35,10 +33,6 @@ def run():
|
|||||||
is_mod = bool(subreddit.moderator(redditor=reddit.user.me()))
|
is_mod = bool(subreddit.moderator(redditor=reddit.user.me()))
|
||||||
print_level(1, f'Is mod? {is_mod}')
|
print_level(1, f'Is mod? {is_mod}')
|
||||||
|
|
||||||
if TEST_COMMENTS:
|
|
||||||
make_comments(subreddit, levels)
|
|
||||||
return
|
|
||||||
|
|
||||||
db = database.Database(cfg.database_path)
|
db = database.Database(cfg.database_path)
|
||||||
|
|
||||||
# Monitor new comments for confirmed solutions
|
# Monitor new comments for confirmed solutions
|
||||||
@@ -51,43 +45,46 @@ def run():
|
|||||||
print_level(0, '\nFound comment')
|
print_level(0, '\nFound comment')
|
||||||
print_level(1, f'Comment text: "{comm.body}"')
|
print_level(1, f'Comment text: "{comm.body}"')
|
||||||
|
|
||||||
if marks_as_solved(comm):
|
if not marks_as_solved(comm):
|
||||||
if not is_first_solution(comm):
|
print_level(1, 'Not a "![Ss]olved" comment')
|
||||||
# Skip this "!solved" comment and wait for the next
|
continue
|
||||||
print_level(1, 'Not the first solution')
|
|
||||||
continue
|
|
||||||
|
|
||||||
print_level(1, 'This is the first solution')
|
if is_mod_comment(comm):
|
||||||
print_solution_info(comm)
|
print_level(1, 'Mod comment')
|
||||||
|
elif not is_first_solution(comm):
|
||||||
|
# Skip this "!solved" comment and wait for the next
|
||||||
|
print_level(1, 'Not the first solution')
|
||||||
|
continue
|
||||||
|
|
||||||
solver = comm.parent().author
|
print_level(1, 'This is the first solution found')
|
||||||
print_level(1, f'Adding point for {solver.name}')
|
print_solution_info(comm)
|
||||||
db.add_point(solver)
|
|
||||||
points = db.get_points(solver)
|
|
||||||
print_level(1, f'Points for {solver.name}: {points}')
|
|
||||||
|
|
||||||
level_info = level.user_level_info(points, levels)
|
solver = find_solver(comm)
|
||||||
|
db.add_point(solver)
|
||||||
|
print_level(1, f'Added point for {solver.name}')
|
||||||
|
|
||||||
# Reply to the comment marking the submission as solved
|
points = db.get_points(solver)
|
||||||
reply_body = reply.make(solver, points, level_info)
|
print_level(1, f'Total points for {solver.name}: {points}')
|
||||||
print_level(1, f'Replying with: "{reply_body}"')
|
level_info = level.user_level_info(points, levels)
|
||||||
comm.reply(reply_body)
|
|
||||||
|
|
||||||
# Check if (non-mod) user flair should be updated to new level
|
# Reply to the comment marking the submission as solved
|
||||||
lvl = level_info.current
|
reply_body = reply.make(solver, points, level_info)
|
||||||
if lvl and lvl.points == points:
|
comm.reply(reply_body)
|
||||||
print_level(1, f'User reached level: {lvl.name}')
|
print_level(1, f'Replied to comment with: "{reply_body}"')
|
||||||
if not subreddit.moderator(redditor=solver):
|
|
||||||
print_level(2, 'Setting flair')
|
# Check if (non-mod) user flair should be updated to new level
|
||||||
print_level(3, f'Flair text: {lvl.name}')
|
lvl = level_info.current
|
||||||
print_level(3, f'Flair template ID: {lvl.flair_template_id}')
|
if lvl and lvl.points == points:
|
||||||
subreddit.flair.set(solver,
|
print_level(1, f'User reached level: {lvl.name}')
|
||||||
text=lvl.name,
|
if not subreddit.moderator(redditor=solver):
|
||||||
flair_template_id=lvl.flair_template_id)
|
print_level(2, 'Setting flair')
|
||||||
else:
|
print_level(3, f'Flair text: {lvl.name}')
|
||||||
print_level(2, 'Solver is mod; don\'t alter flair')
|
print_level(3, f'Flair template ID: {lvl.flair_template_id}')
|
||||||
else:
|
subreddit.flair.set(solver,
|
||||||
print_level(1, 'Not a "!solved" comment')
|
text=lvl.name,
|
||||||
|
flair_template_id=lvl.flair_template_id)
|
||||||
|
else:
|
||||||
|
print_level(2, 'Solver is mod; don\'t alter flair')
|
||||||
|
|
||||||
|
|
||||||
### Reddit Comment Functions ###
|
### Reddit Comment Functions ###
|
||||||
@@ -110,9 +107,13 @@ def marks_as_solved(comment):
|
|||||||
return op_resp_to_solver or mod_resp_to_solver
|
return op_resp_to_solver or mod_resp_to_solver
|
||||||
|
|
||||||
|
|
||||||
|
def is_mod_comment(comment):
|
||||||
|
return comment.subreddit.moderator(redditor=comment.author)
|
||||||
|
|
||||||
|
|
||||||
def is_first_solution(solved_comment):
|
def is_first_solution(solved_comment):
|
||||||
# Retrieve any comments hidden by "more comments"
|
'''Return True if this solved comment is the first, False otherwise.'''
|
||||||
# Passing limit=0 will replace all "more comments"
|
# Retrieve any comments hidden by "more comments" by passing limit=0
|
||||||
submission = solved_comment.submission
|
submission = solved_comment.submission
|
||||||
submission.comments.replace_more(limit=0)
|
submission.comments.replace_more(limit=0)
|
||||||
|
|
||||||
@@ -127,6 +128,10 @@ def is_first_solution(solved_comment):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def find_solver(solved_comment):
|
||||||
|
return solved_comment.parent().author
|
||||||
|
|
||||||
|
|
||||||
### Debugging & Logging ###
|
### Debugging & Logging ###
|
||||||
|
|
||||||
|
|
||||||
@@ -144,22 +149,3 @@ def print_solution_info(comm):
|
|||||||
print_level(3, f'Body: {comm.body}')
|
print_level(3, f'Body: {comm.body}')
|
||||||
|
|
||||||
|
|
||||||
def make_comments(subreddit, levels):
|
|
||||||
testpoints = [1, 3, 5, 10, 15, 30, 45, 75] + list(range(100, 551, 50))
|
|
||||||
|
|
||||||
for sub in subreddit.new():
|
|
||||||
if sub.title == 'Testing comment scenarios':
|
|
||||||
redditor = sub.author
|
|
||||||
for points in testpoints:
|
|
||||||
body = f'Solver: {redditor}\n\nTotal points after solving: {points}'
|
|
||||||
print_level(0, body)
|
|
||||||
comm = sub.reply(body)
|
|
||||||
if comm:
|
|
||||||
level_info = level.user_level_info(points, levels)
|
|
||||||
body = reply.make(redditor, points, level_info)
|
|
||||||
comm.reply(body)
|
|
||||||
else:
|
|
||||||
print_level(1, 'ERROR: Unable to comment')
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
from os.path import abspath, dirname, join
|
|
||||||
import sys
|
import sys
|
||||||
|
from os.path import abspath, dirname, join
|
||||||
|
|
||||||
sys.path.insert(0, abspath(join(dirname(__file__), '..')))
|
sys.path.insert(0, abspath(join(dirname(__file__), '..')))
|
||||||
|
|
||||||
import pointsbot
|
import pointsbot
|
||||||
|
|||||||
@@ -13,6 +13,25 @@ def leftpad(msg, num_indents=1):
|
|||||||
return '\n'.join([('\t' * num_indents + l) for l in msg.split('\n')])
|
return '\n'.join([('\t' * num_indents + l) for l in msg.split('\n')])
|
||||||
|
|
||||||
|
|
||||||
|
def make_comments(subreddit, levels):
|
||||||
|
testpoints = [1, 3, 5, 10, 15, 30, 45, 75] + list(range(100, 551, 50))
|
||||||
|
|
||||||
|
for sub in subreddit.new():
|
||||||
|
if sub.title == 'Testing comment scenarios':
|
||||||
|
redditor = sub.author
|
||||||
|
for points in testpoints:
|
||||||
|
body = f'Solver: {redditor}\n\nTotal points after solving: {points}'
|
||||||
|
print_level(0, body)
|
||||||
|
comm = sub.reply(body)
|
||||||
|
if comm:
|
||||||
|
level_info = level.user_level_info(points, levels)
|
||||||
|
body = reply.make(redditor, points, level_info)
|
||||||
|
comm.reply(body)
|
||||||
|
else:
|
||||||
|
print_level(1, 'ERROR: Unable to comment')
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
### Tests ###
|
### Tests ###
|
||||||
|
|
||||||
levels = [
|
levels = [
|
||||||
|
|||||||
Reference in New Issue
Block a user