FILE 1: /home/custom-text-message.digitalprank.com/public_html/tool_config.json code JSON { "tool": { "identity": { "slug": "custom-text-message", "name": "Text Message Generator", "category": "prank", "tagline": "Create hilarious custom text conversations in seconds.", "description": "Generate realistic-looking custom text messages for pranks. Choose phone style, sender name, and message bubbles.", "keywords": ["custom text", "sms prank", "chat generator", "digital prank"] }, "features": { "bulk_enabled": false, "history_enabled": true, "export_enabled": true, "api_enabled": false }, "fields": [ { "id": "sender_name", "type": "text", "label": "Sender Name", "placeholder": "Mom, Boss, Crush", "required": true, "pro_only": false, "validation": { "type": "string", "min_length": 1, "max_length": 50 } }, { "id": "conversation_bubbles", "type": "textarea", "label": "Conversation", "placeholder": "Type your custom chat here, line by line. Use 'ME: Your message' or 'SENDER: Their message'.", "required": true, "pro_only": false, "validation": { "type": "string", "min_length": 10, "max_length": 2000 } }, { "id": "phone_style", "type": "select", "label": "Phone Style", "default": "iphone", "options": [ { "value": "iphone", "label": "iPhone iMessage" }, { "value": "android", "label": "Android SMS" }, { "value": "darkmode", "label": "Dark Mode Chat" } ], "pro_only": false } ], "limits": { "tier_daily": { "free": 5, "basic": 50, "gold": 200, "ultimate": -1 }, "rate_limit_per_minute": 20, "max_concurrent_requests": 5 }, "billing": { "credit_cost": 0, "one_off_enabled": false, "bill_on": "none" }, "ui": { "form_title": "Generate Your Text Message", "submit_button_text": "Generate Custom Text", "result_display_type": "image", "result_description": "Your custom text message screenshot is ready!", "disclaimer": "This tool is for entertainment and prank purposes only. Do not use for malicious activities or impersonation." }, "dependencies": { "php_extensions": ["gd", "json"], "system_packages": ["php8.1-gd"] }, "database": { "tables": [ { "name": "wp_digitalprank_custom_texts", "schema": { "id": "BIGINT PRIMARY KEY AUTO_INCREMENT", "user_id": "BIGINT", "sender_name": "VARCHAR(255)", "conversation_json": "JSON", "phone_style": "VARCHAR(50)", "generated_image_url": "VARCHAR(255)", "created_at": "TIMESTAMP DEFAULT CURRENT_TIMESTAMP" } } ] }, "seo": { "title": "Text Message Generator - Create Realistic Prank SMS | DigitalPrank", "description": "Create convincing custom text message conversations online. Choose iPhone or Android styles, customize sender, and prank your friends instantly!", "keywords": ["custom text message", "prank sms generator", "iphone text prank", "android sms prank", "chat generator", "prank tool"], "canonical_url": "https://custom-text-message.digitalprank.com" }, "help": { "quick_start": [ "Enter a 'Sender Name' for the person sending the messages.", "Type your 'Conversation' in the textarea. Each line represents a message. Use 'ME: Your message' for messages from you, and 'SENDER: Their message' for messages from the sender.", "Select your preferred 'Phone Style' (iPhone, Android, or Dark Mode).", "Click 'Generate Custom Text' and your image will appear!" ], "features": { "sender_name": "Set who the messages are 'from' (e.g., Mom, Boss, Ex).", "conversation_bubbles": "Craft your entire chat line by line. Our system intelligently determines who sent which message based on your input.", "phone_style": "Choose between popular phone interfaces to make your prank look as realistic as possible." }, "faq": [ { "question": "How do I make messages from 'me' versus 'them'?", "answer": "Prefix your messages with 'ME: ' and the sender's messages with 'SENDER: ' (where SENDER is replaced by the name you entered)." }, { "question": "Can I save my generated custom texts?", "answer": "Yes, all generated images are saved in your history and can be exported." }, { "question": "What if I need more daily generations?", "answer": "Consider upgrading to one of our premium tiers (Basic, Gold, or Ultimate) for higher daily limits and more features." } ], "usage_examples": [ { "title": "Simple Conversation", "input": { "sender_name": "Boss", "conversation_bubbles": "SENDER: Are you coming in today?\nME: Yes, just running a few minutes late.\nSENDER: Ok, see you then." }, "output_description": "An image showing a short text exchange with 'Boss' as the sender." } ] } } } FILE 2: /home/custom-text-message.digitalprank.com/public_html/processor.php code PHP false, 'message' => 'An unknown error occurred.', 'data' => null, 'usage' => null, 'access' => null, 'features' => null ]; $tool_slug = 'custom-text-message'; $user_id = $_POST['user_id'] ?? 0; // Assume 0 for guests, WordPress user ID otherwise $user_ip = $_SERVER['REMOTE_ADDR']; $session_id = session_id(); // Ensure session_start() is called elsewhere if needed $user_agent = $_SERVER['HTTP_USER_AGENT'] ?? ''; // Database connection $db_host = 'localhost'; $db_name = 'digitalprank_db'; $db_user = 'dp_user'; $db_pass = '#$Dealer2355'; $pdo = null; try { $pdo = new PDO("mysql:host=$db_host;dbname=$db_name;charset=utf8mb4", $db_user, $db_pass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { $response['message'] = 'Database connection failed: ' . $e->getMessage(); logUsage($pdo, $tool_slug, $user_ip, $user_id, 'processing_failed', json_encode($_POST), json_encode($response), 0, 'failed'); echo json_encode($response); exit; } // Load tool configuration $config_file = __DIR__ . '/tool_config.json'; if (!file_exists($config_file)) { $response['message'] = 'Tool configuration file not found.'; logUsage($pdo, $tool_slug, $user_ip, $user_id, 'processing_failed', json_encode($_POST), json_encode($response), 0, 'failed'); echo json_encode($response); exit; } $config = json_decode(file_get_contents($config_file), true); if (json_last_error() !== JSON_ERROR_NONE) { $response['message'] = 'Invalid tool configuration JSON: ' . json_last_error_msg(); logUsage($pdo, $tool_slug, $user_ip, $user_id, 'processing_failed', json_encode($_POST), json_encode($response), 0, 'failed'); echo json_encode($response); exit; } $tool_config = $config['tool']; // Get user access level // Placeholder for getUserAccessLevel, assuming it returns an array // with 'level' (free, basic, gold, ultimate) and 'has_pro_access' (bool) $access = getUserAccessLevel($pdo, $user_id, $tool_slug); if (!$access) { $access = ['level' => 'free', 'has_pro_access' => false]; // Default for guests or if function fails } $response['access'] = $access; // Check daily usage limits $daily_limit = $tool_config['limits']['tier_daily'][$access['level']] ?? $tool_config['limits']['tier_daily']['free']; if ($daily_limit !== -1) { // -1 means unlimited $usage_check = checkDailyUsage($pdo, $tool_slug, $user_ip, $user_id, $daily_limit); if (!$usage_check['can_proceed']) { $response['message'] = 'Daily usage limit reached for your tier. Please try again tomorrow or upgrade your plan.'; $response['usage'] = $usage_check; logUsage($pdo, $tool_slug, $user_ip, $user_id, 'rate_limited', json_encode($_POST), json_encode($response), 0, 'failed'); echo json_encode($response); exit; } $response['usage'] = $usage_check; } $input = []; $errors = []; // Fetch tool_id for overrides $stmt_tool_id = $pdo->prepare("SELECT tool_id FROM wp_digitalprank_tools WHERE slug = :tool_slug"); $stmt_tool_id->execute([':tool_slug' => $tool_slug]); $tool_id_row = $stmt_tool_id->fetch(PDO::FETCH_ASSOC); $tool_id = $tool_id_row ? $tool_id_row['tool_id'] : null; if (!$tool_id) { $response['message'] = 'Tool not registered in core tools table.'; logUsage($pdo, $tool_slug, $user_ip, $user_id, 'processing_failed', json_encode($_POST), json_encode($response), 0, 'failed'); echo json_encode($response); exit; } // Process and validate inputs foreach ($tool_config['fields'] as $field_config) { $field_id = $field_config['id']; $field_value = $_POST[$field_id] ?? null; $input[$field_id] = $field_value; // Check for field overrides (pro_only or disabled for current tier) $stmt_override = $pdo->prepare("SELECT tier_required FROM wp_digitalprank_tool_overrides WHERE tool_id = :tool_id AND field_id = :field_id AND is_active = 1 AND override_type = 'tier'"); $stmt_override->execute([':tool_id' => $tool_id, ':field_id' => $field_id]); $override_tier_row = $stmt_override->fetch(PDO::FETCH_ASSOC); $is_pro_field_via_config = $field_config['pro_only'] ?? false; $is_pro_field_via_override = $override_tier_row && ( ($override_tier_row['tier_required'] == 'basic' && in_array($access['level'], ['free'])) || ($override_tier_row['tier_required'] == 'gold' && in_array($access['level'], ['free', 'basic'])) || ($override_tier_row['tier_required'] == 'ultimate' && in_array($access['level'], ['free', 'basic', 'gold'])) ); if (($is_pro_field_via_config || $is_pro_field_via_override) && !$access['has_pro_access']) { if ($field_config['required'] && empty($field_value)) { // If a required pro field is empty and user isn't pro $errors[] = "Field '{$field_config['label']}' requires a premium plan to use or modify."; } // If a pro-only field is submitted by a non-pro user, but it's not required and has a default, let it pass // or ensure it defaults to a free-tier compatible value. For 'select', this means using the default. if ($field_config['type'] === 'select' && $is_pro_field_via_config && !$access['has_pro_access']) { $input[$field_id] = $field_config['default'] ?? $field_config['options'][0]['value']; } continue; // Skip further validation if pro-only and user not pro } // Basic required validation if (($field_config['required'] ?? false) && empty($field_value)) { $errors[] = "Field '{$field_config['label']}' is required."; continue; } // Apply validation rules if (isset($field_config['validation']) && !empty($field_value)) { $validation = $field_config['validation']; switch ($validation['type']) { case 'string': if (isset($validation['min_length']) && strlen($field_value) < $validation['min_length']) { $errors[] = "Field '{$field_config['label']}' must be at least {$validation['min_length']} characters long."; } if (isset($validation['max_length']) && strlen($field_value) > $validation['max_length']) { $errors[] = "Field '{$field_config['label']}' cannot exceed {$validation['max_length']} characters."; } break; case 'number': if (!is_numeric($field_value)) { $errors[] = "Field '{$field_config['label']}' must be a number."; } else { if (isset($validation['min']) && $field_value < $validation['min']) { $errors[] = "Field '{$field_config['label']}' must be at least {$validation['min']}."; } if (isset($validation['max']) && $field_value > $validation['max']) { $errors[] = "Field '{$field_config['label']}' cannot exceed {$validation['max']}."; } } break; // Add more validation types as needed } } } if (!empty($errors)) { $response['message'] = 'Validation errors: ' . implode(' ', $errors); logUsage($pdo, $tool_slug, $user_ip, $user_id, 'validation_failed', json_encode($_POST), json_encode($response), 0, 'failed'); echo json_encode($response); exit; } $start_time = microtime(true); // {{TOOL_PROCESSING_START}} // Specific tool processing logic for Text Message Generator $sender_name = $input['sender_name']; $conversation_raw = $input['conversation_bubbles']; $phone_style = $input['phone_style']; $conversation_lines = explode("\n", $conversation_raw); $parsed_conversation = []; foreach ($conversation_lines as $line) { $line = trim($line); if (empty($line)) continue; if (strpos(strtoupper($line), 'ME:') === 0) { $message = trim(substr($line, 3)); if (!empty($message)) { $parsed_conversation[] = ['sender' => 'me', 'message' => $message]; } } elseif (strpos(strtoupper($line), 'SENDER:') === 0) { $message = trim(substr($line, 7)); if (!empty($message)) { $parsed_conversation[] = ['sender' => 'other', 'message' => $message]; } } else { // Default to sender if no prefix, or handle as an error/default $parsed_conversation[] = ['sender' => 'other', 'message' => $line]; } } if (empty($parsed_conversation)) { $response['message'] = 'No valid conversation lines found.'; logUsage($pdo, $tool_slug, $user_ip, $user_id, 'processing_failed', json_encode($_POST), json_encode($response), (microtime(true) - $start_time), 'failed'); echo json_encode($response); exit; } // Image generation parameters (simplified for this example, a real implementation would be complex) $image_width = 600; $image_height = 800; // Will adjust dynamically based on content // Create base image $im = imagecreatetruecolor($image_width, $image_height); $bg_color = imagecolorallocate($im, 255, 255, 255); // White background $text_color = imagecolorallocate($im, 0, 0, 0); // Black text $bubble_me_color = imagecolorallocate($im, 0, 122, 255); // Blue for 'me' $bubble_other_color = imagecolorallocate($im, 229, 229, 234); // Grey for 'other' $bubble_text_me_color = imagecolorallocate($im, 255, 255, 255); // White for 'me' text $bubble_text_other_color = imagecolorallocate($im, 0, 0, 0); // Black for 'other' text $font_path = __DIR__ . '/fonts/Arial.ttf'; // Ensure you have a font file, e.g., Arial.ttf in a 'fonts' directory if (!file_exists($font_path)) { // Fallback to a system font if Arial.ttf isn't available $font_path = '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf'; if (!file_exists($font_path)) { // Last resort: skip text rendering and just draw bubbles $font_path = null; } } $font_size = 12; $line_height = 20; // Base line height $padding_x = 15; $padding_y = 10; $bubble_padding = 10; // Padding inside bubble $bubble_radius = 15; // Rounded corners $current_y = 20; // Start Y position if ($phone_style === 'darkmode') { $bg_color = imagecolorallocate($im, 25, 25, 25); $text_color = imagecolorallocate($im, 255, 255, 255); $bubble_me_color = imagecolorallocate($im, 0, 122, 255); $bubble_other_color = imagecolorallocate($im, 50, 50, 50); $bubble_text_me_color = imagecolorallocate($im, 255, 255, 255); $bubble_text_other_color = imagecolorallocate($im, 255, 255, 255); } imagefill($im, 0, 0, $bg_color); // Draw header for sender name if ($font_path) { $header_font_size = 14; $header_text_color = ($phone_style === 'darkmode') ? imagecolorallocate($im, 255, 255, 255) : imagecolorallocate($im, 0, 0, 0); $header_bbox = imagettfbbox($header_font_size, 0, $font_path, $sender_name); $header_text_width = $header_bbox[2] - $header_bbox[0]; imagettftext($im, $header_font_size, 0, ($image_width - $header_text_width) / 2, $current_y + $header_font_size, $header_text_color, $font_path, $sender_name); } else { // Fallback if no font $header_text_color = ($phone_style === 'darkmode') ? imagecolorallocate($im, 255, 255, 255) : imagecolorallocate($im, 0, 0, 0); imagestring($im, 5, ($image_width - imagefontwidth(5) * strlen($sender_name)) / 2, $current_y, $sender_name, $header_text_color); } $current_y += 50; // Space after header // Calculate dynamic height $max_message_width = $image_width - ($padding_x * 2) - ($bubble_padding * 2) - 60; // Leave space for padding and margins $total_content_height = 0; foreach ($parsed_conversation as $msg) { $text_to_wrap = $msg['message']; $wrapped_lines = []; if ($font_path) { $wrapped_lines = wrapText($font_path, $font_size, 0, $text_to_wrap, $max_message_width); } else { $wrapped_lines = [$text_to_wrap]; // No wrapping if no font } $total_content_height += count($wrapped_lines) * $line_height + ($bubble_padding * 2); $total_content_height += 15; // Margin between bubbles } $image_height = max(800, $current_y + $total_content_height + 50); // Ensure minimum height // Recreate image with correct height $new_im = imagecreatetruecolor($image_width, $image_height); imagefill($new_im, 0, 0, $bg_color); // Re-draw header on new image if ($font_path) { $header_font_size = 14; $header_text_color = ($phone_style === 'darkmode') ? imagecolorallocate($new_im, 255, 255, 255) : imagecolorallocate($new_im, 0, 0, 0); $header_bbox = imagettfbbox($header_font_size, 0, $font_path, $sender_name); $header_text_width = $header_bbox[2] - $header_bbox[0]; imagettftext($new_im, $header_font_size, 0, ($image_width - $header_text_width) / 2, 20 + $header_font_size, $header_text_color, $font_path, $sender_name); } else { imagestring($new_im, 5, ($image_width - imagefontwidth(5) * strlen($sender_name)) / 2, 20, $sender_name, $text_color); } $current_y = 50; // Reset Y for messages foreach ($parsed_conversation as $msg) { $text = $msg['message']; $is_me = ($msg['sender'] === 'me'); $bubble_bg = $is_me ? $bubble_me_color : $bubble_other_color; $bubble_text_col = $is_me ? $bubble_text_me_color : $bubble_text_other_color; $wrapped_lines = []; if ($font_path) { $wrapped_lines = wrapText($font_path, $font_size, 0, $text, $max_message_width); } else { $wrapped_lines = [$text]; // No wrapping if no font } $bubble_height = count($wrapped_lines) * $line_height + ($bubble_padding * 2); $max_wrapped_line_width = 0; if ($font_path) { foreach ($wrapped_lines as $w_line) { $bbox = imagettfbbox($font_size, 0, $font_path, $w_line); $line_width = $bbox[2] - $bbox[0]; if ($line_width > $max_wrapped_line_width) { $max_wrapped_line_width = $line_width; } } } else { foreach ($wrapped_lines as $w_line) { $line_width = imagefontwidth(5) * strlen($w_line); if ($line_width > $max_wrapped_line_width) { $max_wrapped_line_width = $line_width; } } } $bubble_width = $max_wrapped_line_width + ($bubble_padding * 2); $x1 = $is_me ? ($image_width - $padding_x - $bubble_width) : $padding_x; $y1 = $current_y + $padding_y; $x2 = $is_me ? ($image_width - $padding_x) : ($padding_x + $bubble_width); $y2 = $y1 + $bubble_height; // Draw rounded rectangle for bubble imagefilledarc($new_im, $x1 + $bubble_radius, $y1 + $bubble_radius, $bubble_radius * 2, $bubble_radius * 2, 180, 270, $bubble_bg, IMG_ARC_PIE); imagefilledarc($new_im, $x2 - $bubble_radius, $y1 + $bubble_radius, $bubble_radius * 2, $bubble_radius * 2, 270, 360, $bubble_bg, IMG_ARC_PIE); imagefilledarc($new_im, $x1 + $bubble_radius, $y2 - $bubble_radius, $bubble_radius * 2, $bubble_radius * 2, 90, 180, $bubble_bg, IMG_ARC_PIE); imagefilledarc($new_im, $x2 - $bubble_radius, $y2 - $bubble_radius, $bubble_radius * 2, $bubble_radius * 2, 0, 90, $bubble_bg, IMG_ARC_PIE); imagefilledrectangle($new_im, $x1 + $bubble_radius, $y1, $x2 - $bubble_radius, $y2, $bubble_bg); imagefilledrectangle($new_im, $x1, $y1 + $bubble_radius, $x2, $y2 - $bubble_radius, $bubble_bg); // Draw text inside bubble $text_start_x = $x1 + $bubble_padding; $text_start_y = $y1 + $bubble_padding + $font_size; // Start at base of first line foreach ($wrapped_lines as $line_num => $w_line) { if ($font_path) { imagettftext($new_im, $font_size, 0, $text_start_x, $text_start_y + ($line_num * $line_height), $bubble_text_col, $font_path, $w_line); } else { imagestring($new_im, 5, $text_start_x, $text_start_y + ($line_num * $line_height) - imagefontheight(5), $w_line, $bubble_text_col); } } $current_y = $y2 + 15; // Move Y for next bubble, add some margin } // Function to wrap text using imagettfbbox for precise width calculation function wrapText($font, $size, $angle, $text, $maxWidth) { $words = explode(' ', $text); $lines = []; $currentLine = ''; foreach ($words as $word) { $testLine = $currentLine . ($currentLine == '' ? '' : ' ') . $word; $bbox = imagettfbbox($size, $angle, $font, $testLine); $testWidth = $bbox[2] - $bbox[0]; if ($testWidth <= $maxWidth) { $currentLine = $testLine; } else { $lines[] = $currentLine; $currentLine = $word; } } $lines[] = $currentLine; return $lines; } // Save the image $image_filename = uniqid('faketext_') . '.png'; $image_path = __DIR__ . '/generated/' . $image_filename; // Ensure 'generated' directory exists and is writable if (!is_dir(__DIR__ . '/generated')) { mkdir(__DIR__ . '/generated', 0755, true); } if (!imagepng($new_im, $image_path)) { $response['message'] = 'Failed to save generated image.'; logUsage($pdo, $tool_slug, $user_ip, $user_id, 'processing_failed', json_encode($_POST), json_encode($response), (microtime(true) - $start_time), 'failed'); echo json_encode($response); exit; } imagedestroy($im); imagedestroy($new_im); $generated_image_url = "https://{$tool_slug}.digitalprank.com/generated/{$image_filename}"; // Store generation details in tool-specific table $stmt_insert_text = $pdo->prepare("INSERT INTO wp_digitalprank_custom_texts (user_id, sender_name, conversation_json, phone_style, generated_image_url) VALUES (:user_id, :sender_name, :conversation_json, :phone_style, :generated_image_url)"); $stmt_insert_text->execute([ ':user_id' => $user_id, ':sender_name' => $sender_name, ':conversation_json' => json_encode($parsed_conversation), ':phone_style' => $phone_style, ':generated_image_url' => $generated_image_url ]); $response['data'] = [ 'image_url' => $generated_image_url ]; // {{TOOL_PROCESSING_END}} $end_time = microtime(true); $processing_time = $end_time - $start_time; $response['success'] = true; $response['message'] = 'Custom text message generated successfully!'; $response['features'] = [ 'bulk_enabled' => $tool_config['features']['bulk_enabled'], 'history_enabled' => $tool_config['features']['history_enabled'], 'export_enabled' => $tool_config['features']['export_enabled'], 'api_enabled' => $tool_config['features']['api_enabled'] ]; // Log successful usage logUsage($pdo, $tool_slug, $user_ip, $user_id, 'generation', json_encode($input), json_encode($response['data']), $processing_time, 'success'); echo json_encode($response); // Universal Processor Functions (already exist but copied for clarity if this file is standalone) // function getUserAccessLevel($pdo, $user_id, $tool_slug) { // if ($user_id == 0) { // Guest user // return ['level' => 'free', 'has_pro_access' => false]; // } // // Check wp_pms_member_subscriptions // $stmt = $pdo->prepare("SELECT subscription_plan_id, status FROM wp_pms_member_subscriptions WHERE user_id = :user_id AND status = 'active' ORDER BY id DESC LIMIT 1"); // $stmt->execute([':user_id' => $user_id]); // $subscription = $stmt->fetch(PDO::FETCH_ASSOC); // $level = 'free'; // $has_pro_access = false; // if ($subscription) { // switch ($subscription['subscription_plan_id']) { // case 174: // Basic // case 184: // $level = 'basic'; // $has_pro_access = true; // break; // case 175: // Gold // case 185: // $level = 'gold'; // $has_pro_access = true; // break; // case 176: // Ultimate // case 186: // $level = 'ultimate'; // $has_pro_access = true; // break; // } // } // return ['level' => $level, 'has_pro_access' => $has_pro_access]; // } // function checkDailyUsage($pdo, $tool_slug, $user_ip, $user_id, $limit) { // $today = date('Y-m-d'); // $count = 0; // if ($user_id > Model ThinkingThoughts (experimental) Auto Expand to view model thoughts chevron_right { // Check by user ID for logged-in users // $stmt = $pdo->prepare("SELECT COUNT() FROM wp_digitalprank_usage WHERE user_id = :user_id AND tool_slug = :tool_slug AND action = 'generation' AND DATE(timestamp) = :today"); // $stmt->execute([':user_id' => $user_id, ':tool_slug' => $tool_slug, ':today' => $today]); // } else { // Check by IP for guests // $stmt = $pdo->prepare("SELECT COUNT() FROM wp_digitalprank_usage WHERE ip_address = :ip_address AND tool_slug = :tool_slug AND action = 'generation' AND DATE(timestamp) = :today"); // $stmt->execute([':ip_address' => $user_ip, ':tool_slug' => $tool_slug, ':today' => $today]); // } // $count = $stmt->fetchColumn(); // return [ // 'limit' => $limit, // 'used' => $count, // 'remaining' => $limit - $count, // 'can_proceed' => $count < $limit // ]; // } // function logUsage($pdo, $tool_slug, $user_ip, $user_id, $action_type, $input_data, $output_data, $processing_time, $status = 'success') { // // Log to short-term usage table for rate limiting // $stmt_usage = $pdo->prepare("INSERT INTO wp_digitalprank_usage (user_id, tool_slug, action, credits_used, processing_time, ip_address, session_id, user_agent) VALUES (:user_id, :tool_slug, :action, :credits_used, :processing_time, :ip_address, :session_id, :user_agent)"); // $stmt_usage->execute([ // ':user_id' => $user_id, // ':tool_slug' => $tool_slug, // ':action' => $action_type, // ':credits_used' => 0, // Assuming 0 for this tool // ':processing_time' => $processing_time, // ':ip_address' => $user_ip, // ':session_id' => session_id(), // ':user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '' // ]); // // Log to detailed long-term log table // $stmt_log = $pdo->prepare("INSERT INTO wp_digitalprank_usage_log (user_id, tool_slug, action_type, ip_address, session_id, user_agent, input_data, output_data, processing_time, status) VALUES (:user_id, :tool_slug, :action_type, :ip_address, :session_id, :user_agent, :input_data, :output_data, :processing_time, :status)"); // $stmt_log->execute([ // ':user_id' => $user_id, // ':tool_slug' => $tool_slug, // ':action_type' => $action_type, // ':ip_address' => $user_ip, // ':session_id' => session_id(), // ':user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? '', // ':input_data' => $input_data, // ':output_data' => $output_data, // ':processing_time' => $processing_time, // ':status' => $status // ]); // } ?> code Code ### FILE 3: /home/custom-text-message.digitalprank.com/public_html/tool_form.php ```php <?php echo htmlspecialchars($tool_config['identity']['name']); ?> - DigitalPrank

data-show-if-field="" data-show-if-value="" style="display: none;" > >

FILE 4: /home/custom-text-message.digitalprank.com/public_html/diagnostic.php code PHP "; echo "$title"; echo "" . ($status ? 'OK' : 'FAIL') . ""; echo "" . htmlspecialchars($message) . ""; echo ""; } ?> Tool Diagnostic: Text Message Generator

Diagnostic for Text Message Generator

setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); print_status('Database Connection', true, "Connected successfully to '$db_name' on '$db_host'."); } catch (PDOException $e) { print_status('Database Connection', false, 'Connection failed: ' . $e->getMessage()); } // 3. Required Tables Check if ($pdo) { $required_tables = [ 'wp_digitalprank_tools', 'wp_digitalprank_usage', 'wp_digitalprank_usage_log', 'wp_pms_member_subscriptions', 'wp_digitalprank_entitlements', 'wp_digitalprank_tool_overrides', 'wp_digitalprank_custom_texts' // Tool-specific table ]; foreach ($required_tables as $table) { try { $pdo->query("SELECT 1 FROM $table LIMIT 1"); print_status("Table Check: '$table'", true, 'Table exists.'); } catch (Exception $e) { print_status("Table Check: '$table'", false, 'Table does not exist or is inaccessible.'); } } } else { print_status('Table Checks', false, 'Skipped due to failed database connection.'); } // 4. Dependencies Checking (PHP extensions) if ($config && isset($config['tool']['dependencies']['php_extensions'])) { foreach ($config['tool']['dependencies']['php_extensions'] as $ext) { if (extension_loaded($ext)) { print_status("PHP Extension: '$ext'", true, 'Extension is loaded.'); } else { print_status("PHP Extension: '$ext'", false, 'Extension is not loaded.'); } } } else { print_status('PHP Extension Checks', false, 'Skipped. No dependencies specified or config not loaded.'); } // 5. Writable Directories $generated_dir = __DIR__ . '/generated'; if (is_dir($generated_dir) && is_writable($generated_dir)) { print_status('Directory Writable: /generated/', true, 'Directory exists and is writable.'); } else { print_status('Directory Writable: /generated/', false, 'Directory does not exist or is not writable. Attempting to create...'); if(!is_dir($generated_dir)) { mkdir($generated_dir, 0755, true); } if(is_writable($generated_dir)) { print_status('Directory Creation', true, 'Successfully created /generated/ directory.'); } else { print_status('Directory Creation', false, 'Failed to create or make /generated/ directory writable.'); } } // 6. Tool-specific functionality test (Image Generation) if (extension_loaded('gd')) { $test_im = @imagecreatetruecolor(10, 10); if ($test_im) { print_status('Tool Functionality Test (GD)', true, 'GD library can create an image resource.'); imagedestroy($test_im); } else { print_status('Tool Functionality Test (GD)', false, 'imagecreatetruecolor() failed. GD might be misconfigured.'); } } else { print_status('Tool Functionality Test (GD)', false, 'GD extension not loaded, cannot perform test.'); } // 7. Performance Monitoring $start_time = microtime(true); $pdo_test_query = $pdo ? $pdo->query("SELECT 1") : null; $end_time = microtime(true); $db_query_time = ($end_time - $start_time) * 1000; print_status('Performance (DB Query)', true, 'Simple DB query took ' . number_format($db_query_time, 2) . ' ms.'); ?>
Check Status Details
FILE 5: /home/custom-text-message.digitalprank.com/public_html/help.md code Markdown # Text Message Generator - Help Guide Welcome to the Text Message Generator! This guide will help you get started and make the most out of this tool. ## Quick Start Guide Follow these simple steps to create your first custom text conversation: 1. Enter a 'Sender Name' for the person sending the messages. 2. Type your 'Conversation' in the textarea. Each line represents a message. Use 'ME: Your message' for messages from you, and 'SENDER: Their message' for messages from the sender. 3. Select your preferred 'Phone Style' (iPhone, Android, or Dark Mode). 4. Click 'Generate Custom Text' and your image will appear! ## Feature Descriptions * **Sender Name**: Set who the messages are 'from' (e.g., Mom, Boss, Ex). * **Conversation Bubbles**: Craft your entire chat line by line. Our system intelligently determines who sent which message based on your input. * **Phone Style**: Choose between popular phone interfaces to make your prank look as realistic as possible. ## Frequently Asked Questions (FAQ) **Q: How do I make messages from 'me' versus 'them'?** **A:** Prefix your messages with 'ME: ' and the sender's messages with 'SENDER: ' (where SENDER is replaced by the name you entered). **Q: Can I save my generated custom texts?** **A:** Yes, all generated images are saved in your history and can be exported. **Q: What if I need more daily generations?** **A:** Consider upgrading to one of our premium tiers (Basic, Gold, or Ultimate) for higher daily limits and more features. ## Usage Examples ### Simple Conversation **Input:** Sender Name: Boss Conversation: SENDER: Are you coming in today? ME: Yes, just running a few minutes late. SENDER: Ok, see you then. code Code **Output Description:** An image showing a short text exchange with 'Boss' as the sender. --- *Disclaimer: This tool is for entertainment and prank purposes only. Do not use for malicious activities or impersonation.* FILE 6: /home/digitalprank.com/public_html/blog/data/tools/custom-text-message.json```json { "@context": "https://schema.org", "@type": "SoftwareApplication", "name": "Text Message Generator", "applicationCategory": "Entertainment", "operatingSystem": "Web", "description": "Create convincing custom text message conversations online. Choose iPhone or Android styles, customize sender, and prank your friends instantly!", "url": "https://custom-text-message.digitalprank.com", "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" }, "keywords": ["custom text message", "prank sms generator", "iphone text prank", "android sms prank", "chat generator", "prank tool"], "mainEntityOfPage": { "@type": "WebPage", "@id": "https://custom-text-message.digitalprank.com" }, "featureList": [ "Custom Sender Name", "Line-by-Line Conversation Input", "iPhone iMessage Style", "Android SMS Style", "Dark Mode Chat Style", "Image Export", "User Generation History" ], "technicalDocumentation": { "dependencies": "PHP 8.1+, GD Graphics Library", "outputFormat": "PNG Image" }, "userGuide": { "title": "How to Create a Text Message", "steps": [ { "stepNumber": 1, "name": "Enter Sender Name", "description": "Input the name of the person you want the messages to appear from." }, { "stepNumber": 2, "name": "Write the Conversation", "description": "Type the chat history line-by-line. Use 'ME: ' for your messages and 'SENDER: ' for the other person's messages." }, { "stepNumber": 3, "name": "Choose a Style", "description": "Select from iPhone, Android, or Dark Mode to match the desired look." }, { "stepNumber": 4, "name": "Generate and Download", "description": "Click the 'Generate' button to create your image, which you can then save." } ], "bestPractices": "For maximum realism, keep messages short and use common text message slang. Check for typos before generating the final image." } } code Code ### FILE 7: /home/custom-text-message.digitalprank.com/public_html/deploy.sh ```bash #!/bin/bash set -e TOOL_SLUG="custom-text-message" VHOST_DIR="/home/${TOOL_SLUG}.digitalprank.com" VHOST_CONF_DIR="/usr/local/lsws/conf/vhosts" OWNER="www-data:www-data" echo "--- Starting deployment for ${TOOL_SLUG} ---" # 1. Install System Packages echo "Installing system packages..." apt-get update apt-get install -y php8.1-gd # 2. Create tool-specific database table echo "Creating database table wp_digitalprank_custom_texts..." mysql -h localhost -u dp_user -p'#$Dealer2355' digitalprank_db <<'EOF' CREATE TABLE IF NOT EXISTS wp_digitalprank_custom_texts ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT, sender_name VARCHAR(255), conversation_json JSON, phone_style VARCHAR(50), generated_image_url VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; EOF # 3. Create Directories and set Permissions echo "Creating directories and setting permissions..." mkdir -p "${VHOST_DIR}/public_html/generated" mkdir -p "${VHOST_DIR}/logs" chown -R ${OWNER} ${VHOST_DIR} chmod -R 755 ${VHOST_DIR} chmod -R 775 "${VHOST_DIR}/public_html/generated" # Writable for PHP process # 4. OpenLiteSpeed Virtual Host Configuration echo "Configuring OpenLiteSpeed virtual host..." cat > "${VHOST_CONF_DIR}/${TOOL_SLUG}.conf" <s %b \"%{Referer}i\" \"%{User-Agent}i\"" logHeaders 5 rollingSize 10M keepDays 10 compressArchive 1 } scripthandler { add lsapi:php81 php } extprocessor php81 { type lsapi address uds://tmp/lshttpd/php81.sock maxConns 35 env LSAPI_CHILDREN=35 initTimeout 60 retryTimeout 0 persistConn 1 respBuffer 0 autoStart 1 path /usr/local/lsws/lsphp81/bin/lsphp backlog 100 instances 1 extMaxIdleTime 10 priority 0 memSoftLimit 2047M memHardLimit 2047M procSoftLimit 400 procHardLimit 500 } rewrite { enable 1 autoLoadHtaccess 1 } EOF # 5. Log Rotation Configuration echo "Configuring log rotation..." cat > "/etc/logrotate.d/${TOOL_SLUG}" < /dev/null endscript } EOF # 6. Service Health Validation echo "Restarting OpenLiteSpeed to apply changes..." /usr/local/lsws/bin/lswsctrl restart sleep 5 echo "Validating service..." if curl -s --head "http://${TOOL_SLUG}.digitalprank.com" | grep "200 OK" > /dev/null; then echo "Deployment successful! ${TOOL_SLUG}.digitalprank.com is online." else echo "Deployment failed. The site did not return a 200 OK status." exit 1 fi echo "--- Deployment for ${TOOL_SLUG} finished ---"