diff --git a/wp-ingame-shop/wp-ingame-shop.php b/wp-ingame-shop/wp-ingame-shop.php index e809d36..5918131 100644 --- a/wp-ingame-shop/wp-ingame-shop.php +++ b/wp-ingame-shop/wp-ingame-shop.php @@ -3,7 +3,7 @@ Plugin Name: WP Ingame Shop Pro Plugin URI: https://git.viper.ipv64.net/M_Viper/WP-Ingame-Shop-Pro Description: Vollautomatischer Shop mit Warenkorb + eigener DB-Struktur (SPIGOT COMPATIBLE) -Version: 2.1.0 +Version: 2.1.2 Author: M_Viper Author URI: https://m-viper.de Requires at least: 6.9.1 @@ -18,7 +18,7 @@ Tags: shop, items, minecraft, coupons, deals, categories if (!defined('ABSPATH')) exit; // Plugin Constants -define('WIS_VERSION', '2.1.0'); +define('WIS_VERSION', '2.1.2'); define('WIS_PLUGIN_DIR', plugin_dir_path(__FILE__)); define('WIS_PLUGIN_URL', plugin_dir_url(__FILE__)); @@ -29,6 +29,7 @@ class WIS_Activator { public static function activate() { self::create_tables(); self::set_default_options(); + self::create_default_categories(); if (!wp_next_scheduled('wis_daily_deal_event')) { wp_schedule_event(time(), 'daily', 'wis_daily_deal_event'); @@ -126,20 +127,67 @@ class WIS_Activator { private static function set_default_options() { $defaults = [ - 'wis_currency_name' => 'Coins', - 'wis_image_base_url' => 'https://git.viper.ipv64.net/M_Viper/minecraft-items/raw/branch/main/images/', - 'wis_header_text' => '✅ Auto-Bilder | 💰 Sicherer Checkout | 🎮 Ingame-Bestätigung', + 'wis_currency_name' => 'Coins', + 'wis_image_base_url' => 'https://git.viper.ipv64.net/M_Viper/minecraft-items/raw/branch/main/images/', + 'wis_header_text' => '✅ Auto-Bilder | 💰 Sicherer Checkout | 🎮 Ingame-Bestätigung', 'wis_coupon_exclude_offers' => '0', - 'wis_daily_deal_enabled' => '0', - 'wis_daily_deal_discount' => '20' + 'wis_daily_deal_enabled' => '0', + 'wis_daily_deal_discount' => '20', + 'wis_api_key' => bin2hex(random_bytes(24)), ]; - + foreach ($defaults as $key => $value) { if (get_option($key) === false) { add_option($key, $value); } } } + + public static function check_api_key($request) { + $key = $request->get_header('X-WIS-Key'); + if (empty($key)) { + $key = $request->get_param('api_key'); + } + $stored = get_option('wis_api_key', ''); + return ($stored !== '' && hash_equals($stored, (string) $key)); + } + + public static function spigot_permission($request) { + if (!self::check_api_key($request)) { + return new WP_Error('wis_unauthorized', 'Ungültiger oder fehlender API-Key.', ['status' => 401]); + } + return true; + } + + private static function create_default_categories() { + $default_categories = [ + ['name' => 'Baublöcke', 'slug' => 'baublocke'], + ['name' => 'Dekorationsblöcke', 'slug' => 'dekorationsblocke'], + ['name' => 'Redstone', 'slug' => 'redstone'], + ['name' => 'Transport', 'slug' => 'transport'], + ['name' => 'Natur', 'slug' => 'natur'], + ['name' => 'Werkzeuge & Hilfsmittel', 'slug' => 'werkzeuge-hilfsmittel'], + ['name' => 'Kampf', 'slug' => 'kampf'], + ['name' => 'Nahrung & Tränke', 'slug' => 'nahrung-tranke'], + ['name' => 'Zutaten', 'slug' => 'zutaten'], + ['name' => 'Spawn-Eier', 'slug' => 'spawn-eier'] + ]; + + global $wpdb; + foreach ($default_categories as $cat) { + $exists = $wpdb->get_var($wpdb->prepare( + "SELECT id FROM {$wpdb->prefix}wis_categories WHERE slug = %s", + $cat['slug'] + )); + + if (!$exists) { + $wpdb->insert($wpdb->prefix . 'wis_categories', [ + 'name' => $cat['name'], + 'slug' => $cat['slug'] + ]); + } + } + } public static function run_daily_deal() { if (get_option('wis_daily_deal_enabled') !== '1') return; @@ -148,14 +196,11 @@ class WIS_Activator { $table = $wpdb->prefix . 'wis_items'; $discount = intval(get_option('wis_daily_deal_discount', 20)); - // Reset old daily deal $wpdb->update($table, ['is_daily_deal' => 0], ['is_daily_deal' => 1]); - // Select random item $item = $wpdb->get_row("SELECT * FROM $table WHERE status = 'publish' AND price > 0 ORDER BY RAND() LIMIT 1"); if ($item) { - // Syntax Error Fix here: removed extra parent $offer_price = max(0, floor($item->price - ($item->price * ($discount / 100)))); $wpdb->update($table, [ 'is_daily_deal' => 1, @@ -178,10 +223,354 @@ class WIS_Activator { } self::set_default_options(); + self::create_default_categories(); return true; } } +// =========================================================== +// ITEM CATEGORIZER +// =========================================================== +class WIS_Item_Categorizer { + public static function auto_categorize($item_id) { + $item_id = strtolower($item_id); + $item_id = str_replace('minecraft:', '', $item_id); + + if (strpos($item_id, 'spawn_egg') !== false) { + return ['spawn-eier']; + } + + if (preg_match('/(wooden|stone|iron|golden|diamond|netherite|copper)_(pickaxe|axe|shovel|hoe)/', $item_id)) { + return ['werkzeuge-hilfsmittel']; + } + + if (in_array($item_id, [ + 'shears', 'fishing_rod', 'flint_and_steel', 'bucket', 'water_bucket', 'lava_bucket', + 'milk_bucket', 'powder_snow_bucket', 'axolotl_bucket', 'cod_bucket', 'pufferfish_bucket', + 'salmon_bucket', 'tadpole_bucket', 'tropical_fish_bucket', + 'compass', 'recovery_compass', 'clock', 'spyglass', 'map', 'filled_map', + 'brush', 'lead', 'name_tag', 'saddle', 'carrot_on_a_stick', 'warped_fungus_on_a_stick' + ])) { + return ['werkzeuge-hilfsmittel']; + } + + if (preg_match('/(wooden|stone|iron|golden|diamond|netherite|copper)_(sword|spear)/', $item_id)) { + return ['kampf']; + } + + if (preg_match('/(leather|chainmail|iron|golden|diamond|netherite|copper|turtle)_(helmet|chestplate|leggings|boots|cap|tunic|pants|shell)/', $item_id)) { + return ['kampf']; + } + + if (in_array($item_id, [ + 'bow', 'crossbow', 'arrow', 'spectral_arrow', 'tipped_arrow', + 'shield', 'trident', 'mace', + 'totem_of_undying', 'elytra', + 'horse_armor', 'iron_horse_armor', 'golden_horse_armor', 'diamond_horse_armor', + 'wolf_armor' + ]) || strpos($item_id, 'horse_armor') !== false) { + return ['kampf']; + } + + if (preg_match('/(raw_|cooked_)?(beef|porkchop|mutton|chicken|rabbit|cod|salmon)/', $item_id)) { + return ['nahrung-tranke']; + } + + if (in_array($item_id, [ + 'apple', 'golden_apple', 'enchanted_golden_apple', + 'melon_slice', 'glow_berries', 'sweet_berries', 'chorus_fruit', + 'carrot', 'golden_carrot', 'potato', 'baked_potato', 'poisonous_potato', + 'beetroot', + 'bread', 'cookie', 'cake', 'pumpkin_pie', + 'dried_kelp', + 'tropical_fish', 'pufferfish', 'rotten_flesh', 'spider_eye' + ])) { + return ['nahrung-tranke']; + } + + if (strpos($item_id, '_stew') !== false || strpos($item_id, '_soup') !== false) { + return ['nahrung-tranke']; + } + + if (strpos($item_id, 'potion') !== false || in_array($item_id, [ + 'honey_bottle', 'milk_bucket', 'glass_bottle', 'dragon_breath', + 'experience_bottle', 'ominous_bottle' + ])) { + return ['nahrung-tranke']; + } + + if (strpos($item_id, '_boat') !== false || strpos($item_id, '_raft') !== false) { + return ['transport']; + } + + if (strpos($item_id, 'minecart') !== false) { + return ['transport']; + } + + if (in_array($item_id, ['elytra', 'saddle', 'lead'])) { + return ['transport']; + } + + if (strpos($item_id, 'redstone') !== false && $item_id !== 'redstone_ore') { + return ['redstone']; + } + + if (in_array($item_id, [ + 'repeater', 'comparator', 'observer', + 'piston', 'sticky_piston', + 'dispenser', 'dropper', 'hopper', + 'lever', 'tripwire_hook', 'daylight_detector', + 'tnt', 'target', 'lightning_rod' + ]) || strpos($item_id, 'button') !== false || strpos($item_id, 'pressure_plate') !== false) { + return ['redstone']; + } + + if (strpos($item_id, '_rail') !== false || $item_id === 'rail') { + return ['redstone']; + } + + $pure_materials = [ + 'stick', 'coal', 'charcoal', 'diamond', 'emerald', 'lapis_lazuli', + 'iron_ingot', 'gold_ingot', 'copper_ingot', 'netherite_ingot', + 'iron_nugget', 'gold_nugget', 'copper_nugget', + 'raw_iron', 'raw_gold', 'raw_copper', + 'netherite_scrap', 'netherite_upgrade', + 'amethyst_shard', 'prismarine_shard', 'prismarine_crystals', + 'quartz', 'nether_quartz', 'echo_shard', 'disc_fragment', + 'string', 'feather', 'leather', 'rabbit_hide', + 'slimeball', 'ender_pearl', 'ender_eye', + 'blaze_rod', 'blaze_powder', 'magma_cream', 'ghast_tear', + 'nether_star', 'nether_brick', + 'nautilus_shell', 'heart_of_the_sea', 'scute', 'turtle_scute', 'armadillo_scute', + 'bone', 'bone_meal', 'gunpowder', 'glowstone_dust', 'sugar', + 'phantom_membrane', 'ink_sac', 'glow_ink_sac', + 'paper', 'book', 'flint', + 'fermented_spider_eye', 'glistering_melon_slice', 'rabbit_foot', + 'nether_wart', 'breeze_rod', + 'clay_ball', 'brick', 'firework_star', + 'shulker_shell', 'popped_chorus_fruit' + ]; + + if (in_array($item_id, $pure_materials)) { + return ['zutaten']; + } + + if (strpos($item_id, '_pottery_sherd') !== false || strpos($item_id, '_armor_trim') !== false) { + return ['zutaten']; + } + + if (in_array($item_id, [ + 'dirt', 'coarse_dirt', 'rooted_dirt', 'grass_block', 'podzol', 'mycelium', + 'farmland', 'dirt_path', + 'sand', 'red_sand', 'gravel', 'clay', + 'suspicious_sand', 'suspicious_gravel' + ])) { + return ['natur']; + } + + if (strpos($item_id, '_leaves') !== false || strpos($item_id, '_sapling') !== false || + strpos($item_id, 'azalea') !== false) { + return ['natur']; + } + + $flowers = [ + 'dandelion', 'poppy', 'blue_orchid', 'allium', 'azure_bluet', + 'red_tulip', 'orange_tulip', 'white_tulip', 'pink_tulip', + 'oxeye_daisy', 'cornflower', 'lily_of_the_valley', 'wither_rose', + 'sunflower', 'lilac', 'rose_bush', 'peony', + 'pitcher_plant', 'pitcher_pod', 'torchflower', 'torchflower_seeds', + 'pink_petals', 'spore_blossom' + ]; + if (in_array($item_id, $flowers)) { + return ['natur']; + } + + if (strpos($item_id, 'mushroom') !== false || strpos($item_id, 'fungus') !== false || + in_array($item_id, ['short_grass', 'tall_grass', 'fern', 'large_fern', 'dead_bush'])) { + return ['natur']; + } + + if (in_array($item_id, [ + 'seagrass', 'tall_seagrass', 'kelp', 'dried_kelp', 'sea_pickle', + 'vine', 'weeping_vines', 'twisting_vines', 'cave_vines', 'glow_lichen', + 'hanging_roots', 'mangrove_roots', 'muddy_mangrove_roots' + ])) { + return ['natur']; + } + + if (strpos($item_id, '_seeds') !== false || in_array($item_id, [ + 'wheat', 'beetroot', 'carrot', 'potato', + 'melon', 'pumpkin', 'carved_pumpkin', + 'sugar_cane', 'bamboo', 'cocoa_beans', + 'sweet_berries', 'glow_berries', 'sweet_berry_bush', + 'nether_wart', 'cactus', + 'mangrove_propagule' + ])) { + return ['natur']; + } + + if (in_array($item_id, [ + 'crimson_roots', 'warped_roots', 'nether_sprouts', + 'crimson_nylium', 'warped_nylium' + ])) { + return ['natur']; + } + + if (in_array($item_id, [ + 'moss_block', 'moss_carpet', + 'big_dripleaf', 'small_dripleaf', + 'lily_pad', 'bee_nest', 'honeycomb', 'honeycomb_block', + 'snow', 'snowball', 'powder_snow' + ])) { + return ['natur']; + } + + if (strpos($item_id, 'glass') !== false && strpos($item_id, '_pane') === false) { + return ['dekorationsblocke']; + } + if (strpos($item_id, 'glass_pane') !== false || strpos($item_id, 'stained_glass_pane') !== false) { + return ['dekorationsblocke']; + } + + if (strpos($item_id, '_door') !== false || strpos($item_id, '_trapdoor') !== false || + strpos($item_id, '_fence_gate') !== false) { + return ['dekorationsblocke']; + } + + if ((strpos($item_id, '_fence') !== false && strpos($item_id, '_fence_gate') === false) || + (strpos($item_id, '_wall') !== false && !in_array($item_id, ['wall_banner', 'wall_sign', 'wall_torch'])) || + $item_id === 'iron_bars') { + return ['dekorationsblocke']; + } + + if (strpos($item_id, '_stairs') !== false || strpos($item_id, '_slab') !== false) { + return ['dekorationsblocke']; + } + + if (strpos($item_id, '_carpet') !== false) { + return ['dekorationsblocke']; + } + + if (in_array($item_id, [ + 'torch', 'soul_torch', 'lantern', 'soul_lantern', + 'campfire', 'soul_campfire', 'end_rod', + 'shroomlight', 'froglight', 'sea_lantern' + ]) || strpos($item_id, '_candle') !== false || $item_id === 'candle') { + return ['dekorationsblocke']; + } + + if (in_array($item_id, [ + 'crafting_table', 'furnace', 'blast_furnace', 'smoker', + 'chest', 'trapped_chest', 'ender_chest', 'barrel', + 'enchanting_table', 'anvil', 'chipped_anvil', 'damaged_anvil', + 'grindstone', 'smithing_table', 'cartography_table', 'fletching_table', + 'loom', 'stonecutter', 'brewing_stand', 'cauldron', 'composter', + 'lectern', 'bookshelf', 'chiseled_bookshelf', + 'bell', 'beacon', 'conduit', 'lodestone', 'respawn_anchor' + ]) || strpos($item_id, '_bed') !== false || strpos($item_id, 'shulker_box') !== false) { + return ['dekorationsblocke']; + } + + if (strpos($item_id, '_sign') !== false || strpos($item_id, '_hanging_sign') !== false || + strpos($item_id, '_banner') !== false || + in_array($item_id, ['item_frame', 'glow_item_frame', 'painting', 'armor_stand'])) { + return ['dekorationsblocke']; + } + + if (in_array($item_id, [ + 'ladder', 'scaffolding', 'chain', + 'flower_pot', 'decorated_pot', + 'dragon_egg', 'dragon_head', + 'note_block', 'jukebox' + ]) || strpos($item_id, '_head') !== false || strpos($item_id, '_skull') !== false || + strpos($item_id, 'coral') !== false) { + return ['dekorationsblocke']; + } + + if (in_array($item_id, [ + 'stone', 'cobblestone', 'mossy_cobblestone', + 'granite', 'polished_granite', 'diorite', 'polished_diorite', + 'andesite', 'polished_andesite', 'calcite', 'tuff', + 'smooth_stone' + ]) || strpos($item_id, 'stone_brick') !== false) { + return ['baublocke']; + } + + if (strpos($item_id, 'deepslate') !== false) { + return ['baublocke']; + } + + if (strpos($item_id, 'brick') !== false && $item_id !== 'brick' && $item_id !== 'nether_brick') { + return ['baublocke']; + } + + if (strpos($item_id, 'sandstone') !== false) { + return ['baublocke']; + } + + if (strpos($item_id, 'quartz_') !== false && strpos($item_id, 'nether_quartz') === false) { + return ['baublocke']; + } + + if (strpos($item_id, 'prismarine') !== false || strpos($item_id, 'purpur') !== false) { + return ['baublocke']; + } + + if (strpos($item_id, 'concrete') !== false || strpos($item_id, 'terracotta') !== false) { + return ['baublocke']; + } + + if (strpos($item_id, '_wool') !== false) { + return ['baublocke']; + } + + if (strpos($item_id, '_planks') !== false || + (strpos($item_id, '_log') !== false && strpos($item_id, 'stripped') === false) || + (strpos($item_id, '_wood') !== false && strpos($item_id, 'stripped') === false)) { + return ['baublocke']; + } + + if (strpos($item_id, 'stripped_') !== false) { + return ['baublocke']; + } + + if (in_array($item_id, ['bamboo_block', 'bamboo_mosaic', 'crimson_stem', 'warped_stem', + 'crimson_hyphae', 'warped_hyphae'])) { + return ['baublocke']; + } + + if (strpos($item_id, 'copper_') !== false && strpos($item_id, '_ingot') === false && + strpos($item_id, '_nugget') === false && $item_id !== 'copper_door' && $item_id !== 'copper_trapdoor') { + return ['baublocke']; + } + + if (strpos($item_id, '_block') !== false) { + return ['baublocke']; + } + + if (in_array($item_id, [ + 'netherrack', 'soul_sand', 'soul_soil', + 'basalt', 'polished_basalt', 'smooth_basalt', + 'end_stone', 'obsidian', 'crying_obsidian' + ]) || strpos($item_id, 'blackstone') !== false || strpos($item_id, 'end_stone_brick') !== false) { + return ['baublocke']; + } + + if (in_array($item_id, [ + 'glowstone', 'sponge', 'wet_sponge', + 'ice', 'packed_ice', 'blue_ice', + 'magma_block', 'slime_block', 'honey_block', + 'hay_block', 'dried_kelp_block', + 'mud', 'packed_mud', 'mud_bricks', + 'dripstone_block', 'amethyst_block', 'budding_amethyst' + ])) { + return ['baublocke']; + } + + return ['baublocke']; + } +} + // =========================================================== // DATABASE HELPER // =========================================================== @@ -190,11 +579,54 @@ class WIS_DB { global $wpdb; $table = $wpdb->prefix . 'wis_items'; - $where = isset($args['status']) ? $wpdb->prepare("WHERE status = %s", $args['status']) : "WHERE 1=1"; + $where_parts = ["1=1"]; + + if (isset($args['status'])) { + $where_parts[] = $wpdb->prepare("status = %s", $args['status']); + } + + if (isset($args['category_slug']) && !empty($args['category_slug'])) { + $search_pattern = '%"' . $args['category_slug'] . '"%'; + $where_parts[] = $wpdb->prepare("categories LIKE %s", $search_pattern); + } + + if (isset($args['ids']) && is_array($args['ids']) && !empty($args['ids'])) { + $ids = array_map('intval', $args['ids']); + $placeholders = implode(',', array_fill(0, count($ids), '%d')); + $where_parts[] = sprintf("id IN ($placeholders)", ...$ids); + } + + if (isset($args['search']) && !empty($args['search'])) { + $search_like = '%' . $wpdb->esc_like($args['search']) . '%'; + $where_parts[] = $wpdb->prepare("(name LIKE %s OR item_id LIKE %s)", $search_like, $search_like); + } + + $where = implode(" AND ", $where_parts); $limit = isset($args['limit']) ? "LIMIT " . intval($args['limit']) : ""; $orderby = isset($args['orderby']) ? "ORDER BY " . sanitize_text_field($args['orderby']) : "ORDER BY name ASC"; - return $wpdb->get_results("SELECT * FROM $table $where $orderby $limit"); + return $wpdb->get_results("SELECT * FROM $table WHERE $where $orderby $limit"); + } + + public static function count_items($args = []) { + global $wpdb; + $table = $wpdb->prefix . 'wis_items'; + $where_parts = ["1=1"]; + + if (isset($args['status'])) { + $where_parts[] = $wpdb->prepare("status = %s", $args['status']); + } + if (isset($args['category_slug']) && !empty($args['category_slug'])) { + $search_pattern = '%"' . $args['category_slug'] . '"%'; + $where_parts[] = $wpdb->prepare("categories LIKE %s", $search_pattern); + } + if (isset($args['search']) && !empty($args['search'])) { + $search_like = '%' . $wpdb->esc_like($args['search']) . '%'; + $where_parts[] = $wpdb->prepare("(name LIKE %s OR item_id LIKE %s)", $search_like, $search_like); + } + + $where = implode(" AND ", $where_parts); + return (int) $wpdb->get_var("SELECT COUNT(*) FROM $table WHERE $where"); } public static function get_item($id) { @@ -215,6 +647,12 @@ class WIS_DB { public static function insert_item($data) { global $wpdb; + + if (empty($data['categories']) || $data['categories'] === '[]') { + $auto_cats = WIS_Item_Categorizer::auto_categorize($data['item_id']); + $data['categories'] = json_encode($auto_cats); + } + return $wpdb->insert($wpdb->prefix . 'wis_items', $data); } @@ -228,7 +666,6 @@ class WIS_DB { return $wpdb->delete($wpdb->prefix . 'wis_items', ['id' => $id]); } - // Servers public static function get_servers() { global $wpdb; return $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wis_servers ORDER BY name ASC"); @@ -247,7 +684,6 @@ class WIS_DB { return $wpdb->delete($wpdb->prefix . 'wis_servers', ['id' => $id]); } - // Categories public static function get_categories() { global $wpdb; return $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wis_categories ORDER BY name ASC"); @@ -266,7 +702,6 @@ class WIS_DB { return $wpdb->delete($wpdb->prefix . 'wis_categories', ['id' => $id]); } - // Coupons public static function get_coupons() { global $wpdb; return $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wis_coupons ORDER BY created_at DESC"); @@ -299,7 +734,6 @@ class WIS_DB { return $wpdb->delete($wpdb->prefix . 'wis_coupons', ['id' => $id]); } - // Orders public static function get_orders($limit = 100) { global $wpdb; return $wpdb->get_results($wpdb->prepare( @@ -363,7 +797,6 @@ class WIS_Admin { } public static function page_overview() { - // Handle settings save if (isset($_POST['wis_save_settings']) && check_admin_referer('wis_settings')) { update_option('wis_currency_name', sanitize_text_field($_POST['wis_currency_name'])); update_option('wis_image_base_url', esc_url_raw($_POST['wis_image_base_url'])); @@ -371,8 +804,14 @@ class WIS_Admin { update_option('wis_coupon_exclude_offers', isset($_POST['wis_coupon_exclude_offers']) ? '1' : '0'); update_option('wis_daily_deal_enabled', isset($_POST['wis_daily_deal_enabled']) ? '1' : '0'); update_option('wis_daily_deal_discount', intval($_POST['wis_daily_deal_discount'])); + update_option('wis_offline_queue_enabled', isset($_POST['wis_offline_queue_enabled']) ? '1' : '0'); echo '
✅ Einstellungen gespeichert!
🔑 Neuer API-Key generiert! Bitte in der config.yml des Spigot-Plugins aktualisieren.
Erfordert Spigot-Plugin v6.3+ mit Offline-Queue-Unterstützung
++ +
Dieser Key muss in der config.yml des Spigot-Plugins als api-key eingetragen werden.
+ Geschützte Endpunkte: pending_orders, execute_order, complete_order, cancel_order, pending_offline
+
Aktion: für Items.
-