This page looks best with JavaScript enabled

†やるべきことをやらずにTwitterをした人を殺すデーモン†を実装する

 ·  ☕ 3 min read  ·  🐶 odanny · 👀... views

完成したもの

Twitter を起動するとデーモンが出てきて、強制的に再起動される。

再起動の前に暴言を吐く機能付きでちょっと腹立つのがポイントだ。

(図はみんな大好き いらすとや さんより作成。)


はじまり

せっかくゴールデンウイークがはじまったのに、なにも有意義なことをせずSNSを眺めてしまう。
そんな現状を打破したいと思った。

そんなとき、犬のかがやき(@inunokagayaki)さんの「〇〇する人を殺すデーモン」に感銘をうけた。

よし、やるべきことをやらずにTwitterをした人を殺すデーモン を召喚して、ゴールデンウイークを充実したものにするぞ!

アイデアは以下だ。

idea.png

  1. PCの作業状況を監視。
  2. Twittterの起動を検知すると、†やるべきことをやらずにTwitterをした人を殺すデーモン† が登場。
  3. 罵声を浴びせたあと、強制的にPCを再起動する。

ゴールデンウィーク初開発として、ふさわしい内容だ!


環境

  • Windows 10 Education
  • Python 3.6.5

あとGUIをつくるのに、PySimpleGUIをつかった。

1
2
3
4
import PySimpleGUI as sg
sg.version

'4.37.0 Released 15-Mar-2021'

実装

がんばって実装した。詳細は Gist を見てほしい。

Twitterを開くとデーモンがPCを再起動するスクリプト Gist

機能ごとに実装を眺めていく。


デーモンによる監視

win32apiを使って、起動中のプログラムをすべて取得。「Twitter, twitter」の単語を含むプログラムが含まれている場合は、Twitter を開いていると判定する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def _get_all_windows(self) -> list:
    """現在開いているプログラム名をすべて返す。
    virtual desktop であっても取得できる。
    """
    import ctypes

    EnumWindows = ctypes.windll.user32.EnumWindows
    EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool,
                                        ctypes.POINTER(ctypes.c_int),
                                        ctypes.POINTER(ctypes.c_int))
    GetWindowText = ctypes.windll.user32.GetWindowTextW
    GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
    IsWindowVisible = ctypes.windll.user32.IsWindowVisible

    titles = []

    def foreach_window(hwnd, lParam):
        if IsWindowVisible(hwnd):
            length = GetWindowTextLength(hwnd)
            buff = ctypes.create_unicode_buffer(length + 1)
            GetWindowText(hwnd, buff, length + 1)
            titles.append(buff.value)
        return True
    EnumWindows(EnumWindowsProc(foreach_window), 0)
    titles = set(titles)

    # print("起動中プログラム一覧を取得しました")
    # print(*titles, sep="\n")
    return list(titles)

def is_twitter_running(self) -> bool:
    title_list = self._get_all_windows()
    # 'twitter'を含むプログラムを検索
    deny_list = ["twitter", "Twitter"]
    for title in title_list:
        for ng_word in deny_list:
            if ng_word in title:
                return True
    return False

プログラム名から判定することで、シークレットモードであっても Twitter をしていることを判定できる。(チョットコワイ…)


デーモン登場

daemon.png

これは単純にウィンドウを描画するだけだ。keep_on_top=Trueとすることで、仮想デスクトップを切り替えても常に最前面に描画される。

1
2
3
4
5
6
7
8
sg.popup("Twitterやってる場合ちゃうぞ!",
                    background_color=POPUP_BACKGROUND_COLOR,
                    text_color=POPUP_TEXT_COLOR,
                    font=POPUP_FONT,
                    no_titlebar=True,
                    image=daemon_image,
                    keep_on_top=True
                    )

暴言を吐く

音声合成のTTSライブラリを探すのが面倒くさいので、Windows標準装備のコルタナを呼び出す。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def say(text: str):
    sapi = win32com.client.Dispatch("SAPI.SpVoice")
    cat = win32com.client.Dispatch("SAPI.SpObjectTokenCategory")
    cat.SetID(
        r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech_OneCore\Voices", False)
    v = [t for t in cat.EnumerateTokens() if t.GetAttribute("Name")
        == "Microsoft Sayaka"]
    if v:
        oldv = sapi.Voice
        sapi.Voice = v[0]
        sapi.Speak(text)
        sapi.Voice = oldv

再起動する

コマンドをたたく。

1
2
def reboot():
    os.system("shutdown /r /t 0")

デーモンと一緒に有意義な休暇を過ごそう!

デーモンを起動しておけば、カンタンにTwitterとおさらばできる! と言いながら、スマホでTwitterを開くodannyであった…。(有意義な休暇にしよう。)

ちなみにぼくは5回くらいデーモンに殺されました。


参考文献

cmd - ms speech from command line - Stack Overflow
:コルタナを呼び出すスクリプト例。

トライデント・トリアイナのイラスト | かわいいフリー素材集 いらすとや
:つかった槍の素材。かっこいい名前がついてる。


Share on

odanny
WRITTEN BY
odanny
自作キーボードはまり中