aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Cleberg <hello@cleberg.net>2023-05-31 20:58:43 -0500
committerChristian Cleberg <hello@cleberg.net>2023-05-31 20:58:43 -0500
commit468bc55ada06979e53b1d03b040b2dfe6beaf017 (patch)
tree472b23c050ab8ce7d1ae1cab30bcb37ebfe031e5
downloadhn-468bc55ada06979e53b1d03b040b2dfe6beaf017.tar.gz
hn-468bc55ada06979e53b1d03b040b2dfe6beaf017.tar.bz2
hn-468bc55ada06979e53b1d03b040b2dfe6beaf017.zip
initial commit
-rw-r--r--LICENSE24
-rw-r--r--README.md5
-rw-r--r--index.php112
-rw-r--r--src/View/class-template.php39
-rw-r--r--templates/template.html37
5 files changed, 217 insertions, 0 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..68a49da
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <http://unlicense.org/>
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..de3700d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# hn
+
+[hn](https://hn.cleberg.net) is a simple front-end alternative for Hacker News.
+hn focuses on the links shared on Hacker News, currently leaving out an options
+to login or view comments.
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..f5f7438
--- /dev/null
+++ b/index.php
@@ -0,0 +1,112 @@
+<?php
+
+$full_domain = 'https://hn.cleberg.net';
+$path = ltrim($_SERVER['REQUEST_URI'], '/');
+$elements = explode('/', $path);
+
+if (empty($elements[0])) {
+ get_stories(
+ 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=30&orderBy="$key"',
+ 'Top'
+ );
+ echo_html(
+ $GLOBALS['full_domain'] . '/best/',
+ 'The top 30 stories from Hacker News. Proxied by hn.',
+ 'hn',
+ $html_output
+ );
+} else {
+ switch (array_shift($elements)) {
+ case 'top':
+ get_stories(
+ 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=30&orderBy="$key"',
+ 'Top'
+ );
+ echo_html(
+ $GLOBALS['full_domain'] . '/best/',
+ 'The top 30 stories from Hacker News. Proxied by hn.',
+ 'hn',
+ $html_output
+ );
+ break;
+
+ case 'best':
+ echo 'best';
+ break;
+
+ case 'new':
+ echo 'new';
+ break;
+
+ case 'ask':
+ echo 'ask';
+ break;
+
+ case 'show':
+ echo 'show';
+ break;
+
+ case 'job':
+ echo 'job';
+ break;
+
+ default:
+ header('HTTP/1.1 404 Not Found');
+ }
+}
+
+/**
+ * Extract a set of stories from Hacker News API and format in HTML
+ *
+ * @access public
+ * @author cmc <hello@cleberg.net>
+ * @param string $api_url The API endpoint to use for extraction
+ * @param string $inline_title The <h1> title to use in the HTML
+ * @return string $html_output The formatted HTML result of stories from the API
+ */
+function get_stories($api_url, $inline_title)
+{
+ $response_raw = file_get_contents($api_url);
+ $response = json_decode($response_raw, true);
+
+ $html_output = '<h1>' . $inline_title . '</h1>';
+
+ for ($i = 0; $i < count($response); $i++) {
+ $sub_url = 'https://hacker-news.firebaseio.com/v0/item/' . $response[$i] . '.json';
+ $sub_response_raw = file_get_contents($sub_url);
+ $sub_response = json_decode($sub_response_raw, true);
+
+ $html = '<div><a href="' . $sub_response['url'] . '">' . $sub_response['title'] . '</a>';
+ $html .= '<p><time datetime="' . date('Y-m-d h:m:s', $sub_response['time']) . '">';
+ $html .= date('Y-m-d h:m:s', $sub_response['time']) . '</time> by ';
+ $html .= $sub_response['by'] . ' | ' . $sub_response['score'] . ' points</p></div>';
+ $html_output .= $html;
+ }
+
+ return $html_output;
+}
+
+/**
+ * Send formatted HTML results to the user via a template
+ *
+ * @access public
+ * @author cmc <hello@cleberg.net>
+ * @param string $page_url Canoncial URL for HTML header
+ * @param string $page_description Page description for HTML header
+ * @param string $page_title Page title for HTML header
+ * @param string $page_content Page content to display in <main>
+ */
+function echo_html(string $page_url, string $page_description, string $page_title, string $page_content) {
+ include_once '_classes/template.php';
+
+ $template = new HN\View\Template(
+ $page_url,
+ $page_description,
+ $page_title,
+ $page_content
+ );
+
+ $template->echo_template();
+}
+
+// EOF
diff --git a/src/View/class-template.php b/src/View/class-template.php
new file mode 100644
index 0000000..ea75648
--- /dev/null
+++ b/src/View/class-template.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace HN\View;
+
+/**
+ * Template View
+ *
+ * @author cmc <hello@cleberg.net>
+ */
+class Template
+{
+ public function __construct(string $canonical_url, string $page_description, string $page_title, string $content_col)
+ {
+ $this->canonical_url = $canonical_url;
+ $this->description = $page_description;
+ $this->title = $page_title;
+ $this->content = $content_col;
+ $this->current_year = date("Y");
+ }
+
+ public function echo_template()
+ {
+ // Get the template file
+ $template_file = 'templates/template.html';
+ $page = file_get_contents($template_file);
+
+ // Replace the template variables
+ $page = str_replace('{page_title}', $this->title, $page);
+ $page = str_replace('{page_description}', $this->description, $page);
+ $page = str_replace('{canonical_url}', $this->canonical_url, $page);
+ $page = str_replace('{content}', $this->content, $page);
+ $page = str_replace('{current_year}', $this->current_year, $page);
+
+ // Echo the filled-out template
+ echo $page;
+ }
+}
+
+// EOF
diff --git a/templates/template.html b/templates/template.html
new file mode 100644
index 0000000..638562a
--- /dev/null
+++ b/templates/template.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+ <title>{page_title}</title>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+ <meta http-equiv="x-ua-compatible" content="ie=edge">
+ <meta name="author" content="My Name">
+ <meta name="description" content="{page_description}">
+ <link rel="canonical" href="{canoncial_url}">
+ <link rel="icon" href="/favicon.ico">
+ <link rel="stylesheet" href="/static/styles.css">
+</head>
+
+<body>
+<main id="main">
+ <nav class="links">
+ <span><a href="/">Top</a> &middot; </span>
+ <span><a href="/best/">Best</a> &middot;</span>
+ <span><a href="/new/">New</a> &middot;</span>
+ <span><a href="/ask/">Ask</a> &middot;</span>
+ <span><a href="/show/">Show</a> &middot;</span>
+ <span><a href="/job/">Job</a></span>
+ </nav>
+ {content}
+</main>
+
+<footer>
+ <h2>Contact</h2>
+ <p><a href="https://sr.ht/~cmc/hn/"></a></p>
+ <p>Copyright &copy; 2023 - {current_year}</p>
+</footer>
+
+</body>
+
+</html>