]> git.0d.be Git - botaradio.git/commitdiff
feat: web interface tag support
authorTerry Geng <gengyanda@gmail.com>
Sun, 8 Mar 2020 04:53:17 +0000 (12:53 +0800)
committerTerry Geng <gengyanda@gmail.com>
Sun, 8 Mar 2020 04:53:17 +0000 (12:53 +0800)
command.py
configuration.default.ini
database.py
interface.py
static/css/custom.css
templates/index.html
templates/playlist.html

index f94300ea0626e6169dc0ec0678c622e9d00323bd..581c6e579779a0dac4c008f77fde1d8a361d0d52 100644 (file)
@@ -59,7 +59,7 @@ def register_all_commands(bot):
     bot.register_command(constants.commands('remove_tag'), cmd_remove_tag)
     bot.register_command(constants.commands('find_tagged'), cmd_find_tagged)
     bot.register_command(constants.commands('drop_database'), cmd_drop_database, True)
-    bot.register_command(constants.commands('recache'), cmd_refresh_cache, True)
+    bot.register_command(constants.commands('rescan'), cmd_refresh_cache, True)
 
     # Just for debug use
     bot.register_command('rtrms', cmd_real_time_rms, True)
@@ -904,7 +904,7 @@ def cmd_drop_database(bot, user, text, command, parameter):
 def cmd_refresh_cache(bot, user, text, command, parameter):
     global log
     var.library.build_dir_cache(bot)
-    log.info("command: cache refreshed.")
+    log.info("command: Local file cache refreshed.")
     bot.send_msg(constants.strings('cache_refreshed'), text)
 
 # Just for debug use
index 508cbd80350364b2c7940f0c31d9345ecc2fac98..ff2ffa3d970e3d7419218bf62fee65a3df39d183 100644 (file)
@@ -171,7 +171,7 @@ ducking_threshold = duckthres
 ducking_volume = duckv
 
 drop_database = dropdatabase
-recache = recache
+rescan = rescan
 
 [strings]
 current_volume = Current volume: {volume}.
@@ -259,10 +259,11 @@ help = <h3>Commands</h3>
        <ul>
        <li> <b>!<u>n</u>ow </b> (or <b>!np</b>) - display the current song </li>
        <li> <b>!<u>q</u>ueue </b> - display items in the playlist </li>
-       <li> <b>!file </b>(or <b>!f</b>) {path/folder/index/keyword} - append file to the playlist by its path or index returned by !listfile </li>
+       <li> <b>!file </b>(or <b>!f</b>) {path/folder/index/keyword} - add a single file to the playlist by its path or index returned by !listfile </li>
        <li> <b>!<u>filem</u>atch </b>(or <b>!fm</b>) {pattern} - add all files that match regex {pattern} </li>
-       <li> <b>!<u>ur</u>l </b> {url} - append youtube or soundcloud music to the playlist </li>
-       <li> <b>!<u>playl</u>ist </b> {url} [{offset}] - append items in a youtube or soundcloud playlist, and start with the {offset}-th item </li>
+       <li> <b>!<u>ur</u>l </b> {url} - add Youtube or SoundCloud music </li>
+       <li> <b>!<u>playl</u>ist </b> {url} [{offset}] - add all items in a Youtube or SoundCloud playlist, and start with the {offset}-th item </li>
+       <li> <b>!<u>t</u>ag </b> {tags} - add all items with tags {tags}, tags separated by ",". </li>
        <li> <b>!rm </b> {num} - remove the num-th song on the playlist </li>
        <li> <b>!<u>rep</u>eat </b> [{num}] - repeat current song {num} (1 by default) times.</li>
        <li> <b>!<u>ran</u>dom </b> - randomize the playlist.</li>
@@ -274,6 +275,12 @@ help = <h3>Commands</h3>
        <li> <b>!<u>yp</u>lay </b> {index/keywords} - play an item from the list returned by <i>!ytquery</i>, or add the
        first search result of {keywords} into the playlist.</li>
        </ul>
+       <b>Tag</b>
+       <li> <b>!<u>addt</u>ag </b> {index} {tags} - add {tags} to {index}-th item on the playlist, tags separated by ",". </li>
+       <li> <b>!<u>addt</u>ag </b> * {tags} - add {tags} to all items on the playlist. </li>
+       <li> <b>!<u>un</u>tag </b> {index/*} {tags} - remove {tags} from {index}-th item on the playlist. </li>
+       <li> <b>!<u>un</u>tag </b> {index/*} * - remove all tags from {index}-th item on the playlist. </li>
+       <li> <b>!<u>fin</u>dtagged </b> (or <b>!ft</b>) {tags} - find item with {tags} in the music library. </li>
        <b>Other</b>
        <ul>
        <li> <b>!<u>j</u>oinme {token} </b> - join your own channel with {token}.</li>
@@ -288,7 +295,7 @@ admin_help = <h3>Admin command</h3>
              <li><b>!<u>urlb</u>an </b> {url}  - ban an url</li>
              <li><b>!<u>urlu</u>nban </b> {url}  - unban an url</li>
              <li><b>!<u>urlu</u>nban </b> {url}  - unban an url</li>
-             <li><b>!recache </b> {url}  - rebuild local music file cache</li>
+             <li><b>!rescan </b> {url}  - rebuild local music file cache</li>
              <li><b>!dropdatabase</b> - clear the entire database, you will lose all settings and music library.</li>
              </ul>
 
index 9bcc94a6d7d4df0395d50dc2897f4e4d58150341..11d5983a0aaa58bed492f73be5ff23bb5ee016c1 100644 (file)
@@ -219,7 +219,6 @@ class MusicDatabase:
         else:
             return None
 
-
     def query_music_by_tags(self, tags):
         condition = []
         filler = []
@@ -251,6 +250,20 @@ 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
+        else:
+            return None
+
     def delete_music(self, **kwargs):
         condition = []
         filler = []
index 1cd43aa177ffd5a5e8bddca0486a33f40befd708..dc492b2d7be101a7654f921c752880d750b8424c 100644 (file)
@@ -90,12 +90,20 @@ def requires_auth(f):
         return f(*args, **kwargs)
     return decorated
 
+def build_tags_lookup():
+    lookup = {}
+    for path, id in var.library.file_id_lookup.items():
+        lookup[path] = var.music_db.query_tags_by_id(id)
+
+    return lookup
 
 @web.route("/", methods=['GET'])
 @requires_auth
 def index():
+    tags_lookup = build_tags_lookup()
     return render_template('index.html',
                            all_files=var.library.files,
+                           tags_lookup=tags_lookup,
                            music_library=var.library.dir,
                            os=os,
                            playlist=var.playlist,
@@ -272,6 +280,9 @@ def post():
                 var.playlist = media.playlist.get_playlist("autoplay", var.playlist)
                 var.db.set('playlist', 'playback_mode', "autoplay")
                 log.info("web: playback mode changed to autoplay.")
+            if action == "rescan":
+                var.library.build_dir_cache(var.bot)
+                log.info("web: Local file cache refreshed.")
             elif action == "stop":
                 var.bot.stop()
             elif action == "pause":
index c826894e6836380d389696bb857752edd8d8cb1b..7b49d0026c276e03d86d1032df741eef33d5c032 100644 (file)
@@ -1,4 +1,5 @@
 .bs-docs-section{margin-top:4em}
 .btn-space{margin-right:5px}
-.playlist-title{display:inline-block}
-.playlist-artwork{display:inline-block; margin-left:5px;}
+.playlist-title-td{width:60%}
+.playlist-title{float:left; }
+.playlist-artwork{float:left; margin-left:10px;}
index d2f7d28613a382c8f7ed7995e1807935a69820bd..5e3e88f3c1343f1b2d471d388c49b02f15c3b4da 100644 (file)
             </div>
 
         </div>
-        <div class="btn-group lead"><div class="btn-space"><i class="fa fa-music" aria-hidden="true"></i></div> {{ filepath }}</div>
+        <div class="btn-group lead">
+            <div class="btn-space"><i class="fa fa-music" aria-hidden="true"></i></div>
+            {{ filepath }}
+        </div>
+            {% for tag in tags_lookup[filepath] %}
+                <span class="badge badge-warning">{{ tag }}</span>
+            {% endfor %}
 
         <div class="btn-group" style="float: right;">
             <form action="./download" method="get" class="file file_download">
                             <thead>
                                 <tr>
                                     <th scope="col">#</th>
-                                    <th scope="col">Title</th>
+                                    <th scope="col" class="playlist-title-td">Title</th>
                                     <th scope="col">Url/Path</th>
                                     <th scope="col">Action</th>
                                 </tr>
 
                     <div class="card-body">
                         <div class="btn-group" style="margin-bottom: 5px;" role="group">
+                            <button type="submit" class="btn btn-secondary btn-space"
+                            onclick="request('/post', {action : 'rescan'}); location.reload()">
+                                <i class="fas fa-sync-alt" aria-hidden="true"></i> Rescan Files
+                            </button>
                             <form action="./download" method="get" class="directory form1">
                                 <input type="text" value="./" name="directory" hidden>
                                 <button type="submit" class="btn btn-secondary btn-space"><i class="fa fa-download" aria-hidden="true"></i> Download All</button>
index 03bf9ffaa1e905dba39c169d105596df72b8a7f3..bfe9c0c58f56b56909bc701d62c7d3060b215746 100644 (file)
@@ -24,7 +24,7 @@
                 <b>{{ m.url|truncate(45) }}</b>
             {% endif %}
             <span class="badge badge-secondary">{{ m.display_type() }}</span>
-            <br>
+            <br />
             {% if m.type == 'file' %}
                 {% if m.artist %}
                     {{ m.artist }}
             {% else %}
                 Unknown Artist
             {% endif %}
+            <br />
+            {% for tag in m.tags %}
+                <span class="badge badge-warning">{{ tag }}</span>
+            {% endfor %}
         </div>
     </td>
     <td>