import logging import os import re from io import BytesIO import base64 import hashlib import mutagen from PIL import Image import json import util import variables as var from media.item import BaseItem import constants ''' type : file id path title artist duration thumbnail user ''' class FileItem(BaseItem): def __init__(self, bot, path, from_dict=None): if not from_dict: super().__init__(bot) self.path = path self.title = "" self.artist = "??" self.thumbnail = None if self.path: self.id = hashlib.md5(path.encode()).hexdigest() if os.path.exists(self.uri()): self._get_info_from_tag() self.ready = "yes" 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(): self.ready = "failed" self.type = "file" def uri(self): return var.music_folder + self.path def is_ready(self): return True def validate(self): if not os.path.exists(self.uri()): self.log.info( "file: music file missed for %s" % self.format_debug_string()) self.send_client_message(constants.strings('file_missed', file=self.path)) return False self.ready = "yes" return True def _get_info_from_tag(self): match = re.search("(.+)\.(.+)", self.uri()) assert match is not None file_no_ext = match[1] ext = match[2] try: im = None path_thumbnail = file_no_ext + ".jpg" if os.path.isfile(path_thumbnail): im = Image.open(path_thumbnail) if ext == "mp3": # title: TIT2 # artist: TPE1, TPE2 # album: TALB # cover artwork: APIC: tags = mutagen.File(self.uri()) if 'TIT2' in tags: self.title = tags['TIT2'].text[0] if 'TPE1' in tags: # artist self.artist = tags['TPE1'].text[0] if im is None: if "APIC:" in tags: im = Image.open(BytesIO(tags["APIC:"].data)) elif ext == "m4a" or ext == "m4b" or ext == "mp4" or ext == "m4p": # title: ©nam (\xa9nam) # artist: ©ART # album: ©alb # cover artwork: covr tags = mutagen.File(self.uri()) if '©nam' in tags: self.title = tags['©nam'][0] if '©ART' in tags: # artist self.artist = tags['©ART'][0] if im is None: if "covr" in tags: im = Image.open(BytesIO(tags["covr"][0])) if im: self.thumbnail = self._prepare_thumbnail(im) except: pass if not self.title: self.title = os.path.basename(file_no_ext) def _prepare_thumbnail(self, im): im.thumbnail((100, 100), Image.ANTIALIAS) buffer = BytesIO() im = im.convert('RGB') im.save(buffer, format="JPEG") return base64.b64encode(buffer.getvalue()).decode('utf-8') def to_dict(self): dict = super().to_dict() dict['type'] = 'file' dict['path'] = self.path dict['title'] = self.title dict['artist'] = self.artist dict['thumbnail'] = self.thumbnail return dict def format_debug_string(self): return "[file] {artist} - {title} ({path})".format( title=self.title, artist=self.artist, path=self.path ) def format_song_string(self, user): return constants.strings("file_item", title=self.title, artist=self.artist, user=user ) def format_current_playing(self, user): display = constants.strings("now_playing", item=self.format_song_string(user)) if self.thumbnail: thumbnail_html = '' display += "
" + thumbnail_html return display def display_type(self): return constants.strings("file")