124 lines
No EOL
4.9 KiB
Python
124 lines
No EOL
4.9 KiB
Python
from flask import Flask, request, Response
|
||
import logging
|
||
from config import config
|
||
from handlers.registry import HandlerRegistry
|
||
from utils.rss_generator import RSSGenerator
|
||
|
||
# 配置日志
|
||
logging.basicConfig(level=logging.INFO)
|
||
logger = logging.getLogger(__name__)
|
||
|
||
def create_app(config_name='default'):
|
||
app = Flask(__name__)
|
||
app.config.from_object(config[config_name])
|
||
|
||
# 初始化处理器注册中心
|
||
handler_registry = HandlerRegistry()
|
||
|
||
# 初始化RSS生成器
|
||
rss_generator = RSSGenerator(
|
||
title=app.config['RSS_TITLE'],
|
||
description=app.config['RSS_DESCRIPTION'],
|
||
link=app.config['RSS_LINK'],
|
||
language=app.config['RSS_LANGUAGE']
|
||
)
|
||
|
||
@app.route('/')
|
||
def index():
|
||
"""API文档页面"""
|
||
available_handlers = handler_registry.list_handlers()
|
||
docs = f"""
|
||
<h1>Crypto RSS Service</h1>
|
||
<h2>可用的RSS订阅源:</h2>
|
||
<ul>
|
||
"""
|
||
|
||
for handler_name in available_handlers:
|
||
if handler_name == 'crypto':
|
||
docs += f"""
|
||
<li><a href="/rss/{handler_name}">/rss/{handler_name}</a> - 默认加密货币价格</li>
|
||
<li><a href="/rss/{handler_name}/eth/usdt">/rss/{handler_name}/eth/usdt</a> - ETH/USDT价格</li>
|
||
<li><a href="/rss/{handler_name}/btc/usdt">/rss/{handler_name}/btc/usdt</a> - BTC/USDT价格</li>
|
||
<li><a href="/rss/{handler_name}/ETH/USDC">/rss/{handler_name}/ETH/USDC</a> - ETH/USDC价格(大写)</li>
|
||
"""
|
||
|
||
docs += """
|
||
</ul>
|
||
<h2>使用说明:</h2>
|
||
<p>将RSS链接粘贴到您的墨水屏RSS阅读器中即可。</p>
|
||
<p>URL格式:/rss/crypto/[base_currency]/[quote_currency]</p>
|
||
<p>例如:/rss/crypto/eth/usdc 或 /rss/crypto/ETH/USDC 都表示 ETH-USDC 交易对</p>
|
||
<p>支持大小写混合格式</p>
|
||
"""
|
||
return docs
|
||
|
||
@app.route('/rss/<handler_name>')
|
||
@app.route('/rss/<handler_name>/<path:base_currency>')
|
||
@app.route('/rss/<handler_name>/<path:base_currency>/<path:quote_currency>')
|
||
def rss_feed(handler_name, base_currency=None, quote_currency=None):
|
||
"""RSS订阅源端点"""
|
||
handler = handler_registry.get_handler(handler_name)
|
||
|
||
if not handler:
|
||
return Response("Handler not found", status=404)
|
||
|
||
try:
|
||
# 构建请求参数
|
||
request_params = {}
|
||
|
||
# 处理crypto handler的特殊逻辑
|
||
if handler_name == 'crypto':
|
||
if base_currency and quote_currency:
|
||
# 将路径参数转换为pair格式
|
||
pair = f"{base_currency.upper()}-{quote_currency.upper()}"
|
||
request_params['pair'] = pair
|
||
elif base_currency and not quote_currency:
|
||
# 只有base_currency,使用默认quote_currency (通常是USDC)
|
||
default_quote = 'USDC' # 你可以在config中配置这个默认值
|
||
pair = f"{base_currency.upper()}-{default_quote}"
|
||
request_params['pair'] = pair
|
||
else:
|
||
# 使用默认pair
|
||
request_params['pair'] = app.config.get('DEFAULT_CRYPTO_PAIR', 'BTC-USDT')
|
||
|
||
# 合并其他查询参数(如果有的话)
|
||
request_params.update(request.args.to_dict())
|
||
|
||
# 让处理器处理请求
|
||
items = handler.handle(**request_params)
|
||
|
||
if not items:
|
||
return Response("No data available", status=204)
|
||
|
||
if handler_name == 'crypto':
|
||
motdTitle = request_params.get('pair', app.config.get('DEFAULT_CRYPTO_PAIR', 'BTC-USDT'))
|
||
motdTitle = motdTitle.replace('-', '/').upper()
|
||
rss_xml = rss_generator.generate_rss(items, motdTitle=motdTitle)
|
||
else:
|
||
rss_xml = rss_generator.generate_rss(items)
|
||
|
||
return Response(rss_xml, mimetype='application/rss+xml')
|
||
|
||
|
||
except Exception as e:
|
||
logger.error(f"生成RSS时出错: {e}")
|
||
error_items = [{
|
||
"title": "服务暂时不可用",
|
||
"description": f"生成RSS时出现错误: {str(e)}",
|
||
"link": app.config['RSS_LINK']
|
||
}]
|
||
rss_xml = rss_generator.generate_rss(error_items)
|
||
return Response(rss_xml, mimetype='application/rss+xml', status=500)
|
||
|
||
@app.route('/health')
|
||
def health_check():
|
||
"""健康检查端点"""
|
||
return {"status": "healthy", "available_handlers": handler_registry.list_handlers()}
|
||
|
||
return app
|
||
|
||
app = create_app('production') # 生产环境使用production配置
|
||
|
||
if __name__ == '__main__':
|
||
app = create_app('development')
|
||
app.run(host='0.0.0.0', port=5000, debug=True) |