commit 62b7a08bc3948dc6a067cb9e08f35c976e62753c Author: flashwave Date: Mon Jul 4 00:07:38 2022 +0000 Initial import diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..293c98f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/config/git-broadcast.ini +/config/flashii.ini diff --git a/public/_flashii.php b/public/_flashii.php new file mode 100644 index 0000000..e433f25 --- /dev/null +++ b/public/_flashii.php @@ -0,0 +1,42 @@ + PDO::CASE_NATURAL, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::ATTR_EMULATE_PREPARES => false, + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET SESSION time_zone = \'+00:00\'' + . ', sql_mode = \'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION\'', + ]); +} catch(PDOException $ex) { + http_response_code(500); + echo '{"error":103}'; + exit; +} diff --git a/public/charasort-shit.php b/public/charasort-shit.php new file mode 100644 index 0000000..cdfd2b5 --- /dev/null +++ b/public/charasort-shit.php @@ -0,0 +1,72 @@ +prepare('SELECT `role_id`, `role_name` FROM `msz_roles` WHERE `role_hidden` = 0 ORDER BY `role_id` ASC'); +$getRoles->execute(); +while(($role = $getRoles->fetch()) !== false) + printf(' { name: "%s", key: "R%d" },%s', $role[1], $role[0], PHP_EOL); + +printf(' ],%s', PHP_EOL); +printf(' },%s', PHP_EOL); +printf(' {%s', PHP_EOL); +printf(' name: "Remove inactive members",%s', PHP_EOL); +printf(' key: "inactive",%s', PHP_EOL); +printf(' tooltip: "Limits the selection to people who have showed up within the last year.",%s', PHP_EOL); +printf(' },%s', PHP_EOL); +printf(' {%s', PHP_EOL); +printf(' name: "Remove members with no posts",%s', PHP_EOL); +printf(' key: "noposts",%s', PHP_EOL); +printf(' tooltip: "Removes members that have not made any forum posts yet.",%s', PHP_EOL); +printf(' },%s', PHP_EOL); +printf('];%s', PHP_EOL); + +echo PHP_EOL; + +printf('dataSet[dataSetVersion].characterData = [%s', PHP_EOL); + +$getUsers = $db->prepare('SELECT `user_id`, `username`, `user_active` > NOW() - INTERVAL 1 YEAR AS `user_active`, (SELECT COUNT(*) FROM `msz_forum_posts` WHERE `user_id` = u.`user_id` AND `post_deleted` IS NULL) AS `user_posts` FROM `msz_users` AS u WHERE `user_deleted` IS NULL ORDER BY `user_id` ASC'); +$getUsers->execute(); +while(($user = $getUsers->fetch()) !== false) { + printf(' {%s', PHP_EOL); + printf(' name: "%s",%s', $user[1], PHP_EOL); + printf(' img: "https://flashii.net/assets/avatar/%d?res=300",%s', $user[0], PHP_EOL); + printf(' opts: {%s', PHP_EOL); + printf(' role: [', PHP_EOL); + + $getRoles = $db->prepare('SELECT `role_id` FROM `msz_user_roles` WHERE `user_id` = :user'); + $getRoles->bindValue('user', $user[0]); + $getRoles->execute(); + while(($role = $getRoles->fetchColumn()) !== false) + printf(' "R%d", ', $role); + + printf('],%s', PHP_EOL); + + if(!$user[2]) + printf(' inactive: true,%s', PHP_EOL); + + if($user[3] < 1) + printf(' noposts: true,%s', PHP_EOL); + + printf(' },%s', PHP_EOL); + printf(' },%s', PHP_EOL); +} + +printf('];%s', PHP_EOL); diff --git a/public/exrate.php b/public/exrate.php new file mode 100644 index 0000000..b49411e --- /dev/null +++ b/public/exrate.php @@ -0,0 +1,83 @@ + PDO::CASE_NATURAL, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::ATTR_EMULATE_PREPARES => false, + PDO::MYSQL_ATTR_INIT_COMMAND => " + SET SESSION + sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION', + time_zone = '+00:00'; + ", + ]); +} catch(PDOException $ex) { + die((string)$ex); +} + +define('EXRATE_INTER', 'EUR'); +define('EXRATE_COMMON', [ + 'EUR', 'AUD', 'GBP', 'CAD', 'USD', 'JPY', 'PLN', 'SGD', 'RUB', 'ILS', +]); + +$from = strtoupper((string)filter_input(INPUT_GET, 'from', FILTER_SANITIZE_STRING)); +$to = strtoupper((string)filter_input(INPUT_GET, 'to', FILTER_SANITIZE_STRING)); +$amount = (string)(filter_input(INPUT_GET, 'amount', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) ?? '1'); + +if((!empty($to) && strlen($to) !== 3) || strlen($from) !== 3) { + http_response_code(400); + die('Invalid currency specified.'); +} + +$needsRefresh = $pdo->prepare('SELECT MAX(`rate_stored`) <= NOW() - INTERVAL 1 DAY FROM `exchange-rates` LIMIT 1'); +$needsRefresh = $needsRefresh->execute() ? $needsRefresh->fetchColumn() : 1; +if($needsRefresh !== 0) { + $data = json_decode(file_get_contents('https://api.exchangerate.host/latest?base=' . EXRATE_INTER), true); + if($data !== null) { + $pdo->exec('TRUNCATE `exchange-rates`;'); + $insertCurrency = $pdo->prepare('REPLACE INTO `exchange-rates` (`rate_from`, `rate_to`, `rate_value`) VALUES (:from, :to, :value)'); + $insertCurrency->bindValue('from', $data['base']); + foreach($data['rates'] as $currency => $rate) { + $insertCurrency->bindValue('to', $currency); + $insertCurrency->bindValue('value', $rate); + $insertCurrency->execute(); + } + } +} + +$result = new stdClass; +$result->from = $from; +$result->to = $to; +$result->amount = (float)$amount; + +if($from === $to) { + $result->result = $result->amount; +} else { + $convertCurrency = $pdo->prepare('SELECT (SELECT (:amount / `rate_value`) FROM `exchange-rates` WHERE `rate_from` = \'' . EXRATE_INTER . '\' AND `rate_to` = :from) * `rate_value` FROM `exchange-rates` WHERE `rate_from` = \'' . EXRATE_INTER . '\' AND `rate_to` = :to;'); + $convertCurrency->bindValue('from', $from); + $convertCurrency->bindValue('amount', $amount); + + if(empty($to)) { + $result->results = []; + foreach(EXRATE_COMMON as $commonCurrency) { + if($commonCurrency === $from) + continue; + $result->results[] = $current = new stdClass; + $current->to = $commonCurrency; + $convertCurrency->bindValue('to', $commonCurrency); + $convertCurrency->execute(); + $current->result = $convertCurrency->fetchColumn() ?? 0; + } + } else { + $convertCurrency->bindValue('to', $to); + $convertCurrency->execute(); + $result->result = $convertCurrency->fetchColumn() ?? 0; + } +} + +http_response_code(200); +header('Content-Type: application/json'); +echo json_encode($result); diff --git a/public/get-profile-field.php b/public/get-profile-field.php new file mode 100644 index 0000000..1ddb6d8 --- /dev/null +++ b/public/get-profile-field.php @@ -0,0 +1,22 @@ +prepare('SELECT `field_value` FROM `msz_profile_fields_values` WHERE `field_id` = :field AND `user_id` = :user'); + $fetch->bindValue('user', $userId); + $fetch->bindValue('field', $fieldId); + $fetch->execute(); + $data = $fetch->fetchObject(); + if($data) + echo json_encode($data); + else { + http_response_code(404); + echo '{"error":105}'; + } +} catch(PDOException $ex) { + http_response_code(500); + echo '{"error":104}'; +} diff --git a/public/get-user-for-tetrio.php b/public/get-user-for-tetrio.php new file mode 100644 index 0000000..24f0f0f --- /dev/null +++ b/public/get-user-for-tetrio.php @@ -0,0 +1,47 @@ +profileFields(); +$discord = ''; +foreach($fields as $field) + if($field->field_key === 'discord') { + $discord = $field->field_value; + break; + } + +$regAddr = $userInfo->getRegisterRemoteAddress(); +$lastAddr = $userInfo->getLastRemoteAddress(); + +if(strpos($regAddr, ':') === false) + $regAddr = '::ffff:' . $regAddr; +if(strpos($lastAddr, ':') === false) + $lastAddr = '::ffff:' . $lastAddr; + +echo json_encode([ + 'id' => $userInfo->getId(), + 'name' => $userInfo->getUsername(), + 'email' => $userInfo->getEmailAddress(), + 'reg_addr' => $regAddr, + 'last_addr' => $lastAddr, + 'asscord' => $discord, +]); diff --git a/public/get-user-id.php b/public/get-user-id.php new file mode 100644 index 0000000..9447be5 --- /dev/null +++ b/public/get-user-id.php @@ -0,0 +1,52 @@ + PDO::CASE_NATURAL, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::ATTR_EMULATE_PREPARES => false, + PDO::MYSQL_ATTR_INIT_COMMAND => " + SET SESSION + sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION', + time_zone = '+00:00'; + " + ]); +} catch(PDOException $ex) { + die('-3'); +} + +$userId = $flashii->prepare('SELECT `user_id` FROM `msz_users` WHERE LOWER(`username`) = :username OR LOWER(`email`) = :email'); +$userId->bindValue('username', $name); +$userId->bindValue('email', $name); +$userId->execute(); + +echo (int)$userId->fetchColumn(); diff --git a/public/get-user-names.php b/public/get-user-names.php new file mode 100644 index 0000000..ca93b90 --- /dev/null +++ b/public/get-user-names.php @@ -0,0 +1,65 @@ + 100) + die('-6:too many'); + +foreach($ids as $k => $id) { + $_id = intval($id); + if($id != $_id) + die('-4:format'); + $ids[$k] = $_id; +} + +$config = parse_ini_file($config['msz-config-path'], true, INI_SCANNER_TYPED); +if(empty($config)) + die('-1:config gone'); + +$info = $config['Database']; +if(empty($config)) + die('-2:config gone'); + +$dsn = 'mysql:'; + +if ($info['unix_socket'] ?? false) { + $dsn .= 'unix_socket=' . $info['unix_socket'] . ';'; +} else { + $dsn .= 'host=' . ($info['host'] ?? '127.0.0.1') . ';'; + $dsn .= 'port=' . intval($info['port'] ?? 3306) . ';'; +} + +$dsn .= 'charset=' . ($info['charset'] ?? 'utf8mb4') . ';'; +$dsn .= 'dbname=' . ($info['database'] ?? 'misuzu') . ';'; + +try { + $flashii = new PDO($dsn, ($info['username'] ?? null), ($info['password'] ?? null), [ + PDO::ATTR_CASE => PDO::CASE_NATURAL, + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL, + PDO::ATTR_STRINGIFY_FETCHES => false, + PDO::ATTR_EMULATE_PREPARES => false, + PDO::MYSQL_ATTR_INIT_COMMAND => " + SET SESSION + sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION', + time_zone = '+00:00'; + " + ]); +} catch(PDOException $ex) { + die('-5:db gone'); +} + +$rows = $flashii->query('SELECT `user_id`, `username` FROM `msz_users` WHERE `user_id` IN (' . implode(',', $ids) . ')')->fetchAll(PDO::FETCH_ASSOC); +$out = ''; + +foreach($rows as $row) + $out .= "{$row['user_id']}:{$row['username']};"; + +echo substr($out, 0, -1); diff --git a/public/git-broadcast.php b/public/git-broadcast.php new file mode 100644 index 0000000..5f09dfa --- /dev/null +++ b/public/git-broadcast.php @@ -0,0 +1,169 @@ + $repoToken) { + if(hash_equals(hash_hmac($sigParts[0], $rawData, $repoToken), $sigParts[1])) { + $repoAuthenticated = true; + break; + } +} + +if(!$repoAuthenticated) + die('signature check failed'); + +$data = json_decode($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded' + ? $_POST['payload'] + : $rawData); + +if(empty($data)) + die('body is corrupt'); + +if(empty($data->repository->full_name)) + die('body is corrupt'); + +if($data->repository->full_name !== $repoName) + die('invalid repository token'); + +$message = ''; + +switch($_SERVER['HTTP_X_GITHUB_EVENT']) { + case 'ping': + $message = "ping received from {$data->repository->full_name}!"; + break; + + case 'create': + switch ($data->ref_type) { + case 'tag': + $message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url][/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] created tag [url={$data->repository->html_url}/releases/tag/{$data->ref}]{$data->ref}[/url]"; + break; + + case 'branch': + $message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url][/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] created branch [url={$data->repository->html_url}/tree/{$data->ref}]{$data->ref}[/url]"; + break; + + case 'repository': + // doubt we'll ever get here + // TODO: test organisation level webhooks? + break; + } + break; + + case 'delete': + switch($data->ref_type) { + case 'tag': + if (acl_check(ACL_BROADCAST)) + $message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url][/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] deleted tag {$data->ref}"; + break; + + case 'branch': + if (acl_check(ACL_BROADCAST)) + $message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url][/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] deleted branch {$data->ref}"; + break; + + case 'repository': + if (acl_check(ACL_BROADCAST)) + $message = "[b]{$data->repository->full_name}[/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] deleted the repository :crying:"; + break; + } + break; + + case 'push': + $commitCount = count($data->commits); + if($commitCount < 1) + break; + + $message .= "[b]{$data->repository->full_name}:" . substr($data->ref, strrpos($data->ref, '/') + 1) . "[/b] {$commitCount} new commit" . ($commitCount === 1 ? '' : 's') . "\r\n"; + + foreach($data->commits as $commit) { + $timestamp = strtotime($commit->timestamp); + $commit->message = trim($commit->message); + $message .= "[b][url={$commit->url}][code]" . substr($commit->id, 0, 7) . "[/code][/url][/b] {$commit->message} - [url=" . ($isGitea ? 'https://git.flash.moe/' : 'https://github.com/') . "{$commit->author->username}]{$commit->author->username}[/url]\r\n"; + } + break; + + case 'status': + $status_colour['failure'] = '#cb2431'; + //$status_colour['pending'] = '#b5ab86'; + $status_colour['success'] = '#28a745'; + $status_colour['error'] = '#586069'; + + $status_emotes['failure'] = [':angry:', ':angrier:', ':angriest:', ':sad:', ':ouch:', ':dizzy:', ':sweat:', ':fat:', ':jew:']; + $status_emotes['success'] = [':happy:', ':lol:', ':yay:']; + $status_emotes['error'] = [':blank:']; + + $status_name['continuous-integration/travis-ci/push'] = 'Unit Tests'; + $status_name['continuous-integration/styleci/push'] = 'Style Check'; + + if (!array_key_exists($data->context, $status_name) || !array_key_exists($data->state, $status_colour)) { + //$message = "/msg flash {$data->context}: {$data->state}"; + break; + } + + $message = "[b][url={$data->commit->html_url}]{$data->repository->full_name}[/url] [url={$data->target_url}]" . $status_name[$data->context] . '[/url][/b]: [b][i][color=' . $status_colour[$data->state] . ']' . ucfirst($data->state) . ' ' . $status_emotes[$data->state][array_rand($status_emotes[$data->state])] . '[/color][/i][/b]'; + break; + + case 'watch': + switch($data->action) { + case 'started': + $message = "[url={$data->sender->html_url}]{$data->sender->login}[/url] starred [url={$data->repository->html_url}]{$data->repository->full_name}[/url] :love:"; + break; + } + break; + + case 'fork': + $message = "[url={$data->forkee->html_url}]{$data->forkee->owner->login}[/url] forked [url={$data->repository->html_url}]{$data->repository->full_name}[/url] :omg:"; + break; + + case 'issues': + if(!in_array($data->action, ['opened', /*'edited',*/ 'closed', 'reopened'])) + break; + + $message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url] [url={$data->sender->html_url}]{$data->sender->login}[/url] {$data->action} issue [/b][url={$data->issue->html_url}][b]#{$data->issue->number}[/b]: {$data->issue->title}[/url]"; + break; + + case 'pull_request': + if(!in_array($data->action, ['opened', /*'edited',*/ 'closed', 'reopened'])) + break; + + $message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url]: [url={$data->sender->html_url}]{$data->sender->login}[/url] {$data->action} pull request [/b][url={$data->pull_request->html_url}][b]#{$data->pull_request->number}[/b]: {$data->pull_request->title}[/url]"; + break; +} + +if(!empty($message)) { + var_dump($message); + $sock = fsockopen($config['boat']['host'], $config['boat']['port'], $errno, $errstr, 5); + $message = chr(0xF) . hash_hmac('sha256', $message, $config['boat']['secret']) . $message . chr(0xF); + fwrite($sock, $message); + fflush($sock); +} diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..5678434 --- /dev/null +++ b/public/index.php @@ -0,0 +1,50 @@ + + + + + + Cannot find page + + + +
+

+ + The page cannot be found +

+

+ The page you are looking for might have been removed, had its + name changed, or is temporarily unavailable. +

+
+

+ Please try the following: +

+ +

+ HTTP 404 - File not found +
+ Internet Explorer +

+
+ + \ No newline at end of file diff --git a/public/markov-shit.php b/public/markov-shit.php new file mode 100644 index 0000000..92e63d5 --- /dev/null +++ b/public/markov-shit.php @@ -0,0 +1,437 @@ + + + +

msz_changelog_changes -> change_log

+ + +

msz_changelog_changes -> change_text

+ + +

msz_changelog_tags -> tag_name

+ + +

msz_changelog_tags -> tag_description

+ + +

msz_comments_posts -> comment_text

+ + +

msz_forum_categories -> forum_name

+ + +

msz_forum_categories -> forum_description

+ + +

msz_forum_posts -> post_text

+ + +

msz_forum_topics -> topic_title

+ + +

msz_news_categories -> category_name

+ + +

msz_news_categories -> category_description

+ + +

msz_news_posts -> post_title

+ + +

msz_news_posts -> post_text

+ + +

msz_roles -> role_name

+ + +

msz_roles -> role_title

+ + +

msz_roles -> role_description

+ + +

msz_users -> username

+ + +

msz_users -> user_about_content

+ + +

msz_users -> user_signature_content

+ + +

msz_users -> user_title

+ + +

msz_profile_fields_values -> field_value -> 1

+ + +

msz_profile_fields_values -> field_value -> 2

+ + +

msz_profile_fields_values -> field_value -> 3

+ + +

msz_profile_fields_values -> field_value -> 4

+ + +

msz_profile_fields_values -> field_value -> 5

+ + +

msz_profile_fields_values -> field_value -> 6

+ + +

msz_profile_fields_values -> field_value -> 7

+ + +

msz_profile_fields_values -> field_value -> 8

+ + +

msz_profile_fields_values -> field_value -> 9

+ + +

msz_profile_fields_values -> field_value -> 10

+ + +

msz_profile_fields_values -> field_value -> 11

+ + +

msz_profile_fields_values -> field_value -> 12

+ + +

msz_profile_fields_values -> field_value -> 13

+ + +

msz_profile_fields_values -> field_value -> 14

+ + +

msz_profile_fields_values -> field_value -> 15

+ + +

msz_profile_fields_values -> field_value -> 16

+ + +

msz_profile_fields_values -> field_value -> 17

+ + +

msz_profile_fields_values -> field_value -> 18

+ + +

msz_profile_fields_values -> field_value -> 19

+ diff --git a/public/recent-forum-posts.php b/public/recent-forum-posts.php new file mode 100644 index 0000000..81def32 --- /dev/null +++ b/public/recent-forum-posts.php @@ -0,0 +1,43 @@ +prepare(' + SELECT + p.`post_id`, + t.`topic_id`, t.`topic_title`, + f.`forum_id`, f.`forum_name`, + u.`user_id`, u.`username`, + COALESCE(u.`user_colour`, r.`role_colour`) AS `user_colour`, + ( + SELECT MIN(`post_id`) = p.`post_id` + FROM `msz_forum_posts` + WHERE `topic_id` = p.`topic_id` + ) AS `is_opening_post` + FROM `msz_forum_posts` as p + LEFT JOIN `msz_users` AS u + ON u.`user_id` = p.`user_id` + LEFT JOIN `msz_roles` AS r + ON r.`role_id` = u.`display_role` + LEFT JOIN `msz_forum_topics` AS t + ON t.`topic_id` = p.`topic_id` + LEFT JOIN `msz_forum_categories` AS f + ON f.`forum_id` = p.`forum_id` + WHERE `post_id` > :post_id + AND `post_deleted` IS NULL + AND `post_created` > NOW() - INTERVAL 2 DAY + AND p.`forum_id` IN (2, 7, 24, 6, 5, 4, 16, 20, 8, 19, 10, 11, 13, 21, 15, 14, 27, 29, 28, 18, 23) + ORDER BY `post_id` + LIMIT 10 + '); + $fetch->bindValue('post_id', $startId); + if($fetch->execute()) + echo json_encode($fetch->fetchAll(PDO::FETCH_ASSOC)); + else + echo '[]'; +} catch(PDOException $ex) { + http_response_code(500); + echo '{"error":104}'; +} diff --git a/public/recent-registrations.php b/public/recent-registrations.php new file mode 100644 index 0000000..22678b7 --- /dev/null +++ b/public/recent-registrations.php @@ -0,0 +1,23 @@ +prepare(' + SELECT `user_id`, `username` + FROM `msz_users` + WHERE `user_id` > :user_id + AND `user_created` > NOW() - INTERVAL 2 DAY + ORDER BY `user_id` + LIMIT 10 + '); + $fetch->bindValue('user_id', $startId); + if($fetch->execute()) + echo json_encode($fetch->fetchAll(PDO::FETCH_ASSOC)); + else + echo '[]'; +} catch(PDOException $ex) { + http_response_code(500); + echo '{"error":104}'; +} diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..1f53798 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / diff --git a/public/satori.css b/public/satori.css new file mode 100644 index 0000000..b2d9134 --- /dev/null +++ b/public/satori.css @@ -0,0 +1,79 @@ +html, +body { + min-height: 100%; + width: 90; +} + +html { + background: url('//static.flash.moe/images/satori-error.png') top right no-repeat #fff; + font-family: 'verdana', sans-serif; + font-size: .8em; +} + +body { + margin: 0 2em; +} + +#wrap { + max-width: 34em; +} + +h1, +h2, +h3, +p { + margin: 0; + padding: 0; + font-size: 1em; + font-weight: normal; +} + +h1 { + font-size: 1.5em; + margin: 1.33em 0; +} + +h1 img { + margin: 0 .5em -.75em 0; +} + +p { + padding: 0; + margin: 2em 0; + line-height: 1.33em; +} + +hr { + margin: 1.9em 0; + background: #BBB; + border: none; +} + +ul { + padding: .75em 0 0 0; +} + +li { + margin: 0 0 .8em 3.46em; + line-height: 1.32em; +} + +a { + color: red; +} + +img+a:before { + content: " "; +} + +h3 { + margin: 2.5em 0; +} + +li:nth-child(3) img { + margin: -0.2em 0; +} + +li:nth-child(4) img { + margin: -0.5em 0; +} diff --git a/public/tetrio-user-reverse.php b/public/tetrio-user-reverse.php new file mode 100644 index 0000000..35968e9 --- /dev/null +++ b/public/tetrio-user-reverse.php @@ -0,0 +1,27 @@ + 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0', + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => json_encode(['query' => (string)filter_input(INPUT_GET, 'q', FILTER_SANITIZE_STRING)]), + CURLOPT_HTTPHEADER => [ + 'Authorization: Bearer ' . TETRIO_TOKEN, + 'Content-Type: application/json', + ], +]); +$out = curl_exec($curl); +curl_close($curl); + +echo $out; diff --git a/public/translate.php b/public/translate.php new file mode 100644 index 0000000..f2608ea --- /dev/null +++ b/public/translate.php @@ -0,0 +1,157 @@ +\r\n"; + + switch ($mode) { + case 'list': + $type = get_class($arr[0]); + $output .= ""; + foreach ($arr as $part) { + $output .= "<{$type} "; + + foreach (get_object_vars($part) as $name => $value) { + $output .= "{$name}=\"{$value}\" "; + } + + $output .= '/>'; + } + $output .= ""; + break; + + case 'do': + $output .= " $value) { + $value = htmlspecialchars($value); + $output .= "{$name}=\"{$value}\" "; + } + + $output .= '/>'; + break; + } + break; + + case 'json': + default: + $mimeType = 'application/json'; + $output = json_encode($arr, JSON_ARGS); + break; + } + + header("Content-Type: {$mimeType}; charset=utf-8"); + die($output); +} + +define('TRANSLATE_URL', 'https://translate.google.com/translate_a/single?ie=UTF-8&oe=UTF-8&multires=1&client=gtx&sl=%s&tl=%s&dt=t&q=%s'); +define('CURL_USER_AGENT', 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'); +define('MAX_TRANSL_LENGTH', 630); + +function curl_req($url) +{ + $curl = curl_init($url); + + curl_setopt_array($curl, [ + CURLOPT_RETURNTRANSFER => true, + CURLOPT_SSL_VERIFYPEER => false, + CURLOPT_SSL_VERIFYHOST => false, + + CURLOPT_USERAGENT => CURL_USER_AGENT, + ]); + + return curl_exec($curl); +} + +class Language { + public $code; + public $name; + + public function __construct($code, $name) + { + $this->code = $code; + $this->name = $name; + } + + public static function fromCode($code) + { + return new Language($code, locale_get_display_name($code)); + } +} + +$languages = [ + 'af', 'sq', 'ar', 'hy', 'az', 'eu', 'be', 'bn', 'bs', + 'bg', 'ca', 'ny', 'co', 'hr', 'cs', 'da', 'nl', 'en', + 'eo', 'tl', 'fi', 'fr', 'fy', 'gl', 'ka', 'de', 'el', + 'gu', 'ht', 'ha', 'iw', 'hi', 'hu', 'is', 'ig', 'id', + 'ga', 'ja', 'jw', 'kn', 'kk', 'km', 'ko', 'ku', 'ky', + 'lo', 'la', 'lv', 'lt', 'lb', 'mk', 'mg', 'ms', 'ml', + 'mt', 'mi', 'mr', 'mn', 'my', 'ne', 'no', 'ps', 'fa', + 'pl', 'pt', 'ma', 'ro', 'ru', 'sm', 'gd', 'sr', 'st', + 'sn', 'sd', 'si', 'sk', 'sl', 'so', 'es', 'su', 'sw', + 'sv', 'tg', 'ta', 'te', 'th', 'tr', 'uk', 'ur', 'uz', + 'vi', 'cy', 'xh', 'yi', 'yo', 'zu', 'it', + 'ceb', 'haw', 'hmn', + 'zh-cn', 'zh-tw', +]; + +$mode = $_GET['m'] ?? null; + +switch ($mode) +{ + case 'list': + $out = []; + + foreach ($languages as $lang) + $out[] = Language::fromCode($lang); + + out($out, $mode); + + case 'do': + $from = strtolower($_GET['f'] ?? 'auto'); + $to = strtolower($_GET['t'] ?? 'en'); + + if ($from !== 'auto' && !in_array($from, $languages)) + out(['error' => 'The given origin language is invalid.'], $mode); + + if (!in_array($to, $languages)) + out(['error' => 'The given destination language is invalid.'], $mode); + + $text = isset($_GET['z']) ? $_GET['z'] : file_get_contents('php://input'); + $t_len = strlen($text); + + if ($t_len < 1) + out(['error' => 'Nothing to translate.'], $mode); + + if ($t_len > MAX_TRANSL_LENGTH) + out(['error' => 'Too much text, please split some up.'], $mode); + + $google_txt = curl_req(sprintf(TRANSLATE_URL, $from, $to, rawurlencode($text))); + + $google = json_decode($google_txt); + + if (strlen($google_txt) < 1 || !$google) + out(['error' => 'Something happened.'], $mode); + + $result = $google[0][0][0]; + $original = $google[0][0][1]; + $from = $google[2]; + $from_text = locale_get_display_name($from); + $to_text = locale_get_display_name($to); + + out(compact('from', 'from_text', 'to', 'to_text', 'original', 'result'), $mode); +}