ufw 防火墙常用命令,省的每次都问 Gemini
sudo apt update && sudo apt install -y ufw
sudo ufw allow 22022/tcp sudo ufw allow 2443/udp
sudo ufw default deny incoming sudo ufw default allow outgoing
sudo ufw enable sudo ufw status verbose
sudo apt update && sudo apt install -y ufw
sudo ufw allow 22022/tcp sudo ufw allow 2443/udp
sudo ufw default deny incoming sudo ufw default allow outgoing
sudo ufw enable sudo ufw status verbose
这个门槛低~~仅分享~~
源码地址:
https://github.com/budwk/budmon
功能介绍:
开发缘由:
本脆更新:
反正苹果开发者也花了钱了,ChatGPT 闲着也是闲着,开发个iOS自己用也方便。





外星人(或许不是外星人,是人工智能?)入侵地球,从天空一块块飘下某种金属,天罗地网的铺到地面、河沟,全是金属丝网,人类根本躲不了,然后(我)被网抓起来,他一望周围都是被抓起来的人。(我)被放到某种机器上,意识被抽取到机器人身体里,机器人被放到工厂没日没夜干活,偷懒就被打。然后逃跑的都被抓回来,外星人用那种很长很长的像蛇的东西飞着去勾人,(我)躲进某个建筑里打开一个房间,发现里面还有两个人类工人他们在施工手里刚好有硫磺,碰巧发现外星人怕硫磺,(我)和工人用硫磺战胜外星人,然后男主角(我,机器人)站在空旷地面上,周围还有好多机器人都伫立着。
让 CPT 6-Astra 生成了3D视频: https://www.youtube.com/watch?v=K9nUeWQX874
某知回答: 比起拼音,更糟糕的是半瓶水的英语命名。 我司某消息相关的代码,初期开发的大哥把message拼成了massage,后来接手对该消息进行解析需求的二哥鬼脑一动,把analysis缩写成了anal,于是这一块代码里到处都是anal massage。 你以为这就完了? 往后又来了个根据黑名单筛选的需求,负责的三哥灵机一转,既然按需求来说,黑名单会是个类似字典的结构,那就叫blackdictionary吧,缩写成black dic刚刚好,对就这么干。 现在这个方法叫 anal massage by black dic
iOS:设置->电话->来电阻止与身份识别->实时主叫号码查询
来电时系统通过 Live Caller ID Lookup 用 PIR 查询服务端,把号码身份显示在系统来电界面
利用AI生成DEMO可以跑通,但如果实际应用存在几个问题:
比 Call Directory Extension 插件的好处是不用把庞大的号码库下载到手机上。
本来想用 wordpress 来建站,但是可能AI “太笨了”,制作的主题样式和后台功能总是不满足需求,也可能是 AI对 Wordpress 功能了解不足吧。
然后让 AI 根据设计的前端页面,基于 python3 + ant design 来开发后台,除了权限体系外还有具体的功能:
文章管理、分类管理、标签管理、商城管理(应用商城)、评论管理、广告管理、友链管理、爬虫管理、投诉管理、模型管理、安全记录。
其中文章管理,增加AI写作助手,可根据网址抓取+自动填充文章内容,大模型管理可配置各类API格式模型用于总结网址内容。
爬虫自动分析目标网页结构,分析文章内容自动填充内容并送审。
精选收录全球优质、前沿的人工智能软件,涵盖实用 AI 写作、AI 绘画、编程、音视频及办公等各领域应用
AILOL.xyz(爱乐AI)是一个专业精选的 AI 工具、人工智能应用与 AI 导航分类目录网站。精选收录全球优秀的前沿人工智能软件,助您极速发现实用 AI 利器!
基于 Python FastAPI + SQLite + Ant Design + ZLMediaKit + Jessibuca 实现的简易 ONVIF / RTSP 摄像头监控平台。
https://github.com/budwk/budcam 源码及安装包地址
制作一款 wordpress 6.9 版本下的反垃圾评论插件,插件名称 wizspam,支持根据关键词过滤、IP地址过滤,支持对关键词、IP的管理等功能。
一款功能强大的 WordPress 反垃圾评论插件,支持基于关键词和 IP 地址的智能过滤。
192.168.1.100192.168.1.*192.168.1.0/24PS:有需要的可以评论留下 Email,我会免费发送给你~~
Ondřej Surý 的 PPA 是 Debian/Ubuntu 生态中最权威的 PHP 源,它会第一时间同步 PHP 8.5.x 的稳定版。
<code>sudo apt update
sudo apt install -y software-properties-common
# 添加 PPA 源(如果已添加则会自动跳过)
sudo add-apt-repository ppa:ondrej/php -y
sudo apt update
为了确保你的业务能正常运行,除了安装核心包,还需要安装常用的扩展(以替代 8.0 版本的扩展):
<code># 安装 PHP 8.5 核心、FPM 及常用扩展
sudo apt install -y php8.5 php8.5-cli php8.5-fpm php8.5-common php8.5-mysql \
php8.5-xml php8.5-curl php8.5-mbstring php8.5-zip php8.5-gd php8.5-intl
安装后,系统内会并存多个 PHP 版本。你需要将命令行默认指向 8.5:
<code># 切换 CLI 版本
sudo update-alternatives --set php /usr/bin/php8.5
# 验证版本
php -v
如果你使用的是 Nginx,需要手动修改站点配置文件(通常在 /etc/nginx/sites-enabled/):
fastcgi_pass 这一行。fastcgi_pass unix:/run/php/php8.0-fpm.sock;fastcgi_pass unix:/run/php/php8.5-fpm.sock;sudo nginx -t && sudo systemctl restart nginx确认网站运行无误后,可以删除 PHP 8.0 以节省 磁盘空间:
<code>sudo apt purge php8.0*
sudo apt autoremove -y
背景:2013年比特币兴起的时候,注册了比特币官网账号及钱包,从TB等处买了少量BTC,大概有0.02个吧,当时助记词存在硬盘上,N年来电脑换了好几个,最终由于Thinkpad X1 SSD硬盘挂了(见文章:https://wizzer.cn/archives/3552),导致历史备份文件永久丢失。最近从邮箱中找到了当时钱包的备份文件,wallet.aes.json 但密钥文件使用密码加密了,尝试了一堆常用密码,都不对(不知道当时脑子咋想了,弄那么复杂的密码干啥),于是尝试破解密码。
这个工具主要通过海量的密码词典,进行匹配,看是否有可能匹配的密码组合:
python btcrecover.py --wallet wallet.aes.json --passwordlist weakpass.txt --no-dupchecks
–no-dupchecks 关闭重复猜测检查以节省内存
import itertools
import random
def generate_passwords(base_string, max_length=5):
# 生成所有可能的字符组合,允许任意顺序
base_list = list(base_string)
for length in range(1, max_length + 1):
for combo in itertools.product(base_list, repeat=length):
# 生成大小写的所有组合
for case in itertools.product(*[(char.lower(), char.upper()) for char in combo]):
yield ''.join(case)
def save_to_file(passwords, filename):
with open(filename, 'w') as file:
for password in passwords:
file.write(password + '\n')
if __name__ == "__main__":
base_string = 'abcdefg123456'
max_length = 11 # 可以根据需要调整
passwords = generate_passwords(base_string, max_length)
save_to_file(passwords, 'passwords.txt')
print(f"生成的密码已保存到 passwords.txt")
然而,使用了weakpass网站的上十亿密码组合,依旧没有匹配到我的密码……
尝试用生成密码的方式找回密码中……
<strong>1. 创建凭据文件</strong>
sudo mkdir -p /root/.smbcredentials
sudo bash -c 'echo "username=u" > /root/.smbcredentials/wizzer'
sudo bash -c 'echo "password=p" >> /root/.smbcredentials/wizzer'
sudo chmod 600 /root/.smbcredentials/wizzer
<strong>2. 创建挂载点目录</strong>
sudo mkdir -p /vol2/1000/Photo/wizzer
编辑 /etc/fstab 文件,添加以下内容:
//10.10.10.10/homes/wizzer/Photos/MobileBackup /vol2/1000/Photo/wizzer cifs credentials=/root/.smbcredentials/wizzer,file_mode=0777,dir_mode=0777,uid=1000,gid=1000,forceuid,forcegid,_netdev 0 0
4. 测试配置
sudo mount -a
这样配置后,系统重启时会自动挂载 SMB 共享,无需手动操作。
mkdir tmp
cd tmp
# 解压jar主包
jar xf ../main.jar
# 编译lib文件夹下某子jar依赖包, 生成class文件,使用classpath加载依赖包
javac -cp "../*:." com/budwk/Demo.java
# 将class文件打包到jar包中
jar uf demo.jar com/budwk/Demo.class
# 手动覆盖新的 demo.jar 包
# 不能使用这个更新命令,会导致jar包被二次压缩
# jar uf ../main.jar lib/demo.jar
# 使用0这个参数,将解压文件打包到jar包中
jar cfM0 ../main.jar *
@Column
@ColDefine(customType = "GEOGRAPHY(Point,4326)", adaptor = PsqlPointAdaptor.class)
@ApiModelProperty(description = "坐标")
private String geomPoint;//值格式为"POINT(经度 纬度)"
import net.postgis.jdbc.PGgeometry;
import net.postgis.jdbc.geometry.Point;
import org.nutz.dao.jdbc.ValueAdaptor;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
public class PsqlPointAdaptor implements ValueAdaptor {
@Override
public Object get(ResultSet rs, String colName) throws SQLException {
return rs.getObject(colName);
}
@Override
public void set(PreparedStatement stat, Object obj, int index) throws SQLException{
if (null == obj) {
stat.setNull(index, Types.NULL);
} else {
String pointStr = (String) obj;
Point point = new Point(pointStr);
PGgeometry pgGeometry = new PGgeometry(point);
stat.setObject(index, pgGeometry, Types.OTHER);
}
}
}
<properties>
<postgis-jdbc.version>2024.1.0</postgis-jdbc.version>
</properties>
<dependencies>
<!-- PostGIS扩展类型 -->
<dependency>
<groupId>net.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>${postgis-jdbc.version}</version>
</dependency>
Let`s Encrypt 证书自动获取和部署
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx
sudo systemctl reload nginx
sudo certbot renew --dry-run
1、ArgGIS 按图层分别导出shp
原始没有坐标系,要手动配准:
投影坐标 4524 CGCS2000_3_Degree_GK_Zone_36

2、GeoServer
1)创建工作区
2)数据存储-添加新的数据存储-选择文件夹 Directory of spatial files (shapefiles)
3)图层-添加新的资源-选择要发布的文件-Native Bounding Box 从数据中计算
问题1:只能收到APP在线时推送的消息,离线消息收不到
问题2:一台设备一天只能收到2次消息推送
解决方法:
1、uniapp 要正确获取clientId,并且APP要获取通知权限
bindPushCid() {
var timer = setTimeout(function() {
plus.push.getClientInfoAsync(function(info) {
if (info.clientid) {
// 绑定到后台用户
updateGetuiClientId(info.clientid);
clearInterval(timer);
}
}, function(e) {
console.log(JSON.stringify(e));
})
}, 1000)
},
permissionPush(){
let platform = uni.getSystemInfoSync().platform
if (platform == 'android') {
/* 获取当前手机是否有通知权限 */
// let main = plus.android.runtimeMainActivity();
// let pkName = main.getPackageName();
// console.log("是否有通知权限pkName",pkName);
// let NotificationManagerCompat = plus.android.importClass("android.support.v4.app.NotificationManagerCompat");
// console.log("是否有通知权限NotificationManagerCompat",NotificationManagerCompat);
// let packageNames = NotificationManagerCompat.from(main);
var main = plus.android.runtimeMainActivity();
var NotificationManagerCompat = plus.android.importClass("androidx.core.app.NotificationManagerCompat");
let packageNames = NotificationManagerCompat.from(main);
let pkName = main.getPackageName();
if (!packageNames.areNotificationsEnabled()) { //手机没有开启通知的权限
uni.showModal({
title: '通知权限',
content: '通知权限暂未开启',
cancelText: '暂不开启',
confirmText: '前往开启',
success: function (res) {
if (res.confirm) {
let uid = main.getApplicationInfo().plusGetAttribute("uid");
let Intent = plus.android.importClass('android.content.Intent');
let Build = plus.android.importClass("android.os.Build");
let intent = '';
//android 8.0引导
if (Build.VERSION.SDK_INT >= 26) {
intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
intent.putExtra('android.provider.extra.APP_PACKAGE', pkName);
} else if (Build.VERSION.SDK_INT >= 21) { //android 5.0-7.0
intent = new Intent('android.settings.APP_NOTIFICATION_SETTINGS');
intent.putExtra("app_package", pkName);
intent.putExtra("app_uid", uid);
} else { //(<21)其他--跳转到该应用管理的详情页
let Settings = plus.android.importClass("android.provider.Settings");
let Uri = plus.android.importClass("android.net.Uri");
intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
let uri = Uri.fromParts("package", main.getPackageName(), null);
intent.setData(uri);
}
// 跳转到该应用的系统通知设置页
main.startActivity(intent);
} else if (res.cancel) {
console.log('用户点击取消');
}
},
fail: () => {},
complete: () => {}
});
}
}
}
2、华为开发者后台,申请“自分类权益”,以便解除通知条数限制,现在申请很简单,提交示例和截图,系统直接审核通过

3、厂家参数要注意细节
因为importance和category参数,调试很久
Map<String, Map<String, Object>> options = new HashMap<>();
Map<String, Object> oop = new HashMap<>();
oop.put("/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
oop.put("/message/android/notification/badge/add_num", 1);
oop.put("/message/android/notification/importance", "NORMAL");
oop.put("/message/android/category", "WORK");
options.put("HW", oop);
ups.setOptions(options);
4、服务端完整代码
package com.budwk.app;
import com.getui.push.v2.sdk.ApiHelper;
import com.getui.push.v2.sdk.GtApiConfiguration;
import com.getui.push.v2.sdk.api.PushApi;
import com.getui.push.v2.sdk.common.ApiResult;
import com.getui.push.v2.sdk.dto.CommonEnum;
import com.getui.push.v2.sdk.dto.req.Audience;
import com.getui.push.v2.sdk.dto.req.AudienceDTO;
import com.getui.push.v2.sdk.dto.req.message.PushChannel;
import com.getui.push.v2.sdk.dto.req.message.PushDTO;
import com.getui.push.v2.sdk.dto.req.message.PushMessage;
import com.getui.push.v2.sdk.dto.req.message.android.AndroidDTO;
import com.getui.push.v2.sdk.dto.req.message.android.GTNotification;
import com.getui.push.v2.sdk.dto.req.message.android.ThirdNotification;
import com.getui.push.v2.sdk.dto.req.message.android.Ups;
import com.getui.push.v2.sdk.dto.req.message.harmony.HarmonyDTO;
import com.getui.push.v2.sdk.dto.req.message.harmony.HarmonyNotification;
import com.getui.push.v2.sdk.dto.res.TaskIdDTO;
import com.gexin.rp.sdk.base.IPushResult;
import com.gexin.rp.sdk.base.impl.AppMessage;
import com.gexin.rp.sdk.base.impl.ListMessage;
import com.gexin.rp.sdk.base.impl.SingleMessage;
import com.gexin.rp.sdk.base.impl.Target;
import com.gexin.rp.sdk.exceptions.RequestException;
import com.gexin.rp.sdk.http.IGtPush;
import com.gexin.rp.sdk.template.*;
import com.gexin.rp.sdk.template.style.Style0;
import lombok.extern.slf4j.Slf4j;
import org.nutz.json.Json;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
public class GeTuiUtil {
private static String appId;
private static String appKey;
private static String masterSecret;
private static String host;
private static Long OfflineExpireTime;
private static String logo;
private static boolean isRing;
private static boolean isVibrate;
private static boolean isClearable;
private static int transmissionType;
private static PushApi pushApi;
// 初始化个推的系统app参数
static {
appId = "";
appKey = "";
masterSecret = "";
host = "http://sdk.open.api.igexin.com/apiex.htm";
OfflineExpireTime = 259200000L;
logo = "icon.png";
isRing = true;
isVibrate = true;
isClearable =true;
transmissionType = 1;
System.setProperty("http.maxConnections", "200");
GtApiConfiguration apiConfiguration = new GtApiConfiguration();
//填写应用配置
apiConfiguration.setAppId(appId);
apiConfiguration.setAppKey(appKey);
apiConfiguration.setMasterSecret(masterSecret);
// 接口调用前缀,请查看文档: 接口调用规范 -> 接口前缀
apiConfiguration.setDomain("https://restapi.getui.com/v2/");
// 实例化ApiHelper对象,用于创建接口对象
ApiHelper apiHelper = ApiHelper.build(apiConfiguration);
// 创建对象,建议复用。目前有PushApi、StatisticApi、UserApi
pushApi = apiHelper.creatApi(PushApi.class);
}
public static Map<String, Object> sendSingleNew(String title, String content, String cid) {
PushDTO<Audience> pushDTO = new PushDTO<Audience>();
pushDTO.setRequestId(System.currentTimeMillis() + "");
buildPushMessage(title, content, pushDTO);
Audience audience = new Audience();
pushDTO.setAudience(audience);
audience.addCid(cid);
ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushToSingleByCid(pushDTO);
log.info("sendSingleNew result :" + Json.toJson(apiResult));
Map<String, Object> result = new HashMap<>();
result.put("code", apiResult.getCode());
if (apiResult.isSuccess()) {
result.put("data", apiResult.getData());
} else {
result.put("msg", apiResult.getMsg());
}
return result;
}
public static void main(String[] args) {
String title = "你有新的待办任务";
String content = "任务内容:测" + System.currentTimeMillis();
String cid = "77336b3d6d136da0cf56e288a7462949";
Map<String, Object> stringObjectMap = sendSingleNew(title, content, cid);
// List<String> cids = new ArrayList<>();
// cids.add(cid);
// Map<String, Object> stringObjectMap = sendBatchNew(title, content, cids);
// Map<String, Object> stringObjectMap = sendAllClientNew(title, content);
//
}
private static PushMessage buildPushMessage(String title, String content, PushDTO pushDTO) {
PushMessage pushMessage = new PushMessage();
pushDTO.setPushMessage(pushMessage);
GTNotification notification = new GTNotification();
pushMessage.setNotification(notification);
notification.setTitle(title);
notification.setBody(content);
notification.setBadgeAddNum("1");
notification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);
notification.setSlotType("2");
notification.setCategory("CATEGORY_REMINDER");
PushChannel pushChannel = new PushChannel();
pushDTO.setPushChannel(pushChannel);
AndroidDTO androidDTO = new AndroidDTO();
pushChannel.setAndroid(androidDTO);
Ups ups = new Ups();
androidDTO.setUps(ups);
ThirdNotification thirdNotification = new ThirdNotification();
ups.setNotification(thirdNotification);
thirdNotification.setTitle(title);
thirdNotification.setBody(content);
thirdNotification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);
Map<String, Map<String, Object>> options = new HashMap<>();
Map<String, Object> oop = new HashMap<>();
oop.put("/message/android/notification/badge/class", "io.dcloud.PandoraEntry");
oop.put("/message/android/notification/badge/add_num", 1);
oop.put("/message/android/notification/importance", "NORMAL");
oop.put("/message/android/category", "WORK");
options.put("HW", oop);
ups.setOptions(options);
HarmonyDTO harmonyDTO = new HarmonyDTO();
pushChannel.setHarmony(harmonyDTO);
HarmonyNotification harmonyNotification = new HarmonyNotification();
harmonyDTO.setNotification(harmonyNotification);
harmonyNotification.setTitle(title);
harmonyNotification.setBody(content);
harmonyNotification.setCategory("CATEGORY_REMINDER");
harmonyNotification.setClickType(CommonEnum.ClickTypeEnum.TYPE_STARTAPP.type);
return pushMessage;
}
private static Map<String, Object> send(AbstractTemplate template, List<String> cids) {
if (cids == null || cids.size() == 0) {
// 给appId下所有人发
return sendAllClient(template);
}
if (cids.size() == 1) {
// 单发
Map<String, Object> result = sendSingle(template, cids.get(0));
return result;
} else {
// 群发
Map<String, Object> result = sendBatch(template, cids);
return result;
}
}
private static Map<String, Object> sendNew(String title, String content, List<String> cids) {
log.info("进入推送信息:" + title);
if (cids == null || cids.size() == 0) {
// 给appId下所有人发
Map<String, Object> stringObjectMap = sendAllClientNew(title, content);
log.info("APP群推发送返回结果:" + Json.toJson(stringObjectMap));
return stringObjectMap;
}
if (cids.size() == 1) {
// 单发
Map<String, Object> result = sendSingleNew(title, content, cids.get(0));
log.info("单推发送返回结果:" + Json.toJson(result));
return result;
} else {
// 群发
Map<String, Object> result = sendBatchNew(title, content, cids);
log.info("群推发送返回结果:" + Json.toJson(result));
return result;
}
}
/**
* @Description 发送通知模板消息
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param title:消息标题
* @Param content:消息内容
* @Param cids: 1、null或size==0:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return map类型, 可能为null,例如:"{result=ok, contentId=OSL-0424_y2LxEeM6hvA0yhTqa77qw4,
* details={"c85fa1218fe4c54652a77bef22726fb0":"TokenMD5Error",
* "a5800ff27659a5258b8ba86e4e1d7c87":"successed_online"
* }
* }"
* result==ok,发送成功,details里面是每个cid对应的发送结果,包含successed表示成功,其他失败
*/
public static Map<String, Object> sendNotification(String title, String content, List<String> cids) {
NotificationTemplate template = buildNotificationTemplate(title, content);
return send(template, cids);
}
public static Map<String, Object> sendNotificationNew(String title, String content, List<String> cids) {
return sendNew(title, content, cids);
}
/**
* @param
* @param template
* @param msgItem
* @return
* @throws
* @author daitao
* @version 1.0
* @description 个推单发
* @date 2019/4/12
**/
private static Map<String, Object> sendSingle(AbstractTemplate template, String cid) {
IGtPush push = new IGtPush(host, appKey, masterSecret);
SingleMessage message = new SingleMessage();
message.setOffline(true);
// 离线有效时间,单位为毫秒,可选
message.setOfflineExpireTime(OfflineExpireTime);
message.setData(template);
// 可选,1为wifi,0为不限制网络环境。根据手机处于的网络情况,决定是否下发
message.setPushNetWorkType(0);
Target target = new Target();
target.setAppId(appId);
target.setClientId(cid);
IPushResult ret;
try {
ret = push.pushMessageToSingle(message, target);
} catch (RequestException e) {
e.printStackTrace();
ret = push.pushMessageToSingle(message, target, e.getRequestId());
}
return ret.getResponse();
}
/**
* @param
* @param template
* @param msgItem
* @return
* @throws
* @author daitao
* @version 1.0
* @description 个推单发
* @date 2019/4/12
**/
private static Map<String, Object> sendBatch(AbstractTemplate template, List<String> cids) {
// 配置返回每个用户返回用户状态,可选
System.setProperty("gexin_pushList_needDetails", "true");
IGtPush push = new IGtPush(host, appKey, masterSecret);
// 通知透传模板
ListMessage message = new ListMessage();
message.setData(template);
// 设置消息离线,并设置离线时间
message.setOffline(true);
// 离线有效时间,单位为毫秒,可选
message.setOfflineExpireTime(OfflineExpireTime);
// taskId用于在推送时去查找对应的message
String taskId = push.getContentId(message);
List<Target> targets = handleTargets(cids);
IPushResult ret = push.pushMessageToList(taskId, targets);
return ret.getResponse();
}
private static Map<String, Object> sendBatchNew(String title, String content, List<String> cids) {
Map<String, Object> result = new HashMap<>();
PushDTO<String> pushDTO = new PushDTO<String>();
pushDTO.setRequestId(System.currentTimeMillis() + "");
buildPushMessage(title, content, pushDTO);
ApiResult<TaskIdDTO> createResult = pushApi.createMsg(pushDTO);
log.info("sendBatchNew createResult :" + Json.toJson(createResult));
result.put("code", createResult.getCode());
if (createResult.isSuccess()) {
result.put("data", createResult.getData());
TaskIdDTO taskIdDTO = createResult.getData();
AudienceDTO pushBatchDTO = new AudienceDTO();
pushBatchDTO.setTaskid(taskIdDTO.getTaskId());
Audience audience = new Audience();
audience.setCid(cids);
pushBatchDTO.setAudience(audience);
ApiResult<Map<String, Map<String, String>>> apiResult = pushApi.pushListByCid(pushBatchDTO);
log.info("sendBatchNew apiResult :" + Json.toJson(apiResult));
result.put("code", apiResult.getCode());
if (apiResult.isSuccess()) {
result.put("data", apiResult.getData());
} else {
result.put("msg", apiResult.getMsg());
}
} else {
result.put("msg", createResult.getMsg());
}
return result;
}
private static List<Target> handleTargets(List<String> cids) {
List<Target> targets = new ArrayList<>();
for (String cid : cids) {
Target target = new Target();
target.setAppId(appId);
target.setClientId(cid);
targets.add(target);
}
return targets;
}
private static NotificationTemplate buildNotificationTemplate(String title, String content) {
NotificationTemplate template = new NotificationTemplate();
// 设置APPID与APPKEY
template.setAppId(appId);
template.setAppkey(appKey);
template.setTransmissionType(transmissionType);
Style0 style = new Style0();
// 设置通知栏标题与内容
style.setTitle(title);
style.setText(content);
// 配置通知栏图标
style.setLogo(logo);
// 配置通知栏网络图标
style.setLogoUrl("");
// 设置通知是否响铃,震动,或者可清除
style.setRing(isRing);
style.setVibrate(isVibrate);
style.setClearable(isClearable);
template.setStyle(style);
return template;
}
/**
* @Description
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param cids: 1、null或size==0:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return
* @Exception
*/
public static Map<String, Object> sendLinkTemplate(String title, String content, String openUrl, List<String> cids) {
LinkTemplate template = buildLinkTemplate(title, content, openUrl);
return send(template, cids);
}
private static LinkTemplate buildLinkTemplate(String title, String content, String openUrl) {
LinkTemplate template = new LinkTemplate();
// 设置APPID与APPKEY
template.setAppId(appId);
template.setAppkey(appKey);
Style0 style = new Style0();
// 设置通知栏标题与内容
style.setTitle(title);
style.setText(content);
// 配置通知栏图标
style.setLogo(logo);
// 配置通知栏网络图标
style.setLogoUrl("");
// 设置通知是否响铃,震动,或者可清除
style.setRing(isRing);
style.setVibrate(isVibrate);
style.setClearable(isClearable);
template.setStyle(style);
// 设置打开的网址地址
template.setUrl(openUrl);
return template;
}
/**
* @Description
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param cids: 1、null:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return
* @Exception
*/
public static Map<String, Object> sendNotyPopLoadTemplate(String title, String content,
String popTitle, String popContent, String downloadTitle, String downloadIcon, String downloadUrl, List<String> cids) {
NotyPopLoadTemplate template = buildNotyPopLoadTemplate(title, content, popTitle, popContent, downloadTitle, downloadIcon, downloadUrl);
return send(template, cids);
}
/**
* @param title 消息标题
* @param content 消息内容
* @param popTitle 弹框标题
* @param popContent 弹框内容
* @param downloadTitle 下载标题
* @param downloadIcon 下载图标
* @param downloadUrl 下载的url资源地址
* @return
*/
private static NotyPopLoadTemplate buildNotyPopLoadTemplate(String title, String content,
String popTitle, String popContent, String downloadTitle, String downloadIcon, String downloadUrl
) {
NotyPopLoadTemplate template = new NotyPopLoadTemplate();
// 设置APPID与APPKEY
template.setAppId(appId);
template.setAppkey(appKey);
Style0 style = new Style0();
// 设置通知栏标题与内容
style.setTitle(title);
style.setText(content);
// 配置通知栏图标
style.setLogo(logo);
// 配置通知栏网络图标
style.setLogoUrl("");
// 设置通知是否响铃,震动,或者可清除
style.setRing(isRing);
style.setVibrate(isVibrate);
style.setClearable(isClearable);
template.setStyle(style);
// 设置弹框标题与内容
template.setPopTitle(popTitle);
template.setPopContent(popContent);
// 设置弹框显示的图片
template.setPopImage("");
template.setPopButton1("下载");
template.setPopButton2("取消");
// 设置下载标题
template.setLoadTitle(downloadTitle);
template.setLoadIcon(downloadIcon);
//设置下载地址
template.setLoadUrl(downloadUrl);
return template;
}
/**
* @Description
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param cids: 1、null:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return
* @Exception
*/
public static Map<String, Object> sendTransmissionTemplate(String title, String content, List<String> cids) {
TransmissionTemplate template = buildTransmissionTemplate(title, content);
return send(template, cids);
}
/**
* 安卓推送透传消息模板
*
* @param title
* @param content
* @return
*/
private static TransmissionTemplate buildTransmissionTemplate(String title, String content) {
TransmissionTemplate template = new TransmissionTemplate();
template.setAppId(appId);
template.setAppkey(appKey);
// 透传消息设置,1为强制启动应用,客户端接收到消息后就会立即启动应用;2为等待应用启动
template.setTransmissionType(transmissionType);
template.setTransmissionContent(content);
return template;
}
/**
* @param oldTaskId 指定需要撤回消息对应的taskId
* @param force 客户端没有找到对应的taskid,是否把对应appid下所有的通知都撤回
* @Description
* @Author daitao
* @version 1.0
* @Date 2019/4/24 17:57
* @Param cids: 1、null:表示给appId下所有人发
* 2、size为1:单发
* 3、size大于1:群发
* @Return
* @Exception
*/
public static Map<String, Object> sendRevokeTemplate(String oldTaskId, boolean force, List<String> cids) {
RevokeTemplate template = getRevokeTemplate(oldTaskId, force);
return send(template, cids);
}
/**
* 获取撤回模板
*
* @param oldTaskId 指定需要撤回消息对应的taskId
* @param force 客户端没有找到对应的taskid,是否把对应appid下所有的通知都撤回
* @return
*/
private static RevokeTemplate getRevokeTemplate(String oldTaskId, boolean force) {
RevokeTemplate template = new RevokeTemplate();
template.setAppId(appId);// 应用appid
template.setAppkey(appKey);// 应用appkey
template.setOldTaskId(oldTaskId);
return template;
}
/**
* 发个应用的所有客户端
*
* @param template
* @return
*/
private static Map<String, Object> sendAllClient(AbstractTemplate template) {
IGtPush push = new IGtPush(host, appKey, masterSecret);
// 定义"点击链接打开通知模板",并设置标题、内容、链接
List<String> appIds = new ArrayList<String>();
appIds.add(appId);
// 定义"AppMessage"类型消息对象,设置消息内容模板、发送的目标App列表、是否支持离线发送、以及离线消息有效期(单位毫秒)
AppMessage message = new AppMessage();
message.setData(template);
message.setAppIdList(appIds);
message.setOffline(true);
message.setOfflineExpireTime(OfflineExpireTime);
IPushResult ret = push.pushMessageToApp(message);
return ret.getResponse();
}
private static Map<String, Object> sendAllClientNew(String title, String content) {
PushDTO<String> pushDTO = new PushDTO<String>();
pushDTO.setRequestId(System.currentTimeMillis() + "");
pushDTO.setAudience("all");
buildPushMessage(title, content, pushDTO);
ApiResult<TaskIdDTO> apiResult = pushApi.pushAll(pushDTO);
Map<String, Object> result = new HashMap<>();
log.info("sendAllClientNew result :" + Json.toJson(apiResult));
result.put("code", apiResult.getCode());
if (apiResult.isSuccess()) {
result.put("data", apiResult.getData());
} else {
result.put("msg", apiResult.getMsg());
}
return result;
}
}
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!--个推-->
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-sdk-http</artifactId>
<version>4.1.0.1</version>
</dependency>
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-sdk-base</artifactId>
<version>4.0.0.26</version>
</dependency>
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-sdk-template</artifactId>
<version>4.0.0.20</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.gexin.platform/gexin-rp-fastjson -->
<!-- https://mvnrepository.com/artifact/com.getui.push/restful-sdk -->
<dependency>
<groupId>com.getui.push</groupId>
<artifactId>restful-sdk</artifactId>
<version>1.0.6.0</version>
</dependency>
<dependency>
<groupId>com.gexin.platform</groupId>
<artifactId>gexin-rp-fastjson</artifactId>
<version>1.0.0.1</version>
</dependency>
仓库
<repository>
<id>getui</id>
<url>http://mvn.gt.getui.com/nexus/content/repositories/releases/</url>
</repository>
以下以Nutz代码为例:
Header header = Header.create();
header.addv("Content-Type", "application/json");
header.addv("AppCode", appcode);
Request request = Request.create(url, Request.METHOD.POST);
NutMap body = NutMap.NEW();
body.put("kssj", kssj);
body.put("jssj", jssj);
request.setHeader(header);
request.setData(Json.toJson(body));
Sender sender = Sender.create(request).setTimeout(30 * 1000);
if (url.startsWith("https")) {
try {
SSLContext sslcontext = this.createIgnoreVerifySSL();
sender.setSSLSocketFactory(sslcontext.getSocketFactory());
sender.setHostnameVerifier((urlHostName, session) -> true);
} catch (Exception e) {
e.printStackTrace();
}
}
Response response = sender.send();
if (response.isOK()) {
//todo
}
private static class TrustAllManager
implements X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkServerTrusted(X509Certificate[] certs,
String authType) {
}
public void checkClientTrusted(X509Certificate[] certs,
String authType) {
}
}
public SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new CityLifelineServer.TrustAllManager()}, null);
return sc;
}
ALTER USER 'root'@'%' IDENTIFIED BY 'pwd' PASSWORD EXPIRE NEVER;
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd';
FLUSH PRIVILEGES;
pve 8.2
1、第一步,升级pve内核到最新
1)设置dns,让源域名可以解析
2)设置国内源
#编辑 Debian sources.list 源文件,写入国内源
nano /etc/apt/sources.list
# 内容如下:
deb https://mirrors.ustc.edu.cn/debian/ bookworm main contrib
deb-src https://mirrors.ustc.edu.cn/debian/ bookworm main contribe
deb https://mirrors.ustc.edu.cn/debian/ bookworm-updates main contrib
deb-src https://mirrors.ustc.edu.cn/debian/ bookworm-updates main contrib
# 编辑 PVE 源文件 pve-no-subscription.list
nano /etc/apt/sources.list.d/pve-no-subscription.list
# 内容如下:
deb https://mirrors.tuna.tsinghua.edu.cn/proxmox/debian bookworm pve-no-subscription
# 编辑屏蔽 PVE 企业源文件
nano /etc/apt/sources.list.d/pve-enterprise.list
# 将下面这一行注释掉 (前面加上井号)
# deb https://mirrors.tuna.tsinghua.edu.cn/proxmox/debian bookworm pve-no-subscription
3)升级内核
数据中心 – pve 节点 – 更新 – 升级
升级结束重启
2、第二步,虚拟机先安装系统
正常的虚拟机配置(默认配置),安装好飞牛OS系统。
BIOS选择 OVMF(UEFI)
BIOS 关闭 Secure Boot
处理器类型选择 host
显卡 默认
机型 默认
3、第三步,设置显卡直通
1)虚拟机停机,如果pve控制台停机不了,则网页进入飞牛系统关机。
pve节点配置参数
nano /etc/pve/qemu-server/101.conf
args%3A -set device.hostpci0.addr=02.0
飞牛os虚拟机设置:
2)显卡 选择 无
3)机型 选择 q35
5)添加PCI设备,选择原始设备 0000:00:02.0,勾选所有功能,主GPU、PCI-Express 不要勾选。
6)启动虚拟机,飞牛OS设置中查看是否显示GPU,影视播放启用硬解,并播放其他分辨率查看GPU占用情况。
ps:不同主机的GPU编号可能不同,比如 0000:00:02.0 ,device.hostpci0.addr=02.0