trymsae.memeshell.psm1
|
# MemeShell Module Load Message $messageFile = Join-Path $PSScriptRoot "templates\texts\load-messages.b64" if (Test-Path $messageFile) { try { $base64Content = Get-Content $messageFile -Raw $bytes = [Convert]::FromBase64String($base64Content.Trim()) $decodedText = [System.Text.Encoding]::UTF8.GetString($bytes) $messages = $decodedText -split "`r?`n" | Where-Object { $_.Trim() -ne "" } $randomMessage = $messages | Get-Random Write-Host "█▀▄▀█ █▀▀ █▀▄▀█ █▀▀ █▀ █░█ █▀▀ █░░ █░░ █░░ █▀█ ▄▀█ █▀▄ █▀▀ █▀▄" -ForegroundColor Magenta Write-Host "█░▀░█ ██▄ █░▀░█ ██▄ ▄█ █▀█ ██▄ █▄▄ █▄▄ █▄▄ █▄█ █▀█ █▄▀ ██▄ █▄▀" -ForegroundColor Magenta Write-host "$($randomMessage)" } catch { Write-host "Catch these hands" } } function Disable-MemePrompt { <# .SYNOPSIS Disables the MemeShell prompt and restores your original prompt .DESCRIPTION Returns your prompt to its pre-MemeShell state .EXAMPLE Disable-MemePrompt #> [CmdletBinding()] param( [Parameter(Position = 0, Mandatory = $false)] [switch]$noBitches ) begin { # No bitches? } process { if ($script:OriginalPrompt) { # Restore the original prompt function, boring. Set-Content -Path function:global:prompt -Value $script:OriginalPrompt } else { Write-Warning "No original prompt found. noob." } } end { if ($script:OriginalPrompt) { Write-Host "MemePrompt disabled. normalcy restored, back to work I guess?" -ForegroundColor Green } } } function Enable-MemePrompt { <# .SYNOPSIS Enables the highly sophisticated meme prompt. .DESCRIPTION Replaces your boring prompt with some dank lines. .PARAMETER allTheBitches Specifies all the bitches you aint getting son. .EXAMPLE PS> Enable-MemePrompt #> [CmdletBinding()] param( [Parameter(Position = 0, Mandatory = $false)] [switch]$allTheBitches ) begin { # Save the current prompt before replacing it (save the actual function definition) if (-not $script:OriginalPrompt) { $script:OriginalPrompt = ${function:prompt} } # Load prompt messages from file (the juice) $promptMessagesFile = Join-Path $PSScriptRoot "templates\texts\prompt-messages.b64" if (Test-Path $promptMessagesFile) { try { $base64Content = Get-Content $promptMessagesFile -Raw $bytes = [Convert]::FromBase64String($base64Content.Trim()) $decodedText = [System.Text.Encoding]::UTF8.GetString($bytes) $script:MemePrompts = $decodedText -split "`r?`n" | Where-Object { $_.Trim() -ne "" } } catch { # catch these hands (fallback to basics) $script:MemePrompts = @("DANK", "BASED", "no cap", "fr fr", "💀", "skill issue") } } else { # if file missing, lmao $script:MemePrompts = @("DANK", "BASED", "no cap", "fr fr", "💀", "skill issue") } # Dank colors for the prompt $script:MemeColors = @( "Cyan" "Magenta" "Yellow" "Green" "Red" "Blue" "DarkCyan" "DarkMagenta" "DarkYellow" "DarkGreen" "DarkRed" ) } process { # Create the meme prompt function with random colors function global:prompt { $prefix = $script:MemePrompts | Get-Random $color1 = $script:MemeColors | Get-Random $color2 = $script:MemeColors | Get-Random $Path = (Get-Location).Path $Path = $Path -replace "C:\\Users\\$($env:USERNAME)\\", "~\" # lmao if ((Get-Random -Minimum 1 -Maximum 35) -eq 1) { try { $soundsPath = Join-Path $PSScriptRoot "templates\sounds" if (Test-Path $soundsPath) { $sounds = Get-ChildItem $soundsPath -Filter "*.wav" -ErrorAction SilentlyContinue if ($sounds) { $randomSound = $sounds | Get-Random $player = New-Object System.Media.SoundPlayer $player.SoundLocation = $randomSound.FullName $player.Play() } } } catch { # catch these hands } } # Chaos level selection (doing ur mom) $chaosRoll = Get-Random -Minimum 1 -Maximum 11 if ($chaosRoll -le 5) { # 50% - Classic format Write-Host "[" -ForegroundColor $color2 -NoNewline Write-Host $prefix -ForegroundColor $color1 -NoNewline Write-Host "] - " -ForegroundColor $color2 -NoNewline Write-Host "(" -ForegroundColor $color2 -NoNewline Write-Host "$($Path)" -NoNewline Write-Host ")" -ForegroundColor $color2 -NoNewline Write-host " >" -NoNewline } elseif ($chaosRoll -eq 6) { # ALL CAPS SCREAMING Write-Host "[" -ForegroundColor $color2 -NoNewline Write-Host $prefix.ToUpper() -ForegroundColor $color1 -NoNewline Write-Host "] - " -ForegroundColor $color2 -NoNewline Write-Host "(" -ForegroundColor $color2 -NoNewline Write-Host "$($Path)" -NoNewline Write-Host ")" -ForegroundColor $color2 -NoNewline Write-host " >>>" -NoNewline } elseif ($chaosRoll -eq 7) { # dubblare $prefix2 = $script:MemePrompts | Get-Random Write-Host "[[" -ForegroundColor $color2 -NoNewline Write-Host $prefix -ForegroundColor $color1 -NoNewline Write-Host "] [" -ForegroundColor $color2 -NoNewline Write-Host $prefix2 -ForegroundColor $color1 -NoNewline Write-Host "]] " -ForegroundColor $color2 -NoNewline Write-Host "$($Path)" -NoNewline Write-host " $" -NoNewline } elseif ($chaosRoll -eq 8) { # no brackets? Write-Host $prefix -ForegroundColor $color1 -NoNewline Write-Host " @ " -ForegroundColor $color2 -NoNewline Write-Host "$($Path)" -NoNewline Write-host " #" -NoNewline } elseif ($chaosRoll -eq 9) { # spin it around bby Write-Host "]" -ForegroundColor $color2 -NoNewline Write-Host $prefix -ForegroundColor $color1 -NoNewline Write-Host "[ - " -ForegroundColor $color2 -NoNewline Write-Host ")" -ForegroundColor $color2 -NoNewline Write-Host "$($Path)" -NoNewline Write-Host "(" -ForegroundColor $color2 -NoNewline Write-host " <" -NoNewline } else { # lmao symbols $symbols = @(">", ">>", ">>>", "$", "#", "λ", "~>", "=>", "!!") $randomSymbol = $symbols | Get-Random Write-Host "{" -ForegroundColor $color2 -NoNewline Write-Host $prefix -ForegroundColor $color1 -NoNewline Write-Host "} " -ForegroundColor $color2 -NoNewline Write-Host "$($Path)" -NoNewline Write-host " $randomSymbol" -NoNewline } return " " } } end { Write-Host "MemePrompt enabled. your terminal is now " -ForegroundColor Cyan -NoNewline Write-Host "cooked" -ForegroundColor Red -NoNewline Write-Host "." -ForegroundColor Cyan } } function Get-Emoji { <# .SYNOPSIS This function adds emojis to clipboard or directly in console .DESCRIPTION This function is a quick access for my personal used emojis. Now with more chaos. .PARAMETER emoji Specify your emoji or use 'random' for surprise .EXAMPLE PS > Get-Emoji -emoji dunno ¯\_(ツ)_/¯ | yoinked to clipboard .EXAMPLE PS > emoji random (╯°□°)╯︵ ┻━┻ | yoinked to clipboard #> [alias('emoji')] [CmdletBinding()] param ( [parameter(Position = 0, Mandatory = $true)] [ValidateSet('dunno', 'beer', 'surfsup', 'tableflip', 'unflip', 'shrug', 'lenny', 'disapprove', 'dealwithit', 'rage', 'happy', 'sad', 'dead', 'fire', 'skull', 'eyes', 'point', 'think', 'clap', 'pray', 'facepalm', 'knife', 'gun', 'bomb', 'sus', 'based', 'cringe', 'yeet', 'oof', 'bruh', 'fr', 'nocap', 'ratio', 'random')] [string]$emoji, [parameter(Position = 1, Mandatory = $false)] [switch]$noClipboard ) begin { # the juice $emojiMap = @{ # the classics 'dunno' = '¯\_(ツ)_/¯' 'shrug' = '¯\_(ツ)_/¯' 'tableflip' = '(╯°□°)╯︵ ┻━┻' 'unflip' = '┬─┬ノ( º _ ºノ)' 'lenny' = '( ͡° ͜ʖ ͡°)' 'disapprove' = 'ಠ_ಠ' 'dealwithit' = '(⌐■_■)' 'rage' = '(ノಠ益ಠ)ノ彡┻━┻' 'happy' = '(◕‿◕)' 'sad' = '(╥﹏╥)' 'dead' = '(✖╭╮✖)' 'think' = '(¬‿¬)' # the mojis 'beer' = '🍺' 'surfsup' = '🤙' 'fire' = '🔥' 'skull' = '💀' 'eyes' = '👀' 'point' = '👉' 'clap' = '👏' 'pray' = '🙏' 'facepalm' = '🤦' 'knife' = '🔪' 'gun' = '🔫' 'bomb' = '💣' # the unwelcomed 'sus' = 'ඞ' 'based' = '🗿' 'cringe' = '😬' 'yeet' = '༼ つ ◕_◕ ༽つ' 'oof' = 'F' 'bruh' = '🤨' 'fr' = '💯' 'nocap' = '🧢' 'ratio' = '📉' } # rando if ($emoji -eq 'random') { $randomKey = $emojiMap.Keys | Where-Object { $_ -ne 'random' } | Get-Random $output = $emojiMap[$randomKey] $emoji = $randomKey # for display purposes } else { $output = $emojiMap[$emoji] } } process { # no bitches? } end { if ( -not $noClipboard ) { Set-Clipboard -Value $output Write-Host "$($output) | " -NoNewline Write-Host "plastered to clipboard" -ForegroundColor Green -NoNewline Write-Host " [$emoji]" -ForegroundColor DarkGray } else { Write-Host $output } } } function New-Meme { <# .SYNOPSIS Generates dank memes from local templates .DESCRIPTION Creates memes by adding text to local image templates. Classic top/bottom text format or use -manual for GUI mode. .PARAMETER template Template image name (without extension) from templates\pictures folder .PARAMETER topText Text for the top of the meme (classic format) .PARAMETER bottomText Text for the bottom of the meme (classic format) .PARAMETER manual Opens GUI window for manual meme creation (more control, less speed) .PARAMETER noClipboard Don't copy the result to clipboard (just save it) .EXAMPLE PS > New-Meme -template "drake" -topText "Using APIs" -bottomText "Local images with PowerShell" Meme created and mogged to clipboard .EXAMPLE PS > meme -manual Opens GUI for manual meme crafting #> [alias('meme')] [CmdletBinding()] param ( [parameter(Position = 0, Mandatory = $false)] [string]$template, [parameter(Position = 1, Mandatory = $false)] [string]$topText, [parameter(Position = 2, Mandatory = $false)] [string]$bottomText, [parameter(Position = 3, Mandatory = $false)] [switch]$manual, [parameter(Position = 4, Mandatory = $false)] [switch]$noClipboard, [parameter(Position = 5, Mandatory = $false)] [ValidateRange(2, 6)] [int]$TextLines = 2 ) begin { # Load the juice (System.Drawing for image manipulation) Add-Type -AssemblyName System.Drawing Add-Type -AssemblyName System.Windows.Forms # get templates folder $picturesPath = Join-Path $PSScriptRoot "templates\pictures" if (-not (Test-Path $picturesPath)) { Write-Error "Templates folder not found at: $picturesPath (no bitches?)" return } # grab all image files $availableTemplates = Get-ChildItem $picturesPath -Include *.jpg,*.jpeg,*.png,*.bmp -Recurse -ErrorAction SilentlyContinue if ($availableTemplates.Count -eq 0) { Write-Error "No templates found in $picturesPath (folder is empty fr)" return } # temp output path $tempPath = [System.IO.Path]::GetTempPath() $outputFile = Join-Path $tempPath "meme_$(Get-Date -Format 'yyyyMMdd_HHmmss').png" } process { # Manual mode (GUI goes hard) if ($manual) { # Calculate form height based on text lines (dynamic sizing fr fr) $textLineHeight = 80 $previewStartY = 90 + ($TextLines * $textLineHeight) + 20 $previewHeight = 250 $buttonY = $previewStartY + $previewHeight + 20 $formHeight = $buttonY + 80 # Create the form (dynamic height based on text lines, wider for X controls) $form = New-Object System.Windows.Forms.Form $form.Text = "MemeShell - Manual Mode 🔥 ($TextLines lines)" $form.Size = New-Object System.Drawing.Size 780, $formHeight $form.StartPosition = "CenterScreen" $form.FormBorderStyle = "FixedDialog" $form.MaximizeBox = $false # Template dropdown $labelTemplate = New-Object System.Windows.Forms.Label $labelTemplate.Location = New-Object System.Drawing.Point 10, 20 $labelTemplate.Size = New-Object System.Drawing.Size 280, 20 $labelTemplate.Text = "Select Template:" $form.Controls.Add($labelTemplate) $comboTemplate = New-Object System.Windows.Forms.ComboBox $comboTemplate.Location = New-Object System.Drawing.Point 10, 45 $comboTemplate.Size = New-Object System.Drawing.Size 740, 25 $comboTemplate.DropDownStyle = "DropDownList" foreach ($tmpl in $availableTemplates) { $comboTemplate.Items.Add($tmpl.BaseName) | Out-Null } if ($comboTemplate.Items.Count -gt 0) { $comboTemplate.SelectedIndex = 0 } $form.Controls.Add($comboTemplate) # Create dynamic text line controls (array-based for flexibility) $textBoxes = @() $numericXControls = @() $numericYControls = @() $checkboxWrapControls = @() $defaultYPositions = @(50, 200, 350, 500, 650, 800) # Default Y positions for up to 6 lines for ($i = 0; $i -lt $TextLines; $i++) { $yPos = 90 + ($i * $textLineHeight) $lineNum = $i + 1 # Text label $labelText = New-Object System.Windows.Forms.Label $labelText.Location = New-Object System.Drawing.Point 10, $yPos $labelText.Size = New-Object System.Drawing.Size 280, 20 $labelText.Text = "Text Line $($lineNum):" $form.Controls.Add($labelText) # Text input $textBox = New-Object System.Windows.Forms.TextBox $textBox.Location = New-Object System.Drawing.Point 10, ($yPos + 25) $textBox.Size = New-Object System.Drawing.Size 380, 25 $textBox.Font = New-Object System.Drawing.Font("Arial", 10) $textBox.Tag = $i # Store index for later reference $form.Controls.Add($textBox) $textBoxes += $textBox # X position label $labelX = New-Object System.Windows.Forms.Label $labelX.Location = New-Object System.Drawing.Point 400, ($yPos + 5) $labelX.Size = New-Object System.Drawing.Size 70, 20 $labelX.Text = "X Position:" $form.Controls.Add($labelX) # X position control (-1 = center, 0+ = absolute position) $numericX = New-Object System.Windows.Forms.NumericUpDown $numericX.Location = New-Object System.Drawing.Point 400, ($yPos + 25) $numericX.Size = New-Object System.Drawing.Size 80, 25 $numericX.Minimum = -1 $numericX.Maximum = 2000 $numericX.Value = -1 # -1 means "center" (auto-calculated) $numericX.Increment = 5 $numericX.Tag = $i $form.Controls.Add($numericX) $numericXControls += $numericX # Y position label $labelY = New-Object System.Windows.Forms.Label $labelY.Location = New-Object System.Drawing.Point 490, ($yPos + 5) $labelY.Size = New-Object System.Drawing.Size 70, 20 $labelY.Text = "Y Position:" $form.Controls.Add($labelY) # Y position control $numericY = New-Object System.Windows.Forms.NumericUpDown $numericY.Location = New-Object System.Drawing.Point 490, ($yPos + 25) $numericY.Size = New-Object System.Drawing.Size 80, 25 $numericY.Minimum = 0 $numericY.Maximum = 2000 $numericY.Value = $defaultYPositions[$i] $numericY.Increment = 5 $numericY.Tag = $i # Store index for later reference $form.Controls.Add($numericY) $numericYControls += $numericY # Center X button (quick reset to center) $buttonCenterX = New-Object System.Windows.Forms.Button $buttonCenterX.Location = New-Object System.Drawing.Point 580, ($yPos + 24) $buttonCenterX.Size = New-Object System.Drawing.Size 75, 25 $buttonCenterX.Text = "Center X" $buttonCenterX.Tag = $i $buttonCenterX.Add_Click({ param($btnSender, $btnEvent) $index = $btnSender.Tag $numericXControls[$index].Value = -1 }) $form.Controls.Add($buttonCenterX) # Auto-wrap checkbox $checkboxWrap = New-Object System.Windows.Forms.CheckBox $checkboxWrap.Location = New-Object System.Drawing.Point 665, ($yPos + 26) $checkboxWrap.Size = New-Object System.Drawing.Size 100, 20 $checkboxWrap.Text = "Auto-wrap" $checkboxWrap.Checked = $true $checkboxWrap.Tag = $i $form.Controls.Add($checkboxWrap) $checkboxWrapControls += $checkboxWrap } # Set initial text for first two lines if provided (backward compatibility) if ($textBoxes.Count -ge 1 -and -not [string]::IsNullOrWhiteSpace($topText)) { $textBoxes[0].Text = $topText } if ($textBoxes.Count -ge 2 -and -not [string]::IsNullOrWhiteSpace($bottomText)) { $textBoxes[1].Text = $bottomText } # Preview box $pictureBox = New-Object System.Windows.Forms.PictureBox $pictureBox.Location = New-Object System.Drawing.Point 10, $previewStartY $pictureBox.Size = New-Object System.Drawing.Size 740, $previewHeight $pictureBox.SizeMode = "Zoom" $pictureBox.BorderStyle = "FixedSingle" $form.Controls.Add($pictureBox) # Live preview update function (the sauce) $updatePreview = { $selectedTemplate = $availableTemplates | Where-Object { $_.BaseName -eq $comboTemplate.SelectedItem } if (-not $selectedTemplate) { return } try { # Dispose previous image if ($pictureBox.Image) { $pictureBox.Image.Dispose() } # Load base template $previewImage = [System.Drawing.Image]::FromFile($selectedTemplate.FullName) $previewBitmap = New-Object System.Drawing.Bitmap($previewImage.Width, $previewImage.Height) $previewGraphics = [System.Drawing.Graphics]::FromImage($previewBitmap) $previewGraphics.DrawImage($previewImage, 0, 0, $previewImage.Width, $previewImage.Height) # Set up text rendering (MAXIMUM QUALITY MODE - matches final output) $previewGraphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit $previewGraphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias $previewGraphics.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality $previewGraphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic # Font setup $previewFontSize = [Math]::Max(24, $previewImage.Width / 15) $previewFont = New-Object System.Drawing.Font("Impact", $previewFontSize, [System.Drawing.FontStyle]::Bold) $previewBrushWhite = [System.Drawing.Brushes]::White $previewPenBlack = New-Object System.Drawing.Pen([System.Drawing.Color]::Black, ($previewFontSize / 12)) $previewPenBlack.LineJoin = [System.Drawing.Drawing2D.LineJoin]::Round # Smooth corners, no artifacts # Helper to draw text with outline and wrapping support (chef's kiss) $drawPreviewText = { param($text, $x, $y, $useXCenter, $enableWrap) if ([string]::IsNullOrWhiteSpace($text)) { return } $upperText = $text.ToUpper() # Check if wrapping is needed $textWidth = $previewGraphics.MeasureString($upperText, $previewFont).Width $maxWidth = $previewImage.Width * 0.9 # Leave 10% margin if ($enableWrap -and $textWidth -gt $maxWidth) { # Split text into words and wrap (the wrapping sauce) $words = $upperText -split ' ' $lines = @() $currentLine = "" foreach ($word in $words) { $testLine = if ($currentLine) { "$currentLine $word" } else { $word } $testWidth = $previewGraphics.MeasureString($testLine, $previewFont).Width if ($testWidth -gt $maxWidth -and $currentLine) { $lines += $currentLine $currentLine = $word } else { $currentLine = $testLine } } if ($currentLine) { $lines += $currentLine } # Draw each line with offset $lineHeight = $previewFontSize * 1.2 $startY = $y - (($lines.Count - 1) * $lineHeight / 2) for ($lineIdx = 0; $lineIdx -lt $lines.Count; $lineIdx++) { $lineY = $startY + ($lineIdx * $lineHeight) $lineX = if ($useXCenter) { $previewImage.Width / 2 } else { $x } $format = New-Object System.Drawing.StringFormat $format.Alignment = if ($useXCenter) { [System.Drawing.StringAlignment]::Center } else { [System.Drawing.StringAlignment]::Near } $format.LineAlignment = [System.Drawing.StringAlignment]::Center $path = New-Object System.Drawing.Drawing2D.GraphicsPath $path.AddString( $lines[$lineIdx], $previewFont.FontFamily, [int]$previewFont.Style, $previewFontSize, (New-Object System.Drawing.PointF($lineX, $lineY)), $format ) $previewGraphics.DrawPath($previewPenBlack, $path) $previewGraphics.FillPath($previewBrushWhite, $path) $path.Dispose() $format.Dispose() } } else { # Single line rendering (classic mode) $finalX = if ($useXCenter) { $previewImage.Width / 2 } else { $x } $format = New-Object System.Drawing.StringFormat $format.Alignment = if ($useXCenter) { [System.Drawing.StringAlignment]::Center } else { [System.Drawing.StringAlignment]::Near } $format.LineAlignment = [System.Drawing.StringAlignment]::Center $path = New-Object System.Drawing.Drawing2D.GraphicsPath $path.AddString( $upperText, $previewFont.FontFamily, [int]$previewFont.Style, $previewFontSize, (New-Object System.Drawing.PointF($finalX, $y)), $format ) $previewGraphics.DrawPath($previewPenBlack, $path) $previewGraphics.FillPath($previewBrushWhite, $path) $path.Dispose() $format.Dispose() } } # Draw all text lines dynamically with X position and wrapping (no cap we looping fr) for ($j = 0; $j -lt $textBoxes.Count; $j++) { if (-not [string]::IsNullOrWhiteSpace($textBoxes[$j].Text)) { $textX = $numericXControls[$j].Value $textY = $numericYControls[$j].Value $useCenter = ($textX -eq -1) $actualX = if ($useCenter) { $previewImage.Width / 2 } else { $textX } $wrapEnabled = $checkboxWrapControls[$j].Checked & $drawPreviewText $textBoxes[$j].Text $actualX $textY $useCenter $wrapEnabled } } # Cleanup and set preview $previewGraphics.Dispose() $previewFont.Dispose() $previewPenBlack.Dispose() $previewImage.Dispose() $pictureBox.Image = $previewBitmap } catch { # catch these hands (fallback to template only) Write-Verbose "Preview update failed: $($_.Exception.Message)" } } # Load initial preview & $updatePreview # Hook up all the events to update preview (live preview goes hard) $comboTemplate.Add_SelectedIndexChanged({ & $updatePreview }) # Hook up events for all text lines dynamically (array gang) for ($k = 0; $k -lt $textBoxes.Count; $k++) { $textBoxes[$k].Add_TextChanged({ & $updatePreview }) $numericXControls[$k].Add_ValueChanged({ & $updatePreview }) $numericYControls[$k].Add_ValueChanged({ & $updatePreview }) $checkboxWrapControls[$k].Add_CheckedChanged({ & $updatePreview }) } # Mouse drag functionality (absolute madness but it works fr fr) $script:isDragging = $false $script:dragTargetIndex = -1 # Index of text line being dragged $script:lastMouseY = 0 $pictureBox.Add_MouseDown({ param($clickSender, $clickEvent) if (-not $pictureBox.Image) { return } # Convert click coordinates to image coordinates (account for zoom) $displayRect = $pictureBox.ClientRectangle # Calculate actual image position in the control (centered with zoom) $imageAspect = $pictureBox.Image.Width / $pictureBox.Image.Height $controlAspect = $displayRect.Width / $displayRect.Height if ($imageAspect -gt $controlAspect) { # Image is wider - fit to width $displayWidth = $displayRect.Width $displayHeight = [int]($displayRect.Width / $imageAspect) $displayX = 0 $displayY = [int](($displayRect.Height - $displayHeight) / 2) } else { # Image is taller - fit to height $displayHeight = $displayRect.Height $displayWidth = [int]($displayRect.Height * $imageAspect) $displayX = [int](($displayRect.Width - $displayWidth) / 2) $displayY = 0 } # Convert mouse coordinates to image coordinates if ($clickEvent.X -lt $displayX -or $clickEvent.X -gt ($displayX + $displayWidth) -or $clickEvent.Y -lt $displayY -or $clickEvent.Y -gt ($displayY + $displayHeight)) { return # Click outside image } $imageX = [int](($clickEvent.X - $displayX) / $displayWidth * $pictureBox.Image.Width) $imageY = [int](($clickEvent.Y - $displayY) / $displayHeight * $pictureBox.Image.Height) # Check if clicking near any text line (50px tolerance, find closest) $closestIndex = -1 $closestDistance = 999999 for ($m = 0; $m -lt $textBoxes.Count; $m++) { # Only check lines with text if ([string]::IsNullOrWhiteSpace($textBoxes[$m].Text)) { continue } $lineY = $numericYControls[$m].Value $distance = [Math]::Abs($imageY - $lineY) if ($distance -lt $closestDistance -and $distance -lt 50) { $closestDistance = $distance $closestIndex = $m } } # Start dragging if we found a nearby text line (that's the vibe - now with X and Y drag support) if ($closestIndex -ge 0) { $script:isDragging = $true $script:dragTargetIndex = $closestIndex $script:lastMouseY = $imageY $pictureBox.Cursor = [System.Windows.Forms.Cursors]::SizeAll } }) $pictureBox.Add_MouseMove({ param($moveSender, $moveEvent) if (-not $script:isDragging -or -not $pictureBox.Image) { return } # Convert to image coordinates (same logic as MouseDown) $displayRect = $pictureBox.ClientRectangle $imageAspect = $pictureBox.Image.Width / $pictureBox.Image.Height $controlAspect = $displayRect.Width / $displayRect.Height if ($imageAspect -gt $controlAspect) { $displayWidth = $displayRect.Width $displayHeight = [int]($displayRect.Width / $imageAspect) $displayX = 0 $displayY = [int](($displayRect.Height - $displayHeight) / 2) } else { $displayHeight = $displayRect.Height $displayWidth = [int]($displayRect.Height * $imageAspect) $displayX = [int](($displayRect.Width - $displayWidth) / 2) $displayY = 0 } $imageX = [int](($moveEvent.X - $displayX) / $displayWidth * $pictureBox.Image.Width) $imageY = [int](($moveEvent.Y - $displayY) / $displayHeight * $pictureBox.Image.Height) # Clamp to image bounds $imageX = [Math]::Max(0, [Math]::Min($imageX, $pictureBox.Image.Width)) $imageY = [Math]::Max(0, [Math]::Min($imageY, $pictureBox.Image.Height)) # Update both X and Y numeric controls (this triggers preview update) if ($script:dragTargetIndex -ge 0 -and $script:dragTargetIndex -lt $numericYControls.Count) { # Only update X if it's not set to center (-1) if ($numericXControls[$script:dragTargetIndex].Value -ne -1) { $numericXControls[$script:dragTargetIndex].Value = $imageX } $numericYControls[$script:dragTargetIndex].Value = $imageY } }) $pictureBox.Add_MouseUp({ param($upSender, $upEvent) if ($script:isDragging) { $script:isDragging = $false $script:dragTargetIndex = -1 $pictureBox.Cursor = [System.Windows.Forms.Cursors]::Default } }) # Generate button $buttonGenerate = New-Object System.Windows.Forms.Button $buttonGenerate.Location = New-Object System.Drawing.Point 10, $buttonY $buttonGenerate.Size = New-Object System.Drawing.Size 740, 40 $buttonGenerate.Text = "Generate Meme (no cap) 🔥" $buttonGenerate.Font = New-Object System.Drawing.Font("Arial", 11, [System.Drawing.FontStyle]::Bold) $buttonGenerate.Add_Click({ $script:manualTemplate = $comboTemplate.SelectedItem # Collect all text lines, positions, and settings directly to arrays (no ArrayList nonsense) $script:manualTextLines = @() $script:manualXPositions = @() $script:manualYPositions = @() $script:manualWrapSettings = @() for ($n = 0; $n -lt $textBoxes.Count; $n++) { $script:manualTextLines += [string]$textBoxes[$n].Text $script:manualXPositions += [int]$numericXControls[$n].Value $script:manualYPositions += [int]$numericYControls[$n].Value $script:manualWrapSettings += [bool]$checkboxWrapControls[$n].Checked } $form.DialogResult = [System.Windows.Forms.DialogResult]::OK $form.Close() }) $form.Controls.Add($buttonGenerate) # Show form $result = $form.ShowDialog() # Cleanup if ($pictureBox.Image) { $pictureBox.Image.Dispose() } $form.Dispose() if ($result -eq [System.Windows.Forms.DialogResult]::OK) { $template = $script:manualTemplate # Use script-level arrays directly (no conversion nonsense that breaks everything) # Check if we have any non-blank text (filter out empties) $hasNonBlankText = $false for ($idx = 0; $idx -lt $script:manualTextLines.Count; $idx++) { if (-not [string]::IsNullOrWhiteSpace($script:manualTextLines[$idx])) { $hasNonBlankText = $true break } } # Set flags for later use $useMultiLineMode = $hasNonBlankText # Backward compatibility: set topText/bottomText from first 2 lines for classic fallback if ($script:manualTextLines.Count -ge 1 -and -not [string]::IsNullOrWhiteSpace($script:manualTextLines[0])) { $topText = $script:manualTextLines[0] $topTextY = $script:manualYPositions[0] } if ($script:manualTextLines.Count -ge 2 -and -not [string]::IsNullOrWhiteSpace($script:manualTextLines[1])) { $bottomText = $script:manualTextLines[1] $bottomTextY = $script:manualYPositions[1] } } else { Write-Host "Meme generation cancelled (skill issue)" -ForegroundColor Yellow return } } # Validate template if ([string]::IsNullOrWhiteSpace($template)) { Write-Error "No template specified. Use -template or -manual (bruh)" Write-Host "Available templates:" -ForegroundColor Cyan $availableTemplates | ForEach-Object { Write-Host " - $($_.BaseName)" -ForegroundColor Gray } return } # Find the template file $templateFile = $availableTemplates | Where-Object { $_.BaseName -eq $template } | Select-Object -First 1 if (-not $templateFile) { Write-Error "Template '$template' not found (L + ratio)" Write-Host "Available templates:" -ForegroundColor Cyan $availableTemplates | ForEach-Object { Write-Host " - $($_.BaseName)" -ForegroundColor Gray } return } # Load image try { $image = [System.Drawing.Image]::FromFile($templateFile.FullName) $bitmap = New-Object System.Drawing.Bitmap($image.Width, $image.Height) $graphics = [System.Drawing.Graphics]::FromImage($bitmap) $graphics.DrawImage($image, 0, 0, $image.Width, $image.Height) # Set up text rendering (MAXIMUM QUALITY MODE - no more grimy text) $graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit $graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias $graphics.CompositingQuality = [System.Drawing.Drawing2D.CompositingQuality]::HighQuality $graphics.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic # Font setup (Impact-style, bold and thicc) $fontSize = [Math]::Max(24, $image.Width / 15) $font = New-Object System.Drawing.Font("Impact", $fontSize, [System.Drawing.FontStyle]::Bold) $brushWhite = [System.Drawing.Brushes]::White $penBlack = New-Object System.Drawing.Pen([System.Drawing.Color]::Black, ($fontSize / 12)) $penBlack.LineJoin = [System.Drawing.Drawing2D.LineJoin]::Round # Smooth corners, no black streaks # Helper function to draw outlined text with wrapping support (the sauce with extra sauce) $drawOutlinedText = { param($text, $x, $y, $alignment, $enableWrap) if ([string]::IsNullOrWhiteSpace($text)) { return } $upperText = $text.ToUpper() # Check if wrapping is needed $textWidth = $graphics.MeasureString($upperText, $font).Width $maxWidth = $image.Width * 0.9 # Leave 10% margin if ($enableWrap -and $textWidth -gt $maxWidth) { # Split text into words and wrap (wrapping goes hard fr) $words = $upperText -split ' ' $lines = @() $currentLine = "" foreach ($word in $words) { $testLine = if ($currentLine) { "$currentLine $word" } else { $word } $testWidth = $graphics.MeasureString($testLine, $font).Width if ($testWidth -gt $maxWidth -and $currentLine) { $lines += $currentLine $currentLine = $word } else { $currentLine = $testLine } } if ($currentLine) { $lines += $currentLine } # Draw each line with offset (multi-line rendering) $lineHeight = $fontSize * 1.2 $startY = $y - (($lines.Count - 1) * $lineHeight / 2) for ($lineIdx = 0; $lineIdx -lt $lines.Count; $lineIdx++) { $lineY = $startY + ($lineIdx * $lineHeight) $format = New-Object System.Drawing.StringFormat $format.Alignment = $alignment $format.LineAlignment = [System.Drawing.StringAlignment]::Center $path = New-Object System.Drawing.Drawing2D.GraphicsPath $path.AddString( $lines[$lineIdx], $font.FontFamily, [int]$font.Style, $fontSize, (New-Object System.Drawing.PointF($x, $lineY)), $format ) $graphics.DrawPath($penBlack, $path) $graphics.FillPath($brushWhite, $path) $path.Dispose() $format.Dispose() } } else { # Single line rendering (classic mode) $format = New-Object System.Drawing.StringFormat $format.Alignment = $alignment $format.LineAlignment = [System.Drawing.StringAlignment]::Center $path = New-Object System.Drawing.Drawing2D.GraphicsPath $path.AddString( $upperText, $font.FontFamily, [int]$font.Style, $fontSize, (New-Object System.Drawing.PointF($x, $y)), $format ) # Draw black outline (thicc) $graphics.DrawPath($penBlack, $path) # Draw white fill $graphics.FillPath($brushWhite, $path) $path.Dispose() $format.Dispose() } } # Draw text lines (multi-line support with X positioning and wrapping fr fr) if ($useMultiLineMode -and $script:manualTextLines -and $script:manualTextLines.Count -gt 0) { # Manual mode with multiple text lines (using script arrays directly, no conversion bs) for ($p = 0; $p -lt $script:manualTextLines.Count; $p++) { $currentText = $script:manualTextLines[$p] if (-not [string]::IsNullOrWhiteSpace($currentText)) { $textX = $script:manualXPositions[$p] $textY = $script:manualYPositions[$p] $wrapEnabled = $script:manualWrapSettings[$p] # Determine X position and alignment $useCenter = ($textX -eq -1) $finalX = if ($useCenter) { $image.Width / 2 } else { $textX } $alignment = if ($useCenter) { [System.Drawing.StringAlignment]::Center } else { [System.Drawing.StringAlignment]::Near } & $drawOutlinedText $currentText $finalX $textY $alignment $wrapEnabled } } } else { # Classic mode with just top/bottom text (backward compatibility with wrapping enabled) if (-not [string]::IsNullOrWhiteSpace($topText)) { # Use custom Y position if provided (from manual mode), otherwise default if ($topTextY) { $topY = $topTextY } else { $topY = $fontSize } & $drawOutlinedText $topText ($image.Width / 2) $topY ([System.Drawing.StringAlignment]::Center) $true } if (-not [string]::IsNullOrWhiteSpace($bottomText)) { # Use custom Y position if provided (from manual mode), otherwise default if ($bottomTextY) { $bottomY = $bottomTextY } else { $bottomY = $image.Height - ($fontSize * 1.5) } & $drawOutlinedText $bottomText ($image.Width / 2) $bottomY ([System.Drawing.StringAlignment]::Center) $true } } # Save the masterpiece $bitmap.Save($outputFile, [System.Drawing.Imaging.ImageFormat]::Png) # Cleanup (no memory leaks in this house) $graphics.Dispose() $bitmap.Dispose() $image.Dispose() $font.Dispose() $penBlack.Dispose() } catch { Write-Error "Meme generation failed: $($_.Exception.Message) (catch these hands)" return } } end { if (Test-Path $outputFile) { # Copy to clipboard (based) if (-not $noClipboard) { try { $image = [System.Drawing.Image]::FromFile($outputFile) [System.Windows.Forms.Clipboard]::SetImage($image) $image.Dispose() Write-Host "Meme created and " -NoNewline Write-Host "mogged to clipboard" -ForegroundColor Green -NoNewline Write-Host " 🔥" } catch { Write-Warning "Clipboard copy failed (skill issue): $($_.Exception.Message)" } } Write-Host "Saved to: " -NoNewline -ForegroundColor Cyan Write-Host $outputFile -ForegroundColor Gray # Open the meme (optional flex) try { Start-Process $outputFile } catch { # lmao whatever } } else { Write-Error "Output file not created (something broke but we ship anyway)" } } } function New-YoloCommit { <# .SYNOPSIS Generates unhinged but technically valid commit messages .DESCRIPTION Just send a commit message, bro. .PARAMETER type Commit type: feat, fix, chore, refactor, docs, style, test, perf, ci, build .PARAMETER module Module name for monorepo scope (default: trymsae.memeshell) .PARAMETER major major in ur mom. .PARAMETER noClipboard Just for display. .EXAMPLE PS > New-YoloCommit -type feat feat(trymsae.memeshell): yeet the deprecated code into the sun | mogged to clipboard .EXAMPLE PS > yolo fix fix(trymsae.memeshell): turns out the bug was a feature all along | mogged to clipboard .EXAMPLE PS > yolo feat -major feat(trymsae.memeshell)!: this changes everything .EXAMPLE PS > yolo feat -module "ur.mom" feat(ur.mom): built different fr fr | mogged to clipboard #> [alias('yolo')] [CmdletBinding()] param ( [parameter(Position = 0, Mandatory = $true)] [ValidateSet('feat', 'fix', 'chore', 'refactor', 'docs', 'style', 'test', 'perf', 'ci', 'build')] [string]$type, [parameter(Position = 1, Mandatory = $false)] [string]$module = "trymsae.memeshell", [parameter(Position = 2, Mandatory = $false)] [switch]$major, [parameter(Position = 3, Mandatory = $false)] [switch]$noClipboard ) begin { # get the sauce $messagesFile = Join-Path $PSScriptRoot "templates\texts\commit-messages.b64" if (Test-Path $messagesFile) { try { $base64Content = Get-Content $messagesFile -Raw $bytes = [Convert]::FromBase64String($base64Content.Trim()) $decodedText = [System.Text.Encoding]::UTF8.GetString($bytes) $commitMessages = $decodedText -split "`r?`n" | Where-Object { $_.Trim() -ne "" } } catch { # catch these hands $commitMessages = @("something broke but we ship anyway") } } else { # if shit breaks, lmao. $commitMessages = @("yolo commit message generator broke lmao") } } process { # yeet a random message $randomMessage = $commitMessages | Get-Random # handle majors if ($major) { # breaking change vibes $output = "$($type)($($module))!: $($randomMessage)" } else { # what else? $output = "$($type)($($module)): $($randomMessage)" } } end { if ( -not $noClipboard ) { Set-Clipboard -Value $output Write-Host "$($output) | " -NoNewline Write-Host "mogged to clipboard" -ForegroundColor Green } else { Write-Host $output } } } # Auto-activate meme prompt on module load (no escape lmao) Enable-MemePrompt |