From 575d363de3b552e56b20c13b052b42f061f7e3bc Mon Sep 17 00:00:00 2001 From: Terry Geng Date: Sat, 21 Mar 2020 00:10:30 +0800 Subject: [PATCH] refactor: new database format --- database.py | 93 ++++++++++++++++++++++++++++++++++++++------------- media/file.py | 7 ++-- media/item.py | 12 ++++++- 3 files changed, 86 insertions(+), 26 deletions(-) diff --git a/database.py b/database.py index a0a0ff5..7f3c50a 100644 --- a/database.py +++ b/database.py @@ -112,10 +112,10 @@ class Condition: return self +SETTING_DB_VERSION = 1 +MUSIC_DB_VERSION = 1 class SettingsDatabase: - version = 1 - def __init__(self, db_path): self.db_path = db_path @@ -127,10 +127,10 @@ class SettingsDatabase: conn.commit() conn.close() - def has_table(self): + def has_table(self, table): conn = sqlite3.connect(self.db_path) cursor = conn.cursor() - tables = cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='botamusique';").fetchall() + tables = cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", (table,)).fetchall() conn.close() if len(tables) == 0: return False @@ -140,17 +140,16 @@ class SettingsDatabase: conn = sqlite3.connect(self.db_path) cursor = conn.cursor() - if self.has_table(): + if self.has_table('botamusique'): # check version - result = cursor.execute("SELECT value FROM botamusique WHERE section=? AND option=?", - ("bot", "db_version")).fetchall() + ver = self.getint("bot", "db_version", fallback=None) - if len(result) == 0 or int(result[0][0]) != self.version: - old_name = "botamusique_old_%s" % datetime.datetime.now().strftime("%Y%m%d") - cursor.execute("ALTER TABLE botamusique RENAME TO %s" % old_name) + if ver is None or ver != SETTING_DB_VERSION: + # old_name = "botamusique_old_%s" % datetime.datetime.now().strftime("%Y%m%d") + # cursor.execute("ALTER TABLE botamusique RENAME TO %s" % old_name) + cursor.execute("DROP TABLE botamusique") conn.commit() self.create_table() - self.set("bot", "old_db_name", old_name) else: self.create_table() @@ -165,9 +164,7 @@ class SettingsDatabase: "value TEXT, " "UNIQUE(section, option))") cursor.execute("INSERT INTO botamusique (section, option, value) " - "VALUES (?, ?, ?)", ("bot", "db_version", "1")) - cursor.execute("INSERT INTO botamusique (section, option, value) " - "VALUES (?, ?, ?)", ("bot", "music_db_version", "0")) + "VALUES (?, ?, ?)", ("bot", "db_version", SETTING_DB_VERSION)) conn.commit() conn.close() @@ -248,20 +245,61 @@ class MusicDatabase: def __init__(self, db_path): self.db_path = db_path - # connect + self.db_version_check_and_create() + + def has_table(self, table): + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + tables = cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name=?;", (table,)).fetchall() + conn.close() + if len(tables) == 0: + return False + return True + + def create_table(self): conn = sqlite3.connect(self.db_path) cursor = conn.cursor() - # check if table exists, or create one - cursor.execute("CREATE TABLE IF NOT EXISTS music (" + cursor.execute("CREATE TABLE music (" "id TEXT PRIMARY KEY, " "type TEXT, " "title TEXT, " + "keywords TEXT, " "metadata TEXT, " - "tags TEXT)") + "tags TEXT, " + "path TEXT, " + "create_at DATETIME DEFAULT CURRENT_TIMESTAMP" + ")") + cursor.execute("INSERT INTO music (id, title) " + "VALUES ('info', ?)", (MUSIC_DB_VERSION,)) + conn.commit() conn.close() + def db_version_check_and_create(self): + conn = sqlite3.connect(self.db_path) + cursor = conn.cursor() + if self.has_table('music'): + ver = cursor.execute("SELECT title FROM music WHERE id='info'").fetchone() + if ver and int(ver[0]) == MUSIC_DB_VERSION: + conn.close() + return True + else: + cursor.execute("ALTER TABLE music RENAME TO music_old") + conn.commit() + + self.create_table() + + cursor.execute("INSERT INTO music (id, type, title, metadata, tags)" + "SELECT id, type, title, metadata, tags FROM music_old") + cursor.execute("DROP TABLE music_old") + conn.commit() + conn.close() + else: + self.create_table() + + + def insert_music(self, music_dict): conn = sqlite3.connect(self.db_path) cursor = conn.cursor() @@ -269,19 +307,25 @@ class MusicDatabase: id = music_dict['id'] title = music_dict['title'] type = music_dict['type'] + path = music_dict['path'] + keywords = music_dict['keywords'] tags = ",".join(music_dict['tags']) + "," del music_dict['id'] del music_dict['title'] del music_dict['type'] del music_dict['tags'] + del music_dict['path'] + del music_dict['keywords'] - cursor.execute("INSERT OR REPLACE INTO music (id, type, title, metadata, tags) VALUES (?, ?, ?, ?, ?)", + cursor.execute("INSERT OR REPLACE INTO music (id, type, title, metadata, tags, path, keywords) VALUES (?, ?, ?, ?, ?, ?, ?)", (id, type, title, json.dumps(music_dict), - tags)) + tags, + path, + keywords)) conn.commit() conn.close() @@ -323,7 +367,7 @@ class MusicDatabase: conn = sqlite3.connect(self.db_path) cursor = conn.cursor() - results = cursor.execute("SELECT id, type, title, metadata, tags FROM music " + results = cursor.execute("SELECT id, type, title, metadata, tags, path, keywords FROM music " "WHERE %s" % condition_str, filler).fetchall() conn.close() @@ -373,8 +417,8 @@ class MusicDatabase: def query_random_music(self, count): conn = sqlite3.connect(self.db_path) cursor = conn.cursor() - results = cursor.execute("SELECT id, type, title, metadata, tags FROM music " - "WHERE id IN (SELECT id FROM music ORDER BY RANDOM() LIMIT ?)", (count,)).fetchall() + results = cursor.execute("SELECT id, type, title, metadata, tags, path, keywords FROM music " + "WHERE id != 'info' AND id IN (SELECT id FROM music ORDER BY RANDOM() LIMIT ?)", (count,)).fetchall() conn.close() return self._result_to_dict(results) @@ -388,6 +432,9 @@ class MusicDatabase: music_dict['title'] = result[2] music_dict['id'] = result[0] music_dict['tags'] = result[4].strip(",").split(",") + if result[5]: + music_dict['path'] = result[5] + music_dict['keywords'] = result[6] if not music_dict['tags'][0]: music_dict['tags'] = [] diff --git a/media/file.py b/media/file.py index 4718ea3..146faf7 100644 --- a/media/file.py +++ b/media/file.py @@ -51,10 +51,9 @@ class FileItem(BaseItem): if os.path.exists(self.uri()): self._get_info_from_tag() self.ready = "yes" + self.keywords = self.title + " " + self.artist else: super().__init__(bot, from_dict) - self.path = from_dict['path'] - self.title = from_dict['title'] self.artist = from_dict['artist'] self.thumbnail = from_dict['thumbnail'] if not self.validate(): @@ -75,6 +74,10 @@ class FileItem(BaseItem): self.send_client_message(constants.strings('file_missed', file=self.path)) return False + if not self.keywords: + self.keywords = self.title + " " + self.artist # migrate from previous version + self.version += 1 + # self.version += 1 # 0 -> 1, notify the wrapper to save me when validate() is visited the first time self.ready = "yes" return True diff --git a/media/item.py b/media/item.py index bd09a81..c8d7067 100644 --- a/media/item.py +++ b/media/item.py @@ -43,6 +43,7 @@ class BaseItem: self.title = "" self.path = "" self.tags = [] + self.keywords = "" self.version = 0 # if version increase, wrapper will re-save this item if from_dict is None: @@ -52,6 +53,9 @@ class BaseItem: self.id = from_dict['id'] self.ready = from_dict['ready'] self.tags = from_dict['tags'] + self.title = from_dict['title'] + self.path = from_dict['path'] + self.keywords = from_dict['keywords'] def is_ready(self): return True if self.ready == "yes" else False @@ -105,4 +109,10 @@ class BaseItem: self.bot.send_msg(msg) def to_dict(self): - return {"type": self.type, "id": self.id, "ready": self.ready, "path": self.path, "tags": self.tags} + return {"type": self.type, + "id": self.id, + "ready": self.ready, + "title": self.title, + "path": self.path, + "tags": self.tags, + "keywords": self.keywords}