forked from MisakaFxxk/MisakaF_Emby
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
aa6109d
commit bbaccaa
Showing
3 changed files
with
271 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Infuse扫库优化模块 | ||
|
||
### 一、原理实现 | ||
|
||
Infuse扫库时只需要接收固定的json数据,所以我们可以将这些数据保存到数据库内,如果有扫库请求,通过URL内的一些参数定位json,返回即可。 | ||
|
||
Nginx劫持Infuse扫库请求到本地搭建的扫库服务上,首先判断此条json数据库内是否存在,若存在则直接返回,若不存在则通过GET向Emby请求获取,先向Infuse客户端返回json,再保存到数据库内,以供下次直接使用。 | ||
|
||
### 二、环境配置 | ||
|
||
Nginx反向代理本地Emby服务端,Python3&Pip3。 | ||
|
||
``` | ||
安装Python第三方包: | ||
pip3 install flask | ||
pip3 install requests | ||
pip3 install pymysql | ||
pip3 install DBUtils==1.2 | ||
``` | ||
|
||
### 三、Nginx配置 | ||
|
||
打开Nginx反向代理配置文件,在location / 下面的大括号**内**添加: | ||
|
||
I know, I know,这个实现方法相当蠢。如果有高人还望不吝赐教,但目前它至少能跑,反正代码和我有一个能跑就行。 | ||
|
||
``` | ||
if ($http_user_agent ~* "Infuse") { | ||
set $check yes; | ||
} | ||
if ( $request_uri ~* /Users/(.*)/Items\?ExcludeLocationTypes=Virtual ) | ||
{ | ||
set $check2 "${check}yes"; | ||
} | ||
if ( $request_uri ~* Episode ) | ||
{ | ||
set $check3 "${check2}yes"; | ||
} | ||
if ( $request_uri ~* Movie ) | ||
{ | ||
set $check3 "${check2}yes"; | ||
} | ||
set $check4 yes; | ||
if ( $request_uri ~* StartIndex=0 ) | ||
{ | ||
set $check4 no; | ||
} | ||
set $check3 "${check3}${check4}"; | ||
if ($check3 = "yesyesyesyes") | ||
{ | ||
proxy_pass http://127.0.0.1:60000; | ||
} | ||
``` | ||
|
||
### 三、数据库配置 | ||
|
||
在Emby本机上安装Mysql 8.0数据库。 | ||
|
||
首先创建一个名为`infuse`的数据库,然后创建一个名为`metadata`的表,表内结构如下,也可直接使用文件夹内的metadata.sql来导入表结构。 | ||
|
||
![image-20230307091348630](C:\Users\ChengYifei\AppData\Roaming\Typora\typora-user-images\image-20230307091348630.png) | ||
|
||
### 四、Python配置 | ||
|
||
将`infuse.py`下载到本地并打开,修改第11行的Emby地址为未经过Nginx反向代理的Emby地址,修改14行开始的数据库配置内的user和password。 | ||
|
||
### 五、启动优化模块 | ||
|
||
``` | ||
screen -S infuse | ||
python3 infuse.py | ||
或后台运行: | ||
nohup python3 infuse.py > infuse.log 2>&1 & | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
import flask,requests,json,pymysql | ||
from flask import request | ||
from DBUtils.PooledDB import PooledDB | ||
from pymysql.converters import escape_string | ||
|
||
api = flask.Flask(__name__) | ||
localhost = 'http://127.0.0.1:8096' #本地Emby地址,未经过Nginx的Emby访问链接,最后不加/ | ||
|
||
#连接数据库 | ||
DB_CONFIG={ | ||
"host":"127.0.0.1", | ||
"port":3306, | ||
"user":"", | ||
"password":"", | ||
"db":"infuse", | ||
"charset":"utf8" | ||
} | ||
|
||
#创建Mysql线程池 | ||
class MysqlTools(object): | ||
def __init__(self): | ||
self.pool=PooledDB( | ||
creator=pymysql, | ||
maxconnections=10, #连接池允许的最大连接数 | ||
mincached=1, | ||
maxcached=5, | ||
maxshared=3, | ||
blocking=True, | ||
maxusage=None, | ||
setsession=[], | ||
ping=0, | ||
host=DB_CONFIG["host"], | ||
port=DB_CONFIG["port"], | ||
user=DB_CONFIG["user"], | ||
password=DB_CONFIG["password"], | ||
database=DB_CONFIG["db"], | ||
charset=DB_CONFIG["charset"] | ||
) | ||
|
||
def open(self): | ||
conn=self.pool.connection() | ||
cursor=conn.cursor(cursor=pymysql.cursors.DictCursor) | ||
return conn,cursor | ||
|
||
def close(self,conn,cursor): | ||
cursor.close() | ||
conn.close() | ||
|
||
def get_list(self, sql, args=None): | ||
try: | ||
conn,cursor=self.open() | ||
cursor.execute(sql, args) | ||
result = cursor.fetchall() | ||
self.close(conn,cursor) | ||
return result | ||
except: | ||
return False | ||
|
||
# 查询单条记录 | ||
def get_one(self, sql, args=None): | ||
try: | ||
conn, cursor = self.open() | ||
cursor.execute(sql, args) | ||
result = cursor.fetchone() | ||
self.close(conn, cursor) | ||
return result | ||
except: | ||
return False | ||
|
||
# 执行单条sql | ||
def execute_one(self, sql, args=None): | ||
try: | ||
conn, cursor = self.open() | ||
cursor.execute(sql, args) | ||
conn.commit() | ||
self.close(conn, cursor) | ||
return True | ||
except Exception as e: | ||
print(e) | ||
|
||
# 添加数据返回insertID | ||
def create(self, sql, args=None): | ||
try: | ||
conn, cursor = self.open() | ||
cursor.execute(sql, args) | ||
conn.commit() | ||
insert_id = cursor.lastrowid | ||
self.close(conn, cursor) | ||
return insert_id | ||
except: | ||
self.close(conn, cursor) | ||
return False | ||
|
||
def close(self,conn,cursor): | ||
try: | ||
|
||
cursor.close() | ||
conn.close() | ||
except: | ||
raise Exception("关闭数据库失败") | ||
|
||
|
||
@api.route('/Users/<user_id>/Items', methods=["GET", "POST"]) | ||
def update(user_id): | ||
my_mysql=MysqlTools() | ||
#参数获取 | ||
ParentId = request.args.get("ParentId") | ||
StartIndex = request.args.get("StartIndex") | ||
Limit = request.args.get("Limit") | ||
IncludeItemTypes = request.args.get("IncludeItemTypes") | ||
UserAgent = request.user_agent | ||
XEmbyAuthorization = request.headers.get('X-Emby-Authorization') | ||
|
||
#判断是否为新数据 | ||
exist = 0 | ||
try: | ||
sql = "select count(*) from metadata where ParentId = {ParentId} and StartIndex = {StartIndex} and IncludeItemTypes = '{IncludeItemTypes}'".format(ParentId=ParentId,StartIndex=StartIndex,IncludeItemTypes=IncludeItemTypes) | ||
result = my_mysql.get_one(sql) | ||
except Exception as e: | ||
print(e,"flag1") | ||
else: | ||
exist = result["count(*)"] | ||
if(exist == 0): | ||
#新数据请求 | ||
print("未命中,写入数据库") | ||
headers = { | ||
'Connection': 'keep-alive', | ||
'Accept-Language': 'zh-CN', | ||
'Accept-Encoding': 'gzip, deflate', | ||
'User-Agent': str(UserAgent), | ||
'Accept': 'application/json', | ||
'X-Emby-Authorization': str(XEmbyAuthorization) | ||
} | ||
url = localhost + '/Users/{user_id}/Items?ExcludeLocationTypes=Virtual&Fields=DateCreated,Etag,Genres,MediaSources,Overview,ParentId,Path,People,ProviderIds,SortName,CommunityRating,OfficialRating,PremiereDate&ParentId={ParentId}&StartIndex={StartIndex}&Limit={Limit}&IncludeItemTypes={IncludeItemTypes}&Recursive=true'.format(user_id=user_id,ParentId=ParentId,StartIndex=StartIndex,Limit=Limit,IncludeItemTypes=IncludeItemTypes) | ||
response = requests.get(url,headers=headers) | ||
resjson = response.json() | ||
|
||
try: | ||
#向Infuse客户端返回 | ||
return resjson,200,{"Content-Type":"application/json; charset=utf-8","Access-Control-Allow-Headers": "Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, Content-Type, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, X-Emby-Token, X-Emby-Client, X-Emby-Client-Version, X-Emby-Device-Id, X-Emby-Device-Name, X-Emby-Authorization","Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS","Access-Control-Allow-Origin": "*"} | ||
finally: | ||
#向数据库追加新数据 | ||
data = json.dumps(resjson,ensure_ascii=False) | ||
try: | ||
sql = "insert into metadata (ParentId,StartIndex,IncludeItemTypes,data) values ({ParentId},{StartIndex},'{IncludeItemTypes}','{data}')".format(ParentId=ParentId,StartIndex=StartIndex,IncludeItemTypes=IncludeItemTypes,data=escape_string(data)) | ||
result = my_mysql.create(sql) | ||
except Exception as e: | ||
print(e,"flag2") | ||
else: | ||
#数据库中已存在 | ||
print("命中") | ||
try: | ||
sql = "select data from metadata where ParentId = {ParentId} and StartIndex = {StartIndex} and IncludeItemTypes = '{IncludeItemTypes}'".format(ParentId=ParentId,StartIndex=StartIndex,IncludeItemTypes=IncludeItemTypes) | ||
result = my_mysql.get_one(sql) | ||
except Exception as e: | ||
print(e,"flag3") | ||
else: | ||
data = result["data"] | ||
resjson = json.loads(data) | ||
#向Infuse客户端返回 | ||
return resjson,200,{"Content-Type":"application/json; charset=utf-8","Access-Control-Allow-Headers": "Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, Content-Type, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, X-Emby-Token, X-Emby-Client, X-Emby-Client-Version, X-Emby-Device-Id, X-Emby-Device-Name, X-Emby-Authorization","Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS","Access-Control-Allow-Origin": "*"} | ||
|
||
|
||
if __name__ == '__main__': | ||
api.run(port=60000,debug=True,host='0.0.0.0',threaded=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
Navicat Premium Data Transfer | ||
Source Server : 公益服2Infuse数据库 | ||
Source Server Type : MySQL | ||
Source Server Version : 80024 (8.0.24) | ||
Source Host : 172.96.161.64:3306 | ||
Source Schema : infuse | ||
Target Server Type : MySQL | ||
Target Server Version : 80024 (8.0.24) | ||
File Encoding : 65001 | ||
Date: 06/03/2023 15:44:29 | ||
*/ | ||
|
||
SET NAMES utf8mb4; | ||
SET FOREIGN_KEY_CHECKS = 0; | ||
|
||
-- ---------------------------- | ||
-- Table structure for metadata | ||
-- ---------------------------- | ||
DROP TABLE IF EXISTS `metadata`; | ||
CREATE TABLE `metadata` ( | ||
`ParentId` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, | ||
`StartIndex` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, | ||
`IncludeItemTypes` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, | ||
`limit` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, | ||
`data` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL | ||
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; | ||
|
||
SET FOREIGN_KEY_CHECKS = 1; |