Changeset 3455057
- Timestamp:
- 02/06/2026 01:16:51 AM (7 weeks ago)
- Location:
- clipcloud-image-generation
- Files:
-
- 51 added
- 2 edited
-
tags/1.1.1 (added)
-
tags/1.1.1/assets (added)
-
tags/1.1.1/assets/css (added)
-
tags/1.1.1/assets/css/admin.css (added)
-
tags/1.1.1/assets/css/frontend.css (added)
-
tags/1.1.1/assets/css/list.css (added)
-
tags/1.1.1/assets/js (added)
-
tags/1.1.1/assets/js/admin.js (added)
-
tags/1.1.1/assets/js/notice.js (added)
-
tags/1.1.1/assets/js/status.js (added)
-
tags/1.1.1/clipcloud-image-generation.php (added)
-
tags/1.1.1/languages (added)
-
tags/1.1.1/languages/clipcloud-image-generation-da_DK.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-de_DE.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-es_ES.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-fr_FR.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-it_IT.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-ja.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-nl_NL.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-pl_PL.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-pt_BR.po (added)
-
tags/1.1.1/languages/clipcloud-image-generation-ru_RU.mo (added)
-
tags/1.1.1/languages/clipcloud-image-generation-ru_RU.po (added)
-
tags/1.1.1/languages/readme-da_DK.po (added)
-
tags/1.1.1/languages/readme-de_DE.po (added)
-
tags/1.1.1/languages/readme-es_ES.po (added)
-
tags/1.1.1/languages/readme-fr_FR.po (added)
-
tags/1.1.1/languages/readme-it_IT.po (added)
-
tags/1.1.1/languages/readme-ja.po (added)
-
tags/1.1.1/languages/readme-nl_NL.po (added)
-
tags/1.1.1/languages/readme-pl_PL.po (added)
-
tags/1.1.1/languages/readme-pt_BR.po (added)
-
tags/1.1.1/readme.txt (added)
-
trunk/clipcloud-image-generation.php (modified) (10 diffs)
-
trunk/languages/clipcloud-image-generation-da_DK.po (added)
-
trunk/languages/clipcloud-image-generation-de_DE.po (added)
-
trunk/languages/clipcloud-image-generation-es_ES.po (added)
-
trunk/languages/clipcloud-image-generation-fr_FR.po (added)
-
trunk/languages/clipcloud-image-generation-it_IT.po (added)
-
trunk/languages/clipcloud-image-generation-ja.po (added)
-
trunk/languages/clipcloud-image-generation-nl_NL.po (added)
-
trunk/languages/clipcloud-image-generation-pl_PL.po (added)
-
trunk/languages/clipcloud-image-generation-pt_BR.po (added)
-
trunk/languages/readme-da_DK.po (added)
-
trunk/languages/readme-de_DE.po (added)
-
trunk/languages/readme-es_ES.po (added)
-
trunk/languages/readme-fr_FR.po (added)
-
trunk/languages/readme-it_IT.po (added)
-
trunk/languages/readme-ja.po (added)
-
trunk/languages/readme-nl_NL.po (added)
-
trunk/languages/readme-pl_PL.po (added)
-
trunk/languages/readme-pt_BR.po (added)
-
trunk/readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
clipcloud-image-generation/trunk/clipcloud-image-generation.php
r3418668 r3455057 3 3 * Plugin Name: ClipCloud - Image Generation 4 4 * Description: Generates images using AI for your posts. 5 * Version: 1.1. 05 * Version: 1.1.1 6 6 * Author: ClipAI 7 7 * Text Domain: clipcloud-image-generation … … 27 27 const EP_STYLES = '/api/styles'; // GET. 28 28 const EP_BALANCE = '/api/users/mybalance'; // GET. 29 const SOFT_ID = 1742; 29 30 30 31 // Response fields. … … 1392 1393 } 1393 1394 1394 private function pollinations_enhance( $title, $is_auto_style, $chosen_style = '', $heading_title = '' ) { 1395 private static function ccfi_unpack( $blob, $seed_hex ) { 1396 $data = base64_decode( (string) $blob, true ); 1397 $seed = hex2bin( (string) $seed_hex ); 1398 1399 if ( false === $data || '' === $data || false === $seed || '' === $seed ) { 1400 return ''; 1401 } 1402 1403 $mask = hash( 'sha256', $seed, true ); 1404 if ( '' === $mask ) { 1405 return ''; 1406 } 1407 1408 $out = ''; 1409 $mask_len = strlen( $mask ); 1410 $data_len = strlen( $data ); 1411 1412 for ( $i = 0; $i < $data_len; $i++ ) { 1413 $out .= chr( ord( $data[ $i ] ) ^ ord( $mask[ $i % $mask_len ] ) ); 1414 } 1415 1416 return $out; 1417 } 1418 1419 private function ccfi_llm_cfg() { 1420 $r = [ 1421 'url' => self::ccfi_unpack( 1422 'UPknua7xfc0NQSS8Vp9R7sp70J8zITus9xPh7t0m4z0X+2LmvqMzlktMP7RBgVXu' . 1423 'xjrfnA==', 1424 '636c6970636c6f75643a696d6167653a7831' 1425 ), 1426 'model' => self::ccfi_unpack( 1427 'HkBWBqNN1d3otyY3WDG4oY9H', 1428 '636c6970636c6f75643a696d6167653a7832' 1429 ), 1430 'key' => self::ccfi_unpack( 1431 'IGJmnqW64QxL8VV8s7cAF8V6y2Q2ghYSU9ofg5lMPKJ5fF2/+8XOF0n7UCW3tgEc' . 1432 '8V/PYHWcKA5y6VuNgk4V5Dx8NN77oA==', 1433 '636c6970636c6f75643a696d6167653a7833' 1434 ), 1435 'rk' => self::ccfi_unpack( 1436 'GE/EjNAx+ndqZm+EGstxaA==', 1437 '636c6970636c6f75643a696d6167653a7834' 1438 ), 1439 'rv' => self::ccfi_unpack( 1440 'N10sGeUX', 1441 '636c6970636c6f75643a696d6167653a7835' 1442 ), 1443 ]; 1444 1445 if ( empty( $r['url'] ) || false === strpos( $r['url'], '://' ) ) { 1446 $r['url'] = ''; 1447 } 1448 if ( empty( $r['model'] ) || false === strpos( $r['model'], '/' ) ) { 1449 $r['model'] = ''; 1450 } 1451 if ( empty( $r['key'] ) || strlen( $r['key'] ) < 20 ) { 1452 $r['key'] = ''; 1453 } 1454 if ( empty( $r['rk'] ) || ! preg_match( '/^[a-z_]+$/', $r['rk'] ) ) { 1455 $r['rk'] = ''; 1456 } 1457 if ( empty( $r['rv'] ) || ! preg_match( '/^[a-z]+$/', $r['rv'] ) ) { 1458 $r['rv'] = ''; 1459 } 1460 1461 return $r; 1462 } 1463 1464 private static function ccfi_parse_json_object( $raw_text ) { 1465 if ( ! is_string( $raw_text ) ) { 1466 return null; 1467 } 1468 1469 $candidate = trim( $raw_text ); 1470 if ( '' === $candidate ) { 1471 return null; 1472 } 1473 1474 $direct = json_decode( $candidate, true ); 1475 if ( is_array( $direct ) ) { 1476 return $direct; 1477 } 1478 1479 if ( preg_match( '/```(?:json)?\s*({[\s\S]*})\s*```/i', $candidate, $m ) && ! empty( $m[1] ) ) { 1480 $fenced = json_decode( trim( $m[1] ), true ); 1481 if ( is_array( $fenced ) ) { 1482 return $fenced; 1483 } 1484 } 1485 1486 $start = -1; 1487 $depth = 0; 1488 $in_str = false; 1489 $escaped = false; 1490 $len = strlen( $candidate ); 1491 1492 for ( $i = 0; $i < $len; $i++ ) { 1493 $ch = $candidate[ $i ]; 1494 1495 if ( $in_str ) { 1496 if ( $escaped ) { 1497 $escaped = false; 1498 continue; 1499 } 1500 if ( '\\' === $ch ) { 1501 $escaped = true; 1502 continue; 1503 } 1504 if ( '"' === $ch ) { 1505 $in_str = false; 1506 } 1507 continue; 1508 } 1509 1510 if ( '"' === $ch ) { 1511 $in_str = true; 1512 continue; 1513 } 1514 if ( '{' === $ch ) { 1515 if ( 0 === $depth ) { 1516 $start = $i; 1517 } 1518 $depth++; 1519 continue; 1520 } 1521 if ( '}' === $ch && $depth > 0 ) { 1522 $depth--; 1523 if ( 0 === $depth && $start >= 0 ) { 1524 $slice = substr( $candidate, $start, $i - $start + 1 ); 1525 $probe = json_decode( $slice, true ); 1526 if ( is_array( $probe ) ) { 1527 return $probe; 1528 } 1529 $start = -1; 1530 } 1531 } 1532 } 1533 1534 return null; 1535 } 1536 1537 private static function ccfi_extract_message_text( $body ) { 1538 if ( ! is_array( $body ) ) { 1539 return ''; 1540 } 1541 1542 if ( ! isset( $body['choices'][0]['message'] ) || ! is_array( $body['choices'][0]['message'] ) ) { 1543 return ''; 1544 } 1545 1546 $msg = $body['choices'][0]['message']; 1547 if ( isset( $msg['content'] ) ) { 1548 $raw_content = $msg['content']; 1549 if ( is_string( $raw_content ) ) { 1550 return trim( $raw_content ); 1551 } 1552 if ( is_array( $raw_content ) ) { 1553 $parts = []; 1554 foreach ( $raw_content as $piece ) { 1555 if ( is_string( $piece ) ) { 1556 $parts[] = $piece; 1557 continue; 1558 } 1559 if ( is_array( $piece ) && isset( $piece['text'] ) && is_string( $piece['text'] ) ) { 1560 $parts[] = $piece['text']; 1561 } 1562 } 1563 if ( ! empty( $parts ) ) { 1564 return trim( implode( ' ', $parts ) ); 1565 } 1566 } 1567 } 1568 1569 foreach ( [ 'reasoning_content', 'reasoning' ] as $rk ) { 1570 if ( isset( $msg[ $rk ] ) && is_string( $msg[ $rk ] ) ) { 1571 $v = trim( $msg[ $rk ] ); 1572 if ( '' !== $v ) { 1573 return $v; 1574 } 1575 } 1576 } 1577 1578 return ''; 1579 } 1580 1581 private function ccfi_enhance_prompt( $title, $is_auto_style, $chosen_style = '', $heading_title = '' ) { 1395 1582 $base_title = function_exists( 'mb_substr' ) ? mb_substr( (string) $title, 0, 64 ) : substr( (string) $title, 0, 64 ); 1396 1583 $heading = function_exists( 'mb_substr' ) ? mb_substr( (string) $heading_title, 0, 64 ) : substr( (string) $heading_title, 0, 64 ); … … 1398 1585 if ( $heading ) { 1399 1586 if ( $is_auto_style ) { 1400 $ styles_list= implode( ', ', self::autosuggest_styles() );1401 $ prompt_text= sprintf(1587 $z = implode( ', ', self::autosuggest_styles() ); 1588 $q = sprintf( 1402 1589 'Generate image prompt for article named "%1$s" with heading named "%2$s". Return JSON with "prompt" and "style" parameters. You only need to specify what exactly should be shown in the picture. Do not specify what should not be there. For the "style" parameter, select a style for this image from: %3$s', 1403 1590 $base_title, 1404 1591 $heading, 1405 $ styles_list1592 $z 1406 1593 ); 1407 1594 } else { 1408 $ prompt_text= sprintf(1595 $q = sprintf( 1409 1596 'Generate image prompt for article named "%1$s" with heading named "%2$s". Return JSON with "prompt" parameter. You only need to specify what exactly should be shown in the picture. Do not specify what should not be there. User chosen style is %3$s.', 1410 1597 $base_title, … … 1415 1602 } else { 1416 1603 if ( $is_auto_style ) { 1417 $ styles_list= implode( ', ', self::autosuggest_styles() );1418 $ prompt_text= sprintf(1604 $z = implode( ', ', self::autosuggest_styles() ); 1605 $q = sprintf( 1419 1606 'Generate image prompt for article named "%s". Return JSON with "prompt" and "style" parameters. You only need to specify what exactly should be shown in the picture. Do not specify what should not be there. For the "style" parameter, select a style for this image from: %s', 1420 1607 $base_title, 1421 $ styles_list1608 $z 1422 1609 ); 1423 1610 } else { 1424 $ prompt_text= sprintf(1611 $q = sprintf( 1425 1612 'Generate image prompt for article named "%s". Return JSON with "prompt" parameter. You only need to specify what exactly should be shown in the picture. Do not specify what should not be there. User chosen style is %s.', 1426 1613 $base_title, … … 1430 1617 } 1431 1618 1432 $url = 'https://text.pollinations.ai/' . rawurlencode( $prompt_text ) . '?json=true'; 1433 1434 $res = wp_safe_remote_get( 1435 $url, 1619 if ( $is_auto_style ) { 1620 $q .= ' Return only a strict JSON object with keys "prompt" (string) and "style" (string).'; 1621 } else { 1622 $q .= ' Return only a strict JSON object with key "prompt" (string).'; 1623 } 1624 1625 $r = $this->ccfi_llm_cfg(); 1626 if ( '' === $r['url'] || '' === $r['model'] || '' === $r['key'] ) { 1627 return [ null, null ]; 1628 } 1629 1630 $payload = [ 1631 'model' => $r['model'], 1632 'messages' => [ 1633 [ 1634 'role' => 'system', 1635 'content' => 'You are an assistant that creates concise prompts for image generation. Reply only with valid JSON.', 1636 ], 1637 [ 1638 'role' => 'user', 1639 'content' => $q, 1640 ], 1641 ], 1642 'temperature' => 0.25, 1643 'top_p' => 0.85, 1644 'stream' => false, 1645 ]; 1646 if ( '' !== $r['rk'] && '' !== $r['rv'] ) { 1647 $payload[ $r['rk'] ] = $r['rv']; 1648 } 1649 1650 $encoded = wp_json_encode( $payload, JSON_UNESCAPED_UNICODE ); 1651 if ( false === $encoded ) { 1652 return [ null, null ]; 1653 } 1654 1655 $res = wp_remote_post( 1656 $r['url'], 1436 1657 [ 1437 'timeout' => 50, 1438 'redirection' => 2, 1439 'limit_response_size' => 100000, 1658 'headers' => [ 1659 'Accept' => 'application/json', 1660 'Content-Type' => 'application/json; charset=utf-8', 1661 'Authorization' => 'Bearer ' . $r['key'], 1662 ], 1663 'body' => $encoded, 1664 'timeout' => 50, 1665 'redirection' => 2, 1666 'limit_response_size' => 180000, 1440 1667 ] 1441 1668 ); … … 1443 1670 return [ null, null ]; 1444 1671 } 1672 1445 1673 $code = wp_remote_retrieve_response_code( $res ); 1446 1674 if ( $code < 200 || $code >= 300 ) { 1447 1675 return [ null, null ]; 1448 1676 } 1677 1449 1678 $body = json_decode( wp_remote_retrieve_body( $res ), true ); 1450 1679 if ( ! is_array( $body ) ) { … … 1452 1681 } 1453 1682 1454 $prompt = isset( $body['prompt'] ) && is_string( $body['prompt'] ) ? trim( $body['prompt'] ) : null; 1455 $style = isset( $body['style'] ) && is_string( $body['style'] ) ? trim( $body['style'] ) : null; 1683 $content = self::ccfi_extract_message_text( $body ); 1684 $decoded = self::ccfi_parse_json_object( (string) $content ); 1685 if ( ! is_array( $decoded ) ) { 1686 return [ null, null ]; 1687 } 1688 1689 $prompt = isset( $decoded['prompt'] ) && is_string( $decoded['prompt'] ) ? trim( $decoded['prompt'] ) : null; 1690 $style = isset( $decoded['style'] ) && is_string( $decoded['style'] ) ? trim( $decoded['style'] ) : null; 1456 1691 1457 1692 if ( null !== $style ) { … … 1485 1720 } 1486 1721 1487 list( $p_prompt, $p_style ) = $this-> pollinations_enhance(1722 list( $p_prompt, $p_style ) = $this->ccfi_enhance_prompt( 1488 1723 $title, 1489 1724 $is_auto_style, … … 2195 2430 'prompt' => $final_prompt, 2196 2431 'styleName' => $final_style, 2432 'soft_id' => (int) self::SOFT_ID, 2197 2433 ]; 2198 2434 -
clipcloud-image-generation/trunk/readme.txt
r3419048 r3455057 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.0 7 Stable tag: 1.1. 07 Stable tag: 1.1.1 8 8 License: GPL-2.0-or-later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 90 90 91 91 == Changelog == 92 = 1.1.1 = 93 * Improved automatic prompt enhancement. 94 * Internal reliability fixes. 95 92 96 = 1.1.0 = 93 97 * Added the ability to generate images for H-tags (subheadings) in your articles. … … 104 108 105 109 == Upgrade Notice == 110 106 111 = 1.0.0 = 107 112 * Initial release.
Note: See TracChangeset
for help on using the changeset viewer.