表情管理器 | 更多迁移到antd | 进入 lts 状态

[!abstract] 文件v2
bug-v3.zip (1.6 MB)
dist.zip (1.5 MB)

[!caution] UI 改动
现在手机安装的拓展的弹窗应该可以铺满了
拓展弹窗中的表情不再按行对齐

[!note]
插件版本暂不支持tar.gz风格的自动解压并上传
可以使用这个自动上传的脚本上传到IDC (因为两边都有缓存机制,建议不要同时使用拓展(因为是共享的表情,使用这边的图片链接会导致重复缓存,从而浪费资源)

// ==UserScript==
// @name         Standalone Image Uploader
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Extracted image upload UI from bug-v3 as a standalone userscript
// @author       auto
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
  'use strict'

  // Minimal createE implementation
  function createE(tag, opts) {
    const el = document.createElement(tag)
    if (!opts) return el
    if (opts.wi) el.style.width = opts.wi
    if (opts.he) el.style.height = opts.he
    if (opts.class) el.className = opts.class
    if (opts.text) el.textContent = opts.text
    if (opts.ph && 'placeholder' in el) el.placeholder = opts.ph
    if (opts.type && 'type' in el) el.type = opts.type
    if (opts.val !== undefined && 'value' in el) el.value = opts.val
    if (opts.style) el.style.cssText = opts.style
    if (opts.src && 'src' in el) el.src = opts.src
    if (opts.attrs) for (const k in opts.attrs) el.setAttribute(k, opts.attrs[k])
    if (opts.dataset) for (const k in opts.dataset) el.dataset[k] = opts.dataset[k]
    if (opts.in) el.innerHTML = opts.in
    if (opts.ti) el.title = opts.ti
    if (opts.alt && 'alt' in el) el.alt = opts.alt
    if (opts.id) el.id = opts.id
    if (opts.accept && 'accept' in el) el.accept = opts.accept
    if (opts.multiple !== undefined && 'multiple' in el) el.multiple = opts.multiple
    if (opts.role) el.setAttribute('role', opts.role)
    if (opts.tabIndex !== undefined) el.tabIndex = Number(opts.tabIndex)
    if (opts.ld && 'loading' in el) el.loading = opts.ld
    if (opts.on) {
      for (const [evt, handler] of Object.entries(opts.on)) {
        el.addEventListener(evt, handler)
      }
    }
    return el
  }

  // Helper: insert into common editors (textarea or ProseMirror)
  function insertIntoEditor(text) {
    const textArea = document.querySelector('textarea.d-editor-input')
    const richEle = document.querySelector('.ProseMirror.d-editor-input')

    if (!textArea && !richEle) {
      console.error('找不到输入框')
      return
    }

    if (textArea) {
      const start = textArea.selectionStart
      const end = textArea.selectionEnd
      const value = textArea.value

      textArea.value = value.substring(0, start) + text + value.substring(end)
      textArea.setSelectionRange(start + text.length, start + text.length)
      textArea.focus()

      const event = new Event('input', { bubbles: true })
      textArea.dispatchEvent(event)
    } else if (richEle) {
      const selection = window.getSelection()
      if (selection && selection.rangeCount > 0) {
        const range = selection.getRangeAt(0)
        const textNode = document.createTextNode(text)
        range.insertNode(textNode)
        range.setStartAfter(textNode)
        range.setEndAfter(textNode)
        selection.removeAllRanges()
        selection.addRange(range)
      }
      richEle.focus()
    }
  }

  // Parse filenames from markdown image tags
  function parseImageFilenamesFromMarkdown(markdownText) {
    const imageRegex = /!\[([^\]]*)\]\([^\)]+\)/g
    const filenames = []
    let match
    while ((match = imageRegex.exec(markdownText)) !== null) {
      const filename = match[1]
      if (filename && filename.trim()) filenames.push(filename.trim())
    }
    return filenames
  }

  // Uploader class (adapted)
  class ImageUploader {
    constructor() {
      this.waitingQueue = []
      this.uploadingQueue = []
      this.failedQueue = []
      this.successQueue = []
      this.isProcessing = false
      this.maxRetries = 2
      this.progressDialog = null
    }

    uploadImage(file) {
      return new Promise((resolve, reject) => {
        const item = {
          id: `upload_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
          file,
          resolve,
          reject,
          retryCount: 0,
          status: 'waiting',
          timestamp: Date.now()
        }

        this.waitingQueue.push(item)
        this.updateProgressDialog()
        this.processQueue()
      })
    }

    moveToQueue(item, targetStatus) {
      this.waitingQueue = this.waitingQueue.filter(i => i.id !== item.id)
      this.uploadingQueue = this.uploadingQueue.filter(i => i.id !== item.id)
      this.failedQueue = this.failedQueue.filter(i => i.id !== item.id)
      this.successQueue = this.successQueue.filter(i => i.id !== item.id)

      item.status = targetStatus
      if (targetStatus === 'waiting') this.waitingQueue.push(item)
      if (targetStatus === 'uploading') this.uploadingQueue.push(item)
      if (targetStatus === 'failed') this.failedQueue.push(item)
      if (targetStatus === 'success') this.successQueue.push(item)

      this.updateProgressDialog()
    }

    async processQueue() {
      if (this.isProcessing || this.waitingQueue.length === 0) return
      this.isProcessing = true

      while (this.waitingQueue.length > 0) {
        const item = this.waitingQueue.shift()
        if (!item) continue
        this.moveToQueue(item, 'uploading')
        try {
          const result = await this.performUpload(item.file)
          item.result = result
          this.moveToQueue(item, 'success')
          item.resolve(result)
          const markdown = `![${result.original_filename}](${result.url})`
          insertIntoEditor(markdown)
        } catch (error) {
          item.error = error
          if (this.shouldRetry(error, item)) {
            item.retryCount++
            if (error.error_type === 'rate_limit' && error.extras?.wait_seconds) {
              await this.sleep(error.extras.wait_seconds * 1000)
            } else {
              await this.sleep(Math.pow(2, item.retryCount) * 1000)
            }
            this.moveToQueue(item, 'waiting')
          } else {
            this.moveToQueue(item, 'failed')
            item.reject(error)
          }
        }
      }

      this.isProcessing = false
    }

    shouldRetry(error, item) {
      if (item.retryCount >= this.maxRetries) return false
      return error.error_type === 'rate_limit'
    }

    retryFailedItem(itemId) {
      const item = this.failedQueue.find(i => i.id === itemId)
      if (item && item.retryCount < this.maxRetries) {
        item.retryCount++
        this.moveToQueue(item, 'waiting')
        this.processQueue()
      }
    }

    showProgressDialog() {
      if (this.progressDialog) return
      this.progressDialog = this.createProgressDialog()
      document.body.appendChild(this.progressDialog)
    }

    hideProgressDialog() {
      if (this.progressDialog) {
        this.progressDialog.remove()
        this.progressDialog = null
      }
    }

    updateProgressDialog() {
      if (!this.progressDialog) return
      const allItems = [...this.waitingQueue, ...this.uploadingQueue, ...this.failedQueue, ...this.successQueue]
      this.renderQueueItems(this.progressDialog, allItems)
    }

    sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms))
    }

    createProgressDialog() {
      const dialog = createE('div', {
        style: `position: fixed; top: 20px; right: 20px; width: 350px; max-height: 400px; background: white; border-radius: 8px; box-shadow: 0 10px 25px rgba(0,0,0,0.15); z-index: 10000; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; border:1px solid #e5e7eb; overflow: hidden;`
      })

      const header = createE('div', { style: `padding: 16px 20px; background:#f9fafb; border-bottom:1px solid #e5e7eb; font-weight:600; font-size:14px; color:#374151; display:flex; justify-content:space-between; align-items:center;`, text: '图片上传队列' })
      const closeButton = createE('button', { text: '✕', style: `background:none; border:none; font-size:16px; cursor:pointer; color:#6b7280; padding:4px; border-radius:4px; transition: background-color .2s;` })
      closeButton.addEventListener('click', () => this.hideProgressDialog())
      header.appendChild(closeButton)
      const content = createE('div', { class: 'upload-queue-content', style: `max-height:320px; overflow-y:auto; padding:12px;` })
      dialog.appendChild(header)
      dialog.appendChild(content)
      return dialog
    }

    renderQueueItems(dialog, allItems) {
      const content = dialog.querySelector('.upload-queue-content')
      if (!content) return
      content.innerHTML = ''
      if (allItems.length === 0) {
        content.appendChild(createE('div', { style: `text-align:center; color:#6b7280; font-size:14px; padding:20px;`, text: '暂无上传任务' }))
        return
      }

      allItems.forEach(item => {
        const itemEl = createE('div', { style: `display:flex; align-items:center; justify-content:space-between; padding:8px 12px; margin-bottom:8px; background:#f9fafb; border-radius:6px; border-left:4px solid ${this.getStatusColor(item.status)};` })
        const leftSide = createE('div', { style: `flex:1; min-width:0;` })
        const fileName = createE('div', { style: `font-size:13px; font-weight:500; color:#374151; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;`, text: item.file.name })
        const status = createE('div', { style: `font-size:12px; color:#6b7280; margin-top:2px;` })
        status.textContent = this.getStatusText(item)
        leftSide.appendChild(fileName)
        leftSide.appendChild(status)
        const rightSide = createE('div', { style: `display:flex; align-items:center; gap:8px;` })
        if (item.status === 'failed' && item.retryCount < this.maxRetries) {
          const retryButton = createE('button', { text: '🔄', style: `background:none; border:none; cursor:pointer; font-size:14px; padding:4px; border-radius:4px; transition: background-color .2s;`, ti: '重试上传' })
          retryButton.addEventListener('click', () => this.retryFailedItem(item.id))
          rightSide.appendChild(retryButton)
        }
        const statusIcon = createE('div', { style: 'font-size:16px;', text: this.getStatusIcon(item.status) })
        rightSide.appendChild(statusIcon)
        itemEl.appendChild(leftSide)
        itemEl.appendChild(rightSide)
        content.appendChild(itemEl)
      })
    }

    getStatusColor(status) {
      switch (status) {
        case 'waiting': return '#f59e0b'
        case 'uploading': return '#3b82f6'
        case 'success': return '#10b981'
        case 'failed': return '#ef4444'
        default: return '#6b7280'
      }
    }

    getStatusText(item) {
      switch (item.status) {
        case 'waiting': return '等待上传'
        case 'uploading': return '正在上传...'
        case 'success': return '上传成功'
        case 'failed': return item.error?.error_type === 'rate_limit' ? `上传失败 - 请求过于频繁 (重试 ${item.retryCount}/${this.maxRetries})` : `上传失败 (重试 ${item.retryCount}/${this.maxRetries})`
        default: return '未知状态'
      }
    }

    getStatusIcon(status) {
      switch (status) {
        case 'waiting': return '⏳'
        case 'uploading': return '📤'
        case 'success': return '✅'
        case 'failed': return '❌'
        default: return '❓'
      }
    }

    async performUpload(file) {
      const sha1 = await this.calculateSHA1(file)
      const formData = new FormData()
      formData.append('upload_type', 'composer')
      formData.append('relativePath', 'null')
      formData.append('name', file.name)
      formData.append('type', file.type)
      formData.append('sha1_checksum', sha1)
      formData.append('file', file, file.name)

      const csrfToken = this.getCSRFToken()
      const headers = { 'X-Csrf-Token': csrfToken }
      if (document.cookie) headers['Cookie'] = document.cookie

      const response = await fetch(window.location.origin + `/uploads.json?client_id=` + (window.location.host === 'linux.do' ? 'f06cb5577ba9410d94b9faf94e48c2d8' : 'b9cdb79908284b25925d62befbff3921'), { method: 'POST', headers, body: formData })

      if (!response.ok) {
        const errorData = await response.json()
        throw errorData
      }

      return await response.json()
    }

    getCSRFToken() {
      const metaToken = document.querySelector('meta[name="csrf-token"]')
      if (metaToken) return metaToken.content
      const match = document.cookie.match(/csrf_token=([^;]+)/)
      if (match) return decodeURIComponent(match[1])
      const hiddenInput = document.querySelector('input[name="authenticity_token"]')
      if (hiddenInput) return hiddenInput.value
      console.warn('[Image Uploader] No CSRF token found')
      return ''
    }

    async calculateSHA1(file) {
      const text = `${file.name}-${file.size}-${file.lastModified}`
      const encoder = new TextEncoder()
      const data = encoder.encode(text)
      if (crypto.subtle) {
        try {
          const hashBuffer = await crypto.subtle.digest('SHA-1', data)
          const hashArray = Array.from(new Uint8Array(hashBuffer))
          return hashArray.map(b => b.toString(16).padStart(2, '0')).join('')
        } catch (e) {
          console.warn('[Image Uploader] Could not calculate SHA1, using fallback')
        }
      }
      let hash = 0
      for (let i = 0; i < text.length; i++) {
        const char = text.charCodeAt(i)
        hash = (hash << 5) - hash + char
        hash = hash & hash
      }
      return Math.abs(hash).toString(16).padStart(40, '0')
    }
  }

  const uploader = new ImageUploader()

  // --- tar.gz support helpers ---
  function isTarGzFile(file) {
    const name = (file && file.name) || ''
    return name.toLowerCase().endsWith('.tar.gz') || name.toLowerCase().endsWith('.tgz')
  }

  async function decompressGzipToArrayBuffer(blob) {
    if (typeof DecompressionStream === 'function') {
      try {
        const ds = new DecompressionStream('gzip')
        const decompressedStream = blob.stream().pipeThrough(ds)
        const ab = await new Response(decompressedStream).arrayBuffer()
        return ab
      } catch (e) {
        console.error('DecompressionStream failed', e)
        throw e
      }
    }
    // No native DecompressionStream available
    throw new Error('浏览器不支持 DecompressionStream(gzip),无法解压 tar.gz')
  }

  function readStringFromBytes(bytes, start, length) {
    const slice = bytes.subarray(start, start + length)
    // Trim at first NUL
    let end = slice.length
    for (let i = 0; i < slice.length; i++) {
      if (slice[i] === 0) { end = i; break }
    }
    return new TextDecoder().decode(slice.subarray(0, end))
  }

  function parseOctalString(s) {
    const str = s.replace(/\0/g, '').trim()
    if (!str) return 0
    return parseInt(str, 8) || 0
  }

  function parseTarFromArrayBuffer(ab) {
    const bytes = new Uint8Array(ab)
    const files = []
    let offset = 0
    while (offset + 512 <= bytes.length) {
      // Check for two consecutive zero blocks
      const isEmpty = (i => {
        for (let j = 0; j < 512; j++) if (bytes[i + j] !== 0) return false
        return true
      })(offset)
      if (isEmpty) break

      const name = readStringFromBytes(bytes, offset + 0, 100)
      if (!name) break
      const sizeStr = readStringFromBytes(bytes, offset + 124, 12)
      const size = parseOctalString(sizeStr)

      const dataStart = offset + 512
      const dataEnd = dataStart + size
      if (dataEnd > bytes.length) break
      const fileBytes = bytes.slice(dataStart, dataEnd)

      files.push({ name, size, bytes: fileBytes })

      // Advance to next header (file data is padded to 512)
      const padded = Math.ceil(size / 512) * 512
      offset = dataStart + padded
    }
    return files
  }

  function isLikelyImageName(name) {
    const lower = name.toLowerCase()
    return /\.(png|jpe?g|gif|webp|bmp|svg|avif)$/i.test(lower)
  }

  async function extractFilesFromTarGzFile(file) {
    // returns array of File objects
    try {
      const ab = await decompressGzipToArrayBuffer(file)
      const entries = parseTarFromArrayBuffer(ab)
      const out = []
      for (const e of entries) {
        if (!e.name) continue
        if (!isLikelyImageName(e.name)) continue
        const blob = new Blob([e.bytes], { type: 'application/octet-stream' })
        // infer mime from extension
        const ext = (e.name.split('.').pop() || '').toLowerCase()
        let mime = 'application/octet-stream'
        if (ext === 'png') mime = 'image/png'
        else if (ext === 'jpg' || ext === 'jpeg') mime = 'image/jpeg'
        else if (ext === 'gif') mime = 'image/gif'
        else if (ext === 'webp') mime = 'image/webp'
        else if (ext === 'svg') mime = 'image/svg+xml'
        else if (ext === 'avif') mime = 'image/avif'
        const imageBlob = new Blob([e.bytes], { type: mime })
        const fileObj = new File([imageBlob], e.name, { type: mime })
        out.push(fileObj)
      }
      return out
    } catch (err) {
      console.error('extractFilesFromTarGzFile error', err)
      alert('无法解压 tar.gz:' + (err && err.message ? err.message : String(err)))
      return []
    }
  }
  // --- end tar.gz helpers ---

  function createDragDropUploadPanel() {
    const panel = createE('div', { class: 'drag-drop-upload-panel', style: `position: fixed; top:50%; left:50%; transform: translate(-50%,-50%); width:500px; max-width:90vw; background:white; border-radius:12px; box-shadow:0 20px 25px -5px rgba(0,0,0,0.1),0 10px 10px -5px rgba(0,0,0,0.04); z-index:10000; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;` })

    const overlay = createE('div', { style: `position: fixed; top:0; left:0; right:0; bottom:0; background: rgba(0,0,0,0.5); z-index:9999;` })

    const header = createE('div', { style: `padding:20px 24px 0; display:flex; justify-content:space-between; align-items:center;` })
    const title = createE('h2', { text: '上传图片', style: `margin:0; font-size:18px; font-weight:600; color:#111827;` })
    const closeButton = createE('button', { in: '✕', style: `background:none; border:none; font-size:20px; cursor:pointer; color:#6b7280; padding:4px; border-radius:4px; transition:background-color .2s;` })
    header.appendChild(title)
    header.appendChild(closeButton)

    const content = createE('div', { class: 'upload-panel-content', style: `padding:24px;` })
    const tabContainer = createE('div', { style: `display:flex; border-bottom:1px solid #e5e7eb; margin-bottom:20px;` })
    const regularTab = createE('button', { text: '常规上传', style: `flex:1; padding:10px 20px; background:none; border:none; border-bottom:2px solid #3b82f6; color:#3b82f6; font-weight:500; cursor:pointer; transition:all .2s;` })
    const diffTab = createE('button', { text: '差分上传', style: `flex:1; padding:10px 20px; background:none; border:none; border-bottom:2px solid transparent; color:#6b7280; font-weight:500; cursor:pointer; transition:all .2s;` })
    tabContainer.appendChild(regularTab)
    tabContainer.appendChild(diffTab)

    const regularPanel = createE('div', { class: 'regular-upload-panel', style: `display:block;` })
    const dropZone = createE('div', { class: 'drop-zone', style: `border:2px dashed #d1d5db; border-radius:8px; padding:40px 20px; text-align:center; background:#f9fafb; transition:all .2s; cursor:pointer;` })
    const dropIcon = createE('div', { in: '📁', style: `font-size:48px; margin-bottom:16px;` })
    const dropText = createE('div', { in: `<div style="font-size:16px; font-weight:500; color:#374151; margin-bottom:8px;">拖拽图片到此处,或点击选择文件</div><div style="font-size:14px; color:#6b7280;">支持 JPG、PNG、GIF 等格式,最大 10MB</div>` })
    const fileInput = createE('input', { type: 'file', accept: 'image/*', multiple: true, style: `display:none;` })
    dropZone.appendChild(dropIcon)
    dropZone.appendChild(dropText)
    regularPanel.appendChild(dropZone)
    regularPanel.appendChild(fileInput)

    const diffPanel = createE('div', { class: 'diff-upload-panel', style: `display:none;` })
    const markdownTextarea = createE('textarea', { ph: '请粘贴包含图片的markdown文本...', style: `width:100%; height:120px; padding:12px; border:1px solid #d1d5db; border-radius:6px; font-family:monospace; font-size:14px; resize:vertical; margin-bottom:12px; box-sizing:border-box;` })
    const diffDropZone = createE('div', { class: 'diff-drop-zone', style: `border:2px dashed #d1d5db; border-radius:8px; padding:30px 20px; text-align:center; background:#f9fafb; transition:all .2s; cursor:pointer; margin-bottom:12px;` })
    const diffFileInput = createE('input', { type: 'file', accept: 'image/*', multiple: true, style: `display:none;` })
    diffPanel.appendChild(markdownTextarea)
    diffPanel.appendChild(diffDropZone)
    diffPanel.appendChild(diffFileInput)

    content.appendChild(tabContainer)
    content.appendChild(regularPanel)
    content.appendChild(diffPanel)
    panel.appendChild(header)
    panel.appendChild(content)

    const switchToTab = (activeTab, inactiveTab, activePanel, inactivePanel) => {
      activeTab.style.borderBottomColor = '#3b82f6'
      activeTab.style.color = '#3b82f6'
      inactiveTab.style.borderBottomColor = 'transparent'
      inactiveTab.style.color = '#6b7280'
      activePanel.style.display = 'block'
      inactivePanel.style.display = 'none'
    }

    regularTab.addEventListener('click', () => switchToTab(regularTab, diffTab, regularPanel, diffPanel))
    diffTab.addEventListener('click', () => switchToTab(diffTab, regularTab, diffPanel, regularPanel))

    return { panel, overlay, dropZone, fileInput, closeButton, diffDropZone, diffFileInput, markdownTextarea }
  }

  async function showImageUploadDialog() {
    return new Promise(resolve => {
      const { panel, overlay, dropZone, fileInput, closeButton, diffDropZone, diffFileInput, markdownTextarea } = createDragDropUploadPanel()
      let isDragOver = false
      let isDiffDragOver = false

      const cleanup = () => {
        document.body.removeChild(overlay)
        document.body.removeChild(panel)
        resolve()
      }

      const handleFiles = async files => {
        if (!files || files.length === 0) return
        cleanup()
        uploader.showProgressDialog()
        try {
            const expanded = []
            for (const f of Array.from(files)) {
              if (isTarGzFile(f)) {
                const imgs = await extractFilesFromTarGzFile(f)
                expanded.push(...imgs)
              } else {
                expanded.push(f)
              }
            }

            if (expanded.length === 0) return

            const promises = expanded.map(async file => {
            try { return await uploader.uploadImage(file) } catch (e) { console.error('[Image Uploader] Upload failed:', e); throw e }
          })
          await Promise.allSettled(promises)
        } finally {
          setTimeout(() => uploader.hideProgressDialog(), 3000)
        }
      }

      const handleDiffFiles = async files => {
        if (!files || files.length === 0) return
        const markdownText = markdownTextarea.value
        const existingFilenames = parseImageFilenamesFromMarkdown(markdownText)
          const expanded = []
          for (const f of Array.from(files)) {
            if (isTarGzFile(f)) {
              const imgs = await extractFilesFromTarGzFile(f)
              expanded.push(...imgs)
            } else {
              expanded.push(f)
            }
          }

          const filesToUpload = expanded.filter(file => !existingFilenames.includes(file.name))
        if (filesToUpload.length === 0) { alert('所有选择的图片都已在markdown文本中存在,无需上传。'); return }
        if (filesToUpload.length < files.length) {
          const skippedCount = files.length - filesToUpload.length
          const proceed = confirm(`发现 ${skippedCount} 个图片已存在于markdown文本中,将被跳过。是否继续上传剩余 ${filesToUpload.length} 个图片?`)
          if (!proceed) return
        }
        cleanup()
        uploader.showProgressDialog()
        try {
          const promises = filesToUpload.map(async file => { try { return await uploader.uploadImage(file) } catch (e) { console.error('[Image Uploader] Diff upload failed:', e); throw e } })
          await Promise.allSettled(promises)
        } finally {
          setTimeout(() => uploader.hideProgressDialog(), 3000)
        }
      }

      fileInput.addEventListener('change', async event => { const files = event.target.files; if (files) await handleFiles(files) })
      dropZone.addEventListener('click', () => fileInput.click())
      dropZone.addEventListener('dragover', e => { e.preventDefault(); if (!isDragOver) { isDragOver = true; dropZone.style.borderColor = '#3b82f6'; dropZone.style.backgroundColor = '#eff6ff' } })
      dropZone.addEventListener('dragleave', e => { e.preventDefault(); if (!dropZone.contains(e.relatedTarget)) { isDragOver = false; dropZone.style.borderColor = '#d1d5db'; dropZone.style.backgroundColor = '#f9fafb' } })
      dropZone.addEventListener('drop', async e => { e.preventDefault(); isDragOver = false; dropZone.style.borderColor = '#d1d5db'; dropZone.style.backgroundColor = '#f9fafb'; const files = e.dataTransfer?.files; if (files) await handleFiles(files) })

      diffFileInput.addEventListener('change', async event => { const files = event.target.files; if (files) await handleDiffFiles(files) })
      diffDropZone.addEventListener('click', () => diffFileInput.click())
      diffDropZone.addEventListener('dragover', e => { e.preventDefault(); if (!isDiffDragOver) { isDiffDragOver = true; diffDropZone.style.borderColor = '#3b82f6'; diffDropZone.style.backgroundColor = '#eff6ff' } })
      diffDropZone.addEventListener('dragleave', e => { e.preventDefault(); if (!diffDropZone.contains(e.relatedTarget)) { isDiffDragOver = false; diffDropZone.style.borderColor = '#d1d5db'; diffDropZone.style.backgroundColor = '#f9fafb' } })
      diffDropZone.addEventListener('drop', async e => { e.preventDefault(); isDiffDragOver = false; diffDropZone.style.borderColor = '#d1d5db'; diffDropZone.style.backgroundColor = '#f9fafb'; const files = e.dataTransfer?.files; if (files) await handleDiffFiles(files) })

      closeButton.addEventListener('click', cleanup)
      overlay.addEventListener('click', cleanup)

      const preventDefaults = e => { e.preventDefault(); e.stopPropagation() }
      ;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => document.addEventListener(eventName, preventDefaults, false))

      const originalCleanup = cleanup
      const enhancedCleanup = () => { ;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => document.removeEventListener(eventName, preventDefaults, false)); originalCleanup() }

      closeButton.removeEventListener('click', cleanup)
      overlay.removeEventListener('click', cleanup)
      closeButton.addEventListener('click', enhancedCleanup)
      overlay.addEventListener('click', enhancedCleanup)

      document.body.appendChild(overlay)
      document.body.appendChild(panel)
    })
  }

  // Floating trigger button
  function createFloatingButton() {
    const btn = createE('button', { text: '上传', style: `position:fixed; right:18px; bottom:18px; z-index:100000; padding:10px 14px; border-radius:9999px; background:#3b82f6; color:white; border:none; font-weight:600; cursor:pointer; box-shadow:0 6px 18px rgba(59,130,246,0.3);` })
    btn.addEventListener('click', () => showImageUploadDialog())
    document.body.appendChild(btn)
  }

  // Wait DOM ready
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', createFloatingButton)
  } else {
    createFloatingButton()
  }

  // Expose for debugging
  window.__standaloneImageUploader = { uploader, showImageUploadDialog }
})();

[!error] 已知问题
在你输入了超过屏幕高度的文字后,自动补全会飞走……

[!example] 开发应该会接近停滞了
自动阅读的提示部分修了

[!abstract]
完整版本(带默认数据)
Linux do 表情扩展 (Emoji Extension)
精简版本(无默认表情)
Linux do 表情扩展 (Emoji Extension) lite

22 个赞

感觉会火,占个沙发

这个功能效果图能给个看看吗?


[!abstract] 自动补全

加急按钮

表情部分蚕食discourse自带的设计就行了

1 个赞

还行 可有呀

好用,爱用,多用

[!important]自动补全这个功能挺好,给佬友点赞!

你好强啊!

这个看起来挺好啊! :laughing:

[!success]- 大帅哥都说强!
那佬一定强!

discourse应该是有使用tensor表情的能力的(不过始皇应该没有安装那个……

2 个赞

佬太强了!感谢分享


裤裤也是会用表情包的崽了hhh

1 个赞

来电……生草

[
  {
    "id": "emoji-1758814954129-4z08d4",
    "packet": 1758814954129,
    "name": "AgADmQQAAngt6UQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/7/9/a794d4d2cc49acaf22546c0e3fc2289b1d7a0a7b.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-e896g7",
    "packet": 1758814954129,
    "name": "AgADuQUAAvQq6EQ.webp",
    "url": "https://cdn3.linux.do/original/4X/0/c/6/0c6004ed967d338a68f3bcdb4dfec1c677dfbfb2.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-k9g1f2",
    "packet": 1758814954129,
    "name": "AgAD0wIAAoB8aEU.webp",
    "url": "https://cdn3.linux.do/original/4X/1/a/1/1a11dcabc319769048fd21a0ae874639905ff7f1.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-glgn12",
    "packet": 1758814954129,
    "name": "AgAD1QIAArFbiUU.webp",
    "url": "https://cdn3.linux.do/original/4X/2/3/e/23e275841ac26631d289d368352c33e4a6c009a7.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-ole526",
    "packet": 1758814954129,
    "name": "AgAD3gMAAvi1aUU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/b/c/0bc58579e9f0675d7623d75cb7c3f685c903e1b5.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-7pvcra",
    "packet": 1758814954129,
    "name": "AgAD4QIAAoDeaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/8/0/a/80a6dfb347168900b096a2871f7b5d2bca3e4834.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-a299wa",
    "packet": 1758814954129,
    "name": "AgAD5gQAAn-88UQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/8/b/68bf2a4565b91c73ef87d4a4de7884e841fbcd7a.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-dfkn38",
    "packet": 1758814954129,
    "name": "AgAD6gMAAo7McEU.webp",
    "url": "https://cdn3.linux.do/original/4X/5/b/8/5b850ef2e479d396cef32b4fe5a0d71f6931bcc4.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-fjgev5",
    "packet": 1758814954129,
    "name": "AgAD8QQAAvWiaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/5/9/d/59d30b4ec427e86e7fba6ad4e706faa5328ad2bd.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-uii1hr",
    "packet": 1758814954129,
    "name": "AgAD8gIAAitwcUU.webp",
    "url": "https://cdn3.linux.do/original/4X/8/4/7/8473b7eb90ff1836ebefc969be23defea47316fb.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-hc6vk3",
    "packet": 1758814954129,
    "name": "AgAD9AIAArAzaUU.webp",
    "url": "https://cdn3.linux.do/original/4X/e/b/8/eb82fd0b5518e2286d53d005624bf700b6562571.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-u31u7v",
    "packet": 1758814954129,
    "name": "AgAD-QIAAkpoaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/2/a/7/2a7d1f562dcf441a7217c6b5b798290062de5afc.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-ef8i4z",
    "packet": 1758814954129,
    "name": "AgADBwMAAqtniUc.webp",
    "url": "https://cdn3.linux.do/original/4X/2/e/2/2e2c0094990eaa6496b5df2446c4fee05dcf4397.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954129-22sav5",
    "packet": 1758814954129,
    "name": "AgADCQUAAvKa8EQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/3/d/83de912d91cad700343b682b0b88afdd473bf9fb.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-6kkp9h",
    "packet": 1758814954129,
    "name": "AgADCwQAAnUuoEQ.webp",
    "url": "https://cdn3.linux.do/original/4X/1/a/0/1a07c120201cc202b2a3c278f58201f70505b198.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-tm7cw2",
    "packet": 1758814954130,
    "name": "AgADDQQAAqzvkUc.webp",
    "url": "https://cdn3.linux.do/original/4X/b/5/1/b510a67e26556a8cb76f1e1653ca43f179972c8f.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-jjwm0f",
    "packet": 1758814954130,
    "name": "AgADEAMAAsPOaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/a/9/8/a980169f93cf9057e5f3ceba684545e6ec041f6a.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-wk0f40",
    "packet": 1758814954130,
    "name": "AgADFgQAAhAvaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/2/6/0/2601e005524e3f979ab365c56788428261f178b1.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-b9x4sj",
    "packet": 1758814954130,
    "name": "AgADGgMAAr-lwEY.webp",
    "url": "https://cdn3.linux.do/original/4X/4/b/1/4b19a3717472951da77031b06df17d39b6b2bde2.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-31a128",
    "packet": 1758814954130,
    "name": "AgADHwMAAk53cUQ.webp",
    "url": "https://cdn3.linux.do/original/4X/e/7/9/e797ee419300b1ac5a6c15b5287b0571deb727f6.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-ucifgx",
    "packet": 1758814954130,
    "name": "AgADJwMAArsPoEQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/1/e/a1ef60cf374e361161de3912f1b9ca4d1ebd5fa9.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-ck4w7y",
    "packet": 1758814954130,
    "name": "AgADKAQAAvt5uUY.webp",
    "url": "https://cdn3.linux.do/original/4X/7/6/a/76ad8ebf6319dfec38dd075691c02de63c12eb9f.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-yufnqk",
    "packet": 1758814954130,
    "name": "AgADLQMAAm9maUU.webp",
    "url": "https://cdn3.linux.do/original/4X/5/8/a/58a53ebc94d1d09fb2ea03b6d31355443645969d.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-7udxhq",
    "packet": 1758814954130,
    "name": "AgADLgMAAqdRcEU.webp",
    "url": "https://cdn3.linux.do/original/4X/b/f/f/bff1e92bf8f8b45ae1373a0e393b271c96586490.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-5xgnen",
    "packet": 1758814954130,
    "name": "AgADLgQAAlfeiEU.webp",
    "url": "https://cdn3.linux.do/original/4X/e/1/f/e1f3f5b2eb520b7386e3f3a1e5c5a3ff66ce57ad.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-2dnj0g",
    "packet": 1758814954130,
    "name": "AgADMAIAAq5faEU.webp",
    "url": "https://cdn3.linux.do/original/4X/2/a/4/2a468b458c41cfb5d049628c32d3f8fd2fdcb5fe.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-4fzfa5",
    "packet": 1758814954130,
    "name": "AgADNgMAAiH9cUQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/0/c/a0cb1b586c45aad41892590d2bc86db0bc319d41.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-kkx4y3",
    "packet": 1758814954130,
    "name": "AgADOQMAAlJnaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/4/6/a/46a88a4ef69f3bac1e0a68eec2ad3466cc1ece4f.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-gws3go",
    "packet": 1758814954130,
    "name": "AgADOgMAAkM-wUU.webp",
    "url": "https://cdn3.linux.do/original/4X/a/c/c/acc82c716c74e057e7c4f8ac522040c65c3270eb.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-ywiowj",
    "packet": 1758814954130,
    "name": "AgADOwQAAuLOwUY.webp",
    "url": "https://cdn3.linux.do/original/4X/7/6/3/7631124500069c7857f8c5b93888eb313cba9a39.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-0wrady",
    "packet": 1758814954130,
    "name": "AgADPQQAAr3ecUU.webp",
    "url": "https://cdn3.linux.do/original/4X/4/0/8/408caaf4880e6aed96e79d9c2c9c781fec8333b6.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-ykgzw0",
    "packet": 1758814954130,
    "name": "AgADSgMAAkwhwUU.webp",
    "url": "https://cdn3.linux.do/original/4X/1/2/6/1260bc32a0147460314f8cf7c7815446024f617b.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-0ngwp6",
    "packet": 1758814954130,
    "name": "AgAD_wUAAhfo6EQ.webp",
    "url": "https://cdn3.linux.do/original/4X/5/e/e/5ee823195a9d345cb3f256ebf5a3230fe4e4e51c.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-4ydki3",
    "packet": 1758814954130,
    "name": "AgADcAQAAu0Z8EQ.webp",
    "url": "https://cdn3.linux.do/original/4X/4/9/6/496ad4c723461ee5655b232a03a3dce48426ec83.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-vmft8t",
    "packet": 1758814954130,
    "name": "AgADcQMAArxBaUU.webp",
    "url": "https://cdn3.linux.do/original/4X/f/2/1/f2167905ae1fe1681f101675654b0cbd67d638e2.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-huklm3",
    "packet": 1758814954130,
    "name": "AgADdwMAAlDFmEc.webp",
    "url": "https://cdn3.linux.do/original/4X/c/9/b/c9b931a707149aa82310a44e2277875b560a7d68.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-vt9z6i",
    "packet": 1758814954130,
    "name": "AgADeAMAAoEKcUQ.webp",
    "url": "https://cdn3.linux.do/original/4X/e/2/f/e2fac16abbfc68d7b24b1c6dd4eb8f1bed4dd003.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-q9v789",
    "packet": 1758814954130,
    "name": "AgADeAQAA3ToRA.webp",
    "url": "https://cdn3.linux.do/original/4X/e/1/4/e1445dde835014fb2dc7a9b978a789ac03ce1e65.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-2tmsmb",
    "packet": 1758814954130,
    "name": "AgADgwIAAukEwUU.webp",
    "url": "https://cdn3.linux.do/original/4X/9/6/e/96e72aef19ef815a7819185043997bef90d021e1.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-r9iadu",
    "packet": 1758814954130,
    "name": "AgADkgQAAiZ6aUU.webp",
    "url": "https://cdn3.linux.do/original/4X/1/9/8/198e861ac9f27beae9a6719ebabb2cc88e973a6e.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-34xy1m",
    "packet": 1758814954130,
    "name": "AgADlAMAAmtraUU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/9/9/099e59bfdfcf4339300d272678c04a0c60b92d84.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-bj74es",
    "packet": 1758814954130,
    "name": "AgADnQgAAgxpaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/6/2/b/62be843e09d28694ffc3294c3e37e16921fe3f51.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-gs1gkz",
    "packet": 1758814954130,
    "name": "AgADnwMAAjhfiEU.webp",
    "url": "https://cdn3.linux.do/original/4X/3/c/6/3c64f3965391f43f94b20f74dbdbed36d31cdc39.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-dfonif",
    "packet": 1758814954130,
    "name": "AgADpgIAAjGUaUU.webp",
    "url": "https://cdn3.linux.do/original/4X/c/1/2/c128cda5c84ae49e07d0bb657518e5545f6a1157.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-cqwxhx",
    "packet": 1758814954130,
    "name": "AgADqAMAAi_WaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/8/c/e/8ce4f3bf6521faf18119666a8a5b8f02ba617e30.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-9kykae",
    "packet": 1758814954130,
    "name": "AgADqQMAAjzqwEY.webp",
    "url": "https://cdn3.linux.do/original/4X/8/9/5/895390f08463f3ed5184655d95c82577a8d5a6b4.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-n858yq",
    "packet": 1758814954130,
    "name": "AgADrAQAAk_naUU.webp",
    "url": "https://cdn3.linux.do/original/4X/2/6/a/26a07778a254bf104de4e7208b6acfbaba16e65a.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-a5968h",
    "packet": 1758814954130,
    "name": "AgADtwMAAqywcEU.webp",
    "url": "https://cdn3.linux.do/original/4X/1/2/e/12e21c899542197fdfd694e818e5868a9a56f728.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-0amq4k",
    "packet": 1758814954130,
    "name": "AgADuQUAAjwdoEQ.webp",
    "url": "https://cdn3.linux.do/original/4X/3/0/3/303c278f1d3331c355b9b4097c9c14008f8eb516.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-smxh8o",
    "packet": 1758814954130,
    "name": "AgADvQIAAo8hiEU.webp",
    "url": "https://cdn3.linux.do/original/4X/5/b/6/5b6072a39aeedccf81c9e4e60934d21143b91d2e.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-03a6cs",
    "packet": 1758814954130,
    "name": "AgADxwUAAj7y8UQ.webp",
    "url": "https://cdn3.linux.do/original/4X/f/2/0/f20d43b84ebc3c1ac31fbd8c6b0fbe544dba4ee3.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-djmdwk",
    "packet": 1758814954130,
    "name": "AgADzAMAApe9cEQ.webp",
    "url": "https://cdn3.linux.do/original/4X/3/c/3/3c3bc74dec059c26c79c2b151c1780ae5c645cdd.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-3gw9np",
    "packet": 1758814954130,
    "name": "AgADzAMAAswHcUU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/a/1/0a1361ae33794fffab50cd7c7e1cdc628b5addeb.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-xofvz7",
    "packet": 1758814954130,
    "name": "AgAD-AMAAjePcEU.webp",
    "url": "https://cdn3.linux.do/original/4X/a/6/9/a694487eeab39b1d84aaa8955d63318eb656ab4b.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-nrhid2",
    "packet": 1758814954130,
    "name": "AgADDwQAAp3uaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/c/2/b/c2bad78cfd0a916ed2ba340b1fbadcab3d5e5f14.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-ghkjof",
    "packet": 1758814954130,
    "name": "AgADGAMAAtcawEY.webp",
    "url": "https://cdn3.linux.do/original/4X/6/f/c/6fcd09fd687d9f740986cd71d06a3df965733881.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-ffyt0d",
    "packet": 1758814954130,
    "name": "AgADHgMAArCVaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/1/a/f/1aff5e28911039eb8c723c2ce2360d1d3dcf5ed9.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-5q16eg",
    "packet": 1758814954130,
    "name": "AgADHwYAAi4M8EQ.webp",
    "url": "https://cdn3.linux.do/original/4X/e/8/0/e806d884e35b312d07474c1ba1760e62922270a1.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-nfi0y3",
    "packet": 1758814954130,
    "name": "AgADKwQAAs9NcEQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/7/2/67237525696693a7b95735394a2e4df4cc54ae4e.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-l7xsw2",
    "packet": 1758814954130,
    "name": "AgADOQMAApNbcUU.webp",
    "url": "https://cdn3.linux.do/original/4X/e/5/6/e5638715ad4ebb752b6fa5384e58211a48e444d2.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-vxsepn",
    "packet": 1758814954130,
    "name": "AgADOwgAA29pRQ.webp",
    "url": "https://cdn3.linux.do/original/4X/4/c/b/4cb36c82df65c479a5cba152b5d436d1c522c7d4.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-h5ziiv",
    "packet": 1758814954130,
    "name": "AgAD_gMAAnaHmUc.webp",
    "url": "https://cdn3.linux.do/original/4X/f/f/d/ffd3cb638269f85c56e917b1b7441a74c6564ec3.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-nxuef7",
    "packet": 1758814954130,
    "name": "AgADdwMAAo4gaUU.webp",
    "url": "https://cdn3.linux.do/original/4X/6/f/2/6f20ee3ec6c34ec8ab556b11f5da0aabbdf91694.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-orra6k",
    "packet": 1758814954130,
    "name": "AgADeQMAAlLGaUU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/1/2/012c1e06c52f5df8a0f6ed53551762541bdcf2c2.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-460evr",
    "packet": 1758814954130,
    "name": "AgADkQMAAjAkcUU.webp",
    "url": "https://cdn3.linux.do/original/4X/c/1/1/c115d30123c7f16875811295f204c756f35d65e9.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-wdxabo",
    "packet": 1758814954130,
    "name": "AgADkgYAAqaFaUU.webp",
    "url": "https://cdn3.linux.do/original/4X/1/b/e/1becf465a04b5eef6039140bab946a847505a6e6.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-rh0ubs",
    "packet": 1758814954130,
    "name": "AgADmAIAAgF2iEU.webp",
    "url": "https://cdn3.linux.do/original/4X/9/2/7/9272a6fd0cb3cbbbbd101ed51163628965890ad2.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-d6e9qd",
    "packet": 1758814954130,
    "name": "AgADqwMAAgI6aEU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/2/9/029dfe5dac95eef426492acaa8073f0e1d0039c5.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-gnd6ai",
    "packet": 1758814954130,
    "name": "AgADuQMAAlJOcUU.webp",
    "url": "https://cdn3.linux.do/original/4X/b/c/8/bc8fa10f8242d4e51bc320ec58dee3b185dfca09.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-g9q1my",
    "packet": 1758814954130,
    "name": "AgADwQIAApKrwEU.webp",
    "url": "https://cdn3.linux.do/original/4X/6/e/a/6ea7237f4dea21eeb19e5ae293565e86da914598.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-t0xg5t",
    "packet": 1758814954130,
    "name": "AgADKAQAAlQkwUY.webp",
    "url": "https://cdn3.linux.do/original/4X/b/4/0/b409a76a2af825e33d02f61dab6b979f75fe0891.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-crkbxt",
    "packet": 1758814954130,
    "name": "AgADmgMAAknriEU.webp",
    "url": "https://cdn3.linux.do/original/4X/8/b/e/8beaad82b40780d3c05e5e18874e5a5598d26b0d.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-x414ix",
    "packet": 1758814954130,
    "name": "AgADmAQAAiml6UQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/b/6/6b6f79e8e945f3961229f36ccdb3cacc7273a494.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-1ky7zp",
    "packet": 1758814954130,
    "name": "AgAD6wIAAmRnkUc.webp",
    "url": "https://cdn3.linux.do/original/4X/4/4/b/44ba2e60f7cda0327b24bdb43263b93db8dd1bc5.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-hxa85k",
    "packet": 1758814954130,
    "name": "AgADMwQAAvfXaEU.webp",
    "url": "https://cdn3.linux.do/original/4X/c/a/c/cacb61ef31e96eca948962896a3c74f48e337597.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-rxqini",
    "packet": 1758814954130,
    "name": "AgADOwMAAs7CaUU.webp",
    "url": "https://cdn3.linux.do/original/4X/a/c/6/ac6b03c8ad5b108375f4d07ef396976ec1bbde46.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-d2aufj",
    "packet": 1758814954130,
    "name": "AgADPgQAAtdRuEY.webp",
    "url": "https://cdn3.linux.do/original/4X/8/2/9/829bb9935053a54894d5a18342865636c4c489bf.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-sqjjor",
    "packet": 1758814954130,
    "name": "AgADyQMAAtdTuEU.webp",
    "url": "https://cdn3.linux.do/original/4X/2/0/6/206fe6458da728a1799f303cfc77a0623206cf8f.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  },
  {
    "id": "emoji-1758814954130-w2ima5",
    "packet": 1758814954130,
    "name": "AgADnQIAAuW0wEU.webp",
    "url": "https://cdn3.linux.do/original/4X/3/5/4/354f1dadc8a3ccfbf3135e5a488bbffaf64d0595.webp",
    "width": 512,
    "height": 443,
    "groupId": "超"
  }
]

注释:脚本当自强

1 个赞

悄咪咪地更新一下默认表情配置……
extesnion.zip (1.7 MB)
bug-v3.zip (1.6 MB)

对于脚本,非lite版本已经更新,可以通过清理对应的localstorge强制更新为默认表情

// ==UserScript==
// @name         LocalStorage Editor (Simple)
// @namespace    https://example.com/
// @version      0.1
// @description  在页面上显示一个浮动面板,方便查看/编辑当前页面的 localStorage(查看/编辑/删除/导入/导出)。
// @author       Generated
// @match        *://*/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
  'use strict'

  // Minimal styles for the panel
  const style = document.createElement('style')
  style.textContent = `
    #ls-editor-toggle { position: fixed; right: 12px; bottom: 12px; z-index:2147483646; }
    #ls-editor-panel { position: fixed; right: 12px; bottom: 56px; width: 520px; max-height: 70vh; z-index:2147483646; background:#fff; border:1px solid #ccc; box-shadow:0 6px 24px rgba(0,0,0,0.2); font-family: Arial, Helvetica, sans-serif; color:#111; border-radius:8px; overflow:hidden; display:none; }
    #ls-editor-panel .header { display:flex; align-items:center; justify-content:space-between; padding:8px 10px; background:#f5f5f5; border-bottom:1px solid #eee; }
    #ls-editor-panel .body { display:flex; gap:8px; padding:8px; }
    #ls-editor-keys { width: 45%; max-height:50vh; overflow:auto; border:1px solid #eee; padding:8px; border-radius:4px; }
    #ls-editor-keys .key { padding:6px; border-radius:4px; cursor:pointer; margin-bottom:6px; background: #fff; }
    #ls-editor-keys .key.selected { background:#e8f0ff; }
    #ls-editor-right { width:55%; display:flex; flex-direction:column; gap:8px; }
    #ls-editor-right textarea { width:100%; height:160px; font-family: monospace; font-size:12px; padding:8px; border-radius:4px; border:1px solid #ddd; resize:vertical; }
    #ls-editor-controls { display:flex; gap:8px; flex-wrap:wrap; }
    #ls-editor-panel input[type="text"], #ls-editor-panel input[type="search"] { width:100%; padding:6px 8px; border:1px solid #ddd; border-radius:4px; }
    #ls-editor-panel button { padding:6px 10px; border-radius:4px; border:1px solid #bbb; background:#fff; cursor:pointer; }
    #ls-editor-panel button.primary { background:#0366d6; color:#fff; border-color:#0366d6; }
    #ls-editor-panel .small { font-size:12px; color:#666; }
  `
  document.head.appendChild(style)

  // Toggle button
  const toggle = document.createElement('button')
  toggle.id = 'ls-editor-toggle'
  toggle.textContent = 'LS'
  toggle.title = 'Open LocalStorage Editor'
  toggle.style.padding = '8px 10px'
  toggle.style.borderRadius = '6px'
  toggle.style.border = '1px solid #bbb'
  toggle.style.background = '#fff'
  toggle.style.cursor = 'pointer'
  document.body.appendChild(toggle)

  // Panel
  const panel = document.createElement('div')
  panel.id = 'ls-editor-panel'

  panel.innerHTML = `
    <div class="header">
      <div style="font-weight:600">LocalStorage 编辑器</div>
      <div style="display:flex;gap:8px;align-items:center">
        <button id="ls-export">导出</button>
        <button id="ls-import">导入</button>
        <button id="ls-close">关闭</button>
      </div>
    </div>
    <div class="body">
      <div id="ls-editor-keys">
        <div style="margin-bottom:8px"><input id="ls-search" type="search" placeholder="搜索 key..." /></div>
        <div id="ls-keys-list"></div>
      </div>
      <div id="ls-editor-right">
        <div>
          <div style="display:flex; gap:8px;">
            <input id="ls-key-input" type="text" placeholder="Key" />
            <button id="ls-new" class="primary">新增/选中</button>
          </div>
          <div class="small">选择一个 key 编辑其值;新增时输入 key 并点击 “新增/选中”。</div>
        </div>
        <textarea id="ls-value"></textarea>
        <div id="ls-editor-controls">
          <button id="ls-save" class="primary">保存</button>
          <button id="ls-delete">删除</button>
          <button id="ls-copy">复制值</button>
          <button id="ls-clear">清空所有(危险)</button>
        </div>
      </div>
    </div>
    <!-- hidden file input for import -->
    <input id="ls-file-input" type="file" accept=".json,application/json" style="display:none" />
  `

  document.body.appendChild(panel)

  const keysListEl = panel.querySelector('#ls-keys-list')
  const searchEl = panel.querySelector('#ls-search')
  const keyInputEl = panel.querySelector('#ls-key-input')
  const valueEl = panel.querySelector('#ls-value')
  const saveBtn = panel.querySelector('#ls-save')
  const deleteBtn = panel.querySelector('#ls-delete')
  const newBtn = panel.querySelector('#ls-new')
  const exportBtn = panel.querySelector('#ls-export')
  const importBtn = panel.querySelector('#ls-import')
  const closeBtn = panel.querySelector('#ls-close')
  const copyBtn = panel.querySelector('#ls-copy')
  const clearBtn = panel.querySelector('#ls-clear')
  const fileInput = panel.querySelector('#ls-file-input')

  let selectedKey = null

  function listKeys(filter = '') {
    const keys = []
    for (let i = 0; i < localStorage.length; i++) {
      const k = localStorage.key(i)
      if (k == null) continue
      if (!filter || k.includes(filter)) keys.push(k)
    }
    keysListEl.innerHTML = ''
    if (keys.length === 0) {
      keysListEl.innerHTML = '<div class="small">(no keys)</div>'
      return
    }
    keys
      .sort()
      .forEach(k => {
        const el = document.createElement('div')
        el.className = 'key'
        if (k === selectedKey) el.classList.add('selected')
        el.textContent = k + ' (' + (localStorage.getItem(k) || '').length + ' chars)'
        el.addEventListener('click', () => {
          selectKey(k)
        })
        keysListEl.appendChild(el)
      })
  }

  function selectKey(k) {
    selectedKey = k
    keyInputEl.value = k
    valueEl.value = localStorage.getItem(k) || ''
    listKeys(searchEl.value.trim())
  }

  function saveSelected() {
    const k = (keyInputEl.value || '').trim()
    if (!k) return alert('请输入 key')
    try {
      localStorage.setItem(k, valueEl.value)
      selectedKey = k
      listKeys(searchEl.value.trim())
      alert('保存成功')
    } catch (e) {
      alert('保存失败:' + e)
    }
  }

  function deleteSelected() {
    if (!selectedKey) return alert('请先选择要删除的 key')
    if (!confirm('确认删除 key: ' + selectedKey + ' ?')) return
    try {
      localStorage.removeItem(selectedKey)
      selectedKey = null
      keyInputEl.value = ''
      valueEl.value = ''
      listKeys(searchEl.value.trim())
      alert('删除成功')
    } catch (e) {
      alert('删除失败:' + e)
    }
  }

  function exportAll() {
    const obj = {}
    for (let i = 0; i < localStorage.length; i++) {
      const k = localStorage.key(i)
      if (k == null) continue
      obj[k] = localStorage.getItem(k) || ''
    }
    const text = JSON.stringify(obj, null, 2)
    // copy to clipboard if possible
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(text).then(
        () => alert('已复制到剪贴板'),
        () => downloadText('localStorage-export.json', text)
      )
    } else {
      downloadText('localStorage-export.json', text)
    }
  }

  function downloadText(filename, text) {
    const a = document.createElement('a')
    const blob = new Blob([text], { type: 'application/json' })
    a.href = URL.createObjectURL(blob)
    a.download = filename
    document.body.appendChild(a)
    a.click()
    a.remove()
  }

  function importFromText(text, options = { overwrite: false }) {
    try {
      const parsed = JSON.parse(text)
      if (parsed && typeof parsed === 'object') {
        const keys = Object.keys(parsed)
        if (keys.length === 0) return alert('导入的 JSON 为空')
        let overwritten = 0
        keys.forEach(k => {
          const v = String(parsed[k])
          if (!options.overwrite && localStorage.getItem(k) != null) {
            // skip
          } else {
            if (localStorage.getItem(k) != null) overwritten++
            localStorage.setItem(k, v)
          }
        })
        listKeys(searchEl.value.trim())
        alert('导入完成,已覆盖 ' + overwritten + ' 项')
      } else {
        alert('导入失败:JSON 格式不正确')
      }
    } catch (e) {
      alert('导入失败:解析 JSON 错误\n' + e)
    }
  }

  // UI events
  toggle.addEventListener('click', () => {
    panel.style.display = panel.style.display === 'block' ? 'none' : 'block'
  })

  closeBtn.addEventListener('click', () => (panel.style.display = 'none'))
  searchEl.addEventListener('input', () => listKeys(searchEl.value.trim()))
  newBtn.addEventListener('click', () => {
    const k = (keyInputEl.value || '').trim()
    if (!k) return alert('请输入 key')
    selectKey(k)
  })
  saveBtn.addEventListener('click', saveSelected)
  deleteBtn.addEventListener('click', deleteSelected)
  copyBtn.addEventListener('click', () => {
    const v = valueEl.value
    if (!navigator.clipboard) return alert('复制失败:浏览器不支持剪贴板 API')
    navigator.clipboard.writeText(v).then(
      () => alert('已复制值到剪贴板'),
      () => alert('复制失败')
    )
  })
  clearBtn.addEventListener('click', () => {
    if (!confirm('确认清空 localStorage(当前域)?此操作不可恢复')) return
    try {
      localStorage.clear()
      selectedKey = null
      keyInputEl.value = ''
      valueEl.value = ''
      listKeys(searchEl.value.trim())
      alert('已清空')
    } catch (e) {
      alert('清空失败:' + e)
    }
  })

  exportBtn.addEventListener('click', exportAll)

  importBtn.addEventListener('click', () => {
    // Offer two options: paste JSON or choose file
    const choice = confirm('点击 OK 从文件导入 (.json),点击 Cancel 粘贴 JSON 导入')
    if (choice) {
      fileInput.value = ''
      fileInput.click()
    } else {
      const text = prompt('请粘贴 JSON 内容:')
      if (text) importFromText(text, { overwrite: true })
    }
  })

  fileInput.addEventListener('change', ev => {
  const input = ev.target
    if (!input.files || input.files.length === 0) return
    const file = input.files[0]
    const reader = new FileReader()
    reader.onload = () => {
      const text = String(reader.result || '')
      // Ask whether to overwrite existing keys
      const overwrite = confirm('是否覆盖已存在的相同 key?点击 OK 覆盖,Cancel 则跳过已存在 key')
      importFromText(text, { overwrite })
    }
    reader.onerror = () => alert('读取文件失败')
    reader.readAsText(file)
  })

  // initial
  listKeys()

  // expose for debugging in console
  ;(window).__localStorageEditor = {
    open: () => (panel.style.display = 'block'),
    close: () => (panel.style.display = 'none'),
    listKeys
  }
})()

1 个赞

偷一点:pinching_hand:

[
  {
    "id": "emoji-1758866638297-tu5lij",
    "packet": 1758866638297,
    "name": "AgADKRwAAto0KVU.webp",
    "url": "https://cdn3.linux.do/original/4X/f/4/5/f451313a2cbc79b2fc1cb7cf8382487c9dd0ea29.webp",
    "width": 512,
    "height": 299,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-ls5qw5",
    "packet": 1758866638297,
    "name": "AgADdSEAAtKZKVU.webp",
    "url": "https://cdn3.linux.do/original/4X/8/4/1/841ef45e32d45b2f00e0fc2d8fdb4b9d142b47ad.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-xt8fm4",
    "packet": 1758866638298,
    "name": "AgADeRcAAgvykFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/b/9/6/b96ab4ea2fcc82b28b4a2cde1c4982005f3f98e2.webp",
    "width": 422,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-v1akx7",
    "packet": 1758866638298,
    "name": "AgADExgAAgwgiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/f/8/af8bcc9383a040add8c711b50e409c506221d5a2.webp",
    "width": 512,
    "height": 393,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-ztp2y7",
    "packet": 1758866638298,
    "name": "AgADExkAAkO5MFU.webp",
    "url": "https://cdn3.linux.do/original/4X/4/a/2/4a2bea46b8897a4cfe283d8b30ab61da42383d3f.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-358458",
    "packet": 1758866638298,
    "name": "AgADExUAAiUfiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/c/1/8c187246b019ed028ca1b4d661db314c304ec2e9.webp",
    "width": 512,
    "height": 490,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-v180il",
    "packet": 1758866638298,
    "name": "AgADFBsAAuKhMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/6/c/3/6c3ba3500325a3abca17e2e7a833b00dec5ab1d1.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-635mq1",
    "packet": 1758866638298,
    "name": "AgADFhoAAhhTiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/f/0/c/f0c66e6642b06ccd6e6b70aed47955efffe50662.webp",
    "width": 512,
    "height": 373,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-g130ue",
    "packet": 1758866638298,
    "name": "AgADfhwAAt2pMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/6/b/c/6bce4105470500f6df22a3e378edd1f40f8b7673.webp",
    "width": 458,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-pz8j8l",
    "packet": 1758866638298,
    "name": "AgADGRoAAprbyVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/d/d/4/dd4453e2f81f120fb55ea740dd665bbc49c1d026.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-5uf5jx",
    "packet": 1758866638298,
    "name": "AgADhBoAAr9aMVU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/1/0/010db175fae7e8536ec5654d3b84c72cbfb88216.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-qnzj9w",
    "packet": 1758866638298,
    "name": "AgAD-hcAAn4CgVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/e/c/7/ec72889382902349537b0c8a0c5c3ac792edf367.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-lv0qme",
    "packet": 1758866638298,
    "name": "AgAD-xgAApSriFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/1/d/e/1deb40bd4a22ab1014fb1c35a98acea3babbf948.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-rtx7ik",
    "packet": 1758866638298,
    "name": "AgAD2hsAAharwFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/4/0/0/400ee88b26a1296d5fbed9d2aac4b3e4cabc4e20.webp",
    "width": 362,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-kmygym",
    "packet": 1758866638298,
    "name": "AgAD2xgAAteH2VQ.gif",
    "url": "https://cdn3.linux.do/original/4X/7/6/a/76aef6c231f8b5032b1dee22685fbf6d39217296.gif",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-95qmt2",
    "packet": 1758866638298,
    "name": "AgAD3RgAAkLrgVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/7/d/87dc00bd7ab247494fd1b46b7e96f4eeb0db5139.webp",
    "width": 437,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-5l1inr",
    "packet": 1758866638298,
    "name": "AgAD3xkAAkZYKFU.webp",
    "url": "https://cdn3.linux.do/original/4X/f/0/0/f002095a15b25120dadb119bf7ef1e6744d8f56e.webp",
    "width": 512,
    "height": 506,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-jvh8ti",
    "packet": 1758866638298,
    "name": "AgAD4xUAAkbEiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/c/4/d/c4d6e5627a60a1cb47352e860318c7936bde1d39.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-m3o3p2",
    "packet": 1758866638298,
    "name": "AgAD5xgAAh76MVU.webp",
    "url": "https://cdn3.linux.do/original/4X/1/f/a/1fad227856f76c306600e23d260c869d1fe28de0.webp",
    "width": 512,
    "height": 339,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-l01h8b",
    "packet": 1758866638298,
    "name": "AgAD6RoAAlEuiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/b/c/9/bc94b8c44b74d7d17689bcf5d0275dd8a548406c.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638298-4wtdw2",
    "packet": 1758866638298,
    "name": "AgAD7hcAAiFuKVU.webp",
    "url": "https://cdn3.linux.do/original/4X/5/6/8/5683e7fa167e398d18c5832cf8b849c82f5b58c0.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-t25hvv",
    "packet": 1758866638298,
    "name": "AgAD8hoAAsPBkVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/f/4/c/f4c90063f8bbbcd6021e0b9de59afe197b15aa88.webp",
    "width": 290,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-x1x0qo",
    "packet": 1758866638299,
    "name": "AgAD8xcAAihBiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/d/4/6/d465fcf103a5da91e2a7fb19dc1334fdd661b52a.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-ieketn",
    "packet": 1758866638299,
    "name": "AgAD9BcAAkeEMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/8/6/d/86d7918b25e6a1559d0b97c8dfbe872214eaf72d.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-023ajf",
    "packet": 1758866638299,
    "name": "AgAD9BoAAjqfKVU.webp",
    "url": "https://cdn3.linux.do/original/4X/d/3/6/d36f9c3cb5c4db6f54ff94310937bf0e7195ffc7.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-xidg9x",
    "packet": 1758866638299,
    "name": "AgAD_h8AAgXoKFU.webp",
    "url": "https://cdn3.linux.do/original/4X/5/b/0/5b09eda4963de337f8049a2f5a29ffe32d0d5330.webp",
    "width": 512,
    "height": 328,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-c0kpur",
    "packet": 1758866638299,
    "name": "AgADaBgAAhjxkFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/2/f/82f4c87343e53529fb40436be8a4ef8d2e332627.webp",
    "width": 512,
    "height": 361,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-n56cav",
    "packet": 1758866638299,
    "name": "AgADaBkAAuLsiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/b/5/d/b5d3e1a84affce04bc4d6b285deb9b8b102aefd3.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-lk2a2p",
    "packet": 1758866638299,
    "name": "AgADaRcAAlFmiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/6/1/661b3589fae14c56dafd3305b0ff48fc9e453a46.webp",
    "width": 512,
    "height": 290,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-9o8zc9",
    "packet": 1758866638299,
    "name": "AgADbBcAArZ1MFU.webp",
    "url": "https://cdn3.linux.do/original/4X/3/5/2/35236fc9420b065114de85119e1526410932bc6b.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-tqp52y",
    "packet": 1758866638299,
    "name": "AgADbR0AAiWEiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/4/0/b/40b637851f4d4e41b330510a13872aae9b1dd643.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-mt9j3v",
    "packet": 1758866638299,
    "name": "AgADCRoAApjdkFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/2/7/6/276139c6d158852f25ba83e08f4b7bb1c8451b0d.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-be1dzo",
    "packet": 1758866638299,
    "name": "AgADCx0AAieFiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/d/0/9/d09b19c8fa59bae7f7fd5707cc7a8de3f0f48b06.webp",
    "width": 512,
    "height": 326,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-wps2ex",
    "packet": 1758866638299,
    "name": "AgADDB4AAscBiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/5/f/3/5f37ef193cf97985b8b8250de28b48b001d3600d.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-wg7tou",
    "packet": 1758866638299,
    "name": "AgADDhwAAvQaiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/e/8/ae8fd0c928fd450c9147be331c247f6acf835bb6.webp",
    "width": 375,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-ok47nx",
    "packet": 1758866638299,
    "name": "AgADdicAAgl8KFU.webp",
    "url": "https://cdn3.linux.do/original/4X/1/d/3/1d34fa5dc16677a7c606aa3f1842bc381503a77c.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-cwojur",
    "packet": 1758866638299,
    "name": "AgADbRcAApv3iFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/e/9/9/e996647c27639819589e120708a6060c4370a80b.webp",
    "width": 512,
    "height": 360,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-u77lu2",
    "packet": 1758866638299,
    "name": "AgADbycAAuFoiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/b/2/5/b25749447b0e0c7ecfa84d42f341c7946875e2bb.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-2klg9v",
    "packet": 1758866638299,
    "name": "AgADChkAApw7gFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/6/b/a6b4aedf2da795b3778cfde63ed8430728eda7c7.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-ez2tx8",
    "packet": 1758866638299,
    "name": "AgADCRkAAvkRiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/b/6/9/b69ca93ac875c7513131d6eb0fc8377d2ff2f01e.webp",
    "width": 428,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-w1etp2",
    "packet": 1758866638299,
    "name": "AgADdRsAAjmbMVU.webp",
    "url": "https://cdn3.linux.do/original/4X/f/7/c/f7c6954969d8a69dfd62e72bb4336426e09c8b48.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-9yt2n2",
    "packet": 1758866638299,
    "name": "AgADDRsAAuTwwVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/1/2/6/12698c7a3bfd8efe75208e0bbe5cabf6f015d01f.webp",
    "width": 410,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-j57cgp",
    "packet": 1758866638299,
    "name": "AgADHBsAAhzyiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/a/7/aa7eeb7fa290500fdd6a4aa07c35dcb57ee166b3.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-gay0wh",
    "packet": 1758866638299,
    "name": "AgADhRgAAlhzkFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/4/c/f/4cf0a85b35a70003add113093356c9b09df6e101.webp",
    "width": 512,
    "height": 384,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-na621q",
    "packet": 1758866638299,
    "name": "AgADhRgAArHiiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/7/c/b/7cb845b69d196c8df9b17ccf3780945cf4ab0c89.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-09s128",
    "packet": 1758866638299,
    "name": "AgADHxgAAstwiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/d/1/6d10f84e6d5e2b15d5571a51e6d3d46ae1dc8b3d.webp",
    "width": 512,
    "height": 409,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-lzmezb",
    "packet": 1758866638299,
    "name": "AgADHxkAAof9MFU.webp",
    "url": "https://cdn3.linux.do/original/4X/f/a/5/fa5bd415f5741f5915b5c59e47cccd41715e2e40.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-8nu6y5",
    "packet": 1758866638299,
    "name": "AgADHxkAAop9iVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/2/5/625c0d3580cbbcb837b7db4791f59f2954bdae76.webp",
    "width": 328,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-7h24lv",
    "packet": 1758866638299,
    "name": "AgADhyIAAg3OiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/5/c/7/5c740585835f972618c61152c09e65edb1b0bfd5.webp",
    "width": 512,
    "height": 457,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-3o2x2x",
    "packet": 1758866638299,
    "name": "AgADiBcAAmv7MFU.webp",
    "url": "https://cdn3.linux.do/original/4X/7/6/0/7602d0eb943bb0e60af992b6bbd6fdd262d55d38.webp",
    "width": 342,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-hvnpil",
    "packet": 1758866638299,
    "name": "AgADiRkAAivsMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/a/4/a/a4ac85e8d9645e1a83468883a1a698bd2223383e.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-hf2y8x",
    "packet": 1758866638299,
    "name": "AgADISUAAkr0gFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/6/0/6605819d514f833c20400772f07d0ca402457938.webp",
    "width": 512,
    "height": 325,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-86kync",
    "packet": 1758866638299,
    "name": "AgADjBkAAg28KVU.webp",
    "url": "https://cdn3.linux.do/original/4X/a/b/6/ab647d8b1b71aaacd8bbb097168fd8fd5c6dc3fd.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-zbhawl",
    "packet": 1758866638299,
    "name": "AgADjBkAAlcoiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/1/e/2/1e2eb0e11203d453e539c9c87897da4036b3f491.webp",
    "width": 298,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-cbrb67",
    "packet": 1758866638299,
    "name": "AgADjBkAAm6gMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/e/0/0e0d1b53abfc35a2e1ce8c954c96ca9a0076afe6.webp",
    "width": 512,
    "height": 310,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-b0f216",
    "packet": 1758866638299,
    "name": "AgADJhcAAhNjiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/6/e/66e370c77e0e239f4b9330f391d1eb2d3e2e3985.webp",
    "width": 442,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-v1818b",
    "packet": 1758866638299,
    "name": "AgADjhMAAhTYiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/2/c/82c006a4c3c89935a3ff5987c8c9e8b5e15d40af.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638299-6z3uz7",
    "packet": 1758866638299,
    "name": "AgADJhsAAvIxiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/2/0/a2096cedfd683649ac5e1b098c36d11bc31d443d.webp",
    "width": 455,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-6rh49n",
    "packet": 1758866638300,
    "name": "AgADJRoAAlb9gFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/b/a/8/ba84a048bd5059d23ebb45e8fd9b3bc095eb3e55.webp",
    "width": 512,
    "height": 385,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-hw3sem",
    "packet": 1758866638300,
    "name": "AgADJxoAAlYbiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/d/1/b/d1b674fe3b80fbbd7b6d98fdb7b6ca29a38e60b4.webp",
    "width": 512,
    "height": 380,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-nf7nbe",
    "packet": 1758866638300,
    "name": "AgADkRgAArBYiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/3/5/7/35744ee8f1e50b4c1bad5778b3d805de693a29ad.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-ag2q1a",
    "packet": 1758866638300,
    "name": "AgADKxgAAsslKVU.webp",
    "url": "https://cdn3.linux.do/original/4X/8/7/5/8755b609fe288a504ccb3bd13b5816ebf39871b4.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-oqz3m6",
    "packet": 1758866638300,
    "name": "AgADkxYAAiFAiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/9/1/5/915f9a3e27cdb0f7b0afbbc83bef15ea6dc8eee7.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-q8awl7",
    "packet": 1758866638300,
    "name": "AgADLhcAAgWcKVU.webp",
    "url": "https://cdn3.linux.do/original/4X/e/d/a/eda3d4270c12e7a6e05f83b768c1397a068a2d69.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-ejp4lc",
    "packet": 1758866638300,
    "name": "AgADlRsAAnb6iFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/e/0/ae0058b42a1e092762757a60a64d2da56fec3e66.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-m7yckh",
    "packet": 1758866638300,
    "name": "AgADnBkAArTBiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/d/6/8d6d7956cb5690a7645a1d48d486d7ef898478d1.webp",
    "width": 357,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-cudoef",
    "packet": 1758866638300,
    "name": "AgADnRcAAtgcMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/6/d/6/6d606aaba6b061d72573424a0214bd0c55f0505d.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-czeljf",
    "packet": 1758866638300,
    "name": "AgADoBkAArBMiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/b/c/4/bc40828b85be8f6a5946826e37c94f3142b82021.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-7tv41o",
    "packet": 1758866638300,
    "name": "AgADOBoAAri4kFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/e/e/2/ee2fc328efc1e8c3125356c1d4db438d69947d07.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-dltbdu",
    "packet": 1758866638300,
    "name": "AgADOhoAAvxOMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/4/d/c/4dca276671f044fa3e8133066cfd49ce0c797de9.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-8fjadd",
    "packet": 1758866638300,
    "name": "AgADoRoAAtDXkFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/c/e/3/ce317285ce59e1e5b2894983400308c2a55fda01.webp",
    "width": 512,
    "height": 410,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-wrivvv",
    "packet": 1758866638300,
    "name": "AgADPBcAAvDniVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/f/2/8f23ef323019ac00a2f619b780fbb1036b4a082a.webp",
    "width": 512,
    "height": 463,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-8oc6xv",
    "packet": 1758866638300,
    "name": "AgADPBkAAilDiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/3/3/a333eb53f4f4315c1336088d563b99755ebe9497.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-my4za6",
    "packet": 1758866638300,
    "name": "AgADPBsAAlm5iVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/d/e/6deb9a3d3ac014d175d87dbec29889b6759d1b9e.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-e4kn6x",
    "packet": 1758866638300,
    "name": "AgADphkAAsMIiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/6/6/6661ed0c85f52a502dca961b54e4c78b037f7b05.webp",
    "width": 364,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-p0q33v",
    "packet": 1758866638300,
    "name": "AgADPhwAAliNiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/d/0/1/d01c84135772ff852646c7c0bade8b3c29bf3542.webp",
    "width": 470,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-n1ujpe",
    "packet": 1758866638300,
    "name": "AgADpx4AAhgEiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/1/a/5/1a5baecf2f4be3bd0b4758d27bb523c657fce664.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-5xvzw3",
    "packet": 1758866638300,
    "name": "AgADQRgAAul1MVU.webp",
    "url": "https://cdn3.linux.do/original/4X/7/4/0/7409dd666c0b63bb0b1cd838e15367283a9025e9.webp",
    "width": 469,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-l079l0",
    "packet": 1758866638300,
    "name": "AgADrCgAAnUFiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/e/b/8/eb8b8dee2ffdb6d5ce6cd1ccb5ed37b28496c34d.webp",
    "width": 358,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-yzfu7q",
    "packet": 1758866638300,
    "name": "AgADRh0AAnf7KFU.webp",
    "url": "https://cdn3.linux.do/original/4X/4/5/5/4556d6121e0c2263907e982dc25f6476bd6ab0dd.webp",
    "width": 512,
    "height": 495,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-jb9r2q",
    "packet": 1758866638300,
    "name": "AgADrhcAAnCIMVU.webp",
    "url": "https://cdn3.linux.do/original/4X/b/b/d/bbd4f613ee987e3943f8ed523716f3767e1621c9.webp",
    "width": 386,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-g578yl",
    "packet": 1758866638300,
    "name": "AgADrxYAAme9kVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/e/0/ae07a8a6fc56228d4cf9bc19f79378fc2fb44351.webp",
    "width": 512,
    "height": 481,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-7nn9hb",
    "packet": 1758866638300,
    "name": "AgADrxYAAnu9MFU.webp",
    "url": "https://cdn3.linux.do/original/4X/a/a/9/aa91f45dc32498bd4f39adc54996d45fa79e9b07.webp",
    "width": 512,
    "height": 392,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-zr9drr",
    "packet": 1758866638300,
    "name": "AgADryUAAlRPMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/d/b/0dbdbc9cfac02440325d5c77c7eb76fcc23270eb.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-cnf5td",
    "packet": 1758866638300,
    "name": "AgADsBYAArRciFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/9/b/5/9b52cdb7b4234640db252def4502f8c04f7dba30.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-xjusm3",
    "packet": 1758866638300,
    "name": "AgADsxUAAqpliVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/3/5/d/35de1d7ce57b645e78321a3583e9ee9cd7442ff1.webp",
    "width": 375,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-sff8gq",
    "packet": 1758866638300,
    "name": "AgADTBoAAgdPMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/3/3/4/3343002806928b6044d9019467608dbea84ba2cd.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-nuvgy8",
    "packet": 1758866638300,
    "name": "AgADtRgAAtWKMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/9/9/4/9947fc80f42212b5e52a80372bfc3becba39f0d5.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-br2ugp",
    "packet": 1758866638300,
    "name": "AgADuBcAArCcKFU.webp",
    "url": "https://cdn3.linux.do/original/4X/5/5/4/554950c273b1474875108699ee2c1db8054f5e93.webp",
    "width": 512,
    "height": 358,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-fz864u",
    "packet": 1758866638300,
    "name": "AgADuBkAAoRJiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/0/5/4/0544d99a6658687a107b10e93bbe805fb0ddd5fb.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-i3b65y",
    "packet": 1758866638300,
    "name": "AgADuBoAAlpikFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/9/f/69f4c8eb4bdf9cb6abff843a65e1247d13aaedb8.webp",
    "width": 422,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-rfur0h",
    "packet": 1758866638300,
    "name": "AgADuRwAAlAWiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/c/d/d/cddee3e5ba08fb11ba71e51055ebc25be10ca59c.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-s071m0",
    "packet": 1758866638300,
    "name": "AgADuxkAAlaPMVU.webp",
    "url": "https://cdn3.linux.do/original/4X/4/6/8/4680b7a51137a142cfbf853bbc8b9122bec0e69b.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-lr6fpv",
    "packet": 1758866638300,
    "name": "AgADUxYAAgcUMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/c/b/1/cb1c0cdaa86aa66163bf335fd99d69681a86ed55.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-p63q2b",
    "packet": 1758866638300,
    "name": "AgADVB4AAv0ViFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/2/1/2/2122b63c42cb1d2f1f8698dba752703435b50032.webp",
    "width": 512,
    "height": 432,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-g5t0po",
    "packet": 1758866638300,
    "name": "AgADvhcAAgLZKFU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/2/b/02b278ce5dd847a3e980e5cde29bd9c9aca66183.webp",
    "width": 512,
    "height": 486,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-5xniaa",
    "packet": 1758866638300,
    "name": "AgADVhcAAun7iVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/7/4/5/745f3614a1ad676cb5ce14661dbe9a5f91b7169b.webp",
    "width": 512,
    "height": 433,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-lu68xa",
    "packet": 1758866638300,
    "name": "AgADvxgAAugs4VQ.gif",
    "url": "https://cdn3.linux.do/original/4X/6/6/b/66bb8ecad1462cda317efdae39aeb0123f5d1e96.gif",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-ncq5j5",
    "packet": 1758866638300,
    "name": "AgADvxoAAsiTgVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/b/a/6/ba63ebaf0f1c7ab3db3e20781ee1cc98e405ad56.webp",
    "width": 470,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-ctnuaz",
    "packet": 1758866638300,
    "name": "AgADWRkAAqn1kVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/3/c/63c639a2150cc4961952179598a25b12e74e6fe7.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-gps1qw",
    "packet": 1758866638300,
    "name": "AgADwxYAAgzRiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/7/1/2/7123247d98eee47e2df0c39288705e3706e74a5e.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-i29vnr",
    "packet": 1758866638300,
    "name": "AgADxxkAAuWQyFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/0/7/e/07e6a46aa382503b26602006549a58228416de46.webp",
    "width": 512,
    "height": 382,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-l0io3p",
    "packet": 1758866638300,
    "name": "AgADyhcAAo4viVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/4/2/a42ea57bba4fa27ad921cd465e745b98425ab464.webp",
    "width": 414,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-d7d7wx",
    "packet": 1758866638300,
    "name": "AgADyhgAAveaiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/3/f/a/3fa5ff9bd752ed31d66b2cb8d3a08037f6169d08.webp",
    "width": 512,
    "height": 398,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-gbun0x",
    "packet": 1758866638300,
    "name": "AgADyhYAAo_jMFU.webp",
    "url": "https://cdn3.linux.do/original/4X/f/c/9/fc9a05a67eb27084b5a5290679f17b11da85abb4.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-oimlv9",
    "packet": 1758866638300,
    "name": "AgADYRgAAmKnMVU.webp",
    "url": "https://cdn3.linux.do/original/4X/5/b/6/5b6d2bad30c2c98a1cd7b85e7e6d2fd762e8609d.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-d3caa1",
    "packet": 1758866638300,
    "name": "AgADyxsAAwkxVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/1/d/e/1deb1966dae9be659841e09a2f7a2ce2413a6c79.webp",
    "width": 512,
    "height": 370,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-753gcs",
    "packet": 1758866638300,
    "name": "AgADzxkAAnS3iVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/c/8/9/c898fe9cde1b779c7214db1ba6a75f816a953ae3.webp",
    "width": 470,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-5d3n4a",
    "packet": 1758866638300,
    "name": "AgAEGAACDV0oVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/d/1/5/d156dcfa7f598e08c9dbb8d6b3493b1e204fe135.webp",
    "width": 440,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-52pzxf",
    "packet": 1758866638300,
    "name": "AgADiRkAAqO1MFU.webp",
    "url": "https://cdn3.linux.do/original/4X/d/8/8/d88f294103492faecc5113addc6660acf703894c.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-um7y4a",
    "packet": 1758866638300,
    "name": "AgADJhoAAjbfkVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/4/d/6/4d6519a8745df0389e229fc6dd022422508e8c00.webp",
    "width": 512,
    "height": 394,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-yrhoqy",
    "packet": 1758866638300,
    "name": "AgADNRoAArzSiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/b/3/ab33448017bb964e6e8b45b03e1b489fe305bc8e.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-hwksv0",
    "packet": 1758866638300,
    "name": "AgADPBcAAtstkVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/2/5/7/25728e9815c3151656be8d5ad4c7d6fa36988c27.webp",
    "width": 512,
    "height": 420,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-39w2nc",
    "packet": 1758866638300,
    "name": "AgADPxgAAqJlKFU.webp",
    "url": "https://cdn3.linux.do/original/4X/0/6/9/06991c56fde17289f27fd7b10afec1ff9336965a.webp",
    "width": 330,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-0i1w9s",
    "packet": 1758866638300,
    "name": "AgADRRwAAv5TiFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/e/b/9/eb9f6f8509c4224ccbedb689d4dfb40373623413.webp",
    "width": 512,
    "height": 349,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-5546ts",
    "packet": 1758866638300,
    "name": "AgADThcAAmKRiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/6/6/a/66aa10799b9f461f299294982da04dd70c973568.webp",
    "width": 512,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-3n31nq",
    "packet": 1758866638300,
    "name": "AgADURsAAk1tyFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/0/8/808b7690a9d2fe106fd2d0417a34897391b9de7e.webp",
    "width": 512,
    "height": 424,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-ujql3i",
    "packet": 1758866638300,
    "name": "AgADZBkAApB0iFQ.webp",
    "url": "https://cdn3.linux.do/original/4X/4/b/f/4bf4551ba80415724a1780a5e1aa73bedff32db8.webp",
    "width": 512,
    "height": 382,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-s3huc5",
    "packet": 1758866638300,
    "name": "AgAD7xUAAt0ZkVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/8/9/4/8946791b3c9afc1f8abc3238673b62e33dc5e46e.webp",
    "width": 436,
    "height": 512,
    "groupId": "少女2"
  },
  {
    "id": "emoji-1758866638300-xt9ni2",
    "packet": 1758866638300,
    "name": "AgADxRkAAieiiVQ.webp",
    "url": "https://cdn3.linux.do/original/4X/a/c/e/ace1576aea5669ec6fb7e23141afe80440c6f4d8.webp",
    "width": 512,
    "height": 360,
    "groupId": "少女2"
  }
]
1 个赞

297 297 297

用上了,感谢大佬!

2 个赞

老哥,下载了插件文件,咋用啊

@stevessr 我不知道啊,其实我只是水一帖

1 个赞

打开拓展的开发者模式,解压,然后拖入解压的文件夹

edge cannary(安卓)下载那个crx版本,解压后,直接从开发者选项安装

2 个赞

[!success]+
thumbsup.png 搞好了

1 个赞