├── packages ├── fxd-app-codegen │ ├── .gitignore │ ├── package.json │ ├── fxd-apps.txt │ ├── fxd-intro.txt │ └── LICENSE.txt ├── fxd-cli │ ├── fxd.cmd │ ├── CHANGE.md │ ├── package.json │ ├── README.md │ ├── fxd │ ├── index.js │ └── LICENSE.txt ├── fxd-sdk │ ├── CHANGE.md │ ├── package.json │ └── LICENSE.txt ├── fxd-app-core │ ├── prompts.md │ ├── README.md │ ├── CHANGE.md │ ├── package.json │ ├── doc.md │ └── LICENSE.txt ├── fxd-app-browser │ ├── package.json │ ├── index.js │ └── LICENSE.txt ├── fxd-app-demo │ ├── index.js │ ├── package.json │ └── LICENSE.txt ├── fxd-app-douyin-count │ ├── package.json │ ├── index.js │ └── LICENSE.txt ├── fxd-app-weibo-live │ ├── index.js │ ├── package.json │ └── LICENSE.txt ├── fxd-app-flow-runner │ ├── package.json │ └── LICENSE.txt ├── fxd-app-screenshot │ ├── index.js │ ├── package.json │ └── LICENSE.txt ├── fxd-app-rss-fetch │ ├── package.json │ ├── index.js │ └── LICENSE.txt ├── fxd-app-gpt-bat │ ├── package.json │ ├── index.js │ └── LICENSE.txt ├── fxd-app-translate │ ├── index.js │ ├── package.json │ └── LICENSE.txt ├── fxd-app-weibo-publish │ ├── package.json │ ├── LICENSE.txt │ └── index.js ├── fxd-app-fetch │ ├── index.js │ ├── LICENSE.txt │ └── package.json ├── fxd-app-search │ ├── package.json │ └── index.js ├── fxd-app-memo-forward │ ├── package.json │ └── LICENSE.txt ├── fxd-app-check-chan │ ├── LICENSE.txt │ ├── index.js │ └── package.json └── fxd-app-keep-live2 │ ├── LICENSE.txt │ ├── package.json │ └── index.js ├── images ├── image.png └── 20240414114221.png ├── .gitignore ├── package.json ├── README.zh-cn.md ├── LICENSE.txt └── README.md /packages/fxd-app-codegen/.gitignore: -------------------------------------------------------------------------------- 1 | log.txt -------------------------------------------------------------------------------- /packages/fxd-cli/fxd.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | node index.js %* -------------------------------------------------------------------------------- /images/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/fxd/HEAD/images/image.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | # 忽略所有目录下的 .DS_Store 3 | .DS_Store 4 | test.txt 5 | test.js -------------------------------------------------------------------------------- /packages/fxd-sdk/CHANGE.md: -------------------------------------------------------------------------------- 1 | # Change log 2 | 3 | 1. 1.0.60: add packageVersion to this.sdk -------------------------------------------------------------------------------- /images/20240414114221.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/easychen/fxd/HEAD/images/20240414114221.png -------------------------------------------------------------------------------- /packages/fxd-app-core/prompts.md: -------------------------------------------------------------------------------- 1 | 请根据附件的代码,编写一个说明文档,对这个基础app提供的方法、参数和返回值进行说明。需要注明方法的用途、参数的类型和是否必填。 2 | -------------------------------------------------------------------------------- /packages/fxd-app-core/README.md: -------------------------------------------------------------------------------- 1 | # Fxd 核心应用 2 | 3 | 1. std app interface 在这里定义 4 | 1. login/logout 等网站相关功能在这里实现 5 | 1. 数据存储等 fxd app 通用基础功能在这里事项 -------------------------------------------------------------------------------- /packages/fxd-cli/CHANGE.md: -------------------------------------------------------------------------------- 1 | # Change log 2 | 3 | 1. 1.0.6: 兼容 yarn. 4 | 1. 1.0.5: Add cli_path as an argument to the method call. 5 | 2. 1.0.4: Add fxd-cli/node_modules to the search folders. 6 | 3. 1.0.3: Add npm and yarn global node_modules folder. -------------------------------------------------------------------------------- /packages/fxd-app-core/CHANGE.md: -------------------------------------------------------------------------------- 1 | # Change log 2 | 3 | 4 | 1. 1.0.46: add package verison to help method 5 | 1. 1.0.45: force install method works in fxd-cli folder 6 | 1. 1.0.43: add install method to install npm package: `fxd _install packagename` 7 | 1. 1.0.42: fix typo ( setDeaultOpts && setDeaultCommand ) -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "repository": "https://gitlab.com/easychen/fxd.git", 6 | "author": "Easy ", 7 | "private": "true", 8 | "license": "SEE LICENSE IN LICENSE.txt", 9 | "workspaces": [ 10 | "packages/*" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /packages/fxd-app-browser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-browser", 3 | "displayName": "fxd browser", 4 | "version": "1.0.8", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "dependencies": { 9 | "@playwright/browser-chromium": "^1.41.2", 10 | "fxd-app-core": "^1.0.42", 11 | "json-diff": "^1.0.6", 12 | "playwright": "^1.41.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/fxd-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-sdk", 3 | "version": "1.0.69", 4 | "main": "index.js", 5 | "license": "SEE LICENSE IN LICENSE.txt", 6 | "type": "module", 7 | "dependencies": { 8 | "api2d": "^0.1.40", 9 | "cross-fetch": "^4.0.0", 10 | "https-proxy-agent": "^7.0.4", 11 | "node-fetch": "^3.3.2", 12 | "node-json-db": "^2.3.0", 13 | "read-pkg": "^9.0.1", 14 | "socket.io-client": "^4.7.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/fxd-app-core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-core", 3 | "displayName": "fxd核心应用", 4 | "version": "1.0.48", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "dependencies": { 9 | "chalk": "^5.3.0", 10 | "clipboardy": "^4.0.0", 11 | "fxd-sdk": "^1.0.59", 12 | "humps": "^2.0.1", 13 | "inquirer": "^9.2.14", 14 | "lodash": "^4.17.21", 15 | "read-pkg": "^9.0.1" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/fxd-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-cli", 3 | "version": "1.0.7", 4 | "main": "index.js", 5 | "license": "SEE LICENSE IN LICENSE.txt", 6 | "dependencies": { 7 | "chalk": "^5.3.0", 8 | "fxd-app-core": "^1.0.43", 9 | "humps": "^2.0.1", 10 | "minimist": "^1.2.8" 11 | }, 12 | "type": "module", 13 | "bin": { 14 | "fxd": "index.js" 15 | }, 16 | "engines": { 17 | "node": ">=18.0.0" 18 | }, 19 | "scripts": { 20 | "test": "echo \"Error: no test specified\" && exit 1" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/fxd-app-demo/index.js: -------------------------------------------------------------------------------- 1 | import FxdApp from 'fxd-app-core'; 2 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 3 | 4 | 5 | 6 | export default class FxdDemo extends FxdApp { 7 | constructor() { 8 | super(); 9 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 10 | // ... 11 | } 12 | 13 | async main(args, opts, command, cli_path) { 14 | this.setDefaultOpts(opts); 15 | this.setDefaultCommand(command); 16 | this.format = this.get('format'); 17 | console.log(this.sdk.name, command, args, opts, this.get('url', opts)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/fxd-app-douyin-count/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-douyin-count", 3 | "displayName": "抖音作品数监测", 4 | "version": "1.0.0", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "args": { 10 | "main": { 11 | "url": { 12 | "name": "url", 13 | "description": "抖音账号页面URL", 14 | "type": "string", 15 | "required": true, 16 | "example": "https://www.douyin.com/user/..." 17 | } 18 | } 19 | } 20 | }, 21 | "dependencies": { 22 | "fxd-app-check-chan": "^1.0.25" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/fxd-app-douyin-count/index.js: -------------------------------------------------------------------------------- 1 | // import FxdCheckChan from '/Users/easy/Code/gitcode/fxd/packages/fxd-app-check-chan/index.js'; 2 | import FxdCheckChan from 'fxd-app-check-chan'; 3 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 4 | 5 | export default class FxdDouyinCoutn extends FxdCheckChan { 6 | constructor() { 7 | super(); 8 | const oldArgsSettings = this.sdk.args; 9 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 10 | this.sdk.args = this.mergeProps(oldArgsSettings,[ 11 | 'watch', 12 | 'main|check|watch.-selectors,prejs,prejs_args,preplay,list' 13 | ]); 14 | } 15 | 16 | async main(args, opts, command) { 17 | opts['selectors'] = `[data-e2e='user-tab-count']`; 18 | return await this.watch(args, opts, 'watch'); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /packages/fxd-app-weibo-live/index.js: -------------------------------------------------------------------------------- 1 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 2 | import FxdKeepLive2 from 'fxd-app-keep-live2'; 3 | 4 | 5 | export default class FxdWeiboLive extends FxdKeepLive2 { 6 | constructor() { 7 | super(); 8 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 9 | // ... 10 | } 11 | 12 | async main(args, opts, command, cli_path) { 13 | return this.help(); 14 | } 15 | 16 | async auth(args, opts, command) { 17 | // 指定 authurl 18 | opts['auth_url'] = 'https://m.weibo.cn'; 19 | return super.auth(args, opts, command); 20 | } 21 | 22 | async refresh(args, opts, command) { 23 | // 指定 refreshurl 24 | opts['refresh_url'] = 'https://m.weibo.cn'; 25 | return super.refresh(args, opts, command); 26 | } 27 | 28 | async check(args, opts, command) { 29 | // 指定 checkurl 30 | opts['check_url'] = 'https://m.weibo.cn/profile'; 31 | opts['check_selector'] = 'div.profile-header'; 32 | return super.check(args, opts, command); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/fxd-app-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-demo", 3 | "description": "app demo", 4 | "version": "1.0.0", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 0, 11 | "args": { 12 | "main": { 13 | "url": { 14 | "name": "url", 15 | "description": "要打开的页面 URL", 16 | "type": "string", 17 | "required": false, 18 | "default": "https://f.ftqq.com", 19 | "example": "https://www.example.com" 20 | } 21 | } 22 | }, 23 | "output": { 24 | "main": { 25 | "success": { 26 | "result": { 27 | "name": "result", 28 | "description": "返回结果" 29 | } 30 | } 31 | }, 32 | "fail": { 33 | "error": { 34 | "name": "error", 35 | "type": "string", 36 | "description": "错误信息", 37 | "example": "搜索过程中发生错误" 38 | } 39 | } 40 | } 41 | }, 42 | "dependencies": { 43 | "fxd-app-core": "^1.0.47", 44 | "fxd-sdk": "^1.0.66" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/fxd-app-core/doc.md: -------------------------------------------------------------------------------- 1 | FxdApp 类,是Fxd系列应用的基础类,应用都直接或者间接的继承自它。 2 | 3 | 以下是它包含的方法: 4 | 5 | ## 方法 6 | 7 | ### run(params, opts, raw) 8 | - 用途:运行命令 9 | - 参数: 10 | - params:命令参数数组 11 | - opts:选项参数对象 12 | - raw:是否原始模式,默认为false 13 | 14 | ### list(args, opts) 15 | - 用途:列出保存的命令 16 | 17 | ### exe(index) / exec(index) 18 | - 用途:执行保存的命令 19 | - 参数: 20 | - index:命令索引 21 | 22 | ### login(args, opts) 23 | - 用途:登录 24 | - 参数: 25 | - opts.token: 用户令牌,字符串,非必填 26 | 27 | ### logout() 28 | - 用途:退出登录 29 | 30 | ### profile() 31 | - 用途:获取用户信息 32 | 33 | ### echoError(msg) 34 | - 用途:显示错误信息 35 | - 参数: 36 | - msg:错误消息文本 37 | 38 | ### help() 39 | - 用途:显示帮助信息 40 | 41 | ### setDeaultOpts(opts) 42 | - 用途:设置默认选项 43 | - 参数: 44 | - opts:选项参数对象 45 | 46 | ### setDeaultCommand(command) 47 | - 用途:设置默认命令 48 | - 参数: 49 | - command:命令名称,字符串 50 | 51 | ### get(key, opts, command) 52 | - 用途:获得参数 53 | - 参数: 54 | - key:参数名称 55 | - opts:选项参数对象,非必填 56 | - command:命令名称,字符串,非必填 57 | 58 | ### log(...args) 59 | - 用途:打印日志 60 | - 参数: 61 | - args: 要打印的内容 62 | 63 | ### return(ret) 64 | - 用途:统一返回值格式 65 | - 参数: 66 | - ret:要返回的值 67 | 68 | ### feedPublish(content, meta, is_public, command) 69 | - 用途:发布 feed 70 | - 参数: 71 | - content: feed 内容 72 | - meta: feed 元信息 73 | - is_public: 是否公开 74 | - command: 命令名,字符串,非必填 75 | 76 | ### feedRemove(id) 77 | - 用途:删除 feed 78 | - 参数: 79 | - id: feed id 80 | 81 | ### mergeProps(oldObject, props) 82 | - 用途:合并属性 83 | - 参数: 84 | - oldObject: 原对象 85 | - props: 新的属性 86 | 87 | -------------------------------------------------------------------------------- /packages/fxd-app-flow-runner/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-flow-runner", 3 | "description": "后台运行fxd flow", 4 | "version": "1.0.8+042714", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 1, 11 | "args": { 12 | "main": { 13 | "id": { 14 | "name": "id", 15 | "description": "要运行的flow id", 16 | "type": "number", 17 | "required": false, 18 | "default": 0, 19 | "example": 1 20 | }, 21 | "file_path": 22 | { 23 | "name": "file_path", 24 | "description": "要运行的flow文件路径", 25 | "type": "string", 26 | "required": false, 27 | "example": "flow/flow.json" 28 | }, 29 | "format": 30 | { 31 | "name": "format", 32 | "description": "返回结果格式", 33 | "type": "string", 34 | "required": false, 35 | "default": "json", 36 | "example": "json" 37 | } 38 | } 39 | }, 40 | "output": { 41 | "main": { 42 | "success": { 43 | "result": { 44 | "name": "result", 45 | "description": "返回结果" 46 | } 47 | } 48 | }, 49 | "fail": { 50 | "error": { 51 | "name": "error", 52 | "type": "string", 53 | "description": "错误信息", 54 | "example": "搜索过程中发生错误" 55 | } 56 | } 57 | } 58 | }, 59 | "dependencies": { 60 | "api2d": "^0.1.40", 61 | "jsonata": "^2.0.4" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /packages/fxd-app-browser/index.js: -------------------------------------------------------------------------------- 1 | // import FxdApp from '/Users/easy/Code/gitcode/fxd/packages/fxd-app-core/index.js'; 2 | import FxdApp from 'fxd-app-core'; 3 | import { FxdSdk, getDirname, getHomeDir } from 'fxd-sdk'; 4 | import { readPackageSync } from 'read-pkg'; 5 | import path from 'path'; 6 | import { chromium, firefox, webkit } from 'playwright'; 7 | import chalk from 'chalk'; 8 | 9 | export default class FxdBrowser extends FxdApp { 10 | constructor() { 11 | super(); 12 | this.sdk = new FxdSdk(readPackageSync({ cwd: getDirname(import.meta.url) })); 13 | } 14 | 15 | getUserDirFullPath(username) { 16 | return path.resolve(getHomeDir(), 'user', username); 17 | } 18 | 19 | async getBrowserAndMore( userDirFullPath, options ) 20 | { 21 | if( process.env.FXD_LOCAL_CHROME ) options.executablePath = process.env.FXD_LOCAL_CHROME; 22 | const browserType = options.browserType || process.env.FXD_BROWSER_TYPE || 'chromium'; 23 | const Browser = (browserType === 'firefox' ) ? firefox : ( browserType === 'webkit' ) ? webkit : chromium; 24 | const browser = await Browser.launchPersistentContext(userDirFullPath, options); 25 | // 如果打开了页面,且页面为 blank,则重用页面 26 | const openedPages = browser.pages().find( page => page.url() === 'about:blank' ) ; 27 | const page = openedPages || await browser.newPage(); 28 | const context = page.context(); 29 | 30 | return { browser, page, context }; 31 | } 32 | 33 | async main(args, opts, command) { 34 | this.log(chalk.red("FxdBrowser 公用库,为基于无头浏览器的服务提供基础,不可直接运行")); 35 | return false; 36 | } 37 | 38 | 39 | 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /packages/fxd-app-screenshot/index.js: -------------------------------------------------------------------------------- 1 | import FxdBrowser from 'fxd-app-browser'; 2 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 3 | import path from 'path'; 4 | import fs from 'fs'; 5 | 6 | export default class FxdScreenshot extends FxdBrowser { 7 | constructor() { 8 | super(); 9 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 10 | // ... 11 | } 12 | 13 | async main(args, opts, command, cli_path) { 14 | this.setDefaultOpts(opts); 15 | this.setDefaultCommand(command); 16 | this.format = this.get('format'); 17 | 18 | const url = this.get('url'); 19 | // 不存在则使用当前目录 20 | const savePath = this.get('save_path') || path.join(process.cwd(), 'screenshot.png'); 21 | const userDirFullPath = process.env.FXD_USER_DIR || this.getUserDirFullPath(this.get('user')); 22 | const { browser, page, context } = await this.getBrowserAndMore(userDirFullPath, { headless: this.get('headless'), browserType: this.get('browser'), deviceScaleFactor: this.get('scale')}); 23 | // timeout 24 | page.setDefaultTimeout(this.get('timeout')); 25 | 26 | await page.setViewportSize({ 27 | width:this.get('width'), 28 | height:this.get('height') 29 | }); 30 | await page.goto(url); 31 | await page.waitForLoadState(this.get('wait_type')); 32 | await page.screenshot({ 33 | path: savePath, 34 | fullPage: this.get('full_page') 35 | }); 36 | await browser.close(); 37 | // 检查文件是否存在 38 | return fs.existsSync(savePath) ? this.return({ action: 'screenshot', message: 'done', output: savePath }) : this.return({ action: 'screenshot', message: 'error', output: 'screenshot failed' }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/fxd-app-weibo-live/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-weibo-live", 3 | "description": "刷新微博页面,保持登录态", 4 | "version": "1.0.0", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 1, 11 | "args": { 12 | "main|auth|check|refresh": { 13 | "user": { 14 | "name": "user", 15 | "cn_name": "浏览器用户", 16 | "description": "浏览器使用的用户目录", 17 | "type": "string", 18 | "default": "default", 19 | "example": "admin" 20 | }, 21 | "timeout": { 22 | "name": "timeout", 23 | "cn_name": "加载超时时间", 24 | "description": "状态检测页面加载超时时间,单位毫秒", 25 | "type": "number", 26 | "default": 5000, 27 | "example": 8000 28 | }, 29 | "headless": { 30 | "name": "headless", 31 | "cn_name": "后台模式", 32 | "description": "是否使用后台模式", 33 | "type": "boolean", 34 | "default": true, 35 | "example": false 36 | }, 37 | "format": { 38 | "name": "format", 39 | "cn_name": "返回格式", 40 | "description": "返回的数据格式", 41 | "type": "string", 42 | "default": "text", 43 | "example": "json", 44 | "enum": [ 45 | "json", 46 | "text" 47 | ] 48 | }, 49 | "browser": { 50 | "name": "browser", 51 | "description": "浏览器类型", 52 | "type": "string", 53 | "default": "chrome", 54 | "example": "chrome", 55 | "enum": [ 56 | "chrome", 57 | "firefox", 58 | "webkit" 59 | ] 60 | } 61 | } 62 | } 63 | }, 64 | "dependencies": { 65 | "fxd-app-keep-live2": "^1.0.2" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/fxd-app-codegen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-codegen", 3 | "description": "自动生成fxd app代码", 4 | "version": "1.0.0", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 0, 11 | "args": { 12 | "main": { 13 | "url": { 14 | "name": "url", 15 | "description": "要打开的页面 URL", 16 | "type": "string", 17 | "required": false, 18 | "default": "https://f.ftqq.com", 19 | "example": "https://www.example.com" 20 | } 21 | }, 22 | "gen": 23 | { 24 | "howto": 25 | { 26 | "name": "howto", 27 | "description": "描述应用功能,以及如何生成", 28 | "type": "string", 29 | "required": false, 30 | "example": "从由wordpress架设的ft07.com获取最新的rss" 31 | }, 32 | "package_name": 33 | { 34 | "name": "package_name", 35 | "description": "应用包名", 36 | "type": "string", 37 | "required": true, 38 | "example": "fxd-app-test" 39 | }, 40 | "parent_package": 41 | { 42 | "name": "parent_package", 43 | "description": "父类对应的包名", 44 | "type": "string", 45 | "required": true, 46 | "example": "fxd-app-core" 47 | } 48 | }, 49 | "indexing": 50 | { 51 | "indexType": 52 | { 53 | "name": "type", 54 | "description": "索引类型", 55 | "type": "string", 56 | "required": false, 57 | "example": "intro", 58 | "default": "intro", 59 | "enum": ["intro", "code", "sdk"] 60 | } 61 | } 62 | }, 63 | "output": { 64 | "main": { 65 | "success": { 66 | "result": { 67 | "name": "result", 68 | "description": "返回结果" 69 | } 70 | } 71 | }, 72 | "fail": { 73 | "error": { 74 | "name": "error", 75 | "type": "string", 76 | "description": "错误信息", 77 | "example": "搜索过程中发生错误" 78 | } 79 | } 80 | } 81 | }, 82 | "dependencies": { 83 | "fxd-app-core": "^1.0.47", 84 | "fxd-sdk": "^1.0.67", 85 | "inquirer": "^9.2.22", 86 | "vectra": "^0.7.6" 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /packages/fxd-app-rss-fetch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-rss-fetch", 3 | "description": "解析RSS并返回是否有更新", 4 | "version": "1.0.4", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 0, 11 | "args": { 12 | "main": { 13 | "url": { 14 | "name": "url", 15 | "description": "RSS Feed URL", 16 | "type": "string", 17 | "required": true, 18 | "default": "https://ft07.com/feed", 19 | "example": "https://ft07.com/feed" 20 | }, 21 | "only_changed": { 22 | "name": "only_changed", 23 | "cn_name": "只看最新", 24 | "description": "仅返回新的entries", 25 | "type": "boolean", 26 | "required": false, 27 | "default": false, 28 | "example": true 29 | }, 30 | "sendkey": { 31 | "name": "sendkey", 32 | "description": "Server酱的sendkey,填写后检查到新entries会推送", 33 | "type": "string", 34 | "required": false, 35 | "example": "SCT123456" 36 | }, 37 | "timeout": { 38 | "name": "timeout", 39 | "description": "超时时间(毫秒)", 40 | "type": "number", 41 | "required": false, 42 | "default": 10000, 43 | "example": 10000 44 | }, 45 | "proxy": { 46 | "name": "proxy", 47 | "description": "代理地址", 48 | "type": "string", 49 | "required": false, 50 | "example": "http://127.0.0.1:8001" 51 | }, 52 | "format": { 53 | "name": "format", 54 | "description": "返回数据格式", 55 | "type": "string", 56 | "required": false, 57 | "default": "json", 58 | "example": "json" 59 | } 60 | } 61 | }, 62 | "output": { 63 | "main": { 64 | "success": { 65 | "feed": { 66 | "name": "feed", 67 | "description": "feed的相关信息" 68 | }, 69 | "output": { 70 | "name": "output", 71 | "description": "任务页面的信息" 72 | } 73 | } 74 | }, 75 | "fail": { 76 | "error": { 77 | "name": "error", 78 | "type": "string", 79 | "description": "错误信息", 80 | "example": "搜索过程中发生错误" 81 | } 82 | } 83 | } 84 | }, 85 | "dependencies": { 86 | "@extractus/feed-extractor": "^7.1.0", 87 | "dayjs": "^1.11.10", 88 | "https-proxy-agent": "^7.0.4" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /packages/fxd-cli/README.md: -------------------------------------------------------------------------------- 1 | **What is Fxd?** 2 | 3 | [ [中文](./README.zh-cn.md) | [English](./README.md) ] 4 | 5 | Fxd stands for "Flow eXtension Define" and is a specification designed for extending workflows, especially AI and automation workflows. 6 | 7 | For example, if you need to monitor the latest articles from an RSS feed, translate them into Chinese, create illustrations for them, and then publish them on your own platform, this task isn't difficult for AI, but due to the multiple steps involved, few tools can automate the entire process. 8 | 9 | According to the Fxd approach, we would first encapsulate several Fxd Apps: 10 | 11 | - RSS Monitoring App 12 | - GPTChat App 13 | - DALL-E App 14 | - X Publishing App 15 | 16 | Each of these is an independent NPM package, and each app can be called via the Fxd-Cli on the command line. Thus, by using Shell or other scripts to combine these Fxd Apps, various functionalities can be flexibly implemented. For instance, if you decide not to publish to the original platform but to Weibo instead, you simply replace the last app. 17 | 18 | For users unfamiliar with using command lines, there is also a client compatible with the Fxd specification, such as the FlowDeer we are currently beta testing, which helps users design workflows through a visual flowchart. 19 | 20 | **License** 21 | 22 | The SDK, command-line tools, and core packages of FXD by default adopt the PolyForm Noncommercial License. If different licenses are included in the packages directory, the latter will prevail. 23 | 24 | Any code contributed to this project is considered authorized for commercial use by the project authors and their companies, and distributed under the project's agreement (PolyForm Noncommercial License). 25 | 26 | The PolyForm Noncommercial License allows you to modify the project and distribute it for non-commercial purposes. During distribution, it is necessary to ensure that the user receives a copy of the authorization agreement and is aware that the copyright belongs to "Fangtang Balloon". For more details, please read the license document. 27 | 28 | The application you create based on FXD (like fxd-app-demo) is up to you to license, but distribution must still adhere to the agreement. For example: 29 | 30 | 1. If you create an fxd-app-demo and license it under the MIT license, you may handle the code of fxd-app-demo under your chosen protocol. 31 | 2. If you guide users to install and use fxd-app-demo through fxd-cli, there is no need to adhere to the project's protocol. 32 | 3. If you package the fxd-cli and fxd-sdk code as a product for distribution, then you must comply with the project's protocol. -------------------------------------------------------------------------------- /packages/fxd-app-gpt-bat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-gpt-bat", 3 | "description": "长文本批处理", 4 | "version": "1.0.2", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 0, 11 | "args": { 12 | "main|file": { 13 | "char_count": { 14 | "name": "char_count", 15 | "type": "number", 16 | "description": "每次处理的字符数", 17 | "default": 1000, 18 | "example": 1000 19 | }, 20 | "prompt": { 21 | "name": "prompt", 22 | "type": "string", 23 | "description": "提示词", 24 | "required": true, 25 | "example": "请翻译一下内容{{{content}}}" 26 | }, 27 | "ai_key": { 28 | "name": "ai_key", 29 | "type": "string", 30 | "description": "AI密钥", 31 | "example": "123456" 32 | }, 33 | "ai_apibase": { 34 | "name": "ai_apibase", 35 | "type": "string", 36 | "description": "AI接口地址", 37 | "example": "http://oa.api2d.net" 38 | }, 39 | "ai_model": { 40 | "name": "ai_model", 41 | "type": "string", 42 | "description": "AI模型", 43 | "example": "gpt-3.5-turbo" 44 | }, 45 | "format": { 46 | "name": "format", 47 | "type": "string", 48 | "description": "返回结果格式", 49 | "default": "json", 50 | "example": "json" 51 | } 52 | }, 53 | "main": 54 | { 55 | "content": { 56 | "name": "content", 57 | "type": "string", 58 | "required": true, 59 | "description": "待处理的长文本", 60 | "example": "这是一段文本", 61 | "ui": "textarea" 62 | } 63 | }, 64 | "file": 65 | { 66 | "file_path": 67 | { 68 | "name": "file_path", 69 | "type": "string", 70 | "required": true, 71 | "description": "待处理的文件路径", 72 | "example": "/tmp/test.txt" 73 | } 74 | } 75 | }, 76 | "output": { 77 | "main": { 78 | "success": { 79 | "result": { 80 | "name": "result", 81 | "description": "返回结果" 82 | } 83 | } 84 | }, 85 | "fail": { 86 | "error": { 87 | "name": "error", 88 | "type": "string", 89 | "description": "错误信息", 90 | "example": "搜索过程中发生错误" 91 | } 92 | } 93 | } 94 | }, 95 | "dependencies": { 96 | "api2d": "^0.1.40" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /packages/fxd-app-translate/index.js: -------------------------------------------------------------------------------- 1 | import FxdApp from 'fxd-app-core'; 2 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 3 | import FxdGptBat from 'fxd-app-gpt-bat'; 4 | import Api2d from 'api2d'; 5 | import fs from 'fs'; 6 | 7 | export default class FxdTranslate extends FxdApp { 8 | constructor() { 9 | super(); 10 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 11 | // ... 12 | } 13 | 14 | async main(args, opts, command, cli_path) { 15 | this.setDefaultOpts(opts); 16 | this.setDefaultCommand(command); 17 | this.format = this.get('format'); 18 | const content = this.get('content'); 19 | let summary; 20 | 21 | if( this.get('summarize_first') ) 22 | { 23 | // 首先通过 gpt 对 content 进行摘要 24 | const prompt1 = `你是世界一流的语言学家,正在翻译一篇长文。由于篇幅较长,每次只翻译其中一部分。为了保持翻译的连贯性,请先阅读全文,并编写一个翻译提示,注明文章的主题和内容,涉及什么领域的专有名词。全文如下:\n\n${content},不要翻译全文,先撰写翻译提示:`; 25 | 26 | const ai = new Api2d(this.get('ai_key'), this.get('ai_apibase')); 27 | summary = await ai.completion({ 28 | messages: [{ 29 | role: 'user', 30 | content: prompt1 31 | }], 32 | stream: true, 33 | model: this.get('model')||'gpt-3.5-turbo-16k', 34 | onMessage: (chars) => { 35 | this.sdk.wslog(chars, true); 36 | } 37 | }); 38 | } 39 | 40 | const translate_tips = summary ? `全文的翻译提示:${summary}` : ''; 41 | if(translate_tips) this.log(translate_tips); 42 | 43 | const gpt_bat = new FxdGptBat(); 44 | return await gpt_bat.main( 45 | null, 46 | { 47 | content: content, 48 | char_count: this.get('char_count'), 49 | prompt: `你是世界一流的语言学家,正在翻译一篇长文中的一段。${translate_tips} 请翻译,${this.get('from_lang')}:\n\n{{{content}}},${this.get('to_lang')}:`, 50 | ai_key: this.get('ai_key')||"", 51 | ai_apibase: this.get('ai_apibase')||"https://oa.api2d.net", 52 | ai_model: this.get('ai_model')||'gpt-3.5-turbo-16k', 53 | format: this.get('format'), 54 | }, 55 | 'main', 56 | ); 57 | } 58 | 59 | async file(args, opts, command) { 60 | const file_path = this.get('file_path', opts, command ); 61 | if( !file_path ) 62 | { 63 | return this.echoError('file_path is required'); 64 | } 65 | if(!fs.existsSync(file_path)) return this.echoError(`file not exists: ${file_path}`); 66 | const content = fs.readFileSync(file_path, 'utf-8'); 67 | opts.content = content; 68 | return await this.main(args, opts, 'main'); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/fxd-app-translate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-translate", 3 | "description": "长文翻译", 4 | "version": "1.0.5", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 0, 11 | "args": { 12 | "main|file": { 13 | "char_count": { 14 | "name": "char_count", 15 | "type": "number", 16 | "description": "每次处理的字符数", 17 | "default": 1000, 18 | "example": 1000 19 | }, 20 | "ai_key": { 21 | "name": "ai_key", 22 | "type": "string", 23 | "description": "AI密钥", 24 | "example": "123456" 25 | }, 26 | "ai_apibase": { 27 | "name": "ai_apibase", 28 | "type": "string", 29 | "description": "AI接口地址", 30 | "example": "http://oa.api2d.net" 31 | }, 32 | "ai_model": { 33 | "name": "ai_model", 34 | "type": "string", 35 | "description": "AI模型", 36 | "example": "gpt-3.5-turbo" 37 | }, 38 | "format": { 39 | "name": "format", 40 | "type": "string", 41 | "description": "返回结果格式", 42 | "default": "json", 43 | "example": "json" 44 | }, 45 | "from_lang": { 46 | "name": "from_lang", 47 | "type": "string", 48 | "description": "源语言", 49 | "default": "中文", 50 | "example": "中文" 51 | }, 52 | "to_lang": { 53 | "name": "to_lang", 54 | "type": "string", 55 | "description": "目标语言", 56 | "default": "英文", 57 | "example": "英文" 58 | }, 59 | "summarize_first": { 60 | "name": "summarize_first", 61 | "type": "boolean", 62 | "description": "是否先进行摘要", 63 | "default": false, 64 | "example": true 65 | } 66 | }, 67 | "main": { 68 | "content": { 69 | "name": "content", 70 | "type": "string", 71 | "required": true, 72 | "description": "待处理的长文本", 73 | "example": "这是一段文本", 74 | "ui": "textarea" 75 | } 76 | }, 77 | "file": { 78 | "file_path": { 79 | "name": "file_path", 80 | "type": "string", 81 | "required": true, 82 | "description": "待处理的文件路径", 83 | "example": "/tmp/test.txt" 84 | } 85 | } 86 | }, 87 | "output": { 88 | "main": { 89 | "success": { 90 | "message": { 91 | "name": "message", 92 | "type": "string", 93 | "description": "状态", 94 | "example": "success" 95 | }, 96 | "data": { 97 | "name": "data", 98 | "type": "string", 99 | "description": "处理结果", 100 | "example": "翻译后的内容" 101 | } 102 | } 103 | }, 104 | "fail": { 105 | "error": { 106 | "name": "error", 107 | "type": "string", 108 | "description": "错误信息", 109 | "example": "搜索过程中发生错误" 110 | } 111 | } 112 | } 113 | }, 114 | "dependencies": { 115 | "api2d": "^0.1.40", 116 | "fxd-app-gpt-bat": "^1.0.2" 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /README.zh-cn.md: -------------------------------------------------------------------------------- 1 | # Fxd是什么 2 | 3 | 4 | [ [中文](./README.zh-cn.md) | [English](./README.md) ] 5 | 6 | ![](images/20240414114221.png) 7 | 8 | Fxd 是 Flow eXtension Define 的缩写,它是一个被设计用于工作流(尤其是AI和自动化工作流)扩展的规范。 9 | 10 | [FXD官方手册](https://ft07.com/fxd/) 11 | 12 | 比如说,你需要从RSS中监测最新文章,然后翻译为中文,并为其配图后,发布到自己的X上边。这个任务对AI来讲并不困难,但因为环节较多,很少有工具可以自动化完成。 13 | 14 | 按Fxd的做法,我们会首先封装以下几个Fxd App: 15 | 16 | - RSS监测 App 17 | - GPTChat APP 18 | - DALL-E APP 19 | - X发布APP 20 | 21 | 其中每一个都是独立的 NPM Package,而且每一个 APP 都可以通过 Fxd-Cli 在命令行下调用。这样,我们只需要用 Shell 或者其他脚本,将这些 Fxd App 组合起来,就可以灵活地实现各种功能。比如你不想发布到X了,改为发布到微博。那么只需要将最后一个APP 换掉。 22 | 23 | 一个发布微博的例子: 24 | 25 | ```bash 26 | fxd weiboLive auth # 首次发布时需要在启动的浏览器中登录,不用每次都手动登录 27 | fxd weiboPublish --content="你好呀" --self_only="true" --format="json" --headless="false" 28 | ``` 29 | 30 | 也可以在遵循 FXD 规范的客户端,比如 FlowDeer 客户端中直接使用。 31 | 32 | ![FlowDeer](images/image.png) 33 | 34 | # 开发环境 35 | 36 | 37 | ## 命令行调试 38 | 39 | 本 Repo 采用了 Yarn workspaces 来管理多个包。在根目录下运行: 40 | 41 | ```bash 42 | yarn install 43 | ``` 44 |
45 | Windows 无法加载文件 **Roaming\npm\yarn.ps1 的解决方案 46 | 这是因为策略限制导致的错误,请按以下步骤解决: 47 | 48 | 1. 搜索Powershell,右键以管理员身份运行 49 | 1. 输入 Set-ExecutionPolicy RemoteSigned 然后选 Y 50 | 1. 关闭PowerShell,重新运行 yarn 命令 51 |
52 | 53 | 54 | 然后进入命令行的目录 55 | ```bash 56 | cd packages/fxd-cli 57 | ``` 58 | 59 | 类Unix系统上,将目录下的 ./fxd 作为命令行工具使用即可: 60 | 61 | ```bash 62 | # 查看帮助 63 | ./fxd core help 64 | 65 | # 查看Demo应用帮助 66 | ./fxd demo help 67 | ``` 68 | Windows上需要手工添加 node 命令前缀 69 | 70 | ```bash 71 | # 查看帮助 72 | node fxd core help 73 | 74 | # 查看Demo应用帮助 75 | node fxd demo help 76 | ``` 77 | 78 | ## fxd app 代码生成 79 | 80 | 你可以为 `fxd-app-demo` 创建副本进行修改调试,完成后,`npm publish fxd-app-your-app` 发布即可在所有支持FXD规范的软件中使用。 81 | 82 | 2024/05/21 开始引入 codegen app 来初始化 fxd app,使用方式如下: 83 | 84 | 配置环境变量: 85 | 86 | - DEFAULT_AI_CHAT_KEY # openai/api2d key 87 | - DEFAULT_AI_CHAT_BASEURL # https://api.openai.com 或者 https://oa.api2d.net 88 | - DEFAULT_AI_CHAT_MODEL # 模型,默认使用 gpt-4o 89 | 90 | 在 fxd-cli 目录下,运行: 91 | 92 | ```bash 93 | ./fxd codegen 94 | ``` 95 | 96 | 按提示操作即可。 97 | 98 | https://github.com/easychen/fxd/assets/1294760/c6f995f8-b5ae-4db4-9265-8d6ebb4b781c 99 | 100 | 101 | ## 在FlowDeer中调试 102 | 103 | 默认情况下,FlowDeer直接安装 NPM 网站上的包;但我们有需要在发布前调试。这里提供一种解决方案: 104 | 105 | 由于FlowDeer会优先在本地目录查找,因此我们可以通过命令行在 FlowDeer 对应的目录下运行 npm install 进行本地安装。 106 | 107 | 具体而言,对于Mac系统: 108 | 109 | ```bash 110 | cd /Applications/FlowDeer.app/Contents/Resources/app.asar.unpacked/src/local-api 111 | npm install path/to/your/package 112 | ``` 113 | 114 | 如果你没有将 FlowDeer 安装在 Application 目录,请自行调整 /Applications/FlowDeer.app 部分路径。 115 | 116 | 对于Windows系统: 117 | 118 | ```bash 119 | cd /resources/app.asar.unpacked/src/local-api 120 | npm install path/to/your/package 121 | ``` 122 | 123 | 安装完成后,再在 FlowDeer 界面添加包名即可。 124 | 125 | # License 126 | 127 | FXD 的SDK、命令行工具和核心包默认采用 PolyForm Noncommercial License,如 packages 目录下包含不同的 License,则以后者为准。 128 | 129 | 任何贡献到本项目的代码,均视为授权项目作者及其名下公司用于商业用途、并按本项目协议(PolyForm Noncommercial License)分发。 130 | 131 | PolyForm Noncommercial License 允许您对本项目进行修改,并用于任何非商业目的分发。分发过程中,需要确保使用人获得授权协议副本,并知晓版权归属于「方糖气球」。更详细的说明请阅读授权文件。 132 | 133 | 您创建的基于 FXD 的应用(类似 fxd-app-demo )由您自行决定授权,但分发时仍需遵守协议。举例而言: 134 | 135 | 1. 如果您创建了 fxd-app-demo 并以 MIT 协议授权,您可以按自定协议随意处理 fxd-app-demo 的代码 136 | 2. 如果您引导用户通过 fxd-cli 安装并使用 fxd-app-demo,亦无需遵守本项目的协议 137 | 3. 如果您将 fxd-cli 和 fxd-sdk 代码打包为一个产品进行分发,那么则需要遵守本项目的协议 -------------------------------------------------------------------------------- /packages/fxd-app-rss-fetch/index.js: -------------------------------------------------------------------------------- 1 | import FxdApp from 'fxd-app-core'; 2 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 3 | import { extract } from '@extractus/feed-extractor'; 4 | import dayjs from 'dayjs'; 5 | import { HttpsProxyAgent } from 'https-proxy-agent'; 6 | 7 | export default class FxdRssFetch extends FxdApp { 8 | constructor() { 9 | super(); 10 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 11 | // ... 12 | } 13 | 14 | async main(args, opts, command, cli_path) { 15 | this.setDefaultOpts(opts); 16 | this.setDefaultCommand(command); 17 | this.format = this.get('format'); 18 | const proxyObject = this.get('proxy') ? {agent:new HttpsProxyAgent(this.get('proxy'))} : {}; 19 | 20 | try { 21 | const url = this.get('url'); 22 | const feed = await extract(url, { 23 | getExtraEntryFields: (feedEntry) => { 24 | // console.log("feedEntry",feedEntry); 25 | return { 'content': feedEntry.content && feedEntry.content['#text'] ? turndownService.turndown(feedEntry.content['#text']) : "" }; 26 | } 27 | },{ 28 | signal: AbortSignal.timeout(this.get('timeout')), 29 | ...proxyObject 30 | }); 31 | 32 | if( this.get('only_changed') && feed.entries && feed.entries.length > 0) 33 | { 34 | const urlSHA = this.sdk.sha1(`rss-fetch:${url}`); 35 | // console.log("urlSHA", urlSHA); 36 | const newFeedIdArray = []; 37 | const newEntries = []; 38 | const sentFeeds = await this.sdk.getValue(urlSHA)||[]; 39 | // 如果 feed.entries 的 item.id 不在 sentFeeds 里,则加入 newEntries;否则加入 oldEntries 40 | for( const entry of feed.entries ) 41 | { 42 | if( !sentFeeds.includes(entry.id) ) 43 | { 44 | newEntries.push(entry); 45 | newFeedIdArray.push(entry.id); 46 | } 47 | } 48 | 49 | // console.log("newFeedIdArray", newFeedIdArray); 50 | 51 | if( newEntries.length > 0 ) 52 | { 53 | feed.entries = newEntries; 54 | feed.changed = true; 55 | await this.sdk.setValue(urlSHA, [...newFeedIdArray,...sentFeeds]); 56 | 57 | if( this.get('sendkey') ) 58 | { 59 | let markdown = ``; 60 | for( const entry of newEntries ) 61 | { 62 | markdown += `### ${entry.title}\n\n${entry.description}\n\n${dayjs(entry.pubDate).format('YYYY-MM-DD HH:mm:ss')}\n\n[查看网页](${entry.link})\n\n---\n\n`; 63 | } 64 | this.sdk.scSend(`${feed.title}有更新`, markdown, this.get('sendkey')); 65 | } 66 | 67 | }else 68 | { 69 | feed.entries = []; 70 | feed.changed = false; 71 | } 72 | } 73 | 74 | feed.only_changed = this.get('only_changed'); 75 | const result = {feed, output: feed.changed ? 'changed' : 'unchanged'}; 76 | 77 | this.log(JSON.stringify(result, null, 4)); 78 | return this.return(result); 79 | 80 | } catch (error) { 81 | this.echoError(error); 82 | } 83 | 84 | 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /packages/fxd-app-gpt-bat/index.js: -------------------------------------------------------------------------------- 1 | import FxdApp from 'fxd-app-core'; 2 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 3 | import Api2d from 'api2d'; 4 | import fs from 'fs'; 5 | 6 | export default class FxdGptBat extends FxdApp { 7 | constructor() { 8 | super(); 9 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 10 | // ... 11 | } 12 | 13 | async main(args, opts, command, cli_path) { 14 | this.setDefaultOpts(opts); 15 | this.setDefaultCommand(command); 16 | this.format = this.get('format'); 17 | 18 | let content = this.get('content'); 19 | const char_count = parseInt(this.get('char_count'))||1000; 20 | // 将 content 按句号和换行符分割成数组,然后拼接起来,保证每一段字数不超过 char_count。注意,句号和换行不能丢 21 | // 先把句号后边没有换行的都加上换行 22 | content = content.replace(/([。!?])([^\\n])/g, '$1\n$2'); 23 | // 然后按换行符分割 24 | let contentArray = content.split('\n'); 25 | // 按字数重新组合为段 26 | let newContentArray = []; 27 | let temp = ''; 28 | for( let i = 0; i < contentArray.length; i++ ) 29 | { 30 | let line = contentArray[i]; 31 | if( temp.length + line.length > char_count ) 32 | { 33 | newContentArray.push(temp); 34 | temp = ''; 35 | } 36 | temp += line; 37 | } 38 | if( temp.length > 0 ) 39 | { 40 | newContentArray.push(temp); 41 | } 42 | 43 | // 去掉空行 44 | newContentArray = newContentArray.filter( item => item.length > 0 ); 45 | 46 | this.log(`分为 ${newContentArray.length} 段`); 47 | // console.log(newContentArray); 48 | 49 | try { 50 | const result = []; 51 | const prompt_template = this.get('prompt'); 52 | // 然后分段用 gpt 处理 53 | for( let i = 0; i < newContentArray.length; i++ ) 54 | { 55 | this.log(`处理第 ${i+1}/${newContentArray.length} 段`); 56 | let line = newContentArray[i]; 57 | const prompt = prompt_template.replace('{{{content}}}', line); 58 | // console.log(prompt); 59 | const ai = new Api2d(this.get('ai_key'), this.get('ai_apibase')); 60 | const ret = await ai.completion({ 61 | messages: [{ 62 | role: 'user', 63 | content: prompt 64 | }], 65 | stream: true, 66 | model: this.get('model')||'gpt-3.5-turbo', 67 | onMessage: (chars) => { 68 | this.sdk.wslog(chars, true); 69 | } 70 | }); 71 | if( ret ) 72 | { 73 | this.log(ret); 74 | result.push(ret); 75 | } 76 | } 77 | this.log(result); 78 | return this.return({ message: 'success', data: result.join('\n') }); 79 | 80 | } catch (error) { 81 | return this.echoError(error?.message); 82 | } 83 | } 84 | 85 | async file(args, opts, command) { 86 | const file_path = this.get('file_path', opts, command ); 87 | if( !file_path ) 88 | { 89 | return this.echoError('file_path is required'); 90 | } 91 | if(!fs.existsSync(file_path)) return this.echoError(`file not exists: ${file_path}`); 92 | const content = fs.readFileSync(file_path, 'utf-8'); 93 | opts.content = content; 94 | return await this.main(args, opts, 'main'); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /packages/fxd-cli/fxd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import chalk from 'chalk'; 4 | import minimist from 'minimist'; 5 | import humps from 'humps'; 6 | import path, { dirname } from 'path'; 7 | import { execSync, exec as execCb } from 'child_process'; 8 | import { promisify } from 'util'; 9 | const exec = promisify(execCb); 10 | 11 | async function checkYarnInstallation() { 12 | try { 13 | const { stdout } = await exec('yarn --version'); 14 | return true; 15 | } catch (error) { 16 | return false; 17 | } 18 | } 19 | 20 | import { fileURLToPath, pathToFileURL } from 'url'; 21 | import fs from 'fs'; 22 | import os from 'os'; 23 | const __dirname = dirname(fileURLToPath(import.meta.url)); 24 | 25 | // const DEV = true || process.env.NODE_ENV === 'development'; 26 | 27 | // 读取参数 28 | const { _: args, ...opts } = minimist(process.argv.slice(2)); 29 | let [command, ...params] = args; 30 | // ./fxd _login main --user=easy -p "book/23423432/ 34234" 31 | // ^ ^ ^ ^ ^ ^ ^ ^ 32 | // command params opts opts opts opts opts 33 | 34 | // console.log(chalk.green('fxd-cli'), command, params, opts); 35 | 36 | // 如果命令不存在,则默认为 core help 37 | if( !command ) 38 | { 39 | command = 'core'; 40 | params = ['help']; 41 | } 42 | 43 | // 如果命令以 _ 开头,则为内部命令,转向 core 44 | if( command.startsWith('_') ) 45 | { 46 | // 内部命令 47 | params = [command.slice(1), ...params]; 48 | command = 'core'; 49 | } 50 | 51 | // 检查 fxd_app_${command} module 是否存在(ESM语法) 52 | let module; 53 | const formattedCommand = humps.decamelize(command, { separator: '-' }); 54 | const packageName = `fxd-app-${formattedCommand}`; 55 | try { 56 | 57 | // 调试模式则加载本地文件 58 | const paths = []; 59 | // 上级目录 60 | paths.push(path.join(__dirname, '..', packageName , 'index.js')); 61 | // 开发目录(独立项目) 62 | paths.push(`~/Code/gitcode/${packageName}/index.js`); 63 | 64 | // npm 全局安装目录,通过 npm root -g 实时获取,使用 ESM 语法 65 | const npmGlobalRoot = execSync('npm root -g').toString().trim(); 66 | paths.push(path.join(npmGlobalRoot, packageName, 'index.js')); 67 | 68 | // 作为 fxd-cli 全局安装的子目录被安装 69 | paths.push(path.join(npmGlobalRoot, 'fxd-cli', 'node_modules', packageName, 'index.js')); 70 | 71 | // 检查 yarn 命令是否存在 72 | if( await checkYarnInstallation() ) 73 | { 74 | // yarn 全局安装目录,通过 yarn global dir 实时获取,使用 ESM 语法 75 | const yarnGlobalRoot = execSync('yarn global dir').toString().trim(); 76 | paths.push(path.join(yarnGlobalRoot, 'node_modules', packageName, 'index.js')); 77 | 78 | // 作为 fxd-cli 全局安装的子目录被安装 79 | paths.push(path.join(yarnGlobalRoot,'node_modules', 'fxd-cli', 'node_modules', packageName, 'index.js')); 80 | } 81 | 82 | // 挨个尝试,如果都不存在,这为 `${packageName}` 83 | let thePath = `${packageName}`; 84 | // 循环 paths,如果存在,则赋值给 thePath 85 | for (const p of paths) { 86 | if (fs.existsSync(p)) { 87 | thePath = p; 88 | break; 89 | } 90 | } 91 | 92 | const app = await import(pathToFileURL(thePath)); 93 | module = new app.default(); 94 | // 如果存在 module.run 方法,则执行 95 | if (module && module.run) { 96 | 97 | // params, opts, command, cli_path 98 | await module.run(params, opts, params[0], __dirname); 99 | }else 100 | { 101 | console.log("no module.run", module); 102 | } 103 | } 104 | catch(e) 105 | { 106 | console.log("e", e); 107 | console.error(chalk.red(`fxd-cli: command "${command}(${packageName})" not found`)); 108 | process.exit(1); 109 | } 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /packages/fxd-cli/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import chalk from 'chalk'; 4 | import minimist from 'minimist'; 5 | import humps from 'humps'; 6 | import path, { dirname } from 'path'; 7 | import { execSync, exec as execCb } from 'child_process'; 8 | import { promisify } from 'util'; 9 | const exec = promisify(execCb); 10 | 11 | async function checkYarnInstallation() { 12 | try { 13 | const { stdout } = await exec('yarn --version'); 14 | return true; 15 | } catch (error) { 16 | return false; 17 | } 18 | } 19 | 20 | import { fileURLToPath, pathToFileURL } from 'url'; 21 | import fs from 'fs'; 22 | import os from 'os'; 23 | const __dirname = dirname(fileURLToPath(import.meta.url)); 24 | 25 | // const DEV = true || process.env.NODE_ENV === 'development'; 26 | 27 | // 读取参数 28 | const { _: args, ...opts } = minimist(process.argv.slice(2)); 29 | let [command, ...params] = args; 30 | // ./fxd _login main --user=easy -p "book/23423432/ 34234" 31 | // ^ ^ ^ ^ ^ ^ ^ ^ 32 | // command params opts opts opts opts opts 33 | 34 | // console.log(chalk.green('fxd-cli'), command, params, opts); 35 | 36 | // 如果命令不存在,则默认为 core help 37 | if( !command ) 38 | { 39 | command = 'core'; 40 | params = ['help']; 41 | } 42 | 43 | // 如果命令以 _ 开头,则为内部命令,转向 core 44 | if( command.startsWith('_') ) 45 | { 46 | // 内部命令 47 | params = [command.slice(1), ...params]; 48 | command = 'core'; 49 | } 50 | 51 | // 检查 fxd_app_${command} module 是否存在(ESM语法) 52 | let module; 53 | const formattedCommand = humps.decamelize(command, { separator: '-' }); 54 | const packageName = `fxd-app-${formattedCommand}`; 55 | try { 56 | 57 | // 调试模式则加载本地文件 58 | const paths = []; 59 | // 上级目录 60 | paths.push(path.join(__dirname, '..', packageName , 'index.js')); 61 | // 开发目录(独立项目) 62 | paths.push(`~/Code/gitcode/${packageName}/index.js`); 63 | 64 | // npm 全局安装目录,通过 npm root -g 实时获取,使用 ESM 语法 65 | const npmGlobalRoot = execSync('npm root -g').toString().trim(); 66 | paths.push(path.join(npmGlobalRoot, packageName, 'index.js')); 67 | 68 | // 作为 fxd-cli 全局安装的子目录被安装 69 | paths.push(path.join(npmGlobalRoot, 'fxd-cli', 'node_modules', packageName, 'index.js')); 70 | 71 | // 检查 yarn 命令是否存在 72 | if( await checkYarnInstallation() ) 73 | { 74 | // yarn 全局安装目录,通过 yarn global dir 实时获取,使用 ESM 语法 75 | const yarnGlobalRoot = execSync('yarn global dir').toString().trim(); 76 | paths.push(path.join(yarnGlobalRoot, 'node_modules', packageName, 'index.js')); 77 | 78 | // 作为 fxd-cli 全局安装的子目录被安装 79 | paths.push(path.join(yarnGlobalRoot,'node_modules', 'fxd-cli', 'node_modules', packageName, 'index.js')); 80 | } 81 | 82 | // 挨个尝试,如果都不存在,这为 `${packageName}` 83 | let thePath = `${packageName}`; 84 | // 循环 paths,如果存在,则赋值给 thePath 85 | for (const p of paths) { 86 | if (fs.existsSync(p)) { 87 | thePath = p; 88 | break; 89 | } 90 | } 91 | 92 | const app = await import(pathToFileURL(thePath)); 93 | module = new app.default(); 94 | // 如果存在 module.run 方法,则执行 95 | if (module && module.run) { 96 | 97 | // params, opts, command, cli_path 98 | await module.run(params, opts, params[0], __dirname); 99 | }else 100 | { 101 | console.log("no module.run", module); 102 | } 103 | } 104 | catch(e) 105 | { 106 | console.log("e", e); 107 | console.error(chalk.red(`fxd-cli: command "${command}(${packageName})" not found`)); 108 | process.exit(1); 109 | } 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /packages/fxd-app-weibo-publish/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-weibo-publish", 3 | "version": "1.0.13", 4 | "main": "index.js", 5 | "type": "module", 6 | "meta": { 7 | "for": "fxd", 8 | "author_uid": 1, 9 | "args": { 10 | "main|publish": { 11 | "content": { 12 | "name": "content", 13 | "cn_name": "微博正文", 14 | "type": "string", 15 | "required": true, 16 | "description": "微博内容" 17 | }, 18 | "headless": { 19 | "name": "headless", 20 | "cn_name": "后台模式", 21 | "description": "是否使用后台模式", 22 | "type": "boolean", 23 | "default": true, 24 | "example": "true" 25 | }, 26 | "user": { 27 | "name": "user", 28 | "description": "浏览器使用的用户目录", 29 | "type": "string", 30 | "default": "default", 31 | "example": "admin" 32 | }, 33 | "format": { 34 | "name": "format", 35 | "description": "返回的数据格式", 36 | "type": "string", 37 | "default": "text", 38 | "example": "json", 39 | "enum": [ 40 | "json", 41 | "text" 42 | ] 43 | }, 44 | "timeout": { 45 | "name": "timeout", 46 | "description": " Playwright 操作超时时间,单位毫秒", 47 | "type": "number", 48 | "default": 60000, 49 | "example": 30000 50 | }, 51 | "wait_type": { 52 | "name": "wait_type", 53 | "description": "等待元素出现的方式", 54 | "type": "string", 55 | "default": "domcontentloaded", 56 | "example": "networkidle", 57 | "enum": [ 58 | "domcontentloaded", 59 | "load", 60 | "networkidle" 61 | ] 62 | }, 63 | "images": { 64 | "name": "images", 65 | "cn_name": "微博配图URL", 66 | "description": "图片地址,用逗号分隔", 67 | "type": "string", 68 | "default": "", 69 | "example": "https://www.baidu.com/1.jpg,https://www.baidu.com/2.jpg" 70 | }, 71 | "self_only": { 72 | "name": "self_only", 73 | "cn_name": "仅自己可见", 74 | "description": "是否仅对自己可见", 75 | "type": "boolean", 76 | "default": false, 77 | "example": "true" 78 | }, 79 | "browser": { 80 | "name": "browser", 81 | "description": "浏览器类型", 82 | "type": "string", 83 | "default": "chrome", 84 | "example": "chrome", 85 | "enum": [ 86 | "chrome", 87 | "firefox", 88 | "webkit" 89 | ] 90 | } 91 | } 92 | }, 93 | "output": { 94 | "main|publish": { 95 | "success": { 96 | "action": { 97 | "name": "action", 98 | "type": "string", 99 | "description": "执行的动作", 100 | "example": "publish" 101 | }, 102 | "message": { 103 | "name": "message", 104 | "type": "string", 105 | "description": "执行结果的简述", 106 | "example": "done" 107 | }, 108 | "output": { 109 | "name": "output", 110 | "type": "string", 111 | "description": "微博内容的前100个字符加上省略号", 112 | "example": "这是微博的前100个字符的示例..." 113 | }, 114 | "checked": { 115 | "name": "checked", 116 | "type": "boolean", 117 | "description": "是否在用户主页上检查到发布的微博", 118 | "example": "true" 119 | } 120 | }, 121 | "fail": { 122 | "error": { 123 | "name": "error", 124 | "type": "string", 125 | "description": "错误的详细信息", 126 | "example": "发布微博时出错" 127 | }, 128 | "output": { 129 | "name": "output", 130 | "type": "string", 131 | "description": "错误信息的消息文本", 132 | "example": "网络连接失败" 133 | } 134 | } 135 | } 136 | } 137 | }, 138 | "dependencies": { 139 | "dayjs": "^1.11.10", 140 | "download": "^8.0.0" 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /packages/fxd-app-fetch/index.js: -------------------------------------------------------------------------------- 1 | // import FxdBrowser from '/Users/easy/Code/gitcode/fxd/packages/fxd-app-browser/index.js'; 2 | import FxdBrowser from 'fxd-app-browser'; 3 | import { FxdSdk, getPackageInfo, myFetch, jsonDecode } from 'fxd-sdk'; 4 | import TurndownService from 'turndown'; 5 | const turndownService = new TurndownService(); 6 | import { JSDOM } from 'jsdom'; 7 | import { Readability } from '@mozilla/readability'; 8 | import sanitizeHtml from 'sanitize-html'; 9 | 10 | export default class FxdFetch extends FxdBrowser { 11 | constructor() { 12 | super(); 13 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 14 | } 15 | 16 | async main(args, opts, command) { 17 | this.setDefaultOpts(opts); 18 | this.setDefaultCommand(command); 19 | this.format = this.get('format'); 20 | 21 | // URL 22 | const url = this.get('url'); 23 | if (!url) this.echoError("url is required"); 24 | 25 | const headless = this.get('headless'); 26 | const { page, browser } = await this.getBrowserAndMore(this.getUserDirFullPath(this.get('user')), { headless, browserType:this.get('browser') }); 27 | 28 | page.setDefaultTimeout(this.get('timeout')); // 设置超时 29 | await page.goto(url);// 打开URL 30 | await page.waitForLoadState( this.get('wait_type')); 31 | 32 | if( this.get('delay') > 0 ) 33 | { 34 | // 等待 delay ms 35 | await page.waitForTimeout(this.get('delay')); 36 | } 37 | 38 | const html = await page.content(); 39 | // 使用 Readability 解析 html 40 | const dom = new JSDOM(html, { url } ); 41 | const reader = new Readability(dom.window.document); 42 | const article = reader.parse(); 43 | const contentHtml = article.content || dom.window.document.body.innerHTML; 44 | const contentText = article.textContent || dom.window.document.body.textContent; 45 | 46 | const element = page.locator('body').first(); 47 | let ret; 48 | switch( this.get('output') ) 49 | { 50 | case 'raw': 51 | ret = await element.innerHTML(); 52 | this.log(ret); 53 | break; 54 | case 'markdown': 55 | // 使用 turndown 实现 html to markdown 56 | ret = turndownService.turndown(contentHtml); 57 | this.log(ret); 58 | break; 59 | case 'readable': 60 | ret = contentHtml; 61 | this.log(ret); 62 | break; 63 | // 注意这个 html 是简化版本的,仅用于编写selector 64 | case 'html': 65 | ret = normalizeWhitespace(sanitizeHtml(await element.innerHTML(), { 66 | allowedAttributes: { 67 | '*': [ 'id', 'class', 'data-*' ] 68 | }, 69 | enforceHtmlBoundary: true, 70 | })); 71 | this.log(ret); 72 | break; 73 | case 'raw_text': 74 | ret = await element.innerText(); 75 | this.log(ret); 76 | break; 77 | case 'text': 78 | default: 79 | ret = contentText?.replace(/\n{2,}/g, '\n').replace(/\s{2,}/g, ' '); 80 | this.log(ret); 81 | } 82 | 83 | // 关闭浏览器 84 | await browser.close(); 85 | 86 | return this.return({"content_format": this.get('output'), "content": ret}); 87 | 88 | } 89 | 90 | async json(args, opts, command) { 91 | this.setDefaultOpts(opts); 92 | this.setDefaultCommand(command); 93 | this.format = this.get('format'); 94 | const timeout = this.get('timeout'); 95 | 96 | // URL 97 | const url = this.get('url'); 98 | if (!url) this.echoError("url is required"); 99 | 100 | // 直接通过 fetch 获取内容 101 | const response = await myFetch(url, {}, timeout); 102 | const text = await response.text(); 103 | const content = jsonDecode(text) || text; 104 | return this.return({content}); 105 | } 106 | } 107 | 108 | // 去掉连续空格和空行以节省token 109 | function normalizeWhitespace(html) { 110 | // 将所有连续的空格替换为单个空格 111 | const normalizedSpaces = html.trim().replace(/(\s){2,}/g, '$1'); 112 | return normalizedSpaces; 113 | } 114 | -------------------------------------------------------------------------------- /packages/fxd-app-codegen/fxd-apps.txt: -------------------------------------------------------------------------------- 1 | fxd-app-fetch [method] [options] 2 | 3 | Method - main: 4 | --url 要获取的页面 URL (default: https://ftqq.com) (required) 5 | --format 返回数据格式 (default: text) 6 | --output 输出数据格式 (default: markdown) 7 | --timeout 超时时间 (default: 5000) 8 | --headless 是否启用后台模式 (default: true) 9 | --browser 浏览器类型 (default: chromium) 10 | --user 用户名 (default: default) 11 | --wait_type 等待类型 (default: domcontentloaded) 12 | --delay 延迟时间,单位是毫秒 (default: 0) 13 | 14 | --- 15 | 16 | fxd-app-check-chan [method] [options] 17 | 18 | Method - main: 19 | --url 要打开的页面 URL (required) 20 | --headless 是否使用后台模式 (default: true) 21 | --browser 浏览器类型 (default: chromium) 22 | --selectors 要检测的元素的 CSS 选择器,多个用逗号分隔 (default: body) (required) 23 | --prejs 页面加载完成后执行的自定义 JavaScript 代码 24 | --prejs_args 自定义 JavaScript 代码的参数 25 | --preplay 页面加载完成后执行的自定义 Playwright 代码 26 | --timeout Playwright 操作超时时间,单位毫秒 (default: 60000) 27 | --list 选择器是否返回元素列表 (default: false) 28 | --user 浏览器使用的用户目录 (default: default) 29 | --format 返回的数据格式 (default: text) 30 | --wait_type 等待元素出现的方式 (default: domcontentloaded) 31 | 32 | --- 33 | 34 | fxd-app-gpt-bat [method] [options] 35 | 36 | Method - main: 37 | --char_count 每次处理的字符数 (default: 1000) 38 | --prompt 提示词 (required) 39 | --ai_key AI密钥 40 | --ai_apibase AI接口地址 41 | --ai_model AI模型 42 | --format 返回结果格式 (default: json) 43 | --content 待处理的长文本 (required) 44 | 45 | --- 46 | 47 | fxd-app-keep-live2 [method] [options] 48 | 49 | Method - main: 50 | --user 浏览器使用的用户目录 (default: default) 51 | --timeout 状态检测页面加载超时时间,单位毫秒 (default: 5000) 52 | --headless 是否使用后台模式 (default: true) 53 | --format 返回的数据格式 (default: text) 54 | --browser 浏览器类型 (default: chrome) 55 | 56 | --- 57 | 58 | fxd-app-rss-fetch [method] [options] 59 | 60 | Method - main: 61 | --url RSS Feed URL (default: https://ft07.com/feed) (required) 62 | --only_changed 仅返回新的entries (default: false) 63 | --sendkey Server酱的sendkey,填写后检查到新entries会推送 64 | --timeout 超时时间(毫秒) (default: 10000) 65 | --proxy 代理地址 66 | --format 返回数据格式 (default: json) 67 | 68 | --- 69 | 70 | fxd-app-screenshot [method] [options] 71 | 72 | Method - main: 73 | --url 要截图页面 URL (default: https://ftqq.com) 74 | --width 截图宽度 (default: 1920) 75 | --height 截图高度 (default: 1080) 76 | --scale 设备缩放因子 (default: 1) 77 | --full_page 是否截取整个页面 (default: false) 78 | --timeout 截图超时时间 (default: 30000) 79 | --wait_type 等待页面加载的事件 (default: load) 80 | --save_path 截图保存路径 81 | --user 登录用户名 (default: default) 82 | --browser 浏览器类型 (default: chrome) 83 | --headless 是否无头模式 (default: true) 84 | 85 | --- 86 | 87 | fxd-app-search [method] [options] 88 | 89 | Method - main: 90 | --query 要搜索的关键词,如果指定了sites参数,这里就不要再重复出现网站相关关键词。 (required) 91 | --sites 如果传入,则只搜索匹配站点的内容。多个域名用,分隔 92 | --format 返回数据格式 (default: text) 93 | --timeout 超时时间 (default: 60000) 94 | --headless 是否启用后台模式 (default: true) 95 | --user 用户名 (default: default) 96 | --wait_type 等待类型 (default: domcontentloaded) 97 | --result_limit 结果数量限制 (default: 3) 98 | --result_extend 是否返回额外信息 (default: false) 99 | --result_length 每一条结果的Markdown长度限制 (default: 2000) 100 | 101 | --- 102 | 103 | 104 | fxd-app-weibo-publish [method] [options] 105 | 106 | Method - main: 107 | --content 微博内容 (required) 108 | --headless 是否使用后台模式 (default: true) 109 | --user 浏览器使用的用户目录 (default: default) 110 | --format 返回的数据格式 (default: text) 111 | --timeout Playwright 操作超时时间,单位毫秒 (default: 60000) 112 | --wait_type 等待元素出现的方式 (default: domcontentloaded) 113 | --images 图片地址,用逗号分隔 (default: ) 114 | --self_only 是否仅对自己可见 (default: false) 115 | --browser 浏览器类型 (default: chrome) -------------------------------------------------------------------------------- /packages/fxd-app-screenshot/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-screenshot", 3 | "description": "对传入的url截图", 4 | "version": "1.0.2", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 1, 11 | "args": { 12 | "main": { 13 | "url": { 14 | "name": "url", 15 | "description": "要截图页面 URL", 16 | "type": "string", 17 | "required": false, 18 | "default": "https://ftqq.com", 19 | "example": "https://www.example.com" 20 | }, 21 | "width": { 22 | "name": "width", 23 | "description": "截图宽度", 24 | "type": "number", 25 | "required": false, 26 | "default": 1920, 27 | "example": 1920 28 | }, 29 | "height": { 30 | "name": "height", 31 | "description": "截图高度", 32 | "type": "number", 33 | "required": false, 34 | "default": 1080, 35 | "example": 1080 36 | }, 37 | "scale": { 38 | "name": "scale", 39 | "description": "设备缩放因子", 40 | "type": "number", 41 | "required": false, 42 | "default": 1, 43 | "example": 1 44 | }, 45 | "full_page": { 46 | "name": "full_page", 47 | "description": "是否截取整个页面", 48 | "type": "boolean", 49 | "required": false, 50 | "default": false, 51 | "example": false 52 | }, 53 | "timeout": { 54 | "name": "timeout", 55 | "description": "截图超时时间", 56 | "type": "number", 57 | "required": false, 58 | "default": 30000, 59 | "example": 30000 60 | }, 61 | "wait_type": { 62 | "name": "wait_type", 63 | "description": "等待页面加载的事件", 64 | "type": "string", 65 | "required": false, 66 | "default": "load", 67 | "example": "load" 68 | }, 69 | "save_path": { 70 | "name": "save_path", 71 | "description": "截图保存路径", 72 | "type": "string", 73 | "required": false, 74 | "example": "/tmp/abc.png" 75 | }, 76 | "user": { 77 | "name": "user", 78 | "description": "登录用户名", 79 | "type": "string", 80 | "required": false, 81 | "default": "default", 82 | "example": "admin" 83 | }, 84 | "browser": { 85 | "name": "browser", 86 | "description": "浏览器类型", 87 | "type": "string", 88 | "required": false, 89 | "default": "chrome", 90 | "example": "chrome" 91 | }, 92 | "headless": { 93 | "name": "headless", 94 | "description": "是否无头模式", 95 | "type": "boolean", 96 | "required": false, 97 | "default": true, 98 | "example": true 99 | } 100 | } 101 | }, 102 | "output": { 103 | "main": { 104 | "success": { 105 | "action": { 106 | "name": "action", 107 | "type": "string", 108 | "description": "动作类型", 109 | "example": "screenshot" 110 | }, 111 | "message": { 112 | "name": "message", 113 | "type": "string", 114 | "description": "操作结果消息", 115 | "example": "done" 116 | }, 117 | "output": { 118 | "name": "output", 119 | "type": "string", 120 | "description": "截图保存路径", 121 | "example": "/path/to/screenshot.png" 122 | } 123 | }, 124 | "fail": { 125 | "action": { 126 | "name": "action", 127 | "type": "string", 128 | "description": "动作类型", 129 | "example": "screenshot" 130 | }, 131 | "message": { 132 | "name": "message", 133 | "type": "string", 134 | "description": "错误信息", 135 | "example": "error" 136 | }, 137 | "output": { 138 | "name": "output", 139 | "type": "string", 140 | "description": "错误详细信息", 141 | "example": "screenshot failed" 142 | } 143 | } 144 | } 145 | } 146 | }, 147 | "dependencies": { 148 | "fxd-app-browser": "^1.0.8" 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /packages/fxd-app-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-search", 3 | "description": "根据传入的query搜索网页,返回搜索结果。支持用sites指定网站搜索", 4 | "version": "1.0.8", 5 | "main": "index.js", 6 | "license": "MIT", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 1, 11 | "args": { 12 | "main": { 13 | "query": { 14 | "name": "query", 15 | "description": "要搜索的关键词,如果指定了sites参数,这里就不要再重复出现网站相关关键词。", 16 | "type": "string", 17 | "required": true 18 | }, 19 | "sites": { 20 | "name": "sites", 21 | "description": "如果传入,则只搜索匹配站点的内容。多个域名用,分隔", 22 | "type": "string", 23 | "required": false, 24 | "example": "ftqq.com" 25 | }, 26 | "format": { 27 | "name": "format", 28 | "description": "返回数据格式", 29 | "type": "string", 30 | "required": false, 31 | "default": "text", 32 | "example": "json" 33 | }, 34 | "timeout": { 35 | "name": "timeout", 36 | "description": "超时时间", 37 | "type": "number", 38 | "required": false, 39 | "default": 60000, 40 | "example": 5000 41 | }, 42 | "headless": { 43 | "name": "headless", 44 | "description": "是否启用后台模式", 45 | "type": "boolean", 46 | "required": false, 47 | "default": true, 48 | "example": true 49 | }, 50 | "user": { 51 | "name": "user", 52 | "description": "用户名", 53 | "type": "string", 54 | "required": false, 55 | "default": "default", 56 | "example": "username" 57 | }, 58 | "wait_type": { 59 | "name": "wait_type", 60 | "description": "等待类型", 61 | "type": "string", 62 | "required": false, 63 | "default": "domcontentloaded", 64 | "example": "domcontentloaded", 65 | "enum": [ 66 | "load", 67 | "domcontentloaded", 68 | "networkidle" 69 | ] 70 | }, 71 | "result_limit": { 72 | "name": "result_limit", 73 | "description": "结果数量限制", 74 | "type": "number", 75 | "required": false, 76 | "default": 3, 77 | "example": 10 78 | }, 79 | "result_extend": { 80 | "name": "result_extend", 81 | "description": "是否返回额外信息", 82 | "type": "boolean", 83 | "required": false, 84 | "default": false, 85 | "example": true 86 | }, 87 | "result_length": { 88 | "name": "result_length", 89 | "description": "每一条结果的Markdown长度限制", 90 | "type": "number", 91 | "required": false, 92 | "default": 2000, 93 | "example": 1000 94 | } 95 | } 96 | }, 97 | "output": { 98 | "main": { 99 | "success": { 100 | "results": { 101 | "name": "results", 102 | "type": "array", 103 | "description": "搜索结果数组", 104 | "items": { 105 | "type": "object", 106 | "properties": { 107 | "title": { 108 | "name": "title", 109 | "type": "string", 110 | "description": "结果标题" 111 | }, 112 | "link": { 113 | "name": "link", 114 | "type": "string", 115 | "description": "结果链接" 116 | }, 117 | "snippet": { 118 | "name": "snippet", 119 | "type": "string", 120 | "description": "结果摘要" 121 | }, 122 | "markdown": { 123 | "name": "markdown", 124 | "type": "string", 125 | "description": "结果Markdown内容,只有在result_extend为true时返回" 126 | } 127 | } 128 | } 129 | } 130 | }, 131 | "fail": { 132 | "error": { 133 | "name": "error", 134 | "type": "string", 135 | "description": "错误信息", 136 | "example": "搜索过程中发生错误" 137 | } 138 | } 139 | } 140 | } 141 | }, 142 | "dependencies": { 143 | "@mozilla/readability": "^0.5.0", 144 | "jsdom": "^24.0.0", 145 | "turndown": "^7.1.2" 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /packages/fxd-app-search/index.js: -------------------------------------------------------------------------------- 1 | import FxdBrowser from 'fxd-app-browser'; 2 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 3 | import { JSDOM } from 'jsdom'; 4 | import { Readability } from '@mozilla/readability'; 5 | import TurndownService from 'turndown'; 6 | const turndownService = new TurndownService(); 7 | 8 | 9 | export default class FxdDemo extends FxdBrowser { 10 | constructor() { 11 | super(); 12 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 13 | // ... 14 | } 15 | 16 | async main(args, opts, command) { 17 | this.setDefaultOpts(opts); 18 | this.setDefaultCommand(command); 19 | this.format = this.get('format'); 20 | const query = this.get('query'); 21 | const sites = this.get('sites')?this.get('sites').split(','):[]; 22 | const headless = this.get('headless'); 23 | const { page, browser } = await this.getBrowserAndMore(this.getUserDirFullPath(this.get('user')), { headless }); 24 | page.setDefaultTimeout(this.get('timeout')); // 设置超时 25 | 26 | const url = 'https://www.google.com/search?q=' + encodeURIComponent(sites ? sites.map( site => `site:${site}` ).join(' ') + ' filetype:md OR filetype:html ' + query : ' filetype:md OR filetype:html ' + query); 27 | await page.goto(url);// 打开URL 28 | await page.waitForLoadState( this.get('wait_type')); 29 | 30 | let results_all = await page.evaluate(() => { 31 | let data = []; 32 | let elements = document.querySelectorAll('.g'); 33 | for (var element of elements) { 34 | let title = element.querySelector('a').innerText?.trim(); 35 | let link = element.querySelector('a').href; 36 | let snippet = element.innerText.trim().split('\n').pop(); 37 | data.push({title, link, snippet}); 38 | } 39 | return data; 40 | }); 41 | // 等待1秒 42 | await page.waitForTimeout(1000); 43 | await browser.close(); 44 | 45 | let results = results_all.slice(0,this.get("result_limit")); 46 | // 去掉 link 重复的 47 | results = results.filter((item, index, self) => 48 | index === self.findIndex((t) => ( 49 | t.link === item.link.trim() 50 | )) 51 | ); 52 | this.log(results); 53 | 54 | if( !this.get("result_extend") ) return this.return({results}); 55 | 56 | let extended_results = []; 57 | for (let result of results) { 58 | let markdown = await this.fetch(result.link, this.get('result_length')); 59 | if (markdown) { 60 | result.markdown = markdown; 61 | extended_results.push(result); 62 | } 63 | } 64 | this.log(extended_results); 65 | return this.return({results:extended_results}); 66 | 67 | } 68 | 69 | async fetch(url, length = 3000, timeout = 20*1000) 70 | { 71 | // 首先验证 url 是否是一个合法的 url 72 | if( !url.match(/^https?:\/\//) ) return ''; 73 | 74 | try { 75 | const { page, browser } = await this.getBrowserAndMore(this.getUserDirFullPath(this.get('user')), { headless: this.get('headless') }); 76 | page.setDefaultTimeout(timeout); // 设置超时 77 | 78 | // page 超时后关掉浏览器 79 | page.on('pageerror', async (err) => { 80 | await browser.close(); 81 | this.log(err); 82 | return ''; 83 | }); 84 | 85 | await page.goto(url);// 打开URL 86 | await page.waitForLoadState( this.get('wait_type')); 87 | const html = await page.content(); 88 | await browser.close(); 89 | // 使用 Readability 解析 html 90 | const dom = new JSDOM(html, { url } ); 91 | const reader = new Readability(dom.window.document); 92 | const article = reader.parse(); 93 | let markdown = false; 94 | 95 | if (article && article.content) { 96 | markdown = turndownService.turndown(article.content); 97 | } else { 98 | if (dom.window.document) 99 | { 100 | markdown = turndownService.turndown(dom.window.document); 101 | } 102 | } 103 | 104 | return markdown ? ( length ? markdown.substring(0, length) : markdown) : ''; 105 | } catch (error) { 106 | return ''; 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /packages/fxd-app-codegen/fxd-intro.txt: -------------------------------------------------------------------------------- 1 | # 基本结构 2 | FXD App是一个标准的NPM Package,在`package.json`中添加额外字段描述输入输出参数和格式。主要内容包括: 3 | 4 | 1. `meta`属性包含四部分: 5 | - `for`: 标识是否为fxd应用。 6 | - `author_uid`: 用于识别开发者。 7 | - `args`: 描述输入参数。 8 | - `output`: 描述输出参数。 9 | 10 | # `args`属性 11 | - 以方法作为一级分组,每个分组包含具体字段。 12 | - 字段描述包括: 13 | - `name`: 字段名。 14 | - `cn_name`: 中文名称。 15 | - `description`: 字段详细说明。 16 | - `type`: 类型 (`string`, `boolean`, `number`)。 17 | - `enum`: 枚举值,选填。 18 | - `required`: 是否必填。 19 | - `default`: 默认值。 20 | - `example`: 示例值。 21 | 22 | # `output`属性 23 | - 和`args`类似,采用方法作为一级分组。 24 | - 包含成功 (`success`) 和失败 (`fail`) 两种情况。 25 | 26 | # 典型`package.json`示例 27 | ```json 28 | { 29 | "name": "fxd-app-fetch", 30 | "displayName": "Fxd网页内容获取", 31 | "description": "根据输入的url抓取网页内容,并进行优化和格式转换", 32 | "version": "1.0.8", 33 | "main": "index.js", 34 | "license": "SEE LICENSE IN LICENSE.txt", 35 | "type": "module", 36 | "meta": { 37 | "for": "fxd", 38 | "author_uid": 1, 39 | "args": { 40 | "main": { 41 | "url": { 42 | "name": "url", 43 | "description": "要获取的页面 URL", 44 | "type": "string", 45 | "required": true, 46 | "default": "https://ftqq.com", 47 | "example": "https://www.example.com" 48 | } 49 | }, 50 | "json": { 51 | "url": { 52 | "name": "url", 53 | "description": "要获取的页面 URL", 54 | "type": "string", 55 | "required": true, 56 | "default": "https://ftqq.com", 57 | "example": "https://www.example.com" 58 | } 59 | } 60 | }, 61 | "output": { 62 | "main": { 63 | "success": { 64 | "content_format": { 65 | "name": "content_format", 66 | "type": "string", 67 | "description": "返回数据格式,包括raw/markdown/html/text", 68 | "example": "html" 69 | } 70 | }, 71 | "fail": { 72 | "error": { 73 | "name": "error", 74 | "type": "string", 75 | "description": "错误信息", 76 | "example": "获取页面内容失败" 77 | } 78 | } 79 | }, 80 | "json": { 81 | "success": { 82 | "content": { 83 | "name": "content", 84 | "type": "string", 85 | "description": "返回的JSON数据", 86 | "example": "https://www.example.com" 87 | } 88 | }, 89 | "fail": { 90 | "error": { 91 | "name": "error", 92 | "type": "string", 93 | "description": "错误信息", 94 | "example": "获取页面内容失败" 95 | } 96 | } 97 | } 98 | } 99 | } 100 | } 101 | ``` 102 | 103 | # 入口 104 | FXD自动加载模块的`default export`,需对外暴露`run`方法,接受以下参数: 105 | ```javascript 106 | async run(args, opts, command, cli_path) 107 | ``` 108 | 109 | 典型的FXD应用示例: 110 | ```javascript 111 | export default class FxdSimple { 112 | async main(args, opts, command, cli_path) { 113 | // 处理业务逻辑 114 | } 115 | } 116 | ``` 117 | 118 | # extend 已有应用来实现功能的例子 119 | 120 | ```javascript 121 | import FxdCheckChan from 'fxd-app-check-chan'; 122 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 123 | 124 | export default class FxdDouyinCoutn extends FxdCheckChan { 125 | constructor() { 126 | super(); 127 | const oldArgsSettings = this.sdk.args; 128 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 129 | this.sdk.args = this.mergeProps(oldArgsSettings,[ 130 | 'watch', 131 | 'main|check|watch.-selectors,prejs,prejs_args,preplay,list' 132 | ]); 133 | } 134 | 135 | async main(args, opts, command) { 136 | opts['selectors'] = `[data-e2e='user-tab-count']`; 137 | return await this.watch(args, opts, 'watch'); 138 | } 139 | } 140 | ``` 141 | 142 | # 混搭组合已有应用实现功能的例子 143 | 144 | ```javascript 145 | import FxdWeiboPublish from 'fxd-app-weibo-publish'; // 首先 import进来 146 | 147 | async main(args, opts, command) { 148 | this.setDeaultOpts(opts); 149 | this.setDeaultCommand(command); 150 | this.format = this.get('format'); 151 | // ... 152 | // 这里要发布微博了 153 | const weibo_publish = new FxdWeiboPublish();// 创建对象 154 | result = await weibo_publish.publish( // 调用 publish 方法 155 | null, // 第一个参数留空,第二个参数参入调用参数 156 | { 157 | content: 微博内容, 158 | headless: String('false'), // ⚠️ 特别注意这里的参数需要String类型,否则不生效 159 | user: this.get('user'), 160 | }, 161 | 'publish' // 第三个参数固定为被调用的方法名,也就是 publish 162 | ); 163 | } 164 | ``` -------------------------------------------------------------------------------- /packages/fxd-app-memo-forward/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-memo-forward", 3 | "description": "转发memo到微博", 4 | "version": "1.0.9", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "meta": { 9 | "for": "fxd", 10 | "author_uid": 1, 11 | "args": { 12 | "main": { 13 | "api_base": { 14 | "name": "api_base", 15 | "description": "memos 实例的url", 16 | "type": "string", 17 | "required": true, 18 | "example": "https://memo.ft07.com" 19 | }, 20 | "access_token": { 21 | "name": "access_token", 22 | "description": "访问令牌", 23 | "type": "string", 24 | "required": true, 25 | "example": "eyJhbGciOiJ..." 26 | }, 27 | "tags": { 28 | "name": "tags", 29 | "description": "同步标签,多个之间用逗号,隔开,不指定则全部同步", 30 | "type": "string", 31 | "required": false, 32 | "example": "工作" 33 | }, 34 | "to": { 35 | "name": "to", 36 | "description": "发送到什么平台", 37 | "type": "string", 38 | "required": false, 39 | "default": "weibo", 40 | "example": "weibo", 41 | "enum": [ 42 | "weibo", 43 | "subdeer", 44 | "x" 45 | ] 46 | }, 47 | "subdeer_token": { 48 | "name": "subdeer_token", 49 | "description": "subdeer token", 50 | "type": "string", 51 | "required": false, 52 | "example": "eyJhbGciOiJ..." 53 | }, 54 | "subdeer_channel_id": { 55 | "name": "subdeer_channel_id", 56 | "description": "subdeer channel id", 57 | "type": "number", 58 | "required": false, 59 | "example": 1 60 | }, 61 | "days": { 62 | "name": "days", 63 | "cn_name": "天数", 64 | "type": "number", 65 | "description": "最近多少天的内容", 66 | "default": 1 67 | }, 68 | "extra_images": { 69 | "name": "extra_images", 70 | "description": "附加图片,多个之间用逗号,隔开,不指定则不附加图片", 71 | "type": "string", 72 | "required": false, 73 | "example": "https://www.baidu.com/img/bd_logo1.png" 74 | }, 75 | "append_text": { 76 | "name": "append_text", 77 | "description": "微博等社交媒体发布是的追加文案,会在同步内容之后自动加上", 78 | "type": "string", 79 | "required": false, 80 | "example": "更多内容可查看 https://ft07.com" 81 | }, 82 | "self_only": { 83 | "name": "self_only", 84 | "cn_name": "仅自己可见", 85 | "description": "是否仅对自己可见", 86 | "type": "boolean", 87 | "default": false, 88 | "example": "true" 89 | }, 90 | "user": { 91 | "name": "user", 92 | "description": "浏览器使用的用户目录", 93 | "type": "string", 94 | "default": "default", 95 | "example": "admin" 96 | }, 97 | "format": { 98 | "name": "format", 99 | "description": "返回的数据格式", 100 | "type": "string", 101 | "default": "text", 102 | "example": "json", 103 | "enum": [ 104 | "json", 105 | "text" 106 | ] 107 | }, 108 | "headless": { 109 | "name": "headless", 110 | "cn_name": "后台模式", 111 | "description": "是否使用后台模式", 112 | "type": "boolean", 113 | "default": true, 114 | "example": "true" 115 | }, 116 | "browser": { 117 | "name": "browser", 118 | "description": "浏览器类型", 119 | "type": "string", 120 | "default": "chrome", 121 | "example": "chrome", 122 | "enum": [ 123 | "chrome", 124 | "firefox", 125 | "webkit" 126 | ] 127 | } 128 | } 129 | }, 130 | "output": { 131 | "main": { 132 | "success": { 133 | "result": { 134 | "name": "result", 135 | "description": "返回结果" 136 | } 137 | } 138 | }, 139 | "fail": { 140 | "error": { 141 | "name": "error", 142 | "type": "string", 143 | "description": "错误信息", 144 | "example": "搜索过程中发生错误" 145 | } 146 | } 147 | } 148 | }, 149 | "dependencies": { 150 | "dayjs": "^1.11.10", 151 | "fxd-app-core": "^1.0.47", 152 | "fxd-app-weibo-publish": "^1.0.12", 153 | "fxd-app-x-publish": "^1.0.0", 154 | "fxd-sdk": "^1.0.66" 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-cli/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-sdk/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-browser/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-codegen/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-core/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-demo/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-fetch/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-gpt-bat/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-check-chan/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-douyin-count/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-flow-runner/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-keep-live2/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-memo-forward/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-rss-fetch/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-screenshot/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-translate/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-weibo-live/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-weibo-publish/LICENSE.txt: -------------------------------------------------------------------------------- 1 | # PolyForm Noncommercial License 1.0.0 2 | 3 | 4 | 5 | ## Acceptance 6 | 7 | In order to get any license under these terms, you must agree 8 | to them as both strict obligations and conditions to all 9 | your licenses. 10 | 11 | ## Copyright License 12 | 13 | The licensor grants you a copyright license for the 14 | software to do everything you might do with the software 15 | that would otherwise infringe the licensor's copyright 16 | in it for any permitted purpose. However, you may 17 | only distribute the software according to [Distribution 18 | License](#distribution-license) and make changes or new works 19 | based on the software according to [Changes and New Works 20 | License](#changes-and-new-works-license). 21 | 22 | ## Distribution License 23 | 24 | The licensor grants you an additional copyright license 25 | to distribute copies of the software. Your license 26 | to distribute covers distributing the software with 27 | changes and new works permitted by [Changes and New Works 28 | License](#changes-and-new-works-license). 29 | 30 | ## Notices 31 | 32 | You must ensure that anyone who gets a copy of any part of 33 | the software from you also gets a copy of these terms or the 34 | URL for them above, as well as copies of any plain-text lines 35 | beginning with `Required Notice:` that the licensor provided 36 | with the software. For example: 37 | 38 | > Required Notice: Copyright Fangtangjun, Inc. (https://ft07.com) 39 | 40 | ## Changes and New Works License 41 | 42 | The licensor grants you an additional copyright license to 43 | make changes and new works based on the software for any 44 | permitted purpose. 45 | 46 | ## Patent License 47 | 48 | The licensor grants you a patent license for the software that 49 | covers patent claims the licensor can license, or becomes able 50 | to license, that you would infringe by using the software. 51 | 52 | ## Noncommercial Purposes 53 | 54 | Any noncommercial purpose is a permitted purpose. 55 | 56 | ## Personal Uses 57 | 58 | Personal use for research, experiment, and testing for 59 | the benefit of public knowledge, personal study, private 60 | entertainment, hobby projects, amateur pursuits, or religious 61 | observance, without any anticipated commercial application, 62 | is use for a permitted purpose. 63 | 64 | ## Noncommercial Organizations 65 | 66 | Use by any charitable organization, educational institution, 67 | public research organization, public safety or health 68 | organization, environmental protection organization, 69 | or government institution is use for a permitted purpose 70 | regardless of the source of funding or obligations resulting 71 | from the funding. 72 | 73 | ## Fair Use 74 | 75 | You may have "fair use" rights for the software under the 76 | law. These terms do not limit them. 77 | 78 | ## No Other Rights 79 | 80 | These terms do not allow you to sublicense or transfer any of 81 | your licenses to anyone else, or prevent the licensor from 82 | granting licenses to anyone else. These terms do not imply 83 | any other licenses. 84 | 85 | ## Patent Defense 86 | 87 | If you make any written claim that the software infringes or 88 | contributes to infringement of any patent, your patent license 89 | for the software granted under these terms ends immediately. If 90 | your company makes such a claim, your patent license ends 91 | immediately for work on behalf of your company. 92 | 93 | ## Violations 94 | 95 | The first time you are notified in writing that you have 96 | violated any of these terms, or done anything with the software 97 | not covered by your licenses, your licenses can nonetheless 98 | continue if you come into full compliance with these terms, 99 | and take practical steps to correct past violations, within 100 | 32 days of receiving notice. Otherwise, all your licenses 101 | end immediately. 102 | 103 | ## No Liability 104 | 105 | ***As far as the law allows, the software comes as is, without 106 | any warranty or condition, and the licensor will not be liable 107 | to you for any damages arising out of these terms or the use 108 | or nature of the software, under any kind of legal claim.*** 109 | 110 | ## Definitions 111 | 112 | The **licensor** is the individual or entity offering these 113 | terms, and the **software** is the software the licensor makes 114 | available under these terms. 115 | 116 | **You** refers to the individual or entity agreeing to these 117 | terms. 118 | 119 | **Your company** is any legal entity, sole proprietorship, 120 | or other kind of organization that you work for, plus all 121 | organizations that have control over, are under the control of, 122 | or are under common control with that organization. **Control** 123 | means ownership of substantially all the assets of an entity, 124 | or the power to direct its management and policies by vote, 125 | contract, or otherwise. Control can be direct or indirect. 126 | 127 | **Your licenses** are all the licenses granted to you for the 128 | software under these terms. 129 | 130 | **Use** means anything you do with the software requiring one 131 | of your licenses. 132 | -------------------------------------------------------------------------------- /packages/fxd-app-fetch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-fetch", 3 | "displayName": "Fxd网页内容获取", 4 | "description": "根据输入的url抓取网页内容,并进行优化和格式转换", 5 | "version": "1.0.11", 6 | "main": "index.js", 7 | "license": "SEE LICENSE IN LICENSE.txt", 8 | "type": "module", 9 | "meta": { 10 | "args": { 11 | "main": { 12 | "url": { 13 | "name": "url", 14 | "description": "要获取的页面 URL", 15 | "type": "string", 16 | "required": true, 17 | "default": "https://ftqq.com", 18 | "example": "https://www.example.com" 19 | }, 20 | "format": { 21 | "name": "format", 22 | "description": "返回数据格式", 23 | "type": "string", 24 | "required": false, 25 | "default": "text", 26 | "example": "json" 27 | }, 28 | "output": { 29 | "name": "output", 30 | "description": "输出数据格式", 31 | "type": "string", 32 | "required": false, 33 | "default": "markdown", 34 | "example": "html", 35 | "enum": [ 36 | "markdown", 37 | "html", 38 | "text", 39 | "raw" 40 | ] 41 | }, 42 | "timeout": { 43 | "name": "timeout", 44 | "description": "超时时间", 45 | "type": "number", 46 | "required": false, 47 | "default": 5000, 48 | "example": 5000 49 | }, 50 | "headless": { 51 | "name": "headless", 52 | "description": "是否启用后台模式", 53 | "type": "boolean", 54 | "required": false, 55 | "default": true, 56 | "example": true 57 | }, 58 | "browser":{ 59 | "name": "browser", 60 | "description": "浏览器类型", 61 | "type": "string", 62 | "required": false, 63 | "default": "chromium", 64 | "example": "chromium", 65 | "enum": ["chromium","firefox","webkit"] 66 | }, 67 | "user": { 68 | "name": "user", 69 | "description": "用户名", 70 | "type": "string", 71 | "required": false, 72 | "default": "default", 73 | "example": "username" 74 | }, 75 | "wait_type": { 76 | "name": "wait_type", 77 | "description": "等待类型", 78 | "type": "string", 79 | "required": false, 80 | "default": "domcontentloaded", 81 | "example": "domcontentloaded", 82 | "enum": [ 83 | "load", 84 | "domcontentloaded", 85 | "networkidle" 86 | ] 87 | }, 88 | "delay": 89 | { 90 | "name": "delay", 91 | "description": "延迟时间,单位是毫秒", 92 | "type": "number", 93 | "required": false, 94 | "default": 0, 95 | "example": 1000 96 | } 97 | }, 98 | "json": { 99 | "url": { 100 | "name": "url", 101 | "description": "要获取的页面 URL", 102 | "type": "string", 103 | "required": true, 104 | "default": "https://ftqq.com", 105 | "example": "https://www.example.com" 106 | }, 107 | "format": { 108 | "name": "format", 109 | "description": "返回数据格式", 110 | "type": "string", 111 | "required": false, 112 | "default": "text", 113 | "example": "json" 114 | }, 115 | "timeout": { 116 | "name": "timeout", 117 | "description": "超时时间", 118 | "type": "number", 119 | "required": false, 120 | "default": 5000, 121 | "example": 5000 122 | } 123 | } 124 | }, 125 | "output": 126 | { 127 | "main": 128 | { 129 | "success": 130 | { 131 | "content_format": 132 | { 133 | "name": "content_format", 134 | "type": "string", 135 | "description": "返回数据格式,包括raw/markdown/html/text", 136 | "example": "html" 137 | }, 138 | "content": 139 | { 140 | "name": "content", 141 | "type": "string", 142 | "description": "返回数据内容", 143 | "example": "https://www.example.com" 144 | } 145 | }, 146 | "fail": 147 | { 148 | "error": 149 | { 150 | "name": "error", 151 | "type": "string", 152 | "description": "错误信息", 153 | "example": "获取页面内容失败" 154 | } 155 | } 156 | }, 157 | "json": 158 | { 159 | "success": 160 | { 161 | "content": 162 | { 163 | "name": "content", 164 | "type": "string", 165 | "description": "返回的JSON数据", 166 | "example": "https://www.example.com" 167 | } 168 | }, 169 | "fail": 170 | { 171 | "error": 172 | { 173 | "name": "error", 174 | "type": "string", 175 | "description": "错误信息", 176 | "example": "获取页面内容失败" 177 | } 178 | } 179 | } 180 | } 181 | }, 182 | "dependencies": { 183 | "@mozilla/readability": "^0.4.4", 184 | "fxd-app-browser": "^1.0.8", 185 | "jsdom": "^22.1.0", 186 | "sanitize-html": "^2.11.0", 187 | "turndown": "^7.1.2" 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /packages/fxd-app-keep-live2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-keep-live2", 3 | "version": "1.0.3", 4 | "main": "index.js", 5 | "license": "SEE LICENSE IN LICENSE.txt", 6 | "type": "module", 7 | "meta": { 8 | "args": { 9 | "main|auth|check|refresh": { 10 | "user": { 11 | "name": "user", 12 | "cn_name": "浏览器用户", 13 | "description": "浏览器使用的用户目录", 14 | "type": "string", 15 | "default": "default", 16 | "example": "admin" 17 | }, 18 | "timeout": { 19 | "name": "timeout", 20 | "cn_name": "加载超时时间", 21 | "description": "状态检测页面加载超时时间,单位毫秒", 22 | "type": "number", 23 | "default": 5000, 24 | "example": 8000 25 | }, 26 | "headless": { 27 | "name": "headless", 28 | "cn_name": "后台模式", 29 | "description": "是否使用后台模式", 30 | "type": "boolean", 31 | "default": true, 32 | "example": false 33 | }, 34 | "format": { 35 | "name": "format", 36 | "cn_name": "返回格式", 37 | "description": "返回的数据格式", 38 | "type": "string", 39 | "default": "text", 40 | "example": "json", 41 | "enum": [ 42 | "json", 43 | "text" 44 | ] 45 | }, 46 | "browser": { 47 | "name": "browser", 48 | "description": "浏览器类型", 49 | "type": "string", 50 | "default": "chrome", 51 | "example": "chrome", 52 | "enum": [ 53 | "chrome", 54 | "firefox", 55 | "webkit" 56 | ] 57 | } 58 | }, 59 | "auth": { 60 | "auth_url": { 61 | "name": "auth_url", 62 | "cn_name": "登录页面URL", 63 | "description": "登录页面URL,用于前台打开给用户手动登录", 64 | "type": "string", 65 | "example": "https://passport.weibo.cn/signin/login" 66 | } 67 | }, 68 | "check": { 69 | "check_url": { 70 | "name": "check_url", 71 | "cn_name": "状态检测页面URL", 72 | "description": "状态检测页面URL,设置后会检测页面状态是否过期", 73 | "type": "string", 74 | "example": "https://m.weibo.cn" 75 | }, 76 | "check_selector": { 77 | "name": "check_selector", 78 | "cn_name": "待检测元素selector", 79 | "description": "状态检测页面待检测元素的selector", 80 | "type": "string", 81 | "default": "body", 82 | "example": "div.lite-iconf-msg" 83 | }, 84 | "check_text": { 85 | "name": "check_text", 86 | "cn_name": "待检测元素包含文本", 87 | "description": "状态检测页面待检测元素应该包含的文本,如果为空,则只判断元素是否存在", 88 | "type": "string", 89 | "example": "OK" 90 | } 91 | }, 92 | "refresh": { 93 | "refresh_url": { 94 | "name": "refresh_url", 95 | "cn_name": "刷新页面URL", 96 | "description": "刷新页面URL,设置后每次运行命令时会刷新一次,用来维护状态", 97 | "type": "string", 98 | "example": "https://m.weibo.cn" 99 | } 100 | } 101 | }, 102 | "output": { 103 | "main|auth|check|refresh": { 104 | "success": { 105 | "action": { 106 | "name": "action", 107 | "type": "string", 108 | "description": "执行的动作类型", 109 | "example": "auth" 110 | }, 111 | "message": { 112 | "name": "message", 113 | "type": "string", 114 | "description": "执行结果消息", 115 | "example": "done" 116 | }, 117 | "output": { 118 | "name": "output", 119 | "type": "string", 120 | "description": "额外的输出信息", 121 | "example": "authed manually" 122 | }, 123 | "url": { 124 | "name": "url", 125 | "type": "string", 126 | "description": "访问的URL", 127 | "example": "https://m.weibo.cn", 128 | "required": false 129 | }, 130 | "selector": { 131 | "name": "selector", 132 | "type": "string", 133 | "description": "使用的选择器", 134 | "example": "div.lite-iconf-msg", 135 | "required": false 136 | }, 137 | "text": { 138 | "name": "text", 139 | "type": "string", 140 | "description": "选择器中应包含的文本", 141 | "example": "OK", 142 | "required": false 143 | }, 144 | "count": { 145 | "name": "count", 146 | "type": "number", 147 | "description": "找到的选择器数量", 148 | "example": 1, 149 | "required": false 150 | }, 151 | "selectedText": { 152 | "name": "selectedText", 153 | "type": "string", 154 | "description": "选择器中的文本内容", 155 | "example": "Your content here", 156 | "required": false 157 | }, 158 | "ret": { 159 | "name": "ret", 160 | "type": "boolean", 161 | "description": "检查结果", 162 | "example": true, 163 | "required": false 164 | } 165 | }, 166 | "fail": { 167 | "error": { 168 | "name": "error", 169 | "type": "string", 170 | "description": "错误信息", 171 | "example": "页面加载失败" 172 | } 173 | } 174 | } 175 | } 176 | }, 177 | "dependencies": { 178 | "chalk": "^5.3.0", 179 | "fxd-app-browser": "^1.0.8", 180 | "fxd-sdk": "^1.0.59" 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What is Fxd 2 | 3 | [ [中文](./README.zh-cn.md) | [English](./README.md) ] 4 | 5 | ![](images/20240414114221.png) 6 | 7 | Fxd stands for Flow eXtension Define, a specification designed for extending workflows, especially AI and automation workflows. 8 | 9 | [FXD Official Manual](https://ft07.com/fxd/) 10 | 11 | For example, if you need to monitor the latest articles from an RSS feed, translate them into Chinese, add images, and post them to your X platform, this task is not difficult for AI. However, due to the many steps involved, few tools can automate the entire process. 12 | 13 | Using Fxd, we would first encapsulate the following Fxd Apps: 14 | 15 | - RSS Monitoring App 16 | - GPTChat App 17 | - DALL-E App 18 | - X Posting App 19 | 20 | Each of these is an independent NPM package, and each app can be called via the command line using Fxd-Cli. This way, we only need to use Shell or other scripts to combine these Fxd Apps, flexibly achieving various functions. For example, if you want to post to Weibo instead of X, you only need to replace the last app. 21 | 22 | An example of posting to Weibo: 23 | 24 | ```bash 25 | fxd weiboLive auth # Initial posting requires logging in through the browser, no need to manually log in each time 26 | fxd weiboPublish --content="Hello there" --self_only="true" --format="json" --headless="false" 27 | ``` 28 | 29 | It can also be used directly in clients that comply with the FXD specification, such as the FlowDeer client. 30 | 31 | ![FlowDeer](images/image.png) 32 | 33 | # Development Environment 34 | 35 | ## Command Line Debugging 36 | 37 | This repo uses Yarn workspaces to manage multiple packages. Run in the root directory: 38 | 39 | ```bash 40 | yarn install 41 | ``` 42 |
43 | Solution for Windows error "cannot load file **Roaming\npm\yarn.ps1" 44 | This error is caused by policy restrictions. Please follow these steps to resolve it: 45 | 46 | 1. Search for PowerShell, right-click to run as administrator 47 | 1. Enter `Set-ExecutionPolicy RemoteSigned` and choose Y 48 | 1. Close PowerShell and rerun the yarn command 49 |
50 | 51 | Then navigate to the command line directory 52 | ```bash 53 | cd packages/fxd-cli 54 | ``` 55 | 56 | On Unix-like systems, use `./fxd` in the directory as the command line tool: 57 | 58 | ```bash 59 | # View help 60 | ./fxd core help 61 | 62 | # View Demo app help 63 | ./fxd demo help 64 | ``` 65 | On Windows, manually add the node command prefix 66 | 67 | ```bash 68 | # View help 69 | node fxd core help 70 | 71 | # View Demo app help 72 | node fxd demo help 73 | ``` 74 | 75 | ## FXD App Code Generation 76 | 77 | You can create a copy of the `fxd-app-demo` for modification and debugging. Once completed, publish it using `npm publish fxd-app-your-app` to make it available on all software supporting the FXD specification. 78 | 79 | Starting from May 21, 2024, code generation for initializing an FXD app is introduced. The usage is as follows: 80 | 81 | Configure environment variables: 82 | 83 | - `DEFAULT_AI_CHAT_KEY`: openai/api2d key 84 | - `DEFAULT_AI_CHAT_BASEURL`: `https://api.openai.com` or `https://oa.api2d.net` 85 | - `DEFAULT_AI_CHAT_MODEL`: model, default to gpt-4o 86 | 87 | In the `fxd-cli` directory, run: 88 | 89 | ```bash 90 | ./fxd codegen 91 | ``` 92 | 93 | https://github.com/easychen/fxd/assets/1294760/c6f995f8-b5ae-4db4-9265-8d6ebb4b781c 94 | 95 | Follow the prompts to complete the process. 96 | 97 | ## Debugging in FlowDeer 98 | 99 | By default, FlowDeer installs packages from the NPM site directly; however, we may need to debug before publishing. Here is a solution: 100 | 101 | Since FlowDeer prioritizes local directories, we can run `npm install ` in the corresponding FlowDeer directory via the command line for local installation. 102 | 103 | Specifically, for Mac systems: 104 | 105 | ```bash 106 | cd /Applications/FlowDeer.app/Contents/Resources/app.asar.unpacked/src/local-api 107 | npm install path/to/your/package 108 | ``` 109 | 110 | If you haven't installed FlowDeer in the Applications directory, please adjust the `/Applications/FlowDeer.app` part of the path accordingly. 111 | 112 | For Windows systems: 113 | 114 | ```bash 115 | cd /resources/app.asar.unpacked/src/local-api 116 | npm install path/to/your/package 117 | ``` 118 | 119 | After installation, simply add the package name in the FlowDeer interface. 120 | 121 | # License 122 | 123 | The SDK, command line tools, and core packages of FXD are by default licensed under the PolyForm Noncommercial License. If the packages directory contains different licenses, the latter prevails. 124 | 125 | Any code contributed to this project is considered authorized for commercial use by the project authors and their affiliated companies and distributed under this project's license (PolyForm Noncommercial License). 126 | 127 | The PolyForm Noncommercial License allows you to modify this project and distribute it for any non-commercial purposes. During distribution, you must ensure that the recipients receive a copy of the license and are aware that the copyright belongs to "Sugar Balloons". For more detailed instructions, please read the license document. 128 | 129 | Applications based on FXD (similar to fxd-app-demo) can be licensed as you see fit, but distribution must still comply with the agreement. For example: 130 | 131 | 1. If you create fxd-app-demo and license it under the MIT license, you can handle the fxd-app-demo code as you wish. 132 | 2. If you guide users to install and use fxd-app-demo via fxd-cli, you do not need to comply with this project's license. 133 | 3. If you bundle fxd-cli and fxd-sdk code as a product for distribution, then you must comply with this project's license. -------------------------------------------------------------------------------- /packages/fxd-app-weibo-publish/index.js: -------------------------------------------------------------------------------- 1 | import FxdBrowser from 'fxd-app-browser'; 2 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 3 | import dayjs from 'dayjs'; 4 | import path from 'path'; 5 | import fs from 'fs'; 6 | import download from 'download'; 7 | 8 | export default class FxdWeiboPublish extends FxdBrowser { 9 | constructor() { 10 | super(); 11 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 12 | } 13 | 14 | async publish(args, opts, command) { 15 | this.setDefaultOpts(opts); 16 | this.setDefaultCommand(command); 17 | this.format = this.get('format'); 18 | 19 | const url = 'https://m.weibo.cn/compose/'; // 微博发布页面URL 20 | const content = this.get('content') // 从命令行选项中获取微博内容 21 | let images = this.get('images') ; 22 | images = images ? images.split(',') : []// 从命令行选项中获取微博图片 23 | 24 | const self_only = this.get('self_only') // 从命令行选项中获取微博图片 25 | 26 | if (!content) { 27 | console.error('微博内容不能为空'); 28 | return; 29 | } 30 | 31 | const { browser, page } = await this.getBrowserAndMore(this.getUserDirFullPath(this.get('user')), { headless: this.get('headless'), browserType: this.get('browser')}); 32 | 33 | try { 34 | await page.goto(url, { waitUntil: this.get('wait_type') }); 35 | await page.waitForSelector('textarea'); 36 | await page.evaluate( (content) => { 37 | document.querySelector('textarea').value = content; 38 | document.querySelector('textarea').dispatchEvent(new Event('input')); 39 | }, content); 40 | 41 | // 图片 42 | if( self_only ) 43 | { 44 | const element = await page.waitForSelector('footer div.visible'); 45 | await element.click(); 46 | await element.click(); 47 | } 48 | 49 | if( images.length > 0 ) 50 | { 51 | // 确保临时目录存在 52 | const tmp_dir = path.join( "/tmp", this.sdk.name ); 53 | if( !fs.existsSync(tmp_dir) ){ 54 | fs.mkdirSync(tmp_dir); 55 | } 56 | this.log("tmp_dir", tmp_dir); 57 | // const upload_input = await page.waitForSelector('input#selectphoto', { visible: false }); 58 | for (let i = 0; i < images.length; i++) { 59 | let image = images[i].trim(); 60 | this.log("deal with image", image) 61 | // 如果是网络图片,先下载到本地 62 | if( image.startsWith('http') ) 63 | { 64 | // 根据url获得文件扩展名 65 | const ext = path.extname(image)??'.jpg'; 66 | this.log( "ext", ext ); 67 | if( ext == '.mp4' ) continue; 68 | 69 | const filename = `${dayjs().format('YYYYMMDDHHmmss')}_${i}${ext}`; 70 | this.log("referrer",new URL(image).origin ) 71 | await download(image, tmp_dir, { 72 | filename, 73 | headers: 74 | { 75 | Referer: new URL(image).origin 76 | } 77 | }); 78 | image = path.join(tmp_dir, filename); 79 | this.log("local image path", image); 80 | } 81 | 82 | await page.setInputFiles('input#selectphoto', image); 83 | // 等待图片上传完成 84 | // 一张图等待5秒 85 | await page.waitForTimeout(1000*5); 86 | } 87 | } 88 | await page.click('.m-send-btn'); 89 | 90 | // 监测浏览器的URL是否变化 91 | // await page.waitForNavigation({ timeout: this.get('timeout'), waitUntil: this.get('wait_type') }); 92 | await page.waitForURL('about:blank', { timeout: this.get('timeout') }); 93 | 94 | // 转向到用户主页查看是否发布成功 95 | await page.goto('https://m.weibo.cn/profile', { waitUntil: this.get('wait_type') }); 96 | 97 | await page.waitForSelector('.wb-item span.time', { timeout: 1000*10 }); 98 | const weiboTextArray = await page.evaluate(() => { 99 | let data = []; 100 | let elements = document.querySelectorAll('.wb-item'); 101 | for (var element of elements) { 102 | data.push( element.innerText ); 103 | } 104 | return data; 105 | }); 106 | await browser.close(); 107 | let checked = false; 108 | // console.log(ret); 109 | for( const weiboText of weiboTextArray ) 110 | { 111 | // 检查其中是否包含 刚刚 和微博正文的前5个字 112 | if( weiboText.includes('刚刚') && weiboText.includes(String(content)?.substring(0,5)) ) 113 | { 114 | checked = true; 115 | break; 116 | } 117 | } 118 | 119 | 120 | this.log('微博发布成功'); 121 | return this.return({ 'action': 'publish', 'message': 'done', 'output': String(content)?.substring(0,100) + '...', 'checked': checked}); 122 | } catch (error) { 123 | console.error('发布微博时出错:', error); 124 | await browser.close(); 125 | return this.return({ 'action': 'publish', 'message': 'error', 'error': error, 'output' : error.message }); 126 | } 127 | } 128 | 129 | async main(args, opts, command) { 130 | return await this.publish(args, opts, command); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /packages/fxd-app-keep-live2/index.js: -------------------------------------------------------------------------------- 1 | // import FxdBrowser from '/Users/easy/Code/gitcode/fxd/packages/fxd-app-browser/index.js'; 2 | import FxdBrowser from 'fxd-app-browser'; 3 | import {FxdSdk, getPackageInfo} from 'fxd-sdk'; 4 | import chalk from 'chalk'; 5 | 6 | 7 | export default class FxdKeepLive2 extends FxdBrowser { 8 | constructor() { 9 | super(); 10 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 11 | } 12 | 13 | async main(args, opts, command) 14 | { 15 | this.setDefaultOpts(opts); 16 | this.setDefaultCommand(command); 17 | this.format = this.get( 'format' ); 18 | 19 | // keepLive2 --authUrl="https://passport.weibo.cn/signin/login" --refreshUrl="https://m.weibo.cn" --checkUrl="https://m.weibo.cn" --checkSelector="div.lite-iconf-msg" --timeout="5000" 20 | 21 | // 如果 check_url 存在,则执行 check;否则: (如果 refresh_url 存在,则执行 refresh;否则执行 auth) 22 | if( this.get('check_url') ) 23 | { 24 | const ret = await this.check(args, {...opts, format:"json", silent: true}, command); 25 | // 根据检测结果,判断是刷新还是授权 26 | if( ret && ret.ret ) return await this.refresh(args, opts, command); 27 | else return await this.auth(args, {...opts, headless: false}, command); 28 | }else if( this.get('refresh_url') ) 29 | { 30 | return this.refresh(args, opts, command); 31 | } else 32 | { 33 | console.log("auth_url", this.get('auth_url')); 34 | if( !this.get('auth_url') ) this.echoError("auth_url is required"); 35 | return this.auth(args, opts, command); 36 | } 37 | } 38 | 39 | 40 | // 打开网页,访问页面,然后等待用户关闭 41 | async auth(args, opts, command) { 42 | this.setDefaultOpts(opts); 43 | this.setDefaultCommand(command); 44 | this.format = this.get( 'format' ); 45 | 46 | 47 | // 使用 playwright 模拟浏览器打开网页,用户关闭浏览器后,自动退出 48 | const url = this.get( 'auth_url' ); 49 | const userDirFullPath = process.env.FXD_USER_DIR || this.getUserDirFullPath(this.get('user')); 50 | 51 | const { browser, page } = await this.getBrowserAndMore(userDirFullPath, { headless: false, browserType: this.get('browser')}); 52 | 53 | await page.goto(url); 54 | // 用户关闭page后,自动退出 55 | page.on('close', () => { 56 | browser.close(); 57 | const retObj ={ 'action': 'auth', 'message': 'done', 'output':'authed manually' }; 58 | return this.return(retObj,opts['silent']||false); 59 | }); 60 | } 61 | 62 | async refresh(args, opts, command) { 63 | this.setDefaultOpts(opts); 64 | this.setDefaultCommand(command); 65 | this.format = this.get( 'format' ); 66 | 67 | 68 | // 打开网页,访问页面,然后关闭 69 | const url = this.get( 'refresh_url' ); 70 | const headless = this.get( 'headless' ); 71 | const timeout = this.get( 'timeout' ); 72 | 73 | const { browser, page } = await this.getBrowserAndMore(this.getUserDirFullPath(this.get('user')), { headless, browserType: this.get('browser') }); 74 | 75 | await page.goto(url); 76 | // 设置超时 77 | page.setDefaultTimeout(timeout); 78 | // 等待页面加载完成 79 | await page.waitForLoadState('networkidle'); 80 | // 关掉页面 81 | await page.close(); 82 | // 关掉浏览器 83 | await browser.close(); 84 | 85 | const retObj ={ 'action': 'refresh', 'message': 'done','output':'refreshed' }; 86 | this.log("页面已刷新",retObj); 87 | return this.return(retObj); 88 | } 89 | 90 | async check(args, opts, command) { 91 | this.setDefaultOpts(opts); 92 | this.setDefaultCommand(command); 93 | this.format = this.get( 'format' ); 94 | 95 | 96 | // 使用 playwright 模拟浏览器打开网页,监测selector是否包含特定文字 97 | const url = this.get( 'check_url' ); 98 | const selector = this.get( 'check_selector' ); 99 | const text = this.get( 'check_text' ); 100 | 101 | const headless = this.get( 'headless' ); 102 | 103 | const { browser, page } = await this.getBrowserAndMore(this.getUserDirFullPath(this.get('user')), { headless, browserType: this.get('browser')}); 104 | // 设置超时 105 | page.setDefaultTimeout(this.get( 'timeout' )); 106 | 107 | await page.goto(url); 108 | // 等待 selector 出现 109 | // await page.waitForSelector(selector, { timeout: this.get( 'timeout' ) }); 110 | // 等待页面加载完成 111 | await page.waitForLoadState('networkidle'); 112 | this.log("页面加载完成"); 113 | // 使用 locator 获取 selector 的文字 114 | const locator = page.locator(selector); 115 | // 获得 locator 对应的 html 116 | const count = await locator.count(); 117 | this.log("locator", locator, count); 118 | let selectedText; 119 | // 用 allTextContents 是为了获得dom包含的所有文字(包括子元素的) 120 | if( count > 0 ) selectedText = (await locator.allTextContents()).join(' '); 121 | this.log("selectedText", selectedText); 122 | // 如果 selector 的文字包含 text,则返回 true 123 | let ret = false; 124 | if( text && text.length > 0 && selectedText.includes(text) ) ret = true; 125 | if( (!text || text.length < 1) && count > 0 ) ret = true; 126 | await browser.close(); 127 | if( this.get( 'format' ) == 'json' ) 128 | { 129 | const retObj = { 130 | url, 131 | selector, 132 | text, 133 | count, 134 | selectedText, 135 | ret, 136 | 'output':ret?'success':'failed' 137 | }; 138 | this.log(JSON.stringify(retObj, null, 4)); 139 | return this.return(retObj,opts['silent']||false); 140 | }else 141 | { 142 | this.log("检测结果", ret ? chalk.green('成功') : chalk.red('失败')); 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /packages/fxd-app-check-chan/index.js: -------------------------------------------------------------------------------- 1 | // import FxdBrowser from '/Users/easy/Code/gitcode/fxd/packages/fxd-app-browser/index.js'; 2 | import FxdBrowser from 'fxd-app-browser'; 3 | import { FxdSdk, getPackageInfo } from 'fxd-sdk'; 4 | import { diffString, diff } from 'json-diff'; 5 | 6 | 7 | export default class FxdCheckChan extends FxdBrowser { 8 | constructor() { 9 | super(); 10 | this.sdk = new FxdSdk(getPackageInfo(import.meta.url)); 11 | } 12 | 13 | async main(args, opts, command) { 14 | return await this.check(args, opts, command); 15 | } 16 | 17 | async check(args, opts, command, force_silent = false) { 18 | this.setDefaultOpts(opts); 19 | this.setDefaultCommand(command); 20 | this.format = this.get('format'); 21 | 22 | const ret = []; 23 | let ret_texts = ''; 24 | let ret_htmls = ''; 25 | // 是否使用 headless 模式 26 | const headless = this.get('headless'); 27 | 28 | // 要检测的元素 CSS 选择器,多个选择器用逗号分隔 29 | const selectors = this.get('selectors') ? this.get('selectors').split(',') : ['body']; 30 | // process.exit(0); 31 | 32 | // URL 33 | const url = this.get('url'); 34 | if (!url) this.echoError("url is required"); 35 | 36 | const userDirFullPath = process.env.FXD_USER_DIR || this.getUserDirFullPath(this.get('user')); 37 | 38 | const { browser, page, context } = await this.getBrowserAndMore(userDirFullPath, { headless, browserType:this.get('browser') }); 39 | 40 | page.setDefaultTimeout(this.get('timeout')); // 设置超时 41 | await page.goto(url);// 打开URL 42 | // console.log('goto', url); 43 | await page.waitForLoadState( this.get('wait_type')); // 确保页面加载完成 44 | // console.log('waitForLoadState', 'networkidle end'); 45 | 46 | // 执行自定义 playwirght 代码 47 | const preplay = this.get('preplay'); 48 | if (preplay) { 49 | // 定义一个异步函数,用于执行动态代码 50 | const asyncFn = new Function('page', 'context', `return (async () => {${preplay}})();`); 51 | 52 | // 执行异步函数 53 | await asyncFn(page, context); 54 | } 55 | 56 | // 执行自定义的 js 代码 57 | // @Todo 这个地方需要测试下,是否可以正常执行 58 | const prejs = this.get('prejs'); 59 | const prejsArgs = this.get('prejs_args'); 60 | if (prejs) { 61 | await page.evaluate(prejs, prejsArgs); 62 | } 63 | 64 | // 循环 selectors 数组,获取每个元素的 HTML、innerText 65 | for (const selector of selectors) { 66 | let elements = await page.locator(selector).all(); 67 | // console.log('elements', elements.length); 68 | 69 | if (!this.get('list')) elements = [elements[0]]; 70 | let htmls = [], texts = []; 71 | // 循环每个元素,push HTML、innerText 72 | for (const element of elements) { 73 | if(!element) continue; 74 | htmls.push(await element.innerHTML()); 75 | texts.push(await element.innerText()); 76 | } 77 | 78 | const html = htmls.join('\n'); 79 | const text = texts.join('\n'); 80 | 81 | ret.push({ selector, html, text, meta: { html: htmls, text: texts } }); 82 | 83 | if (html) ret_htmls += '\n\n' + html; 84 | if (text) ret_texts += '\n\n' + text; 85 | } 86 | 87 | // 关闭浏览器 88 | // await context.close(); 89 | await browser.close(); 90 | 91 | // 输出中间数据 92 | this.log('检测到的数据', JSON.stringify(ret, null, 2)); 93 | 94 | return this.return({ 95 | merged_html: ret_htmls, 96 | merged_text: ret_texts, 97 | output: ret_texts, 98 | data: [...ret], 99 | }, force_silent) 100 | } 101 | 102 | async watch(args, opts, command, force_silent = false) { 103 | const ret = await this.check(args, opts, 'check', true); // 为了不输出结果,这里强制 force_silent 为 true 104 | 105 | // 借用 check 命令的参数设置 106 | const url = this.get('url'); 107 | const title = this.get('task_title') || this.sdk.displayName; 108 | const icon = this.get('task_icon') || '/logo.svg'; 109 | 110 | // 切换为 watch 命令的设置 111 | this.setDeaultCommand(command); 112 | 113 | // 获取上一次的结果 114 | const urlSHA = this.sdk.sha1(url); 115 | const lastRet = await this.sdk.getValue(urlSHA); 116 | // 保存本次结果 117 | await this.sdk.setValue(urlSHA, ret); 118 | 119 | if (!lastRet) { 120 | this.log("不存在历史记录,将当前结果保存为历史记录"); 121 | } else { 122 | // 比较两次结果 123 | if (diff(lastRet, ret)) { 124 | const differenceString = diffString(lastRet, ret); 125 | const differenceText = diffString(lastRet, ret, { color: false }); 126 | this.log("检测到变动", differenceString); 127 | 128 | const markdown_body = `\`\`\`diff 129 | ${differenceText} 130 | \`\`\``; 131 | 132 | // 如果 opts.sendkey 存在,则发送到指定的 key 133 | const sendkey = this.get('sendkey'); 134 | if (sendkey) { 135 | const send_ret = await this.sdk.scSend(`${title} 有新的动态`, markdown_body, sendkey); 136 | this.log("存在sendkey,发送结果到Server酱", send_ret); 137 | } 138 | 139 | const apprise_server_url = this.get('apprise_server_url'); 140 | if (apprise_server_url) 141 | { 142 | // apprise -t '你好' -b '[hello](http://ftqq.com)' -i 'markdown' 'schan://SCT1T...' 143 | // 调用命令行 144 | const send_ret = await this.sdk.apprise(apprise_server_url, `${title} 有新的动态`, markdown_body, 'markdown'); 145 | this.log("存在apprise_server_url,发送结果到Apprise", send_ret); 146 | 147 | } 148 | 149 | // 如果 opts.feed_publish 存在,则发布到 feed 150 | const feed_publish = this.get('feed_publish'); 151 | if (feed_publish) { 152 | const feed_ret = await this.feedPublish( `${ret.merged_text} \n\n[链接](${url})`, ret , this.get('feed_as_public'), command, title, icon); 153 | 154 | this.log("发布结果到feed列表", feed_ret); 155 | } 156 | 157 | 158 | return this.return({ 159 | "message": "检测到变动", 160 | "diff": differenceText, 161 | "action": "changed", 162 | "data": ret, 163 | "output": ret.merged_text, 164 | }, force_silent); 165 | } else { 166 | this.log("目标数据没有变化"); 167 | return this.return({ "message": "目标数据没有变化", "action": "unchanged", "output": ret.merged_text }, force_silent); 168 | } 169 | } 170 | } 171 | } 172 | 173 | -------------------------------------------------------------------------------- /packages/fxd-app-check-chan/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fxd-app-check-chan", 3 | "displayName": "CheckChan", 4 | "version": "1.0.27", 5 | "main": "index.js", 6 | "license": "SEE LICENSE IN LICENSE.txt", 7 | "type": "module", 8 | "dependencies": { 9 | "@playwright/browser-chromium": "^1.41.2", 10 | "fxd-app-browser": "^1.0.8", 11 | "fxd-app-core": "^1.0.42", 12 | "fxd-sdk": "^1.0.59", 13 | "json-diff": "^1.0.6", 14 | "playwright": "^1.41.2" 15 | }, 16 | "meta": { 17 | "for": "fxd", 18 | "author_uid": 1, 19 | "args": { 20 | "main|check|watch": { 21 | "url": { 22 | "name": "url", 23 | "description": "要打开的页面 URL", 24 | "type": "string", 25 | "required": true, 26 | "example": "https://www.example.com" 27 | }, 28 | "headless": { 29 | "name": "headless", 30 | "cn_name": "后台模式", 31 | "description": "是否使用后台模式", 32 | "type": "boolean", 33 | "default": true, 34 | "example": "true" 35 | }, 36 | "browser":{ 37 | "name": "browser", 38 | "description": "浏览器类型", 39 | "type": "string", 40 | "required": false, 41 | "default": "chromium", 42 | "example": "chromium", 43 | "enum": ["chromium","firefox","webkit"] 44 | }, 45 | "selectors": { 46 | "name": "selectors", 47 | "cn_name": "元素选择器", 48 | "description": "要检测的元素的 CSS 选择器,多个用逗号分隔", 49 | "type": "string", 50 | "default": "body", 51 | "required": true, 52 | "example": "div.content,div#footer" 53 | }, 54 | "prejs": { 55 | "name": "prejs", 56 | "cn_name": "自定义 JavaScript 代码", 57 | "description": "页面加载完成后执行的自定义 JavaScript 代码", 58 | "type": "string", 59 | "ui": "textarea", 60 | "advanced": true, 61 | "example": "document.body.style.backgroundColor = 'red'" 62 | }, 63 | "prejs_args": { 64 | "name": "prejs_args", 65 | "cn_name": "自定义 JavaScript 代码的参数,逗号分隔", 66 | "description": "自定义 JavaScript 代码的参数", 67 | "type": "string", 68 | "advanced": true, 69 | "example": "arg1,arg2" 70 | }, 71 | "preplay": { 72 | "name": "preplay", 73 | "cn_name": "自定义 Playwright 代码", 74 | "advanced": true, 75 | "description": "页面加载完成后执行的自定义 Playwright 代码", 76 | "type": "string", 77 | "ui": "textarea", 78 | "example": "await page.click('button#submit')" 79 | }, 80 | "timeout": { 81 | "name": "timeout", 82 | "cn_name": "操作超时时间", 83 | "description": " Playwright 操作超时时间,单位毫秒", 84 | "type": "number", 85 | "advanced": true, 86 | "default": 60000, 87 | "example": 30000 88 | }, 89 | "list": { 90 | "name": "list", 91 | "cn_name": "返回元素列表而非单个元素", 92 | "description": " 选择器是否返回元素列表", 93 | "type": "boolean", 94 | "advanced": true, 95 | "default": false, 96 | "example": "true" 97 | }, 98 | "user": { 99 | "name": "user", 100 | "cn_name": "用户目录名称", 101 | "description": "浏览器使用的用户目录", 102 | "type": "string", 103 | "advanced": true, 104 | "default": "default", 105 | "example": "admin" 106 | }, 107 | "format": { 108 | "name": "format", 109 | "cn_name": "返回数据格式", 110 | "description": "返回的数据格式", 111 | "type": "string", 112 | "advanced": true, 113 | "default": "text", 114 | "example": "json", 115 | "enum": [ 116 | "json", 117 | "text" 118 | ] 119 | }, 120 | "wait_type": { 121 | "name": "wait_type", 122 | "cn_name": "元素检测时机", 123 | "description": "等待元素出现的方式", 124 | "type": "string", 125 | "advanced": true, 126 | "default": "domcontentloaded", 127 | "example": "networkidle", 128 | "enum": [ 129 | "domcontentloaded", 130 | "load", 131 | "networkidle" 132 | ] 133 | } 134 | }, 135 | "watch": { 136 | "sendkey": { 137 | "name": "sendkey", 138 | "description": "填入后,检测到变化时会调用Server酱发消息", 139 | "type": "string", 140 | "example": "abcdefg1234" 141 | }, 142 | "apprise_server_url": { 143 | "name": "apprise_server_url", 144 | "cn_name": "Apprise Server URL", 145 | "description": "apprise的Server URL;需安装 apprise 命令行以后才可使用", 146 | "type": "string", 147 | "example": "schan://SCT1U...", 148 | "advanced": true 149 | }, 150 | "task_title": { 151 | "name": "task_title", 152 | "description": "显示在动态中,非命令行模式则无需填写", 153 | "cn_name": "任务名称", 154 | "type": "string", 155 | "example": "监测方小代版本更新", 156 | "advanced": true 157 | }, 158 | "task_icon": { 159 | "name": "task_icon", 160 | "description": "显示在动态中,非命令行模式则无需填写", 161 | "cn_name": "任务图标地址", 162 | "type": "string", 163 | "example": "/logo.svg", 164 | "advanced": true 165 | }, 166 | "feed_publish": { 167 | "name": "feed_publish", 168 | "cn_name": "数据变动时发布Feed", 169 | "description": "是否发布为Feed,将显示在动态页面", 170 | "type": "boolean", 171 | "default": false, 172 | "example": "true" 173 | }, 174 | "feed_as_public": { 175 | "name": "feed_as_public", 176 | "cn_name": "Feed是否公开(并入RSS)", 177 | "description": "Feed 是否公开", 178 | "type": "boolean", 179 | "advanced": true, 180 | "default": true, 181 | "example": "true", 182 | "show_when_field_not_empty": "feed_publish" 183 | } 184 | } 185 | }, 186 | "output": { 187 | "main|watch": { 188 | "success": { 189 | "merged_html": { 190 | "name": "merged_html", 191 | "description": "所有选择器匹配元素的HTML内容合并之后的结果", 192 | "type": "string", 193 | "example": "
Example HTML content
" 194 | }, 195 | "merged_text": { 196 | "name": "merged_text", 197 | "description": "所有选择器匹配元素的文本内容合并之后的结果", 198 | "type": "string", 199 | "example": "Example text content" 200 | }, 201 | "output": { 202 | "name": "output", 203 | "description": "根据format参数决定是返回merged_text还是其他格式的数据", 204 | "type": "string", 205 | "example": "Example output content" 206 | }, 207 | "data": { 208 | "name": "data", 209 | "description": "包含每个选择器匹配的元素的详细信息,如HTML内容和文本内容", 210 | "type": "array", 211 | "example": "[{\"selector\": \"div.content\", \"html\": \"
content
\", \"text\": \"content\"}]" 212 | } 213 | }, 214 | "fail": { 215 | "error": { 216 | "name": "error", 217 | "type": "string", 218 | "description": "错误信息", 219 | "example": "页面加载失败或元素未找到" 220 | } 221 | } 222 | } 223 | } 224 | } 225 | } 226 | --------------------------------------------------------------------------------