Compare commits

...

346 commits

Author SHA1 Message Date
9bf5a82343 Merge pull request 'バグ修正のためtestingをmainにマージ' (#24) from testing into main
Reviewed-on: #24
2024-10-18 14:00:08 +09:00
a4dad36dff Merge branch 'main' into testing 2024-10-18 13:59:10 +09:00
368d51d5f7 キーボード、マウスともに自前のときのボタンを追加 2024-10-18 13:57:23 +09:00
c7c8da46ed ログオン時にデバイスが0番になるバグを修正 2024-10-18 13:50:50 +09:00
9d17d2cb4b Merge pull request 'testing を mainにマージ' (#21) from testing into main
Reviewed-on: #21
なんかよくわからんけどマージしとく
2024-10-09 14:22:35 +09:00
6e49fc5431 Merge branch 'main' into testing 2024-10-09 14:20:49 +09:00
1eb535408b Dockerイメージビルド時の一部の処理を削除 2024-10-06 23:15:04 +09:00
2861c9ffd4 Merge branch 'testing' 2024-10-06 19:46:56 +09:00
5604c7a2bb 削除データの追加を無効 2024-10-05 11:03:42 +09:00
af18cae3ff 削除するデータを追加できるように 2024-10-05 10:45:01 +09:00
c8d6517c3c 登録時のエラーメッセージを追加 2024-10-05 10:37:35 +09:00
683be42817 pcinfoで登録されていないPCを非表示に 2024-10-05 10:30:23 +09:00
a8bf3ab4b7 新規登録できないバグその3 2024-10-05 10:25:37 +09:00
ecfc39695a 新規PCが登録できないバグ修正その2 2024-10-05 10:18:29 +09:00
9e01485e0a 新規PCが登録できないバグを修正 2024-10-05 10:14:54 +09:00
a0056ef2c4 登録時のステータスコードを修正 2024-10-05 10:09:06 +09:00
08a1178209 initでボタンが送信できないバグを修正 2024-10-05 10:00:14 +09:00
4547e05700 pc_tokenを取得できるように 2024-10-05 09:58:13 +09:00
bc35550693 登録されていないPCのボタンは送信しないように 2024-10-05 09:55:12 +09:00
461bcf6fba リレーションの関係でDELETEはUPDATEに 2024-10-05 09:48:00 +09:00
ee4061d10b 存在しないPC番号の場合はINSERTでレコードを作るように 2024-10-05 09:35:49 +09:00
d643e6d1ba #20 PCの登録を解除するスラッシュコマンドの追加 2024-10-05 09:35:14 +09:00
e65f6024d3 デバイスリストが空の場合の処理を追加 2024-10-04 16:38:57 +09:00
43519b104d デバイスリストの送信を無効化 2024-10-04 16:32:26 +09:00
2d963de60f PostgreSQLのバージョンを16に固定 2024-10-03 21:33:43 +09:00
6e7b59de65 必要なライブラリを更新 2024-10-03 20:50:18 +09:00
aeb67bf093 PC情報が取得できないバグを修正 2024-10-03 16:58:34 +09:00
98574811f3 PC情報の使用ユーザー表示を修正 2024-10-03 16:54:53 +09:00
d4fb94c0a2 pc情報が取得できないバグを修正 2024-10-03 16:29:19 +09:00
df9100d66f 使用停止処理を優先して行うように 2024-10-01 23:52:03 +09:00
b6bbefbcbe レイアウトを修正、文言の編集、guitestモード追加 2024-10-01 16:18:50 +09:00
d1cf551fd3 gridのstickyをなくす 2024-10-01 15:49:48 +09:00
b704606dec レイアウト修正、カバー画像のパス修正 2024-10-01 15:45:49 +09:00
07742da1f5 がバー画像ファイルを追加 2024-10-01 15:36:57 +09:00
4969680f09 coverディレクトリの除外を削除 2024-10-01 15:36:47 +09:00
d88a40a360 カバー画像の追加 2024-10-01 15:32:33 +09:00
5de0d66829 タイムアウト時のログ送信を無効にする 2024-10-01 12:23:06 +09:00
af62f218c2 aboutからreasonに変えたい 2024-10-01 12:15:43 +09:00
e3d0e2ae24 fstopのときにログに理由が表示されないバグを修正 2024-10-01 12:14:08 +09:00
5bff1f6a16 ちょっと説明の補足 2024-10-01 12:10:11 +09:00
a2c7fd6f05 PCのニックネーム設定時にログにニックネームが出ない問題を修正 2024-10-01 12:07:42 +09:00
a5b7ba9c18 ログの種類を増やす 2024-10-01 12:04:24 +09:00
dba2358534 パスワードのタイムアウトを通知するように, 無駄なコードの削除 2024-10-01 11:51:29 +09:00
bef78a85d6 タイトルに絵文字を追加する 2024-10-01 11:42:16 +09:00
d932730ed7 自前のデバイスは0番として処理するように 2024-10-01 11:36:27 +09:00
ace3cab44b ログチャンネルに送信する内容をembedに変更 2024-10-01 11:31:11 +09:00
12415c9674 dislocker_slash.pyから移行 2024-09-30 17:32:44 +09:00
9474eaa739 文字、文字つきロゴの画像を追加 2024-09-30 17:26:56 +09:00
b9b55ac2f9 withdrawでウィンドウを完全に非表示に 2024-09-29 22:13:39 +09:00
5488be9ec9 アイコンを変更、ウィンドウを完全に非表示に 2024-09-29 22:07:01 +09:00
aa413cee19 対応するシグナルを変えてみる 2024-09-29 21:56:17 +09:00
5c7611481c customtkinterをimportから除外 2024-09-29 15:30:03 +09:00
ae117944c0 customtkinterからtkinterに変えてみる 2024-09-29 15:29:42 +09:00
b835fe5a74 無駄な二重コードを削除 2024-09-29 15:15:27 +09:00
35aad379a4 タスクの終了コマンドを追加 2024-09-29 12:03:25 +09:00
781e408910 更新対象のファイルを更新 2024-09-29 11:59:17 +09:00
98e45292ab shutdown実行ファイル用のアイコン追加 2024-09-29 11:48:23 +09:00
d2bb01533b ロック解除時にシャットダウン時の実行ファイルを実行するように 2024-09-29 11:40:25 +09:00
8a69b25d52 シャットダウン時の処理を別ファイルに分割 2024-09-29 11:33:12 +09:00
b96496018f selfでいいじゃん!修正 2024-09-29 02:01:37 +09:00
76df98f6d8 データが削除されないバグを修正 2024-09-29 02:01:05 +09:00
7960315a40 Merge pull request 'testing_slash を testing にマージ' (#18) from testing_slash into testing
Reviewed-on: #18
2024-09-29 01:07:40 +09:00
1385eff922 文言を更新 2024-09-29 01:02:51 +09:00
d93111b723 コピーを_internalディレクトリだけにする 2024-09-29 00:59:55 +09:00
d6e046178e インターネット経由でアップデートするためのスクリプトを追加 2024-09-29 00:52:52 +09:00
f237d4ce06 dislockerの圧縮ファイルを削除する処理を追加 2024-09-29 00:52:32 +09:00
0b718125ee マウスの登録ボタンが出ない問題修正(2) 2024-09-29 00:40:13 +09:00
970e04bc75 マウスの登録ボタンが出ないバグを修正 2024-09-29 00:31:32 +09:00
b0865354a3 PCのニックネームが登録できないバグを修正 2024-09-29 00:28:59 +09:00
dfb21e3a25 キーボード、マウスのボタンが呼び出せないバグを修正 2024-09-29 00:24:15 +09:00
c82351e186 ボタンを呼び出せないバグを修正 2024-09-29 00:18:30 +09:00
5f17506447 PC,デバイスの登録ボタンがdbと連動するように 2024-09-29 00:08:56 +09:00
ab96092b39 管理者向けのスラッシュコマンドの返信をembedへ移行, PCのニックネーム設定機能追加, PCの情報取得機能追加 2024-09-28 23:41:19 +09:00
cb3bc05faf デバイスが自前(0番)の時に他人が使っている判定になるのを修正 2024-09-28 22:00:01 +09:00
6bf928ac13 各PC,デバイスのテーブルにalt_nameカラムを追加 2024-09-28 21:52:25 +09:00
31fd32acc9 admin_userとserver_idをリストにして複数指定できるように 2024-09-26 22:01:05 +09:00
364b32c0e7 管理者コマンドのセキュリティの向上 2024-09-26 21:57:13 +09:00
8775b22738 キー名も間違えてたので修正 2024-09-26 21:45:56 +09:00
6fae61351d 関数名間違えてたので修正 2024-09-26 21:44:16 +09:00
69cb9537ff マスターパスワードを取得するスラッシュコマンドと処理を追加 2024-09-26 21:42:33 +09:00
42e36bf1c4 if文のミス修正、on_messageのself削除 2024-09-26 21:24:49 +09:00
224492568a 起動時にワンタイムパスワードを削除する処理を追加 2024-09-26 21:22:08 +09:00
aa9379b2a6 スラッシュコマンドでワンタイムパスワードが要求できないバグを修正 2024-09-26 21:15:47 +09:00
421b1b48c7 スラッシュコマンドのPC、デバイス登録処理を更新 2024-09-26 21:05:43 +09:00
aebab83b86 ワンタイムパスワードの仕様変更に対応 2024-09-26 18:10:12 +09:00
33dd3aef9b 指定ユーザーのDMにこたえるように 2024-09-26 18:09:51 +09:00
02e0b8b95d アクティビティの変更処理を移植 2024-09-26 17:30:21 +09:00
885f625403 asyncioをthreadingに置き換える 2024-09-26 17:26:48 +09:00
1cd58404c6 関数の名前ミスを修正 2024-09-26 17:17:15 +09:00
6ea299f661 asyncio導入 2024-09-26 17:16:15 +09:00
f13d119eb2 デバイス番号が自前の時に0を登録するように 2024-09-26 17:04:55 +09:00
ff30611ebd コマンドの権限を設定 2024-09-26 17:01:20 +09:00
65d1f6e568 使用理由のモーダルが起動しなかったバグを修正 2024-09-26 16:57:49 +09:00
fc16d15ef9 ボタン周りの処理を修正 2024-09-26 16:52:48 +09:00
f1967f0388 ボタン周りの機能を移植してくる 2024-09-26 16:36:18 +09:00
db16ddce29 日本語使えなかったので修正 2024-09-26 09:29:19 +09:00
3575818af8 Workbookのインポートを修正 2024-09-26 09:28:20 +09:00
f7f3e5d40b sqlのインポートを修正、日本語テスト 2024-09-26 09:25:31 +09:00
4f78a54b2f スラッシュコマンドを追加 2024-09-26 08:42:54 +09:00
5578cffad6 説明文言を100文字以下に抑える 2024-09-25 22:58:54 +09:00
0fc7c0c3eb datetimeのimportを修正, メッセージの文言修正 2024-09-25 22:56:08 +09:00
fd8b5e3a8b 使用登録、使用停止ができるように 2024-09-25 22:46:53 +09:00
71ca2c0cda スラッシュコマンドテスト用 2024-09-25 14:50:11 +09:00
99fd556319 文言の変更 2024-09-24 14:27:46 +09:00
6b617a6a63 ダウンロード用のスクリプトを追加 2024-09-24 14:27:21 +09:00
1e1ab94dcf それぞれのブロック処理の順番を見直し 2024-09-24 00:10:58 +09:00
b090e27056 既に開かれているウィンドウをロック前に最小化する処理を追加 2024-09-23 23:50:33 +09:00
8c8e9e6f06 hard_lockのエクスプローラーの終了をApp起動時に変更 2024-09-23 23:11:47 +09:00
83ef0bbd07 ホストURLを指定できるように 2024-09-23 23:06:26 +09:00
20b46e8c40 configファイルの値をわかりやすく etc...
hard_lockモードの実装
subprocessの実行コマンドの入力をリストから文字列に変更
2024-09-23 22:24:08 +09:00
84d1b0cb59 使用目的がカスタムで送信できないバグを修正 2024-09-17 14:02:14 +09:00
7b75da62a3 ホストURLをコマンドラインから指定できるように 2024-09-11 16:28:10 +09:00
ab6e77a99f 停止処理ができないバグを修正 2024-09-10 19:21:01 +09:00
a28df9ad77 logを除外 2024-09-10 19:18:25 +09:00
9389441262 configにstop用のeraserキーを追加 2024-09-10 18:30:33 +09:00
45d6b9f3c8 testingの成果をマージ 2024-09-10 18:17:00 +09:00
45b1b767ac tempディレクトリは追跡外に 2024-09-10 18:13:10 +09:00
8658955998 tempディレクトリ削除 2024-09-10 18:12:40 +09:00
6bcb570b10 終了処理を簡略化 2024-09-10 18:11:41 +09:00
8ade781d4b 使用理由が聞かれないバグを修正 2024-09-09 14:20:26 +09:00
cf47a5b2ad 自前のボタンを追加 2024-09-09 14:04:19 +09:00
c08afa08c3 使用目的のプリセットを追加 2024-09-08 15:14:06 +09:00
5a709197e7 configの内容をtestingからもってくる 2024-09-08 15:03:16 +09:00
e4b99a85ff 使用目的が取得できないバグへの暫定的対応 2024-09-07 15:30:31 +09:00
9fe9330b13 この前の前のコミットのバグを今度今度こそ修正 2024-09-07 14:57:58 +09:00
65403a4cca この前のコミットのバグを今度こそ修正
ついでにメッセージの表示を見やすく
2024-09-07 14:47:47 +09:00
0fcfc8009f PCを自分が使用中なのに他人が使用中と出力されるバグを修正 2024-09-07 14:36:27 +09:00
ebef42cc55 内部エラーのときもパスワードが間違っていると出力するバグを修正 2024-09-07 14:06:26 +09:00
20fa6f1fb8 デバイスリストのキー名を修正 2024-09-07 14:01:05 +09:00
7e35bd6089 デバイスIDをデバイスインスタンスパスに変更
ワンタイムパスワードが消去されないバグを修正
デバイス登録の際USBデバイスではなく入力デバイスの一覧を出力するように
自前のデバイスは0番として処理するように
2024-09-07 13:40:13 +09:00
61e01ae055 アップデートを簡略化するバッチファイルを追加 2024-09-06 16:30:10 +09:00
487dfbd96d delete_appdataの修正をtestingからもってくる 2024-09-06 14:47:31 +09:00
cc771d5196 get_usb_devicesがclass内で動作しなかったバグを修正 2024-09-06 02:39:40 +09:00
4836e6ae8f リストの番号を修正 2024-09-06 02:29:19 +09:00
e97562b9b2 デバイス番号のボタンを削除 2024-09-06 02:26:52 +09:00
7282af55e0 デバイス一覧から参照する型名を修正 2024-09-06 02:04:51 +09:00
611bd03b80 strへの変換を撤回 2024-09-06 02:02:07 +09:00
75fa89497e selfなくす 2024-09-06 01:55:19 +09:00
3f31307164 改名できてなかった こっちで改名 2024-09-06 01:48:54 +09:00
9279edc8ca devicesetupをdeviceregisterに改名とちょっとのバグ修正 2024-09-06 01:47:45 +09:00
4713dc7a23 デバイス番号の入力の自動化 (#14) への対応 2024-09-06 01:30:44 +09:00
550cf83e86 ハッシュをSHA256へ変更
マスターパスワードの管理をデータベースで行うように
テーブルの一部カラム変更
2024-09-06 00:09:37 +09:00
e41324eae4 使用目的のプリセットが使えなくなるバグを修正 2024-09-05 21:11:34 +09:00
b1994c5def tempディレクトリを再度除外 2024-09-05 21:04:09 +09:00
a6c856cf48 tempの中を削除 2024-09-05 21:03:39 +09:00
036e1c0b0b 使用目的かけないバグ対処そのに 2024-09-05 10:43:34 +09:00
e50a5748c9 使用目的が書けなくなったバグへの対処 2024-09-05 10:38:17 +09:00
55f989d365 ログファイルが見ずらいのを修正 2024-09-04 19:47:58 +09:00
cf0013e53a 使用理由のプリセットを指定できるように
ログファイルを作成するように
いくつか説明の追加
2024-09-04 19:42:39 +09:00
5384cc9668 テスト用クライアントの追加 2024-08-31 16:13:25 +09:00
518eea2061 #6 のバグへの対策 2024-08-30 23:35:32 +09:00
77ada9a5e2 削除処理の繰り返しを修正 2024-08-30 23:29:50 +09:00
e585e9d596 password_hashがあったときの処理を修正 2024-08-26 00:51:31 +09:00
86a4ef8766 型を明示的に指定 2024-08-26 00:47:39 +09:00
631fd990cb printの実行順番を修正 2024-08-26 00:46:15 +09:00
3086f689ad ファイルの消去を設定できるように 2024-08-26 00:40:20 +09:00
b3687e8a2d ANDの,を消す 2024-08-26 00:35:18 +09:00
4366aa06ca json処理あたりを修正 2024-08-26 00:25:04 +09:00
25f3ae6404 UUID型をstr(VARCHAR)に変更 2024-08-26 00:19:53 +09:00
c6c602a34b if文のあたりのミスを修正 2024-08-26 00:16:53 +09:00
27361d40db returnコードを修正 2024-08-26 00:04:39 +09:00
b6b34ce315 参照するカラム名を修正 2024-08-26 00:02:24 +09:00
665b53c28d registerのワンタイムパスワードをstr型に指定 2024-08-25 23:58:53 +09:00
bd1aa2243c ワンタイムパスワードを入力できるように 2024-08-25 23:47:14 +09:00
de8412e4eb ワンタイムパスワードの長さを決定(8文字) 2024-08-25 23:35:02 +09:00
bf1dc817ab クライアント登録時のワンタイムパスワードを実装 2024-08-25 23:28:36 +09:00
2ddcc6626a user_idをdiscord_user_idに全面的に改める 2024-08-23 02:33:17 +09:00
d433f38d94 stopのKeyErrorを修正 2024-08-23 02:28:23 +09:00
26f5269ce5 PC使用登録時管理者側のメッセージでDiscordのユーザー名が見える問題を修正 2024-08-23 02:24:42 +09:00
35ba7e0dff それぞれ参照するカラム名の修正 2024-08-23 02:17:10 +09:00
668af84ca8 PC使用開始時に管理者側に送るメッセージを修正 2024-08-23 02:12:10 +09:00
698e629063 exportを修正 2024-08-23 02:09:13 +09:00
ef0bd4b509 Monitorを修正 2024-08-23 02:04:41 +09:00
3160f1c079 念の為、マウスとキーボード使用確認のcursorを上に持っていく 2024-08-23 01:53:09 +09:00
7bade8c366 printf攻撃 2024-08-23 01:48:01 +09:00
aae08d4701 こころぐを追加2 2024-08-23 01:42:02 +09:00
ca6ff5d050 ここログを追加 2024-08-23 01:38:54 +09:00
1e8ef35e3f cursorが見つからないエラーを修正したい 2024-08-23 01:30:58 +09:00
2d5ea6a48d PCの使用登録でデータベースのコミットを忘れてた 2024-08-23 01:18:02 +09:00
125ca3e601 キーボード、マウスの使用確認関数に自前のものかを判定する処理を追加 2024-08-23 01:15:21 +09:00
cd6461641c PCの使用チェックにmember_idで確認できる処理を追加
PC使用登録時にmember_idを使ってPCの使用確認をするように
2024-08-23 01:09:00 +09:00
69dbdd0bc3 PC使用登録時にユーザーが登録されていなかったときの返り値を修正 2024-08-23 00:58:38 +09:00
edd01a0d4d 登録のときにどうしてもエラーになるバグを修正 2024-08-23 00:55:49 +09:00
9269441051 custom_idで言うところのreasonregisterあたりの処理を修正 2024-08-23 00:53:03 +09:00
7d7cc17193 マウスを選ぶボタンのところのviewの名前が間違ってたので修正 2024-08-23 00:44:57 +09:00
4b4455694e かっこ閉じ必要だったのでロールバック 2024-08-23 00:39:34 +09:00
ee4113f95d 無駄なかっことじを削除 2024-08-23 00:34:07 +09:00
829184a91a club_memberテーブルのカラム名を修正 2024-08-23 00:26:42 +09:00
55b55046df スペースがなかったのが気になっただけ 2024-08-23 00:22:01 +09:00
db55479da9 ちょっとバグ修正 2024-08-23 00:19:33 +09:00
8e635eb92c Botの仕様変更に合わせて更新 2024-08-23 00:18:07 +09:00
c107400ed2 fstop側のマウス、キーボードの使用停止処理を追加 2024-08-23 00:17:51 +09:00
07fcc298a9 全部変えた
だいたいの関数で返り値をreturnで直接返すようにした
返り値の辞書の構造変更(resultはだいたいの状況がわかる番号で、aboutに従来のresultであった理由を記載)
データベース構造の変更(キーボード、マウスリスト追加、その他カラム名変更)
PC使用登録時にマウスとキーボードの番号をを別で尋ねるように
PC使用登録時にマウスとキーボードを自前で持ってきている場合のボタンと処理を追加
PC登録の関数内の一部の処理を別の関数に移した
2024-08-22 23:58:31 +09:00
03319676e9 tempディレクトリを除外 2024-08-22 23:53:37 +09:00
7fc3ca701c 大幅な仕様変更のためtestingをmainにマージ 2024-08-22 22:46:41 +09:00
66f39eb293 ウィンドウのアイコンを適用できるように 2024-08-22 11:46:52 +09:00
19cf8e195c 多重起動防止の処理をロールバック 2024-08-22 11:18:04 +09:00
9cb5f22cfc ボタンの色を修正
init周りを修正
2024-08-21 13:21:08 +09:00
d7094656a3 アイコンのパスを修正 2024-08-21 13:11:29 +09:00
19afc4a57a issue #7 の解決案(ボタン無効化)を適用 2024-08-21 12:59:45 +09:00
9dc9938732 READMEを更新 2024-08-21 12:16:50 +09:00
04ae26862f clientの動作確認用 2024-08-21 12:16:41 +09:00
111686c257 念のため他のテーブルの型も修正 2024-08-19 22:57:07 +09:00
8a88a1a31f ユーザー登録時に文字数超過のエラーが出ることへの暫定的な対応 2024-08-19 10:01:49 +09:00
8019674b13 Monitorのpc_listのprintを無効化 2024-08-16 13:23:12 +09:00
60d4fc9c81 MonitorのResultがNONEだった時のログを出力しないように 2024-08-16 13:15:10 +09:00
7a1aa6a7db configファイルを明示的にUTF-8で読み書きするように 2024-08-15 22:46:55 +09:00
f7ecdc535f monitorの時間類の設定をconfigファイルへ移動 2024-08-15 22:41:38 +09:00
3073f12e6c 多重起動防止の処理をいったんやめにする 2024-08-14 00:03:47 +09:00
f304346426 initのif文を修正 2024-08-13 14:43:47 +09:00
b5fc778715 fstopに理由を要求するように
使用停止忘れのための停止処理を追加
2024-08-11 15:25:01 +09:00
3aad819485 生成されるconfigファイルの内容を合わせる 2024-08-10 18:47:16 +09:00
c55fd3162b データベースの環境変数をenvファイルに移動 2024-08-10 18:33:48 +09:00
7f92544102 volumeが逆だったので修正 2024-08-10 18:30:12 +09:00
dca3cad736 それぞれのDockerfileとcompose.ymlを追加 2024-08-10 18:27:24 +09:00
a10f5c47e9 Flaskのデバッグモードを明示的に無効化 2024-08-10 18:21:35 +09:00
ba9f227e09 タイムスタンプのバグを修正
自動停止処理が時間をおいて起動するように
2024-08-10 18:10:35 +09:00
b9d9e797d3 環境変数をミスってたので修正 2024-08-10 17:38:09 +09:00
a9d15357c4 PCの使用履歴のシートを除外 2024-08-10 17:37:49 +09:00
2663ad2ff6 ユーザーとして登録されていないときに停止ボタンを押したときに内部エラーと表示される仕様を変更
定期監視の一部仕様変更
2024-08-10 17:32:14 +09:00
425edead34 Dockerで動かす用 2024-08-10 17:06:53 +09:00
c4b4718583 終了処理にself忘れてた 2024-08-09 11:30:03 +09:00
16ea317730 引数の名前修正 2024-08-09 11:09:06 +09:00
8deb85e9fb 停止処理をできるように 2024-08-09 10:49:48 +09:00
b47305439c Riotのデータを削除するように 2024-08-08 00:31:34 +09:00
8e8c052b0c 多重起動防止のための処理追加 2024-08-07 11:37:23 +09:00
b5285c0f21 EAとSteamのデータを削除するように 2024-08-07 10:42:43 +09:00
3bf7918bb4 アクティビティの変更を忘れていた 2024-07-26 13:29:09 +09:00
a8f9ad0ec6 アクティビティを設定できるように 2024-07-26 13:23:21 +09:00
95e8855c27 アプリデータの削除処理を追加 2024-07-26 11:45:13 +09:00
a9109dba0a タイムアウト処理の実装 2024-07-25 23:44:47 +09:00
e48a0fc3c2 PC番号をもっと大きく表示するように 2024-07-25 21:32:08 +09:00
2edd37fbfd ショートカットの作成処理を修正 2024-07-25 21:13:50 +09:00
765a0bd2ba pyinstaller用のコマンドを追加 2024-07-25 20:29:07 +09:00
348fa96759 pyinstallerのカレントディレクトリ問題を対策 2024-07-25 20:19:03 +09:00
5a1ac0e3c1 クライアントへインストール用のスクリプトを追加 2024-07-25 20:05:01 +09:00
5653b79906 testing_2ブランチの変更をマージ 2024-07-25 20:02:12 +09:00
db9afe38f2 Merge branch 'testing_2' into testing 2024-07-25 19:59:38 +09:00
b630d7aa98 カレントディレクトリの処理を追加 2024-07-25 19:57:38 +09:00
a193d25877 クライアント用 2024-07-25 19:57:09 +09:00
1cc6d1d60f 引数setupを追加 2024-07-25 19:35:22 +09:00
ad5f84d238 initのテスト 2024-07-25 19:25:47 +09:00
e23662422e 入力欄でEnterを押したときの処理を追加 2024-07-25 16:17:33 +09:00
451ea60140 monitorを無効化 2024-07-25 14:31:18 +09:00
e9a322f839 デバイス番号を10番までに変更 2024-07-25 14:24:24 +09:00
7b3708dd51 認証ウィンドウを中央に配置
メッセージウィンドウが表示できるように
2024-07-25 10:44:07 +09:00
41788bb622 アイコンを追加 2024-07-24 23:45:42 +09:00
78114d3f04 引数stopで使用停止処理とシャットダウンを同時に行えるように 2024-07-24 23:34:49 +09:00
ab7147ffde シャットダウン時の使用停止処理を追加 2024-07-23 15:15:44 +09:00
18de0e7b85 停止処理を追加 2024-07-23 15:15:24 +09:00
34ce84532d タイムアウトまでの時間を5分に延長 2024-07-22 20:58:04 +09:00
c1ce0ceb5b ログアウト時にタスクマネージャーを復活するように 2024-07-22 12:00:40 +09:00
e3ff1a78b2 printデバッグ用 2024-07-22 11:58:05 +09:00
45323b2f48 機能修正 2024-07-22 11:57:50 +09:00
b908ce17ed ボタン操作ができるように、タイムアウト機能の実装、スラッシュコマンド対応への準備 2024-07-21 16:36:16 +09:00
f7b6caca30 メッセージ内容を修正 2024-07-20 23:18:36 +09:00
1bf03a600e PCの登録がチャンネル上でできるように 2024-07-20 23:08:27 +09:00
7129a08508 PCの登録を追加 2024-07-20 20:12:19 +09:00
585ddf8cf1 ユーザー登録をユーザー自身でもできるように 2024-07-20 20:11:11 +09:00
00a4c00fcf 認証サーバーがserver.jsonの設定ファイルを読み込むように 2024-07-20 20:10:18 +09:00
707e2e3ed6 ログアウトボタンの表記をサインアウトに変更 2024-07-08 11:42:19 +09:00
d76ba87887 ヘルプ、サインアウトの関数を追加 2024-07-08 11:41:38 +09:00
889c464c5f 使用履歴出力のreturn修正 2024-07-08 11:30:20 +09:00
abf03bd4d6 Excelシートで出力できるように 2024-07-08 11:23:19 +09:00
b37573a371 出力されるcsvファイルが履歴のid順で並ぶように 2024-07-07 18:15:15 +09:00
9f59b8dab1 csv出力のコードを修正その5 2024-07-07 18:09:25 +09:00
ce3bf1cd3c csv出力のコードを修正その4 2024-07-07 18:07:53 +09:00
e1fee8b2e5 csv出力のコードを修正その3 2024-07-07 18:00:49 +09:00
d640155e75 csv出力のコード修正その2 2024-07-07 17:48:54 +09:00
8b7e7a2a65 csv出力のコード修正 2024-07-07 17:43:36 +09:00
f26e0d9ad9 force_stopのreturnを追加 2024-07-07 17:40:03 +09:00
c9b7259728 fstopの引数が間違っていたのを修正 2024-07-07 17:37:53 +09:00
aeb9553113 int判定を修正 2024-07-07 17:34:51 +09:00
80a266142b printfデバックを削除、チャンネルIDがintで記述されていない場合は起動しなくなるように 2024-07-07 17:24:33 +09:00
62537a1038 printデバック用 2024-07-07 17:10:05 +09:00
57f428e910 使用登録の強制停止を実装 2024-07-07 16:35:57 +09:00
18970c9079 メッセージの文言を変更 2024-07-07 16:08:17 +09:00
9e4f39f8fa ようやく理解した selfを追加 2024-07-07 16:04:46 +09:00
60af46a32b returnを回避 2024-07-07 15:55:14 +09:00
bf418936d4 tryを修正 2024-07-07 15:52:46 +09:00
73502817e0 きれそう 2024-07-07 15:48:43 +09:00
4ecf209e7e データベース接続時の例外処理を追加 2024-07-07 15:43:43 +09:00
f7f7033ea5 class名だめだったから修正 2024-07-07 15:33:30 +09:00
2ef4d639bf やっぱ初期処理と関連の変数のクラスを分けた 2024-07-07 15:24:55 +09:00
a16a0424dc 初期挙動をbotクラスに統合、csvファイルの出力ができるように 2024-07-07 15:02:54 +09:00
41e85cb6bc csv出力のテスト 2024-07-07 15:02:11 +09:00
dde933fc14 名前変更に伴い削除 2024-07-07 15:01:24 +09:00
5de39f92a4 PC使用履歴のテーブルからcsvファイルを作成できるように 2024-07-07 13:50:57 +09:00
7d06ad18c4 設定がひとつのjsonファイルで完結するように 2024-07-07 13:49:53 +09:00
0a7bb89a98 GUIを再設計 (thanks for 八咫烏!) 2024-07-04 20:40:03 +09:00
5cd099a411 GUIデザインをコンセプトに近づける 2024-07-01 12:51:17 +09:00
e3d9f73fd7 終了用のショートカットキーを追加 2024-06-16 17:03:15 +09:00
a6082c1f0a たのむ 2024-06-10 14:52:27 +09:00
18076cdf31 あーーーーー 2024-06-10 14:38:33 +09:00
1147b50fd1 新規ユーザー(使用履歴がない)ときの処理を追加 2024-06-10 14:31:40 +09:00
3e4798e8d5 テスト用設定の追加 2024-06-10 13:46:42 +09:00
f6c7342002 initialを修正 2024-06-10 13:41:05 +09:00
0f21c03003 マスターパスワードの照合を追加 2024-06-10 13:34:22 +09:00
7087090211 クライアント用のライブラリを追加 2024-06-10 13:34:10 +09:00
d8f9717304 初回起動時の処理を追加 2024-06-10 13:27:21 +09:00
0c4da769ac 動かないのを修正したい 2024-06-09 20:15:06 +09:00
260779fca3 初回の処理を修正 2024-06-09 20:11:20 +09:00
5c15c0b092 ユーザー登録が指定テキストチャンネルでできるように 2024-06-09 19:56:59 +09:00
de96b457eb 無駄なreturnをなくす 2024-06-09 19:04:32 +09:00
d03d5ec4ef 返り値を修正 2024-06-09 18:49:46 +09:00
0427c021a0 諸々の処理を関数に導入 2024-06-09 18:39:42 +09:00
128ebc88b3 背景のボタンを削除 2024-06-08 22:42:26 +09:00
5133e550ed 背景に触れないように 2024-06-08 22:38:53 +09:00
7d8c14c080 db_configのままだったのを修正 2024-06-08 22:17:18 +09:00
7093733a69 int型を明示 2024-06-08 22:07:51 +09:00
dedccf5f95 ダミーページへの誘導を削除 2024-06-08 22:07:30 +09:00
9b8d9dac2c どのIPからも応答できるように 2024-06-08 20:28:00 +09:00
94d4e16cfd 一応ダミーページを返すように 2024-06-08 20:26:26 +09:00
c1e9ca4878 ダミー用 2024-06-08 20:26:11 +09:00
9dec6938dd パスワードをハッシュ化してデータベースに保存するように 2024-06-08 19:19:07 +09:00
26902aa0b3 認証用サーバーにつなぐように 2024-06-08 19:18:50 +09:00
32a183244f 認証用サーバーを追加 2024-06-08 19:18:35 +09:00
bd12378f3c test.pyを追跡外に 2024-06-08 19:18:16 +09:00
451d7facc5 psycopg2をバイナリ版でインストールするように 2024-06-08 11:50:23 +09:00
e58ae29ca7 パスワードの入力を非表示にする 2024-06-08 09:59:33 +09:00
5b9395a1d2 block_taskmgr関数を呼び出してなかったので修正 2024-06-08 09:46:24 +09:00
a52533f34b レジストリのパスを修正 2024-06-08 09:40:37 +09:00
0b03527e33 レジストリでタスクマネージャーの実行をブロックするように 2024-06-08 09:33:54 +09:00
4d391c7a9a テスト用 2024-06-07 22:29:00 +09:00
3f1611dde1 タスクマネージャー対策への第一歩 2024-06-07 22:28:51 +09:00
bdaf1ac0d8 bot_configの修正 2024-06-07 12:29:49 +09:00
f2679a8307 特定のキーをブロックするように 2024-06-06 23:08:15 +09:00
e849afbf91 クライアント用にkeyboard追加 2024-06-06 23:07:43 +09:00
7f6bbfc420 フリーズを修正 2024-06-06 20:04:03 +09:00
4cbd7e1cf1 クライアント用に追加 2024-06-06 19:42:26 +09:00
7f7b8733b6 仮でクライアント用 2024-06-06 19:40:41 +09:00
639fd23970 認証完了時のトースト通知用 2024-06-06 19:40:33 +09:00
f748e48517 PC用のテーブルを作成 2024-06-05 18:38:14 +09:00
0436035b0a パスワードを生成できるように 2024-06-05 18:37:50 +09:00
b01ce7b373 いらないコードを削除、configにログ送信先チャンネルのIDを記載するように 2024-06-05 16:13:57 +09:00
b084ead6b7 改行を修正 2024-06-05 11:36:37 +09:00
a81327a680 データベースへの接続バグを修正 2024-06-05 11:27:57 +09:00
22bc5fe240 ワンタイムパスワード用にマージ予定 2024-06-05 11:22:35 +09:00
ace0af03d6 for_psqlブランチをマージ 2024-06-04 23:06:11 +09:00
7cfd94053e for_psqlブランチをマージ 2024-06-04 23:06:03 +09:00
20d9d15063 pull 2024-06-04 23:04:10 +09:00
dfcc4d7c37 テーブルの名前、カラムなど修正 2024-06-04 22:53:53 +09:00
e0e4ac73bb 一応動くようにする 2024-06-04 22:53:31 +09:00
61219d52ef 1st 2024-06-04 19:53:35 +09:00
05f17d6d68 DMかを判断できるように 2024-06-04 19:53:24 +09:00
68bd6ca282 dbも追加(sqlite用) 2024-06-04 19:43:52 +09:00
43 changed files with 5286 additions and 107 deletions

10
.gitignore vendored
View file

@ -50,7 +50,6 @@ coverage.xml
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
@ -160,5 +159,10 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
config/*
db/*
config/
db/
test.py
data/
export/
temp/
log/

15
Dockerfile_auth Normal file
View file

@ -0,0 +1,15 @@
FROM python:3
USER root
RUN mkdir /dislocker
ENV TZ JST-9
ENV TERM xterm
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN python -m pip install flask psycopg2-binary requests
WORKDIR /dislocker
CMD python -u ./dislocker_auth.py

15
Dockerfile_bot Normal file
View file

@ -0,0 +1,15 @@
FROM python:3
USER root
RUN mkdir /dislocker
ENV TZ JST-9
ENV TERM xterm
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN python -m pip install discord.py psycopg2-binary requests openpyxl
WORKDIR /dislocker
CMD python -u ./dislocker.py

View file

@ -1,2 +1,9 @@
# Dislocker
課題研究用リポジトリ
# 環境構築
## サーバー側
基本的にはDocker上での起動を推奨します。
このリポジトリをクローンし、`docker compose up -d`で起動すると一式のコンテナが起動します。
データベースだけを起動したい場合は、ファイルに`compose_db.yml`を指定してください。
## クライアント側
pyinstallerでビルドしたものを、起動してください。

45
compose.yml Normal file
View file

@ -0,0 +1,45 @@
services:
bot:
build:
context: "./"
dockerfile: "Dockerfile_bot"
restart: always
environment:
- TZ=Asia/Tokyo
depends_on:
- db
volumes:
- ./:/dislocker
networks:
- dislocker_network
auth:
build:
context: "./"
dockerfile: "Dockerfile_auth"
restart: always
environment:
- TZ=Asia/Tokyo
volumes:
- ./:/dislocker
ports:
- 12244:5000
networks:
- dislocker_network
db:
image: postgres:16-alpine3.20
restart: always
environment:
- TZ=Asia/Tokyo
volumes:
- ./data/db:/var/lib/postgresql/data
ports:
- 12245:5432
env_file:
- ./data/.env
networks:
- dislocker_network
networks:
dislocker_network:

18
compose_db.yml Normal file
View file

@ -0,0 +1,18 @@
services:
db:
image: postgres:16-alpine3.20
restart: always
environment:
- TZ=Asia/Tokyo
- POSTGRES_DB=dislocker
- POSTGRES_USER=dislocker
- POSTGRES_PASSWORD=Password
volumes:
- ./data/db:/var/lib/postgresql/data
ports:
- 12245:5432
networks:
- dislocker_network
networks:
dislocker_network:

File diff suppressed because it is too large Load diff

484
dislocker_auth.py Normal file
View file

@ -0,0 +1,484 @@
import psycopg2
import os
import json
from flask import Flask, request, jsonify, render_template
import uuid
import string
import random
import hashlib
config_dir_path = "./config/"
server_config_path = config_dir_path + "server.json"
onetime_config_path = config_dir_path + "onetime.json"
if not os.path.isfile(server_config_path):
if not os.path.isdir(config_dir_path):
os.mkdir(config_dir_path)
server_config = {
"db": {
"host": "localhost",
"port": "5432",
"db_name": "dislocker",
"username": "user",
"password": "password"
},
"bot": {
"token": "TYPE HERE BOTS TOKEN KEY",
"activity": {
"name": "Dislocker",
"details": "ロック中...",
"type": "playing",
"state": "ロック中..."
},
"log_channel_id" : "TYPE HERE CHANNEL ID (YOU MUST USE INT !!!!)",
"config_channel_id": "TYPE HERE CHANNEL ID (YOU MUST USE INT !!!!)",
"config_public_channel_id": "TYPE HERE CHANNEL ID (YOU MUST USE INT !!!!)"
}
}
with open(server_config_path, "w") as w:
json.dump(server_config, w, indent=4)
elif os.path.isfile(server_config_path):
with open(server_config_path, "r") as r:
server_config = json.load(r)
class Auth():
def __init__(self, host, db, port, user, password):
self.db = psycopg2.connect(f"host={host} dbname={db} port={port} user={user} password={password}")
def token_generate(self, length):
letters = string.ascii_letters + string.digits
token = ''.join(random.choice(letters) for _ in range(length))
return token
def master_password_generate(self, length):
characters = string.ascii_letters + string.digits + string.punctuation
master_password = ''.join(random.choice(characters) for _ in range(length))
return master_password
def hash_genarate(self, source):
hashed = hashlib.sha256(source.encode())
return hashed.hexdigest()
def check(self, **kwargs):
try:
cursor = self.db.cursor()
pc_number = int(kwargs["pc_number"])
pc_uuid = str(kwargs["pc_uuid"])
pc_token = str(kwargs["pc_token"])
if "device_list" in kwargs:
if kwargs["device_list"] == []:
device_list = None
else:
device_list = kwargs["device_list"]
else:
device_list = None
keyboard_number = 0
mouse_number = 0
if "password_hash" in kwargs:
password_hash = str(kwargs["password_hash"])
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s AND password_hash = %s AND pc_uuid = %s AND pc_token = %s", (pc_number, password_hash, pc_uuid, pc_token))
pc_info = cursor.fetchall()
if pc_info:
if device_list == None:
pass
else:
for device in device_list:
cursor.execute("SELECT * FROM keyboard_list WHERE device_instance_path = %s", (device["device_instance_path"],))
keyboard_record = cursor.fetchall()
if keyboard_record:
keyboard_number = int(keyboard_record[0][0])
break
else:
pass
for device in device_list:
cursor.execute("SELECT * FROM mouse_list WHERE device_instance_path = %s", (device["device_instance_path"],))
mouse_record = cursor.fetchall()
if mouse_record:
mouse_number = int(mouse_record[0][0])
break
else:
pass
return {"result": 0, "about": "ok", "output_dict": {"keyboard_number": keyboard_number, "mouse_number": mouse_number}}
else:
return {"result": 1, "about": "incorrect_password"}
else:
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s AND pc_uuid = %s AND pc_token = %s", (pc_number, pc_uuid, pc_token))
pc_info = cursor.fetchall()
if pc_info:
return {"result": 0, "about": "ok"}
else:
return {"result": 1, "about": "unregistered_pc"}
except Exception as error:
print("PCの登録状況を調査中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally:
cursor.close()
def device_use_register(self, **kwargs):
try:
pc_number = int(kwargs["pc_number"])
if kwargs["keyboard_number"] == "own":
keyboard_number = 0
else:
keyboard_number = int(kwargs["keyboard_number"])
if kwargs["mouse_number"] == "own":
mouse_number = 0
else:
mouse_number = int(kwargs["mouse_number"])
cursor = self.db.cursor()
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s", (pc_number,))
pc_list_record = cursor.fetchall()
pc_using_member_id = pc_list_record[0][1]
if pc_using_member_id == None:
return {"result": 1, "about": "not_used"}
else:
cursor.execute("SELECT * FROM pc_usage_history WHERE member_id = %s AND pc_number = %s ORDER BY id DESC LIMIT 1", (pc_using_member_id, pc_number))
pc_usage_history_record = cursor.fetchall()
pc_usage_history_record_id = pc_usage_history_record[0][0]
cursor.execute("UPDATE pc_usage_history SET keyboard_number = %s, mouse_number = %s WHERE id = %s", (keyboard_number, mouse_number, pc_usage_history_record_id))
if keyboard_number == 0:
pass
else:
cursor.execute("UPDATE keyboard_list SET using_member_id = %s WHERE keyboard_number = %s", (pc_using_member_id, keyboard_number))
if mouse_number == 0:
pass
else:
cursor.execute("UPDATE mouse_list SET using_member_id = %s WHERE mouse_number = %s", (pc_using_member_id, mouse_number))
self.db.commit()
return {"result": 0, "about": "ok"}
except Exception as error:
print("デバイスの使用登録中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
def device_register(self, **kwargs):
try:
cursor = self.db.cursor()
mode = kwargs["mode"]
number = kwargs["number"]
device_instance_path = kwargs["device_instance_path"]
device_name = kwargs["device_name"]
if mode == "keyboard":
keyboard_number = int(kwargs["number"])
cursor.execute("SELECT * FROM keyboard_list WHERE keyboard_number = %s", (keyboard_number,))
keyboard_record = cursor.fetchall()
if keyboard_record:
cursor.execute("UPDATE keyboard_list SET device_instance_path = %s, device_name = %s WHERE keyboard_number = %s", (device_instance_path, device_name, keyboard_number))
self.db.commit()
return {"result": 0, "about": "ok"}
else:
cursor.execute("INSERT INTO keyboard_list (keyboard_number, device_instance_path, device_name) VALUES (%s, %s, %s)", (keyboard_number, device_instance_path, device_name))
return {"result": 0, "about": "ok"}
elif mode == "mouse":
mouse_number = int(kwargs["number"])
cursor.execute("SELECT * FROM mouse_list WHERE mouse_number = %s", (mouse_number,))
mouse_record = cursor.fetchall()
if mouse_record:
cursor.execute("UPDATE mouse_list SET device_instance_path = %s, device_name = %s WHERE mouse_number = %s", (device_instance_path, device_name, mouse_number))
self.db.commit()
return {"result": 0, "about": "ok"}
else:
cursor.execute("INSERT INTO mouse_list (mouse_number, device_instance_path, device_name) VALUES (%s, %s, %s)", (mouse_number, device_instance_path, device_name))
return {"result": 0, "about": "ok"}
except Exception as error:
print("停止処理中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
def delete(self, pc_number):
try:
cursor = self.db.cursor()
cursor.execute("UPDATE pc_list SET password_hash = NULL WHERE pc_number = %s", (pc_number,))
self.db.commit()
return {"result": 0, "about": "ok"}
except Exception as error:
print("パスワードの削除中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally:
cursor.close()
def user_register_check(self, **kwargs):
try:
discord_user_id = str(kwargs["discord_user_id"])
cursor = self.db.cursor()
cursor.execute("SELECT * FROM club_member WHERE discord_user_id = %s", (discord_user_id,))
user_record = cursor.fetchall()
#ユーザーデータが見つかった場合(登録済みの場合)
if user_record:
member_id = user_record[0][0]
name = user_record[0][1]
discord_user_name = user_record[0][2]
return {"result": 0, "about": "exist", "user_info": {"member_id": member_id, "name": name, "discord_user_name": discord_user_name}}
#ユーザーデータがなかったら(未登録の場合)
else:
return {"result": 1, "about": "user_data_not_found"}
except Exception as error:
print("ユーザーの登録状況を調査中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally:
cursor.close()
def stop(self, **kwargs):
# bot側のfstopを基に
try:
pc_number = kwargs["pc_number"]
cursor = self.db.cursor()
cursor.execute("SELECT * FROM pc_list WHERE pc_number = %s", (pc_number,))
pc_list_record = cursor.fetchall()
pc_using_member_id = pc_list_record[0][1]
pc_password_hash = pc_list_record[0][2]
if pc_using_member_id == None:
return {"result": 1, "about": "not_used"}
else:
cursor.execute("UPDATE pc_list SET using_member_id = NULL WHERE pc_number = %s", (pc_number,))
if pc_password_hash == None:
pass
else:
cursor.execute("UPDATE pc_list SET password_hash = NULL WHERE pc_number = %s", (pc_number,))
cursor.execute("SELECT * FROM pc_usage_history WHERE member_id = %s AND pc_number = %s ORDER BY id DESC LIMIT 1", (pc_using_member_id, pc_number))
pc_usage_history_record = cursor.fetchall()
pc_usage_history_record_id = pc_usage_history_record[0][0]
keyboard_number = pc_usage_history_record[0][3]
mouse_number = pc_usage_history_record[0][4]
if keyboard_number == None:
pass
else:
# keyboard_listの使用中ユーザーを消す
cursor.execute("UPDATE keyboard_list SET using_member_id = NULL WHERE keyboard_number = %s", (keyboard_number,))
if mouse_number == None:
pass
else:
# mouse_listの使用中ユーザーを消す
cursor.execute("UPDATE mouse_list SET using_member_id = NULL WHERE mouse_number = %s", (mouse_number,))
cursor.execute("UPDATE pc_usage_history SET end_use_time = clock_timestamp() WHERE id = %s", (pc_usage_history_record_id,))
self.db.commit()
return {"result": 0, "about": "ok"}
except Exception as error:
print("停止処理中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally:
cursor.close()
def register(self, **kwargs):
try:
cursor = self.db.cursor()
pc_number = int(kwargs["pc_number"])
pc_uuid = str(kwargs["pc_uuid"])
cursor.execute("SELECT pc_number FROM pc_list WHERE pc_number = %s", (pc_number,))
pc_record_number_source = cursor.fetchall()
if pc_record_number_source == []:
pc_token = self.token_generate(36)
master_password = self.master_password_generate(16)
master_password_hash = self.hash_genarate(master_password)
cursor.execute("INSERT INTO pc_list (pc_number, pc_uuid, pc_token, master_password) VALUES (%s, %s, %s, %s)", (pc_number, pc_uuid, pc_token, master_password))
self.db.commit()
return {"result": 0, "about": "ok", "output_dict": {"pc_token": pc_token, "master_password": master_password, "master_password_hash": master_password_hash}}
else:
cursor.execute("SELECT pc_uuid FROM pc_list WHERE pc_number = %s", (pc_number,))
pc_record_uuid_source = cursor.fetchall()
pc_record_uuid = pc_record_uuid_source[0][0]
if pc_record_uuid == None:
pc_token = self.token_generate(36)
master_password = self.master_password_generate(16)
master_password_hash = self.hash_genarate(master_password)
cursor.execute("UPDATE pc_list SET pc_uuid = %s, pc_token = %s, master_password = %s WHERE pc_number = %s", (pc_uuid, pc_token, master_password, pc_number))
self.db.commit()
return {"result": 0, "about": "ok", "output_dict": {"pc_token": pc_token, "master_password": master_password, "master_password_hash": master_password_hash}}
else:
return {"result": 1, "about": "exist"}
except Exception as error:
print("PCの登録処理中にエラーが発生しました。\nエラー内容")
print(str(error.__class__.__name__))
print(str(error.args))
print(str(error))
return {"result": 1, "about": "error"}
finally:
cursor.close()
app = Flask(__name__, static_folder="./resource/")
auth = Auth(server_config["db"]["host"], server_config["db"]["db_name"], server_config["db"]["port"], server_config["db"]["username"], server_config["db"]["password"])
@app.route('/register', methods=['POST'])
def register():
pc_number = int(request.json.get('pc_number'))
pc_uuid = str(request.json.get('pc_uuid'))
onetime_password = str(request.json.get('onetime'))
if os.path.isfile(onetime_config_path):
with open(onetime_config_path, "r") as r:
onetime_config = json.load(r)
if onetime_password == onetime_config["onetime"]["pc_register"]["password"]:
register_result = auth.register(pc_number=pc_number, pc_uuid=pc_uuid)
if register_result["result"] == 0:
pc_token = register_result["output_dict"]["pc_token"]
master_password = register_result["output_dict"]["master_password"]
master_password_hash = register_result["output_dict"]["master_password_hash"]
onetime_config["onetime"]["pc_register"]["current_count"] += 1
if onetime_config["onetime"]["pc_register"]["current_count"] == onetime_config["onetime"]["pc_register"]["max_count"]:
onetime_config["onetime"]["pc_register"]["password"] = None
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok', 'pc_token': pc_token, 'master_password': master_password, 'master_password_hash': master_password_hash}), 200
else:
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok', 'pc_token': pc_token, 'master_password': master_password, 'master_password_hash': master_password_hash}), 200
elif register_result["result"] == 1:
if register_result["about"] == "exist":
return jsonify({'message': 'exist'}), 400
else:
return jsonify({'message': 'damedesu'}), 500
else:
return jsonify({'message': 'damedesu'}), 401
else:
return jsonify({'message': 'damedesu'}), 401
@app.route('/verify', methods=['POST'])
def verify():
pc_number = int(request.json.get('pc_number'))
password_hash = request.json.get('password')
pc_uuid = request.json.get('pc_uuid')
pc_token = request.json.get('pc_token')
devices = request.json.get('devices')
print(str(pc_number) + "の認証処理を開始...")
pc_auth = auth.check(pc_number=pc_number, password_hash=password_hash, pc_uuid=pc_uuid, pc_token=pc_token, device_list=devices)
if pc_auth["result"] == 0:
auth.delete(pc_number)
#auth.device_use_register(pc_number=pc_number, keyboard_number=pc_auth["output_dict"]["keyboard_number"], mouse_number=pc_auth["output_dict"]["mouse_number"])
print(str(pc_number) + "の認証処理は成功しました.")
return jsonify({'message': 'ok'}), 200
elif pc_auth["result"] == 1:
if pc_auth["about"] == "incorrect_password":
print(str(pc_number) + "の認証処理はパスワードが正しくないため失敗しました.")
return jsonify({'message': 'incorrect_password'}), 401
else:
print(str(pc_number) + "の認証処理は失敗しました.")
return jsonify({'message': 'damedesu'}), 500
@app.route('/stop', methods=['POST'])
def stop():
pc_number = int(request.json.get('pc_number'))
pc_uuid = str(request.json.get('pc_uuid'))
pc_token = str(request.json.get('pc_token'))
print(str(pc_number) + "の使用停止処理を開始...")
pc_auth = auth.check(pc_number=pc_number, pc_uuid=pc_uuid, pc_token=pc_token)
if pc_auth["result"] == 0:
pc_stop = auth.stop(pc_number=pc_number)
if pc_stop["result"] == 0:
print(str(pc_number) + "の使用停止処理は成功しました.")
return jsonify({'message': 'ok'}), 200
else:
print(str(pc_number) + "の使用停止処理は失敗しました.")
return jsonify({'message': 'error'}), 500
else:
return jsonify({'message': 'damedesu'}), 401
@app.route('/device_register', methods=['POST'])
def device_register():
onetime_password = str(request.json.get('onetime'))
mode = str(request.json.get('mode'))
number = int(request.json.get('number'))
device_instance_path = str(request.json.get('device_instance_path'))
device_name = str(request.json.get('device_name'))
if os.path.isfile(onetime_config_path):
with open(onetime_config_path, "r") as r:
onetime_config = json.load(r)
if onetime_password == onetime_config["onetime"]["device_register"]:
if mode == "keyboard":
print("キーボードの登録処理を開始...")
device_register = auth.device_register(mode="keyboard", number=number, device_instance_path=device_instance_path, device_name=device_name)
if device_register["result"] == 0:
print(f"キーボード {number} 番の登録処理は成功しました.")
onetime_config["onetime"]["device_register"]["current_count"] += 1
if onetime_config["onetime"]["device_register"]["current_count"] == onetime_config["onetime"]["device_register"]["max_count"]:
onetime_config["onetime"]["device_register"] = None
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok'}), 200
else:
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok'}), 200
else:
print(f"キーボード {number} 番の登録処理は失敗しました.")
return jsonify({'message': 'error'}), 500
elif mode == "mouse":
print("マウスの登録処理を開始...")
device_register = auth.device_register(mode="mouse", number=number, device_instance_path=device_instance_path, device_name=device_name)
if device_register["result"] == 0:
print(f"マウス {number} 番の登録処理は成功しました.")
onetime_config["onetime"]["device_register"]["current_count"] += 1
if onetime_config["onetime"]["device_register"]["current_count"] == onetime_config["onetime"]["device_register"]["max_count"]:
onetime_config["onetime"]["device_register"] = None
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok'}), 200
else:
with open(onetime_config_path, "w") as w:
json.dump(onetime_config, w, indent=4)
return jsonify({'message': 'ok'}), 200
else:
print(f"マウス {number} 番の登録処理は失敗しました.")
return jsonify({'message': 'error'}), 500
else:
return jsonify({'message': 'damedesu'}), 401
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000, debug=False)

672
dislocker_client.py Normal file
View file

@ -0,0 +1,672 @@
import os
import json
import tkinter.messagebox
import customtkinter
from winotify import Notification, audio
import keyboard
import subprocess
import requests
import hashlib
import string
import random
import tkinter
import threading
import sys
import shutil
import uuid
import time
import win32com.client
import pythoncom
from PIL import Image
app_name = "Dislocker"
dislocker_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(dislocker_dir)
sp_startupinfo = subprocess.STARTUPINFO()
sp_startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
sp_startupinfo.wShowWindow = subprocess.SW_HIDE
resource_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "resource")
config_dir_path = "./config/"
client_config_path = config_dir_path + "client.json"
if not os.path.isfile(client_config_path):
if not os.path.isdir(config_dir_path):
os.mkdir(config_dir_path)
client_config = {
"initial": True,
"auth_host_url": "http://localhost",
"pc_number": 1,
"master_password_hash": "",
"testing": False,
"eraser": True,
"erase_data": {
"example": {
"process_name": "example.exe",
"dir_path": "example"
}
},
"pc_uuid": "",
"pc_token": "",
"hard_lock": False
}
elif os.path.isfile(client_config_path):
with open(client_config_path, "r") as r:
client_config = json.load(r)
def get_input_devices():
str_computer = "."
obj_wmi_service = win32com.client.Dispatch("WbemScripting.SWbemLocator")
obj_swem_services = obj_wmi_service.ConnectServer(str_computer, "root\\cimv2")
col_items = obj_swem_services.ExecQuery("Select * from Win32_PnPEntity where PNPDeviceID like 'HID%'")
input_devices = []
for obj_item in col_items:
input_devices.append({
"device_id": obj_item.DeviceID,
"PNPDeviceID": obj_item.PNPDeviceID,
"Description": obj_item.Description,
"device_name": obj_item.Name,
"Manufacturer": obj_item.Manufacturer,
"Service": obj_item.Service,
"FriendlyName": obj_item.Name, # デバイスとプリンターで表示される名前
"device_instance_path": obj_item.DeviceID # デバイスインスタンスパス
})
return input_devices
def device_register(**kwargs):
onetime = str(kwargs["onetime"])
mode = str(kwargs["mode"])
number = int(kwargs["number"])
device_instance_path = str(kwargs["device_instance_path"])
device_name = str(kwargs["device_name"])
device_register_json = {
"number": number,
"device_instance_path": device_instance_path,
"device_name": device_name,
"mode": mode,
"onetime": onetime
}
register_url = client_config["auth_host_url"] + "/device_register"
responce = requests.post(register_url, json=device_register_json)
if responce.status_code == 200:
print("デバイスの登録に成功しました。")
return {"result": 0, "about": "ok"}
elif responce.status_code == 401:
print("認証に失敗しました。")
return {"result": 1, "about": "auth_failed"}
else:
print("内部エラーによりデバイスの登録に失敗しました。")
return {"result": 1, "about": "error"}
def master_password_gen():
numbers = string.digits # (1)
password = ''.join(random.choice(numbers) for _ in range(10)) # (2)
password_hash = hashlib.sha256(password.encode()).hexdigest()
result = {"password": password, "password_hash": password_hash}
return result
def init(**kwargs):
task_exist = subprocess.run('tasklist /fi "IMAGENAME eq dislocker_client.exe"', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
if 'dislocker_client.exe' in task_exist.stdout:
task_count = task_exist.stdout.count("dislocker_client.exe")
if task_count == 1:
pass
else:
return 1
if client_config["initial"] == True:
pc_uuid = uuid.uuid4()
client_config["pc_uuid"] = str(pc_uuid)
if "pc_number" in kwargs:
client_config["pc_number"] = int(kwargs["pc_number"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nPC番号が指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
return 2
if "onetime" in kwargs:
onetime = str(kwargs["onetime"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
return 2
if "host_url" in kwargs:
client_config["auth_host_url"] = str(kwargs["host_url"])
else:
pass
register_url = client_config["auth_host_url"] + "/register"
register_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(pc_uuid),
"onetime": onetime
}
responce = requests.post(register_url, json=register_json)
if responce.status_code == 200:
print("PCの情報が登録されました。")
responce_json = responce.json()
pc_token = str(responce_json["pc_token"])
master_password_hash = str(responce_json["master_password_hash"])
master_password = str(responce_json["master_password"])
client_config["pc_token"] = pc_token
client_config["master_password_hash"] = master_password_hash
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 初回起動を検出", message=f"初回起動のようです。\nマスターパスワードを記録しておいてください。\nBotが起動している場合は、管理者がDiscordから確認することもできます。\n\n{master_password}\n\n")
client_config["initial"] = False
with open(client_config_path, "w") as w:
json.dump(client_config, w, indent=4)
return 2
elif responce.status_code == 400:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\n指定されたPC番号には既に登録されています。PCを置き換えたい場合は、Botから登録を解除してください。")
return 2
elif responce.status_code == 401:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが間違っている可能性があります。")
return 2
elif responce.status_code == 500:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nサーバーで内部エラーが発生しています。")
return 2
else:
return 0
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
if client_config["testing"] == True:
pass
else:
self.block_taskmgr()
self.block_key()
shutup_window = keyboard.press_and_release('windows + d')
self.attributes('-fullscreen', True)
self.attributes('-topmost', True)
if client_config["hard_lock"] == True:
exit_explorer = subprocess.run('taskkill /f /im explorer.exe', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
if exit_explorer.returncode == 0:
pass
else:
signout_session = subprocess.run('shutdown /l /f /t 3', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
error_msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 初回処理のエラー", message=f"初回処理の実行にエラーが発生しました。\n自動的にサインアウトされます。")
self.title(f"{app_name} | ロック中")
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
self.frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.frame.grid(row=0, column=0, sticky='nsew')
lock = Lock()
def exit(self):
self.unlock_taskmgr()
if client_config["hard_lock"] == True:
self.wake_explorer()
else:
pass
self.toast()
self.destroy()
def block_key(self):
block_keys = ['ctrl', 'alt', 'windows', 'shift', 'delete']
for i in block_keys:
keyboard.block_key(i)
def block_taskmgr(self):
block = subprocess.run('reg add HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v DisableTaskMgr /t REG_DWORD /d 1 /f', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
print(block)
def unlock_taskmgr(self):
unlock = subprocess.run('reg delete HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System /v DisableTaskMgr /f', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
print(unlock)
def wake_explorer(self):
wake_explorer = subprocess.Popen('explorer', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
def toast(self):
success = Notification(
app_id='Dislocker',
title='ご協力ありがとうございます!',
msg='パスワード認証に成功しました。\n現在使われたパスワードは削除されます。',
icon=resource_path + r'\success.png'
)
success.set_audio(audio.Default, loop=False)
success.show()
def handler_close(self):
pass
class Lock(customtkinter.CTkToplevel):
def __init__(self):
super().__init__()
if client_config["testing"] == True:
self.title(f'{app_name} | PC番号 {client_config["pc_number"]} | テストモード')
else:
self.title(f'{app_name} | PC番号 {client_config["pc_number"]} | ロックされています')
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
self.window_width = 760
self.window_height = 320
self.screen_width = self.winfo_screenwidth()
self.screen_height = self.winfo_screenheight()
self.center_x = int(self.screen_width/2 - self.window_width/2)
self.center_y = int(self.screen_height/2 - self.window_height/2)
self.geometry(f"{str(self.window_width)}x{str(self.window_height)}+{str(self.center_x)}+{str(self.center_y)}")
self.resizable(height=False, width=False)
self.attributes('-topmost', True)
self.grab_set()
self.lift()
self.protocol("WM_DELETE_WINDOW", self.handler_close)
self.emoji_font = customtkinter.CTkFont(family="Segoe UI Emoji", size=32)
self.title_font = customtkinter.CTkFont(family="meiryo", size=32, weight="bold")
self.pc_number_font = customtkinter.CTkFont(family="meiryo", size=64, weight="bold")
self.title_small_font = customtkinter.CTkFont(family="meiryo", size=16)
self.general_font = customtkinter.CTkFont(family="meiryo", size=18)
self.general_small_font = customtkinter.CTkFont(family="meiryo", size=12)
self.textbox_font = customtkinter.CTkFont(family="meiryo", size=14)
self.button_font = customtkinter.CTkFont(family="meiryo", size=14)
self.cover_img = customtkinter.CTkImage(light_image=Image.open(resource_path + '\\cover\\dislocker_light.png'), dark_image=Image.open(resource_path + '\\cover\\dislocker_dark.png'), size=(160, 320))
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=6)
self.cover_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.cover_frame.grid(row=0, column=0, padx=0, pady=0, sticky="nsew", rowspan=4)
self.cover_img_label = customtkinter.CTkLabel(self.cover_frame, image=self.cover_img, text="")
self.cover_img_label.grid(row=0, column=0, padx=0, pady=0, sticky="w")
self.msg_title_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.msg_title_frame.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")
#self.icon_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text='😎', font=self.emoji_font, justify="left")
#self.icon_title_1.grid(row=0, column=0, padx=10, sticky="w")
self.msg_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'ちょっと待って!! ', font=self.title_font, justify="left")
self.msg_title_1.grid(row=0, column=0, padx=10, sticky="we")
self.pc_number_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'PC番号 | {client_config["pc_number"]}', font=self.title_font, justify="right")
self.pc_number_title_1.grid(row=0, column=1, padx=10, sticky="e")
self.msg_title_2 = customtkinter.CTkLabel(self.msg_title_frame, text="本当にあなたですか?", font=self.title_small_font, justify="left")
self.msg_title_2.grid(row=1, column=0, padx=10, columnspan=2, sticky="w")
self.msg_subtitle_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.msg_subtitle_frame.grid(row=1, column=1, padx=10, pady=0, sticky="nsew")
self.msg_subtitle_frame.grid_columnconfigure(0, weight=1)
self.msg_subtitle_1 = customtkinter.CTkLabel(self.msg_subtitle_frame, text='サインインするには、Discordを開き、Dislockerから送信された\nパスワードを入力してください。', font=self.general_font, justify="left")
self.msg_subtitle_1.grid(row=0, column=0, padx=10, sticky="w")
self.msg_subtitle_2 = customtkinter.CTkLabel(self.msg_subtitle_frame, text='※ パスワードの有効期限は発行から5分間です。期限が切れた場合は、もう一度発行してください。', font=self.general_small_font, justify="left")
self.msg_subtitle_2.grid(row=1, column=0, padx=10, sticky="w")
self.input_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.input_frame.grid(row=2, column=1, padx=10, pady=0, sticky="nsew")
self.input_frame.columnconfigure(0, weight=1)
self.password_entry = customtkinter.CTkEntry(self.input_frame, placeholder_text='パスワード', show='*', font=self.textbox_font)
self.password_entry.grid(row=0, column=0, padx=10, sticky="ew")
self.password_entry.bind("<Return>", self.auth_start_ev)
self.button_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.button_frame.grid(row=3, column=1, padx=10, pady=10, sticky="nsew")
self.button_frame.columnconfigure(0, weight=3)
self.button_frame.columnconfigure(1, weight=1)
self.button_frame.columnconfigure(2, weight=1)
self.signin_button = customtkinter.CTkButton(self.button_frame, text='サインイン', command=self.auth_start, font=self.button_font)
self.signin_button.grid(row=0, column=2, padx=10, sticky="e")
self.signout_button = customtkinter.CTkButton(self.button_frame, text='サインアウト', command=self.signout, font=self.button_font)
self.signout_button.grid(row=0, column=1, padx=10, sticky="e")
self.help_button = customtkinter.CTkButton(self.button_frame, text='ヘルプ', command=self.help_dummy, font=self.button_font)
self.help_button.grid(row=0, column=0, padx=10, sticky="w")
self.keyboard_listener_thread = threading.Thread(target=self.keyboard_listener)
self.keyboard_listener_thread.daemon = True
self.keyboard_listener_thread.start()
def help_wakeup(self):
help = Help()
def keyboard_listener(self):
keyboard.add_hotkey('ctrl+shift+q', self.exit)
def hash_genarate(self, source):
hashed = hashlib.sha256(source.encode())
return hashed.hexdigest()
def auth_start(self):
auth_thread = threading.Thread(target=self.auth)
auth_thread.daemon = True
auth_thread.start()
def auth_start_ev(self, event):
auth_thread = threading.Thread(target=self.auth)
auth_thread.daemon = True
auth_thread.start()
def button_disable(self):
self.help_button.configure(state="disabled", fg_color="gray")
self.signin_button.configure(state="disabled", fg_color="gray")
self.signout_button.configure(state="disabled", fg_color="gray")
def button_enable(self):
self.help_button.configure(state="normal", fg_color="#3c8dd0")
self.signin_button.configure(state="normal", fg_color="#3c8dd0")
self.signout_button.configure(state="normal", fg_color="#3c8dd0")
def get_input_devices(self):
try:
pythoncom.CoInitialize()
str_computer = "."
obj_wmi_service = win32com.client.Dispatch("WbemScripting.SWbemLocator")
obj_swem_services = obj_wmi_service.ConnectServer(str_computer, "root\\cimv2")
col_items = obj_swem_services.ExecQuery("Select * from Win32_PnPEntity where PNPDeviceID like 'HID%'")
input_devices = []
for obj_item in col_items:
input_devices.append({
"device_id": obj_item.DeviceID,
"PNPDeviceID": obj_item.PNPDeviceID,
"Description": obj_item.Description,
"device_name": obj_item.Name,
"Manufacturer": obj_item.Manufacturer,
"Service": obj_item.Service,
"FriendlyName": obj_item.Name, # デバイスとプリンターで表示される名前
"device_instance_path": obj_item.DeviceID # デバイスインスタンスパス
})
pythoncom.CoUninitialize()
return input_devices
except pythoncom.com_error as e:
print("Error:", e)
return []
def auth(self):
self.button_disable()
password = str(self.password_entry.get())
#devices = self.get_input_devices()
devices = []
if len(password) == 10:
print("マスターパスワードで認証を試行します。")
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
if client_config["master_password_hash"] == master_password_hash:
print("マスターパスワードで認証しました。")
self.exit()
else:
print("マスターパスワードで認証できませんでした。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
self.button_enable()
self.deiconify()
print("認証サーバーにアクセスします。")
auth_url = client_config["auth_host_url"] + "/verify"
auth_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"]),
"devices": devices,
"password": self.hash_genarate(str(self.password_entry.get()))
}
try:
responce = requests.post(auth_url, json=auth_json)
if responce.status_code == 200:
print("認証サーバー経由で認証しました。")
self.exit()
elif responce.status_code == 401:
print("認証サーバー経由での認証に失敗しました。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
self.button_enable()
self.deiconify()
elif responce.status_code == 500:
print("内部エラーにより認証に失敗しました。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 内部エラー", message=f"サーバーの内部エラーにより認証に失敗しました。")
self.msg_subtitle_1.configure(text='内部エラーにより認証に失敗しました。 ')
self.button_enable()
self.deiconify()
except:
print("認証サーバーにアクセスできません。マスターパスワードで認証を試行します。")
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
if client_config["master_password_hash"] == master_password_hash:
print("マスターパスワードで認証しました。")
self.exit()
else:
print("マスターパスワードで認証できませんでした。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | ネットワークエラー", message=f"認証サーバーにアクセスできませんでした。\n続行するには、マスターパスワードを入力してください。")
self.msg_subtitle_1.configure(text='ネットワークエラーが発生しています。\n続行するには、マスターパスワードを入力して下さい。 ')
self.button_enable()
self.deiconify()
def signout(self):
app.unlock_taskmgr()
self.destroy()
signout_command = subprocess.run('shutdown /l /f', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
print(signout_command)
def handler_close(self):
pass
def help_dummy(self):
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ヘルプページは製作途中です。\nDiscordサーバーの指示に従って、認証を進めてください。")
self.deiconify()
def wakeup_shutdown_background(self):
wakeup = subprocess.Popen(f'{dislocker_dir}\\dislocker_client_shutdown.exe', startupinfo=sp_startupinfo)
def exit(self):
try:
self.wakeup_shutdown_background()
except:
pass
self.destroy()
app.exit()
class Help(customtkinter.CTkToplevel):
def __init__(self):
super().__init__()
if client_config["testing"] == True:
self.title(f'{app_name} | ヘルプ | テストモード')
else:
self.title(f'{app_name} | ヘルプ')
self.iconbitmap(default=resource_path + '\\icon\\dislocker.ico')
self.geometry("600x400")
self.resizable(height=False, width=False)
self.attributes('-topmost', True)
self.grab_set()
self.lift()
self.protocol("WM_DELETE_WINDOW", self.handler_close)
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ヘルプページは製作途中です。\nDiscordサーバーの指示に従って、認証を進めてください。")
self.destroy()
def handler_close(self):
self.destroy()
class Stop():
def __init__(self) -> None:
pass
def run(self):
stop_thread = threading.Thread(target=self.stop)
stop_thread.run()
def delete_appdata(self, **kwargs):
process_name = kwargs["process_name"]
dir_path = kwargs["dir_path"]
if not os.path.exists(dir_path):
print(f"エラー: 指定されたディレクトリ {dir_path} が存在しません。")
return 1
i = 0
i_max = 10
result = 1
while i != i_max:
i += 1
try:
# プロセスの終了
subprocess.run(f'taskkill /f /t /im {process_name}', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
print(f"{process_name} を終了しました。")
time.sleep(0.1)
# ディレクトリの削除
shutil.rmtree(dir_path)
if os.path.isdir(dir_path):
pass
else:
print(f"{dir_path} を削除しました。")
result = 0
i = i_max
except subprocess.CalledProcessError as e:
print(f"プロセス終了エラー: {e}")
except PermissionError as e:
print(f"権限エラー: {e}")
except Exception as e:
print("エラーが発生しました。\nエラー内容:")
print(f"エラータイプ: {e.__class__.__name__}")
print(f"エラー引数: {e.args}")
print(f"エラーメッセージ: {str(e)}")
return result
def shutdown(self):
shutdown_command = subprocess.run('shutdown /s /f /t 0', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
def stop(self):
print("停止処理を実行。")
if client_config["eraser"] == True:
appdata_local = os.path.expandvars("%LOCALAPPDATA%")
appdata_roaming = os.path.expandvars("%APPDATA%")
epic_del = self.delete_appdata(process_name="EpicGamesLauncher.exe", dir_path=f"{appdata_local}\\EpicGamesLauncher\\Saved")
chrome_del = self.delete_appdata(process_name="chrome.exe", dir_path=f"{appdata_local}\\Google\\Chrome\\User Data")
discord_del = self.delete_appdata(process_name="discord.exe", dir_path=f"{appdata_roaming}\\discord")
steam_del = self.delete_appdata(process_name="steam.exe", dir_path=f"{appdata_local}\\Steam")
ea_del = self.delete_appdata(process_name="EADesktop.exe", dir_path=f"{appdata_local}\\Electronic Arts")
riot_del = self.delete_appdata(process_name="RiotClientServices.exe", dir_path=f"{appdata_local}\\Riot Games\\Riot Client")
else:
print("削除処理をスキップ。")
stop_url = client_config["auth_host_url"] + "/stop"
stop_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"])
}
try:
responce = requests.post(stop_url, json=stop_json)
if responce.status_code == 200:
print("停止処理は成功しました。")
elif responce.status_code == 401:
print("認証に失敗しました。")
else:
print("内部エラーにより停止処理に失敗しました。")
except:
print("ネットワークエラーにより停止処理に失敗しました。")
finally:
self.shutdown()
if __name__ == '__main__':
args = sys.argv
if len(args) >= 2:
if args[1] == "stop":
init_result = init()
if init_result == 1:
print("多重起動を検出。")
elif init_result == 2:
pass
else:
stop = Stop()
stop.run()
elif args[1] == "setup":
if len(args) == 4:
init_result = init(pc_number=args[2], onetime=args[3])
elif len(args) == 5:
init_result = init(pc_number=args[2], onetime=args[3], host_url=args[4])
else:
print("引数エラー。")
error_msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 引数エラー", message=f"引数が多すぎるか、少なすぎます。\n引数がPC番号、ワンタイムパスワード、ホストURLの順で正しく指定されているか確認してください。")
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
pass
elif args[1] == "deviceregister":
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
mode = input('登録するデバイスはキーボードとマウスのどちらですか?(keyboard/mouse): ')
input_devices = get_input_devices()
i = 0
for device in input_devices:
print(f"{str(i + 1)} 番目 | デバイス名: {device['device_name']} \n製造元: {device['Manufacturer']} \nデバイスインスタンスパス: {device['device_instance_path']}")
print("-" * 20)
i += 1
device_num = input('どのデバイスを登録しますか?番号で指定してください: ')
device_register_num = input('そのデバイスは何番目のデバイスとして登録しますか?番号で指定してください: ')
onetime = input('ワンタイムパスワードを入力してください: ')
device_register_result = device_register(onetime=onetime, mode=mode, number=int(device_register_num), device_instance_path=input_devices[int(device_num) - 1]["device_instance_path"], device_name=input_devices[int(device_num) - 1]["device_name"])
if device_register_result["result"] == 0:
print("登録されました。")
elif device_register_result["result"] == 1:
if device_register_result["about"] == "auth_failed":
print("認証に失敗しました。")
else:
print("エラーが発生しました。")
elif args[1] == "guitest":
init_result = init()
client_config["testing"] = True
app = App()
app.mainloop()
else:
print("引数エラー。")
else:
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
app = App()
app.protocol("WM_DELETE_WINDOW", app.handler_close)
app.mainloop()

View file

@ -0,0 +1,166 @@
import os
import json
import tkinter.messagebox
import tkinter
import subprocess
import requests
import tkinter
import sys
import time
import shutil
app_name = "Dislocker"
dislocker_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(dislocker_dir)
sp_startupinfo = subprocess.STARTUPINFO()
sp_startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
sp_startupinfo.wShowWindow = subprocess.SW_HIDE
resource_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "resource")
config_dir_path = "./config/"
client_config_path = config_dir_path + "client.json"
if not os.path.isfile(client_config_path):
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | エラー", message=f"設定ファイルが正しく構成されていません。")
elif os.path.isfile(client_config_path):
with open(client_config_path, "r") as r:
client_config = json.load(r)
def init(**kwargs):
task_exist = subprocess.run('tasklist /fi "IMAGENAME eq dislocker_shutdown.exe"', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
if 'dislocker_shutdown.exe' in task_exist.stdout:
task_count = task_exist.stdout.count("dislocker_shutdown.exe")
if task_count == 1:
pass
else:
return 1
if client_config["initial"] == True:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | エラー", message=f"設定ファイルが正しく構成されていません。")
return 2
else:
return 0
class App(tkinter.Tk):
def __init__(self):
super().__init__()
if client_config["testing"] == True:
pass
else:
pass
self.geometry("160x100")
self.title(f"{app_name} | シャットダウンを監視")
self.iconbitmap(default=resource_path + '\\icon\\dislocker_shutdown.ico')
self.protocol("WM_SAVE_YOURSELF", self.handler_close)
self.frame = tkinter.Frame(self)
self.frame.grid(row=0, column=0, sticky='nsew')
self.withdraw()
def delete_appdata(self, **kwargs):
process_name = kwargs["process_name"]
dir_path = kwargs["dir_path"]
if not os.path.exists(dir_path):
print(f"エラー: 指定されたディレクトリ {dir_path} が存在しません。")
return 1
i = 0
i_max = 10
result = 1
while i != i_max:
i += 1
try:
# プロセスの終了
subprocess.run(f'taskkill /f /t /im {process_name}', startupinfo=sp_startupinfo, stdout=subprocess.PIPE, text=True)
print(f"{process_name} を終了しました。")
time.sleep(0.1)
# ディレクトリの削除
shutil.rmtree(dir_path)
if os.path.isdir(dir_path):
pass
else:
print(f"{dir_path} を削除しました。")
result = 0
i = i_max
except subprocess.CalledProcessError as e:
print(f"プロセス終了エラー: {e}")
except PermissionError as e:
print(f"権限エラー: {e}")
except Exception as e:
print("エラーが発生しました。\nエラー内容:")
print(f"エラータイプ: {e.__class__.__name__}")
print(f"エラー引数: {e.args}")
print(f"エラーメッセージ: {str(e)}")
def handler_close(self):
print("停止処理を実行。")
stop_url = client_config["auth_host_url"] + "/stop"
stop_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"])
}
try:
responce = requests.post(stop_url, json=stop_json)
if responce.status_code == 200:
print("停止処理は成功しました。")
elif responce.status_code == 401:
print("認証に失敗しました。")
else:
print("内部エラーにより停止処理に失敗しました。")
except:
print("ネットワークエラーにより停止処理に失敗しました。")
print("データ削除を実行。")
try:
if client_config["eraser"] == True:
appdata_local = os.path.expandvars("%LOCALAPPDATA%")
appdata_roaming = os.path.expandvars("%APPDATA%")
epic_del = self.delete_appdata(process_name="EpicGamesLauncher.exe", dir_path=f"{appdata_local}\\EpicGamesLauncher\\Saved")
chrome_del = self.delete_appdata(process_name="chrome.exe", dir_path=f"{appdata_local}\\Google\\Chrome\\User Data")
discord_del = self.delete_appdata(process_name="discord.exe", dir_path=f"{appdata_roaming}\\discord")
steam_del = self.delete_appdata(process_name="steam.exe", dir_path=f"{appdata_local}\\Steam")
ea_del = self.delete_appdata(process_name="EADesktop.exe", dir_path=f"{appdata_local}\\Electronic Arts")
riot_del = self.delete_appdata(process_name="RiotClientServices.exe", dir_path=f"{appdata_local}\\Riot Games\\Riot Client")
"""
for i in client_config['erase_data'].keys():
if i == 'example':
pass
else:
erase_process_name = client_config['erase_data'][i]['process_name']
erase_dir_path = client_config['erase_data'][i]['dir_path']
erase_del = self.delete_appdata(process_name=erase_process_name, dir_path=erase_dir_path)
"""
else:
print("削除処理をスキップ。")
except:
print("データ削除に失敗しました。")
self.destroy()
def icon(self):
self.iconify()
if __name__ == '__main__':
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
app = App()
app.mainloop()

View file

@ -0,0 +1,441 @@
import os
import json
import tkinter.messagebox
import customtkinter
import subprocess
import requests
import hashlib
import string
import random
import tkinter
import threading
import sys
import shutil
import uuid
import time
app_name = "Dislocker"
dislocker_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(dislocker_dir)
resource_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "resource")
config_dir_path = "./config/"
client_config_path = config_dir_path + "client.json"
if not os.path.isfile(client_config_path):
if not os.path.isdir(config_dir_path):
os.mkdir(config_dir_path)
client_config = {
"initial": 1,
"auth_host_url": "http://localhost",
"pc_number": 1,
"master_password_hash": "",
"testing": 0,
"eraser": 1,
"pc_uuid": "",
"pc_token": ""
}
elif os.path.isfile(client_config_path):
with open(client_config_path, "r") as r:
client_config = json.load(r)
def master_password_gen():
numbers = string.digits # (1)
password = ''.join(random.choice(numbers) for _ in range(10)) # (2)
password_hash = hashlib.md5(password.encode()).hexdigest()
result = {"password": password, "password_hash": password_hash}
return result
def init(**kwargs):
if client_config["initial"] == 1:
pc_uuid = uuid.uuid4()
client_config["pc_uuid"] = str(pc_uuid)
if "pc_number" in kwargs:
client_config["pc_number"] = int(kwargs["pc_number"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nPC番号が指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
return 2
if "onetime" in kwargs:
onetime = str(kwargs["onetime"])
else:
tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが指定されていません。1個目の引数にPC番号、2個目の引数にワンタイムパスワードを指定して、もう一度お試しください。")
return 2
register_url = client_config["auth_host_url"] + "/register"
register_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(pc_uuid),
"onetime": onetime
}
responce = requests.post(register_url, json=register_json)
if responce.status_code == 200:
print("PCの情報が登録されました。")
responce_json = responce.json()
pc_token = str(responce_json["pc_token"])
client_config["pc_token"] = pc_token
master_password = master_password_gen()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 初回起動を検出", message=f"初回起動のようです。\nマスターパスワードを記録しておいてください。\nこれ以降二度と表示されることはないでしょう。\n\n{master_password["password"]}\n\nまた、認証先サーバーの接続先を指定してください。ロックを解除できなくなります。")
client_config["master_password_hash"] = master_password["password_hash"]
client_config["initial"] = 0
with open(client_config_path, "w") as w:
json.dump(client_config, w, indent=4)
return 2
else:
msgbox = tkinter.messagebox.showerror(title=f"{app_name} | 登録時にエラー", message=f"登録時にエラーが発生しました。\nワンタイムパスワードが間違っている可能性があります。")
return 2
else:
return 0
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
self.title(f"{app_name} | ロック中")
if client_config["testing"] == 1:
pass
else:
self.attributes('-fullscreen', True)
self.attributes('-topmost', True)
self.frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.frame.grid(row=0, column=0, sticky='nsew')
lock = Lock()
def exit(self):
self.unlock_taskmgr()
self.toast()
self.destroy()
def handler_close(self):
pass
class Lock(customtkinter.CTkToplevel):
def __init__(self):
super().__init__()
if client_config["testing"] == 1:
self.title(f'{app_name} | PC番号 {client_config["pc_number"]} | テストモード')
else:
self.title(f'{app_name} | PC番号 {client_config["pc_number"]} | ロックされています')
self.window_width = 600
self.window_height = 320
self.screen_width = self.winfo_screenwidth()
self.screen_height = self.winfo_screenheight()
self.center_x = int(self.screen_width/2 - self.window_width/2)
self.center_y = int(self.screen_height/2 - self.window_height/2)
self.geometry(f"{str(self.window_width)}x{str(self.window_height)}+{str(self.center_x)}+{str(self.center_y)}")
self.resizable(height=False, width=False)
self.attributes('-topmost', True)
self.grab_set()
self.lift()
self.protocol("WM_DELETE_WINDOW", self.handler_close)
self.emoji_font = customtkinter.CTkFont(family="Noto Color Emoji", size=32)
self.title_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=32, weight="bold")
self.pc_number_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=64, weight="bold")
self.title_small_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=16)
self.general_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=18)
self.general_small_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=12)
self.textbox_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=14)
self.button_font = customtkinter.CTkFont(family="Noto Sans CJK JP", size=14)
self.msg_title_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.msg_title_frame.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
self.icon_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text='😎', font=self.emoji_font, justify="left")
self.icon_title_1.grid(row=0, column=0, padx=10, sticky="w")
self.msg_title_1 = customtkinter.CTkLabel(self.msg_title_frame, text=f'ちょっと待って!! PC番号 | {client_config["pc_number"]}', font=self.title_font, justify="left")
self.msg_title_1.grid(row=0, column=1, padx=10, sticky="w")
self.msg_title_2 = customtkinter.CTkLabel(self.msg_title_frame, text="本当にあなたですか?", font=self.title_small_font, justify="left")
self.msg_title_2.grid(row=1, column=1, padx=10, sticky="w")
self.msg_subtitle_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.msg_subtitle_frame.grid(row=1, column=0, padx=10, pady=10, sticky="nsew")
self.msg_subtitle_frame.grid_columnconfigure(0, weight=1)
self.msg_subtitle_1 = customtkinter.CTkLabel(self.msg_subtitle_frame, text='サインインするには、Discordのダイレクトメッセージに送信された\nパスワードを入力してください。', font=self.general_font, justify="left")
self.msg_subtitle_1.grid(row=0, column=0, padx=10, sticky="ew")
self.msg_subtitle_2 = customtkinter.CTkLabel(self.msg_subtitle_frame, text='※ パスワードの有効期限は23:59までです。', font=self.general_small_font, justify="left")
self.msg_subtitle_2.grid(row=1, column=0, padx=10, sticky="w")
self.input_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.input_frame.grid(row=2, column=0, padx=10, pady=10, sticky="nsew")
self.input_frame.columnconfigure(0, weight=1)
self.password_entry = customtkinter.CTkEntry(self.input_frame, placeholder_text='パスワード', show='*', font=self.textbox_font)
self.password_entry.grid(row=0, column=0, padx=10, sticky="ew")
self.password_entry.bind("<Return>", self.auth_start_ev)
self.button_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color='transparent')
self.button_frame.grid(row=3, column=0, padx=10, pady=10, sticky="nsew")
self.button_frame.columnconfigure(0, weight=3)
self.button_frame.columnconfigure(1, weight=1)
self.button_frame.columnconfigure(2, weight=1)
self.signin_button = customtkinter.CTkButton(self.button_frame, text='サインイン', command=self.auth_start, font=self.button_font)
self.signin_button.grid(row=0, column=2, padx=10, sticky="e")
self.signout_button = customtkinter.CTkButton(self.button_frame, text='サインアウト', command=self.signout, font=self.button_font)
self.signout_button.grid(row=0, column=1, padx=10, sticky="e")
self.help_button = customtkinter.CTkButton(self.button_frame, text='ヘルプ', command=self.help_dummy, font=self.button_font)
self.help_button.grid(row=0, column=0, padx=10, sticky="w")
def help_wakeup(self):
help = Help()
def hash_genarate(self, source):
hashed = hashlib.md5(source.encode())
return hashed.hexdigest()
def auth_start(self):
auth_thread = threading.Thread(target=self.auth)
auth_thread.daemon = True
auth_thread.start()
def auth_start_ev(self, event):
auth_thread = threading.Thread(target=self.auth)
auth_thread.daemon = True
auth_thread.start()
def button_disable(self):
self.help_button.configure(state="disabled", fg_color="gray")
self.signin_button.configure(state="disabled", fg_color="gray")
self.signout_button.configure(state="disabled", fg_color="gray")
def button_enable(self):
self.help_button.configure(state="normal", fg_color="#3c8dd0")
self.signin_button.configure(state="normal", fg_color="#3c8dd0")
self.signout_button.configure(state="normal", fg_color="#3c8dd0")
def auth(self):
self.button_disable()
password = str(self.password_entry.get())
if len(password) == 10:
print("マスターパスワードで認証を試行します。")
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
if client_config["master_password_hash"] == master_password_hash:
print("マスターパスワードで認証しました。")
self.exit()
else:
print("マスターパスワードで認証できませんでした。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
self.button_enable()
self.deiconify()
print("認証サーバーにアクセスします。")
auth_url = client_config["auth_host_url"] + "/verify"
auth_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"]),
"password": self.hash_genarate(str(self.password_entry.get()))
}
try:
responce = requests.post(auth_url, json=auth_json)
if responce.status_code == 200:
print("認証サーバー経由で認証しました。")
self.exit()
else:
print("認証サーバー経由での認証に失敗しました。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 誤ったパスワード", message=f"パスワードが間違っています!")
self.msg_subtitle_1.configure(text='パスワードが間違っています! ')
self.button_enable()
self.deiconify()
except:
print("認証サーバーにアクセスできません。マスターパスワードで認証を試行します。")
master_password_hash = self.hash_genarate(str(self.password_entry.get()))
if client_config["master_password_hash"] == master_password_hash:
print("マスターパスワードで認証しました。")
self.exit()
else:
print("マスターパスワードで認証できませんでした。")
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | ネットワークエラー", message=f"認証サーバーにアクセスできませんでした。\n続行するには、マスターパスワードを入力してください。")
self.msg_subtitle_1.configure(text='ネットワークエラーが発生しています。\n続行するには、マスターパスワードを入力して下さい。 ')
self.button_enable()
self.deiconify()
def signout(self):
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ログアウトは未実装です。")
self.deiconify()
def handler_close(self):
pass
def help_dummy(self):
self.withdraw()
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ヘルプページは製作途中です。\nDiscordサーバーの指示に従って、認証を進めてください。")
self.deiconify()
def exit(self):
self.destroy()
app.exit()
class Help(customtkinter.CTkToplevel):
def __init__(self):
super().__init__()
if client_config["testing"] == 1:
self.title(f'{app_name} | ヘルプ | テストモード')
else:
self.title(f'{app_name} | ヘルプ')
self.geometry("600x400")
self.resizable(height=False, width=False)
self.attributes('-topmost', True)
self.grab_set()
self.lift()
self.protocol("WM_DELETE_WINDOW", self.handler_close)
msgbox = tkinter.messagebox.showinfo(title=f"{app_name} | 未実装", message=f"ヘルプページは製作途中です。\nDiscordサーバーの指示に従って、認証を進めてください。")
self.destroy()
def handler_close(self):
self.destroy()
class Stop():
def __init__(self) -> None:
pass
def run(self):
print("停止処理を実行中...")
stop_thread = threading.Thread(target=self.stop)
stop_thread.run()
def delete_appdata(self, **kwargs):
process_name = kwargs["process_name"]
dir_path = kwargs["dir_path"]
if not os.path.exists(dir_path):
print(f"エラー: 指定されたディレクトリ {dir_path} が存在しません。")
return 1
try:
# プロセスの終了
subprocess.run(['taskkill', '/f', '/t', '/im', process_name])
print(f"{process_name} を終了しました。")
time.sleep(0.1)
# ディレクトリの削除
i = 1
ic = 0
while i == 1:
shutil.rmtree(dir_path)
if os.path.isdir(dir_path):
ic += 1
if ic == 10:
i = 0
else:
i = 0
print(f"{dir_path} を削除しました。")
return 0
except subprocess.CalledProcessError as e:
print(f"プロセス終了エラー: {e}")
return 1
except PermissionError as e:
print(f"権限エラー: {e}")
return 1
except Exception as error:
print("エラーが発生しました。\nエラー内容:")
print(f"エラータイプ: {error.__class__.__name__}")
print(f"エラー引数: {error.args}")
print(f"エラーメッセージ: {str(error)}")
return 1
def shutdown(self):
shutdown_command = subprocess.run(['shutdown', '/s', '/t', '1'])
def stop(self):
print("停止処理を実行。")
if client_config["eraser"] == 1:
#appdata_local = os.path.expandvars("%LOCALAPPDATA%")
#appdata_roaming = os.path.expandvars("%APPDATA%")
#epic_del = app.delete_appdata(process_name="EpicGamesLauncher.exe", dir_path=f"{appdata_local}\\EpicGamesLauncher\\Saved")
#chrome_del = app.delete_appdata(process_name="chrome.exe", dir_path=f"{appdata_local}\\Google\\Chrome\\User Data")
#discord_del = app.delete_appdata(process_name="discord.exe", dir_path=f"{appdata_roaming}\\discord")
#steam_del = app.delete_appdata(process_name="steam.exe", dir_path=f"{appdata_local}\\Steam")
#ea_del = app.delete_appdata(process_name="EADesktop.exe", dir_path=f"{appdata_local}\\Electronic Arts")
#riot_del = app.delete_appdata(process_name="RiotClientServices.exe", dir_path=f"{appdata_local}\\Riot Games\\Riot Client")
pass
else:
print("削除処理をスキップ。")
stop_url = client_config["auth_host_url"] + "/stop"
stop_json = {
"pc_number": int(client_config["pc_number"]),
"pc_uuid": str(client_config["pc_uuid"]),
"pc_token": str(client_config["pc_token"])
}
try:
responce = requests.post(stop_url, json=stop_json)
if responce.status_code == 200:
print("停止処理は成功しました。")
elif responce.status_code == 401:
print("認証に失敗しました。")
tkinter.messagebox.showwarning(title=f"{app_name} | エラー", message=f"認証に失敗しました。\nDiscordサーバーの指示に従って、停止処理を自身で行ってください。")
else:
print("内部エラーにより停止処理に失敗しました。")
result_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | エラー", message=f"内部エラーにより停止処理に失敗しました。\nDiscordサーバーの指示に従って、停止処理を自身で行ってください。")
except:
print("ネットワークエラーにより停止処理に失敗しました。")
result_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | エラー", message=f"ネットワークエラーにより停止処理に失敗しました。\nDiscordサーバーの指示に従って、停止処理を自身で行ってください。")
finally:
self.shutdown()
if __name__ == '__main__':
args = sys.argv
if len(args) >= 2:
if args[1] == "stop":
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"もう終了処理を行っています。\nPCがシャットダウンするまで、もう少しお待ちください。")
elif init_result == 2:
pass
else:
stop = Stop()
stop.run()
elif args[1] == "setup":
init_result = init(pc_number=args[2], onetime=args[3])
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
pass
else:
print("引数エラー。")
else:
init_result = init()
if init_result == 1:
warning_msgbox = tkinter.messagebox.showwarning(title=f"{app_name} | 多重起動エラー", message=f"すでに {app_name} は実行されています。\n正常に起動しない場合は、既に起動しているプロセスを終了してから、もう一度起動してみてください。")
elif init_result == 2:
pass
else:
app = App()
app.protocol("WM_DELETE_WINDOW", app.handler_close)
app.mainloop()

1605
dislocker_slash.py Normal file

File diff suppressed because it is too large Load diff

1
docs/pyinstaller.txt Normal file
View file

@ -0,0 +1 @@
pyinstaller .\dislocker_client.py --noconsole --icon .\resource\icon\dislocker.ico --add-data ".\resource:resource"

View file

@ -1,13 +1,11 @@
# ログイン
psql -U suti7 -d dislocker
CREATE TABLE user
(user_id INTEGER PRIMARY KEY NOT NULL,
discord_id INTEGER NOT NULL,
discord_username VARCHAR(32) NOT NULL,
PRIMARY KEY (user_id));
CREATE TABLE club_member (id SERIAL NOT NULL, name VARCHAR(30) NOT NULL, discord_username VARCHAR(32) NOT NULL, discord_userid VARCHAR(18) NOT NULL, PRIMARY KEY (id));
CREATE TABLE pc_list (pc_number INTEGER NOT NULL, using_user_id INTEGER, password_hash VARCHAR(32), PRIMARY KEY (pc_number), FOREIGN KEY (using_user_id) REFERENCES club_member(id));
CREATE TABLE pc_usage_history (id SERIAL NOT NULL, member_id INTEGER NOT NULL, pc_number INTEGER NOT NULL, device_number INTEGER NOT NULL, start_use_time TIMESTAMP NOT NULL, end_use_time TIMESTAMP, use_detail VARCHAR(30), PRIMARY KEY (id), FOREIGN KEY (member_id) REFERENCES club_member(id), FOREIGN KEY (pc_number) REFERENCES pc_list(pc_number));
CREATE TABLE user_list (user_id INTEGER NOT NULL, discord_username VARCHAR(32) NOT NULL, discord_userid INTEGER NOT NULL, PRIMARY KEY (user_id));
# PC登録
INSERT INTO pc_list (pc_number) VALUES (PC番号をいれる);
# テーブルを作る
CREATE TABLE web_auth (id SERIAL, username VARCHAR(10) NOT NULL, password VARCHAR(32) NOT NULL, PRIMARY KEY(id));
INSERTのとき文字列はシングルクォーテーションで囲む

4
requirements.txt Normal file
View file

@ -0,0 +1,4 @@
discord.py
psycopg2-binary
openpyxl
flask

5
requirements_client.txt Normal file
View file

@ -0,0 +1,5 @@
customtkinter
winotify
keyboard
requests
pywin32

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
resource/icon/dislocker.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

BIN
resource/icon/png/128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
resource/icon/png/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

BIN
resource/icon/png/256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
resource/icon/png/32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
resource/icon/png/512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

BIN
resource/icon/png/64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
resource/success.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

10
resource/verify.html Normal file
View file

@ -0,0 +1,10 @@
<html>
<head>
<title>Verify</title>
</head>
<body>
<h1>だめです</h1>
</body>
</html>

16
script/download.cmd Normal file
View file

@ -0,0 +1,16 @@
@echo off
set dir=%~dp0
cd %dir%
set download_url=""
curl -L %download_url% -o %dir%\dislocker_client.zip
mkdir %dir%\temp_ds
tar -xf %dir%\dislocker_client.zip -C %dir%\temp_ds
mkdir C:\ProgramData\Dislocker
xcopy /e %dir%\temp_ds C:\ProgramData\Dislocker
rmdir /s /q %dir%\temp_ds
del %dir%\dislocker_client.zip
C:\ProgramData\Dislocker\setup.cmd

26
script/setup.cmd Normal file
View file

@ -0,0 +1,26 @@
@echo off
set dir=%~dp0
cd %dir%
schtasks /create /tn "Dislocker_Client" /tr "%dir%dislocker_client.exe" /sc onlogon /ru "%USERNAME%" /rl highest /f
if %ERRORLEVEL% == 0 (
echo タスクスケジューラーの設定は完了しました。
)
if %ERRORLEVEL% == 1 (
echo タスクスケジューラーの設定でエラーが発生しました。
)
Cscript "%dir%shortcut.vbs" "%dir%" "%dir%" "dislocker_client.exe" "stop" "シャットダウンと停止処理"
if %ERRORLEVEL% == 0 (
Cscript "%dir%shortcut.vbs" "%USERPROFILE%/Desktop" "%dir%" "dislocker_client.exe" "stop" "シャットダウンと停止処理"
echo ショートカットの作成は完了しました。
)
if %ERRORLEVEL% == 1 (
echo ショートカットの作成でエラーが発生しました。
)
set /P pc_number=PC番号を入力
set /P onetime=ワンタイムパスワードを入力
set /P host_url=ホストURLを入力 (必要な場合のみ)
start %dir%dislocker_client.exe setup %pc_number% %onetime% %host_url%
pause

8
script/shortcut.vbs Normal file
View file

@ -0,0 +1,8 @@
Set WshShell = CreateObject("WScript.Shell")
Set args = Wscript.Arguments
Set Shortcut = WshShell.CreateShortcut(args(0) & "\シャットダウンと終了処理.lnk")
Shortcut.TargetPath = args(1) & args(2)
Shortcut.Arguments = args(3)
Shortcut.WorkingDirectory = args(1)
Shortcut.Save
WScript.Quit(0)

19
script/update.cmd Normal file
View file

@ -0,0 +1,19 @@
@echo off
set dir=%~dp0
cd %dir%
set update_package_path="0"
set /P update_package_path=アップデート元のzipファイルのパスを入力 :
if %update_package_path%=="0" (set update_package_path=C:%HOMEPATH%\Downloads\dislocker_client_latest.zip)
set dislocker_dir_path="0"
set /P dislocker_dir_path=Dislockerのディレクトリのパスを入力 :
if %dislocker_dir_path%=="0" (set dislocker_dir_path=C:\Dislocker)
mkdir %dir%\temp_ds
tar -xf %update_package_path% -C %dir%\temp_ds
rmdir /s /q %dislocker_dir_path%\_internal
mkdir %dislocker_dir_path%\_internal
xcopy /e %dir%\temp_ds\_internal %dislocker_dir_path%\_internal
xcopy /Y %dir%\temp_ds\dislocker_client.exe %dislocker_dir_path%\dislocker_client.exe
rmdir /s /q %dir%\temp_ds
echo アップデート完了。Defenderの警告を消すため、一度起動しておいてください。
pause

24
script/update_online.cmd Normal file
View file

@ -0,0 +1,24 @@
@echo off
set dir=%~dp0
cd %dir%
set download_url=""
taskkill /f /t /im dislocker_client_shutdown.exe
taskkill /f /t /im dislocker_client.exe
curl -L %download_url% -o %dir%\dislocker_client.zip
mkdir %dir%\temp_ds\
tar -xf %dir%\dislocker_client.zip -C %dir%\temp_ds\
rmdir /s /q C:\ProgramData\Dislocker\_internal\
xcopy /e %dir%\temp_ds\_internal\ C:\ProgramData\Dislocker\_internal\
xcopy /Y %dir%\temp_ds\dislocker_client.exe C:\ProgramData\Dislocker\dislocker_client.exe
xcopy /Y %dir%\temp_ds\dislocker_client_shutdown.exe C:\ProgramData\Dislocker\dislocker_client_shutdown.exe
xcopy /Y %dir%\temp_ds\shortcut.vbs C:\ProgramData\Dislocker\shortcut.vbs
xcopy /Y %dir%\temp_ds\setup.cmd C:\ProgramData\Dislocker\setup.cmd
rmdir /s /q %dir%\temp_ds\
del %dir%\dislocker_client.zip
echo アップデート完了。Defenderの警告を消すため、一度起動しておいてください。
pause

34
test.py
View file

@ -1,34 +0,0 @@
# インストールした discord.py を読み込む
import discord
import secrets
import string
# 接続に必要なオブジェクトを生成
client = discord.Client()
# 起動時に動作する処理
@client.event
async def on_ready():
# 起動したらターミナルにログイン通知が表示される
print('ログインしました')
# メッセージ受信時に動作する処理
@client.event
async def on_message(message):
# メッセージ送信者がBotだった場合は無視する
if message.author.bot:
return
# 「/neko」と発言したら「にゃーん」が返る処理
if message.content == '/neko':
await message.channel.send('にゃーん')
if message.content == '/password':
await message.channel.send(get_random_password_string(4))
def get_random_password_string(length):
pass_chars = string.ascii_letters + string.digits
password = ''.join(secrets.choice(pass_chars) for x in range(length))
return password
# Botの起動とDiscordサーバーへの接続
client.run('MTI0NzA1Mzc1NzUxOTM2NDEyNw.Gh5gIt.kz1acBMxphff9mEZLLWrEdEoVD4RJwgBW5P14o')