Commit 468bc55ada

468bc55ada06979e53b1d03b040b2dfe6beaf017

Unsigned

cmc <hello@cleberg.net> · 2023-06-01 01:58 UTC

initial commit

Layout: unified · split

LICENSE added +24
@@ -0,0 +1,24 @@
1This is free and unencumbered software released into the public domain.
2
3Anyone is free to copy, modify, publish, use, compile, sell, or
4distribute this software, either in source code form or as a compiled
5binary, for any purpose, commercial or non-commercial, and by any
6means.
7
8In jurisdictions that recognize copyright laws, the author or authors
9of this software dedicate any and all copyright interest in the
10software to the public domain. We make this dedication for the benefit
11of the public at large and to the detriment of our heirs and
12successors. We intend this dedication to be an overt act of
13relinquishment in perpetuity of all present and future rights to this
14software under copyright law.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23
24For more information, please refer to <http://unlicense.org/>
README.md added +5
@@ -0,0 +1,5 @@
1# hn
2
3[hn](https://hn.cleberg.net) is a simple front-end alternative for Hacker News.
4hn focuses on the links shared on Hacker News, currently leaving out an options
5to login or view comments.
index.php added +112
@@ -0,0 +1,112 @@
1<?php
2
3$full_domain = 'https://hn.cleberg.net';
4$path = ltrim($_SERVER['REQUEST_URI'], '/');
5$elements = explode('/', $path);
6
7if (empty($elements[0])) {
8 get_stories(
9 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=30&orderBy="$key"',
10 'Top'
11 );
12 echo_html(
13 $GLOBALS['full_domain'] . '/best/',
14 'The top 30 stories from Hacker News. Proxied by hn.',
15 'hn',
16 $html_output
17 );
18} else {
19 switch (array_shift($elements)) {
20 case 'top':
21 get_stories(
22 'https://hacker-news.firebaseio.com/v0/topstories.json?limitToFirst=30&orderBy="$key"',
23 'Top'
24 );
25 echo_html(
26 $GLOBALS['full_domain'] . '/best/',
27 'The top 30 stories from Hacker News. Proxied by hn.',
28 'hn',
29 $html_output
30 );
31 break;
32
33 case 'best':
34 echo 'best';
35 break;
36
37 case 'new':
38 echo 'new';
39 break;
40
41 case 'ask':
42 echo 'ask';
43 break;
44
45 case 'show':
46 echo 'show';
47 break;
48
49 case 'job':
50 echo 'job';
51 break;
52
53 default:
54 header('HTTP/1.1 404 Not Found');
55 }
56}
57
58/**
59 * Extract a set of stories from Hacker News API and format in HTML
60 *
61 * @access public
62 * @author cmc <hello@cleberg.net>
63 * @param string $api_url The API endpoint to use for extraction
64 * @param string $inline_title The <h1> title to use in the HTML
65 * @return string $html_output The formatted HTML result of stories from the API
66 */
67function get_stories($api_url, $inline_title)
68{
69 $response_raw = file_get_contents($api_url);
70 $response = json_decode($response_raw, true);
71
72 $html_output = '<h1>' . $inline_title . '</h1>';
73
74 for ($i = 0; $i < count($response); $i++) {
75 $sub_url = 'https://hacker-news.firebaseio.com/v0/item/' . $response[$i] . '.json';
76 $sub_response_raw = file_get_contents($sub_url);
77 $sub_response = json_decode($sub_response_raw, true);
78
79 $html = '<div><a href="' . $sub_response['url'] . '">' . $sub_response['title'] . '</a>';
80 $html .= '<p><time datetime="' . date('Y-m-d h:m:s', $sub_response['time']) . '">';
81 $html .= date('Y-m-d h:m:s', $sub_response['time']) . '</time> by ';
82 $html .= $sub_response['by'] . ' | ' . $sub_response['score'] . ' points</p></div>';
83 $html_output .= $html;
84 }
85
86 return $html_output;
87}
88
89/**
90 * Send formatted HTML results to the user via a template
91 *
92 * @access public
93 * @author cmc <hello@cleberg.net>
94 * @param string $page_url Canoncial URL for HTML header
95 * @param string $page_description Page description for HTML header
96 * @param string $page_title Page title for HTML header
97 * @param string $page_content Page content to display in <main>
98 */
99function echo_html(string $page_url, string $page_description, string $page_title, string $page_content) {
100 include_once '_classes/template.php';
101
102 $template = new HN\View\Template(
103 $page_url,
104 $page_description,
105 $page_title,
106 $page_content
107 );
108
109 $template->echo_template();
110}
111
112// EOF
src/View/class-template.php added +39
@@ -0,0 +1,39 @@
1<?php
2
3namespace HN\View;
4
5/**
6 * Template View
7 *
8 * @author cmc <hello@cleberg.net>
9 */
10class Template
11{
12 public function __construct(string $canonical_url, string $page_description, string $page_title, string $content_col)
13 {
14 $this->canonical_url = $canonical_url;
15 $this->description = $page_description;
16 $this->title = $page_title;
17 $this->content = $content_col;
18 $this->current_year = date("Y");
19 }
20
21 public function echo_template()
22 {
23 // Get the template file
24 $template_file = 'templates/template.html';
25 $page = file_get_contents($template_file);
26
27 // Replace the template variables
28 $page = str_replace('{page_title}', $this->title, $page);
29 $page = str_replace('{page_description}', $this->description, $page);
30 $page = str_replace('{canonical_url}', $this->canonical_url, $page);
31 $page = str_replace('{content}', $this->content, $page);
32 $page = str_replace('{current_year}', $this->current_year, $page);
33
34 // Echo the filled-out template
35 echo $page;
36 }
37}
38
39// EOF
templates/template.html added +37
@@ -0,0 +1,37 @@
1<!doctype html>
2<html lang="en">
3
4<head>
5 <title>{page_title}</title>
6 <meta charset="UTF-8">
7 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
8 <meta http-equiv="x-ua-compatible" content="ie=edge">
9 <meta name="author" content="My Name">
10 <meta name="description" content="{page_description}">
11 <link rel="canonical" href="{canoncial_url}">
12 <link rel="icon" href="/favicon.ico">
13 <link rel="stylesheet" href="/static/styles.css">
14</head>
15
16<body>
17<main id="main">
18 <nav class="links">
19 <span><a href="/">Top</a> &middot; </span>
20 <span><a href="/best/">Best</a> &middot;</span>
21 <span><a href="/new/">New</a> &middot;</span>
22 <span><a href="/ask/">Ask</a> &middot;</span>
23 <span><a href="/show/">Show</a> &middot;</span>
24 <span><a href="/job/">Job</a></span>
25 </nav>
26 {content}
27</main>
28
29<footer>
30 <h2>Contact</h2>
31 <p><a href="https://sr.ht/~cmc/hn/"></a></p>
32 <p>Copyright &copy; 2023 - {current_year}</p>
33</footer>
34
35</body>
36
37</html>