「doM」を含む日記 RSS

はてなキーワード: doMとは

2024-06-26

非エンジニアだけどClaude3に増田ミュート作ってもらったよ

これを改善してってお願いした。何書いてあるかわからないけど動いたよ。

https://anond.hatelabo.jp/20240125203115

// ==UserScript==
// @name         増田ミュート(白塗り版)
// @namespace    http://tampermonkey.net/
// @version      2024-06-26
// @description  ミューワードを含む最小限の範囲白塗りにする
// @author       You
// @match        https://anond.hatelabo.jp/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hatelabo.jp
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const muteWords = [
        "弱者男性",
        "弱男",
        "弱者",
        "婚活",
        "男",
        "女",
        "年収",
        "下方婚",
        "発達障害",
        "発達",
        "ハッタツ",
        "ハッタショ",
        "ハッタショ",
        "競プロ",
        "競技プログラミング",
        "AtCoder",
    ];

    function whiteoutElement(element) {
        element.style.backgroundColor = 'white';
        element.style.color = 'white';
        element.style.textShadow = 'none';
        element.style.cursor = 'default';
        element.style.userSelect = 'none';  // テキスト選択を防止
        element.style.borderBottom = '1px dashed #ccc'; // 枠線を追加してテキストがあることを示す

        // リンク場合クリック無効化
        if (element.tagName === 'A') {
            element.style.pointerEvents = 'none';
            element.removeAttribute('href');
        }

        // 子要素にも適用
        Array.from(element.children).forEach(child => {
            child.style.backgroundColor = 'white';
            child.style.color = 'white';
            child.style.textShadow = 'none';
        });

        // ツールチップを追加
        element.title = 'この内容にはミューワードが含まれています';
    }

    function shouldMute(text) {
        return muteWords.some(word => {
            const parts = word.split('');
            const regex = new RegExp(parts.map(char => `${char}\\s*`).join(''), 'i');
            return regex.test(text);
        });
    }

    function findSmallestMuteableElement(element) {
        if (element.nodeType === Node.TEXT_NODE) {
            return shouldMute(element.textContent) ? element.parentElement : null;
        }

        if (element.tagName === 'PRE' || element.tagName === 'CODE') {
            return shouldMute(element.textContent) ? element : null;
        }

        for (let child of element.childNodes) {
            const result = findSmallestMuteableElement(child);
            if (result) return result;
        }

        return shouldMute(element.textContent) ? element : null;
    }

    function processElement(element) {
        const muteableElement = findSmallestMuteableElement(element);
        if (muteableElement) {
            whiteoutElement(muteableElement);
        }
    }

    function processAllElements(root = document.body) {
        const walker = document.createTreeWalker(
            root,
            NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT,
            null,
            false
        );

        let node;
        while (node = walker.nextNode()) {
            if (node.nodeType === Node.ELEMENT_NODE) {
                processElement(node);
            } else if (node.nodeType === Node.TEXT_NODE && node.parentElement) {
                processElement(node.parentElement);
            }
        }
    }

    function handleClickEvent(event) {
        setTimeout(() => {
            processAllElements(event.target);
        }, 100);
    }

    // 初回実行
    processAllElements();

    // クリックイベント監視
    document.body.addEventListener('click', handleClickEvent);

    // DOM変更の監視
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            if (mutation.type === 'childList') {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        processAllElements(node);
                    }
                });
            } else if (mutation.type === 'characterData') {
                processElement(mutation.target.parentNode);
            }
        });
    });

    observer.observe(document.body, { childList: true, subtree: true, characterData: true });
})();

2024-05-13

???「どんな理由があろうが時間を守らない奴は悪い奴!いたずらでクレーム電話してやる!!」

水俣病団体側に抗議電話が数件 「時間守らない方が悪い」

https://news.yahoo.co.jp/articles/fb31df986a0f0cb5f46b968401424cfbb1cefcb4?source=sns&dv=sp&mid=other&date=20240510&ctg=dom&bt=tw_up

時間を守る事には異常に固執する癖にイチャモン電凸をしちゃいけないという常識は守れないのか・・・(呆れ)

ネットでたまに一行とか一つのコメントですら前半と後半で矛盾した事を言ってる奴がいるけど

そういう奴らの中身はこういう奴なんだろうなって

アホ「ジカンヲマモレー!!!!!!!」

不躾な対応された被害者に対してクレーム入れる

しか水俣病なんて一切関係ない東京都男性から

もうね、人として考えられんよ

マジでこういう権威に楯突く奴に対して異常な攻撃性発揮する奴って何なの

水俣病団体弁護士にでも相談してわけわからん嫌がらせ電話掛けてきたアホの名前出して良いレベル

水俣病団体側に抗議電話が数件 「時間守らない方が悪い」

https://news.yahoo.co.jp/articles/fb31df986a0f0cb5f46b968401424cfbb1cefcb4?source=sns&dv=sp&mid=other&date=20240510&ctg=dom&bt=tw_up

水俣病被害者発言遮断問題に関し、伊藤信太郎環境相との懇談に出席した被害者団体などに「(あらかじめ設定された)3分の持ち時間を守らない方が悪い」などと抗議する電話が数件寄せられたことが10日、各団体への取材で分かった。

熊本県水俣市で1日に行われた懇談に参加した団体によると、伊藤氏が再び同市を訪れ謝罪した8日夜、東京都男性を名乗る人物から3分を守らないあなたたちが悪いのに被害者ぶって抗議するのはおかしい」と非難する電話があった。

2024-04-24

スパム対策か何か知らんが、天◯門とか中国人に対する差別的発言プロフに書き込んでいるやつ

doM @doM_MGE

スパム対策か何か知らんが、天◯門とか中国人に対する差別的発言プロフに書き込んでおきながら、中国人絵描きフォローしてる人、如何にもSNS中毒って感じで胸糞。

恥を知ってくれ。

2024-01-03 21:35:04

doM @doM_MGE

実際に起こって多くの死傷者を出したであろう悲劇的な事件をさ、スパム避けの魔除けとか言って揶揄する目的アカウント名やプロフに書く人、色んなモノを失ってる事に気づいた方が良いと思う。

たかスパム」に強い不快感を示して、モラルと知性に欠けた言動する人、多すぎませんか?

2024-01-06 23:55:12

doM @doM_MGE

そのワード効果についてもさ、眉唾モノだよ。

はっきり言って迷信とか都市伝説に近いレベル

普段知識人気取ったり、正論めいた発言したりしてる人がこういう「遊び」にキャッキャしてるの見ると、乾いた笑いが出ると同時に心が冷える。

何て幼稚なんだろう、この人達は。

2024-01-06 23:55:12

doM @doM_MGE

しかもそういう人に限って、平気でダブスタしてたりする。

そこまでその国が嫌いなのに、その国の人が描いたイラストいいねしてたり、その国の人達が作ったゲームに夢中で金と時間を溶かしてたりする。

恥ずかしくないんかな、色々と。

俺は、こういう人間の発する言葉を決して信用しない。

2024-01-06 23:55:13

doM @doM_MGE

ダブスタについては本人の中で何らかの言い訳屁理屈を用意して正当化してるのかもしれないけどさ、実際その人達がやってる事って「ヘイトクライム特定の国・人種攻撃しておきながら、自分はその国の人達が用意した娯楽で楽しんでる」でしかない。

信念のカケラもない、薄っぺら人達

2024-01-06 23:55:13

doM @doM_MGE

まぁ、日本に住んでる以上、食文化日常生活を送る上でその国の恩恵に全く触れない事なんて限りなく不可能に近いだろうし、そこまで徹底しろなんて言わないけどさ。

その国を殴るなら「嫌いな国の世話になんてなるか!」くらいは言って欲しいし実行して欲しいよ、俺としては。

でないと、ダサすぎる。

2024-01-06 23:55:14

doM @doM_MGE

ゲームや絵なんて人間生命活動に大きな影響も与えないんだからさぁ、我慢する事くらい造作もないだろ?

最悪裏でやっててもその“好き”をネットに出力しなければバレる事もないし、何なら別垢でやれば良いだけだというのに何で同じ垢で出力しちゃうかなぁ。

SNSのやり過ぎで冷静な判断力を失ってない?

2024-01-06 23:55:14

doM @doM_MGE

色々言ったけど俺が何でこんなに愚痴ってるかと言うとこういう人間自分の愛好してるコンテンツファンに居たからなんですよね。

俺の愛好してるコンテンツヘイトクライムは最も似合わない。

なのにプロフにそのワードコンテンツ名を並べたり固定ツイでそのコンテンツ二次創作を貼る。

アホか?

2024-01-06 23:55:15

doM @doM_MGE

何が竜娘が好きだ。

何が🦉の雛だ。

恥を知れ。

コンテンツに対して、原作者様に対してリスペクトを持て。

オマエラのくだらない遊びにコンテンツを巻き込むな。

原作者様の顔に泥塗るな。

そういう遊びは、別垢作って他所でやれ。

スパムとき前後不覚になってる自分を顧みてくれ、頼むから

2024-02-09

anond:20240208194947

こうしてみると仮想DOM以降、webフォーム弄る以上の成果物冷静に考えると薄い気もしてきた

2023-12-18

anond:20231218170959

いうてブラウザ自作するにはCSS仕様完璧に把握してこそdomとか解釈して表示する機能を実現できるわけで、それはプログラミング言語によるものなのだから、やっぱプログラミング言語マークアップ言語以上の難しさだろ

2023-11-14

司法試験1位合格でも年齢差別される恐怖

いやこれ凄いな

未履修からロースクール入学司法試験1位合格って相当優秀だろうに(しか社会人経験もばっちり有りなので勉強しか出来ないガリ勉って訳でもない)

それでも裁判官検察大手どころか中堅の法律事務所も全部落とされるのか…

最近社会人からの予備試験ルート司法試験合格も盛んに宣伝されているけれど

実際に受かったとしても年齢が高ければ門前払いだって事がよーーく分かった。

どんだけ過酷なんだよこの国の年齢差別

そりゃあ戸籍を偽造してでも若く偽りたいと思う人が出てくるのも無理もない。

だってどれだけ苦労して実績を上げるよりも、戸籍の生年月日を若返らせる方が有効なんだから

ITコンサルから転身、32歳入学司法試験1位合格 ロースクール1期生伊藤弁護士が語る「キャリア多様性」』

https://news.yahoo.co.jp/articles/39a6611e17f307644c90dfa755fba1a1a121becf?source=sns&dv=sp&mid=other&date=20231111&ctg=dom&bt=tw_up

裁判所検察庁、大手法律事務所は、若い合格者を優遇して採用しようとします。自分司法試験後に大手・中堅法律事務所に応募しましたが、ことごとく落とされましたか(笑)学生がそこで活躍したいと思ったら『若いうちに合格するしかない』となってしまうのも無理ありません」

2023-07-21

「今回の問題職場トイレ問題であって」ってさあ

職場って1日の、それどころか人生の長い時間を過ごす場所なのに

まりにも軽視され過ぎていやしないか

労働時間が3時間もかならともかく、実際は「最低で」8時間という、長い時間拘束されるのに。

https://news.yahoo.co.jp/articles/53b79e8c47fd13354352db74d57e8f5359cf87de?source=sns&dv=pc&mid=art11t3&date=20230721112126&ctg=dom&bt=tw_up

長官候補ともされる今崎幸彦裁判長は、今回の問題職場トイレ問題であって、トイレを含む不特定多数が使う公共施設使用のあり方とは別とも言及。こうした問題は『一律の解決策になじむものではない』と断言していた。判決文だけでは誤解を生むという判断だろう」(司法関係者

2023-06-29

閣僚が答弁できないの当たり前じゃないの?

ブラック霞が関」で官僚離れ深刻、国会答弁打ち合わせ「朝4時」開始も背景(読売新聞オンライン)

#Yahooニュース

https://news.yahoo.co.jp/articles/ab92fb0543ba4298423f9dcce607678bf56a889c?source=sns&dv=sp&mid=other&date=20230629&ctg=dom&bt=tw_up

これに対して閣僚官僚に答弁を作ってもらってることを批判してるやついるけど、1つの省の全ての業務を1人の人間が把握するのって現実的可能なの?

何十年と働けば可能かもしれないけど、大臣職なんて数年ごとに変わるしその度に各省庁の仕事を全て把握するのはいくらなんでも無理ゲーすぎない?

例えば、お前らは自分の働いてる会社業務全て説明できるか?俺はできない関係ない部署ことなんか説明できないよ

2023-06-17

anond:20230617130556

ワシが携わってるtoBアプリケーションは読み込みに15秒くらいかかるで。

大体のプロジェクトではパフォーマンス改善にまで手が回ってないか仮想DOM人類生産性を下げてそうだなあとか思ってる。

仮想DOMかいらないんだけど

コンポーネント単位で書き分けができるなら、ユーザー側でどうやって表示されようがどうでもいいんだけど。

あのクソ重たくて無闇に複雑な仮想DOMかい技術は本当に必要なの?

2023-06-08

増田記事詳細ページのパンくずリスト末尾にある記事IDDOMがtype=textのinputタグなのが気になる

onfocus="this.select()" という属性があるのでコピペ用のタグ指定だとは思うんだけど普通入力領域なので無意味に上書きできるのがずっと気になってる

2023-05-12

anond:20230512120133

単にDom/Subだけなら日本で言うSM意味は変わらない。

オメガバースあたりから現実とは性別概念が違う」物語流行りはじめたけど

そういう特殊性別設定にSM概念を導入してDom/Sub性別にしてしまった、という話。

昨年流行若者言葉 Dom Subちんぷんかんぷん

検索率上位に入ってたらしいけど

まっっっっっっっったく聞いたことがないのは

オタク方面若者言葉からだろうし

それはい

でも

解説読んでも全然からあああああああん

Dom 庇護する性別

Sub 庇護される性別

???

要するに架空性別ってことなんだろうか

性を作っちゃうのは面白いけど、でも、支配して庇護して守ってあげたいお仕置きしたいって

それ旧弊な家父長的男性像と何が違うん?

っていうか男性女性と並列に着く属性なんだろうか

DomSubコマンド言葉を使って命令して従わせるプレイ、なる儀式をして信頼関係を築くらしい。行き過ぎると セーフワード を行って止める事ができる

へえ

セーフワード普通に現実にもあるけど?

プレイSMみたいだけど単なる性的嗜好ではないのか、どうやって違いを証明して性的指向に入れたのか

よく分からん

世代が、若者についてけないわとかいうの鬱陶しかったけど

いざその立場になると、若者にはついてけないわ感がやばい

これが老化です、か

2023-01-26

VPS自宅サーバーにインストールしたいSaaS代替Webアプリ38選

シェアウェア(という表現はおいておいてのやつ。https://anond.hatelabo.jp/20230124045812)の記事面白かったので、自分の得意分野の領域でいろいろ紹介します。

基本的に、SaaSサービスは便利だけど、あれもこれもと契約していったらサブスク破産するので、

ものによってはセルフホストした方がいいと思ってる派。

Dropbox/GoogleDrive/box代替

NextCloud

もともとownCloudっていうDropbox代替があったんだけど、そこから分派して今も機能開発が続いている。

興味深いのはLAMP構成なので、VPS自宅サーバーじゃなくても、レンサバで動くのがいいよね。

データ保存領域オブジェクトストレージ(S3互換)も利用できるので、例えばWasabiなんかと契約してお安く済ませてしまうのも全然アリかと。

Trello代替

Wekan

最近カンバンシステムって、単体で使うんじゃなくていろんなアプリの中で使われる印象なので、今更Trelloだけ使いたい、なんてニーズはないかもだけど、

そこまで複雑でなく小規模なプロジェクトとかだと、意外とTrelloだけでいいよね、みたいなこともあるかな

そういう時は、これを使うといいかも。

Slack代替

Mattermost

ちょっとUI雰囲気が違うだけで、まんまSlackです。絵文字の追加もできるし、APIもあるし。人によって好き嫌い分かれるスレッド機能も、まあ、あのスレッド機能のまま。

その他のSlack代替選択肢
  • Rocket.chat
  • Zulip

この2つは使ったことないので、名前だけ挙げておきます

Zapier/IFTTT/Make代替

n8n

n8nと書いてnodemationと読ませるらしい。初見殺しすぎんだろ。

Zapier使ったことある人はすぐわかると思います

ZapierやIFTTT無料枠あるけど、あれもこれもやり出すとすぐ無料枠埋まっちゃうので、これ結構いいと思うんだけどな。

その他のZapier/IFTTT/Make代替
  • Huggin
  • Windmill

kintone代替

Exment

kintone使ってる会社増えてると思うんだけど、まだまだ1ユーザー1500円ってのは高いので、零細企業は導入し辛いと思う。

で、それの代替になるのがExment。UIがkintoneとは少し違うので代替と言い切れないかもしれないが、

やれることはkintoneのソレと全く同じなので、用途代替はできる。

開発も日本企業なので、UI日本語化されている。LAMP構成なので、レンサバでも動くよ!

Airtable代替

NocoDB

そもそもAirtableって何やねんって人もいるかもしれないけど、kintoneとGoogleスプレッドシートをいいとこ取りして、Trelloとガントチャートを足した感じ。

これのOSS版です。結構再現度高いので良い感じ。

ZoomGoogleMeet・Microsoft Teams代替

Jitsi

これもまあまあいい感じでZoom再現してますZoomの方が新機能の追加早いけど、Jitsiも頑張って追いついている感じです。

ただ、やる内容が複数人でのリアルタイム動画配信なので、サーバースペック回線スペックはまあまあ必要なので要注意。

BigBlueButton

こちらは使ったことないんだけど、よりオンライン授業向けらしい。

Calendly代替

Cal.com

最近よく見かけるようになった、オンラインミーティングとかの予定をブッキングさせるSaaS

あれのはしりがCalendlyで、日本でもいくつかそれのSaaSができてますね。

あれらも無料枠だと1カレンダーだけしかできなかったりするんだけど、これなら好きなだけブッキングさせられます

Intercom、Zendesk代替

Chatwoot
Papercups

ECサイトとか、Webマーケティングを重視してるサイトによくある、画面右下に吹き出しアイコンがあって、チャットウインドウがぴょこっと出てくるやつ。

日本ではWeb接客とか言われてるけど、あれの代表的SaaSがIntercom。Zendeskは、どちらかというと内部ツール向きかな。

これのOSS版がChatwootとPapercups。自社サイトWeb接客入れたいけど、費用抑えたい、って時にどうぞ。

Backlog/Asana代替

OpenProject

この手のツールがないと仕事にならないという人も多いと思います

これまでだとRedmineがそれのOSS版的立ち位置でしたが、さすがにイマドキあのUIはないなぁ、と。

OpenProjectは、Microsoft Projectの代替イメージしてるみたいですが、

ガントチャートカンバンデフォルトで使えるので、BacklogやAsanaの代替にはちょうど良いでしょう。

ただ、そんな高度なことしてるわけではないのに、サーバー要求スペックちょっと高めなのでご注意を。

Google Analytics代替

Matomo

UA廃止GA離れが始まってるとも聞きますが、疎開先として有名。

PHPで動くので、PHPWordPressでできたサイトに一緒に入れちゃってもいいと思う。

HeadlessCMS関連

HeadlessCMSは、データ表示を持たず、フロントエンドAPIを通じてデータを渡すタイプCMSのこと。

このジャンルでは、SaaSだとContentfulが有名だけど、OSSでもいろいろある。

Strapi

Node.js製。歴史があるので、結構いろんなことができる。

WordPressのGutenbergエディターを取り込んだプラグインなんかもある。

User認証も持ってるので、CGM的なサイトを作ろうと思ったらできなくもない。

Directus

これもNode.js製。利用できるDBが幅広く、既存データベース活用できる。

なので、既にPostgresSQLとかでデータを持ってるんだけど、

非エンジニアにもデータを触らせるためのフロントエンドが欲しい、ってニーズに良いかも。

こちらもUser認証デフォルトで持ってる。

Cockpit CMS

PHP製。SQLiteMongoDBで利用可能MySQL/PostgreSQL使えないのがちょっと残念。

Shopify代替

Medusa.js

近年、本腰入れて自社ECサイトをやろうと思うと必ず選択肢に上がるShopify。

インテグレートパートナー向けのエコシステムも充実してるので、取り組み始めるエンジニアシステム会社も多い。

ヘッドレスコマースや越境ECには向いているものの、これをセルフホストしたい、というニーズに応えたのがmedusa.js

ざっと見てみただけだけど、モダン構成で、今時のフロントバックエンドを分けた構成でやりたい、というのには向いている。

プラグインmedusa-marketplace.jsというのもあり、Amazon的なマーケットプレイスも実現可能

Figma代替

Penpot

昨年、Adobeに買収され、デザイナーたちを驚愕させたFigma

先日はAdobe XD終了のお知らせとなり、UIデザイナーたちの不安は募るばかり。

そんな提供企業に振り回されたくないなら、このPenpotでUIデザインしよう。

Figmaほど機能実装はされていないが、まあまあ一通りのことはできる。

Figma代が嵩むとお嘆きの制作会社なんかは、一考の余地あるんじゃなかろうか。

Google Form代替

Oh My Form

企業によっては、コンタクトフォームをたくさん作りたいという会社もある。

例えばセミナーを頻繁に開く企業だったりとか、

人材採用フォーム職種別に細かく分けたい(しかも頻繁に募集職種が変わるとか)

などの要望によって、GUIフォームを作りたい局面がある。

Google Formで大体解決しそうだけど、それをGoogleに頼りたくないならこちら。

まあまあ機能豊富なので、人によってはGoogleFormよりもこちらを好むかも。

Gmail代替

Mailu

DockerベースWebメールUI。送受信に必要ものを、丸っとDockerで用意してくれているので便利。

SalesForce/HubSpot代替

SuiteCRM
Mautic
Erxes

HubSpotは、いわゆるMarketing AutomationCRMを一体にしたツール無料枠もあるが、かなり限定されている。

上記でいうと、Erxesが単体で一番近い機能を持っている。

MauticはMarketing Automationよりの機能が多く、ユーザーサイト上での回遊をビジュアル化してくれたりする。

SuiteCRMはザ・CRMという感じ。SalesForceデフォルトで使う感じに近い。

ツールが分かれてしまうのは辛いところだけど、それぞれにAPIがあるので、うまく繋げられると強力なツールになってくれるはず。

Sendgrid/Mailgun代替

Postal

Webサービス作ってると、メールの通知や一斉配信などがあると思う。

通常これらはSendGridや、AWS SESなどで処理すると思うが、これらにもOSS代替がある。

PostalDockerメール周りのもの全部用意してくれているので、かなり楽。

Jimdo/Wix代替

Microweber

WordPressモダンにしたような感じで、EC機能デフォルトでついてる。マルチサイトも標準。

Jimdo/Wix代替と書いたが、もちろん自分サイトをMicroweberで作ってもいいが、

自前ホスティングして、JimdoWixのようなサービスを始めることもできる。

テンプレートをいくつか作っておいて、Stripeを仕込んでおけば、今日からあなたJimdo/Wixのような事業を始められるわけだ。

STUDIO/Webflow代替

Webstudio

JImdo/WixSTUDIO/Webflowは一緒くたに語られがちだが、明確な違いがある。

前者はプリディファインドなブロックGUI構成するのに対し、後者DOM要素ベースで構築していく。

まりよりHTML/CSSによる細かなデザインコントロールがしやすく、Webデザイナーが親しみやすい。

それのOSS版がWebstudio。まだアルファ版だが、フロントエンドはそれなりによくできているので、

バックエンドを自前で用意してStripeを仕込んでおけば、今日からあなたも(以下略

Facebook代替

friendica

Facebookなんか使わねーよ、っていう人も多いかもしれないが、

特定コミュニティの中でコミュニケーション取るには、FacebookUI機能は優れていると思う。

なので、サークルとか同窓会、あと自治会とかPTAなんかにいいんじゃないだろうか。

LAMPなので、レンサバでもいけると思う。

Netflix代替

Jellyfin

Netflix代替って、Amazon Primeとかじゃねーの、と思われるのかもしれないが、そうではなくて、

あなたNetflixみたいな商売したいならこれを使うといいよ、というのがJellyfin。

いや、そんな商売しないよ、と思うかもしれないが、

使いようによっては、おじいちゃんおばあちゃん向けの子動画配信サービスとして構築するとか、

Stripeと連携して、劇団バンドオリジナル配信サイトを構築するなんかも面白いと思う。

YouTube/Vimeo代替

PeerTube

今更誰もYouTubeVimeoの後追いをしようとはしないでしょうが

複数ユーザーから動画のアップを受け付けて、それを閲覧したい用途もあると思う。

例えば、軽音部で複数バンド練習風景を録画したのを定期的にアップしたりとか。

学習塾で、授業の録画を授業ごとにアップしていったりとか。

YouTube Live/Facebook Live/ニコ生/Twitch代替

Owncast

ZoomGoogle Meetのような双方向ではなく、一対多の一方通行配信

個人的には、企業のウェビナーツールとしての可能性を感じる。(Zoomのウェビナープランとか高いもん)

メールワイズ/Re:lation代替

FreeScout

つのメールドレス複数人運用したい時のツールメールワイズとRe:lationどちらも日本SaaS

FreeScoutはOSSだけど、海外製。一応日本語化もされてるっぽい。

ECサイト顧客問い合わせや、営業チームのプライマリ対応なんかに良いと思う。

Bubble代替

Budibase
AppSmith
ToolJet

Bubbleってなんぞ? という人のためにお伝えしておくと、ノーコードベースWebアプリ開発ツール

データエンティティ設計したら、自動的CRUDを作ってくれて、フォームを配置するというような感じ。

Bubbleはそれ系の老舗で、歴史が長い分ノウハウも溜まっており、連携できるサービスも多い。

ただ、ベンダーロックインされるし、季節的なキャンペーンとかでは、アプリ使用しない期間もサブスク費用がかかる。

Budibaseは、Bubbleの思想に一番近い感じ。凝ったUI必要なければ、ざっくりコレでなんでも作れちゃう

AppSmithも同じような感じだが、これはDBをあらかじめスキーマ定義しておかないといけないところが若干不便かな。

ToolJetはルーティングURL概念がなく、本格使用を諦めたんだけど、最近アップデートしたらしいので、そこのところどうなってるかまた確認ときたい。

他にもこの手のやつあったら、いろいろ教えて欲しい。単純に好きなので。

「こういう用途のやつ、ある?」みたいな質問も歓迎。

見つかったら追記します。

2022-11-26

anond:20221125160015

トレンドってか、キーワード検索して眺める分にはずっとログイン不要だったべな?

個別アカウントツイートを見てると、ちょっと経ったら「ログインしろ」が出て来てたんだけど

自分拡張機能のTamperMonkey使って自分スクリプトを書いて、ダイアログを消したった。

でも確かに、今見てる限りだと、このスクリプト無くてもダイアログ出なくなってる。。。

Quoraも同じく、DOMスタイルを調整してやれば普通に全部見える。

まあQuoraはほとんど見ないけど。

PinterestTumblrもいつか攻略しようかなと思ってるけど、思ってるだけ。

2022-08-15

Webはてブミュー機能作った

勝手に tampermonkey とかに突っ込んで使ってヨロ

スクリプト保守とかするつもりないから、保守とかするつもりのあるパワーの溢れた人が

これ参考とかにしてもっとかっちょよくしたのを greasy fork あたりに公開してくれ

そしたら俺もそれ使う

使い方:

ブラウザの開発環境を開いて、開発コンソールを開く

localStorage.hatebu_ng_word_list に非表示トリガーになる文字列を|区切り登録する。

localStorage.hatebu_ng_word_list = "池田信夫|フェミ|弱者男性|やまもといちろう"

実際のコード

大なり小なり(>)が実体参照で表示されるのはよくわからん。使う人で適宜コードを直してくれ。

// ==UserScript==
// @name         はてブの一覧NG記事非表示
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       masuda
// @match        https://b.hatena.ne.jp/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hatena.ne.jp
// @grant        none
// ==/UserScript==

(function() {
	'use strict';

	if (!localStorage.hatebu_ng_word_list) {
		return;
	}
	console.log("はてブの一覧NG記事非表示", localStorage.hatebu_ng_word_list);

	/*
	 * 例:
	 * localStorage.hatebu_ng_word_list =
	 * "池田信夫|フェミ|弱者男性|やまもといちろう|togetter.com";
	*/
	let words = localStorage.hatebu_ng_word_list.split('|').map(w => new RegExp(w));

	function entryDelete(els) {
		els.forEach(el => {
			let hit = false;
			words.forEach(w => {
				hit = hit|| w.test(el.textContent);
			});
			if (hit) {
				el.remove();
			}
		});
	}

	// entrylist-header-main li 1つ目のアイテム
	entryDelete(document.querySelectorAll('.entrylist-header-main > li'));
	// 2つ目以降の li アイテム
	entryDelete(document.querySelectorAll('.entrylist-item > li'));
})();

文字正規表現として評価されて、ヒットした記事項目をページから削除する(DOMから要素を削除する)。

際限なくNG登録できるけど、沢山非表示するとつまらない一覧になる

2022-08-01

anond:20220731183342

自動安価をつけて返信するプログラムでもこんなに長く複雑になる(一部抜粋) 

/**************************************

以下のCSV_DIR, FILE_PATHS, SETTINGSを書き換えてね。 <h3>o- *************************************/</h3>

//CSVファイルが置かれてるディレクトリパス投稿前にエラー出たら大体ここの設定ミス。 例:"C:\\Users\\sakuraimasahiro\\Documents\\iMacros\\Macros\\rentou\\";

const CSV_DIR =

'C:\\Users\\USER\\Desktop\\iMacros\\Macros\\rentou\\';

//ファイルパスCSV絶対パスで、拡張子必要。iimは相対パスでよく、拡張子不要

const FILE_PATHS = {

//投稿文が書かれたCSVファイル

textCsv: CSV_DIR + 'textNoAnker.csv',

//レス投稿文が書かれたCSV。通常とレス用で分けないなら同じファイルを使えばいい。

replyTextCsv: CSV_DIR + 'textReply.csv',

};

const SETTINGS = {

//投稿後の基本待ち時間

baseWaitTime: 5,

//baseWaitTime+0~waitTimeRange(ランダム)だけ待つ

waitTimeRange: 5,

//連投しすぎだと忠告された場合に処理を一時停止させる時間(秒)

waitTimeForAvoidingPunishment: 60 * 30,

//メール

mail: 'sage',

//名前設定

nameSettings: {

//名前名無しなら''。

name: '',

//以下、偽装ワッチョイ設定。浪人ワッチョイを非表示にしてるときだけtrueにしてね。

//妙なニックネーム(ワッチョイ、アウアウウーなど)をランダムで決めて付加するかどうか。true=付加する。false=付加しない。

nickname: false,

//妙なニックネームの後に付く8桁の文字列ランダムで決めて付加するかどうか。

korokoro: false,

//IPランダムで決めて付加するかどうか。

ip: false,

//地域ランダムで決めて付加するかどうか。

area: false,

},

postSettings: {

//アンカー無し投稿をするならtrue。しないならfalse。noAnkerPostかreplyPostのどちらかはtrueにすること(両方trueでもOK)。

noAnkerPost: false,

//アンカー付き投稿(返信)をするならtrue。しないならfalse。もしnoAnkerPostとreplyPostの両方がtrue場合投稿は返信が優先され、返信対象が見つからなくなったらアンカー無し投稿をする。

replyPost: true,

//最初に取得するアンカー無し投稿CSVファイルの行番号。もし返信用と同じCSVファイルを使うなら-1と入力

noAnkerPostTextCsvStartRow: 1,

//最初に取得する返信用投稿CSVファイルの行番号。もしアンカー無しと同じCSVファイルを使うなら-1と入力

replyPostTextCsvStartRow: 1,

//テキストCSV/返信用テキストCSVの取得行が最終行に達したら最初の行まで戻るかどうか。true=戻る。false=マクロ終了。

textCsvLoop: true,

//返信する場合、これより小さなレス番には返信しない。返信を投稿すると、この数値は前回の返信先のレス番に更新される。

minAnker: 895,

//返信する場合名前に以下の文字列を含む投稿アンカーをつけて返信する(ワッチョイやIPなど名前フィールドにあるものならなんでも可)。配列複数指定可能指定無しなら空配列([])。filterNamesとfilterNamesNotIncluded共に無指定ならレス番1から順に返信していく(minAnkerが設定されてればそこから順に)。以下のfilter系は全て併用可能

filterNames: [],

//↑とは逆に、名前に以下の文字列を含まない投稿アンカーをつけて返信する。↑と併用も可能

filterNamesNotIncluded: [],

//返信する場合、本文に以下の文字列を含む投稿アンカーをつけて返信する。

filterText: ['自演かな', '自演わらわら', 'スクリプト使うの', '安価ガバ', '>>660', '自演擁護', '最後' ,'あいうえお', 'かきくけこ', 'さしすせそ', 'なにぬねの', 'はひふへほ', 'まみむめも', 'やいゆえよ', 'やゆよ', 'らりるれろ', 'わいうえを', 'わをん', 'わいうえをん'],

},

//自分IPアドレス確認VPNとかでIPを変更してマクロを動かしてるとき、突然VPN作動しなくなってIPが元に戻ったときマクロを止めるためのもの

ipSettings: {

//自分現在IPアドレス確認をする。

checkIp: true,

//以下の文字列自分現在IPアドレスに含まれている場合マクロを一時停止する。基本的自分の本当のIPアドレス入力

avoidTheIp: '133.206.99.224',

},

//浪人設定。最後動作確認したのは5年くらい前で、今も同じように動作するかは、浪人を持ってないか確認できずわからない。

roninSettings: {

//浪人ログインしてるかどうかをチェックするかどうか。trueらするfalseならしない。trueにしていてもし浪人ログインしていないことを確認したらログインしにいく。

checkLogin: false,

//浪人ログインメールアドレス

mailAdress: 'abc@def.com',

//浪人ログインパスワード

password: '1234',

},

//false: run()実行させず(デバッグ用)

run: true,

//true: 投稿処理だけしない デバッグ

skipPost: false,

};

/**************************************

設定箇所終わり。

書き込めない時の早見表 - 5ちゃんねるwiki

https://info.5ch.net/index.php/%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%82%81%E3%81%AA%E3%81%84%E6%99%82%E3%81%AE%E6%97%A9%E8%A6%8B%E8%A1%A8 <h3>o- *************************************/</h3>

/**************************************

メモ

クラスフィールド宣言できない。

・NULL演算子(??)は使えない。論理積(&&)は使える。

オブジェクトの分割代入はできない。

・importはできない。 <h3>o- *************************************/</h3>

/**************************************

関数 <h3>o- *************************************/</h3>

/**

* ここから始まる。

*/

function run() {

//設定ミスがないか調べる。

checkSettings();

var _TextCsvCursors = new TextCsvCursors(

new TextCsvCursor(

SETTINGS.postSettings.noAnkerPostTextCsvStartRow > 0

? SETTINGS.postSettings.noAnkerPostTextCsvStartRow - 1

: SETTINGS.postSettings.noAnkerPostTextCsvStartRow,

FILE_PATHS.textCsv,

SETTINGS.postSettings.textCsvLoop,

),

new TextCsvCursor(

SETTINGS.postSettings.replyPostTextCsvStartRow > 0

? SETTINGS.postSettings.replyPostTextCsvStartRow - 1

: SETTINGS.postSettings.replyPostTextCsvStartRow,

FILE_PATHS.replyTextCsv,

SETTINGS.postSettings.textCsvLoop,

),

);

var _LoopStatuses = new LoopStatuses(0, SETTINGS.postSettings.minAnker);

const _MyPosterName = new MyPosterName({

name: SETTINGS.nameSettings.name,

});

//スレURL指定

const _ThreadUrl = openPromptThreadUrl();

//ループ

while (true) {

//IP確認する設定なら、それをする。

SETTINGS.ipSettings.checkIp && checkCurrentIpNotTheIp();

//スレを開く

openUrl(_ThreadUrl.fullUrlHttps());

//浪人ログインする設定なら、浪人ログインしているかどうかを確認し、していなければログインしにいく。

if (SETTINGS.roninSettings.checkLogin) {

if (!checkRoninLogin()) {

loginRonin();

continue;

}

}

//投稿に使うテキスト取得。

const p = (function () {

if (SETTINGS.postSettings.replyPost) {

//返信あり設定の場合。返信対象が無いか調べる。

const targetAnkerNumber = createPostDOMList()

.filterPostnumberHigher(_LoopStatuses.currentMinAnker())

.filterByPostername(SETTINGS.postSettings.filterNames)

.filterByPosternameNotIncluded(

SETTINGS.postSettings.filterNamesNotIncluded,

)

.filterByText(SETTINGS.postSettings.filterText)

.lowestPostNumber();

if (targetAnkerNumber !== null) {

//返信対象があったのでアンカー付き投稿文を作る。

const r = _TextCsvCursors.takeNextRowTextAsReply(targetAnkerNumber);

messageDisplay(`返信対象有り。アンカー先: ${targetAnkerNumber}`);

return {

...r,

updatedLoopStatuses:

_LoopStatuses.updateMinAnker(targetAnkerNumber),

};

}

}

if (SETTINGS.postSettings.noAnkerPost) {

//返信対象無し、或いは返信しない設定の場合アンカー無し投稿文を作る。

const r = _TextCsvCursors.takeNextRowTextAsNoAnker();

messageDisplay('返信対象無し。アンカー無し投稿。');

return {

...r,

updatedLoopStatuses: _LoopStatuses,

};

}

return null;

})();

if (p) {

//投稿

postThenCheckError(

_ThreadUrl.serverName(),

_MyPosterName.randomize({

nickname: SETTINGS.nameSettings.nickname,

korokoro: SETTINGS.nameSettings.korokoro,

ip: SETTINGS.nameSettings.ip,

area: SETTINGS.nameSettings.area,

}),

SETTINGS.mail,

p.text,

);

//_TextCsvCursorsと_LoopStatusesを更新

_TextCsvCursors = p.updatedTextCsvCursors;

_LoopStatuses = p.updatedLoopStatuses.incrementPostCount();

messageDisplay([

`投稿回数: ${_LoopStatuses.currentPostCount()}`,

`minAnker: ${_LoopStatuses.currentMinAnker()}`,

`今回アンカー無し投稿取得行: ${_TextCsvCursors.currentRows().noAnker}`,

`今回アンカー有り投稿取得行: ${_TextCsvCursors.currentRows().reply}`,

]);

} else {

messageDisplay([

`返信対象が現われるのを待機中...。`,

`投稿回数: ${_LoopStatuses.currentPostCount()}`,

`minAnker: ${_LoopStatuses.currentMinAnker()}`,

`今回アンカー無し投稿取得行: ${_TextCsvCursors.currentRows().noAnker}`,

`今回アンカー有り投稿取得行: ${_TextCsvCursors.currentRows().reply}`,

]);

}

//短時間で連投しまくると規制されるので一定時間待機。

wait(SETTINGS.baseWaitTime + randomRange(0, SETTINGS.waitTimeRange));

}

}

/**

* 投稿処理と投稿結果を見てリトライしたりマクロ終了したり。

* @param {string} serverName サーバー

* @param {MyPosterName} _MyPosterName

* @param {string} postMail メール

* @param {MyText} _MyText

* @param {number} retryTimes

* @returns {void}}

*/

function postThenCheckError(

serverName,

_MyPosterName,

postMail,

_MyText,

retryTimes = 0,

) {

const r =

retryTimes === 0

? new ValuesOfPost(serverName, _MyPosterName, postMail, _MyText).post(

postTo5chTread,

postConfirm,

)

: new ValuesOfPost(

serverName,

_MyPosterName,

postMail,

_MyText,

).postSubstring(retryTimes, postTo5chTread, postConfirm);

if (r) {

back();

return;

}

//エラーページに飛ばされた。エラー情報取得。

wait(7);

const error = createPostErrorMessage().analyze();

messageDisplay(error.message);

if (error.order === 'KILL') {

kill();

} else if (error.order === 'SKIP') {

return;

} else if (error.order === 'TRUNCATE') {

back();

return postThenCheckError(

serverName,

_MyPosterName,

postMail,

_MyText,

retryTimes + 1,

);

} else if (error.order === 'WAIT') {

wait(SETTINGS.waitTimeForAvoidingPunishment);

return postThenCheckError(

serverName,

_MyPosterName,

postMail,

_MyText,

retryTimes,

);

} else if (error.order === 'LOGIN') {

//動作未確認

return postThenCheckError(

serverName,

_MyPosterName,

postMail,

_MyText,

retryTimes,

);

}

return;

}

/**

* 現在IPアドレスに、SETTINGS.ipSettings.avoidTheIpの値が含まれていないことを確認する。含まれていたらマクロを一時停止。

* @returns

*/

function checkCurrentIpNotTheIp() {

//IP確認ページへ飛ぶ

openUrl('https://www.cman.jp/network/support/go_access.cgi');

const _IpAdress = createIpAdressFromCMan();

if (_IpAdress.includes(SETTINGS.ipSettings.avoidTheIp)) {

pause('現在IP指定した値が含まれていることを確認。');

//ポーズ解除したならもう一度確認しに。

checkCurrentIpNotTheIp();

}

return;

}

/**

* 設定に致命的な問題が無いか検査

* @returns

*/

function checkSettings() {

if (

SETTINGS.postSettings.noAnkerPost === false &&

SETTINGS.postSettings.replyPost === false

) {

return kill('設定エラー。noAnkerPostとreplyPost両方ともfalseになってる。');

}

if (

SETTINGS.postSettings.noAnkerPostTextCsvStartRow < 0 &&

SETTINGS.postSettings.replyPostTextCsvStartRow < 0

) {

return kill(

'設定エラー。noAnkerPostTextCsvStartRowとreplyPostTextCsvStartRow両方とも-1になってる。',

);

}

if (

SETTINGS.postSettings.noAnkerPostTextCsvStartRow === 0 ||

SETTINGS.postSettings.replyPostTextCsvStartRow === 0

) {

return kill(

'設定エラー。noAnkerPostTextCsvStartRow/replyPostTextCsvStartRowの初期値は-1或いは1以上で。',

);

}

}

/**

* 入力フォームを表示して入力されたスレURLを受け取る。

* @returns {ThreadUrl}

*/

function openPromptThreadUrl() {

const url = prompt('スレURL入力');

return new ThreadUrl(url);

}

/**

* 開いてるスレレス全て読み取ってPostListインスタンスを作って返す。

* 重すぎるので使うのやめ。どうやらインスタンスの大量生成が原因な模様。

* createPostDOMListを使う。

* @returns {PostList}

*/

function createPostList() {

const posts = window.document.getElementsByClassName('post');

return new PostList(Array.from(posts).map((e) => new Post(e)));

}

/**

* 開いてるスレレス全て取得してPostDOMListに格納して返す。

* @returns

*/

function createPostDOMList() {

const posts = window.document.getElementsByClassName('post');

var arrPostDOMList = [];

for (let index = 0; index < posts.length; index++) {

//HTMLCollectionからElementを1つずつ抽出して配列に。

arrPostDOMList.push(posts.item(index));

}

return new PostDOMList(arrPostDOMList);

}

/**

* 開いてる投稿結果画面に表示されてるエラーを読み取ってPostErrorMessageインスタンスを作って返す。

* @returns {PostErrorMessage}

*/

function createPostErrorMessage() {

return new PostErrorMessage(

window.document

.g Permalink | 記事への反応(0) | 15:40

2022-07-09

anond:20220708095558

2022-06-30

Firefoxアドオン見積もりお願いしま

例えば堀江さんのような常にイライラしていて人生楽しくなさそうな人の発言記事になるのを見かけるだけで気が滅入るので

Web全体に対してTwitterミュー機能みたいなもの実装できないだろうか

指定ワードを含むコンテナの2階層上のDOMを削除とかで実現できそうな気がするんだがユーザースクリプトとかでいけるか?

2022-05-27

最近学んだこと。React編

・ストア

データを一時保存できるエリア

hooksの登場で簡単

ストア内に置いた変数更新される(1)と、ファイル上にある同じ変数に対しても更新がかかる(2)。設定ができるようになった。ちょう便利。

ちなみに(2)の仕組み(DOM の一部分だけ更新する)こそreactの真骨頂である

ステート

コンポーネント状態を表すとかいってるが体感でいうと

ストア内に置いた変数状態を表すことの方が多くね?(1)をステートが変更される。とか表現する。

・hooks

二年前ぐらい?に追加されたreactの便利機能

・useState

hooksの一つ。ストア内に変数を置くことができる。変数更新用の関数と一緒に作らなければならない。

2022-04-13

anond:20220413160429

session.cookieって書かれると「sessionのcookie」とは違うものを表そうとしているのではないかという可能性を否定できないんだよね

たとえば元増がdocument.cookieという例を挙げてるけど、これはブラウザ提供するDOMインタフェースには必ずdocumentというグローバルオブジェクトが含まれると仕様上決まっており、このオブジェクトは必ずプロパティcookieを持つ、という前提があるからこそこれだけで通じるわけで

同じルールでsession.cookieとか書かれると、「ん?sessionなんていうグローバルオブジェクトあるの?聞いたことないけど…」と混乱する

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