|
@@ -20,6 +20,7 @@ |
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
|
# SOFTWARE. |
|
|
# SOFTWARE. |
|
|
|
|
|
|
|
|
|
|
|
from datetime import datetime |
|
|
from os import path |
|
|
from os import path |
|
|
import sqlite3 as sqlite |
|
|
import sqlite3 as sqlite |
|
|
from threading import Lock |
|
|
from threading import Lock |
|
@@ -42,7 +43,6 @@ class Notes(Command): |
|
|
"read": self.do_read, |
|
|
"read": self.do_read, |
|
|
"edit": self.do_edit, |
|
|
"edit": self.do_edit, |
|
|
"info": self.do_info, |
|
|
"info": self.do_info, |
|
|
"history": self.do_history, |
|
|
|
|
|
"rename": self.do_rename, |
|
|
"rename": self.do_rename, |
|
|
"delete": self.do_delete, |
|
|
"delete": self.do_delete, |
|
|
} |
|
|
} |
|
@@ -58,15 +58,6 @@ class Notes(Command): |
|
|
else: |
|
|
else: |
|
|
self.reply("Unknown subcommand: \x0303{0}\x0F.".format(command)) |
|
|
self.reply("Unknown subcommand: \x0303{0}\x0F.".format(command)) |
|
|
|
|
|
|
|
|
def create_db(self, conn): |
|
|
|
|
|
"""Initialize the notes database with its necessary tables.""" |
|
|
|
|
|
script = """ |
|
|
|
|
|
CREATE TABLE entries (entry_id, entry_slug, entry_title, entry_revision); |
|
|
|
|
|
CREATE TABLE users (user_id, user_host); |
|
|
|
|
|
CREATE TABLE revisions (rev_id, rev_entry, rev_user, rev_timestamp, rev_content); |
|
|
|
|
|
""" |
|
|
|
|
|
conn.executescript(script) |
|
|
|
|
|
|
|
|
|
|
|
def do_list(self, data): |
|
|
def do_list(self, data): |
|
|
"""Show a list of entries in the notes database.""" |
|
|
"""Show a list of entries in the notes database.""" |
|
|
query = "SELECT entry_title FROM entries" |
|
|
query = "SELECT entry_title FROM entries" |
|
@@ -95,7 +86,7 @@ class Notes(Command): |
|
|
with sqlite.connect(self._dbfile) as conn, self._db_access_lock: |
|
|
with sqlite.connect(self._dbfile) as conn, self._db_access_lock: |
|
|
try: |
|
|
try: |
|
|
title, content = conn.execute(query, (slug,)).fetchone() |
|
|
title, content = conn.execute(query, (slug,)).fetchone() |
|
|
except sqlite.OperationalError: |
|
|
|
|
|
|
|
|
except (sqlite.OperationalError, TypeError): |
|
|
title, content = slug, None |
|
|
title, content = slug, None |
|
|
|
|
|
|
|
|
if content: |
|
|
if content: |
|
@@ -105,22 +96,60 @@ class Notes(Command): |
|
|
|
|
|
|
|
|
def do_edit(self, data): |
|
|
def do_edit(self, data): |
|
|
"""Edit an entry in the notes database.""" |
|
|
"""Edit an entry in the notes database.""" |
|
|
pass |
|
|
|
|
|
|
|
|
query1 = """SELECT entry_id, entry_title, user_host FROM entries |
|
|
|
|
|
INNER JOIN revisions ON entry_revision = rev_id |
|
|
|
|
|
INNER JOIN users ON rev_user = user_id |
|
|
|
|
|
WHERE entry_slug = ?""" |
|
|
|
|
|
query2 = "INSERT INTO revisions VALUES (?, ?, ?, ?, ?)" |
|
|
|
|
|
query3 = "INSERT INTO entries VALUES (?, ?, ?, ?)" |
|
|
|
|
|
query4 = "UPDATE entries SET entry_revision = ? WHERE entry_id = ?" |
|
|
|
|
|
try: |
|
|
|
|
|
slug = data.args[1].lower().replace("_", "").replace("-", "") |
|
|
|
|
|
except IndexError: |
|
|
|
|
|
self.reply(data, "Please name an entry to edit.") |
|
|
|
|
|
return |
|
|
|
|
|
content = " ".join(data.args[2:]).strip() |
|
|
|
|
|
if not content: |
|
|
|
|
|
self.reply(data, "Please give some content to put in the entry.") |
|
|
|
|
|
return |
|
|
|
|
|
|
|
|
|
|
|
with sqlite.connect(self._dbfile) as conn, self._db_access_lock: |
|
|
|
|
|
create = True |
|
|
|
|
|
try: |
|
|
|
|
|
id_, title, author = conn.execute(query1, (slug,)).fetchone() |
|
|
|
|
|
create = False |
|
|
|
|
|
except sqlite.OperationalError: |
|
|
|
|
|
id_, title, author = 1, data.args[1], data.host |
|
|
|
|
|
self.create_db(conn) |
|
|
|
|
|
except TypeError: |
|
|
|
|
|
id_ = self.get_next_entry(conn) |
|
|
|
|
|
title, author = data.args[1], data.host |
|
|
|
|
|
permdb = self.config.irc["permissions"] |
|
|
|
|
|
if author != data.host and not permdb.is_admin(data): |
|
|
|
|
|
msg = "You must be an author or a bot admin to edit this entry." |
|
|
|
|
|
self.reply(data, msg) |
|
|
|
|
|
return |
|
|
|
|
|
revid = self.get_next_revision(conn) |
|
|
|
|
|
userid = self.get_user(conn, data.host) |
|
|
|
|
|
now = datetime.utcnow() |
|
|
|
|
|
conn.execute(query2, (revid, id_, userid, now, content)) |
|
|
|
|
|
if create: |
|
|
|
|
|
conn.execute(query3, (id_, slug, title, revid)) |
|
|
|
|
|
else: |
|
|
|
|
|
conn.execute(query4, (revid, id_)) |
|
|
|
|
|
|
|
|
|
|
|
self.reply(data, "Entry \x0302{0}\x0F updated.".format(title)) |
|
|
|
|
|
|
|
|
def do_info(self, data): |
|
|
def do_info(self, data): |
|
|
"""Get info on an entry in the notes database.""" |
|
|
"""Get info on an entry in the notes database.""" |
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def do_history(self, data): |
|
|
|
|
|
"""Get the history of an entry in the notes database.""" |
|
|
|
|
|
query = """SELECT entry_title, rev_timestamp, user_host FROM entries |
|
|
query = """SELECT entry_title, rev_timestamp, user_host FROM entries |
|
|
INNER JOIN revisions ON entry_revision = rev_id |
|
|
|
|
|
|
|
|
INNER JOIN revisions ON entry_id = rev_entry |
|
|
INNER JOIN users ON rev_user = user_id |
|
|
INNER JOIN users ON rev_user = user_id |
|
|
WHERE entry_slug = ?""" |
|
|
WHERE entry_slug = ?""" |
|
|
try: |
|
|
try: |
|
|
slug = data.args[1].lower().replace("_", "").replace("-", "") |
|
|
slug = data.args[1].lower().replace("_", "").replace("-", "") |
|
|
except IndexError: |
|
|
except IndexError: |
|
|
self.reply(data, "Please name an entry to get the history of.") |
|
|
|
|
|
|
|
|
self.reply(data, "Please name an entry to get info on.") |
|
|
return |
|
|
return |
|
|
|
|
|
|
|
|
with sqlite.connect(self._dbfile) as conn, self._db_access_lock: |
|
|
with sqlite.connect(self._dbfile) as conn, self._db_access_lock: |
|
@@ -151,3 +180,39 @@ class Notes(Command): |
|
|
def do_delete(self, data): |
|
|
def do_delete(self, data): |
|
|
"""Delete an entry from the notes database.""" |
|
|
"""Delete an entry from the notes database.""" |
|
|
pass |
|
|
pass |
|
|
|
|
|
|
|
|
|
|
|
def create_db(self, conn): |
|
|
|
|
|
"""Initialize the notes database with its necessary tables.""" |
|
|
|
|
|
script = """ |
|
|
|
|
|
CREATE TABLE entries (entry_id, entry_slug, entry_title, |
|
|
|
|
|
entry_revision); |
|
|
|
|
|
CREATE TABLE users (user_id, user_host); |
|
|
|
|
|
CREATE TABLE revisions (rev_id, rev_entry, rev_user, rev_timestamp, |
|
|
|
|
|
rev_content); |
|
|
|
|
|
""" |
|
|
|
|
|
conn.executescript(script) |
|
|
|
|
|
|
|
|
|
|
|
def get_next_entry(self, conn): |
|
|
|
|
|
"""Get the next entry ID.""" |
|
|
|
|
|
query = "SELECT MAX(entry_id) FROM entries" |
|
|
|
|
|
next = conn.execute(query).fetchone()[0] |
|
|
|
|
|
return next + 1 if next else 1 |
|
|
|
|
|
|
|
|
|
|
|
def get_next_revision(self, conn): |
|
|
|
|
|
"""Get the next revision ID.""" |
|
|
|
|
|
query = "SELECT MAX(rev_id) FROM revisions" |
|
|
|
|
|
next = conn.execute(query).fetchone()[0] |
|
|
|
|
|
return next + 1 if next else 1 |
|
|
|
|
|
|
|
|
|
|
|
def get_user(self, conn, host): |
|
|
|
|
|
"""Get the user ID corresponding to a hostname, or make one.""" |
|
|
|
|
|
query1 = "SELECT user_host FROM users WHERE user_id = ?" |
|
|
|
|
|
query2 = "SELECT MAX(user_id) FROM users" |
|
|
|
|
|
query3 = "INSERT INTO users VALUES (?, ?)" |
|
|
|
|
|
user = conn.execute(query1).fetchone()[0] |
|
|
|
|
|
if user: |
|
|
|
|
|
return user |
|
|
|
|
|
last = conn.execute(query2).fetchone()[0] |
|
|
|
|
|
next = last + 1 if last else 1 |
|
|
|
|
|
conn.execute(query3, (next, host)) |
|
|
|
|
|
return next |