Mix-Space云函数备忘

2024 年 8 月 17 日 星期六(已编辑)
/ ,
153
2
AI 生成的摘要
云函数是 Mix Space 中的一个重要功能,它极大地辅助了使用者在 Mix Space 中的体验。通过云函数,Mix Space 可以额外实现实现歌单解析,追番列表等等的功能。
这篇文章上次修改于 2024 年 11 月 3 日 星期日,可能部分内容已经不适用,如有疑问可询问作者。

Mix-Space云函数备忘

云函数是 Mix Space 中的一个重要功能,它极大地辅助了使用者在 Mix Space 中的体验。通过云函数,Mix Space 可以额外实现实现歌单解析,追番列表等等的功能。

建议食用官方文档 https://mx-space.js.org/usage 本篇仅作参考

快速导入

具体配置需要一个一个修改,最多免去了创建过程。

Shiro主题

主题配置

这个是我当前配置 ,仅供参考,根据需要更改

Mix-Space 后台,进入「配置与云函数」页面,点击右上角的新增按钮,在编辑页面中,填入以下设置:

  • 名称:shiro
  • 引用:theme
  • 数据类型:JSON

    {
    # 站点底部相关信息
    "footer": { 
      "otherInfo": {
        "date": "2022-{{now}}",
        "icp": {
          "text": "豫 ICP 备 2022029096号-2",
          "link": "https://beian.miit.gov.cn"
        }
      },
      "linkSections": [
        {
          "name": "😊关于",
          "links": [
            {
              "name": "关于我",
              "href": "/about"
            },
            {
              "name": "关于此项目",
              "href": "https://github.com/innei/Shiro",
              "external": true
            }
          ]
        },
        {
          "name": "🧐更多",
          "links": [
            {
              "name": "时间线",
              "href": "/timeline"
            },
            {
              "name": "友链",
              "href": "/friends"
            },
            {
              "name": "思考",
              "href": "/thinking",
              "external": true
            }
          ]
        },
        {
          "name": "🤗联系",
          "links": [
            {
              "name": "写留言",
              "href": "/message"
            },
            {
              "name": "发邮件",
              "href": "mailto:i@vlo.cc",
              "external": true
            },
            {
              "name": "GitHub",
              "href": "https://github.com/jiuyue52",
              "external": true
            }
          ]
        }
      ]
    },
    "config": {
      "color": {
        "light": [
          "#33A6B8",
          "#FF6666",
          "#26A69A",
          "#fb7287",
          "#69a6cc",
          "#F11A7B",
          "#78C1F3",
          "#FF6666",
          "#7ACDF6"
        ],
        "dark": [
          "#F596AA",
          "#A0A7D4",
          "#ff7b7b",
          "#99D8CF",
          "#838BC6",
          "#FFE5AD",
          "#9BE8D8",
          "#A1CCD1",
          "#EAAEBA"
        ]
      },
      "custom": {
        "css": [],
        "styles": [],
        "js": [],
        "scripts": []
      },
       # 站点图标
      "site": {
        "favicon": "https://mio.vlo.cc/resource/image/J99Y.svg",
        "faviconDark": "https://mio.vlo.cc/resource/image/J99Y.svg"
      },
      "hero": {
        "title": {
          "template": [
            {
              "type": "h1",
              "text": "Hi, I'm ",
              "class": "font-light text-4xl"
            },
            {
              "type": "h1",
              "text": "JiuYue",
              "class": "font-medium mx-2 text-4xl"
            },
            {
              "type": "h1",
              "text": "👋。",
              "class": "font-light text-4xl"
            },
            {
              "type": "br"
            },
            {
              "type": "h1",
              "text": "语言是思想的直接的现实",
              "class": "font-light text-4xl"
            },
            {
              "type": "code",
              "text": "<Developer />",
              "class": "font-medium mx-2 text-3xl rounded p-1 bg-gray-200 dark:bg-gray-800/0 hover:dark:bg-gray-800/100 bg-opacity-0 hover:bg-opacity-100 transition-background duration-200"
            },
            {
              "type": "span",
              "class": "inline-block w-[1px] h-8 -bottom-2 relative bg-gray-800/80 dark:bg-gray-200/80 opacity-0 group-hover:opacity-100 transition-opacity duration-200 group-hover:animation-blink"
            }
          ]
        },
        # hitokoto闭源专属,首页随机一言
        "hitokoto": {
          "random": true
        },
        "description": "内心湛然,则无往而不乐。"
      },
      "module": { 
        # 我的动态
        "activity": { 
          "enable": true,
          "endpoint": "/fn/ps/update"
        },
        # 打赏地址及收款二维码
        "donate": {
          "enable": true, 
          "link": "https://afdian.net/@huasui",
          "qrcode": [
            "https://mio.vlo.cc/image/2408/66b853da25ce7.webp",
            "https://mio.vlo.cc/image/2408/66b853da25ce7.webp"
          ]
        },
        # b站直播间房间号,获取直播状态
        "bilibili": { 
          "liveId": 23359061 
        },
        # svg签名动画,shiroi闭源版专属
        "signature": { 
          "svg": ""  
        }
      }
    }
    }

    我的动态

    需要在主题配置中配置我的动态模块

    新建云函数

  • 名称:update
  • 引用:ps
  • 数据类型:Function
  • 请求方式:POST

这个地方还需要设置一个密钥,在 Secret 中填入 key,在 Value 中填入你自己的密钥。

export default async function handler(ctx: Context) {
  const {
    timestamp,
    process: processName,
    key,
    media,
    meta,
  } = ctx.req.body || {}
  // handle GET
  {
    const [processInfo, mediaInfo] = await Promise.all([
      ctx.storage.cache.get('ps') as any as Promise<Process | undefined>,
      ctx.storage.cache.get('media') as any as Promise<Media | undefined>,
    ])
    if (!key) {
      return {
        processName: processInfo?.name,
        processInfo,
        mediaInfo,
      }
    }
  }

  const ts = +new Date()
  // if (Math.abs(ts - timestamp) > 1000 * 10) {
  //   ctx.throws(400, 'this request is outdate')
  //   return
  // }

  const processInfo: Process = {
    name: processName,
    ...meta,
  }

  const validKey = (await ctx.secret.key) || 'testing'
  if (key != validKey)
    ctx.throws(401, "You haven't permission to update process info")

  const originalPsInfo: Process | null = (await ctx.storage.cache.get(
    'ps',
  )) as any
  await ctx.storage.cache.set('ps', processInfo, 300)

  if (originalPsInfo?.name !== processName)
    ctx?.broadcast?.('ps-update', {
      processInfo,
      process: processInfo.name,
      ts,
    })
  if (media) {
    await ctx.storage.cache.set('media', media, 10)
  }

  const mediaInfo: Media | undefined = (await ctx.storage.cache.get(
    'media',
  )) as any
  if (mediaInfo?.title !== media?.title)
    ctx?.broadcast?.('media-update', media || null)

  return {
    ok: 1,
    mediaInfo,
    process: processInfo.name,
    processInfo,
    timestamp: +new Date(),
  }
}

interface Media {
  title: string
  artist: string
}

interface Process {
  name: string
  iconBase64?: string
  iconUrl?: string
  description?: string
}

另外需要下载对应平台的状态上报软件
参考官方文档: https://mx-space.js.org/themes/shiro/extra#配置软件

个人状态(闭源专属)

新建云函数

  • 名称:status
  • 引用:shiro
  • 数据类型:Function
  • 请求方式:ALL

这个地方还需要设置一个密钥,在 Secret 中填入 key,在 Value 中填入你自己的密钥。

interface Status {
  emoji: string
  icon?: string
  desc?: string
  ttl: number
  untilAt: number
}

function assetAuth(ctx: Context) {
  const body = ctx.req.body
  const authKey = ctx.secret.key
  if (ctx.isAuthenticated) return
  if (body.key !== authKey) {
    ctx.throws(401, 'Unauthorized')
  }
}
export default async function handler(ctx: Context) {
  const method = ctx.req.method.toLowerCase()

  switch (method) {
    case 'get': {
      return GET(ctx)
    }
    case 'post': {
      assetAuth(ctx)
      return POST(ctx)
    }
    case 'delete': {
      assetAuth(ctx)
      return DELETE(ctx)
    }
    default: {
      ctx.throws(405, 'Method Not Allowed')
    }
  }
}

const cacheKey = 'shiro:status'

function DELETE(ctx: Context) {
  ctx.storage.cache.del(cacheKey)
  ctx.broadcast('shiro#status', null)
}
function POST(ctx: Context) {
  const body = ctx.req.body

  const { emoji, icon, desc } = body as Status
  const ttl = body.ttl || 86400 // 1 day

  const status = {
    emoji,
    icon,
    desc,
    ttl,
    untilAt: Date.now() + ttl * 1000,
  } as Status
  ctx.storage.cache.set(cacheKey, JSON.stringify(status), ttl)
  ctx.status(204)

  ctx.broadcast('shiro#status', status)
}

function GET(ctx: Context) {
  const status = ctx.storage.cache.get(cacheKey)
  ctx.res.type('application/json')
  return status
}

设置状态,前端首页->双击左上角头像->登录,点击左上角头像的右下方设置状态。

svg签名动画(闭源专属)

在主题配置代码中找到 module,加入 signature 配置,

受限于 Json 语法规则,此处 svg 代码需替换所有的 "\ ",否则会报错。
  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...