* add more ducking command * fix current music command * provide more controls, like pause, resume, clear. * add more controls in the web interface * refactored and improved: 1. move get_music_tag_info to util, and 2. refined logic related to it. 3. now playlist will check for tag info thus update_music_tag_info is useless and was removed 4. add "add folder" feature to !file asked in #65, 5. fix bugs related to !file * truncate file list if too long * fixed several tiny bugs * fixed several tiny bugs continue * fixed several tiny bugs continue continue * fixed several tiny bugs continue**3 * fixed several tiny bugs continue**4 * added !filematch command to add files that match a regex pattern. * truncate long message * fix web interface delete file issue * refresh after delete file * add regex to listfile command * refactored command part, added partial match support for commands * organized * added random command * typo * typo * Fixed many bugs. * Added workaround for azlux/pymumble#44 to fix the memory leak. * changed logging style. * fixed bugs related to random and resume * fix now playing * fixed issue related to download * fixed issue related to download 2 * fixed thumbnail issue * fixed add url problem in web interface * REFACTORED, turned db.ini into sqlite3 database. * fixed remove song problem * fixed radio get title problem. auto download if tmp file is deleted * fixed current index not loaded from database * fixed: order of songs loaded from the database * fixed: some obscure bugs. beautified error of commands * added a workaround for TerryGeng/botamusique#1. * beautified * fixed: channel not loaded in the config * fixed: auto checked for updates * fixed: mysterious bug: sometimes "now playing" string cannot be properly displayed. The real reason is: do use <br />, do not use <br>. I tried hours to find out this. * chore: unified debug messages that refer to music items * feav: fetch ffmpeg stderr mentioned in #72, reformatted logs. * fix: async download not working * fix: async download not working, still * fix: async download not working, finished * feat: queue command: ▶current playing item◀ * feat: support more than one command prefix * chore: added some WARNINGs into default config file to avoid people to touch it. * refactor: packed all string contants into constants.py, just to avoid people messing it around. * refactor: required by azlux. Added a configuration.example.ini to keep people away from configuration.default.ini
74 lines
2.5 KiB
Python
74 lines
2.5 KiB
Python
import re
|
|
import urllib.request
|
|
import urllib.error
|
|
import logging
|
|
import json
|
|
import http.client
|
|
import struct
|
|
|
|
|
|
def get_radio_server_description(url):
|
|
p = re.compile('(https?\:\/\/[^\/]*)', re.IGNORECASE)
|
|
res = re.search(p, url)
|
|
base_url = res.group(1)
|
|
url_icecast = base_url + '/status-json.xsl'
|
|
url_shoutcast = base_url + '/stats?json=1'
|
|
title_server = None
|
|
try:
|
|
request = urllib.request.Request(url_shoutcast)
|
|
response = urllib.request.urlopen(request)
|
|
data = json.loads(response.read().decode("utf-8"))
|
|
title_server = data['servertitle']
|
|
logging.info("TITLE FOUND SHOUTCAST: " + title_server)
|
|
except urllib.error.HTTPError:
|
|
pass
|
|
except http.client.BadStatusLine:
|
|
pass
|
|
except ValueError:
|
|
return False
|
|
|
|
if not title_server:
|
|
try:
|
|
request = urllib.request.Request(url_icecast)
|
|
response = urllib.request.urlopen(request)
|
|
response_data = response.read().decode('utf-8', errors='ignore')
|
|
if response_data:
|
|
data = json.loads(response_data, strict=False)
|
|
source = data['icestats']['source']
|
|
if type(source) is list:
|
|
source = source[0]
|
|
title_server = source['server_name']
|
|
if 'server_description' in source:
|
|
title_server += ' - ' + source['server_description']
|
|
logging.info("TITLE FOUND ICECAST: " + title_server)
|
|
if not title_server:
|
|
title_server = url
|
|
except urllib.error.URLError:
|
|
title_server = url
|
|
except http.client.BadStatusLine:
|
|
pass
|
|
return title_server
|
|
|
|
|
|
def get_radio_title(url):
|
|
request = urllib.request.Request(url, headers={'Icy-MetaData': 1})
|
|
try:
|
|
|
|
response = urllib.request.urlopen(request)
|
|
icy_metaint_header = int(response.headers['icy-metaint'])
|
|
if icy_metaint_header is not None:
|
|
response.read(icy_metaint_header)
|
|
|
|
metadata_length = struct.unpack('B', response.read(1))[0] * 16 # length byte
|
|
metadata = response.read(metadata_length).rstrip(b'\0')
|
|
logging.info(metadata)
|
|
# extract title from the metadata
|
|
m = re.search(br"StreamTitle='([^']*)';", metadata)
|
|
if m:
|
|
title = m.group(1)
|
|
if title:
|
|
return title.decode()
|
|
except (urllib.error.URLError, urllib.error.HTTPError, http.client.BadStatusLine):
|
|
pass
|
|
return 'Unknown title'
|