Cleanup & ideas

This commit is contained in:
Collin Rapp
2020-08-25 22:23:16 -07:00
parent df63269739
commit 2387e67004
13 changed files with 163 additions and 24 deletions

5
.gitignore vendored
View File

@@ -4,10 +4,7 @@
*.pyc
__pycache__
build/
dist/
releases/
*.html
*.out
*.swp
/.vscode/

View File

@@ -4,6 +4,7 @@ url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
pylint = "*"
[packages]
toml = "*"

116
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "c5de2f495184b77e04ef9eeabbf802ca765c0a28bc36b8e6f84da0dcac053224"
"sha256": "eb0083fecb64a3387eba2a1da2fb9fd3600b34c11989342104f415e9c2568676"
},
"pipfile-spec": 6,
"requires": {
@@ -96,5 +96,117 @@
"version": "==0.57.0"
}
},
"develop": {}
"develop": {
"astroid": {
"hashes": [
"sha256:2f4078c2a41bf377eea06d71c9d2ba4eb8f6b1af2135bec27bbbb7d8f12bb703",
"sha256:bc58d83eb610252fd8de6363e39d4f1d0619c894b0ed24603b881c02e64c7386"
],
"version": "==2.4.2"
},
"colorama": {
"hashes": [
"sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff",
"sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"
],
"markers": "sys_platform == 'win32'",
"version": "==0.4.3"
},
"isort": {
"hashes": [
"sha256:60a1b97e33f61243d12647aaaa3e6cc6778f5eb9f42997650f1cc975b6008750",
"sha256:d488ba1c5a2db721669cc180180d5acf84ebdc5af7827f7aaeaa75f73cf0e2b8"
],
"version": "==5.4.2"
},
"lazy-object-proxy": {
"hashes": [
"sha256:0c4b206227a8097f05c4dbdd323c50edf81f15db3b8dc064d08c62d37e1a504d",
"sha256:194d092e6f246b906e8f70884e620e459fc54db3259e60cf69a4d66c3fda3449",
"sha256:1be7e4c9f96948003609aa6c974ae59830a6baecc5376c25c92d7d697e684c08",
"sha256:4677f594e474c91da97f489fea5b7daa17b5517190899cf213697e48d3902f5a",
"sha256:48dab84ebd4831077b150572aec802f303117c8cc5c871e182447281ebf3ac50",
"sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd",
"sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239",
"sha256:8d859b89baf8ef7f8bc6b00aa20316483d67f0b1cbf422f5b4dc56701c8f2ffb",
"sha256:9254f4358b9b541e3441b007a0ea0764b9d056afdeafc1a5569eee1cc6c1b9ea",
"sha256:9651375199045a358eb6741df3e02a651e0330be090b3bc79f6d0de31a80ec3e",
"sha256:97bb5884f6f1cdce0099f86b907aa41c970c3c672ac8b9c8352789e103cf3156",
"sha256:9b15f3f4c0f35727d3a0fba4b770b3c4ebbb1fa907dbcc046a1d2799f3edd142",
"sha256:a2238e9d1bb71a56cd710611a1614d1194dc10a175c1e08d75e1a7bcc250d442",
"sha256:a6ae12d08c0bf9909ce12385803a543bfe99b95fe01e752536a60af2b7797c62",
"sha256:ca0a928a3ddbc5725be2dd1cf895ec0a254798915fb3a36af0964a0a4149e3db",
"sha256:cb2c7c57005a6804ab66f106ceb8482da55f5314b7fcb06551db1edae4ad1531",
"sha256:d74bb8693bf9cf75ac3b47a54d716bbb1a92648d5f781fc799347cfc95952383",
"sha256:d945239a5639b3ff35b70a88c5f2f491913eb94871780ebfabb2568bd58afc5a",
"sha256:eba7011090323c1dadf18b3b689845fd96a61ba0a1dfbd7f24b921398affc357",
"sha256:efa1909120ce98bbb3777e8b6f92237f5d5c8ea6758efea36a473e1d38f7d3e4",
"sha256:f3900e8a5de27447acbf900b4750b0ddfd7ec1ea7fbaf11dfa911141bc522af0"
],
"version": "==1.4.3"
},
"mccabe": {
"hashes": [
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
"sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"
],
"version": "==0.6.1"
},
"pylint": {
"hashes": [
"sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210",
"sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f"
],
"index": "pypi",
"version": "==2.6.0"
},
"six": {
"hashes": [
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
"version": "==1.15.0"
},
"toml": {
"hashes": [
"sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
"sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
],
"index": "pypi",
"version": "==0.10.1"
},
"typed-ast": {
"hashes": [
"sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355",
"sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919",
"sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa",
"sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652",
"sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75",
"sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01",
"sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d",
"sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1",
"sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907",
"sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c",
"sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3",
"sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b",
"sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614",
"sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb",
"sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b",
"sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41",
"sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6",
"sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34",
"sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe",
"sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4",
"sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"
],
"markers": "implementation_name == 'cpython' and python_version < '3.8'",
"version": "==1.4.1"
},
"wrapt": {
"hashes": [
"sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"
],
"version": "==1.12.1"
}
}
}

View File

View File

@@ -2,6 +2,8 @@
## General
* [X] Initial/Basic Logging
* Especially when unable to handle a comment
## File-Specific
### bot.py

View File

@@ -20,3 +20,22 @@ To ensure that a point is awarded to the correct user:
could simple check that one of the comments in the comment tree belongs to
that user, and then award them the point.
- Honestly, this is probably overcomplicated and unnecessary, though.
## Multiple behaviors
Implement the concept of actions, with a mapping between trigger keywords/patterns and actions. This will allow for multiple behaviors (eg mark as solved for one behavior, and just show points when summoned for another).
Maybe allow chains of actions. For example:
1. OP comments "!solved"
2. Bot receives comment
3. Action 1: Determine whether is "!solved" comment
4. Action 2: Determine solver
5. Action 3: Add points
6. Action 4: Reply
## Making the bot easier to configure
Allow bot user to just specify a list of strings to recognize to trigger the bot's response. Allow user to specify whether case-sensitive. Ways to do this, with varying performance:
* Just search each text for each keyword;
* Use `re.compile()` for each keyword before searching (*may* be faster?); or
* Build a binary search tree for all keywords for each action

View File

@@ -2,4 +2,3 @@
## End-to-end Testing Scenarios

View File

@@ -6,10 +6,17 @@ File-specific lists are in loose descending order of priority.
n/a
## Bugs
* [ ] Users can get multiple points for same solution
- Scenario:
- OP comments !solved
- OP deletes !solved comment
- OP comments !solved again
- Hopefully this will be easily solved once db migrations are working
## General
* [ ] Logging
* Especially when unable to handle a comment
* [ ] Notifications
* Let admins know if a comment can't be properly handled
* Email preferable; could do Reddit message, too
@@ -17,6 +24,7 @@ n/a
* [ ] Testing
- Any PRAW model that inherits from `praw.PRAWBase` has a `parse` method
that could perhaps be used to make fake objects for testing
- Add regression tests for comments, etc.?
* [ ] GUI
- [ ] Create a GUI for configuring and running the bot, and performing other jobs
like adding or subtracting points for specific redditors
@@ -52,6 +60,7 @@ n/a
### bot.py
* [ ] (Maybe) sanitize input text?
* [ ] Now that the date of each solution is being stored, can check for missed
submissions each time the bot is run by searching subreddit history until
last solution found

View File

@@ -47,21 +47,26 @@ def run():
password=cfg.password,
user_agent=USER_AGENT)
logging.info('Connected to Reddit as %s', reddit.user.me())
if not reddit.read_only:
logging.info('Has write access to Reddit')
else:
logging.warning('Has read-only access to Reddit')
access_type = 'read-only' if reddit.read_only else 'write'
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)
logging.info('Watching subreddit %s', subreddit.title)
if subreddit.moderator(redditor=reddit.user.me()):
logging.info('Is moderator for monitored subreddit')
else:
logging.warning('Is NOT moderator for monitored subreddit')
is_mod = subreddit.moderator(redditor=reddit.user.me())
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)
# Ignoring other potential exceptions for now, since we may not be able
# to recover from them as well as from this one
# to recover from them as well as from these ones
except prawcore.exceptions.RequestException as e:
logging.error('Unable to connect to Reddit')
logging.error('Error message: %s', e)
@@ -75,7 +80,7 @@ def run():
def monitor_comments(reddit, subreddit, db, levels, cfg):
"""Monitor new comments in the subreddit, looking for confirmed solutions."""
# Passing pause_after=0 will bypass the internal exponential delay, but have
# to check if any comments are returned with each query
# to check if any comments are returned after each query
for comm in subreddit.stream.comments(skip_existing=True, pause_after=0):
if comm is None:
continue
@@ -288,4 +293,3 @@ def log_solution_info(comm):
logging.debug('Author: %s', comm.parent().author.name)
logging.debug('Body: %s', comm.parent().body)

View File

@@ -191,4 +191,3 @@ def interactive_config(dest):
toml.dump(configvals, f)
print('#' * 80 + f'\nConfig settings saved to {dest}\n' + '#' * 80)

View File

@@ -104,4 +104,3 @@ class Database:
return points

View File

@@ -40,4 +40,3 @@ def user_level_info(points, levels):
def is_max_level(level_info):
return not level_info.next

View File

@@ -153,4 +153,3 @@ def footer(feedback_url=None, scoreboard_url=None):
# '| [Feedback](https://forms.gle/m94aGjFQwGopqQ836) '
# '| [Source Code](https://github.com/cur33/PointsBot))')