首页
留言
导航
统计
Search
1
追番推荐!免费看动漫的网站 - 支持在线观看和磁力下载
2,514 阅读
2
推荐31个docker应用,每一个都很实用
1,313 阅读
3
PVE自动启动 虚拟机 | 容器 顺序设置及参数说明
933 阅读
4
一条命令,永久激活!Office 2024!
618 阅读
5
优选 Cloudflare 官方 / 中转 IP
490 阅读
默认分类
服务器
宝塔
VPS
Docker
OpenWRT
Nginx
群晖
前端编程
Vue
React
Angular
NodeJS
uni-app
后端编程
Java
Python
SpringBoot
SpringCloud
流程引擎
检索引擎
Linux
CentOS
Ubuntu
Debian
数据库
Redis
MySQL
Oracle
虚拟机
VMware
VirtualBox
PVE
Hyper-V
计算机
网络技术
网站源码
主题模板
登录
Search
标签搜索
Java
小程序
Redis
SpringBoot
docker
Typecho
Cloudflare
docker部署
虚拟机
WordPress
群晖
uni-app
CentOS
Vue
Java类库
Linux命令
防火墙配置
Mysql
脚本
Nginx
微醺
累计撰写
264
篇文章
累计收到
11
条评论
首页
栏目
默认分类
服务器
宝塔
VPS
Docker
OpenWRT
Nginx
群晖
前端编程
Vue
React
Angular
NodeJS
uni-app
后端编程
Java
Python
SpringBoot
SpringCloud
流程引擎
检索引擎
Linux
CentOS
Ubuntu
Debian
数据库
Redis
MySQL
Oracle
虚拟机
VMware
VirtualBox
PVE
Hyper-V
计算机
网络技术
网站源码
主题模板
页面
留言
导航
统计
搜索到
264
篇与
的结果
2024-09-12
一条命令,永久激活!Office 2024!
微软已经率先发布 Office 2024英文版(零售版) 。众所周知,零售版是有微软正式发布的离线镜像,目前中文版的镜像微软尚未发布。而对于批量授权版,自从Office 2019开始,微软就已经不再单独发布镜像文件了。所采用的方式均为在线部署安装。很多第三方软件基于微软提供的ODT部署方式,开发了操作更加便捷的Office部署程序。但是最近收到很多小伙伴的留言提问,为什么安装了Office 2024 批量版后,显示preview字样?还是预览版吗?首先,微软至今尚未宣布正式发布Office 2024,它包含零售版和批量授权版两大类,零售版中也仅仅是英文版的Office 2024镜像已经可以在官网下载,但中文版依旧未正式发布。批量授权版的Office 2024均未正式发布,因此现在依然是预览版。其次,现在的预览版可以安装体验了吗?可以!它已经很接近正式版,是准正式版。为什么有的人安装后没有preview字样,这是怎么回事?下面先把安装过程截图展示一下~安装完毕后,默认情况显示 preview 字样,虽然还是预览版,但是当前版本自带的许可证已经包含了正式版的许可证。就好比Windows10或11系统一样,安装专业版密钥它就是专业版,安装企业版密钥它就是企业版。Office 2024这里也一样,安装正式版的密钥,它就不再显示preview字样了。下面这几个是几枚MAK密钥,看起来怪怪的,但确实能够安装。ProPlus2024:NBBBB-BBBBB-BBBBB-BBBJD-VXRPM Standard2024:V28N4-JG22K-W66P8-VTMGK-H6HGR ProjectPro2024:NBBBB-BBBBB-BBBBB-BBBH4-GX3R4 ProjectStd2024:PD3TT-NTHQQ-VC7CY-MFXK3-G87F8 VisioPro2024:NBBBB-BBBBB-BBBBB-BBBCW-6MX6T VisioStd2024:JMMVY-XFNQC-KK4HK-9H7R3-WQQTV更改密钥后,再重新打开Office,preview字样就消失了~最后,使用一条命令激活Office 2024,在 Powershell 中,首先输入以下命令,然后输入 "2" ,最后输入 "1" 即可。irm https://get.activated.win | iex注意:该命令需要联网,其原理是下载MAS激活软件的最新版,目前2.7版已经发布。MAS激活Office的方法是使用了Ohook,为永久激活!
2024年09月12日
618 阅读
0 评论
0 点赞
2024-07-31
还学鸿蒙原生?vue3 + uniapp 可以直接开发鸿蒙啦!
前言7月20号,uniapp 官网 “悄咪咪” 的上线了 uniapp 开发鸿蒙应用 的文档,算是正式开启了 Vue3 + uniapp 开发鸿蒙应用 的时代。开发鸿蒙的前置准备想要使用 uniapp 开发鸿蒙,我们需要具备三个条件:DevEco-Studio 5.0.3.400 以上(下载地址:https://developer.huawei.com/consumer/cn/deveco-studio/)鸿蒙系统版本 API 12 以上 (DevEco-Studio有内置鸿蒙模拟器)HBuilderX-alpha-4.22 以上PS: 这里不得不吐槽一下,一个 DevEco-Studio 竟然有 10 个 G......[安装好之后,我们就可以通过 开发工具 运行 示例代码]运行时,需要用到 鸿蒙真机或者模拟器。但是这里需要 注意: Windows系统需要经过特殊配置才可以启动,mac 系统最好保证系统版本在 mac os 12 以上windows 系统配置方式(非 windows 用户可跳过): 打开控制面板 - 程序与功能 - 开启以下功能Hyper-VWindows 虚拟机监控程序平台虚拟机平台注意: 需要win10专业版或win11专业版才能开启以上功能,家庭版需先升级成专业版或企业版启动鸿蒙模拟器整个过程分为三步(中间会涉及到鸿蒙开发者申请):下载 uni-app 鸿蒙离线SDK template-1.3.4.tgz (下载地址:https://web-ext-storage.dcloud.net.cn/uni-app/harmony/zip/template-1.3.4.tgz)解压刚下载的压缩包,将解压后的模板工程在 DevEco-Studio 中打开等待 Sync 结束,再 启动鸿蒙模拟器 或 连接鸿蒙真机(如无权限,则需要申请(一般 3 个工作日),申请地址:https://developer.huawei.com/consumer/cn/activity/201714466699051861/signup)配置 HBuilderX 吊起 DevEco-Studio打开HBuilderX,点击上方菜单 - 工具 - 设置,在出现的弹窗右侧窗体新增如下配置[注意:值填你自己的 DevEco-Studio 启动路径]"harmony.devTools.path" : "/Applications/DevEco-Studio.app"创建 uni-app 工程BuilderX 新建一个空白的 uniapp 项目,选vue3在 manifest.json 文件中配置鸿蒙离线SDK路径(SDK 路径可在 DevEco-Studio -> Preferences(设置) z中获取)编辑 manifest.json 文件,新增如下配置:然后点击 运行到鸿蒙即可最后这样我们就有了一个初始的鸿蒙项目,并且可以在鸿蒙模拟器上运行。关于更多 uniapp 开发鸿蒙的 API,大家可以直接参考 uniapp 官方文档:https://zh.uniapp.dcloud.io/tutorial/harmony/dev.html#nativeapi
2024年07月31日
44 阅读
0 评论
0 点赞
2024-06-18
Cloudflare橙色云启用后 Nginx Proxy Manager的IP白名单和黑名单配置指南
在使用Cloudflare的橙色云(即启用CDN功能)后,许多用户发现Nginx Proxy Manager中的Access Lists(IP地址白名单/黑名单)失效。这通常是因为Cloudflare的代理服务器屏蔽了真实的客户端IP地址,导致Nginx无法直接获取客户端的真实IP,而只能看到Cloudflare的IP地址。本文将介绍如何配置Nginx,以便它能够正确识别和使用Cloudflare传递的真实客户端IP地址,从而确保访问控制列表的正常工作。配置Cloudflare的真实IP头要解决这一问题,首先需要在Nginx中配置,以便它能够识别Cloudflare传递的真实客户端IP地址。Cloudflare通常通过CF-Connecting-IP或X-Forwarded-For头传递真实的客户端IP。以下是具体步骤:在Nginx配置文件中添加以下内容# Cloudflare IPv4 addresses set_real_ip_from 103.21.244.0/22; set_real_ip_from 103.22.200.0/22; set_real_ip_from 103.31.4.0/22; set_real_ip_from 104.16.0.0/13; set_real_ip_from 104.24.0.0/14; set_real_ip_from 108.162.192.0/18; set_real_ip_from 131.0.72.0/22; set_real_ip_from 141.101.64.0/18; set_real_ip_from 162.158.0.0/15; set_real_ip_from 172.64.0.0/13; set_real_ip_from 173.245.48.0/20; set_real_ip_from 188.114.96.0/20; set_real_ip_from 190.93.240.0/20; set_real_ip_from 197.234.240.0/22; set_real_ip_from 198.41.128.0/17; # Cloudflare IPv6 addresses set_real_ip_from 2400:cb00::/32; set_real_ip_from 2606:4700::/32; set_real_ip_from 2803:f800::/32; set_real_ip_from 2405:b500::/32; set_real_ip_from 2405:8100::/32; set_real_ip_from 2a06:98c0::/29; set_real_ip_from 2c0f:f248::/32; real_ip_header CF-Connecting-IP;CloudflareIP 范围 https://www.cloudflare.com/zh-tw/ips/这些IP段是Cloudflare的代理服务器IP地址,通过set_real_ip_from指令,Nginx将信任这些IP地址,并从CF-Connecting-IP头中获取真实的客户端IP。更新Nginx Proxy Manager配置确保Nginx Proxy Manager能够正确使用上述配置。如果Nginx Proxy Manager允许自定义Nginx配置片段,将上述配置片段添加到相应位置。调整访问控制列表确保你的访问控制列表(白名单/黑名单)中的IP地址策略基于真实的客户端IP,而不是Cloudflare的IP地址。实际使用场景访问控制公司A希望只允许公司内部IP地址访问其网站。他们启用了Cloudflare的CDN加速,但发现所有访问请求的IP地址都显示为Cloudflare的代理服务器IP,导致访问控制列表失效。通过上述配置,Nginx能够正确识别真实的客户端IP,从而确保只有公司内部IP地址能够访问网站。日志记录和分析公司B使用Nginx记录访问日志以进行流量分析和安全监控。在启用Cloudflare CDN后,访问日志中显示的IP地址都是Cloudflare的代理服务器IP。通过上述配置,Nginx能够记录真实的客户端IP,从而提供准确的流量分析和安全监控数据。防止DDoS攻击公司C遇到DDoS攻击,攻击流量通过Cloudflare的代理服务器进入,导致Nginx的防护措施失效。通过正确配置Nginx以识别真实的客户端IP,公司C可以更有效地应用防火墙规则,识别并阻止攻击IP,从而提升防护效果。结论通过正确配置 Nginx 以识别 Cloudflare 传递的真实客户端IP地址,可以解决因启用 Cloudflare CDN 功能导致的访问控制列表失效问题。这不仅能确保访问控制列表的正常工作,还能提升日志记录、流量分析和安全防护的准确性。希望本文对你配置 Nginx Proxy Manager 以支持 Cloudflare CDN 功能有所帮助。
2024年06月18日
252 阅读
0 评论
0 点赞
2024-06-18
200 行 Rust 代码实现简单 CF Workers AI Bot | Rust 学习日记
本文由 High Ping Network 的小伙伴 GenshinMinecraft 进行编撰前言这次主要是用 Rust 重写了之前用 Python3 写的 Cloudflare Workers AI Telegram 机器人一边看着 《Rust 圣经》 一边 Coding,还是挺好玩的当然,因为我是 Rust 新手,所以代码中有问题的地方还请多多包涵请注意,本文会一步步讲解这一 Bot 的实现过程,也算是我学习 Rust 的一个阶段性总结如果你不想看实现过程,请直接翻到本文末尾开干!如何开启一个项目? 那当然是: 新建文件夹!环境环境配置请看 Rust 官方文档 新建文件夹并在终端输入以下命令来初始化一个项目:cargo new [文件夹名字]去 Telegram 申请一个新的 Bot ,保存 Bot Token 以留作备用 (这么简单懒得说了)然后前往这里来创建 Workers AI API 令牌 和 帐户 ID ,也是复制保存备用配置依赖在项目根目录下有个 Cargo.toml ,里面是有关项目信息的内容,在最底下添加如下内容:[dependencies] reqwest = { version = "0.12.4", features = ["json","blocking"] } serde_json = "1.0" teloxide = { version = "0.12", features = ["macros"] } tokio = { version = "1.38.0", features = ["rt-multi-thread", "macros"] } log = "0.4.21" simple_logger = "5.0.0"这里表示了项目需要用到这堆东西,如果之前有用过 Python ,那这玩意就可以理解为 requirements.txt然后删除 src/main.rs 中所有内容,并在开头引用这些库:use reqwest::header; use serde_json::{from_str, json, Value}; use teloxide::{prelude::*,types::ParseMode}; use log::{Level, info, warn, error, debug}; use simple_logger; 这样就算引用完成了!PS: 你可能还需要去终端来安装一下依赖:cargo add reqwest serde_json teloxide log simple_logger常量定义// 初始化全局常量 static API_KEY: &str = ""; static USER_ID: &str = ""; static PROMPT: &str = "你是一个中文大模型,不管我用什么语言提出问题,你必须使用中文回答!"; static MODEL: &str = "@cf/qwen/qwen1.5-14b-chat-awq"; static TELEGRAM_BOTTOKEN: &str = "";API_KEY: Workers AI API 令牌USER_ID: 帐户 IDPROMPT: AI 提示词MODEL: 对话使用的大模型,默认是阿里云的通义千问,可以在这里查看支持的模型,更改即可,非必要无需更改TELEGRAM_BOTTOKEN: Telegram Bot Token按照要求将 Workers AI API 令牌 和 帐户 ID 还有 Telegram Bot Token 放入对应的位置中,以便于下面调用如果有需要,也可以根据文档来修改 MODEL 模型和 PROMPT 提示词编写 GPT 请求函数先不着急编写 Bot 主体部分,来看下有关网络请求的调用函数定义// GPT 对话函数,用于请求 API 并返回async fn gpt(question: &str) -> Result<String, String> {}简单介绍一下:这句定义了一个名为 gpt 的异步函数,question 是参数返回值是 String 但是不确定是返回正常结果还是错误信息,这种做法有助于错误处理构建 Headers玩过大模型 API 的都知道,鉴权 (也就是 API_Tokens 这类东西) 一般是放在 Headers 里面的,所以我们要来构建 Headers而 Workers AI 的 API Headers 格式类似这样:Authorization: Bearer {API_TOKEN}于是,就有了下面的代码:// 初始化 Headers,包含 API KEY let mut headers = header::HeaderMap::new(); headers.insert( "Authorization", format!("Bearer {}", API_KEY).parse().unwrap(), ); headers.insert( "Content-Type", "application/x-www-form-urlencoded".parse().unwrap(), );这里定义了一个变量 headers ,并用 insert 插入两条键值对其中 Authorization 用于存放 API_KEY ,用到了 format!() 宏格式化它的值,运用到了最开始定义的 API_KEY 常量Content-Type 则是表明了发送的数据格式,用于指示资源的MIME类型.parse() : 将字符串转化为 HeaderValue 类型,这是 reqwest 库用来存储 Headers 的类型.unwrap() : 直接获取结果而不进行错误处理 (有错误就退出,不过这段代码没有必要进行错误处理)构建请求体接下来是请求体:let data = json!({ "messages": [ {"role": "system", "content": PROMPT}, {"role": "user", "content": question}, ] }); 简单易懂,调用 `PROMPT` 和函数参数中的 `question` 即可,简单的 Json [发送请求] 终于可以发送请求了,首先,来初始化一个 HTTP Client: '''rust let client = reqwest::Client::new();随后就可以发送请求了:let api: String = client .post(format!( "https://api.cloudflare.com/client/v4/accounts/{}/ai/run/{}", USER_ID, MODEL )) .headers(headers) .json(&data) .send() .await .map_err(|_| "请求出现问题".to_string())? .text() .await .map_err(|_| "解析响应体时出错".to_string())?;这里声明了一个 api 变量,用于存储获取到的数据client.post(): 则是发送 Post 请求的主要语句,URL 中的 Workers AI API 令牌 和 模型 还是一样使用 format!() 来构建headers(headers): 传递 Headers.json(&data): 将 data 转换为 Json 作为请求体.send().await: 这一步就相当于发送请求了,并等待异步操作完成.map_err(|_| "请求出现问题".to_string())?: 错误处理,如果发生问题则直接返回 请求出现问题 而不继续执行,如果出现错误则直接赋值给变量 api.text().await: 将收到的数据转换为文本信息,并等待异步操作完成.map_err(|_| "解析响应体时出错".to_string())?: 作用和上面那个差不多这样就算发送完一个请求并把接收到的信息赋值给 api 了解析 Json经过上面的请求,api 应该是一个 Json 格式的字符串,我们需要在里面提取出需要的答案Json 大概长这样:{ "result": {"response": "我是来自阿里云的超大规模语言模型,我叫通义千问。"}, "success": true, "errors": [], "messages": []}let json: Value = from_str(&api).map_err(|_| "解析 Json 时出错".to_string())?; let result_tmp = json .get("result") .ok_or("Json 中缺少 'result' 字段".to_string())?; let result = result_tmp .get("response") .ok_or("Json 中缺少 'response' 字段".to_string())?; Ok(result.to_string())第一行代码尝试将变量 api 中存储的字符串解析为 JSON 格式,同样的 .map_err() 就不再解释了第一次从 Json 中获取信息返回的是 Option<&Value> 即可能有或可能没有,所以我们使用 .ok_or() 来判断有或无,当有时则直接赋值,没有则返回错误第二次从 Json 中获取信息也一样,不多赘述最后,返回 result 即可编写主程序呼呼,终于等待编写主程序了,不过主要的信息处理程序并不在 main 函数中,main 函数在代码中只起到一个引导的作用async fn main() { // 日志初始化 simple_logger::init_with_level(Level::Debug).unwrap(); // 初始化 Bot info!("Bot 初始化中"); let bot = Bot::new(TELEGRAM_BOTTOKEN); info!("Bot 初始化完毕"); // 主程序 teloxide::repl(bot, |bot: Bot, msg: Message| async move { // 私聊 if msg.chat.is_private() { match msg.text() { Some(_text) => matchmsgprivate(msg, bot).await, None => debug!("消息没有文本内容,跳过"), } } else { // 非私聊 match msg.text() { Some(_text) => matchmsgpublic(msg, bot).await, None => debug!("消息没有文本内容,跳过"), } } Ok(()) }) .await; }首先定义一个 main 异步函数,这是主程序的入口初始化一个 Log 记录器,这里使用了 simple_logger 库,该库无需繁琐地配置 Log 信息即可做到美观的输出,定义 Log Level 为 Debuginfo!() 宏是用来记录 Log 的,相同的,还有 debug!() warn!() error!() 等,分别记录不同等级的日志,下面不再赘述let bot = Bot::new(TELEGRAM_BOTTOKEN): 定义了一个名为 bot 的 Bot Client,它可以接收消息、发送消息等teloxide::repl:异步函数,可以启动一个 REPL 循环 (简要理解成可以处理新信息的循环即可),传入 Bot 并接受名为 msg 的信息提供给下面的代码。下面的代码即为消息处理程序msg.chat.is_private(): 返回一个布尔值,是否为私聊信息if msg.chat.is_private() {} else {}: 消息处理程序分成了两个部分,即判断是否为私聊 Bot,如果是则执行上半部分代码,否则执行下半部分msg.text(): 返回一个字符串,消息的文本内容因为 msg.text() 的类型为 Option<&str>,即可能有或没有 (没有文本信息的话可能为图片、文件、贴纸等),所以需要使用 match 做判断,如果有文本信息则将 bot 和 msg 传入 matchmsgprivate 或者 matchmsgpublic 函数中 (之后会定义这两个函数)当没有文本消息时候,则 Log Debug 输出总的来说,main 函数主要就是接受信息并交给其他函数处理 (尽管是小项目我个人还是建议不要全堆在 main 函数里面)处理私聊信息私聊信息需要做到:/start 发送帮助信息当直接对话 (不是 / 命令时),直接返回结果/ai 问题 返回问题的结果主要思路是判断消息是否为 / 开头,如果不是则直接返回 GPT 回答,如果是再进行指令判断async fn matchmsgprivate(msg: Message, bot: Bot) { let text: &str = msg.text().unwrap(); if text.starts_with('/') { // 是否为 "/" 开头的命令 let mut parts = text.splitn(2, ' '); let command: &str = parts.next().unwrap(); // 命令部分 let argument: Option<&str> = parts.next(); // 参数部分,可能为 None if command.starts_with("/ai") { replyai(msg.clone(), bot, argument).await; } else if command.starts_with("/start") { replystart(msg, bot).await; } else { debug!("非本 Bot 命令,跳过"); } } else { replyai(msg.clone(), bot, msg.text()).await; // 非命令直接当作问题 } }先定义一个 text 用于储存文本信息,便于调用 (因为在主函数调用该函数时候已经做过检测,所以这里使用 .unwrap() 并无不妥)随后进行 / 开头命令检测,为否直接调用 replyai 函数 (等会定义),传入 msg, bot, msg.text() (不想处理借用问题,msg 用 .clone() 就好)如果为是,则使用 .splitn() 分割命令,command 为指令部分 (如 /start),argument 为参数部分 (可能没有,所以用 Option<&str>)如果命令开头为 /ai,则传入 replyai 函数;如果开头为 /start,则传入 replystart 函数 (等会定义)如果都不是机器人的指令,则不做处理,输出 Debug 信息处理群组信息这一部分和处理私聊信息差不多,区别只是非指令消息不回复async fn matchmsgpublic(msg: Message, bot: Bot) { let text: &str = msg.text().unwrap(); if text.starts_with('/') { // 是否为 "/" 开头的命令 let mut parts = text.splitn(2, ' '); let command: &str = parts.next().unwrap(); // 命令部分 let argument: Option<&str> = parts.next(); // 参数部分,可能为 None if command.starts_with("/ai") { replyai(msg.clone(), bot, argument).await; } else if command.starts_with("/start") { replystart(msg, bot).await; } else { debug!("非本 Bot 命令,跳过"); } } else { debug!("非命令,跳过"); } }同样的逻辑,只是检测为非指令仅输出 Debug 消息而已AI 回复这里要实现一个函数需要传入 msg、bot、text 信息,调用 gpt 函数并发送回 Telegramasync fn replyai(msg: Message, bot: Bot, optiontext: Option<&str>) { let text: &str; // 检测是否有参数 match optiontext { Some(texttmp) => text = texttmp, None => { warn!("{}", format!("用户 {:?} 使用方法不正确", msg.chat.id)); let _ = bot.send_message(msg.chat.id, "使用方法不正确!请使用 /start 来查看使用方法") .parse_mode(ParseMode::MarkdownV2) .await; return; } } let mut answer: String = String::new(); // 最重要的一部分 match gpt(text).await { Ok(response) => answer = response, Err(error) => error!("{}", error), } info!("{}", format!("用户 {} 使用了本 Bot, 问题是: {}", msg.chat.id, text)); info!("{}", format!("回答是: {}", answer)); // 回复 let _ = bot.send_message(msg.chat.id, answer) .parse_mode(ParseMode::MarkdownV2) .await; }定义异步函数不再赘述,需要注意 optiontext: Option<&str> 需要传入的是 Option<&str>,对应着消息处理函数的 argument既然 optiontext 为可能有可能没有的,那就先来检测一下。使用 match,当有值时赋值给 text;无值时输出 warn 信息并回复给用户,提示请查看 /start 指令,并退出检测成功后,调用 gpt 函数,也是使用 match。如果正常则赋值给 answer,有错误则输出 error 信息输出几条 info 信息,随后就可以将结果发送回 Telegram 了 (GPT 返回内容多使用 Markdown 格式,所以这里指定使用 MarkdownV2 格式发送)就这么简单,主要的代码还是错误处理,不然没有必要写这么多Start 回复最最最最简单的一部分,传入 bot 和 msg 即可async fn replystart(msg: Message, bot: Bot) { let startmessage: &str = r#" 命令帮助: /start: 显示本消息 /ai 问题: 获取由 Cloudflare Workers AI 驱动的 GPT 答案 PS: 私聊 Bot 可直接对话,无需 /ai 前缀 "#; info!("{}", format!("用户 {} 开始使用本 Bot", msg.chat.id)); let _ = bot.send_message(msg.chat.id, startmessage) .parse_mode(ParseMode::MarkdownV2) .await; }定义一个字符串,作为帮助信息info 输出基本信息发送帮助信息完整代码 use reqwest::header; use serde_json::{from_str, json, Value}; use teloxide::{prelude::*,types::ParseMode}; use log::{Level, info, warn, error, debug}; use simple_logger; // 初始化全局变量 static API_KEY: &str = ""; static USER_ID: &str = ""; static PROMPT: &str = "你是一个中文大模型,不管我用什么语言提出问题,你必须使用中文回答!"; static MODEL: &str = "@cf/qwen/qwen1.5-14b-chat-awq"; static TELEGRAM_BOTTOKEN: &str = ""; // GPT 对话函数,用于请求 API 并返回 async fn gpt(question: &str) -> Result<String, String> { // 初始化 Headers,包含 API KEY let mut headers = header::HeaderMap::new(); headers.insert( "Authorization", format!("Bearer {}", API_KEY).parse().unwrap(), ); headers.insert( "Content-Type", "application/x-www-form-urlencoded".parse().unwrap(), ); // 初始化问题 let data = json!({ "messages": [ {"role": "system", "content": PROMPT}, {"role": "user", "content": question}, ] }); // 初始化 Client let client = reqwest::Client::new(); // 请求 CF API let api: String = client .post(format!( "https://api.cloudflare.com/client/v4/accounts/{}/ai/run/{}", USER_ID, MODEL )) .headers(headers) .json(&data) .send() .await .map_err(|_| "请求出现问题".to_string())? .text() .await .map_err(|_| "解析响应体时出错".to_string())?; // 解析 Json let json: Value = from_str(&api).map_err(|_| "解析 Json 时出错".to_string())?; let result_tmp = json .get("result") .ok_or("Json 中缺少 'result' 字段".to_string())?; let result = result_tmp .get("response") .ok_or("Json 中缺少 'response' 字段".to_string())?; Ok(result.to_string()) } // 主函数 #[tokio::main] async fn main() { // 日志初始化 simple_logger::init_with_level(Level::Debug).unwrap(); // 初始化 Bot info!("Bot 初始化中"); let bot = Bot::new(TELEGRAM_BOTTOKEN); info!("Bot 初始化完毕"); // 主程序 teloxide::repl(bot, |bot: Bot, msg: Message| async move { // 私聊 if msg.chat.is_private() { match msg.text() { Some(_text) => matchmsgprivate(msg, bot).await, None => debug!("消息没有文本内容,跳过"), } } else { // 非私聊 match msg.text() { Some(_text) => matchmsgpublic(msg, bot).await, None => debug!("消息没有文本内容,跳过"), } } Ok(()) }) .await; } // GPT 回复函数 async fn replyai(msg: Message, bot: Bot, optiontext: Option<&str>) { let text: &str; // 检测是否有参数 match optiontext { Some(texttmp) => text = texttmp, None => { warn!("{}", format!("用户 {:?} 使用方法不正确", msg.chat.id)); let _ = bot.send_message(msg.chat.id, "使用方法不正确!请使用 /start 来查看使用方法") .parse_mode(ParseMode::MarkdownV2) .await; return; } } let mut answer: String = String::new(); // 最重要的一部分 match gpt(text).await { Ok(response) => answer = response, Err(error) => error!("{}", error), } info!("{}", format!("用户 {} 使用了本 Bot, 问题是: {}", msg.chat.id, text)); info!("{}", format!("回答是: {}", answer)); // 回复 let _ = bot.send_message(msg.chat.id, answer) .parse_mode(ParseMode::MarkdownV2) .await; } // start 回复函数 async fn replystart(msg: Message, bot: Bot) { let startmessage: &str = r#" 命令帮助: /start: 显示本消息 /ai 问题: 获取由 Cloudflare Workers AI 驱动的 GPT 答案 PS: 私聊 Bot 可直接对话,无需 /ai 前缀 "#; info!("{}", format!("用户 {} 开始使用本 Bot", msg.chat.id)); let _ = bot.send_message(msg.chat.id, startmessage) .parse_mode(ParseMode::MarkdownV2) .await; } // 私聊检测 async fn matchmsgprivate(msg: Message, bot: Bot) { let text: &str = msg.text().unwrap(); if text.starts_with('/') { // 是否为 "/" 开头的命令 let mut parts = text.splitn(2, ' '); let command: &str = parts.next().unwrap(); // 命令部分 let argument: Option<&str> = parts.next(); // 参数部分,可能为 None if command.starts_with("/ai") { replyai(msg.clone(), bot, argument).await; } else if command.starts_with("/start") { replystart(msg, bot).await; } else { debug!("非本 Bot 命令,跳过"); } } else { replyai(msg.clone(), bot, msg.text()).await; // 非命令直接当作问题 } } // 非私聊 async fn matchmsgpublic(msg: Message, bot: Bot) { let text: &str = msg.text().unwrap(); if text.starts_with('/') { // 是否为 "/" 开头的命令 let mut parts = text.splitn(2, ' '); let command: &str = parts.next().unwrap(); // 命令部分 let argument: Option<&str> = parts.next(); // 参数部分,可能为 None if command.starts_with("/ai") { replyai(msg.clone(), bot, argument).await; } else if command.starts_with("/start") { replystart(msg, bot).await; } else { debug!("非本 Bot 命令,跳过"); } } else { debug!("非命令,跳过"); } }保存后 执行下面指令即可编译运行:cargo build --release ./target/release/RUST总结这次主要是了解了 Rust 的基本语法,更深层次的还尚未触及到,对于代码中解释有误或代码有问题的请多多谅解
2024年06月18日
122 阅读
0 评论
0 点赞
2024-06-06
解决 /usr/bin/xauth: file /.../.Xauthority does not exist 报错
root账户下执行命令:find / |grep ".Xauthority"普通账户下执行命令:find ~ |grep ".Xauthority"找了下原因,没找到,然后我重新登陆,发现,居然可以了。简直就是大无语事件!!!
2024年06月06日
286 阅读
0 评论
0 点赞
2024-06-06
Linux SSH Access denied(拒绝访问)解决方案
新安装的 CentOS 7 使用 SSH 连接出现 Access denied,记录一下这个坑。详细问题如下(见图):解决方案查了下资料,Linux 系统默认就是禁止远程登录的。那就打开权限就行了。因为需要修改系统设置,普通用户会出现没有权限,所以在超级管理员下操作!编辑配置文件:vim /etc/ssh/sshd_config修改 PermitRootLogin 为 yes退出编辑:按下 'Esc' 键,输入 ':wq',回车保存即可。重启 SSH:systemctl restart sshd大功告成,可以使用 ssh 链接了~~
2024年06月06日
205 阅读
0 评论
0 点赞
2024-05-31
植物大战僵尸杂交版v2.0来了!附最新安装教程!
今天来给大家分享最新版的植物大战僵尸杂交版,此版本由B站UP主@潜艇伟伟迷个人制作,光宣传片而论,短短十几天的时间就在B站平台爆火,达到了500w的播放量,甚至引得各大直播平台的知名主播都在闲暇之余畅玩。很多小伙伴想玩却不知道如何下载安装,今天就来教大家详细的安装步骤,感兴趣的小伙伴抓紧跟我一起来看看吧!{lamp/}{mtitle title="植物大战僵尸杂交V2.0.88最新版(安装教程)"/}{lamp/}在网盘下载电脑后,鼠标右键压缩包选择解压到当前文件夹。鼠标右键选择管理员身份运行植物大战僵尸杂交版v2.0.88安装程序。耐心等待安装完成,点击开始使用。{lamp/}{mtitle title="全屏游戏教程"/}{lamp/}回到解压后的文件夹,找到【Magpiev0.5.2】压缩包-右键【magpie】-【解压到当前文件夹】。双击运行magpie程序。按照下面进行选项进行设置。设置完成后,点击【五秒后放大】。注:部分电脑可能出现无法放大报错,原因不明。这款植物大战僵尸杂交版游戏模式创意十足,可玩性相当高,非常容易上头,感兴趣的小伙伴抓紧下载体验吧!好了,本期的分享就到这里我们下期再见!游戏获取{cloud title="植物大战僵尸杂交版v2.0.88安装程序" type="ct" url="https://www.123pan.com/s/shFiVv-UTRKA.html" password="HPhp"/}
2024年05月31日
163 阅读
0 评论
0 点赞
2024-05-28
优选 Cloudflare 官方 / 中转 IP
Cloudflare 官方的 IP 很好理解,就是各个边缘节点的 IP。哪怕在全球大部分地方使用了 Anycast 技术, 但不同 IP 在中国大陆的访问体验还是有很大差别。小站收集了很多使用官方 IP 的网站,我们可以通过 DNS 记录查询的方式得到这些 IP,并通过本地测速或者拨测的方式进行筛选。#来源:https://blog.misaka.rest/2023/08/12/pick-cf-best-domain/ #引用时删去部分无效域名 time.cloudflare.com shopify.com time.is icook.hk icook.tw ip.sb japan.com malaysia.com russia.com singapore.com skk.moe www.visa.com www.visa.com.sg www.visa.com.hk www.visa.com.tw www.visa.co.jp www.visakorea.com www.gco.gov.qa www.gov.se www.gov.ua www.digitalocean.com www.csgo.com www.shopify.com www.whoer.net www.whatismyip.com www.ipget.net www.hugedomains.com www.udacity.com www.4chan.org www.okcupid.com www.glassdoor.com www.udemy.com www.baipiao.eu.org alejandracaiccedo.com log.bpminecraft.com www.boba88slot.com gur.gov.ua www.zsu.gov.ua www.iakeys.com edtunnel-dgp.pages.dev www.d-555.com fbi.gov www.sean-now.com download.yunzhongzhuan.com whatismyipaddress.com www.ipaddress.my www.pcmag.com www.ipchicken.com www.iplocation.net iplocation.io www.who.int www.wto.org #其他选择,都是官方 IP 优选 jp.byun.eu.org un.goasa.top emby2.misakaf.org也有大佬做好了一个优选的结果,可以根据需要即取即用:https://stock.hostmonit.com/CloudFlareYes至于中转 IP,其实就是第二层「反向代理」,通过反代 Cloudflare 边缘节点提供服务。中转 IP 大都是个人自用,获取它们的方法大都是大批量的端口扫描,具体细节这里就不再展开了。也是因此,中转 IP 存活的时间都十分短暂,对于网站加速来说,除非自己拿服务器搭建反向代理,否则几乎没有使用价值。使用方法在域名解析里设置国内运营商线路 CNAME解析 到各个优选地址。
2024年05月28日
490 阅读
1 评论
0 点赞
2024-05-28
公共 DNS 服务器
公共 DNS 服务器 —— 国内腾讯的 DNSPod腾讯旗下的 DNSPod 在 DNS 服务领域近年发展迅速,其提供的公共 DNS 服务可用性非常不错,值得一试。IPv4 地址:119.29.29.29、182.254.116.116、119.28.28.28、182.254.118.118 IPv6 地址:2402:4e00:: DoH 地址:https://doh.pub/dns-query https://1.12.12.12/dns-query https://120.53.53.53/dns-query DoH(国密) 地址:https://sm2.doh.pub/dns-query DoT 地址:dot.pub、1.12.12.12、120.53.53.53阿里云的公共 DNS阿里云作为国内云计算的老大哥,其提供的公共 DNS 几乎是国内上网的首选。选择阿里云的 DNS 大多数时候速度和准确性都是不错的。IPv4 地址:223.5.5.5 或 223.6.6.6 IPv6 地址:2400:3200::1 或 2400:3200:baba::1 DoH 地址:dns.alidns.com DoT 地址:dns.alidns.com牙木网络(电信)牙木网络提供的电信 DNS 服务,具有良好的稳定性和可靠性。IPv4 地址:1.1.8.8、1.1.8.9360DNS360DNS 除了提供稳定的 DNS 服务,还支持 DoH 和 DoT,可以满足用户对于更高安全性的需求。DoH 地址:https://doh.360.cn/dns-query DoT 地址:dot.360.cnCFIEC DNSCFIEC DNS 提供了稳定的 DNS 服务,并支持 DoH 和 DoT,貌似需要纯 ipv6 环境,或者手动设置本地 IP,不然解析不出来。DoH 地址:https://dns.cfiec.net/dns-query DoT 地址:dns.cfiec.net火山引擎 DNS火山引擎 DNS 提供了高效稳定的 DNS 服务。IPv4 地址:180.184.1.1、180.184.2.2CNNIC SDNSCNNIC SDNS 是中国互联网络信息中心提供的公共 DNS 服务,可靠性和安全性都相当不错。IPv4 地址:1.2.4.8、210.2.4.8OneDNSOneDNS 提供拦截版和纯净版的 DNS 服务,满足用户的不同需求。家庭版的 DNS 服务也很实用。IPv4 地址: 117.50.11.11 、52.80.66.66(拦截版) 117.50.10.10 、52.80.52.52(纯净版) 117.50.60.30 、52.80.60.30(家庭版)DNS PAIDNS PAI 提供稳定的 DNS 服务。IPv4 地址:101.226.4.6 、218.30.118.6(电信/移动/铁通) 123.125.81.6 、140.207.198.6(联通)除此之外,还有以下服务器可供选择。#南京信风 114.114.114.114、114.114.115.115(公共版) 114.114.114.119、114.114.115.119(安全版) 114.114.114.110、114.114.115.110(家庭版) #百度 180.76.76.76 2400:da00::6666 #红鱼 https://rubyfish.cn/dns-query #MoeDNS - 无污染的公共DNS服务 #这是一个基于AdGuard Home的公共递归DNS,以专线落地作为解析,并确保数据全程处于中国内地的公共DNS服务。 #DNS 221.131.165.165 36.156.184.156 #DoH https://pdns.itxe.net/dns-query #DoT tls://pdns.itxe.net:853 #DoQ quic://pdns.itxe.net:853公共 DNS 服务器 —— 国外Google Public DNSGoogle 不用多说。IPv4 地址:8.8.8.8 或 8.8.4.4 IPv6 地址:2001:4860:4860::8888 或 2001:4860:4860::8844 DoH 地址:https://dns.google/dns-query DoT 地址:dns.google:853Cloudflare DNS国外老牌DNS,它家CDN很好。IPv4 地址:1.1.1.1 或 1.0.0.1 IPv6 地址:2606:4700:4700::1111 或 2606:4700:4700::1001 DoH 地址:https://cloudflare-dns.com/dns-query DoT 地址:1.1.1.1:853 或 1.0.0.1:853OpenDNSIPv4 地址:208.67.222.222 或 208.67.220.220 DoH 地址:https://doh.opendns.com/DNS.SBIPv4 地址:185.222.222.222 或 45.11.45.11 IPv6 地址:2a09:: 或 2a11:: DoH 地址 :https://doh.dns.sb/dns-query DoT 地址 :dot.sb:853同样,这里也记录其他的 DNS 服务器,不做单独介绍。#quad9 9.9.9.9 149.112.112.112 2620:fe::fe 2620:fe::9 https://dns.quad9.net/dns-query tls://dns.quad9.net #adguard 94.140.14.14 94.140.15.15 2a10:50c0::ad1:ff 2a10:50c0::ad2:ff dns.adguard.com/dns-query #DNS-over-HTTPS dns.adguard.com #DNS-over-TLS quic://dns.adguard.com #DNS-over-QUIC #Tiarap Resolver 自带去广告、隐私优先、提供额外端口 IPv4: 174.138.21.128 / 188.166.206.224 - port 53 or port 5003 IPv6: [2400:6180:0:d0::5f6e:4001] - port 53 or port 5003 dot.tiar.app #DNS-over-TLS怎么使用这些 DNS?(仅 IPv4)Windows通过 【开始】 菜单或者 Windows 搜索来打开控制面板先找【网络和 Internet】 菜单项,然后点击 【网络和共享中心】点击左边侧边栏【更改适配器设置】右键你已经连接网络的网络连接, 选择 【属性】在列表中找到并选择 【Internet 协议版本 4 (TCP/IPv4)】 , 点击 【属性】选择【使用下面的 DNS 服务器地址】 , 然后输入你的 DNS 服务器地址。macOS点击苹果图标,点击进入 [系统偏好设置]点击 [网络] 点击列表中第一个连接选项后,点击 [高级]选择 [DNS] 选项卡。输入你的 DNS 服务器地址。安卓在 Android 主屏幕菜单点击【设置】点击菜单中的 Wi-Fi。 所有可用的网络将会被显示 (移动互联不允许设置自定义 DNS,但可以借助代理软件实现)长按您连接的网络,点击【修改网络】在某些设备上,您点击【高级设置】后,才能看到更多选项。为了调整 Android DNS 设置,您需要把【IP 设置】从【DHCP】 改成【静态】。然后输入你的 DNS 服务器地址。iOS在主界面中点击 【设置】在左侧菜单中选择 【Wi-Fi】(注意:为移动网络无法配置 DNS,但可以借助代理软件实现)点击正在连接的网络在【DNS】一栏输入 DNS 服务器地址即可。Ubuntu点击 “网络图标”(位于右上角默认面板)。点击 “编辑连接” 打开网络连接管理器。找到您的链接类型,加亮突出它并点击 “编辑 “。现在点击 “IPv4 设置” 标签,将 “方式” 选项改为 “自动获取地址”(DHCP)。在 “DNS 服务器 “ 键入用逗号分隔的 DNS 服务器地址路由器打开您的路由器设置。通常可在浏览器中输入 URL(例如 http://192.168.0.1/ 或 http://192.168.1.1/)访问它。可能会要求您输入密码,如您忘记密码,通常可以按路由器上的重置按钮重置密码。某些路由器会有特殊应用程序。在这种情况下,该应用程序要早已安装到您的计算机上。查找 DNS 设置,寻找 “DNS” 字符旁边有可输入二到三个数列的字符串。每个数列分四组,一组包括一到三个数。在此输入 DNS 服务器地址。
2024年05月28日
70 阅读
0 评论
0 点赞
2024-05-28
实战:element-ui 树型控件自定义图标(给节点添加图标)
效果图:<el-input v-model="searchVal" placeholder="请输入关键词" clearable style="margin-bottom: 12px" /> <div class="treeBox"> <el-tree :data="sourceData" node-key="id" default-expand-all :expand-on-click-node="false" :props="defaultProps" @node-click="handleNodeClick" > // 重点:给节点添加图标 <span slot-scope="{ node, data }" class="slot-t-node"> <template> <i :class="{ 'el-icon-folder': !node.expanded, // 节点收缩时的图标 'el-icon-folder-opened': node.expanded, // 节点展开时的图标 'el-icon-user-solid': data.type === 2 // data.type是后端配合提供的识别字段,最后一级 }" style="color: #409eff;" // 图标颜色 /> <span>{{ node.label }}</span> </template> </span> </el-tree> </div>data() { return { searchVal: '', // 输入的关键词 defaultProps: { children: 'childrenList', // 将tree中的每项的 childrenList 映射为 children label: 'name' // 将tree中的每项的 name 映射为 label }, sourceData: [ // 树源数据 { id: null, name: '深圳市XXX有限公司', parentId: '0', childrenList: [ { id: null, name: '研发中心', parentId: '1', childrenList: [ { id: null, name: '研发1组', parentId: '2', childrenList: [ { id: null, name: 'IOS测试机', parentId: null, childrenList: null, type: 2 } ], type: 1 }, { id: null, name: '安卓测试机', parentId: null, childrenList: null, type: 2 } ], type: 1 }, { id: null, name: '产品中心', parentId: '1', childrenList: [], type: 1 }, { id: null, name: '员工1', parentId: null, childrenList: null, type: 2 }, { id: null, name: '员工12', parentId: null, childrenList: null, type: 2 }, { id: null, name: '员工13', parentId: null, childrenList: null, type: 2 } ], type: 1 } ] } }, methods: { // 节点点击时 handleNodeClick(data) { // 。。。 } }
2024年05月28日
28 阅读
0 评论
0 点赞
1
...
4
5
6
...
27