thread watcher writes to database incase of disconnect

This commit is contained in:
iou1name 2018-02-13 16:31:23 -05:00
parent 29b740cd33
commit fb2637a14e
2 changed files with 259 additions and 221 deletions

9
db.py
View File

@ -1,6 +1,3 @@
# coding=utf-8
from __future__ import unicode_literals, absolute_import, print_function, division
import json import json
import os.path import os.path
import sys import sys
@ -8,17 +5,13 @@ import sqlite3
from tools import Identifier from tools import Identifier
if sys.version_info.major >= 3:
unicode = str
basestring = str
def _deserialize(value): def _deserialize(value):
if value is None: if value is None:
return None return None
# sqlite likes to return ints for strings that look like ints, even though # sqlite likes to return ints for strings that look like ints, even though
# the column type is string. That's how you do dynamic typing wrong. # the column type is string. That's how you do dynamic typing wrong.
value = unicode(value) value = str(value)
# Just in case someone's mucking with the DB in a way we can't account for, # Just in case someone's mucking with the DB in a way we can't account for,
# ignore json parsing errors # ignore json parsing errors
try: try:

View File

@ -15,6 +15,27 @@ def setup(bot):
""" """
bot.memory["watcher"] = {} bot.memory["watcher"] = {}
con = bot.db.connect()
cur = con.cursor()
try:
watching = cur.execute("SELECT * FROM watcher").fetchall()
except:
cur.execute("CREATE TABLE watcher("
"api_url STRING PRIMARY KEY,"
"name STRING DEFAULT 'Anonymous',"
"last_post INT,"
"time_since STRING,"
"channel STRING)")
cur.commit()
con.close()
else:
for thread in watching:
t = WatcherThread(bot, thread[0], thread[1], thread[2], thread[3],
thread[4])
t.start()
bot.memory["watcher"][get_thread_url(thread[0])] = t
con.close()
def get_time(): def get_time():
""" """
@ -64,7 +85,9 @@ def watch(bot, trigger):
A thread watcher for 4chan. A thread watcher for 4chan.
""" """
url = trigger.group(3) url = trigger.group(3)
op_name = trigger.group(4) name = trigger.group(4)
if not name:
name = "Anonymous"
if url in bot.memory["watcher"].keys(): if url in bot.memory["watcher"].keys():
return bot.say("Error: I'm already watching that thread.") return bot.say("Error: I'm already watching that thread.")
@ -75,12 +98,21 @@ def watch(bot, trigger):
return bot.say("404: thread not found") return bot.say("404: thread not found")
thread = res.json() thread = res.json()
last_post = get_last_post(thread, op_name) last_post = get_last_post(thread, name)
time_since = get_time() time_since = get_time()
t = WatcherThread(bot, api_url, op_name, last_post, time_since) t = WatcherThread(bot, api_url, name, last_post, time_since, trigger.sender)
t.start() t.start()
bot.memory["watcher"][url] = t bot.memory["watcher"][url] = t
con = bot.db.connect()
cur = con.cursor()
cur.execute("INSERT INTO watcher(api_url, name, last_post, time_since, channel)"
" VALUES(?,?,?,?,?)", (api_url, name, last_post, time_since,
trigger.sender))
con.commit()
con.close()
bot.say("[\x0304Watcher\x03] Watching thread: \x0307" + url) bot.say("[\x0304Watcher\x03] Watching thread: \x0307" + url)
@ -96,51 +128,64 @@ def unwatch(bot, trigger):
bot.memory["watcher"].pop(url) bot.memory["watcher"].pop(url)
except KeyError: except KeyError:
return bot.say("Error: I'm not watching that thread.") return bot.say("Error: I'm not watching that thread.")
return bot.say("[\x0304Watcher\x03] No longer watching: \x0307" + url)
con = bot.db.connect()
cur = con.cursor()
cur.execute("DELETE FROM watcher WHERE api_url = ?", (get_api_url(url),))
con.commit()
con.close()
bot.say("[\x0304Watcher\x03] No longer watching: \x0307" + url)
class WatcherThread(threading.Thread): class WatcherThread(threading.Thread):
def __init__(self, bot, api_url, op_name, last_post, time_since): def __init__(self, bot, api_url, name, last_post, time_since, channel):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.stop = threading.Event() self.stop = threading.Event()
self.period = 20 self.period = 20
self.bot = bot self.bot = bot
self.api_url = api_url self.api_url = api_url
self.op_name = op_name self.name = name
self.last_post = last_post self.last_post = last_post
self.time_since = time_since self.time_since = time_since
self.channel = channel
def run(self): def run(self):
while not self.stop.is_set(): while not self.stop.is_set():
self.stop.wait(self.period)
headers = {"If-Modified-Since": self.time_since} headers = {"If-Modified-Since": self.time_since}
try:
res = requests.get(self.api_url, headers=headers, verify=True) res = requests.get(self.api_url, headers=headers, verify=True)
self.time_since = get_time() self.time_since = get_time()
except urllib3.exceptions.NewConnectionError:
print(f"Watcher: Thread {self.api_url}: Connection error")
continue
if res.status_code == 404: if res.status_code == 404:
msg = "[\x0304Watcher\x03] Thread deleted: " \ msg = "[\x0304Watcher\x03] Thread deleted: " \
+ f"\x0307{get_thread_url(self.api_url)}" + f"\x0307{get_thread_url(self.api_url)}"
self.bot.say(msg) self.bot.say(msg, channel)
self.stop.set() self.stop.set()
continue continue
if res.status_code == 304: if res.status_code == 304:
self.stop.wait(self.period)
continue continue
thread = res.json() thread = res.json()
if thread["posts"][0].get("closed"): if thread["posts"][0].get("closed"):
msg = "[\x0304Watcher\x03] Thread closed: " \ msg = "[\x0304Watcher\x03] Thread closed: " \
+ f"\x0307{get_thread_url(self.api_url)}" + f"\x0307{get_thread_url(self.api_url)}"
self.bot.say(msg) self.bot.say(msg, channel)
self.stop.set() self.stop.set()
continue continue
new_last_post = get_last_post(thread, self.op_name) new_last_post = get_last_post(thread, self.name)
if new_last_post > self.last_post: if new_last_post > self.last_post:
self.last_post = new_last_post self.last_post = new_last_post
msg = "[\x0304Watcher\x03] New post from \x0308" \ msg = "[\x0304Watcher\x03] New post from \x0308" \
+ f"{self.op_name}\x03 in \x0307{get_thread_url(self.api_url)}" + f"{self.name}\x03 in \x0307{get_thread_url(self.api_url)}"
self.bot.say(msg) self.bot.say(msg, channel)
self.stop.wait(self.period)