From 3fb10905b7a408e9584037e5e8fa682d33de216c Mon Sep 17 00:00:00 2001 From: Terry Geng Date: Sun, 22 Mar 2020 14:25:09 +0800 Subject: [PATCH] refactor: database logic, add type hints --- command.py | 1 + database.py | 61 ++++++++++++++++++++++++++++++++++++-------- interface.py | 3 ++- media/playlist.py | 6 ++++- templates/index.html | 2 +- variables.py | 18 +++++++++---- 6 files changed, 72 insertions(+), 19 deletions(-) diff --git a/command.py b/command.py index 54b9e29..969644e 100644 --- a/command.py +++ b/command.py @@ -97,6 +97,7 @@ song_shortlist = [] def cmd_joinme(bot, user, text, command, parameter): global log + print(bot.mumble.users[text.actor]['channel_id']) bot.mumble.users.myself.move_in( bot.mumble.users[text.actor]['channel_id'], token=parameter) diff --git a/database.py b/database.py index 283b9ba..3075d94 100644 --- a/database.py +++ b/database.py @@ -27,6 +27,8 @@ class Condition: if self._order_by: sql += f" ORDEY BY {self._order_by}" + print(sql) + print(self.filler) return sql def or_equal(self, column, equals_to, case_sensitive=True): @@ -94,6 +96,15 @@ class Condition: return self + def or_not_sub_condition(self, sub_condition): + self.filler.extend(sub_condition.filler) + if self._sql: + self._sql += f"OR NOT ({sub_condition.sql()})" + else: + self._sql += f"NOT ({sub_condition.sql()})" + + return self + def and_sub_condition(self, sub_condition): self.filler.extend(sub_condition.filler) if self._sql: @@ -103,6 +114,15 @@ class Condition: return self + def and_not_sub_condition(self, sub_condition): + self.filler.extend(sub_condition.filler) + if self._sql: + self._sql += f"AND NOT({sub_condition.sql()})" + else: + self._sql += f"NOT ({sub_condition.sql()})" + + return self + def limit(self, limit): self._limit = limit @@ -323,14 +343,27 @@ class MusicDatabase: del music_dict['path'] del music_dict['keywords'] - cursor.execute("INSERT OR REPLACE INTO music (id, type, title, metadata, tags, path, keywords) VALUES (?, ?, ?, ?, ?, ?, ?)", - (id, - type, - title, - json.dumps(music_dict), - tags, - path, - keywords)) + existed = cursor.execute("SELECT TRUE FROM music WHERE id=?", (id,)).fetchall() + if len(existed) == 0: + cursor.execute( + "INSERT INTO music (id, type, title, metadata, tags, path, keywords) VALUES (?, ?, ?, ?, ?, ?, ?)", + (id, + type, + title, + json.dumps(music_dict), + tags, + path, + keywords)) + else: + cursor.execute("UPDATE music SET type=:type, title=:title, metadata=:metadata, tags=:tags, " + "path=:path, keywords=:keywords WHERE id=:id", + {'id': id, + 'type': type, + 'title': title, + 'metadata': json.dumps(music_dict), + 'tags': tags, + 'path': path, + 'keywords': keywords}) if not _conn: conn.commit() @@ -423,7 +456,7 @@ class MusicDatabase: conn.commit() conn.close() - def query_tags(self, condition): + def query_tags(self, condition: Condition): # TODO: Can we keep a index of tags? conn = sqlite3.connect(self.db_path) cursor = conn.cursor() @@ -441,11 +474,17 @@ class MusicDatabase: return lookup - def query_random_music(self, count): + def query_random_music(self, count, condition: Condition = None): conn = sqlite3.connect(self.db_path) cursor = conn.cursor() + results = [] + + if condition is None: + condition = Condition().and_not_sub_condition(Condition().and_equal('id', 'info')) + results = cursor.execute("SELECT id, type, title, metadata, tags, path, keywords FROM music " - "WHERE id IN (SELECT id FROM music WHERE id != 'info' ORDER BY RANDOM() LIMIT ?)", (count,)).fetchall() + "WHERE id IN (SELECT id FROM music WHERE %s ORDER BY RANDOM() LIMIT ?) ORDER BY RANDOM()" + % condition.sql(), condition.filler + [count]).fetchall() conn.close() return self._result_to_dict(results) diff --git a/interface.py b/interface.py index 4dadaca..49b6062 100644 --- a/interface.py +++ b/interface.py @@ -399,7 +399,8 @@ def build_library_query_condition(form): tags = form['tags'].split(",") for tag in tags: - condition.and_like("tags", f"%{tag},%", case_sensitive=False) + if tag: + condition.and_like("tags", f"%{tag},%", case_sensitive=False) _keywords = form['keywords'].split(" ") keywords = [] diff --git a/media/playlist.py b/media/playlist.py index f13fbbd..8affbb3 100644 --- a/media/playlist.py +++ b/media/playlist.py @@ -6,6 +6,7 @@ import time import variables as var from media.cache import CachedItemWrapper, get_cached_wrapper_from_dict, get_cached_wrapper_by_id +from database import Condition def get_playlist(mode, _list=None, index=None): @@ -361,7 +362,10 @@ class AutoPlaylist(OneshotPlaylist): self.mode = "autoplay" def refresh(self): - dicts = var.music_db.query_random_music(var.config.getint("bot", "autoplay_length", fallback=5)) + dicts = var.music_db.query_random_music(var.config.getint("bot", "autoplay_length", fallback=5), + Condition().and_not_sub_condition( + Condition().and_like('tags', "%don't autoplay,%"))) + if dicts: _list = [get_cached_wrapper_from_dict(var.bot, _dict, "AutoPlay") for _dict in dicts] self.from_list(_list, -1) diff --git a/templates/index.html b/templates/index.html index 62ad287..f98f1d6 100644 --- a/templates/index.html +++ b/templates/index.html @@ -134,7 +134,7 @@
- {% for dir in music_library.get_subdirs_recursively() %} diff --git a/variables.py b/variables.py index 9f8a605..68b928d 100644 --- a/variables.py +++ b/variables.py @@ -1,14 +1,22 @@ -bot = None -playlist = None -cache = None +from typing import Type, TYPE_CHECKING + +if TYPE_CHECKING: + import mumbleBot + import media.playlist + import media.cache + import database + +bot: 'mumbleBot.MumbleBot' = None +playlist: Type['media.playlist.BasePlaylist'] = None +cache: 'media.cache.MusicCache' = None user = "" is_proxified = False dbfile = None db = None -music_db = None -config = None +music_db: 'database.MusicDatabase' = None +config: 'database.SettingsDatabase' = None bot_logger = None