「console.log」を含む日記 RSS

はてなキーワード: console.logとは

2025-09-08

anond:20250908203539

多分お前が意図した通りに動くコードは、これだ。

async function f() {
  console.log(1);
  await new Promise(r => setTimeout(r, 1000));
  console.log(2);
}


 f();
console.log("done");

 

結果は、まず「1」「done」が出力され、1秒後に「2」が出力される。

 

流れを説明すると、f()が実行されると「console.log(1);」と「new Promise(r => setTimeout(r, 1000));」が実行される。

その時点でf()の戻り値として 先ほどnewされた ……じゃなかった、f()を非同期実行中でそのうち続きが実行されますよというPromiseオブジェクトが返ってくる。

 

このPromiseオブジェクトは「resolveされたときにawait以降が実行される」というPromiseオブジェクトだ。

 

そして通常の処理の流れとして、その次の行の「console.log("done");」が実行される。

んで、1秒後にsetTimeoutで終わったことでキューに「r(イコール、resolve関数)」が登録される。

次のキュー登録されたresolve関数が実行される。

 

最後に、resolveが実行されたので、await以降……つまりconsole.log(2);」が実行される。

 

どこか分からないとこある?

dorawii@執筆依頼募集中

実行キューに入るのは非同期処理が終了した後だ。

なんか矛盾してない?

async function f() {
console.log(1);
new Promise(r => setTimeout(r, 1000));
console.log(2);
}


f();
console.log("done");

こう書いたらコンソールに出る順は1,2,doneだよ。1,2を出してる関数は非同期でありそれ以外にはこのコードに非同期関数存在しないんだけど。

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

https://anond.hatelabo.jp/20250908203539#
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaL6/iwAKCRBwMdsubs4+
SNVCAQDh/59YPp/11Ts/tp7JdxGIs6BqRv1PhkFmjUkBZH00owD/fN0PnyFGyJ8N
QGQlMNJvfsFGvNT5tbsEY1d/dhjCmQI=
=KsE1
-----END PGP SIGNATURE-----

dorawii@執筆依頼募集中

ソースコードいくら見てもそのソースコード作成者が想定してるエンジン側の実装なんて推測できんだろ。

ちなみにその「細かいこと」が気になった発端は初歩であるはずのコード挙動理解につまづいたからだけどな。

そしてAIにこんな質問をしたわけね。

setTimeout(() => { console.log("A"); }, 1001); setTimeout(() => { console.log("B"); },1000); console.log("C"); 上のsetTimeout()の各第二引数の大小関係をどのように調整しても常に第二引数により小さい数が指定されたものコールバック関数が先に実行されます。 これはどういうことですか?先にsetTimeoutと書かれたものコールバック関数からキュー登録され、キューへの取り出し方はjs場合fifo採用されているので、上記コードのような場合は、()=>console.log("A")の方が先にキュー登録されたものとして第二引数無関係に()=>console.log("B")より先に実行されるのではないのですか?
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

https://anond.hatelabo.jp/20250908192456# 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaL6u+QAKCRBwMdsubs4+
SAtwAP49XRX8yOJwd/XLSKjjP1TASfuVR29t/NIhuLSNb0vr2AD8CtGJTYMzavjS
i9TuxJTV/DSYuwhuBLnKkd0lsJOldQI=
=wm4J
-----END PGP SIGNATURE-----

2025-08-23

dorawii@執筆依頼募集中

やべえ。爆速ブクマされるプログラムになった。

async function collectAllUrls(startUrl) {
const urls = [];
let nextUrl = startUrl;

while (nextUrl) {
const res = await fetch(nextUrl);
const html = await res.text();
const doc = new DOMParser().parseFromString(html, "text/html");

const links = doc.querySelectorAll("div.section > h3 > a:first-child");
urls.push(...[...links].map(link => link.href));

const nextLink = [...doc.querySelectorAll("a")].find(a => a.textContent.includes("次の25件>"));
nextUrl = nextLink ? nextLink.href : null;
console.log(nextUrl)
}

return urls;
}

(async () => {
const allUrls = await collectAllUrls(window.location.href);
console.log("総件数:", allUrls.length);

await Promise.all(allUrls.map(url =>{console.log(url);
fetch('https://b.hatena.ne.jp/dorawii_bukuma/add.edit.json', {
method: 'POST',
headers: {
},
body: new URLSearchParams({

'url': url,
'private': '0',
'comment': '[dorawii]わしが書いた',
'post_twitter': '0',
'with_status_op': '1',
'from': 'web-confirm'
})
});
} ));

console.log("全送信完了");
})();

https://b.hatena.ne.jp/site/anond.hatelabo.jp/?sort=eid

↑膨大な数のブクマが19:34分前後登録になってるだろ?

途中でブクマ数増えなくなったんだよね。待機処理つけるべきだったか

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

https://anond.hatelabo.jp/20250823194237# 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaKmbHwAKCRBwMdsubs4+
SJC0AP0Q7RDjUSe8p2aNNKV0KLhlbhnTY+kD7uuWCS8yLJILDgEA2Sm4b1496jjy
C0ue64hovLwS3C4dcF5r5TBMyfRifw8=
=zIYi
-----END PGP SIGNATURE-----

2025-08-21

dorawii@執筆依頼募集中

自動ブクマするローカルサーバーとかの構成を作った。

ブクマには↓のサブアカ使用

https://profile.hatena.ne.jp/dorawii_bukuma/

はてなサイト側で読み込まれているはずのrksトークンを生成する関数を直接叩く方法がどうしても分からず結局request処理を自分で書く方法ではなく自動UI側の保存ボタンクリックするという無難な方向に落ち着いた。

最初から後者方法をとっていればもっと全然早く作れたのにというは所詮言い訳か。

とにかくスクリプトを公開しておく。

start-server.bat

@echo off
cd /d "C:\Users\user\Documents\jsscript"

:: Nodeサーバーを別ウィンドウで起動
start /min "" node run-batch-server.js

:: Pythonサーバーを別ウィンドウで起動(hatenaserver配下
start cmd /k "" python hatenaserver\server.py

以降はjsscript直下に配置

config.json

{
"username": "",
"password": ""
}
server.py

from flask import Flask, request, jsonify
import json
import os
from hatena_client import HatenaClient
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

config_path = os.path.join(os.path.dirname(__file__), 'config.json')
with open(config_path, encoding='utf-8') as f:
config = json.load(f)

@app.route('/bookmark', methods=['POST'])
def handle_bookmark():
data = request.json
url = data.get("url")
if not url:
return jsonify({"error": "Missing URL"}), 400

client = HatenaClient(config["username"], config["password"])
client.start_browser()

if not client.login():
client.quit()
return jsonify({"error": "Login failed"}), 403

success = client.add_bookmark(url)
client.quit()

return jsonify({"status": "ok" if success else "fail"})

if __name__ == "__main__":
app.run(port=12347)

あとはグリモンユーザスクリプトとして書くやつ

// ==UserScript==
// @name 自動セルクマ送信
// @namespace tampermonkey.net/
// @version 2025-08-07
// @description try to take over the world!
// @author You
// @match anond.hatelabo.jp/*
// @grant none
// ==/UserScript==

(function () {
'use strict';

const url = location.href;
if (!/^https:\/\/anond\.hatelabo\.jp\/\d+$/.test(url)) return;
const editLink = document.querySelector('a.edit');
if (!editLink) {
// 既に編集ページなので処理をスキップ
console.log('編集リンク存在するため、スクリプトを終了します。');
return;
}

fetch('localhost:12347/bookmark', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ url: url })
}).then(r => console.log("通知成功")).catch(e => console.error("通知失敗", e));
})();
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

https://anond.hatelabo.jp/20250821192753# 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaKb0qwAKCRBwMdsubs4+
SHfiAQDcXmTHBaZ5Zzr1KI/OxZ0xl69oevOdy1FXJYwYvsmo5AD/ZPtZiO1JgTDj
m+27iymlkdzIXOIGWfC82UTr1mJ7EwU=
=YoV+
-----END PGP SIGNATURE-----

2025-07-06

プログラムができる人って特殊技能のように言われているけど

今の時代ChatGPTに教えてもらいながら出てきたコードにらめっこしてたら3日くらいで要領つかめいか

そりゃORMやらMVCやらOOPやらは3日じゃわからないだろうけど、

ifやforやconsole.logくらいはわかるでしょ。そしたらここを変えたらこうなるなくらいはわかるでしょ。

やるかやらないかだと思ってるんだけど。

料理レシピ見せられても料理なんて難しくてできないよ!って言ってるように聞こえる。

2025-07-01

[] 増田CSSを紹介する記事(英文スパム対策付き)

Chromeブラウザには増田を快適に閲覧するための コンパクトな増田 という古い拡張機能があったが、Chrome更新対応し切れておらず、既にChromeには新規インストールできなくなってしまっている。Edgeにはまだインストール可能だが、いずれ対応しなくなる可能性が高い。

そこで、「増田トップページで、言及エントリ(返信・トラバ)を一覧から除外することで、新規エントリだけを一覧できる」という機能に絞ってコンパクト増田再現、ついでにいくつかのおまけ機能付与したスタイルシート(CSS)を今年の4月に公開していたのだが、今回改めて英文スパム対策を追加したので公開する。

これを導入するには Stylus という拡張必要で、少し気軽さには欠けるが、増田以外にも活用できるので、この機会にぜひ導入してみてほしい。拡張インストールしたあとは、下記のコードコピペして新規スタイルとして導入する方法もあるが、スタイルシートを公開できる userstyles.world の増田CSSページ(※毎朝9:00直後はアクセスできない) から [Install] ボタンインストールするほうが、自動更新にも対応するので便利かもしれない。

増田CSS (7/20: 増田文字数制限のため、スパム対策部分は省略しました)

/* トップページ言及エントリを除外 */
/* via: 最近ファーストブクマカが静か https://anond.hatelabo.jp/20250326171302 */
h1/*はてな匿名ダイアリー*/ + #intro/*名前を隠して楽しく日記。*/ + #body div.section:has(h3 > a/*■*/ + a:not(.keyword, .edit)/*anond:YYYYMMDDhhmmss*/){
  display: none;
}

/* うっかりクリックしがちなキーワードリンク無効に */
a.keyword{
  pointer-events: none;
}

/* 執筆時のテキストエリアを広く */
textarea#text-body{
  min-height: 50vh !important;
}

/* 執筆時に特殊記号のヒント(疑似要素なので選択してコピペできないのがもどかしいけど) */
p.post-submit > span.explain::after{
  margin-left: 1em;
  padding-left: 1em;
  content: "特殊記号: &[&#38;] <[&#60;] >[&#62;]";
  background: url(/images/common/outsite-wh.gif) 0 3px no-repeat;
}

/* スパム対策部分は下記URLの [Install] ボタンで事前確認できます(随時更新中) */
/* https://userstyles.world/style/23028/ */

なお、このCSS適用すると、NGワードを含むこの増田自体も、増田トップページからは消えてしまう(この増田単体の個別ページなら閲覧できる)。

PCスマホ向けの導入方法

念のため、PCスマホCSS適用する方法解説にもリンクしておく。

PC: 【StylusウェブサイトCSS適用できる拡張機能自由カスタマイズ! | ナポリタン寿司PC日記

https://www.naporitansushi.com/stylus/

iPhone: MaKeoverアプリiPhone SafariCSSカスタマイズ万博パビリオン予約結果一覧を見やすくする使い方

https://gintachan.com/makeover-app-css-change-safari-how-to/

Android: スマートフォン AndroidFirefoxCSSカスタマイズ Stylus の使い方・初期設定方法

https://skypenguin.net/2025/06/21/post-109209/

(7/21追記) また、スパム特に多い時は、1ページまるごとスパムということもあるので、PCなら uAutoPagerize (Chrome)weAutoPagerize (Firefox) などの拡張を使うと、自動でページが継ぎ足されて快適に読み進められる。ただし、継ぎ足ししまくるとメモリ不足などでブラウザが重くなることがあるので、そうなったら page: 20 などのページ番号をクリックしてから続きを読もう。

(参考) 増田の頻出キーワードリンク上位20抽出JavaScript

また、スパム対策の簡易NGワードは、下記のスクリプトを使って抽出した「直近の増田の頻出キーワードリンク上位20件」から誤判定しそうな lineuser を除いた18件を用いた。10件だと生き残る英文スパムがあったので20件にしたが、それでもわずかに洩れはある。しか日本語による真っ当な(?)増田の直近の誤判定はなかった。はてなキーワードリンクだけを対象にしているので、URLにはこれらのキーワードが入っていても大丈夫だ。ただし、スパムトレンドが変われば話は変わってくるかもしれないし、過去未来増田誤判定は当然あるだろう。気になる人は前掲のCSSを行単位編集してほしい。

// AutoPagerizeでまとまった数のページを読み込ませた後に実行するとよい。
(function(){
  const keywords = [];
  // はてなキーワードの集計
  document.querySelectorAll('a.keyword').forEach(a => {
    // 4文字未満は誤検出の可能性が高まるので除外
    if(a.textContent.length < 4) return;
    let index = keywords.findIndex(k => k.keyword === a.textContent);
    if(index >= 0) keywords[index].count += 1;
    else keywords.push({keyword: a.textContent, count: 1});
  });
  keywords.sort((a, b) => a.count < b.count);
  // ランキング配列の出力
  console.log(keywords);
  // CSS埋め込み用に上位キーワードのみをURIエンコードして出力
  console.log(keywords.slice(0, 20).map(k => encodeURIComponent(k.keyword)).join('\n'));
})();

謝辞

anond:20250326171302 ←元はこの増田きっかけでした。

anond:20250701194328キーワード判定に踏み切る後押しとなりました。

2025-06-13

我が名はサイボーグdorawii

パーマリンク署名対象にするより堅牢自動化を作れた。

一度投稿したうえで別タブを開いてプログラム的(fetch)に送信してその別タブが閉じられる仕組み。

改めてスクリプト配布しちゃる

最初投稿してエントリページに移動した親タブ側のjsコード
// ==UserScript==
      // @name         PGP署名検出と別タブ自動編集
      // @namespace    http://tampermonkey.net/
      // @version      1.0
      // @description  PGP署名がない投稿自動編集ページへ誘導
      // @match        https://anond.hatelabo.jp/*
      // @grant        GM_setValue
      // @grant        GM_getValue
      // @grant        GM.openInTab
      // ==/UserScript==

      (function () {
        'use strict';

        const body = document.getElementById('entry-page');
        if (!body) return;

        const titleText = document.title;
        if (!titleText.includes('dorawii')) return;

        const pgpRegex = /BEGIN.*PGP(?: SIGNED MESSAGE| SIGNATURE)?/;
        const preElements = document.querySelectorAll('div.body pre');
        let hasPgpSignature = false;

        for (const pre of preElements) {
          if (pgpRegex.test(pre.textContent)) {
            hasPgpSignature = true;
            break;
          }
        }

        if (hasPgpSignature) return;

        const editLink = document.querySelector('a.edit');
        const childTab = GM.openInTab(editLink.href, { active: false, insert: true, setParent: true });

      })();
親タブから開かれる編集ページの子タブのjsコード
 // ==UserScript==
      // @name         編集ページ処理と自動送信・閉じ
      // @namespace    http://tampermonkey.net/
      // @version      1.0
      // @description  編集ページで署名処理と送信、タブ自動閉じ
      // @match        https://anond.hatelabo.jp/dorawii_31/edit?id=*
      // @grant        GM_getValue
      // @grant        GM_xmlhttpRequest
      // @grant        GM_setClipboard
      // @grant        GM_notification
      // @connect      localhost
      // ==/UserScript==

      (async function () {
        'use strict';

        const shouldRun = await GM_getValue('open-tab-for-edit', '0');

        const textareaId = 'text-body';
        const textarea = document.getElementById(textareaId);

        if (!textarea) return;

        const content = textarea.value;

        const pgpSignatureRegex = /-----BEGIN PGP SIGNED MESSAGE-----[\s\S]+?-----BEGIN PGP SIGNATURE-----[\s\S]+?-----END PGP SIGNATURE-----/;
        if (pgpSignatureRegex.test(content)) {
          console.log('[PGPスクリプト] 署名が検出されたためそのまま送信します');
          return;
        }

        const httpRequest = (url, data) =&gt; {
          return new Promise((resolve, reject) =&gt; {
            GM_xmlhttpRequest({
              method: 'POST',
              url: url,
              headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
              data: `value=${encodeURIComponent(data)}`,
              onload: function (response) {
                resolve(response.responseText);
              },
              onerror: function (error) {
                reject(error);
              }
            });
          });
        };


        // textarea の値を取得
        // 1. 現在のページのURLからURLオブジェクト作成
        const currentUrl = new URL(window.location.href);

        // 2. ベースとなる部分 (例: "https://anond.hatelabo.jp") を取得
        const origin = currentUrl.origin;

        // 3. 'id' パラメータの値 (例: "20250610184705") を取得
        const idValue = currentUrl.searchParams.get('id');

        // 4. ベース部分とIDを結合して、目的URL文字列を生成
        //    idValueが取得できた場合のみ実行する
        let newUrl = null;
        if (idValue) {
          newUrl = `${origin}/${idValue}`;
        }

        // 5. 生成されたURL変数に代入し、コンソールに出力して確認
        console.log(newUrl);
        const valueToSend = newUrl;

        try {
          const signatureText = await httpRequest('http://localhost:12345/run-batch', valueToSend);
          console.log('バッチ応答:', signatureText);
          if (!signatureText.includes('BEGIN PGP SIGNED MESSAGE')) {
            alert('PGP署名クリップボードに見つかりませんでした。');
            return;
          }

          const newText = content.replace(/\s*$/, '') + '\n' + signatureText + '\n';
          textarea.value = newText;

          console.log('[PGPスクリプト] 署名を貼り付けました。送信を再開します。');


          const form = document.forms.edit;

          const newForm = form.cloneNode(true);
          form.replaceWith(newForm);

          newForm.addEventListener('submit', async (e) =&gt; {
            e.preventDefault(); // HTML標準のsubmitをキャンセル
            const bodyText = textarea?.value || '';

            // reCAPTCHA トークンの取得
            const recaptchaToken = await new Promise((resolve) =&gt; {
              grecaptcha.enterprise.ready(() =&gt; {
                grecaptcha.enterprise.execute('hoge', { action: 'EDIT' })
                  .then(resolve);
              });
            });

            // POSTするデータの構築
            const formData = new FormData(newForm);
            formData.set('body', bodyText);
            formData.set('recaptcha_token', recaptchaToken);
            formData.set('edit', '1');
            try {
              const response = await fetch(newForm.action, {
                method: 'POST',
                body: formData,
                credentials: 'same-origin'
              });


              if (response.ok) {
                console.log('送信成功');
                window.close();


              } else {
                console.error('送信失敗', response.status);
              }
            } catch (err) {
              console.error('送信中にエラーが発生', err);
            }

          });

          // プログラム的に送信トリガー
          newForm.dispatchEvent(new Event('submit', { bubbles: true }));

        } catch (e) {
          console.error('バッチ呼び出し失敗:', e);
        }

      })();
node.jsで動かすローカルサーバーコード
const http = require('http');
const { exec } = require('child_process');
const querystring = require('querystring');

const server = http.createServer((req, res) =&gt; {
  if (req.method === 'GET' &amp;&amp; req.url === '/ping') {
    res.writeHead(200);
    res.end('pong');
  } else if (req.method === 'POST' &amp;&amp; req.url === '/run-batch') {
    let body = '';

    req.on('data', chunk =&gt; {
      body += chunk.toString();
    });

    req.on('end', () =&gt; {
      const parsed = querystring.parse(body);
      const value = parsed.value || 'default';

      // 値を引数としてバッチに渡す
      exec(`C:\\Users\\hoge\\Desktop\\makesign.bat "${value}"`, { encoding: 'utf8' }, (err, stdout, stderr) =&gt; {
        if (err) {
          res.writeHead(500);
          res.end('Error executing batch: ' + stderr);
        } else {
          res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
          res.end(stdout.trim());
        }
      });
    });

  } else {
    res.writeHead(404);
    res.end('Not found');
  }
});

server.listen(12345, () =&gt; {
  console.log('Batch server running at http://localhost:12345/');
});
@echo off
setlocal enabledelayedexpansion


:: 署名するファイルset "infile=%~1"
set outfile=%TEMP%\pgp_output.asc

:: 以前の出力があれば削除
if exist "%outfile%" del "%outfile%"


:signloop
:: AutoHotkeyパスフレーズ入力(gpgがパスワード要求するダイアログが出た場合に備える)
start "" /b "C:\Users\hoge\Documents\AutoHotkey\autopass.ahk"

:: PGPクリア署名作成
echo %infile% | gpg --yes --clearsign --output "%outfile%"


:: 署名成功していればループを抜ける
if exist "%outfile%" (

    goto postprocess
) else (

    timeout /t 1 &gt; nul
    goto signloop
)
:postprocess

powershell -nologo -command ^
  "$header = '&gt;|'; $footer = '|&lt;'; $body = Get-Content '%outfile%' -Raw; Write-Output ($header + \"`r`n\" + $body + $footer)"

powershell -nologo -command ^
  "$header = '&gt;|'; $footer = '|&lt;'; $body = Get-Content 'signed.asc' -Raw; Set-Clipboard -Value ($header + \"`r`n\" + $body + $footer)"

endlocal
exit /b
AutoHotkey(以前と同じ)
#Persistent
#SingleInstance ignore
SetTitleMatchMode, 2
WinWaitActive, pinentry
SendInput password
Sleep 100
SendInput {Enter}
ExitApp

動けばいいという考えで作っているので余分なコードも含んでいるかもしれない。

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

https://anond.hatelabo.jp/20250613185036 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaEv1FQAKCRBwMdsubs4+
SHHkAQDUOLgBcdji2T6MJ7h/vlMdFfGlWAzNdXijjE1gIuEPywEAiMNMZqhrMmtl
c7UqRuggNJ/UTa5xTIcKp622+7jJQQg=
=Lgkl
-----END PGP SIGNATURE-----

2025-06-09

dorawii

ようやく(ほぼ)すべてが自動化された。

あとはローカルサーバーの起動をスタートアップに設定する(方法AIに聞いて指示に従う)だけの消化試合

ここにほとんどAI頼りのコードを公開しておく。

事前にインストールしておくもの

autohotkey

nodejs

ユーザースクリプトを実行できる拡張機能

パスとかの注意

署名要求してくるパスワードを自動入力するahkファイルドキュメントAutoHotkey配下に置いた。

バッチファイル(make.sign.bat)はデスクトップに置いた。

以下コード

autopass.ahk
#Persistent
#SingleInstance ignore
SetTitleMatchMode, 2
WinWaitActive, pinentry
SendInput お前のパスワード
Sleep 100
SendInput {Enter}
ExitApp
run-bacth-server.js
// run-batch-server.js
const http = require('http');
const { exec } = require('child_process');

const server = http.createServer((req, res) =&gt; {
  if (req.url === '/ping') {
    res.writeHead(200);
    res.end('pong');
  } else if (req.url === '/run-batch') {
    exec('C:\\Users\\you\\Desktop\\makesign.bat', (err) =&gt; {
      res.writeHead(200);
      res.end(err ? 'Error' : 'OK');
    })
    ;
  } else {
    res.writeHead(404);
    res.end('Not found');
  }
});

server.listen(12345, () =&gt; {
  console.log('Batch server running at http://localhost:12345/');
});
makesign.bat
@echo off
setlocal enabledelayedexpansion

:: ミリ秒単位UTC時刻を取得
for /f %%a in ('powershell -nologo -command "[int64]::Parse((Get-Date).ToUniversalTime().ToString('yyyyMMddHHmmssfff'))"') do set timestamp=%%a

:: 署名するファイルset infile=%TEMP%\pgp_input.txt
set outfile=%TEMP%\pgp_output.asc

:: 以前の出力があれば削除
if exist "%outfile%" del "%outfile%"

:: タイムスタンプを原文として保存
echo %timestamp% &gt; "%infile%"

:signloop
:: AutoHotkeyパスフレーズ入力(gpgがパスワード要求するダイアログが出た場合に備える)
start "" /b "C:\Users\infini\Documents\AutoHotkey\autopass.ahk"

:: PGPクリア署名作成
gpg --yes --clearsign --output "%outfile%" "%infile%"


:: 署名成功していればループを抜ける
if exist "%outfile%" (
    echo [INFO] 署名成功
    goto postprocess
) else (
    echo [WARN] 署名失敗、再試行します…
    timeout /t 1 &gt; nul
    goto signloop
)
:postprocess

:: PowerShellで余計な改行なしに |&lt; をつけてクリップボードコピー
powershell -nologo -command ^
  "$header = '&gt;|'; $footer = '|&lt;'; $body = Get-Content '%outfile%' -Raw; Set-Clipboard -Value ($header + \"`r`n\" + $body + $footer)"

echo Done. signed.asc created and clipboard updated (no extra blank line).
endlocal
exit /b
tempermonkeyとかに登録するユーザースクリプト
// ==UserScript==
// @name         PGP署名自動付加スクリプト(GM_xmlhttpRequest版)
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  投稿前にPGP署名を付けてから送信(fetch未使用)
// @match        https://anond.hatelabo.jp/dorawii_31/edit*
// @grant        GM_xmlhttpRequest
// @grant        GM_setClipboard
// @grant        GM_notification
// / @connect      localhost
// ==/UserScript==

(function () {
  'use strict';

  const submitId = 'submit-button';
  const textareaId = 'text-body';
  const localServer = 'http://localhost:12345/run-batch';

  const pgpSignatureRegex = /-----BEGIN PGP SIGNED MESSAGE-----[\s\S]+?-----BEGIN PGP SIGNATURE-----[\s\S]+?-----END PGP SIGNATURE-----/;

  const httpRequest = (url) =&gt; {
    return new Promise((resolve, reject) =&gt; {
      GM_xmlhttpRequest({
        method: 'GET',
        url: url,
        onload: function (response) {
          resolve(response.responseText);
        },
        onerror: function (error) {
          reject(error);
        }
      });
    });
  };

  const interceptClick = () =&gt; {
    const btn = document.getElementById(submitId);
    if (!btn || btn.dataset.pgpIntercepted === 'true') return;
    btn.dataset.pgpIntercepted = 'true';

    btn.addEventListener('click', async function (e) {
      const textarea = document.getElementById(textareaId);
      if (!textarea) return;

      const content = textarea.value;

      if (pgpSignatureRegex.test(content)) {
        console.log('[PGPスクリプト] 署名が検出されたためそのまま送信します');
        return;
      }

      e.preventDefault();
      e.stopImmediatePropagation();
      console.log('[PGPスクリプト] 署名が見つからないため処理を停止し、署名を取得します');

      try {
        await httpRequest(localServer); // バッチ実行

        const signatureText = await navigator.clipboard.readText();
        if (!signatureText.includes('BEGIN PGP SIGNED MESSAGE')) {
          alert('PGP署名クリップボードに見つかりませんでした。');
          return;
        }

        const newText = content.replace(/\s*$/, '') + '\n' + signatureText + '\n';
        textarea.value = newText;

        console.log('[PGPスクリプト] 署名を貼り付けました。送信を再開します。');
        btn.click(); // イベント再発火

      } catch (err) {
        alert('PGP署名の取得または貼り付けに失敗しました。\n' + err);
      }
    }, true);
  };

  window.addEventListener('load', () =&gt; {
    setTimeout(interceptClick, 1000);
  });
})();

プロミスメソッドとか全然まだ理解してなくてそのなかに関数代入したその関数オブジェクトプロパティresponseを?いやまあそのあたりのコードが示すデータの流れが全然理解できないような人間でもここまでできちゃった。

AIすごいなと思うよ。そして思うのは今後重要になってくるのは文法とか自体に詳しいことじゃなくて、そのプログラムの処理内容を指示できるシステムエンジニア的な言語化能力のほうじゃないかなと思った。

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

20250609111559680 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaEbCbwAKCRBwMdsubs4+
SLueAPwOv7PBk4voAe5qlcCEvs/PJhmKc5QAb/1R43JMQFuDZgD/UTPEKsL/PhK9
jFGv2HDXK1dVjLNwvosgX9uYJh5xxwY=
=qiOE
-----END PGP SIGNATURE-----

2025-03-22

増田3分以上投稿されない時間

増田で 3 分以上投稿されない期間があるのか気になったから調べた

直近の 1 日だとこれだけあった

 

2025-03-22 00:14 -- 2025-03-22 00:18
2025-03-22 00:10 -- 2025-03-22 00:14
2025-03-21 07:56 -- 2025-03-21 08:00
2025-03-21 07:50 -- 2025-03-21 07:56
2025-03-21 07:44 -- 2025-03-21 07:48
2025-03-21 07:28 -- 2025-03-21 07:32
2025-03-21 06:58 -- 2025-03-21 07:03
2025-03-21 06:45 -- 2025-03-21 06:54
2025-03-21 06:32 -- 2025-03-21 06:37
2025-03-21 05:56 -- 2025-03-21 06:04
2025-03-21 05:51 -- 2025-03-21 05:56
2025-03-21 05:34 -- 2025-03-21 05:38
2025-03-21 05:30 -- 2025-03-21 05:34
2025-03-21 05:00 -- 2025-03-21 05:09
2025-03-21 04:56 -- 2025-03-21 05:00
2025-03-21 04:45 -- 2025-03-21 04:50
2025-03-21 04:09 -- 2025-03-21 04:13
2025-03-21 03:41 -- 2025-03-21 03:45
2025-03-21 03:29 -- 2025-03-21 03:39
2025-03-21 03:03 -- 2025-03-21 03:07
2025-03-21 02:56 -- 2025-03-21 03:02
2025-03-21 02:44 -- 2025-03-21 02:48
2025-03-21 02:33 -- 2025-03-21 02:37
2025-03-21 02:21 -- 2025-03-21 02:27
2025-03-21 02:14 -- 2025-03-21 02:19

 

秒はみてないから 00:01:01 - 00:03:59 はほぼ 3 分だけど 2 分扱いだし、 00:01:59 - 00:04:00 はほぼ 2 分だけど 3 分扱いになるくらいの誤差はある

 

日によって違うだろうし、曜日の影響も大きそうだから 1 ヶ月分くらい調査しようかと思ったけど、

増田の量が思いの外多すぎて 1 日分だけでも 100 ページ以上取得しないといけなかった

件数だと 2500 以上

 

その量の収集は大変だし規制掛かりそうだから諦めた

一応取得に使ったコードも載せとく

そんなきれいなコードでもないけど

 

import { setTimeout } from "node:timers/promises"
import { Browser } from "happy-dom"

const getTimestamps = async function* () {
	const browser = new Browser()
	const page = browser.newPage()

	try {
		for (let num = 1; ; num++) {
			await setTimeout(3000)
			await page.goto(`https://anond.hatelabo.jp/?page=${num}`)

			const days = page.mainFrame.document.querySelectorAll(".day")
			for (const day of days) {
				const date = day.querySelector("h2 .date").textContent.trim()
				for (const footer of day.querySelectorAll(".sectionfooter")) {
					const time = footer.textContent.match(/\d{2}:\d{2}/)[0]
					yield `${date} ${time}`
				}
			}
		}
	} finally {
		await page.close()
		await browser.close()
	}
}

const diff = (a, b) =&gt; {
	return new Date(b + ":00") - new Date(a + ":00")
}

let prev = null
for await (const datetime of getTimestamps()) {
	if (prev &amp;amp;&amp;amp; diff(datetime, prev) &gt; 1000 * 60  * 3) {
		console.log(datetime, prev)
	}
	prev = datetime
}

 

結果をみると昼間はずっと深夜から早朝にかけてときどきある

基本は空いても 5 分程度であり、最大でも 10 分となっている

投稿が少ないと感じるときもあるが、賑わってる方だといえる

2025-02-25

Webしか見ていないのに全てがわかった気になってる人

2024-12-22

gmail大掃除と、自動処理の方法

簡単にすっきりさせて容量を減らす方法

検索式を書きますので、それで見つかったファイルを全て選択して、削除などのアクションをしてください。

細かな調整は各自のお好みで変更してください。

 

◆1年以上前ファイルサイズの大きなメール(300kB以上)を検索(星を付けたメールは除く)。削除しましょう。

older_than:1y larger:300k -is:starred

 

プロモーションソーシャルに分類された1か月以上前メール検索。削除しましょう

(category:promotions OR category:social) older_than:30d

 

◆受信トレイの180日以上前メール検索アーカイブして、受信トレイメール数を減らしましょう

label:inbox older_than:180d

 

プロモーションソーシャルに入ったメールで2日経ったもの検索既読しましょう。

label:inbox (category:promotions OR category:social) older_than:2d

 

これらの作業毎日自動で行ってもらう方法

Google Apps ScriptGAS)を使うとこれを毎日自動で行ってもらえます

 

chromeで以下のURLで新しいGASを作ります

https://script.new

 

文末のソースコードコピペする。

実行の左のアイコンで保存。関数をcleanUpGmailを選んで実行。初回は権限確認メッセージが出るのでOKを押してください。

事実行出来たら一番の難関はクリアです。これを毎日自動で実行してもらいましょう。一度に250通が処理されます

また余裕があれば、左上の無題のプロジェクトになっているところの名前を「gmail自動処理」などに変更しても良いでしょう。

  

自動実行の方法

左の時計マークトリガーを選ぶ

トリガーを追加する。トリガーの設定は

実行する関数:CleanUpGmail
デプロイ:Head
イベント時間主導
時間べース:時間ベース
時間の間隔:6時間おき

 

これで1日に4回、合計1000通が自動処理されますので、たくさんメールが溜まっている方でも、1か月程度で全て処理されると思います

 

function cleanUpGmail() {
  // メインの関数の開始ログ
  console.log("=== cleanUpGmail start ===");
  
  // 1) 2年以上前 &amp;amp; 300KB以上 &amp;amp; from:gmail.comではない &amp;amp; スター付きではない → 削除
  console.log("古い大きなメールは削除");
  processThreads("older_than:2y larger:300k -from:gmail.com -is:starred", "trash");
  
  // 2) プロモーション or ソーシャル &amp;amp; 30日以上前 → 削除
  console.log("プロモーションソーシャルは1か月で削除");
  processThreads("(category:promotions OR category:social) older_than:30d", "trash");
  
  // 3) 受信トレイ &amp;amp; 180日以上前アーカイブ
  console.log("受信トレイの180日以上前アーカイブ");
  processThreads("label:inbox older_than:180d", "archive");
  
  // 4) 受信トレイ &amp;amp; プロモーション or ソーシャル &amp;amp; 2日以上前既読
  console.log("受信トレイプロモーション or ソーシャル かつ 2日以上前既読");
  processThreads("label:inbox (category:promotions OR category:social) older_than:2d", "markRead");
  
  
  console.log("=== cleanUpGmail end ===");
}


function processThreads(query, action) {
  
  // 1回あたり250件だけ処理
  var batchSize = 250;
  // 最初の 250 件のみ取得
  var threads = GmailApp.search(query, 0, batchSize);
  var count = threads.length;
  Logger.log("検索クエリ: [" + query + "] | 取得スレッド数: " + count);
  
  // スレッドごとにアクションを実行
  threads.forEach(function(thread) {
    switch (action) {
      case "trash":
        thread.moveToTrash();
        break;
      case "archive":
        thread.moveToArchive();
        break;
      case "markRead":
        thread.markRead();
        break;
      default:
        Logger.log("不明アクション: " + action);
    }
  });  
  Logger.log("処理したスレッド数: " + count);
}

2024-09-22

AIインフルエンサーたちはChatGPTが世に出る前は何を投稿していたのか?(2/2)

AIインフルエンサーたちはChatGPTが世に出る前は何を投稿していたのか?(1/1)の続き

吉見拓哉|Takuya Yoshimi

このTwitterアカウントは、主にYouTubeSEO競馬アニメなどの話題について呟いており、自身活動や興味関心について発信しています

YouTubeプレミアムが500円増額。しかし、、、不可逆!!!

shimayuz@AIクリエイター

このアカウントは、日々の米国株暗号通貨市場動向、特にテクノロジー関連株やビットコイン価格変動についてツイートしています

ゼロコロナ政策再び。 $AAPL生産に影響が懸念され大きく下落。更に経済混乱が想定され、株価はSP500全業種で

一方で年末商戦売上堅調な滑り出しで $AMZN

暗号資産レンディングBlockFiが経営破綻暗号通貨も軒並み下落。

チャート上、なんとか踏み止まるか? 」

元木大介ᯅシステム生成AI Babel/Zoltraak & 生成AI塾

このアカウントは、AI特にプロマネAIや量子AIに関する話題や、仕事効率化、プログラミング、そして最新の技術トレンドについて呟いています

"プロマネAI実証実験を開始しました!量子AI×NotionによるプロマネAI実証実験を開始 https://prtimes.jp/main/html/rd/p/000000003.000082094.htmlvia @PRTIMES_JP"

sangmin.eth | Dify Ambassador

このアカウントは、主にOpenAIの最新言語モデルtext-davinci-003」の進化と、そのモデルを用いた英語学習ツールサービスについて呟いています特に英語学習におけるAI活用とその重要性を強調しています

"朝起きたら世界がまた変わっていた(笑)。@OpenAI が最新モデルtext-davinci-003」を発表。主な特徴は、①より明確で、説得力のある文章が書ける②より複雑な指示にも対応③より長い形式コンテンツが生成可 1月に"InstructGPT"が出た時も感動したけどそれを遥かに上回る進化、です。"

深津 貴之 / THE GUILD

このアカウントは、主にAI特に画像生成AIに関する話題を呟いています特にStable Diffusionのバージョンアップや使い方について多くのツイートをしています

結果

ここにリストアップした人たち以外もみましたが、分類すると3種類のアカウントがいて

1. ChatGPTブーム後にアカウントを始めた人

2. NFTなどの儲かりそうな技術を追いかけていた人

3. 日常ツイートをしていたが目覚めてしまった人

共通する特徴としては会社代表の人が多いです。

またIDを変更してログがヒットしない人は含まれていません(IDから特定できるけどそこまでやらなかった)

ツイートを取得するJS

javascript:(function() {

const text = Array.from(document.querySelectorAll('[data-testid="tweetText"]')).map(s =&gt; s.textContent.trim()).join('\n');

const textarea = document.createElement('textarea');

textarea.value = text;

document.body.appendChild(textarea);

textarea.select();

try {

document.execCommand('copy');

console.log('結果がクリップボードコピーされました!');

} catch (err) {

console.error('クリップボードへのコピーに失敗しました:', err);

}

document.body.removeChild(textarea);

})();

2024-09-15

RSS 取得メモ

const axios = require('axios'); // HTTPリクエストを行うためのモジュール

const fs = require('fs'); // ファイル操作モジュール

const xml2js = require('xml2js'); // XMLJSONに変換するためのモジュール

const chardet = require('chardet'); // 文字エンコーディングを検出するためのモジュール

const iconv = require('iconv-lite'); // 文字エンコーディングを変換するためのモジュール

// RSSフィードURL

const rssUrl = 'https://www.mlit.go.jp/important.rdf'; // 例としてRSSフィードURL指定

// RSSフィードを取得してファイルに保存する関数

async function fetchAndSaveRSS() {

try {

// RSSを取得

const response = await axios.get(rssUrl, { responseType: 'arraybuffer' });

const rssData = response.data;

// 文字エンコーディングを検出

const detectedEncoding = chardet.detect(rssData);

console.log('検出された文字エンコーディング:', detectedEncoding);

// UTF-8に変換

const utf8Data = iconv.decode(rssData, detectedEncoding);

// XMLJSONパース

xml2js.parseString(utf8Data, (err, result) =&gt; {

if (err) {

console.error('XML解析エラー:', err);

return;

}

// パース結果をファイル書き込み

const jsonData = JSON.stringify(result, null, 2);

fs.writeFileSync('rss_feed.json', jsonData, 'utf8');

console.log('RSSフィードファイルに保存されました。');

});

} catch (error) {

console.error('エラーが発生しました:', error);

}

}

// 実行

fetchAndSaveRSS();

2024-09-05

anond:20240904032316

anond:20240904032316についてたブクマカの初めて買ったCDリリース年を調べた。

スクレイピング

Chromeコンソールから

for (let a of document.body.getElementsByClassName('entry-comment-text js-bookmark-comment')) console.log(a.textContent) 

ってやってテキスト集める。

AIリリース年を教えてもらう

Microsoft Copilotに「以下の文章に出てくる、音楽CDタイトルリリース年を一覧で表にしてください。」って指示。

タイトルリリース
パンチ・ザ・クロック (エルヴィス・コステロ)1983年
ハイランドハードレイン (アズテックカメラ)1983年
TSUNAMI (サザンオールスターズ)2000年
ロケット団永遠に (ポケモン)1998年
パラダイス銀河 (光GENJI)1988年
さよなら人類 (たま)1990年
SUPER BEST II (CHAGE&amp;ASKA)1992年
LOVEマシーン (モーニング娘。)1999年
treasure (B’z)1998年
pleasure (B’z)1997年
POP LIFE (JUDY AND MARY)1998年
F-ZERO GX サウンドトラック2003年
Chicago 17 (Chicago)1984年
Wind Climbing ~風にあそばれて~ (奥井亜紀)1997年
バロック音楽不明
季節がいく時 (SPEED)1999年
天外魔境 (ゲーム)1989年
旅人のうた (中島みゆき)1995年
ドリームシフト (地球防衛組)1991年
INNOCENT SORROW (abingdon boys school)2006年
カルトグラススターズ (ミッシェルガンエレファント)2000年
悪の華 (BUCK-TICK)1990年
風が通り抜ける街へ (ZARD)1993年
My Little Lover1995年
globe1996年
小松未歩 ファーストアルバム1997年
愛の言霊 (サザンオールスターズ)1996年
そばかす (JUDY AND MARY)1996年
中村めいこ不明
ポケットモンスター赤緑 BGM音源1997年
TWO-MIX TRUTH1996年
Wind Climbing ~風にあそばれて~ (魔法陣グルグル)1997年
ジュラシックパーク サウンドトラック1993年
After Burner サウンドトラック (SEGA)1987年
Love Wing (ハミングバード)1993年
super best 2 (CHAGE&amp;ASKA)1992年
中山美穂 8cmCDシングル不明
C-Girl (浅香唯)1988年
天晴 (サディスティック・ミカ・バンド)1974年
Hi! (光GENJI)1988年
CAROL (TM NETWORK)1988年
DORA THE BEST (ドラえもん)1999年
がじゃいも1997年
美少女戦士セーラームーン~In Another Dream1992年
交響曲ドラゴンクエストIV 導かれし者たち N響1990年
ポケモン言えるかな1997年
dear (大江千里)1989年
めずらしい人生 (KAN)1990年
BECAUSE (有頂天)1986年
スーパーゼビウス 12inchEP (細野晴臣)1984年
ZUTTO (永井真理子)1990年
愛は勝つ (KAN)1990年
クラシックCD (100円ショップ)不明
ブルーハーツ ファーストアルバム1987年
I’m Here (小比類巻かほる)1988年
微笑みの爆弾 (幽遊白書)1992年
くじら12号 (JUDY AND MARY)1996年
無罪モラトリアム (椎名林檎)1999年
愛のままにわがままに 僕は君だけを傷つけない (B’z)1993年
WORST (聖飢魔II)1990年
BADDEST (久保田利伸)1989年
Delight Slight Light KISS (松任谷由実)1988年
リフレインが叫んでる (松任谷由実)1988年
Gift for Fanks (TM NETWORK)1987年
もっと強く君を抱きしめたなら1994年
Che Che-Bye Bye (種ともこ)1991年
負けないで (ZARD)1993年
愛と虐殺の日々 (聖飢魔II)1991年
ペットショップボーイズ1986年
機動戦士Zガンダム オリジナルサウンドトラック1985年
マルコじいさん (さねよしいさこ)1995年
めざせポケモンマスター1997年
淋しい熱帯魚 (Wink)1989年
キャロル (TM NETWORK)1988年
幽遊白書 ミュージックバトル編1993年
蜘蛛の糸 (筋肉少女帯)1990年
Winners (サイバーフォーミュラー)1991年
だんご3兄弟1999年
Achtung Baby (U2)1991年
faith (George Michael)1987年
ダイアモンド (プリンセス プリンセス)1989年
The very best of Unicorn1993年
ALFEE GOLD (ALFEE)1985年
そして伝説へ (鴻上尚史)1986年
マシンガンズの集い (SEX MACHINEGUNS)1998年
FF4 アレンジミニアルバム1991年
ブルーウォーター (森川美穂)1990年
鉄骨飲料1990年
SPY (槇原敬之)1994年
尾崎家の祖母(3) (まりちゃんズ)1977年
TIME (REBECCA)1986年
もう一度TENDERNESS1995年
HIGH LANDER (爆風スランプ)1989年
空耳の丘 (遊佐未森)1990年
Yellow Yellow Happy (ポケットビスケッツ)1996年
リッジレーサー2 サウンドトラック1994年
フラッシュパパメンソール (電気グルーヴ)1995年
さよなら人類 (たま)1990年
倉木麻衣アルバム不明
カルミナ・ブラーナ (輸入盤)不明
スキャットマン (Scatman John)1994年
白い雲のように (猿岩石)1996年
幽☆遊☆白書 オリジナルサウンドトラックVol2~魔界の扉編~1994年
ヴェルディ川崎応援歌不明
ShinWeAre (BoA)2003年
忘れない/風の住む星 (西脇唯)1995年
ヴィヴァルディ四季不明
田園 (小学館クラシック・イン」)不明
ゼルダの伝説 風のタクト オリジナルサウンドトラック2003年
MUSIC from HYDLIDE31987年
君だけのTomorrow (ドロンズ)1997年
松浦亜弥アルバム不明
ドラクエサントラ不明
マンモスフラワー (フラワーカンパニーズ)2000年
めざせポケモンマスター1997年
ユグドラシル (BUMP OF CHICKEN)2004年
マリオRPG サウンドトラック1996年
ファイナルファンタジーVII リユニオントラック1997年
Time to Destination (Every Little Thing)1998年
ショパンアルバム (アルゲリッチ)不明
ここは春の国 (谷山浩子)1988年
Valkyrie Notes (TONERICO)2019年
Love Phantom (B’z)1995年
with you (三上博史)1993年
夏の日の1993 (class)1993年
いとしのエリー (サザンオールスターズ)1979年
Round About Midnight (Miles Davis)1957年
Gift for Fanks (TM NETWORK)1987年
ez do dance (TRF)1993年
イージューライダー (奥田民生)1996年
ロマサガ サウンドトラック1992年
ドラクエ2 ドラマCD1990年
DATE (岡村靖幸)1988年
ETERNAL WIND (森口博子)1991年
ARAKAWA魂 (荒川ラップブラザーズ)2003年
愛の言霊 (サザンオールスターズ)1996年
ドラゴンクエスト3 サウンドトラック1988年
モールワールド (ヒューイ・ルイス&amp;ザ・ニュース)1988年
HOME (Mr.Children)2007年
trfアルバム不明
ガニ (とんねるず)不明
暴動 (There’s a Riot GoinOn) (Sly and the Family Stone)1971年
カミワザ -dIvine works-不明
シングルベスト10 おまけつき (シャ乱Q)1997年
カウボーイビバップ サウンドトラック1998年
ガンダムF91 サウンドトラック (森口博子)1991年
暴れだす (ウルフルズ)1995年
団子3兄弟1999年
エルドラド (THE ALFEE)1997年
foo? (ポルノグラフィティ)2001年
Until Strawberry Sherbet (林原めぐみ)1997年
勇気のしるし~リゲインテーマ~ (時任三郎)1989年
いとしさと切なさと心強さと (篠原涼子 with t.komuro)1994年
REVIEW (GLAY)1997年
愛の言霊 (サザンオールスターズ)1996年
ナイスビート (キンモクセイ)2002年
Carol (TM NETWORK)1988年
サン=サーンスオルガン (マルティノン)不明
銀河鉄道の夜 (細野晴臣)1985年
ロード第二章 (THE 虎舞竜)1993年
IT’S ONLY LOVE (福山雅治)1994年
バザール3兄弟音頭不明
さよなら人類 (たま)1990年
フロムイエスタデイ (桑田佳祐)1992年
アスタリスク (ORANGE RANGE)2005年
ark (L’Arc~en~Ciel)1999年
春よ、来い (松任谷由実)1994年
ray (L’Arc~en~Ciel)1999年
ポケモン言えるかな1997年
ニーベルングの指環 管弦楽曲集 (ショルティ/VPO)1986年
minoru land (向谷実)1986年
1stアルバム (人間椅子)1990年
the great escape (JUDY AND MARY)2001年
bluebird (浜崎あゆみ)2006年
Variety (竹内まりや)1984年
Watermark (エンヤ)1988年
BEAT EMOTION (BOOWY)1986年
ARAKAWA魂 (荒川ラップブラザーズ)2003年
MYSELF ~風になりたい~ (徳永英明)1991年
ひとりじゃない (DEEN)1996年
ドリームハンター麗夢 サウンドトラック1985年
シンディ・ローパー不明
Keep The Faith (Bon Jovi)1992年
君がいるだけで (米米CLUB)1992年
シェイク (SMAP)1996年
決戦は金曜日 (DREAMS COME TRUE)1992年
SelEVENTH MOON (FireBomber)1995年
田園 (玉置浩二)1996年
プロビジョン (スクリッティ・ポリッティ)1988年
クラッシュ万事休す不明
yellow yellow happy (ポケットビスケッツ)1996年
STONED TOWN (akeboshi)2004年
ナイトフォール・イン・ミドルアース (ブラインド・ガーディアン)1998年
1st (ブルーハーツ)1987年
FENCE OF DEFENSE III (FENCE OF DEFENSE)1988年
カラクリハウス (レピッシュ)1989年
just communication (two-mix)1995年
マーラー交響曲7番「夜の歌」ロリン・マゼール指揮ウィーンフィル不明
未来航路 (La’cryma Christi)1997年
BELLS (吉田美奈子)1986年
原子心母 (Pink Floyd)1970年
プリパラミュージックコレクション不明
トラブル・イン・ヘブン (宇都宮隆)1994年
Kiss me (氷室京介)1992年
Past Masters1 (The Beatles)1988年
super donuts (スターダストレビュー)1990年
ザ・タイマーズ1989年
LIFE (小沢健二)1994年
FF5 サウンドトラック1992年
踊るポンポコリン (B.B.クィーンズ)1990年
イノセントマン (ビリー・ジョエル)1983年
だんご3兄弟1999年
ベト5シューベルト未完成 (カルロ・マリア・ジュリーニ)不明
MAGIC OF LOVE (アニメ魔法陣グルグル)1994年
ラグランジュポイント サウンドトラック1991年

途中で切れたので分割する。 続き→ anond:20240905115337

2024-08-16

anond:20240816092530

増田コードを表示する方法説明しますね。

記法

ふつう投稿と違うのは以下の3点だけです。

特殊文字は、実体参照(&amp; や &lt;)ではうまくいきません。数値参照を使ってください。

出したい文字数値文字参照
&&#38;
<&#60;
>&#62;

このようなコードを表示したい場合

const dinner = (chicken, curry) => {
if (chicken && curry) {
console.log('チキンかつカレー')
}
}

このように入力してください。

<pre>const dinner = (chicken, curry) =&#62; {<br>    if (chicken &#38;&#38; curry) {<br>        console.log('チキンかつカレー')<br>    }<br>}</pre>

2024-03-01

Imagusの設定

imagusがあにまん掲示板マウスオーバー画像表示に対応してなかったのでsieve設定を自前で書いてみた。

名前:animan

img:bbs\.animanch\.com\/(?:thumb_m|storage\/thumb_m)\/(\d{7}\/\d{1,4})

to:

:

var s0=$[0];

if (s0.includes("storage")) {

console.log("過去ログ.");}

else {

console.log("現行スレ.");}

return s0.replace("thumb_m","img");

2024-01-05

JavaScript でさあ

変数 value が null でも undefined でもない事を確認するのに

   if (value) {
      console.log('null でも undefined でもねーわ');
   }

これほんとやめろって。

おかげで value に 0 とかが入ってる時に、このコンディションが false になるわけだ。

色んな会社さんのコード見てきたけど、このタイプバグ本当に多い。

今まさに、まーたこバグを見つけて増田を書いてるわけで。

昨年は、世界的にも有名な会社さんのフレームワークがこれでバグってた。

ももう既にシステムの一部は本番稼働しててフレームワークはいじれない。

仕方ないので value には一旦文字列の '0' を渡しておいて if (value) {~} の中の重要ロジックを動かして

(めっちゃ幸運な事に、数値 0 のかわりに文字列 '0' でも正しく動くような、型について緩いロジックだったから)

その後で改めて value に数値 0 を入れなおすという、きったないハックで誤魔化した事もある。

自分お客様だったら怒るね。「いやいや、全部理想的コードにしてちょうだいよ。お金払ってんだよ?」って。

もし建築世界でこんな誤魔化しが起こってたら、人の命が消えちゃうよ。。。

2023-12-25

let hello = {hello: "hello"};

let bye = hello.hello;

hello.hello = "aaa";

console.log(bye); helloが表示

↑わかる。helloの値とそれに伴い参照が変わってもbyeの参照は以前"hello"を指してるから

let hello = {hello: "hello"};

let bye = hello;

hello.hello = "aaa";

console.log(bye.hello);aaaが表示

↑わかったようなわからんような…これ以上オブジェクトネストした者同士の代入の組み合わせされるといよいよ理解が追い付かなくなる

2023-10-31

数分で始めるJavaScript

Hello, World!

と出力されていれば成功

これで JavaScript を実行する最小限の環境は整った。

好きなようにプログラムを書いてコンソールに出力したり画面に書き出したりしてみて。

「指示の通りにならない!」という時はどこでつまずいてるか書いて。対応策を助言できるかもしれない。

2023-08-04

綺麗なコードって綺麗に書くことじゃないよ

本当にあった話だけど、JavaScriptstrっていう変数テキストが入っていて

その変数に'apple'とか'banana'とかが入ってるかどうかを判別するっていうロジックを作るとき

const re = new RegExp("apple")
if(re.test(str)) console.log("match")

みたいなサンプルコードを見つけてきて

const re_apple = new RegExp("apple")
const re_banana = new RegExp("banana")
if ( re_apple.test(str) || re_banana.test(str) ) console.log("match")

っていうコードを書く人がおるんよ

別にプログラミング初めて3ヶ月の初心者じゃ無くて20年以上やってるようなベテランだったり

なんならチーフプログラマーとして若手指導してるような人でもこういうレベルの人って割といるわけ

これに対して

正規表現でORを書くべき」

「includeで十分」

かいう指摘ももちろん正しいんだけど

綺麗にコードを書くっていうのは

「これってappleとかbanana以外に増えたりしないの?」

「fruitsかどうかを判別するならその変数を作った方が良くない?」

っていうのを考えて実装するのが綺麗にコードを書くっていうことで

変数名だとか整形とかは大事だけどそういう話じゃ無いんだよね

ちなみに

正規表現でORを書きましょう」

とかをPRレビューコメントしても

「動いてるからいいじゃない」

「綺麗に書いても性能上意味ない」

「言ってることが良く分からない。何が違うのか」

とか言ってくるし

言ってこなくて言われた通りに直しても次もまた同じことしてくるのでマジでレビューって大変だよ

2023-07-23

素早くブクマされた増田を強調 簡易セルクマ検知ユーザースクリプト

https://b.hatena.ne.jp/site/anond.hatelabo.jp

で動くスクリプトでたとえば投稿10分以内にブクマされページに乗ったら「1 user」が「1 user セルクマ 1とか5(何分後にブクマされたか)」になる。もしマイナスなら誤判定なので無視して。

時間を置いたセルクマには効かないし普通ファーストブクマカがどれぐらいの頻度で確認してるかしらないけど5分以内や1分以内もポロポロあるのでまあ目安に。

増田URLと一覧の時刻表示差分を取ってます

増田じゃpre記法でも記号が変換されるみたいだから作業

.forEach(div =&gt; {

('.entrylist-contents-title &gt; a')

if(diffSec &gt;

とかの

&lt;&gt;

<>

に変えてね

他にも見落としあるかも

誤判定が減るから非公開ファーストブクマを判定できたらいいんだけどね。

// ==UserScript==
// @name         hatebu masuda selkmark
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  特定時間以内にブクマされた増田を強調する
// @author       You
// @match        https://b.hatena.ne.jp/site/anond.hatelabo.jp*
// @grant        none
// ==/UserScript==

(function() {
  'use strict';

  const threshold = 60 * 10 // 何秒以内か
  const domain = 'https://anond.hatelabo.jp/'
  const dateTemplate = '202301020304' // 時分まで url時刻表記
  const dateTest = new RegExp('\\d{' + dateTemplate.length + '}')
  document.querySelectorAll('div.entrylist-contents').forEach(div =&gt; {
    const masuda = div.querySelector('.entrylist-contents-title &gt; a')
    const dateStr = masuda.href.substring(domain.length + dateTemplate.length, domain.length)
    if (!dateTest.test(dateStr)) {
      // キーワードとか
      console.log('not diary', dateStr)
      return
    }

    // new Dateできるように変換
    // https://amateur-engineer.com/javascript-date-yyyymmddhhmm/
    const year = parseInt(dateStr.substring(0, 4))
    const month = parseInt(dateStr.substring(4, 6))
    const day = parseInt(dateStr.substring(6, 8))
    const hour = parseInt(dateStr.substring(8, 10))
    const min = parseInt(dateStr.substring(10, 12))
    const date = new Date(year, month - 1, day, hour, min)

    const bukumaDate = new Date(div.querySelector('.entrylist-contents-date').textContent) // 2023/01/23 00:00
    const diffSec = (bukumaDate - date) / 1000 // ms to sec

    if (diffSec &gt; threshold) {
      return
    }
    // ブクマ user
    const user = div.querySelector('span.entrylist-contents-users a').lastChild
    user.textContent += ' セルクマ ' + (diffSec / 60)

    // 古い記事マイナスになる でも2015年ぐらいの記事までかな?新着はセーフ臭い
    /*
    if(diffSec &lt; 0) {
      user.textContent += ' 異常差分:' + diffSec
    }
    */
  })
})();

2023-07-17

console.logデバッグしてたけどデバッガ使ったら便利でしたくらいのレベル感の話

ログイン ユーザー登録
ようこそ ゲスト さん