11import { readdirSync , readFileSync , writeFileSync , existsSync } from 'fs' ;
2+ import { readFile } from 'fs/promises' ;
23import path from 'path' ;
34import * as drpy from '../libs/drpyS.js' ;
45import '../libs_drpy/jinja.js'
56import { naturalSort , urljoin , updateQueryString } from '../utils/utils.js'
67import { md5 } from "../libs_drpy/crypto-util.js" ;
78import { ENV } from "../utils/env.js" ;
9+ import { extractNameFromCode } from "../utils/python.js" ;
810import { validateBasicAuth , validatePwd } from "../utils/api_validate.js" ;
911import { getSitesMap } from "../utils/sites-map.js" ;
1012import { getParsesDict } from "../utils/file.js" ;
@@ -16,7 +18,9 @@ const {jsEncoder} = drpy;
1618async function generateSiteJSON ( options , requestHost , sub , pwd ) {
1719 const jsDir = options . jsDir ;
1820 const dr2Dir = options . dr2Dir ;
21+ const pyDir = options . pyDir ;
1922 const configDir = options . configDir ;
23+ const jsonDir = options . jsonDir ;
2024 const subFilePath = options . subFilePath ;
2125 const rootDir = options . rootDir ;
2226
@@ -48,6 +52,33 @@ async function generateSiteJSON(options, requestHost, sub, pwd) {
4852 }
4953 }
5054 let sites = [ ] ;
55+
56+ //以下为自定义APP模板部分
57+ try {
58+ const templateConfigPath = path . join ( jsonDir , './App模板配置.json' ) ;
59+ if ( existsSync ( templateConfigPath ) ) {
60+ const templateContent = readFileSync ( templateConfigPath , 'utf-8' ) ;
61+ const templateConfig = JSON . parse ( templateContent ) ;
62+ sites = Object . entries ( templateConfig ) . filter ( ( [ key ] ) => valid_files . includes ( `${ key } [模板].js` ) )
63+ . flatMap ( ( [ key , config ] ) =>
64+ Object . entries ( config )
65+ . filter ( ( [ name ] ) => name !== "示例" )
66+ . map ( ( [ name ] ) => ( {
67+ key : `drpyS_${ name } _${ key } ` ,
68+ name : `${ name } [M](${ key . replace ( 'App' , '' ) . toUpperCase ( ) } )` ,
69+ type : 4 ,
70+ api : `${ requestHost } /api/${ key } [模板]${ pwd ? `?pwd=${ pwd } ` : '' } ` ,
71+ searchable : 1 ,
72+ filterable : 1 ,
73+ quickSearch : 0 ,
74+ ext : `../json/App模板配置.json$${ name } `
75+ } ) ) ) ;
76+ }
77+ } catch ( e ) {
78+ console . error ( '读取App模板配置失败:' , e . message ) ;
79+ }
80+ //以上为自定义APP[模板]配置自动添加代码
81+
5182 let link_jar = '' ;
5283 // console.log('hide_adult:', ENV.get('hide_adult'));
5384 if ( ENV . get ( 'hide_adult' ) === '1' ) {
@@ -73,6 +104,7 @@ async function generateSiteJSON(options, requestHost, sub, pwd) {
73104 } catch ( e ) {
74105 throw new Error ( `Error parsing rule object for file: ${ file } , ${ e . message } ` ) ;
75106 }
107+ ruleObject . title = ruleObject . title || baseName ;
76108
77109 let fileSites = [ ] ;
78110 if ( baseName === 'push_agent' ) {
@@ -90,8 +122,8 @@ async function generateSiteJSON(options, requestHost, sub, pwd) {
90122 fileSites . push ( { key, name, ext} ) ;
91123 } ) ;
92124 } else {
93- let key = `drpyS_${ baseName } ` ;
94- let name = `${ baseName } (DS)` ;
125+ let key = `drpyS_${ ruleObject . title } ` ;
126+ let name = `${ ruleObject . title } (DS)` ;
95127 fileSites . push ( { key, name} ) ;
96128 }
97129
@@ -156,6 +188,7 @@ async function generateSiteJSON(options, requestHost, sub, pwd) {
156188 } catch ( e ) {
157189 throw new Error ( `Error parsing rule object for file: ${ file } , ${ e . message } ` ) ;
158190 }
191+ ruleObject . title = ruleObject . title || baseName ;
159192
160193 let fileSites = [ ] ;
161194 if ( baseName === 'push_agent' ) {
@@ -170,8 +203,8 @@ async function generateSiteJSON(options, requestHost, sub, pwd) {
170203 fileSites . push ( { key, name, ext : _ext } ) ;
171204 } ) ;
172205 } else {
173- let key = `drpy2_${ baseName } ` ;
174- let name = `${ baseName } (DR2)` ;
206+ let key = `drpy2_${ ruleObject . title } ` ;
207+ let name = `${ ruleObject . title } (DR2)` ;
175208 fileSites . push ( { key, name, ext} ) ;
176209 }
177210
@@ -200,6 +233,77 @@ async function generateSiteJSON(options, requestHost, sub, pwd) {
200233
201234 }
202235
236+ // 根据用户是否启用py源去生成对应配置
237+ if ( ENV . get ( 'enable_py' , '1' ) === '1' ) {
238+ const py_files = readdirSync ( pyDir ) ;
239+ let py_valid_files = py_files . filter ( ( file ) => file . endsWith ( '.py' ) && ! file . startsWith ( '_' ) ) ; // 筛选出不是 "_" 开头的 .py 文件
240+ // log(py_valid_files);
241+ log ( `开始生成python的t3配置,pyDir:${ pyDir } ,源数量: ${ py_valid_files . length } ` ) ;
242+
243+ const py_tasks = py_valid_files . map ( ( file ) => {
244+ return {
245+ func : async ( { file, pyDir, requestHost, pwd, SitesMap} ) => {
246+ const baseName = path . basename ( file , '.py' ) ; // 去掉文件扩展名
247+ const extJson = path . join ( pyDir , baseName + '.json' ) ;
248+ let api = `${ requestHost } /py/${ file } ` ;
249+ let ext = existsSync ( extJson ) ? `${ requestHost } /py/${ file } ` : '' ;
250+ if ( pwd ) {
251+ api += `?pwd=${ pwd } ` ;
252+ if ( ext ) {
253+ ext += `?pwd=${ pwd } ` ;
254+ }
255+ }
256+ let ruleObject = {
257+ searchable : 1 , // 固定值
258+ filterable : 1 , // 固定值
259+ quickSearch : 1 , // 固定值
260+ } ;
261+ const fileContent = await readFile ( path . join ( pyDir , file ) , 'utf-8' ) ;
262+ ruleObject . title = extractNameFromCode ( fileContent ) || baseName ;
263+
264+ let fileSites = [ ] ;
265+ if ( baseName === 'push_agent' ) {
266+ let key = 'push_agent' ;
267+ let name = `${ ruleObject . title } (hipy_t3)` ;
268+ fileSites . push ( { key, name, ext} ) ;
269+ } else if ( SitesMap . hasOwnProperty ( baseName ) && Array . isArray ( SitesMap [ baseName ] ) ) {
270+ SitesMap [ baseName ] . forEach ( ( it ) => {
271+ let key = `hipy_py_${ it . alias } ` ;
272+ let name = `${ it . alias } (hipy_t3)` ;
273+ let _ext = updateQueryString ( ext , it . queryStr ) ;
274+ fileSites . push ( { key, name, ext : _ext } ) ;
275+ } ) ;
276+ } else {
277+ let key = `hipy_py_${ ruleObject . title } ` ;
278+ let name = `${ ruleObject . title } (hipy_t3)` ;
279+ fileSites . push ( { key, name, ext} ) ;
280+ }
281+
282+ fileSites . forEach ( ( fileSite ) => {
283+ const site = {
284+ key : fileSite . key ,
285+ name : fileSite . name ,
286+ type : 3 , // 固定值
287+ api,
288+ searchable : ruleObject . searchable ,
289+ filterable : ruleObject . filterable ,
290+ quickSearch : ruleObject . quickSearch ,
291+ more : ruleObject . more ,
292+ logo : ruleObject . logo ,
293+ ext : fileSite . ext || "" , // 固定为空字符串
294+ } ;
295+ sites . push ( site ) ;
296+ } ) ;
297+ } ,
298+ param : { file, pyDir, requestHost, pwd, SitesMap} ,
299+ id : file ,
300+ } ;
301+ } ) ;
302+
303+ await batchExecute ( py_tasks , listener ) ;
304+
305+ }
306+
203307 // 根据用户是否启用挂载数据源去生成对应配置
204308 if ( ENV . get ( 'enable_link_data' , '0' ) === '1' ) {
205309 log ( `开始挂载外部T4数据` ) ;
0 commit comments