[^?\s]+)$@i", //image
44 | "@^https?://v\.redd\.it/([\w-]+)$@i", // video
45 | "@^https?://(?:www\.)?reddit\.com/gallery/([\w-]+)$@i" //gallery
46 | ];
47 | foreach ($SKIP_URLS as $re) {
48 | if (preg_match($re, $event->url))
49 | return;
50 | }
51 | $matched = false;
52 | foreach ($URLS as $re) {
53 | if (preg_match($re, $event->url)) {
54 | $matched = true;
55 | break;
56 | }
57 | }
58 | if (!$matched)
59 | return;
60 |
61 | $event->addFuture(\Amp\async(function () use ($event): void {
62 | try {
63 | $info = $this->reddit->info($event->url)->await();
64 | if ($info->kind != 'Listing') {
65 | echo "reddit->info return was not kind: Listing\n";
66 | return;
67 | }
68 | if (!isset($info->data->children) || !is_array($info->data->children)) {
69 | echo "reddit->info return didnt have data->children array\n";
70 | return;
71 | }
72 | /*
73 | * t1_ Comment
74 | t2_ Account
75 | t3_ Link
76 | t4_ Message
77 | t5_ Subreddit
78 | t6_ Award
79 | */
80 | $post = null;
81 | foreach ($info->data->children as $child) {
82 | if ($child->kind == "t3") {
83 | $post = $child->data ?? null;
84 | break;
85 | }
86 | }
87 | if ($post === null) {
88 | echo "reddit: no link kinds found in children\n";
89 | return;
90 | }
91 | $date = Carbon::createFromTimestamp($post->created);
92 | $ago = $date->shortRelativeToNowDiffForHumans(null, 3);
93 | $ups = number_format($post->ups);
94 | $downs = number_format($post->downs);
95 | $reply = "[Reddit $post->subreddit_name_prefixed] $post->title (Posted $ago [+]{$ups} [-]$downs)";
96 | $reply = html_entity_decode($reply, ENT_QUOTES | ENT_HTML5, 'UTF-8');
97 | $event->reply(str_replace(["\r", "\n"], " ", $reply));
98 | } catch (\Exception $e) {
99 | echo "reddit exception {$e->getMessage()}\n";
100 | return;
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 |
--------------------------------------------------------------------------------
/scripts/remindme/entities/reminder.php:
--------------------------------------------------------------------------------
1 | init();
27 | }
28 |
29 | public function init(): void {}
30 | }
--------------------------------------------------------------------------------
/scripts/seen/entities/seen.php:
--------------------------------------------------------------------------------
1 | time = new \DateTime();
40 | }
41 | }
--------------------------------------------------------------------------------
/scripts/seen/seen.php:
--------------------------------------------------------------------------------
1 | ")]
22 | function seen($args, \Irc\Client $bot, \knivey\cmdr\Args $cmdArgs)
23 | {
24 | global $entityManager;
25 | $nick = u($cmdArgs['nick'])->lower();
26 | if ($nick == u($bot->getNick())->lower()) {
27 | $bot->pm($args->chan, "I'm here bb");
28 | return;
29 | }
30 | $this->saveSeens();
31 |
32 | $seen = $entityManager->getRepository(entities\seen::class)->findOneBy([
33 | "network" => $this->network,
34 | "nick" => $nick
35 | ]);
36 | if (!$seen) {
37 | $bot->pm($args->chan, "I've never seen {$cmdArgs['nick']} in my whole life");
38 | return;
39 | }
40 | $entityManager->refresh($seen);
41 | try {
42 | $ago = (new Carbon($seen->time))->diffForHumans(Carbon::now(), CarbonInterface::DIFF_RELATIVE_TO_NOW, true, 3);
43 | } catch (\Exception $e) {
44 | echo $e->getMessage();
45 | $ago = "??? ago";
46 | }
47 | if ($args->chan != $seen->chan) {
48 | $bot->pm($args->chan, "{$seen->orig_nick} was last active in another channel $ago");
49 | return;
50 | }
51 | $n = "<{$seen->orig_nick}>";
52 | if ($seen->action == "action") {
53 | $n = "* {$seen->orig_nick}";
54 | }
55 | if ($seen->action == "notice") {
56 | $n = "[{$seen->orig_nick}]";
57 | }
58 | if(is_string($seen->text))
59 | $text = $seen->text;
60 | else
61 | $text = stream_get_contents($seen->text);
62 | $bot->pm($args->chan, "seen {$ago}: $n {$text}");
63 | }
64 |
65 |
66 |
67 | private $updates = [];
68 |
69 | function updateSeen(string $action, string $chan, string $nick, string $text)
70 | {
71 | $orig_nick = $nick;
72 | $nick = strtolower($nick);
73 | $chan = strtolower($chan);
74 |
75 | $ent = new entities\seen();
76 | $ent->nick = $nick;
77 | $ent->orig_nick = $orig_nick;
78 | $ent->chan = $chan;
79 | $ent->text = $text;
80 | $ent->action = $action;
81 | $ent->network = $this->network;
82 | //Don't save yet, massive floods will destroy us with so many writes
83 | $this->updates[$nick] = $ent;
84 | }
85 |
86 | function saveSeens(): void
87 | {
88 | global $entityManager;
89 | foreach ($this->updates as $ent) {
90 | $previous = $entityManager->getRepository(entities\seen::class)->findOneBy([
91 | "network" => $this->network,
92 | "nick" => $ent->nick
93 | ]);
94 | if ($previous) {
95 | $previous->nick = $ent->nick;
96 | $previous->orig_nick = $ent->orig_nick;
97 | $previous->chan = $ent->chan;
98 | $previous->text = $ent->text;
99 | $previous->action = $ent->action;
100 | $previous->time = $ent->time;
101 | $entityManager->persist($previous);
102 | } else {
103 | $entityManager->persist($ent);
104 | }
105 | }
106 | $entityManager->flush();
107 | $this->updates = [];
108 | }
109 |
110 | function init(): void
111 | {
112 | \Revolt\EventLoop::repeat(15, $this->saveSeens(...));
113 |
114 | $this->client->on('notice', function ($args, \Irc\Client $bot) {
115 | if (!$bot->isChannel($args->to))
116 | return;
117 | //ignore ctcp replies to channel
118 | if (preg_match("@^\x01.*$@i", $args->text))
119 | return;
120 | $this->updateSeen('notice', $args->to, $args->from, $args->text);
121 | });
122 |
123 | $this->client->on('chat', function ($args, \Irc\Client $bot) {
124 | if (preg_match("@^\x01ACTION ([^\x01]+)\x01?$@i", $args->text, $m)) {
125 | $this->updateSeen('action', $args->chan, $args->from, $m[1]);
126 | return;
127 | }
128 | $this->updateSeen('privmsg', $args->chan, $args->from, $args->text);
129 | });
130 | }
131 | }
--------------------------------------------------------------------------------
/scripts/stocks/quote.php:
--------------------------------------------------------------------------------
1 | changePercent) && isset($this->change) && isset($this->price);
37 | }
38 | }
--------------------------------------------------------------------------------
/scripts/stocks/symbol.php:
--------------------------------------------------------------------------------
1 | symbol) &&
18 | isset($this->description) &&
19 | isset($this->type);
20 | }
21 | }
--------------------------------------------------------------------------------
/scripts/tell/entities/tell.php:
--------------------------------------------------------------------------------
1 | created = new \DateTime();
43 | }
44 | }
--------------------------------------------------------------------------------
/scripts/tiktok/tiktok.php:
--------------------------------------------------------------------------------
1 | addListener($this->handleEvents(...));
17 | }
18 |
19 | function handleEvents(UrlEvent $event)
20 | {
21 | global $config;
22 | if ($event->handled)
23 | return;
24 |
25 | if (!preg_match("@^https?://(?:www\.)?tiktok\.com/\@[^/]+/[^/]+\??.*$@i", $event->url)) {
26 | return;
27 | }
28 |
29 | $event->addFuture(\Amp\async(function () use ($event): void {
30 | try {
31 | $d = async_get_contents("https://www.tiktok.com/oembed?url={$event->url}");
32 | $j = json_decode($d, flags: JSON_THROW_ON_ERROR);
33 | if(
34 | !isset($j->author_unique_id) ||
35 | !isset($j->title) ||
36 | !isset($j->author_name)
37 | ) {
38 | $this->logger->error("bad or imcomplete response from tiktok", ['d' => $d, 'j' => $j]);
39 | return;
40 | }
41 | $reply = "[TikTok @$j->author_unique_id ($j->author_name)] $j->title";
42 | //not sure if needed yet
43 | //$reply = html_entity_decode($reply, ENT_QUOTES | ENT_HTML5, 'UTF-8');
44 | $event->reply(str_replace(["\r", "\n"], " ", $reply));
45 | } catch (\Exception $e) {
46 | echo "tiktok exception {$e->getMessage()}\n";
47 | return;
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 |
--------------------------------------------------------------------------------
/scripts/twitter/twitter.php:
--------------------------------------------------------------------------------
1 | addListener($this->handleEvents(...));
18 | }
19 |
20 | function handleEvents(UrlEvent $event): void
21 | {
22 | if ($event->handled)
23 | return;
24 | if(!preg_match("@^https?://(?:mobile\.)?(?:twitter|x)\.com/([^/]+)/status/(\d+).*$@i", $event->url, $m))
25 | return;
26 | $user = $m[1];
27 | $id = $m[2];
28 | $event->addFuture(\Amp\async(function() use ($event, $id, $user) {
29 | global $config;
30 | try {
31 | $client = HttpClientBuilder::buildDefault();
32 | $nitters = [
33 | "https://nitter.net/",
34 | "https://nitter.kavin.rocks/",
35 | "https://nitter.unixfox.eu/",
36 | "https://nitter.moomoo.me/",
37 | "https://nitter.mint.lgbt/",
38 | "https://nitter.esmailelbob.xyz/",
39 | "https://nitter.bird.froth.zone/",
40 | "https://nitter.privacydev.net/",
41 | "https://nitter.no-logs.com/",
42 | ];
43 | $nitters = array_map(fn ($it) => "{$it}$user/status/$id", $nitters);
44 | $responses = [];
45 | foreach ($nitters as $nitter) {
46 | $r = new Request($nitter);
47 | $r->setTransferTimeout(5);
48 | $responses[] = \Amp\async(fn() => $client->request($r, new TimeoutCancellation(5)));;
49 | }
50 | $this->logger->info("starting requests...");
51 | [$fails, $responses] = \Amp\Future\awaitAll($responses);
52 | $this->logger->info(count($responses) . " requests finished, " . count($fails) . " failed/timedout");
53 | $success = [];
54 | foreach($responses as $r) {
55 | /** @var Response $r */
56 | if($r->getStatus() == 200) {
57 | $this->logger->info("200 from {$r->getOriginalRequest()->getUri()}");
58 | $success[] = $r;
59 | } else {
60 | $this->logger->info("failure code {$r->getStatus()} from {$r->getOriginalRequest()->getUri()}");
61 | }
62 | }
63 | if(count($success) == 0) {
64 | $this->logger->notice("no nitters returned 200 OK");
65 | return;
66 | }
67 | /** @var Response $response */
68 | $response = array_pop($success);
69 | $this->logger->info("processing 200 response from " . $response->getOriginalRequest()->getUri());
70 | $body = $response->getBody()->buffer();
71 |
72 | $html = new HtmlDocument();
73 | $html->load($body);
74 | $text = $html->find("div.tweet-content", 0)?->plaintext;
75 | if($text === null) {
76 | $this->logger->notice("couldnt understand response");
77 | return;
78 | }
79 | $date = $html->find("p.tweet-published", 0)->plaintext;
80 | $date = str_replace("· ", "", $date);
81 | $date = Carbon::createFromTimeString($date, 'utc');
82 | $ago = $date->shortRelativeToNowDiffForHumans(null, 3);
83 | $like_count = $html->find('div.icon-container span.icon-heart', 0)->parent()->plaintext;
84 | $reply_count = $html->find('div.icon-container span.icon-comment', 0)->parent()->plaintext;
85 |
86 | $event->reply("[Twitter] $ago $user tweeted: $text | {$like_count} likes, {$reply_count} replies");
87 | } catch (\Exception $e) {
88 | echo "twitter exception {$e->getMessage()}\n";
89 | return;
90 | }
91 | }));
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/scripts/urbandict/urbandict.php:
--------------------------------------------------------------------------------
1 | ...')]
15 | function ud($args, \Irc\Client $bot, \knivey\cmdr\Args $cmdArgs)
16 | {
17 | $query = urlencode($cmdArgs['query']);
18 | try {
19 | $body = async_get_contents("http://www.urbandictionary.com/define.php?term=$query");
20 | } catch (\async_get_exception $e) {
21 | // we get a 404 if word not found
22 | if ($e->getCode() == 404) {
23 | $bot->msg($args->chan, "ud: There are no definitions for this word.");
24 | } else {
25 | echo $e->getCode() . ' ' . $e->getMessageStripped();
26 | $bot->msg($args->chan, "ud: Problem getting data from urbandictionary");
27 | }
28 | return;
29 | } catch (\Exception $error) {
30 | echo $error->getMessage();
31 | $bot->pm($args->chan, "urbandict error: {$error->getMessage()}");
32 | return;
33 | }
34 | if (str_contains($body, "Sorry, we couldn't find:")) {
35 |
36 | return;
37 | }
38 | $doc = new HtmlDocument($body);
39 |
40 | $defs = @$doc->find('div.definition');
41 |
42 | // wonder if this would happen after that earlier check?
43 | if (!is_array($defs) || count($defs) < 1) {
44 | $bot->msg($args->chan, "ud: Couldn't find an entry matching {$cmdArgs['query']}");
45 | return;
46 | }
47 |
48 | $max = 2;
49 | if ($this->server->throttle)
50 | $max = 1;
51 | $num = 0;
52 | for ($i = 0; $i < $max && isset($defs[$i]); $i++) {
53 | $def = $defs[$i];
54 | $num++;
55 | //Haven't seen this on the pages again, maybe they stopped it
56 | if (str_contains($def->find('div.ribbon', 0)?->plaintext, "Word of the Day")) {
57 | $max++;
58 | continue;
59 | }
60 | $meaning = $def->find('div.meaning', 0)->plaintext;
61 | $example = $def->find('div.example', 0)->plaintext;
62 | $word = $def->find('a.word', 0)->plaintext;
63 | $by = $def->find('div.contributor', 0)->plaintext;
64 |
65 | $meaning = html_entity_decode($meaning, ENT_QUOTES | ENT_HTML5);
66 | $example = html_entity_decode($example, ENT_QUOTES | ENT_HTML5);
67 | $word = html_entity_decode($word, ENT_QUOTES | ENT_HTML5);
68 | $by = html_entity_decode($by, ENT_QUOTES | ENT_HTML5);
69 |
70 | $meaning = trim(str_replace(["\n", "\r"], ' ', $meaning));
71 |
72 | $example = str_replace("\r", "\n", $example);
73 | $example = explode("\n", $example);
74 | $example = array_map('trim', $example);
75 | $example = array_filter($example);
76 | $example1line = implode(' | ', $example);
77 |
78 | $bot->msg($args->chan, "ud: $word #$num added $by");
79 | if ($this->server->throttle) {
80 | $bot->msg($args->chan, " ├ Meaning: $meaning");
81 | $bot->msg($args->chan, " └ $example1line");
82 | } else {
83 | $c = 0;
84 | foreach (explode("\n", wordwrap($meaning, 80)) as $m) {
85 | $leader = $c > 0 ? "│ " : "├ ";
86 | $bot->msg($args->chan, " $leader $m");
87 | $c++;
88 | }
89 | $c = 0;
90 | foreach ($example as $e) {
91 | $leader = $c > 0 ? "│ " : "├ ";
92 | if ($c == count($example) - 1)
93 | $leader = "└ ";
94 | $bot->msg($args->chan, " $leader $e");
95 | $c++;
96 | }
97 | }
98 | }
99 | }
100 | }
--------------------------------------------------------------------------------
/scripts/user/Access.php:
--------------------------------------------------------------------------------
1 | ...')]
12 | function wiki($args, \Irc\Client $bot, \knivey\cmdr\Args $cmdArgs)
13 | {
14 | list($rpl, $rpln) = makeRepliers($args, $bot, "Wiki");
15 | $query = rawurlencode($cmdArgs['query']);
16 | try {
17 | $body = async_get_contents("https://en.wikipedia.org/api/rest_v1/page/summary/$query");
18 | } catch (async_get_exception $e) {
19 | if($e->getCode() == 404) {
20 | $rpl("Wikipedia does not have an article with this exact name.", "404");
21 | return;
22 | }
23 | $rpl($e->getIRCMsg(), "error");
24 | return;
25 | } catch (\Exception $e) {
26 | $rpl($e->getMessage(), "error");
27 | return;
28 | }
29 | $json = json_decode($body);
30 | if($json == null) {
31 | $rpl("bad response from server", "error");
32 | return;
33 | }
34 | $title = null;
35 | $extract = null;
36 | $url = null;
37 | if(is_string($json->title))
38 | $title = html_entity_decode($json->title, ENT_QUOTES | ENT_HTML5);
39 | if(is_string($json->extract))
40 | $extract = html_entity_decode($json->extract, ENT_QUOTES | ENT_HTML5);
41 | if(is_string($json->content_urls?->desktop?->page))
42 | $url = html_entity_decode($json->content_urls->desktop->page, ENT_QUOTES | ENT_HTML5);
43 |
44 | if(strlen($extract) > 320) {
45 | $extract = explode("\n", wordwrap($extract, 320), 2)[0] . "...";
46 | }
47 |
48 | $type = null;
49 | if($json->type != "standard")
50 | $type = $json->type;
51 |
52 | $rpl("$title - $extract - $url", $type);
53 | }
--------------------------------------------------------------------------------
/scripts/wolfram/wolfram.php:
--------------------------------------------------------------------------------
1 | ...')]
11 | function calc($args, \Irc\Client $bot, \knivey\cmdr\Args $cmdArgs)
12 | {
13 | global $config;
14 | if(!isset($config['waKey'])) {
15 | echo "waKey not set in config\n";
16 | return;
17 | }
18 |
19 | // https://products.wolframalpha.com/api/documentation?scrollTo=controlling-width-of-results
20 | // width is how many pixels rendered text would fit in
21 | $query = waURL . urlencode($cmdArgs['query']) . '&appid=' . $config['waKey'] .
22 | '&format=plaintext&location=Los+Angeles,+California&width=3000'.
23 | '&excludepodid=MakeChangeMoreThanOneCoin:QuantityData';
24 | try {
25 | $body = async_get_contents($query);
26 |
27 | $xml = simplexml_load_string($body);
28 | $input = '';
29 | $result = '';
30 | $decimalAprox = '';
31 | if ($xml['parsetimedout'] == 'true') {
32 | throw new \Exception("Error, query took too long to parse.");
33 | }
34 | if ($xml['error'] == 'true') {
35 | throw new \Exception("Error, " . @$xml->error->msg);
36 | }
37 |
38 | if ($xml['success'] == 'false') {
39 | // The input wasn't understood, show tips or didyoumeans
40 | if(isset($xml->tips))
41 | $result = ", " . @$xml->tips->tip[0]['text'];
42 | elseif(isset($xml->didyoumeans))
43 | $result .= ", Did you mean: " . @$xml->didyoumeans->didyoumean[0];
44 | throw new \Exception("Query not understood" . $result);
45 | }
46 | $topPod = '';
47 | foreach ($xml->pod as $pod) {
48 | switch($pod['id']) {
49 | case 'Input':
50 | $input = str_replace("\n", "\2;\2 ", $pod->subpod->plaintext);
51 | break;
52 | case 'Result':
53 | $result = str_replace("\n", "\2;\2 ", $pod->subpod->plaintext);
54 | break;
55 | case 'DecimalApproximation':
56 | $decimalAprox = substr($pod->subpod->plaintext, 0, 200);
57 | break;
58 | default:
59 | if($topPod == '')
60 | $topPod = str_replace("\n", "\2;\2 ", $pod->subpod->plaintext);
61 | }
62 | }
63 | if($result == "") {
64 | $result = $topPod;
65 | }
66 | if($result == "" && $decimalAprox != "") {
67 | $result = $decimalAprox;
68 | $decimalAprox = "";
69 | }
70 | $res = "$input = $result";
71 | if($decimalAprox != "") {
72 | $res .= " ($decimalAprox)";
73 | }
74 | $out = explode("\n", wordwrap($res, 400, "\n", true));
75 | $cnt = 0;
76 | foreach ($out as $msg) {
77 | $bot->pm($args->chan, "\2WA:\2 " . $msg);
78 | if($cnt++ > 4) break;
79 | }
80 | } catch (\async_get_exception $error) {
81 | echo $error->getMessage();
82 | $bot->pm($args->chan, "\2WA:\2 {$error->getIRCMsg()}");
83 | return;
84 | } catch (\Exception $error) {
85 | echo $error->getMessage();
86 | $bot->pm($args->chan, "\2WA:\2 {$error->getMessage()}");
87 | }
88 | }
--------------------------------------------------------------------------------
/scripts/yoda/yoda-og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/knivey/lolbot/61cc4a00fd1f18c0921418537c6fc98f58d55e9e/scripts/yoda/yoda-og.png
--------------------------------------------------------------------------------
/scripts/yoda/yoda.php:
--------------------------------------------------------------------------------
1 | ...')]
14 | #[Option("--og", "OG Yoda")]
15 | function yoda_cmd($args, \Irc\Client $bot, \knivey\cmdr\Args $cmdArgs)
16 | {
17 | $url = $cmdArgs['url'];
18 |
19 | if(!filter_var($url, FILTER_VALIDATE_URL))
20 | return;
21 |
22 | try {
23 | $client = HttpClientBuilder::buildDefault();
24 | $request = new Request($url);
25 |
26 | /** @var Response $response */
27 | $response = $client->request($request);
28 | $body = $response->getBody()->buffer();
29 | if ($response->getStatus() != 200) {
30 | $bot->pm($args->chan, "Server returned {$response->getStatus()}");
31 | return;
32 | }
33 |
34 | $img = new Imagick();
35 | try {
36 | $img->readImageBlob($body);
37 | if(!$img->getImageFormat()) {
38 | throw new \Exception();
39 | }
40 | } catch (\Exception $e) {
41 | $bot->pm($args->chan, "couldn't recognize any image data");
42 | return;
43 | }
44 |
45 | $yodaImg = new Imagick();
46 | $yodaImgFile = $cmdArgs->optEnabled('--og') ? "/yoda-og.png" : "/yoda.png";
47 | $yodaImg->readImage(__DIR__ . $yodaImgFile);
48 | $yodaImg->scaleImage($img->getImageWidth(), $img->getImageHeight());
49 |
50 | // original behavior
51 | if ($cmdArgs->optEnabled('--og')) {
52 | $newWidth = $yodaImg->getImageWidth() + $img->getImageWidth();
53 | $newHeight = max($yodaImg->getImageHeight(), $img->getImageHeight());
54 | $finalImg = new Imagick();
55 | $finalImg->newImage($newWidth, $newHeight, new ImagickPixel('transparent'));
56 | $finalImg->compositeImage($yodaImg, Imagick::COMPOSITE_OVER, 0, 0);
57 | $finalImg->compositeImage($img, Imagick::COMPOSITE_OVER, $yodaImg->getImageWidth(), 0);
58 | $img = $finalImg;
59 | } else {
60 | // new chunky behavior
61 | $img->compositeImage($yodaImg, Imagick::COMPOSITE_BLEND, 0, 0);
62 | }
63 |
64 | $tmpfile = tempnam(sys_get_temp_dir(), 'yoda') . '.webp';
65 | $img->writeImage($tmpfile);
66 | $yodaPic = hostToFilehole($tmpfile)->await();
67 | unlink($tmpfile);
68 | $bot->pm($args->chan, $yodaPic);
69 | } catch (\Exception $e) {
70 | return;
71 | }
72 | }
73 |
74 | #[Cmd("doubleyoda")]
75 | #[Syntax('...')]
76 | function doubleyoda_cmd($args, \Irc\Client $bot, \knivey\cmdr\Args $cmdArgs)
77 | {
78 | $url = $cmdArgs['url'];
79 |
80 | if(!filter_var($url, FILTER_VALIDATE_URL))
81 | return;
82 |
83 | try {
84 | $body = async_get_contents($url);
85 | $img = new Imagick();
86 | $img->readImageBlob($body);
87 | if(!$img->getImageFormat()) {
88 | throw new \Exception("data recieved not recognized as image");
89 | }
90 | $yoda = new Imagick(__DIR__ . "/yoda-og.png");
91 | //$yoda->scaleImage(0, $img->getImageHeight());
92 | $final = new Imagick();
93 | $width = $img->getImageWidth() + $yoda->getImageWidth() * 2;
94 | $height = max($img->getImageHeight(), $yoda->getImageHeight());
95 | $final->newImage($width, $height, new ImagickPixel('transparent'));
96 | $final->compositeImage($yoda, Imagick::COMPOSITE_OVER, 0, 0);
97 | $final->compositeImage($img, Imagick::COMPOSITE_OVER, $yoda->getImageWidth(), 0);
98 | $yoda->flopImage();
99 | $final->compositeImage($yoda, Imagick::COMPOSITE_OVER, $width - $yoda->getImageWidth(), 0);
100 | $tmpfile = tempnam(sys_get_temp_dir(), 'yoda') . '.webp';
101 | $final->writeImage($tmpfile);
102 | $yodaPic = hostToFilehole($tmpfile)->await();
103 | unlink($tmpfile);
104 | $bot->pm($args->chan, $yodaPic);
105 | } catch (\Exception $e) {
106 | $bot->pm($args->chan, "yoda troubles: {$e->getMessage()}");
107 | return;
108 | }
109 | }
110 |
111 | /**
112 | *
113 | * @param string $filename
114 | * @return Future
115 | */
116 | function hostToFilehole(string $filename): Future
117 | {
118 | return \Amp\async(function () use ($filename) {
119 | if(!file_exists($filename))
120 | throw new \Exception("hostToFilehole called with non existant filename: $filename");
121 | $client = HttpClientBuilder::buildDefault();
122 | $request = new Request("https://upload.beer", "POST");
123 | $body = new Form();
124 | $body->addField('url_len', '5');
125 | $body->addField('expiry', '86400');
126 | $body->addFile('file', $filename);
127 | $request->setBody($body);
128 | //var_dump($request);
129 | /** @var Response $response */
130 | $response = $client->request($request);
131 | //var_dump($response);
132 | if ($response->getStatus() != 200) {
133 | throw new \Exception("upload.beer returned {$response->getStatus()}");
134 | }
135 | $respBody = $response->getBody()->buffer();
136 | return $respBody;
137 | });
138 | }
139 |
--------------------------------------------------------------------------------
/scripts/yoda/yoda.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/knivey/lolbot/61cc4a00fd1f18c0921418537c6fc98f58d55e9e/scripts/yoda/yoda.png
--------------------------------------------------------------------------------
/scripts/zyzz/zyzz.php:
--------------------------------------------------------------------------------
1 | pm($args->chan, "empty quotes file");
14 | return;
15 | }
16 | $fact = $facts[array_rand($facts)];
17 |
18 | $bot->pm($args->chan, $fact);
19 | }
--------------------------------------------------------------------------------
/scripts/zyzz/zyzz.txt:
--------------------------------------------------------------------------------
1 | Personally I’m a very friendly and happy person, and believe that people need to lighten up and enjoy life more. Even though I put on a lot of size and to some look intimidating, I’m one of the friendliest people you can meet. I love playing up my perceived stereotype, and at the end of the day, never take myself seriously, which is one of the reasons I have accrued the fan base that I have.
2 | My message is to train hard, don't be a hard cunt, enjoy life and don't take yourself too seriously. If there were more people like me, the world will be a happier place. Id rather do what i do and have fun then sit back hating on someone achieving something.
3 | I don't workout for chicks, i workout to create an aura, when i walk into a room, introduce myself to someone, go for a job interview, i love looking dominant, in charge, and in control. I love walking past and having people point and talk about me, i love the fact that when i go somewhere with thousands of people, almost all of them will remember who i am when it is over, and i didn't even have to say a word.
4 | There are normal people. There are try hards. There are hard cunts. Then there are sick cunts. Sick cunts are the best, friendly, sexy, aesthetic, party hard and live it up without being staunch and get along with everyone.
5 | Everybody, one day, will die and be forgotten. Act and behave in a way that will make life interesting and fun, fuck a mundane, predictable life working Monday to Friday with something you derive no pleasure from; just living life out till you grow old and wither away. Find a passion, form relationships, don't be afraid to get out there and fuck what everyone else thinks, trust me it's a lot more fun that way..
6 | At the end off the day bro you got to listen to this, if your a fucking shredded sick kunt you can get away with anything bro. If your some fat kunt making this shit up people will be like aww yeahh zyzz bro yeah, they wont give a fuck man.
7 | I want to move my life in other directions and have found myself far too involved in a lifestyle with no genuine substance, meeting far too many fake people/girls who if i didn't look the way i did, would have never given me the time of day.. Time to get back to studying, there's more to life than partying.
8 | There is no 'Zyzz'.... Everyone has a little bit of Zyzz in them.
9 | Don’t ever pay people out or put people down. Instead just put yourself up and let the haters do their thing. Id rather be a person that’s hated on, than a person that does the hating. A wise man one said.. Haters gonna hate!
10 | Stop giving a fuck what girls think and say whatever the fuck you want to say and do whatever you want to do.
11 | None of this will make sense to any of you once you get the physique and know whats its like, i know it sounds like im bragging, but think of it as driving a ferrari in real life. why do people drive ferrarris? to get attention, looks, extert dominance and superiority from the norm, and to get people talking… but it also inspires jealousy and haters on the person driving. thats exactly what i experience irl.
12 | I always feel i have to train and diet my hardest now because i have a look/image to live up to. People talk and already have high expectations from what they hear about me, so i would never let myself look sloppy. If anything, all this has made me want to train harder, and diet more intensely. Fuk ‘good enough',, perfection is my goal.
13 | Fuck that shit brah, you can either be a sick cunt or you can be a sad cunt, don't be a sad cunt brah
14 | Nah brah I'm sweet.
15 | FUAAAAAAAAAAAARK
16 | We're all gonna make it brah
17 | Fuckin ripped, yeah cunt!
18 | It's fucking ZEEEEZ man! And I'm coming at you bro
19 | You mirin'?
20 | Fucking coked up brah
21 |
22 |
--------------------------------------------------------------------------------