Vue.jsで好きなだけ「大石泉すき」とツイートしてみる


この記事は 「大石泉すき」アドベントカレンダー 12日目の記事です。
今回は重複を気にせず「大石泉すき」とツイートしていきたいと思います。

好きなだけ「大石泉すき」とツイートできるページ

こちらからどうぞ。

Tweet 大石泉すき without duplicated entry
https://ohishi-izumi-suki.herokuapp.com/

ソースコードはこちら。

m19e/non-duplication-tweet
https://github.com/m19e/non-duplication-tweet

諸注意

このページはVue.jsで作ってHerokuでホスティングされていますが、
両方とも細かい説明はしていないので予めご了承ください。

公式サイト↓
Vue.js - The Progressive JavaScript Framework

Herokuへのデプロイはこちらを参考にしました↓
Vue.jsのアプリケーションを手早くHerokuで公開する

何をしているのか

templateとmethodsはこんな感じ。

OhishiIzumiSuki.vue
<template>
  <div class="wrapper">
    <h1>Tweet {{ msg }} without duplicated entry</h1>
    <div class="tweet-button-wrapper">
      <a class="tweet-button" @click="setUrl(msg)" :href="url" target="_blank">{{ msg }}</a>
    </div>
  </div>
</template>
OhishiIzumiSuki.vue
methods: {
    randomRange(start, end) {
      return Math.round(Math.random() * (end - start)) + start
    },
    generateZWSP(width, result = '') {
      if (!width) return result
      return this.generateZWSP(--width, result += '\u200B')
    },
    insertZWSP(text, result = '') {
      if (!text) return result
      result += text[0] + this.generateZWSP(this.randomRange(0, 20))
      return this.insertZWSP(text.slice(1), result)
    },
    countBytes(text) {
      return encodeURIComponent(text).replace(/%../g,"x").length
    },
    setUrl(text) {
      let content = this.insertZWSP(text)
      this.url = "https://twitter.com/intent/tweet?text=" + encodeURI(content + "\nhttps://ohishi-izumi-suki.herokuapp.com")
      console.log(`「${content}」は${content.length}文字(${this.countBytes(content)}bytes)です`)
    },
  },

大きく分けて3つのことをしています。

  1. 「大石泉すき」にゼロ幅スペース(ZWSP)を挟む
  2. ツイート用URLくっつけてボタンに入れる
  3. コンソールに「大石泉すき」の文字数、バイト数を表示する

以上! 簡単ですね。

1.ゼロ幅スペースを挟む

ゼロ幅スペース(zero width space)って?

ゼロ幅スペース(ゼロはばスペース、英: zero width space, ZWSP)は、コンピュータの組版に用いられる非表示文字で、文書処理システムに対して語の切れ目を示すのに用いる。
Wikipedia - ゼロ幅スペース

🤔

要するに「表示されないけどちゃんと存在してる幅のないスペース」って事です。
ゼロ幅スペース(以下ZWSP)を挟むことで見た目は同じテキストでも重複なくツイートする事ができます。

画像の通り、見た目は同じでも文字数バイト数が違います。
これで連投しても怒られないぞ。やったね!

    randomRange(start, end) {
      return Math.round(Math.random() * (end - start)) + start
    },
    generateZWSP(width, result = '') {
      if (!width) return result
      return this.generateZWSP(--width, result += '\u200B')
    },
    insertZWSP(text, result = '') {
      if (!text) return result
      result += text[0] + this.generateZWSP(this.randomRange(0, 20))
      return this.insertZWSP(text.slice(1), result)
    },
  1. randomRange()で0から20までのランダムな数値を取得
  2. 数値をgenerateZWSP()に渡してその数だけ結合されたZWSPを返す
  3. insertZWSP()でテキストの頭から一文字とって作ったZWSPを結合していく

隙あらば再帰しています。好きなので。

generateZWSP()内の'\u200B'が
UnicodeエスケープシークエンスでのZWSPです

Unicodeエスケープシークエンス↓
#Unicode_escape_sequences 字句文法 - JavaScript | MDN

2.ツイート用URLくっつけてボタンに入れる

ツイート用URLは色々できるWeb Intentsで。
Web Intents - Twitter Developers

OhishiIzumiSuki.vue
    <div class="tweet-button-wrapper">
      <a class="tweet-button" @click="setUrl(msg)" :href="url" target="_blank">{{ msg }}</a>
    </div>
OhishiIzumiSuki.vue
    insertZWSP(text, result = '') {
      if (!text) return result
      result += text[0] + this.generateZWSP(this.randomRange(0, 20))
      return this.insertZWSP(text.slice(1), result)
    },
    setUrl(text) {
      let content = this.insertZWSP(text)
      this.url = "https://twitter.com/intent/tweet?text=" + encodeURI(content + "\nhttps://ohishi-izumi-suki.herokuapp.com")
      console.log(`「${content}」は${content.length}文字(${this.countBytes(content)}bytes)です`)
    },
  1. insertZWSP()でテキストにZWSPを挟みこむ
  2. ツイート用URLを作ってthis.urlに代入

setURL()が呼ばれる度にaタグの:hrefが更新され、ツイート内容が変わります。

文字数、バイト数を表示

レギュレーションを遵守するべく「大石泉すき」と出力していきます。
大事な情報も一緒に表示してしまいましょう。

OhishiIzumiSuki.vue
    countBytes(text) {
      return encodeURIComponent(text).replace(/%../g,"x").length
    },
    setUrl(text) {
      let content = this.insertZWSP(text)
      this.url = "https://twitter.com/intent/tweet?text=" + encodeURI(content + "\nhttps://ohishi-izumi-suki.herokuapp.com")
      console.log(`「${content}」は${content.length}文字(${this.countBytes(content)}bytes)です`)
    },
  1. 変数展開してコンソールに出力
  2. バイト数も知りたいのでcountBytes()で数える

完成!

終わりに

当然ながらこのページからのツイートは「大石泉すき」サーチに引っかかりません。
担当サーチの邪魔にもならないので安心して大石泉すきツイートしていきましょう。

あんまり連投するとこわい