-
Notifications
You must be signed in to change notification settings - Fork 1
/
wpai.php
245 lines (194 loc) · 6.61 KB
/
wpai.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
<?php
/**
* Plugin Name: WP AI Code Companion
* Plugin URI: PLUGIN SITE HERE
* Description: An AI Code Companion that you run ENTIRELY AT YOUR OWN RISK
* Author: Ross Wintle
* Author URI: https://rosswintle.uk
* Text Domain: wpai
* Domain Path: /languages
* Version: 0.1.0
*
* @package Wpai
*/
/*
* This is a stupid idea. Don't use this plugin.
*
* You run this code ENTIRELY AT YOUR OWN RISK!!!
*
* I take no responsibility for you website being broken beyond repair; your
* laptop or server being wiped of all files; or ANYTHING that might happen as
* a result of you using this code.
*
* This code tells an AI of dubious trustworthiness to generate more code and
* then runs the "more code" on your computer.
*
* This is REALLY dangerous. You should not do this.
*
* And if you DO do it, do it on a temporary VPS, or a walled-off temporary site,
* or an instawp.com site or something. And you do that - and I can't say this
* strongly enough - entirely at your own risk.
*/
class WPAI {
/**
* The filename to use to save functions to.
*/
const FUNCS_FILENAME = "wpai_funcs.php";
const FUNCS_NAMESPACE = "WPAIFuncs";
const DEBUG = false;
/**
* Initialize the plugin.
*/
public function __construct() {
self::debug_log("Initializing plugin...");
if ( ! function_exists( self::FUNCS_NAMESPACE . '::init' ) ) {
self::load_funcs_file();
}
}
/**
* Print debug messages.
*/
protected static function debug_log( $message ) {
if ( self::DEBUG ) {
echo $message;
}
}
/**
* Create the functions file in mu-plugins.
*/
protected static function create_funcs_file() {
self::debug_log("Creating funcs file...");
$funcs_file = self::get_funcs_filename();
$funcs_file_contents = "<?php
namespace " . self::FUNCS_NAMESPACE . ";
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// This file is automatically generated by the WP AI Code Companion plugin.
// NEW FUNCTIONS GO HERE
";
file_put_contents($funcs_file, $funcs_file_contents);
}
/**
* Load the functions file. Create it if it doesn't exist.
*/
protected static function load_funcs_file() {
self::debug_log("Loading funcs file...");
$funcs_file = self::get_funcs_filename();
if ( ! file_exists( $funcs_file ) ) {
self::create_funcs_file();
}
require_once $funcs_file;
}
public static function __callStatic( $name, $arguments ) {
self::debug_log("Calling function $name");
// Check if the function exists as a method in the functions class.
if ( self::function_exists( $name ) ) {
self::debug_log("Calling existing function $name");
return self::call_function( $name, $arguments );
}
self::debug_log("Calling new function $name");
$function_to_ask_for = str_replace('_', ' ', $name);
$params_array = [];
foreach ($arguments as $arg_name => $arg_value) {
if (is_numeric($arg_name)) {
$arg_name = 'param' . $arg_name;
}
$params_array[] = gettype($arg_value) . ' $' . $arg_name;
}
$params_string = implode(', ', $params_array);
$api_query =
"
Create a single, self-contained, complete PHP function called $name that will $function_to_ask_for
Create only one function, and do not use any other functions. Assume no other functions exist and inline all code into one function.
The function runs inside a WordPress plugin.
The function exists in the namespace " . self::FUNCS_NAMESPACE . " but do not include the namespace declaration.
Do not include any add_action or add_filter calls. Any registration functions are inside the function itself.
After the function's closing bracket add a comment that says \"// END FUNCTION\"
";
// echo $api_query . "\n\n//----------------------\n\n";
$function = self::send_query($api_query, ['stop' => '// END FUNCTION']);
// var_dump($function);
self::write_function_to_file($function);
// Create a temporary, global function to run the code.
$temp_function = str_replace( "function $name", "function wpai_temp_$name", $function );
eval($temp_function);
$func_name = 'wpai_temp_' . $name;
return $func_name(...$arguments);
}
// Get the functions filename.
protected static function get_funcs_filename() {
return WPMU_PLUGIN_DIR . '/' . self::FUNCS_FILENAME;
}
// Check if a function exists in the functions class.
protected static function function_exists( $name ) {
return function_exists( self::FUNCS_NAMESPACE . '\\' . $name );
}
// Call a function in the functions class.
protected static function call_function( $name, $arguments ) {
return call_user_func_array( self::FUNCS_NAMESPACE . '\\' . $name, $arguments );
}
// Write a function to the functions file.
protected static function write_function_to_file( $function ) {
$function = self::strip_comments($function);
$funcs_file = self::get_funcs_filename();
$funcs_file_contents = file_get_contents($funcs_file);
$funcs_file_contents = str_replace('// NEW FUNCTIONS GO HERE', $function . "\n\n// NEW FUNCTIONS GO HERE", $funcs_file_contents);
file_put_contents($funcs_file, $funcs_file_contents);
}
// Strip comments from a string.
public static function strip_comments($string) {
return preg_replace('/\/\*.*\*\//ms', '', $string);
}
public static function query($text) {
$api_query = "
Write a WordPress WP_Posts query that assignes the results to a variable \$posts and fetches
$text
Do not explain the function, just give me the raw code.";
// echo $api_query . "\n\n----------------------\n\n";
echo self::send_query($api_query, ['stop' => ']);']);
}
// Send a query to OpenAI
protected static function send_query($text, $options=[]) {
$defaults = [
'model' => 'gpt-3.5-turbo',
'messages' => [
[
'role' => 'system',
'content' => 'You are my helpful, PHP and WordPress coding helper',
],
[
'role' => 'user',
'content' => $text,
],
],
'max_tokens' => 1500,
'temperature' => 0,
'stream' => false,
];
$options = array_merge( $defaults, $options );
$response = wp_remote_post('https://api.openai.com/v1/chat/completions', [
'headers' => [
'Authorization' => 'Bearer ' . WPAI_API_KEY,
'Content-Type' => 'application/json',
],
'timeout' => 20,
'body' => json_encode($options),
]);
// echo "Response is:";
// var_dump($response);
if (is_wp_error( $response ) ) {
echo "Error: " . $response->get_error_message();
return false;
}
if (200 !== $response['response']['code']) {
echo "Error: " . $response['response']['message'];
return false;
}
$response_json = json_decode($response['body']);
// var_dump($response_json->choices[0]);
return $response_json->choices[0]->message->content;
}
}
// Initialize the plugin.
new WPAI();