first commit

This commit is contained in:
mol
2023-02-04 00:14:50 +08:00
commit a2f1b6d4fd
51 changed files with 839 additions and 0 deletions

65
ExceptionHandler.py Normal file
View File

@ -0,0 +1,65 @@
import logging as logger
class ExceptionHandler(object):
"""异常处理器,可以自行实现错误的捕获、熔断、服务降级等"""
def __init__(self, decorator=None):
if not decorator:
return
# 使用自定义装饰器覆盖
self.decorator = decorator
def handle(self, e, *args, **kwargs):
"""异常处理
:param e:
:param args: request args
:param kwargs: request kwargs
:return: tuple(content, status, headers)
:rtype: tuple
"""
raise NotImplementedError
def decorator(self, func):
def wrapper(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as e:
logger.debug("Exception handle")
return self.handle(e, *args, **kwargs)
return wrapper
class InboundHandler(object):
"""输入处理管道,可自定义一系列拦截器处理请求信息,如验证、鉴权、数据解码、参数包装等"""
#__metaclass__ = 'ABCMeta'
def handle(self, request, *args, **kwargs):
"""
:param dict request: 请求信息 (初始url, parameters, data, method),可根据需要添加
:return: (request, args, kwargs)
"""
raise NotImplementedError
def __call__(self, request, *args, **kwargs):
return self.handle(request, *args, **kwargs)
class OutboundHandler(object):
"""输出处理管道,可自定义一系列拦截器处理返回信息,如返回码处理、数据编码等"""
# __metaclass__ = 'ABCMeta'
def handle(self, response, headers, status, content, *args, **kwargs):
"""
:param requests.Response response: origin http response
:param dict headers: the response headers which will be responded
:param int status: the status code which will be responded
:param str content: the content which will be responded
:return: tuple(headers, status, content)
"""
raise NotImplementedError
def __call__(self, response, headers, status, content, *args, **kwargs):
return self.handle(response, headers, status, content, *args, **kwargs)

149
Gateway.py Normal file
View File

@ -0,0 +1,149 @@
import requests
import utils
import json
import logging as logger
#import InvalidParameterException
from flask import make_response
from flask import request
from ExceptionHandler import *
class NoopExceptionHandler(ExceptionHandler):
DEFAULT_CONTENT = {
"error_code": "InternalServerError",
"error_message": "",
"error_message_chs": "服务器内部错误"
}
def handle(self, e, *args, **kwargs):
logger.exception("Unknown exception occurred: %s", e)
content = dict(self.DEFAULT_CONTENT)
content['error_message'] = e.message
return json.dumps(content), 500
class GenericGateway(object):
def __init__(self, app, routes, url_supplier, exception_handler=None):
"""
:param app: flask app
:type app: flask.Flask
:param routes: 路由列表
:type routes: list of Route
:param url_supplier: 服务名称解析函数通过service name获取service url: url_supplier(service_name) -> service_url
:type url_supplier: function
:param exception_handler: exception handle decorator
:type exception_handler: ExceptionHandler
"""
if not callable(url_supplier):
raise ValueError("service url supplier (url_supplier) must be callable")
self.app = app
self.routes = routes
self.url_supplier = url_supplier
self.exception_handler = exception_handler or NoopExceptionHandler()
self.proxy_list = []
def get_url(self, service_name):
try:
return self.url_supplier(service_name)
except Exception as e:
logger.warning("Failed to get the url of service: %s", service_name, exc_info=True)
raise RuntimeError("Failed to get the url of service {}: {}".format(service_name, e))
def create_request_proxy(self, route):
logger.info("Register route: %s", route.path)
def proxy_request(*args, **kwargs):
upstream_path = route.upstream_path
for p_name in route.upstream_params:
v = get_params_from_context(p_name, kwargs)
upstream_path = utils.replace_placeholder(upstream_path, p_name, v)
endpoint = self.get_url(route.service_name)
final_url = "{}{}".format(endpoint, upstream_path)
upstream_req_info = dict(
url=final_url,
method=request.method,
params=request.args,
data=request.data,
files=request.files,
headers=request.headers,
)
if request.form:
upstream_req_info['data'] = request.form
for pipe_handler in route.inbound_pipes():
upstream_req_info, args, kwargs = pipe_handler(upstream_req_info, *args, **kwargs)
content_type = upstream_req_info['headers'].get('Content-Type')
if content_type and 'boundary' in content_type:
# requests prepare body时会使重新生成 boundaryheaders中旧的 boundary 会导致上游服务无法识别
upstream_req_info['headers'] = {k: v for k, v in upstream_req_info['headers'].items()}
upstream_req_info['headers'].pop('Content-Type', None)
upstream_req_info['headers'].pop('content-type', None)
resp = requests.request(**upstream_req_info)
status = resp.status_code
content = None
headers = resp.headers
for pipe_handler in route.outbound_pipes():
resp, headers, status, content = pipe_handler(resp, headers, status, content, *args, **kwargs)
content = make_response(content or resp.content)
for h_name, h_value in (headers or {}).items():
content.headers[h_name] = h_value
return content, status
# 修改函数名称Flask route注册使用func name必须唯一
proxy_request.__name__ = route.name
return proxy_request
def _register_route(self, route):
"""
:param Route route:
"""
proxy = self.create_request_proxy(route)
self.proxy_list.append(
self.app.route(route.path, methods=route.methods)(proxy)
)
def register_routes(self):
for route in self.routes:
self._register_route(route)
def get_params_from_context(param_name, kwargs):
"""按顺序尝试从url参数、headers、args、form、json中获取参数值
"""
payload = {}
if kwargs and kwargs.get(param_name):
payload = kwargs
elif request.headers.get(param_name):
payload = request.headers
elif request.args and request.args.get(param_name):
payload = request.args
elif request.form and request.form.get(param_name):
payload = request.form
elif request.data:
body = json.loads(request.data)
if body and body.get(param_name):
payload = body
try:
return payload[param_name]
except KeyError as e:
# raise InvalidParameterException(
# message="Missing the required params: {}".format(e),
# message_chs="缺少必要的参数 {}".format(e)
# )
print('')

0
README.md Normal file
View File

66
Route.py Normal file
View File

@ -0,0 +1,66 @@
from utils import *
class Route(object):
"""
路由实体类,对应一项路由配置
TODO replace_placeholder 函数,替换字符串中的占位符
TODO extract_placeholders 函数,获取字符串中的点位符
TODO get_pipe 函数通过handler name获取对应的PipeHandler类
"""
SERVICE_NAME_PLACEHOLDER = 'service_name'
def __init__(self, name, service_name, methods, path, upstream_path, pipelines=None):
"""
:param str name: (string) 路由名称
:param str service_name: (string) 内部微服务名称(如 `resolver` `data_manager` 等)
:param list methods: (array) 支持的请求方法列表, 如 `['GET', 'PUT']`
:param str path: (string) 匹配的路径,使用`flask`的占位符 `<parameter_name>` 声明路径参数,服务名称固定使用 `<service_name>` 占位符
:param str upstream_path: (string) 转发到上游服务的路径,与`path`使用同样风格的参数占位符
:param dict pipelines: (object) 数据处理管道
"""
if not isinstance(methods, (list, set, tuple)):
raise ValueError("methods must be an iterable list")
pipelines = pipelines or {}
self.name = name
self.service_name = service_name
self.methods = list(set(methods))
# 使用 replace_placeholder 将 <service_name> 替换为路由配置中的后端服务
self.path = replace_placeholder(path, self.SERVICE_NAME_PLACEHOLDER, service_name)
self.upstream_path = replace_placeholder(upstream_path, self.SERVICE_NAME_PLACEHOLDER, service_name)
self.pipelines = {
"inbound": map(self.init_pipe_handler, pipelines.get('inbound') or []),
"outbound": map(self.init_pipe_handler, pipelines.get('outbound') or []),
}
# 导出上游服务资源所需的参数(占位符)
self.upstream_params = extract_placeholders(self.upstream_path)
def init_pipe_handler(self, pipe_conf):
try:
name = pipe_conf['name']
properties = pipe_conf.get('properties', {})
klass = get_pipe(name)
return klass(**properties)
except Exception as e:
raise ValueError("illegal pipe config {}: {}".format(pipe_conf, e))
def inbound_pipes(self):
return self.pipelines.get("inbound") or []
def outbound_pipes(self):
return self.pipelines.get("outbound") or []
def load(routes):
"""
:param list of dict routes: 路由配置列表
:rtype: list of Route
"""
return map(lambda kv: Route(**kv), routes)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

66
app.py Normal file
View File

@ -0,0 +1,66 @@
from flask import Flask, request
from Gateway import *
from Route import *
from ExceptionHandler import *
class GatewayServer():
def __init__(self):
self.app = Flask('gateway')
self.url_map = {
'test': 'http://127.0.0.1:7777',
'music_server': 'http://192.168.124.12:4533'
}
self.url_supplier = lambda x: self.url_map[x]
route_2 = {
"name": "add-sound",
"service_name": "music_server",
"methods": ["POST"],
"path": "/music/api/playlist/<playlist_id>/tracks",
"upstream_path": "/api/playlist/<playlist_id>/tracks",
"pipelines": {
"outbound": [{ "name": "plugin.MusicHandler.MusicHandler" }]
}
}
route_3 = {
"name": "del-sound",
"service_name": "music_server",
"methods": ["DELETE"],
"path": "/music/api/playlist/<playlist_id>/tracks",
"upstream_path": "/api/playlist/<playlist_id>/tracks",
"pipelines": {
"outbound": [{ "name": "plugin.MusicHandler.MusicHandler" }]
}
}
route_4 = {
"name": "del-playlist",
"service_name": "music_server",
"methods": ["DELETE"],
"path": "/music/api/playlist/<playlist_id>",
"upstream_path": "/api/playlist/<playlist_id>",
"pipelines": {
"outbound": [{ "name": "plugin.MusicHandler.MusicHandler" }]
}
}
route_5 = {
"name": "add-playlist",
"service_name": "music_server",
"methods": ["POST"],
"path": "/music/api/playlist",
"upstream_path": "/api/playlist",
"pipelines": {
"outbound": [{ "name": "plugin.MusicHandler.MusicHandler" }]
}
}
self.routes = Route.load([route_2, route_3, route_4, route_5])
gateway = GenericGateway(self.app, self.routes, url_supplier=self.url_supplier)
gateway.register_routes()
gateway_server = GatewayServer()
app = gateway_server.app
app.run(port=5000, debug=True)

15
plugin/MusicHandler.py Normal file
View File

@ -0,0 +1,15 @@
from ExceptionHandler import *
import plugin.NavidromePlaylistSync.app as navidromePlaylistSync
class MusicHandler(OutboundHandler):
def handle(self, response, headers, status, content, *args, **kwargs):
"""
:param dict request: 请求信息 (初始url, parameters, data, method),可根据需要添加
:return: (request, args, kwargs)
"""
# raise NotImplementedError
print("222")
print(status)
if status == 200:
navidromePlaylistSync.start()
return [response, headers, status, content]

View File

View File

@ -0,0 +1,25 @@
import requests
def getPlaylist(token):
headers = {
'x-nd-authorization': f'Bearer {token}'
}
res = requests.get('https://music.hiiragi.club:8081/api/playlist?_end=50&_order=ASC&_sort=id&_start=0', headers = headers)
resJson = res.json()
return resJson
def downloadPlayList(palyListId, token):
headers = {
'Accept': 'audio/x-mpegurl',
'x-nd-authorization': f'Bearer {token}'
}
res = requests.get(f'https://music.hiiragi.club:8081/api/playlist/{palyListId}/tracks', headers = headers)
return res.content
def delPlaylist(playlistId, token):
headers = {
'x-nd-authorization': f'Bearer {token}'
}
res = requests.delete(f'https://music.hiiragi.club:8081/api/playlist/{playlistId}', headers = headers)
resJson = res.json()
return resJson

View File

@ -0,0 +1,7 @@
import requests
def getToken():
body = { 'username': 'mol', 'password': 'c!UxnePTkwBMb7' }
res = requests.post('https://music.hiiragi.club:8081/auth/login', json = body)
resJson = res.json()
return resJson.get('token')

View File

@ -0,0 +1,33 @@
from plugin.NavidromePlaylistSync.api.token import *
from plugin.NavidromePlaylistSync.api.playlist import *
from plugin.NavidromePlaylistSync.saveFile import *
from plugin.NavidromePlaylistSync.sync import *
from plugin.NavidromePlaylistSync.resetDir import *
def start():
tempPath = os.path.join(os.path.dirname(__file__), 'temp')
reset(tempPath)
token = getToken()
playlistArray = getPlaylist(token)
delPlaylistIds = []
for i in playlistArray:
id = i.get('id')
name = i.get('name')
if i.get('path') == '':
delPlaylistIds.append(id)
data = downloadPlayList(i.get('id') , token)
saveFile(name, data)
sync()
if len(delPlaylistIds) > 0:
for delId in delPlaylistIds:
delPlaylist(delId, token)
if __name__ == 'main':
start()

View File

@ -0,0 +1,10 @@
import os
def reset(path):
delList = os.listdir(path)
for f in delList:
filePath = os.path.join(path, f)
if os.path.isfile(filePath):
os.remove(filePath)

View File

@ -0,0 +1,6 @@
import os
def saveFile(name, data):
tempPath = os.path.join(os.path.dirname(__file__), 'temp')
with open(os.path.join(tempPath, f'{name}.m3u'), 'wb') as code:
code.write(data)

View File

@ -0,0 +1,28 @@
import os
from webdav3.client import Client
from webdav3.exceptions import LocalResourceNotFound, RemoteResourceNotFound
def sync():
options = {
'webdav_hostname': 'https://pan.hiiragi.club:8081/dav',
'webdav_login': 'mol',
'webdav_password': 'YvG4SkF82qd7ks',
'disable_check': True,
}
client = Client(options)
tempPath = os.path.join(os.path.dirname(__file__), 'temp')
playlists = os.listdir(tempPath)
try:
client.clean('Music/#playlist')
except RemoteResourceNotFound as exception:
print('clean failed!')
for fileName in playlists:
path = os.path.join(tempPath, fileName)
try:
client.upload('Music/#playlist/' + fileName, path)
print(fileName + ' upload success!!')
except LocalResourceNotFound as exception:
print(fileName + ' upload failed!!')

View File

@ -0,0 +1,13 @@
#EXTM3U
#EXTINF:264,ClariS - border
/music/ClariS/ClariS 〜SINGLE BEST 1st〜/11 border.mp3
#EXTINF:260,ClariS - irony
/music/ClariS/irony/1-01 irony.mp3
#EXTINF:304,ClariS - Don't cry
/music/ClariS/nexus/02 Don't cry.mp3
#EXTINF:256,ClariS - STEP
/music/ClariS/STEP/01 STEP.mp3
#EXTINF:282,ClariS - 桜咲く
/music/ClariS/STEP/03 桜咲く.mp3
#EXTINF:272,ClariS - コネクト
/music/ClariS/コネクト/01 コネクト.mp3

View File

@ -0,0 +1,31 @@
#EXTM3U
#EXTINF:226,HIMEHINA - 相思相愛リフレクション
/music/HIMEHINA/希織歌/05 相思相愛リフレクション.flac
#EXTINF:275,HIMEHINA - 流れ行く命
/music/HIMEHINA/流れ行く命/01 流れ行く命.flac
#EXTINF:90,HIMEHINA - 約束の血
/music/HIMEHINA/藍の華/01 約束の血.flac
#EXTINF:227,HIMEHINA - 藍の華
/music/HIMEHINA/藍の華/03 藍の華.flac
#EXTINF:223,HIMEHINA - ヒトガタRock
/music/HIMEHINA/藍の華/04 ヒトガタRock.flac
#EXTINF:262,HIMEHINA - ヒバリ(Laugh-In)
/music/HIMEHINA/藍の華/05 ヒバリ(Laugh-In).flac
#EXTINF:251,HIMEHINA - ライライラビットテイル
/music/HIMEHINA/藍の華/06 ライライラビットテイル.flac
#EXTINF:262,HIMEHINA - 琥珀の身体(Message-In)
/music/HIMEHINA/藍の華/08 琥珀の身体(Message-In).flac
#EXTINF:219,HIMEHINA - 溺れるほど愛した花
/music/HIMEHINA/藍の華/10 溺れるほど愛した花.flac
#EXTINF:301,HIMEHINA - 夢景色
/music/HIMEHINA/藍の華/11 夢景色.flac
#EXTINF:286,HIMEHINA - うたかたよいかないで(Message-In)
/music/HIMEHINA/藍の華/12 うたかたよいかないで(Message-In).flac
#EXTINF:265,HIMEHINA - ララ
/music/HIMEHINA/藍の華/14 ララ.flac
#EXTINF:237,HIMEHINA - アダムとマダム
/music/HIMEHINA/藍の華/16 アダムとマダム.flac
#EXTINF:225,HIMEHINA - ヒトガタ
/music/HIMEHINA/藍の華/17 ヒトガタ.flac
#EXTINF:390,HIMEHINA - My Dear
/music/HIMEHINA/藍の華/19 My Dear.flac

View File

@ -0,0 +1,17 @@
#EXTM3U
#EXTINF:337,SOULd OUT - VOODOO KINGDOM
/music/SOULd OUT/ATTITUDE/04 SOULd OUT - VOODOO KINGDOM.mp3
#EXTINF:262,Coda - BLOODY STREAM
/music/Coda/BLOODY STREAM/01 BLOODY STREAM.mp3
#EXTINF:340,Pat Metheny Group - Last Train Home
/music/Pat Metheny Group/Essential Collection_ Last Train Home/01 Last Train Home.mp3
#EXTINF:243,青木カレン・ハセガワダイスケ - Great Days
/music/青木カレン・ハセガワダイスケ/Great Days/01 Great Days.mp3
#EXTINF:265,富永TOMMY弘明 - ジョジョ 〜その血の運命〜
/music/富永TOMMY弘明/ジョジョ 〜その血の運命〜/01 ジョジョ 〜その血の運命〜.mp3
#EXTINF:264,JO☆STARSTOMMY, Coda, JIN - ジョジョその血の記憶end of THE WORLD
/music/Various Artists/ジョジョの奇妙な冒険 Theme Song Best 「Generation」/06 JO☆STARSTOMMY, Coda, JIN - ジョジョその血の記憶end of THE WORLD.mp3
#EXTINF:175,菅野祐悟 - 高潔なる教皇
/music/菅野祐悟/ジョジョの奇妙な冒険 スターダストクルセイダース O.S.T [Departure]/09 高潔なる教皇.mp3
#EXTINF:308,菅野祐悟 - スターダストクルセイダース
/music/菅野祐悟/ジョジョの奇妙な冒険 スターダストクルセイダース O.S.T [Departure]/23 スターダストクルセイダース.mp3

View File

@ -0,0 +1,17 @@
#EXTM3U
#EXTINF:271,YOASOBI - アンコール
/music/YOASOBI/THE BOOK/02 アンコール.flac
#EXTINF:199,YOASOBI - ハルジオン
/music/YOASOBI/THE BOOK/03 ハルジオン.flac
#EXTINF:241,YOASOBI - あの夢をなぞって
/music/YOASOBI/THE BOOK/04 あの夢をなぞって.flac
#EXTINF:257,YOASOBI - たぶん
/music/YOASOBI/THE BOOK/05 たぶん.flac
#EXTINF:248,YOASOBI - 群青
/music/YOASOBI/THE BOOK/06 群青.flac
#EXTINF:244,YOASOBI - ハルカ
/music/YOASOBI/THE BOOK/07 ハルカ.flac
#EXTINF:259,YOASOBI - 夜に駆ける
/music/YOASOBI/THE BOOK/08 夜に駆ける.flac
#EXTINF:205,YOASOBI - 怪物
/music/YOASOBI/THE BOOK 2/06 YOASOBI - 怪物.flac

View File

@ -0,0 +1,7 @@
#EXTM3U
#EXTINF:191,ナユタン星人 - ダンスロボットダンス
/music/ナユタン星人/ナユタン星からの物体Y/04 ダンスロボットダンス.flac
#EXTINF:203,ナユタン星人 - 太陽系デスコ
/music/ナユタン星人/ナユタン星からの物体Y/07 太陽系デスコ.flac
#EXTINF:211,ナユタン星人 - ディスコミュ星人
/music/ナユタン星人/ナユタン星からの物体Y/08 ディスコミュ星人.flac

View File

@ -0,0 +1,69 @@
#EXTM3U
#EXTINF:222,40mP - 恋愛裁判
/music/40mP/41m/02 40mP - 恋愛裁判.mp3
#EXTINF:216,DECO*27 feat. 初音ミク - おじゃま虫
/music/DECO_27/Conti New/1-02 おじゃま虫.flac
#EXTINF:216,DECO*27 feat. 初音ミク - 妄想税
/music/DECO_27/Conti New/1-10 妄想税.mp3
#EXTINF:306,蝶々P feat. 初音ミク - そういうこと。
/music/蝶々P feat. 初音ミク/Fictional World/11 蝶々P feat. 初音ミク - そういうこと。.mp3
#EXTINF:244,トーマ feat. 初音ミク - オレンジ
/music/Various Artists/HATSUNE MIKU 10th Anniversary Album 「Re_Start」/2-11 トーマ feat. 初音ミク - オレンジ.flac
#EXTINF:149,初音ミク - Ievan Polkka
/music/初音ミク/Hatsune Miku 1st Song Album/11 Ievan Polkka.mp3
#EXTINF:265,ぼーかりおどP/初音ミク - 1/6 -out of the gravity-
/music/ぼーかりおどP_初音ミク/1_6 -out of the gravity-.mp3
#EXTINF:323,doriko feat. 初音ミク - 文学者の恋文
/music/doriko feat.初音ミク/Nostalgia/04 doriko feat. 初音ミク - 文学者の恋文.mp3
#EXTINF:257,livetune feat. 初音ミク - Tell Your World
/music/livetune feat. 初音ミク/Tell Your World/01 Tell Your World.mp3
#EXTINF:277,はりーP feat. 初音ミク - ぼくらのレットイットビー
/music/Various Artists/V♥25 -cantabile-/02 はりーP feat. 初音ミク - ぼくらのレットイットビー.mp3
#EXTINF:210,ryo (supercell) feat. 初音ミク - こっち向いて Baby
/music/ryo (supercell) feat. 初音ミク _ kz (livetune) feat. 初音ミク/こっち向いて Baby _ Yellow/1-01 ryo (supercell) feat. 初音ミク - こっち向いて Baby.flac
#EXTINF:268,鏡音リン - 炉心融解
/music/初音ミク/ミクの日感謝祭 39's Giving Day Project DIVA presents 初音ミク・ソロコンサート~こんばんは、初音ミクです。~/2-09 鏡音リン - 炉心融解.mp3
#EXTINF:184,初音ミク & 鏡音リン - Promise
/music/初音ミク/ミクの日感謝祭 39's Giving Day Project DIVA presents 初音ミク・ソロコンサート~こんばんは、初音ミクです。~/2-12 初音ミク & 鏡音リン - Promise.mp3
#EXTINF:192,初音ミク - 愛言葉 [Live]
/music/初音ミク/ミクの日感謝祭 39's Giving Day Project DIVA presents 初音ミク・ソロコンサート~こんばんは、初音ミクです。~/2-17 初音ミク - 愛言葉 [Live].mp3
#EXTINF:259,ryo feat. 初音ミク - メルト
/music/ryo, supercell feat. 初音ミク/メルト/01 ryo feat. 初音ミク - メルト.flac
#EXTINF:277,doriko feat.初音ミク - ロミオとシンデレラ
/music/doriko feat.初音ミク/ロミオとシンデレラ/09 ロミオとシンデレラ.mp3
#EXTINF:182,KazuP(源屋) feat. 初音ミク - Innocence
/music/Various Artists/初音ミク -Project DIVA- 2nd NONSTOP MIX COLLECTION/1-25 KazuP(源屋) feat. 初音ミク - Innocence.flac
#EXTINF:235,オワタP feat. 鏡音レン - パラジクロロベンゼン
/music/Various Artists/初音ミク -Project DIVA- extend Complete Collection/2-11 オワタP feat. 鏡音レン - パラジクロロベンゼン.mp3
#EXTINF:202,wowaka feat. 初音ミク - 裏表ラバーズ
/music/Various Artists/初音ミク -Project DIVA- extend Complete Collection/2-12 wowaka feat. 初音ミク - 裏表ラバーズ.mp3
#EXTINF:293,さつき が てんこもり - ネトゲ廃人シュプレヒコール
/music/初音ミク/初音ミク 5thバースデー ベスト impacts/13 さつき が てんこもり - ネトゲ廃人シュプレヒコール.mp3
#EXTINF:215,初音ミク - 深海少女
/music/初音ミク/初音ミク 5thバースデー ベスト memories/1-10 深海少女.mp3
#EXTINF:219,黒うさP feat. 初音ミク - 千本桜
/music/Various Artists/初音ミク Project DIVA MEGA39's 10th アニバーサリーコレクション/4-05 黒うさP feat. 初音ミク - 千本桜.mp3
#EXTINF:238,supercell feat. 初音ミク - 恋は戦争
/music/初音ミク/初音ミク ベストimpacts/11 supercell feat. 初音ミク - 恋は戦争.mp3
#EXTINF:241,minato feat. 初音ミク - Magnet
/music/初音ミク/初音ミク ベストimpacts/13 minato feat. 初音ミク - Magnet.mp3
#EXTINF:211,azuma feat. 初音ミク - あなたの歌姫 Complete Ver.
/music/初音ミク/初音ミク ベストmemories/08 azuma feat. 初音ミク - あなたの歌姫 Complete Ver..mp3
#EXTINF:214,初音ミク - Weekender Girl
/music/Various Artists/初音ミク-Project DIVA- Ƒ Complete Collection/1-04 初音ミク - Weekender Girl.mp3
#EXTINF:227,emon feat. 初音ミク・鏡音レン・鏡音リン - shake it!
/music/Various Artists/初音ミク「マジカルミライ 2014」OFFICIAL ALBUM/1-05 emon feat. 初音ミク・鏡音レン・鏡音リン - shake it!.mp3
#EXTINF:235,八王子P feat. 初音ミク - Sweet Devil
/music/Various Artists/初音ミク「マジカルミライ 2014」OFFICIAL ALBUM/1-07 八王子P feat. 初音ミク - Sweet Devil.wav
#EXTINF:311,じーざす(ワンダフル☆オポチュニティ!) feat. 鏡音リン・鏡音レン - リモコン
/music/Various Artists/初音ミク「マジカルミライ 2015」OFFICIAL ALBUM/1-02 じーざす(ワンダフル☆オポチュニティ!) feat. 鏡音リン・鏡音レン - リモコン.mp3
#EXTINF:186,ナユタン星人 feat. 初音ミク - エイリアンエイリアン
/music/Various Artists/初音ミク「マジカルミライ 2017」OFFICIAL ALBUM/03 ナユタン星人 feat. 初音ミク - エイリアンエイリアン.flac
#EXTINF:237,Giga feat. 鏡音リン・レン - 劣等上等
/music/Various Artists/初音ミク「マジカルミライ 2018」OFFICIAL ALBUM/02 Giga feat. 鏡音リン・レン - 劣等上等.flac
#EXTINF:250,すこっぷ feat. 初音ミク Append (Soft) - アイロニ
/music/すこっぷ/境界センチメンタル/04 すこっぷ feat. 初音ミク Append (Soft) - アイロニ.mp3
#EXTINF:250,40mP feat. 初音ミク - からくりピエロ
/music/40mP/小さな自分と大きな世界/07 40mP feat. 初音ミク - からくりピエロ.mp3
#EXTINF:326,doriko feat.初音ミク - letter song
/music/doriko feat.初音ミク/花束 〜the best of doriko feat.初音ミク〜/13 letter song.flac

View File

@ -0,0 +1,7 @@
#EXTM3U
#EXTINF:294,Metavari - Kings Die Like Other Men
/music/Metavari/Be One of Us and Hear No Noise/01 Kings Die Like Other Men.mp3
#EXTINF:304,Lights & Motion - Victory Rose
/music/Lights & Motion/Reanimation/06 Victory Rose.mp3
#EXTINF:487,Whale Fall - You Go Up, I Go Down
/music/Whale Fall/Whale Fall/10 You Go Up, I Go Down.mp3

View File

@ -0,0 +1,13 @@
#EXTM3U
#EXTINF:317,浮森かや子 - お隣はだあれ
/music/浮森かや子/お隣はだあれ.mp3
#EXTINF:275,ウサギキノコ - Secret
/music/ウサギキノコ/eclipse 改/13 Secret.flac
#EXTINF:352,梶浦由記 - my long forgotten cloistered sleep (unreleased work of Xenosaga)
/music/梶浦由記/Fiction II/04 my long forgotten cloistered sleep (unreleased work of Xenosaga).flac
#EXTINF:313,Stack - カゲロウ
/music/暁Records/NO SIGNAL/03 Stack - カゲロウ.flac
#EXTINF:209,kanon×kanon - ザ ドールハウス!
/music/kanon×kanon/カレンデュラ レクイエム/02 ザ ドールハウス!.flac
#EXTINF:256,WhiteFlame - 流れ星
/music/WhiteFlame/月と星の虚構空間/1-01 流れ星.mp3

View File

@ -0,0 +1,21 @@
#EXTM3U
#EXTINF:235,TOKOTOKO feat. ゆいこんぬ - ハートビート・フロムユー
/music/TOKOTOKO/ハートビート・フロムユー/06 TOKOTOKO feat. ゆいこんぬ - ハートビート・フロムユー.mp3
#EXTINF:222,40mP - 恋愛裁判
/music/40mP/41m/02 40mP - 恋愛裁判.mp3
#EXTINF:226,HIMEHINA - 相思相愛リフレクション
/music/HIMEHINA/希織歌/05 相思相愛リフレクション.flac
#EXTINF:254,千石撫子 (花澤香菜) - 恋愛サーキュレーション
/music/千石撫子 (花澤香菜)/恋愛サーキュレーション/01 恋愛サーキュレーション.flac
#EXTINF:277,スズム feat. GUMI - 世界寿命と最後の一日 (Album ver.)
/music/スズム/ケビョウニンゲン/06 スズム feat. GUMI - 世界寿命と最後の一日 (Album ver.).mp3
#EXTINF:244,ギガP feat. れをる - No title
/music/ギガP/No title/06 ギガP feat. れをる - No title.mp3
#EXTINF:239,DECO*27 feat. GUMI - 弱虫モンブラン
/music/DECO_27/DECO_27 VOCALOID COLLECTION 2008~2012/12 DECO_27 feat. GUMI - 弱虫モンブラン.flac
#EXTINF:340,かぴ - 世界は恋に落ちている acoustic version
/music/HoneyWorks/ハニワ曲歌ってみた5/12 かぴ - 世界は恋に落ちている acoustic version.mp3
#EXTINF:250,鹿乃 - アイロニ
/music/鹿乃/曖昧ばんび~な/11 アイロニ.flac
#EXTINF:335,ヲタみん - Letter Song
/music/未分类/ヲタみん - Letter Song.mp3

View File

@ -0,0 +1,5 @@
#EXTM3U
#EXTINF:279,涼宮ハルヒ(CV.平野綾) - God knows...
/music/涼宮ハルヒ(CV.平野綾)、朝比奈みくる(CV.後藤邑子)/涼宮ハルヒの詰合/01 涼宮ハルヒ(CV.平野綾) - God knows....mp3
#EXTINF:255,涼宮ハルヒ(CV.平野綾) - Lost my music
/music/涼宮ハルヒ(CV.平野綾)、朝比奈みくる(CV.後藤邑子)/涼宮ハルヒの詰合/02 涼宮ハルヒ(CV.平野綾) - Lost my music.mp3

View File

@ -0,0 +1,41 @@
#EXTM3U
#EXTINF:250,Sakurakou K-ON Bu - Cagayake!GIRLS
/music/Sakurakou K-ON Bu/Cagayake!GIRLS/01 Cagayake!GIRLS.mp3
#EXTINF:228,Sakurakou K-ON Bu - Happy!? Sorry!!
/music/Sakurakou K-ON Bu/Cagayake!GIRLS/02 Happy!_ Sorry!!.mp3
#EXTINF:264,Sakurakou K-ON Bu - Dont say “lazy”
/music/Sakurakou K-ON Bu/Dont say “lazy”/01 Dont say “lazy”.m4a
#EXTINF:266,Sakurakou K-ON Bu - Sweet Bitter Beauty Song
/music/Sakurakou K-ON Bu/Dont say “lazy”/02 Sweet Bitter Beauty Song.m4a
#EXTINF:251,Ho-Kago Tea Time - GO! GO! MANIAC
/music/Ho-Kago Tea Time/GO! GO! MANIAC/01 GO! GO! MANIAC.mp3
#EXTINF:269,Ho-Kago Tea Time - Genius…!?
/music/Ho-Kago Tea Time/GO! GO! MANIAC/02 Genius…!_.mp3
#EXTINF:260,Death Devil - 光
/music/未分类/日文流行/Death Devil - 光.flac
#EXTINF:227,放課後ティータイム - Listen!!
/music/放課後ティータイム/Listen!!/01 Listen!!.m4a
#EXTINF:252,放課後ティータイム - Our MAGIC
/music/放課後ティータイム/Listen!!/02 Our MAGIC.m4a
#EXTINF:257,Ho-Kago Tea Time - NO, Thank You!
/music/Ho-Kago Tea Time/NO, Thank You!/01 NO, Thank You!.m4a
#EXTINF:214,Ho-Kago Tea Time - Girls in Wonderland
/music/Ho-Kago Tea Time/NO, Thank You!/02 Girls in Wonderland.m4a
#EXTINF:232,放課後ティータイム - Unmei♪wa♪Endless!
/music/放課後ティータイム/Unmei♪wa♪Endless!/01 Unmei♪wa♪Endless!.mp3
#EXTINF:250,放課後ティータイム - いちばんいっぱい
/music/放課後ティータイム/Unmei♪wa♪Endless!/02 いちばんいっぱい.mp3
#EXTINF:242,放課後ティータイム - Utauyo!!MIRACLE
/music/放課後ティータイム/Utauyo!!MIRACLE/01 Utauyo!!MIRACLE.mp3
#EXTINF:220,放課後ティータイム - キラキラDays
/music/放課後ティータイム/Utauyo!!MIRACLE/02 キラキラDays.mp3
#EXTINF:239,桜高軽音部 - ふわふわ時間
/music/桜高軽音部/ふわふわ時間/01 ふわふわ時間.mp3
#EXTINF:204,桜高軽音部 - 翼をください
/music/桜高軽音部/ふわふわ時間/02 翼をください.mp3
#EXTINF:196,放課後ティータイム - カレーのちライス
/music/放課後ティータイム/放課後ティータイム/1-01 カレーのちライス.mp3
#EXTINF:264,放課後ティータイム - わたしの恋はホッチキス
/music/放課後ティータイム/放課後ティータイム/1-02 わたしの恋はホッチキス.mp3
#EXTINF:238,放課後ティータイム - ふでペン 〜ボールペン〜
/music/放課後ティータイム/放課後ティータイム/1-03 ふでペン 〜ボールペン〜.mp3

View File

@ -0,0 +1,45 @@
#EXTM3U
#EXTINF:369,Lia - 鳥の詩
/music/Various Artists/AIR Original SoundTrack/1-03 Lia - 鳥の詩.mp3
#EXTINF:275,ウサギキノコ - Secret
/music/ウサギキノコ/eclipse 改/13 Secret.flac
#EXTINF:197,Yuri Chika - 涙の物語
/music/Yuri Chika/Good Luck To You/09 涙の物語.mp3
#EXTINF:260,ClariS - irony
/music/ClariS/irony/1-01 irony.mp3
#EXTINF:299,茶太 - 小さな手のひら
/music/Various Artists/KSL Live World 2008 ~Way to the Little Busters! EX~/1-13 茶太 - 小さな手のひら.flac
#EXTINF:335,ヲタみん - Letter Song
/music/未分类/ヲタみん - Letter Song.mp3
#EXTINF:221,チト(CV:水瀬いのり)、ユーリ(CV:久保ユリカ) - More One Night
/music/チト(CV_水瀬いのり)、ユーリ(CV_久保ユリカ)/More One Night/01 More One Night.flac
#EXTINF:276,Lia - My Soul, Your Beats!
/music/Lia _ 多田葵/My Soul, Your Beats! _ Brave Song/1-01 Lia - My Soul, Your Beats!.mp3
#EXTINF:325,多田葵 - Brave Song
/music/Lia _ 多田葵/My Soul, Your Beats! _ Brave Song/1-02 多田葵 - Brave Song.flac
#EXTINF:353,本間芽衣子(茅野愛衣) / 安城鳴子(戸松遥) / 鶴見知利子(早見沙織) - secret base 〜君がくれたもの〜 (10 years after Ver.)
/music/本間芽衣子(茅野愛衣) _ 安城鳴子(戸松遥) _ 鶴見知利子(早見沙織)/secret base 〜君がくれたもの〜/01 secret base 〜君がくれたもの〜 (10 years after Ver.).mp3
#EXTINF:360,karuta - 一番の宝物 (original version)
/music/ANANT-GARDE EYES/TVアニメ「Angel Beats!」オリジナルサウンドトラック/2-19 karuta - 一番の宝物 (original version).flac
#EXTINF:268,千反田える(佐藤聡美)&伊原摩耶花(茅野愛衣) - まどろみの約束
/music/千反田える(佐藤聡美)&伊原摩耶花(茅野愛衣)/まどろみの約束/01 まどろみの約束.mp3
#EXTINF:253,RAM WIRE - 僕らの手には何もないけど、
/music/RAM WIRE/むすぶ/13 僕らの手には何もないけど、.mp3
#EXTINF:340,かぴ - 世界は恋に落ちている acoustic version
/music/HoneyWorks/ハニワ曲歌ってみた5/12 かぴ - 世界は恋に落ちている acoustic version.mp3
#EXTINF:235,TOKOTOKO feat. ゆいこんぬ - ハートビート・フロムユー
/music/TOKOTOKO/ハートビート・フロムユー/06 TOKOTOKO feat. ゆいこんぬ - ハートビート・フロムユー.mp3
#EXTINF:335,じん - アヤノの幸福理論
/music/じん/メカクシティレコーズ/10 アヤノの幸福理論.mp3
#EXTINF:273,茶太 - だんご大家族
/music/eufonius _ 茶太/メグメル _ だんご大家族/02 茶太 - だんご大家族.flac
#EXTINF:239,髏々宮カルタ(花澤香菜) - sweets parade
/music/髏々宮カルタ(花澤香菜) & 青鬼院蜻蛉(杉田智和)/妖狐×僕SS ENDING SONG vol.3/01 髏々宮カルタ(花澤香菜) - sweets parade.mp3
#EXTINF:254,千石撫子 (花澤香菜) - 恋愛サーキュレーション
/music/千石撫子 (花澤香菜)/恋愛サーキュレーション/01 恋愛サーキュレーション.flac
#EXTINF:250,鹿乃 - アイロニ
/music/鹿乃/曖昧ばんび~な/11 アイロニ.flac
#EXTINF:173,ゆめこ - 雨き声残響
/music/未分类/动漫歌曲/ゆめこ - 雨き声残響.mp3
#EXTINF:249,つじあやの - 風になる
/music/野見祐二/猫の恩返し サウンドトラック/25 つじあやの - 風になる.mp3

View File

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:317,浮森かや子 - お隣はだあれ
/music/浮森かや子/お隣はだあれ.mp3

View File

@ -0,0 +1 @@
#EXTM3U

View File

@ -0,0 +1,27 @@
#EXTM3U
#EXTINF:90,HIMEHINA - 約束の血
/music/HIMEHINA/藍の華/01 約束の血.flac
#EXTINF:227,HIMEHINA - 藍の華
/music/HIMEHINA/藍の華/03 藍の華.flac
#EXTINF:223,HIMEHINA - ヒトガタRock
/music/HIMEHINA/藍の華/04 ヒトガタRock.flac
#EXTINF:262,HIMEHINA - ヒバリ(Laugh-In)
/music/HIMEHINA/藍の華/05 ヒバリ(Laugh-In).flac
#EXTINF:251,HIMEHINA - ライライラビットテイル
/music/HIMEHINA/藍の華/06 ライライラビットテイル.flac
#EXTINF:262,HIMEHINA - 琥珀の身体(Message-In)
/music/HIMEHINA/藍の華/08 琥珀の身体(Message-In).flac
#EXTINF:219,HIMEHINA - 溺れるほど愛した花
/music/HIMEHINA/藍の華/10 溺れるほど愛した花.flac
#EXTINF:301,HIMEHINA - 夢景色
/music/HIMEHINA/藍の華/11 夢景色.flac
#EXTINF:286,HIMEHINA - うたかたよいかないで(Message-In)
/music/HIMEHINA/藍の華/12 うたかたよいかないで(Message-In).flac
#EXTINF:265,HIMEHINA - ララ
/music/HIMEHINA/藍の華/14 ララ.flac
#EXTINF:237,HIMEHINA - アダムとマダム
/music/HIMEHINA/藍の華/16 アダムとマダム.flac
#EXTINF:225,HIMEHINA - ヒトガタ
/music/HIMEHINA/藍の華/17 ヒトガタ.flac
#EXTINF:390,HIMEHINA - My Dear
/music/HIMEHINA/藍の華/19 My Dear.flac

0
plugin/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

24
test2.py Normal file
View File

@ -0,0 +1,24 @@
from flask import Flask
app = Flask(__name__)
@app.route("/api/tracks")
def hello_tracks():
return "<p>Hello, tracks!</p>"
@app.route("/api/playlist/<playlist_id>/tracks")
def hello_playlist():
return "<p>Hello, playlist!</p>"
app.run(
host = '127.0.0.1',
port = 7777,
debug = True
)
if __name__== '__main__':
app.run(
host = '127.0.0.1',
port = 7777,
debug = True
)

28
utils.py Normal file
View File

@ -0,0 +1,28 @@
import re
import sys
_URL_PLACEHOLDER_PATTERN = re.compile('<(.*?)>')
def get_pipe(name):
"""通过 mod.ClassName 导入自定义的PipeHandler"""
module_name, obj_name = name.rsplit('.', 1)
__import__(module_name)
module = sys.modules[module_name]
obj = getattr(module, obj_name)
return obj
def extract_placeholders(url):
"""
>>> res = extract_placeholders("/<service_name>/resource/<resource_id>/submit/")
>>> assert set(res) == {"service_name", "resource_id"}
:param url: request url name
:return: list of placeholder name
"""
return _URL_PLACEHOLDER_PATTERN.findall(url)
def replace_placeholder(url, placeholder_name, value):
return url.replace('<{}>'.format(placeholder_name), str(value))