0 ]; public $tables = [ 'users', 'groups', 'channels' ]; public function __construct ($configs) { $this->configs = $configs; if ($this->configs['redis']['status']) { $this->response = $this->redisConnect(); if (!$this->response['ok']) { return $this->response; } } if ($this->configs['database']['status']) { $this->response = $this->dbConnect(); if (!$this->response['ok']) { return $this->response; } } return $this->response = ['ok' => 1]; } # Redis Connection public function redisConnect () { if (class_exists('Redis')) { try { $this->redis = new Redis(); $this->redis->connect($this->configs['redis']['host'], $this->configs['redis']['port']); if ($this->configs['redis']['password']) $this->redis->auth($this->configs['redis']['password']); if ($this->configs['redis']['database']) $this->redis->select($this->configs['redis']['database']); return ['ok' => 1]; } catch (Exception $e) { return ['ok' => 0, 'error_code' => 500, 'description' => 'Redis Error: ' . $e->getMessage()]; } } else { return ['ok' => 0, 'error_code' => 500, 'description' => 'Internal Server Error: Redis class not exists']; } } # Redis get public function rget ($key) { if ($this->redis) { try { return $this->redis->get($key); } catch (Exception $e) { } } return 0; } # Redis set public function rset ($key, $value, $time = 0) { if ($this->redis) { try { return $this->redis->set($key, $value, $time); } catch (Exception $e) { } } return 0; } # Redis del public function rdel ($key) { if ($this->redis) { try { return $this->redis->del($key); } catch (Exception $e) { } } return 0; } # Redis keys public function rkeys ($key) { if ($this->redis) { try { return $this->redis->keys($key); } catch (Exception $e) { } } return 0; } # Redis lpush public function rladd ($key, $value) { if ($this->redis) { try { return $this->redis->lPush($key, $value); } catch (Exception $e) { } } return 0; } # Redis lrange public function rlget ($key, $offset = 0, $limit = 50) { if ($this->redis) { try { return $this->redis->lRange($key, $offset, $limit); } catch (Exception $e) { } } return 0; } # Redis lrem public function rldel ($key, $value = 0, $count = 50) { if ($this->redis) { try { return $this->redis->lRem($key, $value, $count); } catch (Exception $e) { } } return 0; } # Database Connection public function dbConnect () { if (class_exists('PDO')) { $this->configs['database']['type'] = strtolower($this->configs['database']['type']); if ($this->configs['database']['type'] == 'sqlite') { return $this->sqliteConnect(); } elseif ($this->configs['database']['type'] == 'mysql') { return $this->mysqlConnect(); } elseif ($this->configs['database']['type'] == 'pgsql') { return $this->pgsqlConnect(); } else { return ['ok' => 0, 'error_code' => 500, 'description' => 'Internal Server Error: unknown database type']; } } else { return ['ok' => 0, 'error_code' => 500, 'description' => 'Internal Server Error: PDO class not found']; } } # PDO Connection with SQLite private function sqliteConnect () { try { $this->PDO = new PDO('sqlite:' . $this->configs['database']['database_name']); return ['ok' => 1]; } catch (PDOException $e) { return ['ok' => 0, 'error_code' => 500, 'description' => 'PDO Error: ' . $e->getMessage()]; } } # PDO Connection with MySQL private function mysqlConnect () { try { $this->PDO = new PDO('mysql:host=' . $this->configs['database']['host'] . ';dbname=' . $this->configs['database']['database_name'] . ';charset=utf8mb4', $this->configs['database']['user'], $this->configs['database']['password']); return ['ok' => 1]; } catch (PDOException $e) { return ['ok' => 0, 'error_code' => 500, 'description' => 'PDO Error: ' . $e->getMessage()]; } } # PDO Connection with PostgreSQL private function pgsqlConnect () { try { $this->PDO = new PDO('pgsql:host=' . $this->configs['database']['host'] . ';dbname=' . strtolower($this->configs['database']['database_name']), strtolower($this->configs['database']['user']), $this->configs['database']['password']); return ['ok' => 1]; } catch (PDOException $e) { return ['ok' => 0, 'error_code' => 500, 'description' => 'PDO Error: ' . $e->getMessage()]; } } # General PDO custom query public function query ($query, $args = 0, $return = 0) { if (!is_string($query)) return ['error' => 'First parameter must be a string']; if (!$this->PDO) return ['error' => 'PDO class not found']; try { $q = $this->PDO->prepare($query); if ($err = $this->PDO->errorInfo() and $err[0] !== '00000') return ['error' => $err]; if (is_array($args) and !empty($args)) { $q->execute($args); } else { $q->execute(); } if ($err = $q->errorInfo() and $err[1] !== null) return ['error' => $err]; if (!$return) { return 1; } elseif ($return === 1) { return $q->fetch(\PDO::FETCH_ASSOC); } else { return $q->fetchAll(); } } catch (PDOException $e) { return ['error' => 'PDO Exception: ' . $e]; } } # Create LIMIT with OFFSET public function limit ($limit = 'ALL', $offset = 0) { if ($this->configs['database']['type'] == 'sqlite') { return 'LIMIT ' . $limit . ' OFFSET ' . round($offset); } elseif ($this->configs['database']['type'] == 'mysql') { return 'LIMIT ' . round($offset) . ', ' . $limit; } elseif ($this->configs['database']['type'] == 'pgsql') { return 'LIMIT ' . $limit . ' OFFSET ' . round($offset); } return; } # Tables Setup for NeleBot X public function setup() { $tables = []; foreach ($this->tables as $table) { $tables[$table] = $this->createTemplateTable($table); } return $tables; } # Templates of users, groups and channels table public function createTemplateTable ($table) { if ($table == 'users') { return $this->query('CREATE TABLE IF NOT EXISTS users ( id BIGINT PRIMARY KEY, name VARCHAR(64) NOT NULL, surname VARCHAR(64), username VARCHAR(32), lang VARCHAR(16) NOT NULL DEFAULT \'en\', settings TEXT NOT NULL DEFAULT \'{}\', registration INT NOT NULL, last_seen INT NOT NULL, ban INT NOT NULL DEFAULT \'0\', status VARCHAR(64) NOT NULL DEFAULT \'Unknown\' );'); } elseif ($table == 'groups') { return $this->query('CREATE TABLE IF NOT EXISTS groups ( id BIGINT PRIMARY KEY, title VARCHAR(64) NOT NULL, description VARCHAR(256), username VARCHAR(32), admins TEXT NOT NULL DEFAULT \'{}\', permissions TEXT NOT NULL DEFAULT \'{}\', settings TEXT NOT NULL DEFAULT \'{}\', registration INT NOT NULL, last_seen INT NOT NULL, ban INT NOT NULL DEFAULT \'0\', status VARCHAR(64) NOT NULL DEFAULT \'Unknown\' );'); } elseif ($table == 'channels') { return $this->query('CREATE TABLE IF NOT EXISTS channels ( id BIGINT PRIMARY KEY, title VARCHAR(64) NOT NULL, description VARCHAR(256), username VARCHAR(32), admins TEXT NOT NULL DEFAULT \'{}\', settings TEXT NOT NULL DEFAULT \'{}\', registration INT NOT NULL, last_seen INT NOT NULL, ban INT NOT NULL DEFAULT \'0\', status VARCHAR(64) NOT NULL DEFAULT \'Unknown\' );'); } return ['error' => 'Table template not found']; } # User on Database public function getUser ($user) { if (!is_array($user)) return ['error' => 'Bad Request: User must be an array']; if (isset($user['id']) or isset($user['username'])) { if (isset($user['id'])) { if ($user['id'] <= 0 or $user['id'] >= 18446744073709551615) return ['error' => 'Bad Request: id is out of range']; $q = $this->query('SELECT * FROM users WHERE id = ?', [round($user['id'])], 1); } else { if (strlen($user['username']) > 32) return ['error' => 'Bad Request: username has too many characters']; $q = $this->query('SELECT * FROM users WHERE LOWER(username) = LOWER(?)', [$user['username']], 1); } if (!isset($q['id']) and $user['first_name']) { if (!isset($user['language_code'])) $user['language_code'] = 'en'; $args = [ $user['id'], $user['first_name'], $user['last_name'], $user['username'], $user['language_code'], time(), time() ]; $i = $this->query('INSERT INTO users (id, name, surname, username, lang, registration, last_seen) VALUES (?,?,?,?,?,?,?)', $args); $q = $this->query('SELECT * FROM users WHERE id = ?', [$user['id']], 1); if (!isset($q['id'])) { return ['error' => 'Error to load user info', 'INSERT' => $i]; } } elseif (isset($user['first_name']) and (($user['first_name'] !== $q['name'] or $user['last_name'] !== $q['surname'] or $user['username'] !== $q['username']) or $q['last_seen'] <= (time() - 60 * 60))) { $q['name'] = $user['first_name']; $q['surname'] = $user['last_name']; $q['username'] = $user['username']; $q['last_seen'] = time(); $this->query('UPDATE users SET name = ?, surname = ?, username = ?, last_seen = ? WHERE id = ?', [$user['first_name'], $user['last_name'], $user['username'], $q['last_seen'], $user['id']]); } // Use this json_decode only if you need it! $q['settings'] = json_decode($q['settings'], 1); if (!is_array($q['settings'])) $q['settings'] = []; return $q; } else { return ['error' => 'There is no id or username']; } } # Group on Database public function getGroup ($chat) { if (!is_array($chat)) return ['error' => 'Bad Request: Chat must be an array']; if (isset($chat['id']) or isset($chat['username'])) { if (isset($chat['id'])) { if ($chat['id'] >= 0) return ['error' => 'Bad Request: id is out of range']; $q = $this->query('SELECT * FROM groups WHERE id = ?', [round($chat['id'])], 1); } else { if (strlen($chat['username']) > 32) return ['error' => 'Bad Request: username has too many characters']; $q = $this->query('SELECT * FROM groups WHERE LOWER(username) = LOWER(?)', [$chat['username']], 1); } if (!isset($q['id']) and $chat['title']) { $args = [ $chat['id'], $chat['title'], $chat['username'], time(), time() ]; $i = $this->query('INSERT INTO groups (id, title, username, registration, last_seen) VALUES (?,?,?,?,?)', $args); $q = $this->query('SELECT * FROM groups WHERE id = ?', [$chat['id']], 1); if (!isset($q['id'])) { return ['error' => 'Error to load chat info', 'INSERT' => $i]; } } elseif (isset($chat['title']) and ($user['title'] !== $q['title'] or $q['last_seen'] <= (time() - 60 * 60))) { $q['title'] = $chat['title']; $q['last_seen'] = time(); $this->query('UPDATE groups SET title = ?, last_seen = ? WHERE id = ?', [$chat['title'], $q['last_seen'], $chat['id']]); } // Use this json_decode only if you need it! else comment these 2 strings $q['settings'] = json_decode($q['settings'], 1); if (!is_array($q['settings'])) $q['settings'] = []; $q['permissions'] = json_decode($q['permissions'], 1); if (!is_array($q['permissions'])) $q['permissions'] = []; $q['admins'] = json_decode($q['admins'], 1); if (!is_array($q['admins'])) $q['admins'] = []; return $q; } else { return ['error' => 'There is no id or username']; } } # Channel on Database public function getChannel ($chat) { if (!is_array($chat)) return ['error' => 'Bad Request: Chat must be an array']; if (isset($chat['id']) or isset($chat['username'])) { if (isset($chat['id'])) { if ($chat['id'] >= 0) return ['error' => 'Bad Request: id is out of range']; $q = $this->query('SELECT * FROM channels WHERE id = ?', [round($chat['id'])], 1); } else { if (strlen($chat['username']) > 32) return ['error' => 'Bad Request: username has too many characters']; $q = $this->query('SELECT * FROM channels WHERE LOWER(username) = LOWER(?)', [$chat['username']], 1); } if (!isset($q['id']) and $chat['title']) { $args = [ $chat['id'], $chat['title'], $chat['username'], time(), time() ]; $i = $this->query('INSERT INTO channels (id, title, username, registration, last_seen) VALUES (?,?,?,?,?)', $args); $q = $this->query('SELECT * FROM channels WHERE id = ?', [$chat['id']], 1); if (!isset($q['id'])) { return ['error' => 'Error to load chat info', 'INSERT' => $i]; } } elseif (isset($chat['title']) and ($user['title'] !== $q['title'] or $q['last_seen'] <= (time() - 60 * 60))) { $q['title'] = $chat['title']; $q['last_seen'] = time(); $this->query('UPDATE channels SET title = ?, last_seen = ? WHERE id = ?', [$chat['title'], $q['last_seen'], $chat['id']]); } // Use this json_decode only if you need it! else comment these 2 strings $q['settings'] = json_decode($q['settings'], 1); if (!is_array($q['settings'])) $q['settings'] = []; $q['admins'] = json_decode($q['admins'], 1); if (!is_array($q['admins'])) $q['admins'] = []; return $q; } else { return ['error' => 'There is no id or username']; } } # Get Chats by Admin (PostgreSQL only) public function getChatsByAdmin ($user_id, $limit = 20) { if (!is_numeric($user_id)) return []; $chats = []; $groups = $this->query('SELECT * FROM groups WHERE admins @> \'[{"user":{"id": ' . $user_id . '}}]\' ' . $this->limit(round($limit / 2)), [], 2); if (isset($groups[0]['id'])) { $chats = array_merge($chats, $groups); } $channels = $this->query('SELECT * FROM channels WHERE admins @> \'[{"user":{"id": ' . $user_id . '}}]\' ' . $this->limit(round($limit / 2)), [], 2); if (isset($channels[0]['id'])) { $chats = array_merge($chats, $channels); } return $chats; } # Ban by id public function ban ($id) { return [ $this->query('UPDATE users SET ban = ? WHERE id = ?', [1, $id]), $this->query('UPDATE groups SET ban = ? WHERE id = ?', [1, $id]), $this->query('UPDATE channels SET ban = ? WHERE id = ?', [1, $id]) ]; } # UnBan by id public function unban ($id) { return [ $this->query('UPDATE users SET ban = ? WHERE id = ?', [0, $id], 1), $this->query('UPDATE groups SET ban = ? WHERE id = ?', [0, $id], 1), $this->query('UPDATE channels SET ban = ? WHERE id = ?', [0, $id], 1) ]; } # Get User ban by user_id public function isBanned ($id) { $q = $this->query('SELECT ban FROM users WHERE id = ?', [$id], 1); if ($q['ban']) return 1; $q = $this->query('SELECT ban FROM groups WHERE id = ?', [$id], 1); if ($q['ban']) return 1; $q = $this->query('SELECT ban FROM channels WHERE id = ?', [$id], 1); if ($q['ban']) return 1; return 0; } # Get User language by user_id public function getLanguage ($id) { if (is_numeric($id) and isset($id) and $id > 0 and $id < 18446744073709551615) { $q = $this->query('SELECT lang FROM users WHERE id = ? LIMIT 1', [round($id)], 1); if (isset($q['lang'])) { return $q['lang']; } } return 'en'; } # Set user Telegram status public function setStatus ($id, $status = 'Unknown', $table = 0) { return $this->query('UPDATE ' . $this->tables[$table] . ' SET status = ? WHERE id = ?', [$status, $id]); } } ?>