]> git.0d.be Git - botaradio.git/commitdiff
feat: optimized autoplay with Lartz
authorTerry Geng <gengyanda@gmail.com>
Sun, 8 Mar 2020 13:25:30 +0000 (21:25 +0800)
committerTerry Geng <gengyanda@gmail.com>
Sun, 8 Mar 2020 13:25:30 +0000 (21:25 +0800)
command.py
configuration.default.ini
configuration.example.ini
database.py
interface.py
media/playlist.py

index 52d12e13dd02f8f2b0c0b0ccf858d4e10a888fee..968fad1103d0707e174cf612bea39fd3a648a6b8 100644 (file)
@@ -11,7 +11,7 @@ import variables as var
 from librb import radiobrowser
 from database import SettingsDatabase, MusicDatabase
 from media.item import item_builders, item_loaders, item_id_generators, dict_to_item, dicts_to_items
-from media.playlist import get_item_wrapper, get_item_wrapper_by_id, get_item_wrappers_by_tags
+from media.playlist import get_item_wrapper_from_scrap, get_item_wrapper_by_id, get_item_wrappers_by_tags
 from media.file import FileItem
 from media.url_from_playlist import PlaylistURLItem, get_playlist_info
 from media.url import URLItem
@@ -197,7 +197,7 @@ def cmd_play_file(bot, user, text, command, parameter, do_not_refresh_cache=Fals
         #     return
 
         if parameter in var.cache.files:
-            music_wrapper = get_item_wrapper(bot, type='file', path=parameter, user=user)
+            music_wrapper = get_item_wrapper_from_scrap(bot, type='file', path=parameter, user=user)
             var.playlist.append(music_wrapper)
             log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
             bot.send_msg(constants.strings('file_added', item=music_wrapper.format_song_string()), text)
@@ -301,7 +301,7 @@ def cmd_play_url(bot, user, text, command, parameter):
 
     url = util.get_url_from_input(parameter)
     if url:
-        music_wrapper = get_item_wrapper(bot, type='url', url=url, user=user)
+        music_wrapper = get_item_wrapper_from_scrap(bot, type='url', url=url, user=user)
         var.playlist.append(music_wrapper)
 
         log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
@@ -328,7 +328,7 @@ def cmd_play_playlist(bot, user, text, command, parameter):
     items = get_playlist_info(url=url, start_index=offset, user=user)
     if len(items) > 0:
         items = var.playlist.extend(list(map(
-            lambda item: get_item_wrapper(bot, **item), items)))
+            lambda item: get_item_wrapper_from_scrap(bot, **item), items)))
         for music in items:
             log.info("cmd: add to playlist: " + music.format_debug_string())
     else:
@@ -353,7 +353,7 @@ def cmd_play_radio(bot, user, text, command, parameter):
             parameter = parameter.split()[0]
         url = util.get_url_from_input(parameter)
         if url:
-            music_wrapper = get_item_wrapper(bot, type='radio', url=url)
+            music_wrapper = get_item_wrapper_from_scrap(bot, type='radio', url=url)
 
             var.playlist.append(music_wrapper)
             log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
@@ -452,7 +452,7 @@ def cmd_rb_play(bot, user, text, command, parameter):
         url = radiobrowser.geturl_byid(parameter)
         if url != "-1":
             log.info('cmd: Found url: ' + url)
-            music_wrapper = get_item_wrapper(bot, type='radio', url=url, name=stationname, user=user)
+            music_wrapper = get_item_wrapper_from_scrap(bot, type='radio', url=url, name=stationname, user=user)
             var.playlist.append(music_wrapper)
             log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
             bot.async_download_next()
@@ -966,7 +966,7 @@ def cmd_shortlist(bot, user, text, command, parameter):
             if 1 <= index <= len(song_shortlist):
                 kwargs = song_shortlist[index - 1]
                 kwargs['user'] = user
-                music_wrapper = get_item_wrapper(bot, **kwargs)
+                music_wrapper = get_item_wrapper_from_scrap(bot, **kwargs)
                 var.playlist.append(music_wrapper)
                 log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
                 msgs.append("<li><b>{}</b></li>".format(music_wrapper.item().title))
@@ -984,7 +984,7 @@ def cmd_shortlist(bot, user, text, command, parameter):
         if 1 <= index <= len(song_shortlist):
             kwargs = song_shortlist[index - 1]
             kwargs['user'] = user
-            music_wrapper = get_item_wrapper(bot, **kwargs)
+            music_wrapper = get_item_wrapper_from_scrap(bot, **kwargs)
             var.playlist.append(music_wrapper)
             log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
             bot.send_msg(constants.strings('file_added', item=music_wrapper.format_song_string()), text)
index ca3d8634e760a014204ea23d631e592dda8ba3cc..b7a19d85f33d1bc08ba8c96aadedc227f144d1fd 100644 (file)
@@ -33,6 +33,7 @@ comment = Hi, I'm here to play radio, local music or youtube/soundcloud music. H
 volume = 0.1
 # playback mode should be one of "one-shot", "loop", "random", "autoplay"
 playback_mode = one-shot
+autoplay_length = 5
 
 # target version, stable or testing (testing need to bot installed with git)
 target_version = stable
index 9b453004a250a184c5dffbf22a802e663b80c011..fd5d1d6b855f698819c73f8de0ccef73ac5daffb 100644 (file)
@@ -32,7 +32,9 @@ port = 64738
 # it should be one of "one-shot" (remove item once played), "repeat" (looping through the playlist),
 # or "random" (randomize the playlist), "autoplay" (randomly grab something from the music library).
 # This option will be overridden by value in the database.
+# 'autoplay_length': how many songs the autoplay mode fills the playlist
 #playback_mode = one-shot
+#autoplay_length = 5
 
 # target version, stable or testing (testing need to bot installed with git)
 # stable will use simple bash with curl command to get releases, testing will follow github master branch with git commands
index 0540834982897ed955f70229a54731ba7cc5b4ad..cdc6363ff4a3f6cc11fc03561c70985db81db7b3 100644 (file)
@@ -217,27 +217,15 @@ class MusicDatabase:
                                 "WHERE %s" % condition_str, filler).fetchall()
         conn.close()
 
-        if len(results) > 0:
-            music_dicts = []
-            for result in results:
-                music_dict = json.loads(result[3])
-                music_dict['type'] = result[1]
-                music_dict['title'] = result[2]
-                music_dict['tags'] = result[4].strip(",").split(",")
-                music_dict['id'] = result[0]
-                music_dicts.append(music_dict)
-
-            return music_dicts
-        else:
-            return None
+        return self._result_to_dict(results)
 
     def query_music_by_keywords(self, keywords):
         condition = []
         filler = []
 
         for keyword in keywords:
-            condition.append('title LIKE ?')
-            filler.append("%{:s}%".format(keyword))
+            condition.append('LOWER(title) LIKE ?')
+            filler.append("%{:s}%".format(keyword.lower()))
 
 
         condition_str = " AND ".join(condition)
@@ -248,30 +236,15 @@ class MusicDatabase:
                                  "WHERE %s" % condition_str, filler).fetchall()
         conn.close()
 
-        if len(results) > 0:
-            music_dicts = []
-            for result in results:
-                music_dict = json.loads(result[3])
-                music_dict['type'] = result[1]
-                music_dict['title'] = result[2]
-                music_dict['id'] = result[0]
-                music_dict['tags'] = result[4].strip(",").split(",")
-                if not music_dict['tags'][0]:
-                    music_dict['tags'] = []
-
-                music_dicts.append(music_dict)
-
-            return music_dicts
-        else:
-            return None
+        return self._result_to_dict(results)
 
     def query_music_by_tags(self, tags):
         condition = []
         filler = []
 
         for tag in tags:
-            condition.append('tags LIKE ?')
-            filler.append("%{:s},%".format(tag))
+            condition.append('LOWER(tags) LIKE ?')
+            filler.append("%{:s},%".format(tag.lower()))
 
 
         condition_str = " AND ".join(condition)
@@ -282,6 +255,33 @@ class MusicDatabase:
                                  "WHERE %s" % condition_str, filler).fetchall()
         conn.close()
 
+        return self._result_to_dict(results)
+
+    def query_tags_by_id(self, id):
+        conn = sqlite3.connect(self.db_path)
+        cursor = conn.cursor()
+        results = cursor.execute("SELECT tags FROM music "
+                                 "WHERE id=?", (id, )).fetchall()
+        conn.close()
+
+        if len(results) > 0:
+            tags = results[0][0].strip(",").split(",")
+
+            return tags if tags[0] else []
+        else:
+            return None
+
+    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()
+        conn.close()
+
+        return self._result_to_dict(results)
+
+
+    def _result_to_dict(self, results):
         if len(results) > 0:
             music_dicts = []
             for result in results:
@@ -299,20 +299,6 @@ class MusicDatabase:
         else:
             return None
 
-    def query_tags_by_id(self, id):
-        conn = sqlite3.connect(self.db_path)
-        cursor = conn.cursor()
-        results = cursor.execute("SELECT tags FROM music "
-                                 "WHERE id=?", (id, )).fetchall()
-        conn.close()
-
-        if len(results) > 0:
-            tags = results[0][0].strip(",").split(",")
-
-            return tags if tags[0] else []
-        else:
-            return None
-
     def delete_music(self, **kwargs):
         condition = []
         filler = []
index 9870976aa978816147d07cabf02322dce8928579..43ad53bbfdec3e7079bbb41f2bef907074961c3a 100644 (file)
@@ -10,7 +10,7 @@ import shutil
 from werkzeug.utils import secure_filename
 import errno
 import media
-from media.playlist import get_item_wrapper, get_item_wrapper_by_id, get_item_wrappers_by_tags
+from media.playlist import get_item_wrapper_from_scrap, get_item_wrapper_by_id, get_item_wrappers_by_tags
 import logging
 import time
 
@@ -238,7 +238,7 @@ def post():
 
 
         elif 'add_url' in request.form:
-            music_wrapper = get_item_wrapper(var.bot, type='url', url=request.form['add_url'], user=user)
+            music_wrapper = get_item_wrapper_from_scrap(var.bot, type='url', url=request.form['add_url'], user=user)
             var.playlist.append(music_wrapper)
 
             log.info("web: add to playlist: " + music_wrapper.format_debug_string())
@@ -248,7 +248,7 @@ def post():
 
         elif 'add_radio' in request.form:
             url = request.form['add_radio']
-            music_wrapper = get_item_wrapper(var.bot, type='radio', url=url, user=user)
+            music_wrapper = get_item_wrapper_from_scrap(var.bot, type='radio', url=url, user=user)
             var.playlist.append(music_wrapper)
 
             log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
index 77f8a9c2dc6af6a5493dc6f6d710501901ddcbd6..347b4233a9515c618f43c8351fcc57c92b48f709 100644 (file)
@@ -6,6 +6,7 @@ import random
 
 import variables as var
 from media.file import FileItem
+from media.item import dict_to_item
 from media.url import URLItem
 from media.url_from_playlist import PlaylistURLItem
 from media.radio import RadioItem
@@ -96,12 +97,17 @@ class PlaylistItemWrapper:
 
 
 # Remember!!! Using these three get wrapper functions will automatically add items into the cache!
-def get_item_wrapper(bot, **kwargs):
+def get_item_wrapper_from_scrap(bot, **kwargs):
     item = var.cache.get_item(bot, **kwargs)
     if 'user' not in kwargs:
         raise KeyError("Which user added this song?")
     return PlaylistItemWrapper(var.cache, item.id, kwargs['type'], kwargs['user'])
 
+def get_item_wrapper_from_dict(bot, dict_from_db, user):
+    item = dict_to_item(bot, dict_from_db)
+    var.cache[dict_from_db['id']] = item
+    return PlaylistItemWrapper(var.cache, item.id, item.type, user)
+
 def get_item_wrapper_by_id(bot, id, user):
     item = var.cache.get_item_by_id(bot, id)
     if item:
@@ -441,16 +447,14 @@ class RandomPlaylist(BasePlaylist):
             return self[0]
 
 
-class AutoPlaylist(BasePlaylist):
+class AutoPlaylist(OneshotPlaylist):
     def __init__(self):
         super().__init__()
         self.mode = "autoplay"
 
     def refresh(self):
-        _list = []
-        ids = var.music_db.query_all_ids()
-        for _ in range(20):
-            _list.append(get_item_wrapper_by_id(var.bot, ids[random.randint(0, len(ids)-1)], 'AutoPlay'))
+        dicts = var.music_db.query_random_music(var.config.getint("bot", "autoplay_length", fallback=5))
+        _list = [get_item_wrapper_from_dict(var.bot, _dict, "AutoPlay") for _dict in dicts]
         self.from_list(_list, -1)
 
     # def from_list(self, _list, current_index):
@@ -465,14 +469,5 @@ class AutoPlaylist(BasePlaylist):
     def next(self):
         if len(self) == 0:
             self.refresh()
-            return False
-
-        self.version += 1
+        return super().next()
 
-        if self.current_index < len(self) - 1:
-            self.current_index += 1
-            return self[self.current_index]
-        else:
-            self.refresh()
-            self.current_index = 0
-            return self[0]