分类
生命在于折腾 聊天

博客服务器又迁移

我现在在兰州

工作需要,整了个服务器,Dell 740xd

我装上了ESXi,这样就能弄好多台虚拟机

宽带

如果服务器要外网更加便捷的访问,就需要拉专线

于是关系之便,拉了一条移动的专线

但是装好后发现有一些问题,上行带宽虽然足够大

而常用端口号则一个都没开,一开始说是要申请

后来打电话没有一个懂的,都以为端口是光猫上的端口

但是也算是有公网IP了

网络结构

这个地方的网络包括移动专线和民用电信,都是走的同一个网关设备

而这个网关设备将会控制不同的设备或者不同的场景走不同的线路

而按照我的设置,所有需要走公网访问的都是以端口映射形式

第一个尝试就是把博客迁移到这台物理服务器上

博客迁移

之前的方案

之前我还没毕业,是将博客放在学生机上,为了备份和安全起见,使用的是腾讯云的TDSQL MySQL

这种方法数据库费用十分高昂,可能隔几天就要充几十块钱

并且维护不方便

本次方案

首先是将文件移到服务器上,设置好域名,并且绑定一个本地端口

然后将端口映射到公网IP的某个端口上

再用CDN绑定域名,使其可以在80/443端口上访问

大致的示意图如下:

遇到的问题

总体来说还是遇到了一些问题,比如说SSL的设置

原本是使用的HTTP源,然后CDN再开放HTTPS

但是WordPress好像不吃这套

后来在服务器这边设置为HTTPS,然后将服务器的443端口映射出去

在CDN设置HTTPS源就好了

分类
生命在于折腾 编程相关

SMSForwarder + Scriptable查看安卓备用机电量和短信

最近换了个备用机K30 Ultra

最开始方案

从一开始我就使用了SMSForwarder

在之前使用小米6作为备用机的时候是用的go-cqhttp机器人,用来转发短信和电量,具体如下:

  • 短信内容转发到我和机器人所在的群内
  • 群名表示手机电量
  • 群头像表示充电状态

后来这个QQ号被封了,我就不再使用QQ机器人

于是我使用了飞书Webhook机器人

Webhook机器人可以用来转发短信内容

但是充电状态和电量无法很好的展示,因为群名和群头像不能更改了

飞书上也没有被动实时展示信息的位置

解决方案

最后我使用了Scriptable用来展示电量和最近几条短信

直接使用小组件在iOS主力机中可以展示安卓备用机的电量和充电状态

也是简单使用JS代码编写,大致的编写方式和Swift UI类似,效果如下:

我也是边学边写的,代码写的很粗糙,也有复制别人的部分,然后具体的安卓系统的某些设定我也不是很懂,但是估计改一下API地址就能直接使用,前两种大小的小组件都能使用

但是好像Scriptable的darkmode的判定有点问题,实际上代码的两种模式适配都是有的,如果Scriptable修复了可以看出来效果

代码如下:

const baseUrl = 'SMSFrowarder的API地址'

const request = new Request('')

const defaultHeaders = {
    'Accept': "application/json",
    "Content-Type": "application/json"
}

const post = async ({ url, body, headers = {} }, callback = () => { }) => {
    body = JSON.stringify(body)
    request.url = url
    request.body = body
    request.method = 'POST'
    request.headers = {
        ...defaultHeaders,
        ...headers
    }
    const data = await request.loadJSON()
    callback(request.response, data)
    return data
}

const get = async ({ url, headers = {} }, callback = () => { }) => {
    request.url = url
    request.method = 'GET'
    request.headers = {
        ...headers,
        ...defaultHeaders
    }
    const data = await request.loadJSON()
    callback(request.response, data)
    return data
}

const provideBatteryIcon = (batteryLevel, charging = false) => {
    if (charging) { return SFSymbol.named("battery.100.bolt").image }

    const batteryWidth = 87
    const batteryHeight = 41

    const draw = new DrawContext()
    draw.opaque = false
    draw.respectScreenScale = true
    draw.size = new Size(batteryWidth, batteryHeight)

    draw.drawImageInRect(SFSymbol.named("battery.0").image, new Rect(0, 0, batteryWidth, batteryHeight))

    const x = batteryWidth * 0.1525
    const y = batteryHeight * 0.247
    const width = batteryWidth * 0.602
    const height = batteryHeight * 0.505

    let level = batteryLevel
    if (level < 0.05) { level = 0.05 }

    const current = width * level
    let radius = height / 6.5
    if (current < (radius * 2)) { radius = current / 2 }

    const barPath = new Path()
    barPath.addRoundedRect(new Rect(x, y, current, height), radius, radius)
    draw.addPath(barPath)
    draw.setFillColor(Color.dynamic(new Color('#262626'), new Color('#dddddd')))
    draw.fillPath()
    return draw.getImage()
}

const getBatteryInfo = async () => {
    return await post({
        url: baseUrl + '/battery/query',
        body: {
            "data": {},
            "timestamp": Date.now(),
            "sign": ""
        }
    }).then(res => {
        return res.data
    })
}

const getSimInfo = async () => {
    return await post({
        url: baseUrl + '/config/query',
        body: {
            "data": {},
            "timestamp": Date.now(),
            "sign": ""
        }
    }).then(res => {
        return res.data
    })
}

const getSmsInfo = async (num) => {
    return await post({
        url: baseUrl + '/sms/query',
        body: {
            "data": {
                "type": 1,
                "page_num": 1,
                "page_size": num
            },
            "timestamp": Date.now(),
            "sign": ""
        }
    }).then(res => {
        return res.data
    })
}


const createWidget = async () => {
    const widget = new ListWidget();
    let nextRefresh = Date.now() + 1000 * 60 * 5;
    widget.refreshAfterDate = new Date(nextRefresh);

    const titleStack = widget.addStack();

    widget.addSpacer()

    titleStack.layoutHorizontally()
    titleStack.centerAlignContent()

    const title = titleStack.addText("额滴圣剑");
    title.font = Font.mediumSystemFont(14)
    title.textColor = Color.blue();

    titleStack.addSpacer()

    const batteryStack = titleStack.addStack();
    batteryStack.layoutHorizontally()
    batteryStack.centerAlignContent()

    const batteryInfo = await getBatteryInfo()
    const batteryLevelVal = batteryInfo.level.split('%')[0]

    const isCharging = batteryInfo.status === '充电中' || batteryInfo.plugged === 'AC'

    const batteryText = batteryStack.addText(`${batteryLevelVal}%`)

    batteryText.font = Font.mediumSystemFont(12)

    if (isCharging) {
        batteryText.textColor = Color.green()
    } else if (batteryLevelVal < 20) {
        batteryText.textColor = Color.red()
    }

    batteryStack.addSpacer(2)

    const batteryIcon = batteryStack.addImage(provideBatteryIcon(batteryLevelVal / 100, isCharging))
    batteryIcon.imageSize = new Size(30, 30)

    const simInfo = await getSimInfo()
    const smsList = await getSmsInfo(3)


    for (let n of smsList) {
        const smsItemStack = widget.addStack();
        smsItemStack.layoutHorizontally()
        smsItemStack.centerAlignContent()

        const title = smsItemStack.addText('发给' + simInfo[`extra_sim${n['sim_id'] + 1}`])
        title.font = Font.mediumSystemFont(11)
        title.textColor = Color.gray()

        smsItemStack.addSpacer()

        const smsItemDateVal = new DateFormatter()
        smsItemDateVal.dateFormat = 'yyyy-MM-dd HH:mm:ss'

        const smsItemDate = smsItemStack.addText(smsItemDateVal.string(new Date(n['date'])))
        smsItemDate.font = Font.systemFont(10)
        smsItemDate.textColor = Color.gray()

        const sms = widget.addText(n.content)

        sms.font = Font.mediumSystemFont(12)
        sms.lineLimit = 2
        widget.addSpacer()
    }

    widget.backgroundColor = Color.dynamic(new Color('#eeeeee'), new Color('#242424'))

    return widget
}

const widget = await createWidget()

if (config.runsInWidget) {
    Script.setWidget(widget)

} else widget.presentMedium()

Script.complete()

引用和参考(fuzhi和zhantie)

https://github.com/mzeryck/Weather-Cal/blob/main/weather-cal-code.js

https://github.com/evilbutcher/Scriptables/blob/master/Env.js