<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel rdf:about="https://let.hatelabo.jp/Awn/rss">
    <link>https://let.hatelabo.jp/Awn/rss</link>
    <description></description>
    <title>Bookmarklets from Awn</title>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="https://let.hatelabo.jp/Awn/let/hJmetP7T1vVA"/>
        <rdf:li rdf:resource="https://let.hatelabo.jp/Awn/let/hLHWrMzj08dj"/>
      </rdf:Seq>
    </items>
  </channel>
  <item rdf:about="https://let.hatelabo.jp/Awn/let/hJmetP7T1vVA">
    <link>https://let.hatelabo.jp/Awn/let/hJmetP7T1vVA</link>
    <dc:date>2017-01-16T15:40:44Z</dc:date>
    <description></description>
    <dc:creator>Awn</dc:creator>
    <title>[Let] おーぷん2ch無視設定変更スクリプト</title>
    <content:encoded>&lt;a href="javascript:%22https%3A%2F%2Flet.st-hatelabo.com%2FAwn%2Flet%2FhJmetP7T1vVA.bookmarklet.js%20%28arg%29%22.replace%28%2F%28%5CS%2B%29%5Cs%2B%28%5CS%2A%29%2F%2Cfunction%28s%2Curl%2Carg%29%7Bs%3Ddocument.createElement%28%22script%22%29%3Bs.charset%3D%22utf-8%22%3Bs.src%3Durl%2B%22%3Fs%3D%22%2BencodeURIComponent%28arg%29%3Bdocument.body.appendChild%28s%29%7D%29%3Bvoid%280%29%3B"&gt;おーぷん2ch無視設定変更スクリプト&lt;/a&gt;&lt;pre&gt;/*
 * @title おーぷん2ch無視設定変更スクリプト
 * @include http://*.open2ch.net/test/read.cgi/*
 * @license MIT License
 */
//作った人 Awn
//Forked from &amp;amp;&amp;amp; Inspired by http://let.hatelabo.jp/TimeFires/let/hJmesYHtkMte

(function (d) {
  //note:「Hatena::Let」の@includeが効かないようなので、
  //      URLが「http://*.open2ch.net/test/read.cgi/*」を満たさ無い場合、スクリプト内部で弾く
  let REGEXP_OPEN2CHREADCGI = new RegExp(/http:\/\/.*\.open2ch\.net\/test\/read\.cgi\/.*/);
  if (!REGEXP_OPEN2CHREADCGI.test(location.href)) {
    console.warn(&amp;quot;available only under http://*.open2ch.net/test/read.cgi/*&amp;quot;);
    return;
  }

  //member
  let appName = 'ignoreManager';
  let _ignores = ignores;


  //initializer
  _init();


  //function
  function _init() {
    _embedHTML();
    _assignEventListener();
  }

  function _embedHTML() {
    _embedBackgroundElm();
    _embedMainElm();
    _setIgnores();
  }

  function _assignEventListener() {
    AddBtnEventListener();
    DeleteAllBtnEventListener();
    DeleteWithoutTwitterBtnEventListener();
    DeleteSelectedBtnEventListener();
    CloseIgnoreManager();
  }

  function _embedBackgroundElm() {
    let bg = d.createElement('div');
    bg.id = `${appName}_bg`;
    bg.style = `
      background:black;
      position:fixed;
      top:0;
      left:0;
      width:100%;
      height:100%;
      opacity:0.5;
      z-index:30;
  `;
    d.body.appendChild(bg);
  }

  function _embedMainElm() {
    let main = d.createElement('div');
    main.id = `${appName}_main`;
    main.style = `
      background:#EFEFEF;
      position:fixed;
      top:30px;
      left:30px;
      width:calc(100% - 80px);
      height:calc(100% - 80px);
      z-index:31;
      border:solid black 1px;
      padding:10px;
    `;
    main.innerHTML = `
    &amp;lt;h1&amp;gt;無視id編集画面&amp;lt;/h1&amp;gt;
    &amp;lt;hr&amp;gt;
    &amp;lt;form name=&amp;quot;ign_form&amp;quot; style=&amp;quot;width:500px&amp;quot; onsubmit=&amp;quot;return false;&amp;quot;&amp;gt;
      &amp;lt;fieldset&amp;gt;
        &amp;lt;legend&amp;gt;一括削除&amp;lt;/legend&amp;gt;
        &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;全て削除&amp;quot; id=&amp;quot;b_deleteAll&amp;quot;&amp;gt;
        &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;TwitterID以外を削除&amp;quot; id=&amp;quot;b_deleteWithoutTwitter&amp;quot;&amp;gt;
      &amp;lt;/fieldset&amp;gt;
      &amp;lt;fieldset&amp;gt;
        &amp;lt;legend&amp;gt;個別追加&amp;lt;/legend&amp;gt;
        &amp;lt;label&amp;gt;
          追加するid &amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;t_input&amp;quot;&amp;gt;
        &amp;lt;/label&amp;gt;
        &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;追加する&amp;quot; id=&amp;quot;b_add&amp;quot;&amp;gt;
      &amp;lt;/fieldset&amp;gt;
    &amp;lt;/form&amp;gt;
    &amp;lt;h2&amp;gt;無視id ↓&amp;lt;/h2&amp;gt;
    &amp;lt;hr&amp;gt;
    &amp;lt;div id=&amp;quot;ignoresView&amp;quot; style=&amp;quot;height:200px;overflow:scroll;&amp;quot;&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;hr&amp;gt;
    &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;選択したidを削除する&amp;quot; id=&amp;quot;b_deleteSelected&amp;quot;&amp;gt;
    &amp;lt;span id=&amp;quot;s_messageArea&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;
    `;
    d.body.appendChild(main);
  }

  function _setIgnores() {
    let keys = Object.keys(_ignores);
    let arr = [];
    let id;
    for (key of keys) {
      [id, key] = _transformID(key);
      arr.push(`&amp;lt;label style=&amp;quot;display: block;&amp;quot;&amp;gt;&amp;lt;input type=&amp;quot;checkbox&amp;quot; value=&amp;quot;${key}&amp;quot;&amp;gt;${id}&amp;lt;/label&amp;gt;`);
    }
    let div = d.querySelector('#ignoresView');
    div.innerHTML = arr.join('');
  }

  function _transformID(key) {
    let id;
    if (key.length &amp;gt; 3 &amp;amp;&amp;amp; key.startsWith('tw@')) {
      id = key;
      key.replace(/^tw@/, 'tw');
      return [id, key];
    }
    if (key.length &amp;gt; 3 &amp;amp;&amp;amp; key.startsWith('tw')) {
      id = key.replace(/^tw/, 'tw@');
      return [id, key];
    }
    if (key.length &amp;gt; 3 &amp;amp;&amp;amp; key.startsWith('@')) {
      id = key.replace(/^@/, 'tw@');
      key = key.replace(/^@/, 'tw');
      return [id, key];
    }
    id = key;
    return [id, key];
  }

  function _addIgnore(key) {
    let elm = d.createElement('label');
    elm.style = 'display:block';
    id = key;
    id = id.length &amp;gt; 3 &amp;amp;&amp;amp; id.startsWith('tw') ? id.replace(/^tw/, 'tw@') : id;
    elm.innerHTML = `&amp;lt;input type=&amp;quot;checkbox&amp;quot; value=&amp;quot;${key}&amp;quot;&amp;gt;${id}`;
    let div = d.querySelector('#ignoresView');
    div.appendChild(elm);
  }

  function _validateID(id) {
    return new Promise((resolve, reject) =&amp;gt; {
      if (id.length &amp;lt; 3) {
        reject();
      }

      //note: idで利用できない文字は弾く
      if (/[^A-Za-z0-9@_]/.test(id)) {
        reject();
      }

      //note: @が2つ以上現れるidは存在しないので弾く
      if (id.includes('@') &amp;amp;&amp;amp; id.match(/@/g).length &amp;gt; 1) {
        reject();
      }

      if (id.length === 3) {
        //note: 3文字の時はtwitterアカウント連携のidではないと「見做す」
        //     理論上(?)[1-3]文字のtwitterアカウントも存在しうるが、そんなレアな人が書き込む可能性は皆無であろう。
        if (id.includes('@') || id.includes('_')) {
          reject();
        }
        resolve(id);
      }

      //note: 3文字より大きい場合 -&amp;gt; twitterIDと見做す
      //     idが[10,9,8,7,6,5,4]桁の過去スレは諦めよう
      /*
        # 正常ケース
          tw@aidee_42 -&amp;gt; twaidee_42
          @aidee_42 -&amp;gt; twaidee_42
          aidee_42 -&amp;gt; twaidee_42
        # エラーケース
          正常ケース以外
      */
      if (id.length &amp;gt; 3) {
        if (id.includes('@')) {
          if (id.startsWith('tw@')) {
            id = id.replace(/^tw@/, 'tw');
            resolve(id);
          } else if (id.startsWith('@')) {
            id = id.replace(/@/, 'tw');
            resolve(id);
          } else {
            reject();
          }
        } else {
          id = 'tw' + id;
          resolve(id);
        }
      }
    });
  }

  //deleter
  function _deleteAll() {
    delStorage(cachekey);
    _ignores = new Object();
    ignores = _ignores;
    return;
  }

  function _deleteAllFromView() {
    let div = d.querySelector('#ignoresView');
    while (div.firstChild) {
      div.removeChild(div.firstChild);
    }
  }


  function _deleteWithoutTwitter() {
    let keys = Object.keys(_ignores);
    for (let key of keys) {
      if (key.length === 3) {
        delete _ignores[key];
      }
    }
    setStorage(cachekey, JSON.stringify(_ignores));
    ignores = _ignores;
  }

  function _deleteWithoutTwitterFromView() {
    let div = d.querySelector('#ignoresView');
    let elms = div.querySelectorAll('input[type=&amp;quot;checkbox&amp;quot;]');
    for (let elm of elms) {
      if (elm.value.length === 3) {
        div.removeChild(elm.parentElement);
      }
    }
  }

  function _deleteSelected() {
    let div = d.querySelector('#ignoresView');
    let elms = div.querySelectorAll('input[type=&amp;quot;checkbox&amp;quot;]');
    let obj = {};
    for (let elm of elms) {
      obj[elm.value] = 1;
    }
    _ignores = obj;
    ignores = _ignores;
    setStorage(cachekey, JSON.stringify(ignores));
    return;
  }

  function _deleteSelectedFromView() {
    let div = d.querySelector('#ignoresView');
    let elms = div.querySelectorAll('input[type=&amp;quot;checkbox&amp;quot;]:checked');
    for (let elm of elms) {
      div.removeChild(elm.parentElement);
    }
    return;
  }

  //EventListener
  function AddBtnEventListener() {
    let elm = d.querySelector('#b_add');
    elm.addEventListener('click', function (ev) {
      ev.preventDefault();
      let id = d.querySelector('#t_input').value;
      id = id.trim();
      _validateID(id)
        .then((key) =&amp;gt; {
          _ignores[key] = 1;
          _addIgnore(key);
          setStorage(cachekey, JSON.stringify(_ignores));
          updateIgnore();
          console.dir(_ignores);
        }, () =&amp;gt; { alert(`${id}はidっぽくないみたい。。`); });
    });
  }

  function DeleteAllBtnEventListener() {
    let elm = d.querySelector('#b_deleteAll');
    elm.addEventListener('click', function (ev) {
      ev.preventDefault();
      if (confirm('消しますか？')) {
        _deleteAll();
        _deleteAllFromView();
      }
    });
  }

  function DeleteWithoutTwitterBtnEventListener() {
    let elm = d.querySelector('#b_deleteWithoutTwitter');
    elm.addEventListener('click', function (ev) {
      ev.preventDefault();
      if (confirm('消しますか？')) {
        _deleteWithoutTwitter();
        _deleteWithoutTwitterFromView();
      }
    });
  }

  function DeleteSelectedBtnEventListener() {
    let elm = d.querySelector('#b_deleteSelected');
    elm.addEventListener('click', function (ev) {
      ev.preventDefault();
      if (confirm('消しますか？')) {
        _deleteSelectedFromView();
        _deleteSelected();
      }
    })
  }

  function CloseIgnoreManager() {
    let elm = document.querySelector('#ignoreManager_bg');
    elm.addEventListener('click', function (ev) {
      if (confirm('閉じますか？')) {
        let main = d.querySelector(`#${appName}_main`);
        let bg = d.querySelector(`#${appName}_bg`);
        d.body.removeChild(main);
        d.body.removeChild(bg);
      }
    });
  }

  return;
})(document);&lt;/pre&gt;</content:encoded>
  </item>
  <item rdf:about="https://let.hatelabo.jp/Awn/let/hLHWrMzj08dj">
    <link>https://let.hatelabo.jp/Awn/let/hLHWrMzj08dj</link>
    <dc:date>2017-01-07T10:39:10Z</dc:date>
    <description></description>
    <dc:creator>Awn</dc:creator>
    <title>[Let] ほぼ完全自動アク禁ブックマークレット2</title>
    <content:encoded>&lt;a href="javascript:%22https%3A%2F%2Flet.st-hatelabo.com%2FAwn%2Flet%2FhLHWrMzj08dj.bookmarklet.js%20%28arg%29%22.replace%28%2F%28%5CS%2B%29%5Cs%2B%28%5CS%2A%29%2F%2Cfunction%28s%2Curl%2Carg%29%7Bs%3Ddocument.createElement%28%22script%22%29%3Bs.charset%3D%22utf-8%22%3Bs.src%3Durl%2B%22%3Fs%3D%22%2BencodeURIComponent%28arg%29%3Bdocument.body.appendChild%28s%29%7D%29%3Bvoid%280%29%3B"&gt;ほぼ完全自動アク禁ブックマークレット2&lt;/a&gt;&lt;pre&gt;/*
 * @title ほぼ完全自動アク禁ブックマークレット2
 * @include http://*.open2ch.net/test/read.cgi/*
 * @license MIT License
 */
//作った人: Awn


(function() {
    //note:「Hatena::Let」の@includeが効かないようなので、
    //      URLが「http://*.open2ch.net/test/read.cgi/*」を満たさ無い場合、スクリプト内部で弾く
    let REGEXP_OPEN2CHREADCGI = new RegExp(/http:\/\/.*\.open2ch\.net\/test\/read\.cgi\/.*/);
    if (!REGEXP_OPEN2CHREADCGI.test(location.href)) {
        console.warn(&amp;quot;available only under http://*.open2ch.net/test/read.cgi/*&amp;quot;);
        return;
    }

    //class
    class MutationListener {
        constructor(f) {
            this.target = document.querySelector(&amp;quot;div.thread&amp;quot;);
            this.option = { childList: true };
            this.mo = new MutationObserver(f);
        }

        start() {
            this.mo.observe(this.target, this.option);
        }

        stop() {
            this.mo.disconnect();
        }
    }

    class AkukinAgent {
        constructor(MESSAGE, FROM, mail) {
            let fd = new FormData();
            fd.set(&amp;quot;bbs&amp;quot;, bbs);
            fd.set(&amp;quot;key&amp;quot;, key);
            fd.set(&amp;quot;submit&amp;quot;, &amp;quot;書き込む&amp;quot;);
            this.fd = fd;

            this.update(MESSAGE, FROM, mail);

            let xhr = new XMLHttpRequest();
            xhr.addEventListener(&amp;quot;loadend&amp;quot;, this.f_xhr);
            this.xhr = xhr;
        }

        update(MESSAGE = &amp;quot;&amp;quot;, FROM = &amp;quot;&amp;quot;, mail = &amp;quot;&amp;quot;) {
            let fd = this.fd;
            fd.set(&amp;quot;FROM&amp;quot;, FROM);
            fd.set(&amp;quot;mail&amp;quot;, mail);
            this.fd = fd;

            this.MESSAGE = MESSAGE;
        }

        set(target) {
            let fd = this.fd;
            fd.set(&amp;quot;MESSAGE&amp;quot;, this.MESSAGE + &amp;quot;\n&amp;quot; + target);
            fd.set(&amp;quot;time&amp;quot;, Math.floor(Date.now() / 1000));
            this.fd = fd;
        }

        f_xhr(result) {
            let response = result.target.response;
            if (response.includes(&amp;quot;&amp;lt;title&amp;gt;書きこみました。&amp;lt;/title&amp;gt;&amp;quot;)) {
                //console.log(&amp;quot;success&amp;quot;);
            } else {
                console.log(&amp;quot;error&amp;quot;);
                console.log(response);
            }
        }

        exec() {
            let xhr = this.xhr;
            let fd = this.fd;
            xhr.open(&amp;quot;POST&amp;quot;, &amp;quot;/test/bbs.cgi?guid=ON&amp;quot;);
            xhr.send(fd);
        }
    }

    class ResHead {
        set(dts) {
            this.dts = dts;
        }

        parse() {
            let reshead = [];
            let main, mail;
            const REGEXP_MAIN = new RegExp(/^([0-9]{1,4}) ：(.*?) ?：.* ID:(.*$)/);
            const REGEXP_MAIL = new RegExp(/&amp;lt;a href=&amp;quot;mailto:(.*?)&amp;quot;&amp;gt;/);
            for (let value of this.dts) {
                main = value.innerText.match(REGEXP_MAIN);
                mail = value.outerHTML.match(REGEXP_MAIL);
                reshead.push({
                    resnum: main[1] - 0,
                    name: main[2],
                    id: main[3].replace(&amp;quot;(主)&amp;quot;, &amp;quot;&amp;quot;).replace(&amp;quot; &amp;quot;, &amp;quot;&amp;quot;).replace(&amp;quot;×&amp;quot;, &amp;quot;&amp;quot;),
                    nusi: main[3].includes(&amp;quot;(主)&amp;quot;),
                    mail: mail === null ? null : mail[1]
                });
            }
            this.data = reshead;
            return reshead;
        }

        get() {
            return this.data;
        }
    }

    class ResBody {
        set(dds) {
            this.dds = dds;
        }

        parse() {
            let nodes, nodeName, node, imgurs, arr;
            let resbody = [];
            for (let value of this.dds) {
                nodes = value.childNodes;
                arr = [];
                for (let ix = 0, len = nodes.length - 3; ix &amp;lt; len; ix++) {
                    node = nodes[ix];
                    nodeName = node.nodeName.toLowerCase();
                    //note: 通常の目に見えるテキスト,いわゆる本文の各一行
                    if (nodeName === &amp;quot;#text&amp;quot;) {
                        arr.push(node.textContent.trim());
                    }

                    //note: 文末改行および空行
                    if (nodeName === &amp;quot;br&amp;quot;) {
                        arr.push(&amp;quot;\n&amp;quot;);
                    }

                    //note: リンク
                    if (nodeName === &amp;quot;a&amp;quot;) {
                        //note: 安価参照の場合はリンクではなく安価テキスト(e.g. &amp;gt;&amp;gt;243-256 )を取得する
                        if (/^\/test\/read\.cgi\/.*/.test(node.pathname)) {
                            arr.push(node.textContent.trim());
                        } else {
                            arr.push(node.href);
                        }
                    }

                    //note: imgur画像は複数毎がグループ化されているので、それを取り出す
                    if (nodeName === &amp;quot;div&amp;quot; &amp;amp;&amp;amp; node.className === &amp;quot;group&amp;quot; &amp;amp;&amp;amp; node.firstChild.className === &amp;quot;imgur&amp;quot;) {
                        imgurs = node.querySelectorAll(&amp;quot;a&amp;quot;);
                        for (let imgur of imgurs) {
                            arr.push(imgur.href);
                        }
                    }

                    if (nodeName === &amp;quot;font&amp;quot;) {
                        arr.push(node.textContent.trim());
                    }

                }
                resbody.push(arr.join(&amp;quot;&amp;quot;));
            }
            this.data = resbody;
            return resbody;
        }

        get() {
            return this.data;
        }
    }

    class Res {
        set(reshead, resbody) {
            for (let ix = 0, len = reshead.length; ix &amp;lt; len; ix++) {
                reshead[ix].text = resbody[ix];
            }
            this.data = reshead;
        }

        get() {
            return this.data;
        }
    }


    //member
    let _form = {};
    let _idList = {};


    //instances
    let _mo;
    let _agent;
    let _reshead;
    let _resbody;
    let _res;


    //initializer
    _init();


    //function
    function _init() {
        _embedForm();

        let enableAkukin = _getStorage(&amp;quot;enableAkukin&amp;quot;);
        let MESSAGE = _getStorage(&amp;quot;autoAku_defaultText&amp;quot;);
        let FROM = _getStorage(&amp;quot;autoAku_defaultName&amp;quot;);
        let mail = _getStorage(&amp;quot;autoAku_defaultMail&amp;quot;);
        _agent = new AkukinAgent(MESSAGE, FROM, mail);
        _mo = new MutationListener(_MutationCallback);

        if (enableAkukin) {
            _setupForm();
            if (enableAkukin === &amp;quot;ON&amp;quot;) {
                _mo.start();
            }
        }

        _assignEventListener();
        _createInstances();
    }

    function _assignEventListener() {
        ShowBtnEventListener();
        SaveBtnEventListener();
        DeleteBtnEventListener();
        SpeedLimitRadioBtnEventListener();
    }

    function _createInstances() {
        _res = new Res();
        _reshead = new ResHead();
        _resbody = new ResBody();
    }

    function _embedForm() {
        let section = document.createElement(&amp;quot;section&amp;quot;);
        section.setAttribute(&amp;quot;id&amp;quot;, &amp;quot;autoAkuSection&amp;quot;);
        section.innerHTML = '&amp;lt;hr&amp;gt;&amp;lt;h2 style=&amp;quot;color:red;&amp;quot;&amp;gt;自動アク禁設定&amp;lt;/h2&amp;gt;&amp;lt;input type=&amp;quot;button&amp;quot; name=&amp;quot;b_autoAkuShow&amp;quot; id=&amp;quot;b_autoAkuShow&amp;quot; value=&amp;quot;開く&amp;quot;&amp;gt; &amp;lt;input type=&amp;quot;button&amp;quot; name=&amp;quot;b_autoAkuDelete&amp;quot; id=&amp;quot;b_autoAkuDelete&amp;quot; value=&amp;quot;データを全て消す&amp;quot;&amp;gt;';

        let form = document.createElement(&amp;quot;form&amp;quot;);
        form.setAttribute(&amp;quot;name&amp;quot;, &amp;quot;fm_autoAku&amp;quot;);
        form.setAttribute(&amp;quot;id&amp;quot;, &amp;quot;fm_autoAku&amp;quot;);
        form.setAttribute(&amp;quot;style&amp;quot;, &amp;quot;display:none;&amp;quot;);
        form.innerHTML = '&amp;lt;fieldset&amp;gt;&amp;lt;legend&amp;gt;自動アク禁投稿で使用する名前とmailと本文&amp;lt;/legend&amp;gt;&amp;lt;label&amp;gt;名前：&amp;lt;input type=&amp;quot;text&amp;quot; size=&amp;quot;40&amp;quot; name=&amp;quot;autoAku_defaultName&amp;quot; placeholder=&amp;quot;(省略化)自動アク禁用の名前&amp;quot;&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;br&amp;gt;&amp;lt;label&amp;gt;mail：&amp;lt;input type=&amp;quot;text&amp;quot; size=&amp;quot;40&amp;quot; name=&amp;quot;autoAku_defaultMail&amp;quot; placeholder=&amp;quot;(省略化)自動アク禁用のmail&amp;quot;&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;br&amp;gt;&amp;lt;textarea rows=&amp;quot;5&amp;quot; cols=&amp;quot;56&amp;quot; name=&amp;quot;autoAku_defaultText&amp;quot; placeholder=&amp;quot;(省略可)ここに書いたメッセージに!aku42といったアク禁コマンドが自動で足されます。&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;/fieldset&amp;gt;&amp;lt;fieldset&amp;gt;&amp;lt;legend&amp;gt;自動アク禁キーワード設定&amp;lt;/legend&amp;gt;&amp;lt;label&amp;gt;アク禁ワード↓&amp;lt;br&amp;gt;&amp;lt;textarea rows=&amp;quot;5&amp;quot; cols=&amp;quot;56&amp;quot; name=&amp;quot;autoAku_words&amp;quot; placeholder=&amp;quot;改行区切りで入力&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;label&amp;gt;アク禁ネーム↓&amp;lt;br&amp;gt;&amp;lt;textarea rows=&amp;quot;5&amp;quot; cols=&amp;quot;56&amp;quot; name=&amp;quot;autoAku_names&amp;quot; placeholder=&amp;quot;改行区切りで入力&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;label&amp;gt;アク禁メール↓&amp;lt;br&amp;gt;&amp;lt;textarea rows=&amp;quot;5&amp;quot; cols=&amp;quot;56&amp;quot; name=&amp;quot;autoAku_mails&amp;quot; placeholder=&amp;quot;改行区切りで入力&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;label&amp;gt;アク禁id↓&amp;lt;br&amp;gt;&amp;lt;textarea rows=&amp;quot;5&amp;quot; cols=&amp;quot;56&amp;quot; name=&amp;quot;autoAku_ids&amp;quot; placeholder=&amp;quot;改行区切りで入力&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;/fieldset&amp;gt;&amp;lt;fieldset&amp;gt;&amp;lt;legend&amp;gt;その他の設定&amp;lt;/legend&amp;gt;投稿間隔でアク禁：&amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;enableSpeedLimit&amp;quot; value=&amp;quot;OFF&amp;quot; checked&amp;gt;OFF&amp;lt;/label&amp;gt;&amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;enableSpeedLimit&amp;quot; value=&amp;quot;ON&amp;quot;&amp;gt;ON&amp;lt;/label&amp;gt;&amp;lt;span id=&amp;quot;field_speedLimit&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;&amp;lt;input type=&amp;quot;number&amp;quot; size=&amp;quot;10&amp;quot; min=&amp;quot;1&amp;quot; max=&amp;quot;3600&amp;quot; name=&amp;quot;autoAku_speedLimit&amp;quot; value=&amp;quot;1&amp;quot;&amp;gt;秒未満の間隔で投稿するidをアク禁する&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;正規表現を利用する：&amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;enableRegexp&amp;quot; value=&amp;quot;OFF&amp;quot; checked&amp;gt;OFF&amp;lt;/label&amp;gt;&amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;enableRegexp&amp;quot; value=&amp;quot;ON&amp;quot;&amp;gt;ON&amp;lt;/label&amp;gt;&amp;lt;br&amp;gt;アク禁を実行する　：&amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;enableAkukin&amp;quot; value=&amp;quot;OFF&amp;quot; checked&amp;gt;OFF&amp;lt;/label&amp;gt;&amp;lt;label&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;enableAkukin&amp;quot; value=&amp;quot;ON&amp;quot;&amp;gt;ON&amp;lt;/label&amp;gt;&amp;lt;/fieldset&amp;gt;&amp;lt;input type=&amp;quot;button&amp;quot; id=&amp;quot;b_autoAkuSave&amp;quot; name=&amp;quot;b_autoAkuSave&amp;quot; value=&amp;quot;アク禁設定を保存する&amp;quot;&amp;gt;&amp;lt;span id=&amp;quot;autoAku_message&amp;quot; style=&amp;quot;color:red;&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;';
        document.body.appendChild(section);
        section.appendChild(form);
    }

    function _setupForm() {
        let form = document.forms[&amp;quot;fm_autoAku&amp;quot;];
        let fd = new FormData(form);
        let temp = {};
        let storage;
        for (let [key, value] of fd) {
            storage = _getStorage(key);
            temp[key] = storage;
            form[key].value = storage;
        }
        _validateForm(temp)
            .then(_setInternalValue);
    }

    function _MutationCallback(record) {
        let dl = record[0].addedNodes[0];
        //note: dlの中にdt, ddは１組以上含まれる可能性がある
        _reshead.set(dl.querySelectorAll(&amp;quot;dt&amp;quot;));
        _resbody.set(dl.querySelectorAll(&amp;quot;dd&amp;quot;));
        _res.set(_reshead.parse(), _resbody.parse());

        let res = _res.get();

        let judge = [];
        let isTarget = false;
        let target = [];
        let limit = _form[&amp;quot;limit&amp;quot;] * 1000;
        let enableSpeedLimit = _form[&amp;quot;enableSpeedLimit&amp;quot;] === &amp;quot;ON&amp;quot; ? true : false;
        for (let value of res) {
            judge = [];
            isTarget = false;
            if (!value.nusi) {
                judge.push(_form[&amp;quot;word&amp;quot;].some((elm) =&amp;gt; elm.test(value.text)));
                judge.push(_form[&amp;quot;name&amp;quot;].some((elm) =&amp;gt; elm.test(value.name)));
                judge.push(_form[&amp;quot;mail&amp;quot;].some((elm) =&amp;gt; elm.test(value.mail)));
                judge.push(_form[&amp;quot;id&amp;quot;].some((elm) =&amp;gt; elm.test(value.id)));
                isTarget = judge.some((elm) =&amp;gt; elm);
                if (isTarget) {
                    target.push(value.resnum);
                }
                if (enableSpeedLimit) {
                    if (Date.now() - _idList[value.id] &amp;lt; limit) {
                        target.push(value.resnum);
                    }
                    _idList[value.id] = Date.now();
                }
            }
        }
        target = target.filter((elm, ind, ary) =&amp;gt; ary.indexOf(elm) === ind);
        target = target.map((elm) =&amp;gt; &amp;quot;!aku&amp;quot; + elm);

        if (target.length) {
            _agent.set(target);
            _agent.exec();
        }
    }


    /* Event Listener */
    function ShowBtnEventListener() {
        let elm = document.querySelector(&amp;quot;#b_autoAkuShow&amp;quot;);
        elm.addEventListener(&amp;quot;click&amp;quot;, function(ev) {
            let form = document.forms[&amp;quot;fm_autoAku&amp;quot;];
            let style = form.getAttribute(&amp;quot;style&amp;quot;);
            if (style.includes(&amp;quot;none&amp;quot;)) {
                form.setAttribute(&amp;quot;style&amp;quot;, &amp;quot;display:block;&amp;quot;);
                elm.value = &amp;quot;開じる&amp;quot;;
            } else {
                form.setAttribute(&amp;quot;style&amp;quot;, &amp;quot;display:none;&amp;quot;);
                elm.value = &amp;quot;開く&amp;quot;;
            }
        });
    }

    function SaveBtnEventListener() {
        let elm = document.querySelector(&amp;quot;#b_autoAkuSave&amp;quot;);
        elm.addEventListener(&amp;quot;click&amp;quot;, function(ev) {
            let form = ev.target.form;
            let fd = new FormData(form);
            let temp = {};
            for (let [key, value] of fd) {
                temp[key] = value;
            }
            let message = document.querySelector(&amp;quot;#autoAku_message&amp;quot;);
            _validateForm(temp)
                .then(function(result) {
                    _setInternalValue(result);

                    fd.set(&amp;quot;autoAku_speedLimit&amp;quot;, result[5]);
                    for (let [key, val] of fd) {
                        _setStorage(key, val);
                    }

                    if (temp[&amp;quot;enableAkukin&amp;quot;] === &amp;quot;ON&amp;quot;) {
                        _mo.start();
                    } else {
                        _mo.stop();
                    }

                    _agent.update(_form[&amp;quot;autoAku_defaultText&amp;quot;], _form[&amp;quot;autoAku_defaultName&amp;quot;], _form[&amp;quot;autoAku_defaultMail&amp;quot;]);

                    message.textContent = &amp;quot;保存しますた！&amp;quot;;
                    setTimeout(() =&amp;gt; { message.textContent = &amp;quot;&amp;quot; }, 1000);

                }, function(reason) {
                    alert(reason);
                    message.textContent = &amp;quot;保存してません！&amp;quot;;
                    setTimeout(() =&amp;gt; { message.textContent = &amp;quot;&amp;quot; }, 1000);
                });
        });
    }

    function _validateForm(data) {
        return new Promise(function(resolve, reject) {
            let word, name, mail, id, limit;

            let words = data[&amp;quot;autoAku_words&amp;quot;];
            let names = data[&amp;quot;autoAku_names&amp;quot;];
            let mails = data[&amp;quot;autoAku_mails&amp;quot;];
            let ids = data[&amp;quot;autoAku_ids&amp;quot;];

            let arr_words = _splitt(words).filter((elm) =&amp;gt; elm !== &amp;quot;&amp;quot;);
            let arr_names = _splitt(names).filter((elm) =&amp;gt; elm !== &amp;quot;&amp;quot;);
            let arr_mails = _splitt(mails).filter((elm) =&amp;gt; elm !== &amp;quot;&amp;quot;);
            let arr_ids = _splitt(ids).filter((elm) =&amp;gt; elm !== &amp;quot;&amp;quot;);

            if (data[&amp;quot;enableRegexp&amp;quot;] === &amp;quot;ON&amp;quot;) {
                try {
                    word = arr_words.map((elm) =&amp;gt; new RegExp(elm, &amp;quot;m&amp;quot;));
                    name = arr_names.map((elm) =&amp;gt; new RegExp(elm, &amp;quot;m&amp;quot;));
                    mail = arr_mails.map((elm) =&amp;gt; new RegExp(elm, &amp;quot;m&amp;quot;));
                    id = arr_ids.map((elm) =&amp;gt; new RegExp(elm, &amp;quot;m&amp;quot;));
                } catch (e) {
                    let message = &amp;quot;正規表現の指定がおかしいみたいです。。\n↓\n↓\n&amp;quot; + e.message;
                    reject(message);
                    return;
                }
            } else {
                word = arr_words.map((elm) =&amp;gt; new RegExp(_escapeRegexp(elm), &amp;quot;m&amp;quot;));
                name = arr_names.map((elm) =&amp;gt; new RegExp(_escapeRegexp(elm), &amp;quot;m&amp;quot;));
                mail = arr_mails.map((elm) =&amp;gt; new RegExp(_escapeRegexp(elm), &amp;quot;m&amp;quot;));
                id = arr_ids.map((elm) =&amp;gt; new RegExp(_escapeRegexp(elm), &amp;quot;m&amp;quot;));
            }

            if (data[&amp;quot;enableSpeedLimit&amp;quot;] === &amp;quot;ON&amp;quot;) {
                limit = data[&amp;quot;autoAku_speedLimit&amp;quot;] - 0;
                limit = isNaN(limit) ? 1 : limit;
                limit = limit &amp;gt;= 1 ? limit : 1;
            } else {
                limit = 1;
            }

            resolve([data, word, name, mail, id, limit]);
            return;
        });
    }

    function _setInternalValue([temp, word, name, mail, id, limit]) {
        _form[&amp;quot;word&amp;quot;] = word;
        _form[&amp;quot;name&amp;quot;] = name;
        _form[&amp;quot;mail&amp;quot;] = mail;
        _form[&amp;quot;id&amp;quot;] = id;
        _form[&amp;quot;limit&amp;quot;] = limit;
        _form[&amp;quot;enableAkukin&amp;quot;] = temp[&amp;quot;enableAkukin&amp;quot;];
        _form[&amp;quot;enableRegexp&amp;quot;] = temp[&amp;quot;enableRegexp&amp;quot;];
        _form[&amp;quot;enableSpeedLimit&amp;quot;] = temp[&amp;quot;enableSpeedLimit&amp;quot;];
        _form[&amp;quot;autoAku_defaultName&amp;quot;] = temp[&amp;quot;autoAku_defaultName&amp;quot;];
        _form[&amp;quot;autoAku_defaultMail&amp;quot;] = temp[&amp;quot;autoAku_defaultMail&amp;quot;];
        _form[&amp;quot;autoAku_defaultText&amp;quot;] = temp[&amp;quot;autoAku_defaultText&amp;quot;];

        if (_form[&amp;quot;enableSpeedLimit&amp;quot;] === &amp;quot;ON&amp;quot;) {
            let target = document.querySelector(&amp;quot;#field_speedLimit&amp;quot;);
            target.setAttribute(&amp;quot;style&amp;quot;, &amp;quot;display:inline;&amp;quot;);
        }

    }

    function _splitt(value) {
        return value.split(&amp;quot;\r\n&amp;quot;);
    }

    function _escapeRegexp(str) {
        return str.replace(/([.*+?^=!:${}()|[\]\/\\])/g, &amp;quot;\\$1&amp;quot;);
    }

    function DeleteBtnEventListener() {
        let elm = document.querySelector(&amp;quot;#b_autoAkuDelete&amp;quot;);
        elm.addEventListener(&amp;quot;click&amp;quot;, function(ev) {
            if (confirm(&amp;quot;消しますか？&amp;quot;)) {
                let form = document.forms[&amp;quot;fm_autoAku&amp;quot;];
                let fd = new FormData(form);
                for (let [key, value] of fd) {
                    _removeStorage(key);
                }

                form.reset();
                _mo.stop();

                let target = document.querySelector(&amp;quot;#field_speedLimit&amp;quot;);
                target.setAttribute(&amp;quot;style&amp;quot;, &amp;quot;display:none;&amp;quot;);
            }
        });
    }

    function SpeedLimitRadioBtnEventListener() {
        let limit_on = document.querySelector(&amp;quot;input[type='radio'][name='enableSpeedLimit'][value='ON']&amp;quot;);
        let limit_off = document.querySelector(&amp;quot;input[type='radio'][name='enableSpeedLimit'][value='OFF']&amp;quot;);
        let target = document.querySelector(&amp;quot;#field_speedLimit&amp;quot;);
        limit_on.addEventListener(&amp;quot;click&amp;quot;, function(ev) {
            target.setAttribute(&amp;quot;style&amp;quot;, &amp;quot;display:inline;&amp;quot;);
        });
        limit_off.addEventListener(&amp;quot;click&amp;quot;, function(ev) {
            target.setAttribute(&amp;quot;style&amp;quot;, &amp;quot;display:none;&amp;quot;);
        });
    }


    /* wrapper function */
    function _getStorage(key) {
        return localStorage.getItem(key);
    }

    function _setStorage(key, val) {
        localStorage.setItem(key, val);
    }

    function _removeStorage(key) {
        localStorage.removeItem(key);
    }

    return;
})();&lt;/pre&gt;</content:encoded>
  </item>
</rdf:RDF>
