如何开发一个自动发送微博私信的chrome插件

背景

需要给很多个用户发同样的私信时需要大量重复工作,如果能自动发送私信就能节省很多人力

难点分析

  1. chrome各端如何相互通信
  2. 私信怎么发给不同人
  3. 怎么发送私信

chrome插件怎么开发,各端如何通信

参照<font color=blue>这篇博客</font>,非常详细

私信怎么发给不同人

在网页微博中可以发现点击私信一个陌生人后,会跳转到一个私信窗口,此时url中是携带一个用户uid的,根据这个uid我们通过跳转url来实现给不同用户发私信

怎么发送私信

  1. 在inject-script中选中输入框
  2. 给输入框赋值value
  3. 用js触发敲击空格事件
  4. 用js触发敲击回车事件
  • 需要触发空格事件的原因:单纯赋值并不能触发onChange事件,导致回车不能将消息发出去,触发回车后即可
  • 第二步到第四步必须依次触发,键盘io是异步的,所以可以使用定时器控制

inject-script

用途:获取dom,发送私信

function fireKeyEvent(el, evtType, keyCode){
    var doc = el.ownerDocument,
        win = doc.defaultView || doc.parentWindow,
        evtObj;
    if(doc.createEvent){
        if(win.KeyEvent) {
            evtObj = doc.createEvent('KeyEvents');
            evtObj.initKeyEvent( evtType, true, true, win, false, false, false, false, keyCode, 0 );
        }
        else {
            evtObj = doc.createEvent('UIEvents');
            Object.defineProperty(evtObj, 'keyCode', {
                get : function() { return this.keyCodeVal; }
            });     
            Object.defineProperty(evtObj, 'which', {
                get : function() { return this.keyCodeVal; }
            });
            evtObj.initUIEvent( evtType, true, true, win, 1 );
            evtObj.keyCodeVal = keyCode;
            if (evtObj.keyCode !== keyCode) {
                console.log("keyCode " + evtObj.keyCode + " 和 (" + evtObj.which + ") 不匹配");
            }
        }
        el.dispatchEvent(evtObj);
    } 
    else if(doc.createEventObject){
        evtObj = doc.createEventObject();
        evtObj.keyCode = keyCode;
        el.fireEvent('on' + evtType, evtObj);
    }
}

function sendText() {
  const target = document.querySelector('#webchat-textarea')
  let textTimer
  if (target) {
    clearTimeout(textTimer)
    target.value = 'xxx'
    
    setTimeout(() => {
      target.focus()
      fireKeyEvent(target, 'keydown', 8)
      setTimeout(() => {
        fireKeyEvent(target, 'keydown', 13)
      }, 1000)
    }, 1000)
  } else {
    textTimer = setTimeout(() => {
      sendText()
    }, 200)
  }
}

setTimeout(() => {
  sendText()
}, 0)

content-script

用途:注入inject-script,可以与popup.js做通信

function injectCustomJs(jsPath) {
  jsPath = jsPath || 'js/inject.js'
  var temp = document.createElement('script')
  temp.setAttribute('type', 'text/javascript')
  temp.src = chrome.extension.getURL(jsPath)
  temp.onload = function () {
    this.parentNode.removeChild(this)
  }
  document.head.appendChild(temp)
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min
}

function Toast(msg, duration) {
  duration = isNaN(duration) ? 3000 : duration
  var m = document.createElement('div')
  m.innerHTML = msg
  m.style.cssText =
    'max-width:60%;min-width: 150px;padding:0 14px;height: 40px;color: rgb(255, 255, 255);line-height: 40px;text-align: center;border-radius: 4px;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);z-index: 999999;background: rgba(0, 0, 0,.7);font-size: 16px;'
  document.body.appendChild(m)
  setTimeout(function () {
    var d = 0.5
    m.style.webkitTransition =
      '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in'
    m.style.opacity = '0'
    setTimeout(function () {
      document.body.removeChild(m)
    }, d * 1000)
  }, duration)
}

window.addEventListener('load', function() {
  injectCustomJs()
})

let timer
let sendTimer
let uidArr = []
let interval
let initinterval
let status = ''

chrome.extension.onMessage.addListener(function (
  request,
  sender,
  sendResponse
) {
  if (request.cmd == 'start') {
    Toast('已开始发私信', 2000)
    uidArr = request.uids
    initinterval = request.interval
    interval = (+request.interval + getRandomInt(1, 5)) * 1000
    status = 'start'
    timer = setInterval(() => {
      if (uidArr.length) {
        window.open(
          `https://api.weibo.com/chat/#/chat?to_uid=${uidArr[0]}&source_from=9`,
          '_blank'
        )
        uidArr.shift()
        sendResponse('recived')
      } else {
        clearInterval(timer)
      }
    }, interval)
  }
  if (request.cmd == 'stop') {
    status = 'stop'
    Toast('已结束发私信', 2000)
    clearInterval(timer)
  }
  if (request.cmd == 'continue') {
    status = 'continue'
    Toast('已继续发私信', 2000)
    timer = setInterval(() => {
      if (uidArr.length) {
        window.open(
          `https://api.weibo.com/chat/#/chat?to_uid=${uidArr[0]}&source_from=9`,
          '_blank'
        )
        uidArr.shift()
        sendResponse('recived')
      } else {
        clearInterval(timer)
      }
    }, interval)
  }
})
sendTimer = setInterval(() => {
  chrome.extension.sendMessage(
    { greeting: uidArr, status: status, interval: initinterval },
    function (response) {
      // console.log('收到来自后台的回复:' + response);
    }
  )
}, 1000)
if (status === 'stop') {
  clearInterval(sendTimer)
}

index.html

用途:点击插件后弹框的结构样式

manifest.json

用途:各种配置项,详情见上文博客

popup-script

用途:index.html的js文件,在index.html中引入,可以做一些事件监听,dom操作的事情

let uidArr = []
let interval = 30
function sendMessageToContentScript(message, callback) {
  chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
    chrome.tabs.sendMessage(tabs[0].id, message, function (response) {
      if (callback) callback(response)
    })
  })
}
document.querySelector('#start').addEventListener('click', function () {
  uidArr = document.querySelector('#list').value.split(/\n|\r/)
  interval = document.querySelector('#interval').value
  sendMessageToContentScript(
    { cmd: 'start', uids: uidArr, interval: interval },
    function (response) {
      console.log('来自content的回复:' + response)
    }
  )
})

document.querySelector('#stop').addEventListener('click', function () {
  if (document.querySelector('#stop').innerHTML === '停止') {
    document.querySelector('#stop').innerHTML = '继续'
    sendMessageToContentScript({ cmd: 'stop' }, function (response) {
      console.log('来自content的回复:' + response)
    })
  } else {
    document.querySelector('#stop').innerHTML = '停止'
    sendMessageToContentScript({ cmd: 'continue' }, function (response) {
      console.log('来自content的回复:' + response)
    })
  }
})

chrome.extension.onMessage.addListener(function (
  request,
  sender,
  sendResponse
) {
  if (request.greeting.length) {
    document.querySelector('#list').value = request.greeting.join('\n')
  }
  if (request.status && request.status === 'stop') {
    document.querySelector('#stop').innerHTML = '继续'
  }
  if (request.status && request.status === 'continue') {
    document.querySelector('#stop').innerHTML = '停止'
  }
  if (request.interval) {
    document.querySelector('#interval').value = request.interval
  }
})

源码地址

https://github.com/chuheji/weibo-sendMessage-Chromextension/tree/master

后记

这个插件是半年前开发的,当时水平有限,代码比较粗糙,见谅

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容