From 1405d651262e9b76e99038b7a38242e5ecb09176 Mon Sep 17 00:00:00 2001 From: flashwave Date: Thu, 30 Jul 2020 00:55:37 +0000 Subject: [PATCH] import --- components/footer.php | 18 ++ components/header.php | 52 +++ lib/fmcolour.php | 28 ++ lib/fmlanguage.php | 14 + lib/fmproject.php | 170 ++++++++++ lib/fmprojectlink.php | 24 ++ pages/blog.php | 42 +++ pages/contact.php | 193 +++++++++++ pages/etcetera.php | 59 ++++ pages/index.php | 199 ++++++++++++ pages/projects.php | 91 ++++++ pages/related.php | 44 +++ public/assets/2020v2.css | 676 +++++++++++++++++++++++++++++++++++++++ public/assets/2020v2.js | 113 +++++++ public/index.php | 127 ++++++++ 15 files changed, 1850 insertions(+) create mode 100644 components/footer.php create mode 100644 components/header.php create mode 100644 lib/fmcolour.php create mode 100644 lib/fmlanguage.php create mode 100644 lib/fmproject.php create mode 100644 lib/fmprojectlink.php create mode 100644 pages/blog.php create mode 100644 pages/contact.php create mode 100644 pages/etcetera.php create mode 100644 pages/index.php create mode 100644 pages/projects.php create mode 100644 pages/related.php create mode 100644 public/assets/2020v2.css create mode 100644 public/assets/2020v2.js create mode 100644 public/index.php diff --git a/components/footer.php b/components/footer.php new file mode 100644 index 0000000..6222c48 --- /dev/null +++ b/components/footer.php @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/components/header.php b/components/header.php new file mode 100644 index 0000000..44b3b8b --- /dev/null +++ b/components/header.php @@ -0,0 +1,52 @@ + + + + + + <?=($title ?? 'flash.moe');?> + + + + + + + + +
+
+ +
+
0) echo " style=\"padding-bottom: {$offset}px\""; ?>> + + +
+
+ +
+
+ +
+
+
+
+
+
+ +
+ + + +
+ +
+
+ +
+ diff --git a/lib/fmcolour.php b/lib/fmcolour.php new file mode 100644 index 0000000..12a5d4f --- /dev/null +++ b/lib/fmcolour.php @@ -0,0 +1,28 @@ +raw = $raw; + } + + public function hasColour(): bool { + return $this->raw !== null; + } + + public function getRaw(): int { + return $this->raw ?? 0; + } + + public function getRed(): int { return ($this->getRaw() >> 16) & 0xFF; } + public function getGreen(): int { return ($this->getRaw() >> 8) & 0xFF; } + public function getBlue(): int { return $this->getRaw() & 0xFF; } + + public function getHex(): string { return str_pad(dechex($this->getRaw()), 6, '0'); } + + public function getCSS(): string { + if(!$this->hasColour()) + return 'inherit'; + return '#' . $this->getHex(); + } +} diff --git a/lib/fmlanguage.php b/lib/fmlanguage.php new file mode 100644 index 0000000..39fbcfe --- /dev/null +++ b/lib/fmlanguage.php @@ -0,0 +1,14 @@ + $val) + $lang->{$prop} = $val; + return $lang; + } +} diff --git a/lib/fmproject.php b/lib/fmproject.php new file mode 100644 index 0000000..1f50a37 --- /dev/null +++ b/lib/fmproject.php @@ -0,0 +1,170 @@ +project_id < 1 ? -1 : $this->project_id; + } + + public function getName(): string { + return $this->project_name; + } + public function getCleanName(): string { + return $this->project_name_clean ?? str_replace(' ', '-', trim(strtolower($this->getName()))); + } + + public function getSummary(): string { + return $this->project_summary ?? ''; + } + public function getDescription(): string { + return $this->project_description ?? ''; + } + public function getDescriptionLines(): array { + $linesRaw = array_reverse(explode("\n", $this->getDescription())); + $lines = []; + while(($line = array_pop($linesRaw)) !== false) { + $line = trim($line); + if(!empty($line)) + $lines[] = $line; + } + return $lines; + } + + public function getOrder(): int { + return $this->project_order; + } + public function getType(): string { + return $this->project_type; + } + public function isProject(): bool { + return $this->getType() === self::TYPE_PROJECT; + } + public function isTool(): bool { + return $this->getType() === self::TYPE_TOOL; + } + + public function isFeatured(): bool { + return boolval($this->project_featured); + } + + // TODO: INHERIT LANGUAGE COLOUR + public function hasColour(): bool { + return $this->project_colour !== null; + } + public function getColour(): FmColour { + return new FmColour($this->project_colour); + } + + public function hasHomepage(): bool { + return !empty($this->project_homepage); + } + public function getHomepage(): string { + return $this->project_homepage ?? ''; + } + + public function hasRepository(): bool { + return !empty($this->project_repository); + } + public function getRepository(): string { + return $this->project_repository ?? ''; + } + + public function hasForum(): bool { + return !empty($this->project_forum); + } + public function getForum(): string { + return $this->project_forum ?? ''; + } + + public function getCreatedTime(): DateTime { + return new DateTime('@' . ($this->project_created ?? 0)); + } + + public function isDeleted(): bool { + return $this->project_deleted !== null; + } + public function getDeletedTime(): DateTime { + return new DateTime('@' . ($this->project_deleted ?? 0)); + } + + public function isArchived(): bool { + return $this->project_archived !== null; + } + public function getArchivedTime(): DateTime { + return new DateTime('@' . ($this->project_archived ?? 0)); + } + + public function getLinks(): array { + $links = []; + if($this->hasHomepage()) + $links[] = FmProjectLink::create('homepage', 'Homepage', $this->getHomepage()); + if($this->hasRepository()) + $links[] = FmProjectLink::create('repository', 'Source', $this->getRepository()); + if($this->hasForum()) + $links[] = FmProjectLink::create('forum', 'Discussion', $this->getForum()); + return $links; + } + + public function getLanguages(): array { + return $this->languages ?? []; + } + + private function transformLanguages(): void { + if(empty($this->languages)) + return; + foreach($this->languages as &$lang) + if($lang instanceof stdClass) + $lang = FmLanguage::fromStdClass($lang); + } + + public static function byFeatured(): array { + return cache_output('projects-featured-noconvert', 300, function() { + $projects = json_decode(file_get_contents('https://flash.moe/2020/projects.php?dump_that_shit&noconvert&rf')); + + foreach($projects as &$project) { + $projRaw = (array)$project; + $project = new static; + foreach($projRaw as $prop => $val) + $project->{$prop} = $val; + $project->transformLanguages(); + } + + return $projects; + }); + } + + public static function all(): array { + return cache_output('projects-noconvert', 300, function() { + $projects = json_decode(file_get_contents('https://flash.moe/2020/projects.php?dump_that_shit&noconvert')); + + foreach($projects as &$project) { + $projRaw = (array)$project; + $project = new static; + foreach($projRaw as $prop => $val) + $project->{$prop} = $val; + $project->transformLanguages(); + } + + return $projects; + }); + } +} diff --git a/lib/fmprojectlink.php b/lib/fmprojectlink.php new file mode 100644 index 0000000..485bc67 --- /dev/null +++ b/lib/fmprojectlink.php @@ -0,0 +1,24 @@ +className; + } + public function getText(): string { + return $this->text; + } + public function getUrl(): string { + return $this->url; + } + + public static function create(string $class, string $text, string $url): self { + $link = new static; + $link->className = $class; + $this->text = $text; + $this->url = $url; + return $link; + } +} diff --git a/pages/blog.php b/pages/blog.php new file mode 100644 index 0000000..faf8cbd --- /dev/null +++ b/pages/blog.php @@ -0,0 +1,42 @@ + $title ?? '%title%', + 'external' => true, + 'styles' => [ + '//blog.flash.moe/assets/blog.css', + ], + ]); + $header = ob_get_contents(); + ob_clean(); + fm_component('footer', [ + 'external' => true, + 'scripts' => [ + '//blog.flash.moe/assets/blog.js', + ], + ]); + $footer = ob_get_contents(); + ob_end_clean(); + + echo json_encode([ + 'header' => $header, + 'footer' => $footer, + ]); + + return FM_HIT; +} diff --git a/pages/contact.php b/pages/contact.php new file mode 100644 index 0000000..4e91776 --- /dev/null +++ b/pages/contact.php @@ -0,0 +1,193 @@ +name)) + echo '[]'; + else { + $lfmInfo = $lfmInfo[0]; + echo json_encode([ + 'name' => strval($lfmInfo->name), + 'now_playing' => !empty($lfmInfo->nowplaying), + 'url' => strval($lfmInfo->url), + 'cover' => !empty($lfmInfo->images->large) ? strval($lfmInfo->images->large) : '', + 'artist' => [ + 'name' => !empty($lfmInfo->artist->name) ? strval($lfmInfo->artist->name) : '', + 'url' => explode('/_/', strval($lfmInfo->url))[0], + ], + ]); + } + + return FM_HIT; +} + +if($reqPath === '/contact') { + if($reqMethod !== 'GET') + return FM_ERR | 405; + + $contact = [ + [ + 'id' => 'contact', + 'title' => 'Direct Contact', + 'items' => [ + [ + 'id' => 'email', + 'name' => 'E-mail', + 'display' => 'me@flash.moe', + 'link' => 'mailto:me+contact@flash.moe', + ], + ], + ], + + [ + 'id' => 'communities', + 'title' => 'Communities & Social Media', + 'items' => [ + [ + 'id' => 'flashii', + 'name' => 'Flashii', + 'display' => 'flash', + 'link' => '//flashii.net/profile.php?u=1', + ], + [ + 'id' => 'twitter', + 'name' => 'Twitter', + 'display' => '@smugwave', + 'link' => '//twitter.com/smugwave', + ], + [ + 'id' => 'youtube', + 'name' => 'YouTube', + 'display' => 'flashwave', + 'link' => '//youtube.com/c/flashwave', + ], + [ + 'id' => 'github', + 'name' => 'Github', + 'display' => 'flashwave', + 'link' => '//github.com/flashwave', + ], + [ + 'id' => 'twitch', + 'name' => 'Twitch.tv', + 'display' => 'flashwave0', + 'link' => '//twitch.tv/flashwave0', + ], + [ + 'id' => 'lastfm', + 'name' => 'Last.fm', + 'display' => 'flashwave_', + 'link' => '//last.fm/user/flashwave_', + ], + ], + ], + + [ + 'id' => 'gaming', + 'title' => 'Gaming', + 'items' => [ + [ + 'id' => 'steam', + 'name' => 'Steam', + 'display' => 'flashwave_', + 'link' => '//steamcommunity.com/id/flashwave_', + ], + [ + 'id' => 'nin-sw', + 'name' => 'Nintendo Switch', + 'display' => 'SW-7446-8163-4902', + ], + [ + 'id' => 'nin-3ds', + 'name' => 'Nintendo 3DS', + 'display' => '4013-0352-0648', + ], + [ + 'id' => 'nin-wiiu', + 'name' => 'Wii U / NNID', + 'display' => 'flashwave0', + ], + [ + 'id' => 'osu', + 'name' => 'osu!', + 'display' => 'flash', + 'link' => '//osu.ppy.sh/u/flash', + ], + ], + ], + + [ + 'id' => 'support', + 'title' => 'Support me', + 'items' => [ + [ + 'id' => 'paypal', + 'name' => 'Paypal Donation', + 'display' => 'flashwave', + 'link' => '//paypal.me/flashwave', + ], + [ + 'id' => 'patreon', + 'name' => 'Patreon', + 'display' => 'flashwave', + 'link' => '//patreon.com/flashwave', + ], + ], + ], + ]; + + fm_component('header', [ + 'title' => 'flash.moe / contact', + ]); + + foreach($contact as $section) { +?> +
+
+
+

+
+
+
+ + + +
+ 'ASCII Table', + 'desc' => 'ASCII character set table with minor filtering functionality.', + 'link' => '//flash.moe/ascii.php', + ], + [ + 'title' => 'MIDI Collection', + 'desc' => 'My collection of MIDI and SF2 files.', + 'link' => '//flash.moe/midis', + ], + [ + 'title' => 'Randomised Keys', + 'desc' => 'Generates a number of random keys at various lengths using a secure random number generator.', + 'link' => '//flash.moe/key.php', + ], + [ + 'title' => 'The Abyss', + 'desc' => 'Accumulated collection of historical trash. Beware that the things here are unaltered products of their time.', + 'link' => '//abyss.flash.moe', + ], + ]; + + fm_component('header', [ + 'title' => 'flash.moe / etcetera', + ]); +?> +
+
+
+

Etcetera

+
+
+ +
+
+ +

+

+
+
+ 'flash.moe / now listening', + 'do_fullscreen_header' => true, + 'offset' => $offset, + ]); +?> + + true, + ]); + + return FM_HIT; +} + +if($reqPath === '/test') { + if($reqMethod !== 'GET') + return FM_ERR | 405; + + header('Content-Type: text/plain'); + + var_dump(FmProject::byFeatured()); + + return FM_HIT; +} + +if($reqPath === '/') { + if($reqMethod !== 'GET') + return FM_ERR | 405; + + $legacyPage = filter_input(INPUT_GET, 'p', FILTER_SANITIZE_STRING); + if(!empty($legacyPage)) { + $legacyPages = [ + 'projects' => '/projects', + 'contact' => '/contact', + 'about' => '/', + 'etc' => '/etc', + 'hosted' => '/etc', + 'friends' => '/related', + ]; + if(isset($legacyPages[$legacyPage])) { + header('Location: ' . $legacyPages[$legacyPage]); + return FM_HIT | 302; + } + } + + $blogInfo = cache_output('blog', 600, function() { + return json_decode(file_get_contents('https://flash.moe/2020/?blog_dump')); + }); + $projInfo = cache_output('projects-featured', 300, function() { + return json_decode(file_get_contents('https://flash.moe/2020/projects.php?dump_that_shit&rf')); + }); + + shuffle($projInfo); + + $contact = [ + [ + 'id' => 'email', + 'name' => 'E-mail', + 'display' => 'me@flash.moe', + 'link' => 'mailto:me+contact@flash.moe', + ], + [ + 'id' => 'flashii', + 'name' => 'Flashii', + 'display' => 'flash', + 'link' => '//flashii.net/profile.php?u=1', + ], + [ + 'id' => 'twitter', + 'name' => 'Twitter', + 'display' => '@smugwave', + 'link' => '//twitter.com/smugwave', + ], + [ + 'id' => 'github', + 'name' => 'Github', + 'display' => 'flashwave', + 'link' => '//github.com/flashwave', + ], + ]; + + fm_component('header', [ + 'title' => 'flash.moe', + 'is_index' => true, + ]); +?> +
+ + + +
+ + + true, + ]); + + return FM_HIT; +} diff --git a/pages/projects.php b/pages/projects.php new file mode 100644 index 0000000..db09297 --- /dev/null +++ b/pages/projects.php @@ -0,0 +1,91 @@ + 'flash.moe / projects', + ]); + + $sectionInfos = [ + 'project' => [ + 'title' => 'Active Projects', + 'desc' => 'Projects that I work on on a fairly regular basis.', + ], + 'tool' => [ + 'title' => 'Tools', + 'desc' => 'Personal quality of life tools that I update when I need something new from them.', + ], + 'archive' => [ + 'title' => 'Archived Projects', + 'desc' => 'Past projects that I no longer work on.', + ], + ]; + + foreach($projInfo as $section => $projects): + $sectionInfo = $sectionInfos[$section]; +?> +
+
+
+

+

+
+
+homepage)) + $links[] = ['class' => 'homepage', 'text' => 'Homepage', 'url' => $proj->homepage]; + if(isset($proj->repository)) + $links[] = ['class' => 'repository', 'text' => 'Source', 'url' => $proj->repository]; + if(isset($proj->forum)) + $links[] = ['class' => 'forum', 'text' => 'Discussion', 'url' => $proj->forum]; + + $descLines = explode("\n", trim($proj->description ?? '')); +?> +
+
+
+

name;?>
+languages as $lang): ?> +
+ name;?> +
+ +

+

summary;?>

+ +

+ +
+ + + +
+
+ 'flash.moe / related', + ]); +?> +
+
+
+

Related Sites

+
+
+ + 'Home', 'link' => '/'], + //['title' => 'Blog', 'link' => '//blog.flash.moe'], + ['title' => 'Blog', 'link' => '//flash.moe/2020/?blog=1'], + ['title' => 'Projects', 'link' => '/projects'], + ['title' => 'Contact', 'link' => '/contact'], + //['title' => 'Related', 'link' => '/related'], + ['title' => 'Etcetera', 'link' => '/etc'], + ['title' => 'Forum', 'link' => '//forum.flash.moe'], +]); + +define('FM_BGS', [ + '//mikoto.misaka.nl/i/Konachan.com%20-%20164484%20blush%20brown_eyes%20brown_hair%20drink%20misaka_mikoto%20seifuku%20short_hair%20skirt%20socks%20to_aru_kagaku_no_railgun%20to_aru_majutsu_no_index.png', + '//mikoto.misaka.nl/i/misaka%202.png', + '//mikoto.misaka.nl/i/misaka.jpg', + '//mikoto.misaka.nl/i/Drl8DEPWwAAPniH.jpg', + '//mikoto.misaka.nl/i/65776322_p2_master1200.jpg', + '//mikoto.misaka.nl/i/52666925_p0.jpg', + '//mikoto.misaka.nl/i/44161767_p0.jpg', + '//mikoto.misaka.nl/i/32809110_p0.jpg', + '//mikoto.misaka.nl/i/1551886307-ZEgXIk2.jpg', + '//mikoto.misaka.nl/i/1551886971-MgnvSNG.jpg', + '//mikoto.misaka.nl/i/1551881563-wR2Dcx8.jpg', + '//mikoto.misaka.nl/i/1552084409-BsTLlKg.jpg', +]); + +define('FM_FEET', [ + 'if it ain\'t broke, i\'ll break it', +]); + +define('FM_ERRS' , [ + 403 => ['code' => 403, 'title' => 'Access Denied'], + 404 => ['code' => 404, 'title' => 'Not Found'], + 405 => ['code' => 405, 'title' => 'Method Not Supported'], +]); + +function fm_component(string $name, array $vars = []) { + extract($vars); + require __DIR__ . '/../components/' . $name . '.php'; +} + +function first_paragraph(string $text, string $delimiter = "\n"): string { + $index = mb_strpos($text, $delimiter); + return $index === false ? $text : mb_substr($text, 0, $index); +} + +function time_elapsed(int $since, bool $full = false): string { + $now = new DateTime; + $since = new DateTime(date('c', $since)); + $diff = $now->diff($since); + + $diff->w = floor($diff->d / 7); + $diff->d -= $diff->w * 7; + + $string = [ + 'y' => 'year', + 'm' => 'month', + 'w' => 'week', + 'd' => 'day', + 'h' => 'hour', + 'i' => 'minute', + 's' => 'second', + ]; + + foreach($string as $key => &$value) { + if($diff->{$key}) + $value = $diff->{$key} . ' ' . $value . ($diff->{$key} > 1 ? 's' : ''); + else + unset($string[$key]); + } + + if(!$full) + $string = array_slice($string, 0, 1); + return $string ? implode(', ', $string) . ' ago' : 'just now'; +} + +function cache_output(string $name, int $lifetime, callable $callable) { + $path = sys_get_temp_dir() . '/fm-' . $name . '.cache'; + if(!is_file($path) || (filemtime($path) + $lifetime) < time()) + file_put_contents($path, serialize($callable())); + return unserialize(file_get_contents($path)); +} + +set_include_path(realpath(__DIR__ . '/../lib/') . PATH_SEPARATOR . get_include_path()); +spl_autoload_extensions('.php'); +spl_autoload_register(); + +ob_start(); + +$reqMethod = filter_input(INPUT_SERVER, 'REQUEST_METHOD', FILTER_SANITIZE_STRING); +$reqPath = '/' . trim(parse_url(filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_STRING), PHP_URL_PATH), '/'); + +if(substr($reqPath, 0, 7) === '/error/') { + $statusCode = intval(substr($reqPath, 8, 3)); +} else { + foreach(glob(__DIR__ . '/../pages/*.php') as $page) { + $result = include_once $page; + $statusCode = $result & 0xFFF; + if(($result & FM_HIT) === FM_HIT) { + if($statusCode >= 100 && $statusCode <= 999) + http_response_code($statusCode); + return; + } + if(($result & FM_ERR) === FM_ERR) + break; + } +} + +$errorInfo = FM_ERRS[$statusCode ?? 404] ?? FM_ERRS[404]; +http_response_code($errorInfo['code']); +fm_component('header', ['title' => $errorInfo['title']]); +printf("

%s

\r\n", $errorInfo['title']); +fm_component('footer');