Archived
4
2

110 Commits

Author SHA1 Message Date
Roan Horning
0f4fdc2d46 Merge pull request 'Add lazy loading to host image' (#88) from I83_Lazy_load_host_images into main
Reviewed-on: #88
2023-03-04 22:00:52 +00:00
Roan Horning
d3c2401e28 Merge branch 'main' into I83_Lazy_load_host_images 2023-03-04 22:00:21 +00:00
Gordon Stanton
c744bdf175 Moved host thumbnail image tag to separate template file.
Added loading="lazy" to image tag.
Changed alt text to show host username.
2023-03-05 02:07:03 +11:00
Roan Horning
444c05f8f9 Merge pull request '[I82] creating sqlite db from hpr.sql' (#86) from I82_creating-sqlite-db-from-hpr.sql into main
Reviewed-on: #86
2023-03-04 05:00:40 +00:00
24a12a5af3 Update instructions for creating SQLite db
Update the main README file and the POD Installation section
of the site-configuration program.
2023-03-03 23:53:21 -05:00
add92ef20d Add utility script to refresh the local website
This script  will download latest MySQL dump file from
hacckerpublicradio.org. Generate a new hpr.db SQLite file,
and then regenerate all of the website files.
2023-03-03 23:32:35 -05:00
f8e397d0bd Add required script mysql2sqlite to repository
Converts MySQL dump to SQLite3 compatible dump
    (including MySQL KEY xxxxx statements from the CREATE block).

    Website: https://github.com/dumblob/mysql2sqlite
    The MIT License (MIT)
    Copyright (c) 2015 esperlu, 2016 dumblob
2023-03-03 23:00:50 -05:00
6d588dc558 Merge branch 'main' into I82_creating-sqlite-db-from-hpr.sql 2023-03-03 22:52:21 -05:00
Roan Horning
f0b0b5ea59 Merge pull request 'Fix database instructions in configuration file' (#85) from Fix_db_sqlite_settings into main
Reviewed-on: #85
2023-03-04 03:49:09 +00:00
a33fa197df Fix database instructions in configuration file
Add back instructions for SQLite
2023-03-03 22:44:05 -05:00
e7e752f1e8 Improve function messages 2023-03-03 21:47:29 -05:00
094287837c Put variables into local scope of the function
Forgot to use the local keyword when declaring the variables.
2023-03-03 21:44:35 -05:00
a53f201842 Code formatting with no functional changes 2023-03-03 20:46:34 -05:00
2ce1280cc0 Make functional stub function copy_to_public_dir 2023-03-03 20:45:16 -05:00
d45ca0de96 Make functional stub function make_hpr_sqlite_db 2023-03-03 20:42:42 -05:00
13aeb647ad Make functional stub function download_hpr_sql 2023-03-03 20:41:29 -05:00
ee6a4e601d Fill out function clean_working_dir 2023-02-27 23:30:24 -05:00
b544687f0f Fill out stub of make_working_dir function 2023-02-27 23:27:26 -05:00
0ed7efe93b Initial add of bash library for update utils
Stubs for functions to be used in update scripts.
2023-02-27 21:07:01 -05:00
Roan Horning
b4e4187902 Merge pull request 'Fix URL's to series RSS feeds' (#80) from I78_Fix-link-to-series-RSS-links into main
Reviewed-on: #80
2023-02-26 04:13:06 +00:00
431126e8a3 Fix URL's to series RSS feeds 2023-02-25 23:06:41 -05:00
Roan Horning
91ceefd88e Merge pull request '[I62] Hide display of future shows on series pages' (#79) from I62_Hide-display-of-future-shows-on-series-pages into main
Reviewed-on: #79
2023-02-25 20:11:11 +00:00
8feb37e831 Hide display of future shows on series episodes page 2023-02-25 14:22:44 -05:00
4a34496f24 Hide display of future shows on series listings page 2023-02-25 11:44:56 -05:00
Roan Horning
f7e54233e2 Merge pull request '[I12] Implement comments_viewer page' (#77) from I12_Implement-comments-viewer into main
Reviewed-on: #77
2023-02-25 01:44:50 +00:00
59875e772e Implement comments_viewer page 2023-02-24 20:42:01 -05:00
Roan Horning
f84ee71b7c Merge pull request '[I75] Fix missing show transcipts[' (#76) from I75_Fix-missing-show-transcipts into main
Reviewed-on: #76
2023-02-25 00:06:18 +00:00
927424901b Add show_transcript MACRO to index and episode pages 2023-02-24 18:58:56 -05:00
27a84529c6 Create shared template for showing show transcripts
Used in main index page and individual episode pages.
2023-02-24 18:57:20 -05:00
59549daa63 Fix archive.org paths in media_path MACRO 2023-02-24 18:55:37 -05:00
Roan Horning
ec7a6ce379 Merge pull request 'Refactor RSS templates for either MySQL or SQLite' (#74) from I73-Fix_queries_for-RSS_feeds into main
Reviewed-on: #74
2023-02-21 03:41:55 +00:00
756bdc0fa1 Refactor RSS templates for either MySQL or SQLite 2023-02-20 22:36:30 -05:00
b2eaea1eb8 Improve look of hosts table 2023-02-12 16:54:17 -05:00
Roan Horning
fe9bf574cf Merge pull request 'Update sydication template text' (#69) from I67-Update_syndication_page into main
Reviewed-on: #69
2023-02-12 19:36:17 +00:00
309ea05c15 Update sydication template text
Now matches what is in the syndication.php page on
hakerpublicradio.org
2023-02-12 13:46:11 -05:00
Roan Horning
649d6c3746 Merge pull request 'Make tags page menu link hard coded' (#68) from I63_Fix-menu-link-to-tags-page into main
Reviewed-on: #68
2023-02-12 18:10:12 +00:00
e41f6029aa Make tags page menu link hard coded
Not implementing tags page in the static generator yet.
Make the link point to the php page on hackerpublicradio.org.
2023-02-12 13:07:06 -05:00
Roan Horning
4bd7c6f867 Merge pull request 'I64_Implement-Show-Transcript-section' (#66) from I64_Implement-Show-Transcript-section into main
Reviewed-on: #66
2023-02-12 16:07:47 +00:00
138b0fdd1b Add Show Transcript section to episode template 2023-02-12 10:58:43 -05:00
d437e66f0e Update media_path MACRO for archive.org transciption files
The whisper transcription files are stored one directory
deeper on archive.org. Add checks and correct path when
passed txt, srt, or vtt media_type.
2023-02-12 10:53:50 -05:00
Roan Horning
a213efa695 Merge pull request '[I57] MySQL implementation' (#65) from MySQL into main
Reviewed-on: #65
2023-02-12 12:59:13 +00:00
Roan Horning
314127441c Merge branch 'main' into MySQL 2023-02-12 12:57:38 +00:00
2a486cb58b Add SQLite specific query templates 2023-02-08 16:05:36 -05:00
7c44f6b680 Remove New Year's Eve 2023 show announcement 2023-01-03 10:08:52 -05:00
71a63e1beb Merge branch 'main' into MySQL 2022-12-31 18:39:25 -05:00
8e1232517a Update New Year's Eve show 2023 2022-12-31 15:55:39 -05:00
cb65d25cfc Refactor MySQL database specific SQL 2022-11-28 22:47:53 -05:00
2b4802508d Remove superflous WHERE condition 2022-11-28 19:55:51 -05:00
1312e3d374 Refactor MySQL database specific SQL 2022-11-28 19:52:39 -05:00
3cc6da57ad Refactor MySQL database specific SQL 2022-11-28 19:49:06 -05:00
675f8fa9d5 Refactor MySQL database specific SQL 2022-11-27 14:04:12 -05:00
6f28bb2a16 Refactor MySQL database specific SQL 2022-11-27 13:54:14 -05:00
cb881558ca Add database type constant for use in templates
This is used to select which database specific SQL query to use.
2022-11-27 13:11:14 -05:00
4e8edf2640 Merge branch 'main' into MySQL 2022-11-11 20:27:47 -05:00
Roan Horning
e86d2c010d Merge pull request '[I60] Implement call for shows feature' (#61) from I60_call-for-shows into main
Reviewed-on: #61
2022-11-11 03:18:38 +00:00
f0fa21ae45 Implement call for shows feature
Add display_call_for_shows MACRO. Update index template to include
call to display_call_for_shows.
2022-11-10 22:14:55 -05:00
0b99483f0d Update installation instruction to include details for MySQL 2022-10-22 21:11:57 -04:00
8c3874ad8b Convert hpr total rss queries from SQLite to MySQL 2022-10-21 23:00:03 -04:00
6f95a33e67 Convert hpr rss queries from SQLite to MySQL 2022-10-21 22:53:13 -04:00
979c8b43e5 Convert twat episode page queries from SQLite to MySQL 2022-10-21 20:43:22 -04:00
e3abe5fd68 Convert series episode page queries from SQLite to MySQL 2022-10-21 20:11:19 -04:00
5612eeed42 Convert episode page queries from SQLite to MySQL 2022-10-21 20:07:53 -04:00
4af117fb7a Convert episodes page queries from SQLite to MySQL 2022-10-21 19:52:53 -04:00
e1b0189275 Convert correspondent page queries from SQLite to MySQL 2022-10-21 19:46:31 -04:00
aad77f3c78 Convert index page queries from SQLite to MySQL 2022-10-20 23:24:56 -04:00
be1344e10c Update database connection information 2022-10-20 23:23:00 -04:00
Roan Horning
308d03d63c Merge pull request '[I55] announcements template' (#56) from I55_announcements-template into main
Reviewed-on: #56
2022-10-16 23:11:14 +00:00
0837e11bfe Include announcement template in index template 2022-10-16 18:56:13 -04:00
06ace35c41 Add announcement template 2022-10-16 18:23:51 -04:00
6d0d1b99a6 Add page mumble-howto 2022-10-16 18:12:05 -04:00
fdeff3879a Update links in the comments section of the episode template 2022-10-09 15:45:22 -04:00
b667c30d40 Update links on syndication page
Add missing external links. Update comments feed link to new statically
generated file.
2022-10-09 13:51:00 -04:00
b08f5c30df Add missing USE date directive
Worked without it in local dev, but needed on hpr.horning.us
2022-10-08 12:35:56 -04:00
Roan Horning
d8613143d3 Merge pull request '[I41] Implement comments feed' (#54) from I41_Implement-comments-feed into main
Reviewed-on: #54
2022-10-08 13:34:45 +00:00
3de4476a3f Add comments feed template 2022-10-08 08:52:47 -04:00
4984ac3383 Add MACRO rss_show_series 2022-10-08 08:48:42 -04:00
e4463dc5ba Zero pad the day's date 2022-10-08 08:44:47 -04:00
Roan Horning
bf8bf8daad Merge pull request '[I52] Allow audio content to be hosted on at different url' (#53) from I52_media_urls into main
Reviewed-on: #53
2022-10-02 18:17:14 +00:00
1d4e6e15b7 Refactor templates to use media_path MACRO 2022-10-01 13:42:46 -04:00
d556e28e2d Consume root_template properties generically
Allow user to define root_template properties in the site.cfg file
without need to modify site_generator program.
2022-10-01 13:33:59 -04:00
fb70ae6253 Add media_path MACRO to shared utilities
Generate the full URL of an audio file.
2022-10-01 13:23:36 -04:00
64ae9c4f86 Refactor media_baseurl MACRO to media_basepath MACRO
Prevent name collision with media_basepath root_template/page property
of same name. Also fix application of trailing forward slash to path
based on existence of baseurl property.
2022-10-01 13:18:35 -04:00
b0d31ee507 Allow user to modify zero_pad_left MACRO's padding
Add optional pad length argument
2022-10-01 12:51:11 -04:00
Roan Horning
6ac65212d7 Merge pull request '[I50] Fix ordering by episode id' (#51) from I50_Fix-ordering-by-episode-id into main
Reviewed-on: #51
2022-09-22 01:47:25 +00:00
991b3dcec1 Update SQL query to order results by id 2022-09-21 21:18:48 -04:00
Roan Horning
1c9eb16934 Merge pull request '[I48] Fix MACRO step_navigation' (#49) from I48_Fix-step-navigation into main
Reviewed-on: #49
2022-09-20 02:03:41 +00:00
2eaaa11a69 Fix MACRO step_navigation
Check for existence of folder arg instead of empty value.
2022-09-19 22:00:18 -04:00
3723303e31 Fix absolute path for media links 2022-09-18 19:21:19 -04:00
Roan Horning
db46938de6 Merge pull request '[I46] Extract Listen Now markup to macro' (#47) from I46_Extract-Listen-Now-markup-to-macro into main
Reviewed-on: #47
2022-09-18 20:32:32 +00:00
3054d6519e Refactor template to use media_baseurl MACRO 2022-09-18 16:27:47 -04:00
c6e7a3c239 Refactor templates to use listen_now MACRO 2022-09-18 16:23:35 -04:00
dbf011395c Add MACRO listen_now 2022-09-18 16:21:00 -04:00
c817e3a17a Add MACRO media_baseurl
Allow the audio files to be served from a different host
2022-09-18 16:18:05 -04:00
0edf9cc5a2 Fix missing id generation for twat episdoe files 2022-09-18 15:36:24 -04:00
Roan Horning
4d34f762d0 Merge pull request '[I43] Integrate twat episodes' (#45) from I43_Today-With-a-Techie-Archived-Shows into main
Reviewed-on: #45
2022-09-17 21:47:38 +00:00
dbd9f8e973 Integrate twat episodes
Add twat shows to the full episodes index, the host pages.
Add individule twat episodes.
2022-09-17 17:28:39 -04:00
Ken Fallon
4fdb32934b Added viewport
Google reports issues with this so I added it
https://web.dev/responsive-web-design-basics/#viewport
2022-09-09 07:45:49 +00:00
Roan Horning
5bd96f69e0 Merge pull request 'Calculate date till next available episode slot' (#40) from I39_days-till-next-available-episode into main
Reviewed-on: #40
2022-09-06 00:33:17 +00:00
38d2e7c363 Calculate date till next available episode slot 2022-09-05 20:26:12 -04:00
Roan Horning
7691209360 Merge pull request '[I37] Fix display of meta data on the episode page' (#38) from I37_Fix-display-meta-data-episode-page into main
Reviewed-on: #38
2022-09-02 22:29:44 +00:00
f7216132a4 Update episode template to match current HPR layout and content 2022-09-02 18:23:50 -04:00
67a8a2bfa4 Add MACRO display_listen_in 2022-09-02 18:21:15 -04:00
cfd463d2b0 Add MACRO display_comments_tally 2022-09-01 23:05:59 -04:00
91cbc81a12 Add MACRO display_tags 2022-09-01 22:58:24 -04:00
Roan Horning
c1a83f8baf Merge pull request '[I35] Add episode comment tally' (#36) from I35_Add-comment-tally into main
Reviewed-on: #36
2022-09-01 01:08:45 +00:00
3b72fe6d28 Add comments to episode page 2022-08-31 20:44:31 -04:00
76b976732b Add comment tally to index page 2022-08-31 20:43:43 -04:00
Roan Horning
bf60d35ed1 Merge pull request '[I33] Format episode duration' (#34) from I33_episode-duration into main
Reviewed-on: #34
2022-08-30 02:03:13 +00:00
e2cf52af6e Use MACRO display_episode_duration in templates 2022-08-29 21:59:24 -04:00
414bae101a Add MACRO display_episode_duration
Format duration as hh:mm:ss
2022-08-29 21:54:42 -04:00
75 changed files with 1867 additions and 203 deletions

View File

@@ -3,12 +3,27 @@ Static web page generator for the Hacker Public Radio website.
## Installation
* Clone or download this repository
* Create the sqlite3 database from the files in the _sql directory. The default name for the database file is "hpr.db" and should be located in the root of the project directory. The name and location can be set in the site.cfg file.
* Two sql helper scripts are available to generate an empty database or a database filled with test data.
- For an empty database: `cat Create_Database_Empty.sql | sqlite3 hpr.db`
- For a database with test data: `cat Create_Database_Test.sql | sqlite3 hpr.db`
* SQLite v3.8.3 or greater is recommended. CTE WITH clauses are used in some template queries. Must convert WITH
clauses to sub-queries when using earlier versions of SQLite.
* With SQLite
* Create the sqlite3 database from the hpr.sql MySQL dump file available on
hackerpublicradio.org. The default name for the database file is "hpr.db"
and should be located in the root of the project directory. The name and
location can be set in the site.cfg file.
* An "update-hpr.sh" helper script is available in the utils directory. This
script will download the hpr.sql file, convert it to the SQLite hpr.db file,
and regenerate the website using the site-generator.
1. `cd` into the root of the project directory
2. Run `./utils/update-hpr.sh`
* SQLite v3.8.3 or greater is recommended. CTE WITH clauses are used in some template queries. Must convert WITH
clauses to sub-queries when using earlier versions of SQLite.
* With MySQL
* Create database hpr_hpr in the MySQL server from HPR dump file.
- ``sudo mysql --host=localhost < hpr.sql``
* Create a user that will be used by the site-generator.
- Suggested username: hpr-generator
- ``CREATE USER 'hpr-generator'@'localhost' IDENTIFIED BY '<password>';``
* Limit the user's privileges to EXECUTE and SELECT
- ``GRANT SELECT ON hpr_hpr.* TO 'hpr-generator'@'localhost';``
- ``GRANT EXECUTE ON `hpr_hpr`.* TO 'hpr-generator'@'localhost';``
* Install the needed Perl modules using preferred method (distribution packages, CPAN, etc.)
* GetOpt
* Pod::Usage
@@ -18,7 +33,7 @@ Static web page generator for the Hacker Public Radio website.
* Template::Plugin::DBI
* DBI
* Tie::DBI
* DBD::SQLite
* DBD::SQLite or DBD:mysql
* Date::Calc
## Usage
@@ -50,4 +65,3 @@ and add the label "**Feature Request**".
## Authors and acknowledgment
* Roan "Rho`n" Horning

View File

@@ -235,6 +235,17 @@ pre { /* Add background, border and scrollbar to <pre> */
clear: both;
}
table.hosts {
background: white
}
table.hosts tr:nth-child(even) { background-color:#cccccc; }
table.hosts tr:nth-child(odd) { background-color:white; }
table.hosts tr td img { vertical-align:middle }
pre.comment {
white-space: pre-wrap;
padding: 2px;
line-height: 1.2rem;
}
@media only screen and (max-width: 680px) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -35,15 +35,30 @@ This is a site generator for the Hacker Public Radio website based upon the Perl
=head1 INSTALLATION
* Create the sqlite3 database from the files in the _sql directory. The default name for the
database file is "hpr.db" and should be located in the root of the project directory. The
name and location can be set in the site.cfg file.
* Two sql helper scripts are available to generate an empty database or a database filled with test data.
- For an empty database: `cat Create_Database_Empty.sql | sqlite3 hpr.db`
- For a database with test data: `cat Create_Database_Test.sql | sqlite3 hpr.db`
* SQLite v3.8.3 or greater is recommended. CTE WITH clauses are used in some template queries. Must convert WITH
clauses to sub-queries when using earlier versions of SQLite.
* Install the needed Perl modules using preferred method (distribution packages, CPAN, etc.)
With SQLite
* Create the sqlite3 database from the hpr.sql MySQL dump file available on
hackerpublicradio.org. The default name for the database file is "hpr.db"
and should be located in the root of the project directory. The name and
location can be set in the site.cfg file.
* An "update-hpr.sh" helper script is available in the utils directory. This
script will download the hpr.sql file, convert it to the SQLite hpr.db file,
and regenerate the website using the site-generator.
1. `cd` into the root of the project directory
2. Run `./utils/update-hpr.sh`
* SQLite v3.8.3 or greater is recommended. CTE WITH clauses are used in some template queries.
Must convert WITH clauses to sub-queries when using earlier versions of SQLite.
With MySQL
* Create database hpr_hpr in the MySQL server from HPR dump file.
- sudo mysql --host=localhost < hpr.sql
* Create a user that will be used by the site-generator.
- Suggested username: hpr-generator
- CREATE USER 'hpr-generator'@'localhost' IDENTIFIED BY '<password>';
* Limit the user's privileges to EXECUTE and SELECT
- GRANT SELECT ON hpr_hpr.* TO 'hpr-generator'@'localhost';
- GRANT EXECUTE ON `hpr_hpr`.* TO 'hpr-generator'@'localhost';
Install the needed Perl modules using preferred method (distribution packages, CPAN, etc.)
* GetOpt
* Pod::Usage
* Config::Std
@@ -52,7 +67,7 @@ This is a site generator for the Hacker Public Radio website based upon the Perl
* Template::Plugin::DBI
* DBI
* Tie::DBI
* DBD::SQLite
* DBD::SQLite or DBD:mysql
* Date::Calc
=head1 AUTHOR
@@ -125,6 +140,8 @@ sub main {
# from the generated list of pages.
@page_args= grep { $_ ne 'DBI' } @page_args;
@page_args= grep { $_ ne 'root_template' } @page_args;
@page_args= grep { $_ ne 'media_hostname' } @page_args;
};
foreach my $page_arg (@page_args) {
my %parsed_arg = parse_page_arg($page_arg);
@@ -138,8 +155,13 @@ sub main {
$page_config->{'root_template'} = $config{root_template}{content};
}
if (exists $config{root_template}{baseurl}) {
$page_config->{'baseurl'} = $config{root_template}{baseurl};
# Set all config root_template properties as default page config properties
# except the previously set root_template content property
my @root_args = grep { $_ ne 'content' } keys %{$config{root_template}};
foreach my $root_arg (@root_args) {
if (exists $page_config->{$root_arg} == 0) {
$page_config->{$root_arg} = $config{root_template}{$root_arg};
}
}
if ($page_config->{'multipage'} && $page_config->{'multipage'} eq 'true') {
@@ -179,6 +201,7 @@ sub get_template_html (\%@) {
PRE_CHOMP => 1,
POST_CHOMP => 1,
CONSTANTS => {
database => $_[0]{database},
driver => $_[0]{driver},
user => $_[0]{user},
password => $_[0]{password},

View File

@@ -2,9 +2,16 @@
# with the database.
# dbi:<driver name [SQLite, CSV, ADO, mSQL, etc.]>:<database name>
[DBI]
driver: dbi:SQLite:hpr.db
user:
password:
# Configuration settings for SQLite
#database: sqlite
#driver: dbi:SQLite:hpr.db
#user: (not used - leave blank)
#password: (not used - leave blank)
# Configuration settings for MySQL
#database: mysql
#driver: dbi:mysql:database=hpr_hpr:hostname=localhost
#user: hpr-generator (Suggested user with read-only privileges)
#password: ********* (Password for user)
# Configure the root template page which pulls in the navigation and
# content templates used by each page. An optional baseurl property may
@@ -13,6 +20,8 @@ password:
[root_template]
content: page.tpl.html
#baseurl: OPTIONAL [i.e. file://<full path to local website directory>]
baseurl: file:///home/roan/Development/hpr/website/hpr_generator/public_html/
media_baseurl: https://archive.org/download/hpr$eps_id/
# Configure the navigation menu and the content templates for each page
# of the site:
@@ -132,6 +141,21 @@ content: content-promote.tpl.html
navigation: navigation-about.tpl.html
content: content-sitemap.tpl.html
[twat_episode]
navigation: navigation-get-shows.tpl.html
content: content-twat_episode.tpl.html
multipage: true
filename: eps/twat[id]/index.html
media_baseurl: https://www.hackerpublicradio.org/eps/
[mumble-howto]
navigation: navigation-about.tpl.html
content: content-mumble-howto.tpl.html
[comments_viewer]
navigation: navigation-about.tpl.html
content: content-comments_viewer.tpl.html
[hpr_ogg]
root_template: rss.tpl.xml
content: rss-hpr.tpl.xml
@@ -169,3 +193,7 @@ root_template: rss.tpl.xml
content: rss-hpr_total.tpl.xml
filename: hpr_total_spx.rss
media_file_extension: spx
[comments]
root_template: rss-comments.tpl.xml
filename: comments.rss

View File

@@ -0,0 +1,43 @@
<!--% PROCESS 'shared-episode-summary.tpl.html' %-->
<!--% PROCESS 'shared-avatar.tpl.html' %-->
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% PROCESS 'shared-listen-now.tpl.html' %-->
<!--% PROCESS "queries-episode-${constants.database}.tpl.html" %-->
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<h2>Comment Viewer</h2>
<p>Because of the spammers we have had to turn on comment moderation. Sorry about the delay this will cause.</p>
<p><a href="<!--% absolute_path(baseurl) %-->comments.rss">Subscribe</a> to the comment feed.</p>
<hr />
<!--% FOREACH item IN DBI.query('
SELECT C.*,
H.host, H.hostid AS host_id,
E.title AS episode_title,
E.date AS episode_date,
E.duration AS episode_duration,
M.id AS series_id, M.name AS series_name
FROM comments AS C
INNER JOIN eps AS E
ON C.eps_id = E.id
INNER JOIN hosts AS H
ON E.hostid = H.hostid
INNER JOIN miniseries AS M
ON E.series = M.id
ORDER BY C.comment_timestamp DESC
LIMIT 30
')
%-->
<article>
<header>
<h1><!--% item.comment_author_name %--> says: <!--% item.comment_title %--></h1>
<p><small>Posted at <!--% item.comment_timestamp %--> relating to the show <a href="<!--% absolute_path(baseurl) %-->eps/hpr<!--% zero_pad_left(item.eps_id) %-->/index.html">hpr<!--% item.eps_id %--></a> which was released on <!--% item.episode_date %--> by <a href="<!--% absolute_path(baseurl) %-->correspondents/<!--% zero_pad_left(item.host_id) %-->.html"><!--% item.host %--></a> entitled <em><!--% item.episode_title %--></em></small>
</p>
</header>
<pre class="comment">
<!--% item.comment_text %-->
</pre>
<footer>
Listen in <a href="<!--% media_path(item.eps_id, 'hpr', 'ogg', baseurl, media_baseurl) %-->">ogg</a>, <a href="<!--% media_path(item.eps_id, 'hpr', 'spx', baseurl, media_baseurl) %-->">spx</a>, or <a href="<!--% media_path(item.eps_id, 'hpr', 'mp3', baseurl, media_baseurl) %-->">mp3</a> format.</p></footer>
</article>
<hr />
<!--% END %-->

View File

@@ -1,13 +1,30 @@
<!--% PROCESS 'shared-episode-summary.tpl.html' %-->
<!--% PROCESS 'shared-avatar.tpl.html' %-->
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% PROCESS "queries-correspondent-${constants.database}.tpl.html" %-->
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% query_show_count = DBI.prepare('
<!--% query_hpr_show_count = DBI.prepare('
SELECT id
FROM eps
WHERE eps.hostid = ? ')
WHERE eps.hostid = ?
')
%-->
<!--% query_shows = DBI.prepare('
<!--% results_hpr_shows = DBI.prepare(query_hpr_shows)
%-->
<!--% hpr_shows_to_count = query_hpr_show_count.execute(id); %-->
<!--% hpr_shows = results_hpr_shows.execute(id); %-->
<!--% hpr_show_count = 0 %-->
<!--% FOREACH show IN hpr_shows_to_count %-->
<!--% hpr_show_count = hpr_show_count +1; %-->
<!--% END %-->
<!--% query_twat_show_count = DBI.prepare('
SELECT id
FROM twat_eps AS eps
WHERE eps.hostid = ?
')
%-->
<!--% query_twat_shows = DBI.prepare('
SELECT
eps.id,
CASE eps.explicit WHEN 1 THEN \'Explicit\' ELSE \'Clean\' END AS explicit ,
@@ -18,18 +35,20 @@
hosts.hostid,
hosts.host, hosts.email,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
FROM twat_eps AS eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE hosts.hostid = ? AND eps.date < date(\'now\', \'+1 days\')
ORDER BY date DESC ')
WHERE hosts.hostid = ?
ORDER BY eps.id DESC
')
%-->
<!--% shows_to_count = query_show_count.execute(id); %-->
<!--% shows = query_shows.execute(id); %-->
<!--% show_count = 0 %-->
<!--% FOREACH show IN shows_to_count %-->
<!--% show_count = show_count +1; %-->
<!--% twat_shows_to_count = query_twat_show_count.execute(id); %-->
<!--% twat_shows = query_twat_shows.execute(id); %-->
<!--% twat_show_count = 0 %-->
<!--% FOREACH show IN twat_shows_to_count %-->
<!--% twat_show_count = twat_show_count +1; %-->
<!--% END %-->
<!--% hosts = DBI.tie('hosts', 'hostid') %-->
<article>
@@ -40,11 +59,15 @@
height="80" alt="Host Image" /><br>
<label>Host ID</label>: <!--% this_host.hostid %--><br><br>
<label>email:</label> <u><!--% this_host.email %--></u><br>
<label>episodes:</label> <strong><!--% show_count %--></strong>
<label>episodes:</label> <strong><!--% hpr_show_count + twat_show_count %--></strong>
</p>
<!--% FOREACH show IN shows; %-->
<!--% FOREACH hpr_show IN hpr_shows; %-->
<!--% show_summary(show, 'hide_host') %-->
<!--% show_summary(hpr_show, 'hide_host') %-->
<!--% END %-->
<!--% FOREACH twat_show IN twat_shows; %-->
<!--% twat_show_summary(twat_show, 'hide_host') %-->
<!--% END %-->
</article>
<p><a href="contribute.html">Become a Correspondent</a></p>

View File

@@ -4,7 +4,7 @@
<p>For more information on how to become a Correspondent see our <a href="<!--% absolute_path(baseurl) %-->contribute.html">contribute</a></center> page. To add a logo here, either email one to admin at hpr or setup your email on <a href="https://en.gravatar.com/">Gravatar</a>. To protect your browsing privacy we gather the images every hour and serve them directly from HPR.<p />
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% PROCESS 'shared-avatar.tpl.html' %-->
<table>
<table class="hosts">
<th >Avatar</th>
<th >Name &amp; Host ID</th>
<th >license</th>
@@ -16,7 +16,7 @@
inner join (select hostid, max(date) as date from eps group by hostid) as e
on h.hostid = e.hostid '
) %-->
<tr height="80" bgcolor="#CCCCCC">
<tr height="80">
<td><img src="<!--% absolute_path(baseurl) %-->images/<!--% get_avatar(host.hostid) %-->" height="80" width="80" alt="avatar" /></td>
<td><strong><!--% host.host %--></strong><br>

View File

@@ -1,60 +1,103 @@
<!--% PROCESS 'shared-episode-summary.tpl.html' %-->
<!--% PROCESS 'shared-avatar.tpl.html' %-->
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% PROCESS 'shared-listen-now.tpl.html' %-->
<!--% PROCESS 'shared-show-transcript.tpl.html' %-->
<!--% PROCESS "queries-episode-${constants.database}.tpl.html" %-->
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% query_episodes = DBI.prepare('
WITH episode_maxmin AS (
SELECT MAX(id) AS \'latest\', MIN(id) AS \'earliest\', ? AS \'id\'
FROM eps
WHERE eps.date < date (\'now\', \'+1 days\')
),
episode_date AS (
SELECT eps.date
FROM eps
WHERE eps.id = ?
),
episode_previous AS (
SELECT MAX(id) AS \'previous\', ? AS \'id\'
FROM eps
INNER JOIN episode_date
ON eps.date < episode_date.date
WHERE eps.id > 1
),
episode_next AS (
SELECT MIN(id) AS \'next\', ? AS \'id\'
FROM eps
INNER JOIN episode_date
ON eps.date > episode_date.date
WHERE eps.date < date (\'now\')
)
SELECT eps.id, eps.date, eps.title, eps.duration,
eps.summary, eps.notes, eps.explicit, eps.license,
eps.tags, eps.version, eps.downloads, eps.valid,
episode_maxmin.latest, episode_maxmin.earliest,
episode_previous.previous, episode_next.next,
hosts.hostid, hosts.host,
miniseries.name AS \'series\', miniseries.id AS \'seriesid\'
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
INNER JOIN episode_maxmin ON eps.id = episode_maxmin.id
INNER JOIN episode_previous ON eps.id = episode_previous.id
INNER JOIN episode_next ON eps.id = episode_next.id
WHERE eps.id = ?
')
<!--% query_episodes = DBI.prepare(query_episode_maxmin)
%-->
<!--% episode_result = query_episodes.execute(id, id, id, id, id) %-->
<!--% FOREACH episode IN episode_result %-->
<!--% episode_navigation = step_navigation(baseurl,episode) %-->
<article>
<header>
<h1>hpr<!--% episode.id %--> :: <!--% episode.title %--></h1>
<h3><!--% episode.summary %--></h3>
<p class="meta"><!--% step_navigation(baseurl,episode) %-->
<p class="meta"><!--% episode_navigation %-->
</p>
<p><!--% IF get_avatar(episode.hostid) != 'hpr_logo.png' %-->
<img src="<!--% absolute_path(baseurl) %-->images/<!--% get_avatar(episode.hostid) %-->" height="80" width="80" alt="" /></a><br><!--% END %-->
Hosted by <a href="<!--% absolute_path(baseurl) %-->correspondents/<!--% zero_pad_left(episode.hostid) %-->.html"><!--% episode.host %--></a>. <!--% show_meta(episode) %--></p>
Hosted by <a href="<!--% absolute_path(baseurl) %-->correspondents/<!--% zero_pad_left(episode.hostid) %-->.html"><!--% episode.host %--></a> on <span><!--% episode.date %--></span> is flagged as <span><!--% display_explicit(episode.explicit) %--></span> and is released under a <span><!--% episode.license %--> license</span>. <br>
<!--% display_tags(episode.tags) %--> <br>
<!--% display_listen_in(episode.id) %--> |
<!--% display_comments_tally(episode.id, episode.eps_tally) %-->
</p>
<h3><!--% show_series(episode.series, episode.seriesid, "Part of the series") %--></h3>
<p><em><!--% episode.series_description %--></em></p>
</header>
<div><!--% episode.notes %--></div>
</article>
<footer>
<!--% show_transcript(episode, "hpr", baseurl, media_baseurl) %-->
<!--% listen_now(episode, "hpr", baseurl, media_baseurl) %-->
<p>
<!--% episode_navigation %-->
</p>
</footer></article>
<!--% END %-->
<hr />
<h1>Comments</h1>
<p id="comments">
Subscribe to the comments <a href="<!--% absolute_path(baseurl) %-->comments.rss">RSS</a> feed.
</p>
<!--% query_comments = DBI.prepare('
SELECT
id,
comment_timestamp,
comment_author_name,
comment_title,
comment_text
FROM comments
WHERE eps_id = ?
')
%-->
<!--% comment_index = 1 %-->
<!--% comments_result = query_comments.execute(id) %-->
<!--% FOREACH comment IN comments_result %-->
<h5 id="comment_<!--% comment.id %-->">Comment #<!--% comment_index %--> posted on <!--% comment.comment_timestamp %--> by <!--% comment.comment_author_name %--></h5>
<h4><!--% comment.comment_title %--></h4>
<!--% comment.comment_text %-->
<!--% comment_index = comment_index + 1 %-->
<!--% END %-->
<h2>Leave Comment</h2>
<p>
<strong>Note to Verbose Commenters</strong><br />
If you can't fit everything you want to say in the comment below then you really should <a href="<!--% absolute_path(baseurl) %-->contribute.html">record</a> a response show instead.
</p>
<p>
<strong>Note to Spammers</strong><br />
All comments are moderated. All links are checked by humans. We strip out all html. Feel free to <a href="<!--% absolute_path(baseurl) %-->contribute.html">record</a> a show about yourself, or your industry, or any other topic we may find interesting. <em>We also check shows for spam :)</em>.
</p>
<form method="POST" action="comment_confirm.php">
<fieldset>
<legend>Provide feedback</legend>
<table>
<tr>
<td>Your Name/Handle:</td>
<td><input required type="text" name="comment_author_name" size="40" maxlength="40" placeholder="Enter your name" ></td>
</tr>
<tr>
<td>Title:</td>
<td><input required type="text" name="comment_title" size="50" maxlength="100" placeholder="What is your comment about ?"></td>
</tr>
<tr>
<td>Comment:</td>
<td><textarea required name="comment_text" maxlength="2000" rows="10" cols="50" placeholder="Place the comment here."></textarea></td>
</tr>
<tr>
<td>Anti Spam Question:</td>
<td>
What does the <strong>P</strong> in <em>HPR</em> stand for ? <br />
<input required type="text" name="anti_spam_question" size="50" maxlength="100" placeholder="Type out what the P in HPR stands for."></td>
</tr>
<input type="hidden" name="spammer" value="No">
<input type="hidden" name="hostid" value="406">
<input type="hidden" name="justification" value="No justification is asked for or required.">
<input type="hidden" name="eps_id" value="3665 ">
</table>
<input type="submit" value="Next">
</fieldset>
</form>

View File

@@ -1,4 +1,5 @@
<!--% PROCESS 'shared-episode-summary.tpl.html' %-->
<!--% PROCESS "queries-episodes-${constants.database}.tpl.html" %-->
<article>
<header>
<h1>Complete Archive of Shows.</h1>
@@ -7,7 +8,16 @@
</p>
</header>
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% FOREACH episodes IN DBI.query('
<!--% FOREACH episodes IN DBI.query(query_episodes)
%-->
<!--% show_summary(episodes) %-->
<!--% END %-->
<h2 id="twat_episodes">Today With a Techie Archived Shows</h2>
<p>
<!-- Creative Commons License -->
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/"><img alt="Creative Commons License" border="0" src="http://creativecommons.org/images/public/somerights20.png" width="88" height="31" /></a><br>The following work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/2.5/">Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License</a>.</p>
<p>T.W.A.T. Radio was brought to you by <a href="https://en.wikipedia.org/wiki/Infonomicon">The Infonomicon Computer Club</a></p>
<!--% FOREACH twat_episode IN DBI.query('
SELECT
eps.id,
eps.explicit,
@@ -16,13 +26,14 @@
hosts.hostid,
hosts.host, hosts.email, hosts.local_image,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
FROM twat_eps as eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < date(\'now\', \'+1 days\')
ORDER BY date DESC
ORDER BY eps.id DESC
')
%-->
<!--% show_summary(episodes) %-->
<!--% twat_show_summary(twat_episode) %-->
<!--% END %-->
</article>

View File

@@ -0,0 +1,2 @@
<!--% PROCESS 'shared-utils.tpl.html' %-->

View File

@@ -1,14 +1,31 @@
<!--% PROCESS 'shared-avatar.tpl.html' %-->
<!--% PROCESS 'host-thumbnail.tpl.html' %-->
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% PROCESS 'shared-listen-now.tpl.html' %-->
<!--% PROCESS 'shared-show-transcript.tpl.html' %-->
<!--% PROCESS 'shared-call_for_shows.tpl.html' %-->
<!--% INCLUDE 'content-index-announcement.tpl.html' %-->
<!--% PROCESS "queries-index-${constants.database}.tpl.html" %-->
<hr>
<article>
<header>
<h3>Welcome to HPR the Community Podcast</h3>
</header>
<!--% days_till_next_episode = 0 %-->
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% FOREACH next_available_episode_result IN DBI.query(query_next_available_episode)
%-->
<!--% USE date %-->
<!--% calc = date.calc %-->
<!--% days_till_next_episode = calc.Delta_Days(date.format(date.now, '%Y'),date.format(date.now, '%m'),date.format(date.now, '%d'),next_available_episode_result.last_year,next_available_episode_result.last_month,next_available_episode_result.last_day + 1) %-->
<!--% END %-->
<!--% USE date %-->
<!--% delta = date.calc.N_Delta_YMD(2005,9,19, date.format(date.now, '%Y'),date.format(date.now, '%m'),date.format(date.now, '%d')) %-->
<p>We started producing shows as <a href="https://www.hackerpublicradio.org/twat.php"><em>Today with a Techie</em></a> on 2005-09-19, <!--% delta.0 %--> years, <!--% delta.1 %--> months, <!--% delta.2 %--> days ago. our shows are produced by <a href="<!--% absolute_path(baseurl) %-->correspondents/index.html">listeners</a> like you and can be on any <a href="<!--% absolute_path(baseurl) %-->eps/index.html">topic</a> that <strong>"are of interest to <a href="https://en.wikipedia.org/wiki/hacker_(hobbyist)">hackers</a>"</strong>. if you listen to HPR then please consider contributing one show a year. if you <a href="<!--% absolute_path(baseurl) %-->contribute.html">record</a> your show now it could be <a href="https://www.hackerpublicradio.org/calendar.php">released</a> in <strong>13</strong> days.</p>
<h4>Meet the team</h4>
<p>We started producing shows as <a href="<!--% absolute_path(baseurl) %-->eps/index.html#twat_episodes"><em>Today with a Techie</em></a> on 2005-09-19, <!--% delta.0 %--> years, <!--% delta.1 %--> months, <!--% delta.2 %--> days ago. our shows are produced by <a href="<!--% absolute_path(baseurl) %-->correspondents/index.html">listeners</a> like you and can be on any <a href="<!--% absolute_path(baseurl) %-->eps/index.html">topic</a> that <strong>"are of interest to <a href="https://en.wikipedia.org/wiki/hacker_(hobbyist)">hackers</a>"</strong>. if you listen to HPR then please consider contributing one show a year. if you <a href="<!--% absolute_path(baseurl) %-->contribute.html">record</a> your show now it could be <a href="https://www.hackerpublicradio.org/calendar.php">released</a> in <strong><!--% days_till_next_episode %--></strong> days.</p>
</article>
<!--% display_call_for_shows() %-->
<article>
<h4>Meet the team</h4>
<p>
<audio controls preload="none">";
<source src="<!--% absolute_path(baseurl) %-->media/promos/all-hpr-hosts.ogg" type="audio/ogg" >
@@ -19,25 +36,8 @@
<hr>
<!--% PROCESS 'shared-episode-summary.tpl.html' %-->
<h1>Latest Shows</h1>
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% FOREACH latest_episodes IN DBI.query('
SELECT
eps.id,
eps.explicit,
eps.date, eps.license, eps.duration,
eps.title, eps.summary, eps.tags,
eps.notes,
hosts.local_image,
hosts.hostid,
hosts.host, hosts.email,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < date(\'now\', \'+1 days\')
ORDER BY date DESC
LIMIT 10
')
<!--% host_cnt = 0 %-->
<!--% FOREACH latest_episodes IN DBI.query(query_latest_episodes)
%-->
<hr>
<article>
@@ -45,50 +45,30 @@
<h1><a href="<!--% absolute_path(baseurl) %-->eps/hpr<!--% zero_pad_left(latest_episodes.id) %-->/index.html">hpr<!--% latest_episodes.id %--> :: <!--% latest_episodes.title %--></a></h1>
<h3><!--% latest_episodes.summary%--></h3>
<p class="meta"$><!--% IF get_avatar(latest_episodes.hostid) != 'hpr_logo.png' %-->
<img src="<!--% absolute_path(baseurl) %-->images/<!--% get_avatar(latest_episodes.hostid) %-->" height="80" width="80" alt="" /></a><!--% END %-->
<a href="<!--% absolute_path(baseurl) %-->correspondents/<!--% zero_pad_left(latest_episodes.hostid) %-->.html">
<!--% host_thumb(get_avatar(latest_episodes.hostid), latest_episodes.host, host_cnt) %-->
</a><!--% END %-->
<br>Hosted by <a href="<!--% absolute_path(baseurl) %-->correspondents/<!--% zero_pad_left(latest_episodes.hostid) %-->.html"><!--% latest_episodes.host %--></a> on <!--% latest_episodes.date %--> is flagged as <!--% display_explicit(latest_episodes.explicit) %--> and released under a <!--% latest_episodes.license %--> license. <br>
<strong>Tags:</strong> <!--% latest_episodes.tags %--><em></em>.<br>
<small>listen in <a href="local/hpr<!--% latest_episodes.id %-->.ogg">ogg</a>, <a href="local/hpr<!--% latest_episodes.id %-->.spx">spx</a>, or <a href="local/hpr<!--% latest_episodes.id %-->.mp3">mp3</a> format. <!--% show_series(latest_episodes.series, latest_episodes.seriesid) %-->
<a href="<!--% absolute_path(baseurl) %-->eps/hpr<!--% zero_pad_left(latest_episodes.id) %-->/index.html#comments">View comments.</a></small>
<!--% display_tags(latest_episodes.tags) %--><br>
<small><!--% display_listen_in(latest_episodes.id) %--> <!--% show_series(latest_episodes.series, latest_episodes.seriesid) %--> |
<!--% display_comments_tally(latest_episodes.id, latest_episodes.eps_tally) %--></small>
</p>
</header>
<!--% latest_episodes.notes %-->
<footer>
<h2>listen now</h2>
<p>Duration: <!--% latest_episodes.duration %--></p>
<audio controls preload="none">
<source src="local/hpr<!--% latest_episodes.id %-->.ogg" type="audio/ogg" >
<source src="local/hpr<!--% latest_episodes.id %-->.mp3" type="audio/mpeg" >
</audio>
<ul>
<li>ogg: <a href="local/hpr<!--% latest_episodes.id %-->.ogg">/local/hpr<!--% latest_episodes.id %-->.ogg</a></li>
<li>spx: <a href="local/hpr<!--% latest_episodes.id %-->.spx">/local/hpr<!--% latest_episodes.id %-->.spx</a></li>
<li>mp3: <a href="local/hpr<!--% latest_episodes.id %-->.mp3">/local/hpr<!--% latest_episodes.id %-->.mp3</a></li>
</ul>
<!--% show_transcript(latest_episodes, "hpr", baseurl, media_baseurl) %-->
<!--% listen_now(latest_episodes, "hpr", baseurl, media_baseurl) %-->
</footer>
</article>
<!--% host_cnt = host_cnt + 1 %-->
<!--% END %-->
<article>
<header>
<hr>
<h1>Previous five weeks</h1>
</header>
<!--% FOREACH last_5_weeks_episodes IN DBI.query('
SELECT
eps.id,
CASE eps.explicit WHEN 1 THEN \'Explicit\' ELSE \'Clean\' END AS explicit ,
eps.date, eps.license, eps.title, eps.summary,
eps.duration, eps.notes, eps.tags,
hosts.hostid,
hosts.host, hosts.email, hosts.local_image,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < date(\'now\', \'+1 days\')
ORDER BY date DESC
LIMIT 30 OFFSET 10
')
<!--% FOREACH last_5_weeks_episodes IN DBI.query(query_last_5_weeks_episodes)
%-->
<!--% show_summary(last_5_weeks_episodes) %-->
<!--% END %-->

View File

@@ -0,0 +1,189 @@
<!--% PROCESS 'shared-utils.tpl.html' %-->
<p>In this article we will show you how to connect to the HPR Community Room on Mumble.</p>
<p>You can think of Mumble like visiting a hotel that has different meeting rooms. Some are locked to you, some only allow you access if you are registered, some you can join but only listen to. In most, like the HPR room, you can hear the other people in the room talking. If you talk they can also hear you. There is a chat section where text can be shared as well.</p>
<p>When using Mumble <strong><em>you should always use a microphone and headset</em></strong> positioned close to your mouth but slightly off to the side.</p>
<h2>Install the software</h2>
<p>The <a href="https://www.mumble.info/downloads/">Mumble website offers download and install instructions</a> for different operating systems.
</p>
<p>Once you have installed the client then connect to the <a href="mumble://chatter.skyehaven.net:64738/Hacker%20Public%20Radio?version=1.2.0">HPR Room on Mumble</a>.
<p>There is a first run wizard that will step you through the process of configuring Mumble the first time. This will open up a series of configuration options.</p>
<p>Press <strong>Next</strong> on the introduction.</p>
<p><img alt="intro screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/01-intro.png" ></p>
<p>The device selection page will allow you to select which audio to use. As this will be different for everyone we can't offer you much help here other than to say that the defaults are usually fine.</p>
<p>When you are done press <strong>Next</strong>.</p>
<p><img alt="device selection screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/02-device-selection.png" ></p>
<p>The device tuning page will allow you to fine tune the latency. Normally the defaults are usually fine.</p>
<p>When you are done press <strong>Next</strong>.</p>
<p><img alt="device tuning screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/03-device-tuning.png" ></p>
<p>The Volume Tuning page will allow you to set your audio levels. Normally the defaults are usually fine.</p>
<p>Then press <strong>Next</strong>.</p>
<p><img alt="volume tuning screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/04-volume.png" ></p>
<p>It is <strong>very important</strong> that you set <strong>Push to Talk (PTT)</strong>, as you will disturb the other people in the room if you select the other methods. It may seem to be working fine to you, but it <em>will</em> result in issues for the others.
</p>
<ul>
<li>Click "Push to Talk:"</li>
<li>Click in the area next to it and press the key you intend to use as the Push To Talk (PTT) Key</li>
</ul>
<p>Try and pick a key that you don't normally use or need. You may have to disable that key mapping in the operating system you are using.</p>
<p>Then press <strong>Next</strong>.</p>
<p><img alt="ptt screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/05-ptt.png" ></p>
<p>The Quality Settings page will allow you to adjust the bandwidth. Normally the defaults are usually fine.</p>
<p>It is <strong>very important</strong> that you <strong>Disable Text-To-Speech</strong>, as all notifications will be read back and will disturb the other people in the room. It may seem to be working fine to you, but it <em>will</em> result in issues for the others.</p>
<ul>
<li>Click "Disable Text-To-Speech and use sounds instead"</li>
</ul>
<p>Then press <strong>Next</strong>.</p>
<p><img alt="no tts screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/06-notts.png" ></p>
<p>The positional audio page will allow you to fine tune the latency. Normally the defaults are usually fine.</p>
<p>Just press <strong>Next</strong>.</p>
<p><img alt="positional audio screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/07-positional-audio.png" ></p>
<p>That's it the initial configuration is done.</p>
<p>Then press <strong>Finish</strong>.</p>
<p><img alt="stats screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/08-stats.png" ></p>
<p>You are expected to have a digital certificate when connecting to Mumble servers.</p>
<p>This screen will allow you to Automatically create one.</p>
<p>Just press <strong>Next</strong>.</p>
<p><img alt="cert screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/09-cert.png" ></p>
<p>That completes the first setup of Mumble.</p>
<p>Then press <strong>Finish</strong>.</p>
<p><img alt="finished screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/10-finished.png" ></p>
<hr>
<p>Now that you have the Mumble client set up we can now start the process of connecting to the <a href="mumble://chatter.skyehaven.net:64738/Hacker%20Public%20Radio?version=1.2.0">HPR Room on Mumble</a>.</p>
<p>If you opened Mumble by clicking the link above, then you may not see the following options, but we'll cover them here if at any time you need to add the HPR server again</p>
<p>Just open mumble and press <strong>Server - Connect</strong></p>
<p>Then press <strong>Add New...</strong>.</p>
<p><img alt="add new connection screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/20-add-new.png" ></p>
<p>You will need to enter the information for the HPR server:</p>
<ul>
<li>Address: <strong>chatter.skyehaven.net</strong></li>
<li>Port: 64738</li>
<li>Username: <strong><em>Your Username</em></strong></li>
<li>Label: chatter.skyehaven.net</li>
</ul>
<p>Think about your username a bit as if you register it on the server you will not be able to change it again.</p>
<p>Then press <strong>Next</strong>.</p>
<p><img alt="add new server screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/21-add-server.png" ></p>
<p>If you clicked the link to the <a href="mumble://chatter.skyehaven.net:64738/Hacker%20Public%20Radio?version=1.2.0">HPR Room on Mumble</a>, then you may be brought to the option to enter a username. Think about this a bit as if you register it on the server you will not be able to change it again.</p>
<p>Then press <strong>Next</strong>.</p>
<p><img alt="username screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/11-username.png" ></p>
<p>You will need to confirm the servers Certificate matches this:</p>
<p>
<pre>Digest (SHA-1): 09:22:05:88:D6:60:17:FD:39:8F:55:B0:F5:A0:45:DA:96:32:9C:23</pre>
</p>
<p>If it matches then press <strong>Yes</strong>.</p>
<p><img alt="accept cert screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/12-accept-cert.png" ></p>
<p>All going well you will be connected to the server. By default you will end up in the <strong>Root</strong> - think the lobby of an hotel !</p>
<p>You will see a lot of rooms with names of other podcasts that use the server.</p>
<p>Before connecting to any room it's good etiquette to make sure your audio is working correctly.</p>
<p>The room <strong>Audio Test</strong> will allow you to speak and the <strong>OpieTheRepeatherBot</strong> will record your speech and after 10 seconds will play it back for you.</p>
<p><em>Click and hold</em> on your username (<em>ken1</em> in this example) and <em>drag</em> yourself into the <strong>Audio Test</strong> room.</p>
<p><img alt="audio test screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/13-audio-test.png" ></p>
<p>You now know how to switch from room to room.</p>
<p>Try to say something. Remember to press the <strong>Push to talk (PTT)</strong>. Everyone forgets to do this but it will become second nature after a while.</p>
<p>A good test is to count to ten slowly.</p>
<p>When you are talking the server should change your icon from a green person to a <em>blue</em> one with <em>sound circles</em> around the head.</p>
<p><img alt="audio ping screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/14-audio-ping.png" ></p>
<p>The <strong>OpieTheRepeatherBot</strong> will create another client with the prefix <strong>Mimic-</strong> followed by your username.</p>
<p>In this example it is <em>Mimic-ken1</em>.</p>
<p>You should hear your audio back.</p>
<p><img alt="audio pong screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/15-audio-pong.png" ></p>
<p>If your audio is poor - as is often the case - then this gives you the opportunity to fix it before interrupting other people.</p>
<p>How you fix it will depend on the operating system that you are using and the exact nature of the problem.</p>
<p>A common problem is that the operating system uses the built in speaker and microphone from the laptop instead of your headset. A tip would be to press the <strong>Push to talk (PTT)</strong> button and tap the microphone of your head set lightly. If you don't hear the tapping then Mumble is probably getting the wrong microphone as input.</p>
<p>In the example below I clicked the Microphone icon in my taskbar and a application (<em>pavucontrol</em>) opened allowing me to set the correct microphone.</p>
<p><img alt="hpr room screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/22-pavucontrol-recording.png" ></p>
<p>While I was there I also checked to make sure that Mumble was playing audio to my headset.</p>
<p><img alt="hpr room screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/23-pavucontrol-playback.png" ></p>
<p>Satisfied that the audio is good, you can <em>click and drag</em> your icon to the <strong>HPR</strong> room.</p>
<p><img alt="hpr room screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/16-hpr-room.png" ></p>
<p>Some rooms require you to be registered to enter a room, to speak, to record, or to chat in the room.</p>
<p>To register first <em>Right Click</em> on your icon and a menu will open.</p>
<p>Press <strong>Register....</strong></p>
<p><img alt="register screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/17-register.png" ></p>
<p>Then press <strong>Yes</strong></p>
<p><img alt="register confirm screenshot" src="<!--% absolute_path(baseurl) %-->images/mumble-howto/18-register-confirm.png" ></p>
<p>That's it - you are now all set to use mumble.</p>

View File

@@ -1,28 +1,16 @@
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% PROCESS "queries-series-${constants.database}.tpl.html" %-->
<article>
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<h1 class="title">In-Depth Series</h1>
<!--% FOREACH series IN DBI.query(
'SELECT miniseries.id, miniseries.name, miniseries.description,
miniseries.private, miniseries.image, miniseries.valid,
ep.number_of_episodes, ep.latest_show, ep.earliest_show
FROM miniseries
INNER JOIN
(SELECT series,
COUNT(eps.id) AS number_of_episodes,
MAX(eps.date) AS latest_show,
MIN(eps.date) AS earliest_show
FROM eps
GROUP BY series) AS ep ON ep.series = miniseries.id
ORDER BY name'
) %-->
<!--% FOREACH series IN DBI.query(query_episodes) %-->
<h2><a href="<!--% absolute_path(baseurl) %-->series/<!--% zero_pad_left(series.id) %-->.html"><!--% series.name %--></a></h2>
<ul>
<li>Number of episodes: <!--% series.number_of_episodes %--></li>
<li>Open/closed: <!--% display_choice(series.private, 'closed', 'open') %--></li>
<li>Date of earliest show: <!--% series.earliest_show %--></li>
<li>Date of latest show: <!--% series.latest_show %--></li>
<li>Series RSS feeds: <a href="hpr_ogg_rss.php?series=38">ogg</a>, <a href="hpr_spx_rss.php?series=38">spx</a>, <a href="hpr_mp3_rss.php?series=38">mp3</a></li>
<li>Series RSS feeds: <a href="https://www.hackerpublicradio.org/hpr_ogg_rss.php?series=<!--% series.id %-->">ogg</a>, <a href="https://www.hackerpublicradio.org/hpr_spx_rss.php?series=<!--% series.id %-->">spx</a>, <a href="https://www.hackerpublicradio.org/hpr_mp3_rss.php?series=<!--% series.id %-->">mp3</a></li>
</ul>
<em><!--% series.description %--></em>
<!--% END %-->

View File

@@ -1,20 +1,8 @@
<!--% PROCESS 'shared-episode-summary.tpl.html' %-->
<!--% PROCESS 'shared-avatar.tpl.html' %-->
<!--% PROCESS "queries-series_episodes-${constants.database}.tpl.html" %-->
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% query_series = DBI.prepare('SELECT miniseries.id, miniseries.name,
miniseries.description,
miniseries.private, miniseries.image, miniseries.valid,
ep.number_of_episodes, ep.latest_show, ep.earliest_show
FROM miniseries
INNER JOIN
(SELECT series,
COUNT(eps.id) AS number_of_episodes,
MAX(eps.date) AS latest_show,
MIN(eps.date) AS earliest_show
FROM eps
GROUP BY series) AS ep ON ep.series = miniseries.id
WHERE miniseries.id = ?
ORDER BY name')
<!--% query_series = DBI.prepare(query_series_sql)
%-->
<!--% series_result = query_series.execute(id) %-->
<article>
@@ -25,21 +13,11 @@
<li>Open/closed: open</li>
<li>Date of earliest show: <!--% series.earliest_show %--></li>
<li>Date of latest show: <!--% series.latest_show %--></li>
<li>Series RSS feeds: <a href="hpr_ogg_rss.php?series=79&full=1&gomax=1">ogg</a>, <a href="hpr_spx_rss.php?series=79&full=1&gomax=1">spx</a>, <a href="hpr_mp3_rss.php?series=79&full=1&gomax=1">mp3</a></li>
<li>Series RSS feeds: <a href="https://www.hackerpublicradio.org/hpr_ogg_rss.php?series=<!--% series.id %-->&full=1&gomax=1">ogg</a>, <a href="https://www.hackerpublicradio.org/hpr_spx_rss.php?series=<!--% series.id %-->&full=1&gomax=1">spx</a>, <a href="https://www.hackerpublicradio.org/hpr_mp3_rss.php?series=<!--% series.id %-->&full=1&gomax=1">mp3</a></li>
</ul>
<div><em><!--% series.description %--></em></div>
<!--% END %-->
<!--% query_shows = DBI.prepare('SELECT
id, date, title,
duration, summary, notes,
explicit, eps.license, tags,
hosts.host, hosts.hostid
FROM eps
INNER JOIN hosts
ON eps.hostid = hosts.hostid
WHERE series = ?
ORDER BY date DESC
')
<!--% query_shows = DBI.prepare(query_shows_sql)
%-->
<!--% show_results = query_shows.execute(id) %-->
<!--% FOREACH show IN show_results %-->

View File

@@ -1,3 +1,51 @@
<h1>RSS Syndication</h1>
<p><small><em><a href="http://hackerpublicradio.org/advanced_rss_settings.php">Advanced Settings</a>.</em></small></p>
<article>
<header>
<h2>Subscribe to our Feeds</h2>
</header>
<p>
Great that you want to listen. Have a look below at the feeds that best suite your listening habits.
</p>
</article>
<article>
<header>
<h2><img src="<!--% absolute_path(baseurl) %-->images/feed.png" alt="rss logo"> The Community News Summary</h2>
<h3>One show a month</h3>
</header>
<p>
If you get overwhelmend by the amount of shows we produce, then this is a good place to start.
</p>
<p>
Every month, the HPR Janitors put down their mops had have a chat about all the shows, and what else has been going on in the HPR community. This is a regular show scheduled for the first Monday of the month.
</p>
<ul>
<li><a href="https://hackerpublicradio.org/hpr_ogg_rss.php?series=47">ogg</a> Larger file size higher quality feed.</li>
<li><a href="https://hackerpublicradio.org/hpr_spx_rss.php?series=47">mp3</a> Larger file size regular quality feed in a common format.</li>
<li><a href="https://hackerpublicradio.org/hpr_mp3_rss.php?series=47">spx</a> Small file size lower quality feed. <br/>Ideal for dial-up/mobile connections.</li>
</ul>
<p>
We also maintain an <a href="https://archive.org/details/hackerpublicradio?and[]=subject%3A%22Community+News%22">Archive.org</a> page where you can get the shows in even more formats.
</p>
</article>
<article>
<header>
<h2><img src="<!--% absolute_path(baseurl) %-->images/feed.png" alt="rss logo"> Two week Audio feed</h2>
<h3>5 shows a week</h3>
</header>
<p>
Use these feeds to keep up to date with the latest HPR Episodes.
</p>
<ul>
<li><a href="hpr_ogg_rss.php">ogg</a> Larger file size higher quality feed.</li>
<li><a href="hpr_rss.php">mp3</a> Larger file size regular quality feed in a common format.</li>
<li><a href="hpr_spx_rss.php">spx</a> Small file size lower quality feed. <br/>Ideal for dial-up/mobile connections.</li>
</ul>
<p>
We also maintain an <a href="https://archive.org/details/hackerpublicradio">Archive.org</a> page where you can get the shows in even more formats. For more recent shows we are now including the original upload as delivered.
</p>
</article>
<article>
<header>
<h2><img src="<!--% absolute_path(baseurl) %-->images/feed.png" alt="rss logo"> Entire Archive Audio feed</h2>
@@ -19,7 +67,7 @@
Use this feed to get the shows as they are posted. The shows will be posted out of order as they come in and may be replaced/reposted if errors are found. This is intended as a means to provide find issues with metadata or the audio quality of new shows before they hit the main feed.
</p>
<ul>
<li><a href="rss-future.php">Shows as they are posted.</a> OGG Only</li>
<li><a href="https://www.hackerpublicradio.org/rss-future.php">Shows as they are posted.</a> OGG Only</li>
</ul>
</article>
<article>
@@ -27,6 +75,27 @@
<h2><img src="<!--% absolute_path(baseurl) %-->images/feed.png" alt="rss logo"> Comment feed</h2>
</header>
<ul>
<li><a href="http://www.hackerpublicradio.org/comments_rss.php">Listener contributed comments to the episodes</a></li>
<li><a href="<!--% absolute_path(baseurl) %-->comments.rss">Listener contributed comments to the episodes</a></li>
</ul>
</article>
<article>
<header>
<h2>Site Replication Sources</h2>
</header>
<ul>
<li><a href="<!--% absolute_path(baseurl) %-->hpr.sql">Daily Database Dump in SQL Format</a></li>
<ul>
</article>
<article>
<header>
<h2>External Sources</h2>
</header>
<ul>
<li><a href="https://archive.org/details/hackerpublicradio">Archive.org</a></li>
<li><a href="https://itunes.apple.com/us/podcast/hacker-public-radio/id281699640?mt=2">iTunes</a></li>
<li><a href="https://podcasts.google.com/feed/aHR0cDovL2hhY2tlcnB1YmxpY3JhZGlvLm9yZy9ocHJfcnNzLnBocA">Google Podcasts</a></li>
<li><a href="https://player.fm/series/hacker-public-radio">PlayerFM</a></li>
<li><a href="https://open.spotify.com/show/7e2hYcnHj9vKgUzsIOf4r3">Spotify</a></li>
<li><a href="https://www.mixcloud.com/hackerpublicradio/">MixCloud</a></li>
<ul>
</article>

View File

@@ -0,0 +1,72 @@
<!--% PROCESS 'shared-episode-summary.tpl.html' %-->
<!--% PROCESS 'shared-avatar.tpl.html' %-->
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% PROCESS 'shared-listen-now.tpl.html' %-->
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% query_episodes = DBI.prepare('
WITH episode_maxmin AS (
SELECT MAX(id) AS \'latest\', MIN(id) AS \'earliest\', ? AS \'id\'
FROM twat_eps AS eps
),
episode_date AS (
SELECT eps.date
FROM twat_eps AS eps
WHERE eps.id = ?
),
episode_previous AS (
SELECT MAX(id) AS \'previous\', ? AS \'id\'
FROM twat_eps AS eps
INNER JOIN episode_date
ON eps.date < episode_date.date
WHERE eps.id > 1
),
episode_next AS (
SELECT MIN(id) AS \'next\', ? AS \'id\'
FROM twat_eps AS eps
INNER JOIN episode_date
ON eps.date > episode_date.date
)
SELECT eps.id, eps.date, eps.title, eps.duration,
eps.summary, eps.notes, eps.explicit, eps.license,
eps.tags, eps.version, eps.downloads, eps.valid,
episode_maxmin.latest, episode_maxmin.earliest,
episode_previous.previous, episode_next.next,
hosts.hostid, hosts.host,
miniseries.name AS \'series\', miniseries.id AS \'seriesid\',
miniseries.description AS \'series_description\'
FROM twat_eps AS eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
INNER JOIN episode_maxmin ON eps.id = episode_maxmin.id
INNER JOIN episode_previous ON eps.id = episode_previous.id
INNER JOIN episode_next ON eps.id = episode_next.id
WHERE eps.id = ?
')
%-->
<!--% episode_result = query_episodes.execute(id, id, id, id, id) %-->
<!--% FOREACH episode IN episode_result %-->
<!--% episode_navigation = step_navigation(baseurl,episode,"twat") %-->
<article>
<header>
<h1><!--% episode.id %--> :: <!--% episode.title %--></h1>
<h3><!--% episode.summary %--></h3>
<p class="meta"><!--% episode_navigation %-->
</p>
<p><!--% IF get_avatar(episode.hostid) != 'hpr_logo.png' %-->
<img src="<!--% absolute_path(baseurl) %-->images/<!--% get_avatar(episode.hostid) %-->" height="80" width="80" alt="" /></a><br><!--% END %-->
Hosted by <a href="<!--% absolute_path(baseurl) %-->correspondents/<!--% zero_pad_left(episode.hostid) %-->.html"><!--% episode.host %--></a> on <span><!--% episode.date %--></span> is flagged as <span><!--% display_explicit(episode.explicit) %--></span> and is released under a <span><!--% episode.license %--> license</span>. <br>
<!--% display_tags(episode.tags) %--> <br>
<!--% display_listen_in(episode.id, "twat") %-->
</p>
<h3><!--% show_series(episode.series, episode.seriesid, "Part of the series") %--></h3>
<p><em><!--% episode.series_description %--></em></p>
</header>
<div><!--% episode.notes %--></div>
<footer>
<!--% listen_now(episode, "twat", baseurl, media_baseurl) %-->
<p>
<!--% episode_navigation %-->
</p>
</footer></article>
<!--% END %-->

View File

@@ -0,0 +1,3 @@
<!--% MACRO host_thumb(avatar, host_name, host_cnt) BLOCK %-->
<img src="<!--% absolute_path(baseurl) %-->images/<!--% avatar %-->" height="80" width="80" alt="Thumbnail of <!--% host_name | html %-->" <!--% IF host_cnt %-->loading="lazy"<!--% END %--> />
<!--% END %-->

View File

@@ -1,8 +1,6 @@
<!--% PROCESS "queries-ids-episode-${constants.database}.tpl.html" %-->
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% FOREACH episode IN DBI.query(
'select eps.id from eps
where eps.date < date (\'now\', \'+1 days\') '
) %-->
<!--% FOREACH episode IN DBI.query(query_ids_episode) %-->
,<!--% episode.id %-->
<!--% END %-->

View File

@@ -0,0 +1,7 @@
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% FOREACH episode IN DBI.query(
'select eps.id from twat_eps AS eps'
) %-->
,<!--% episode.id %-->
<!--% END %-->

View File

@@ -5,7 +5,7 @@
<li><a href="<!--% absolute_path(baseurl) %-->syndication.html">Get Shows</a></li>
<li><a href="<!--% absolute_path(baseurl) %-->contribute.html">Give Shows</a></li>
<li><a href="<!--% absolute_path(baseurl) %-->help_out.html">Contribute</a></li>
<li><a href="<!--% absolute_path(baseurl) %-->tags.html">Tags</a></li>
<li><a href="http://www.hackerpublicradio.org/tags.php">Tags</a></li>
<li><a href="<!--% absolute_path(baseurl) %-->about.html">About</a></li>
<li><a href="<!--% absolute_path(baseurl) %-->search.html">Search</a></li>
</ul>

View File

@@ -10,6 +10,7 @@
<meta http-equiv="X-Clacks-Overhead" content="GNU Terry Pratchett" />
<meta name="keywords" content="Technology, Tech News, Education, Training" />
<meta name="description" content="Hacker Public Radio is an podcast that releases shows every weekday Monday through Friday. Our shows are produced by the community (you) and can be on any topic that are of interest to hackers and hobbyists." />
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Internal CSS -->
<style type="text/css">
article, aside, dialog, figure, footer, header, hgroup, menu, nav, section {

View File

@@ -0,0 +1,6 @@
<!--% query_call_for_shows = '
SELECT CASE WHEN COUNT(id) < 7 THEN True ELSE False END AS `request_for_shows`
FROM eps
WHERE eps.date > NOW() AND eps.date < DATE_ADD(NOW(), INTERVAL 10 DAY)
'
%-->

View File

@@ -0,0 +1,6 @@
<!--% query_call_for_shows = '
SELECT CASE WHEN COUNT(id) < 7 THEN True ELSE False END AS `request_for_shows`
FROM eps
WHERE eps.date > date(\'now\') AND eps.date < date(\'now\', \'+10 days\')
'
%-->

View File

@@ -0,0 +1,18 @@
<!--% query_hpr_shows = '
SELECT
eps.id,
CASE eps.explicit WHEN 1 THEN \'Explicit\' ELSE \'Clean\' END AS explicit ,
eps.date, eps.license, eps.duration,
eps.title, eps.summary, eps.tags,
eps.notes,
hosts.local_image,
hosts.hostid,
hosts.host, hosts.email,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE hosts.hostid = ? AND eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
ORDER BY eps.id DESC
'
%-->

View File

@@ -0,0 +1,18 @@
<!--% query_hpr_shows = '
SELECT
eps.id,
CASE eps.explicit WHEN 1 THEN \'Explicit\' ELSE \'Clean\' END AS explicit ,
eps.date, eps.license, eps.duration,
eps.title, eps.summary, eps.tags,
eps.notes,
hosts.local_image,
hosts.hostid,
hosts.host, hosts.email,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE hosts.hostid = ? AND eps.date < date(\'now\', \'+1 days\')
ORDER BY eps.id + 0 DESC
'
%-->

View File

@@ -0,0 +1,51 @@
<!--% query_episode_maxmin = '
WITH episode_maxmin AS (
SELECT MAX(id) AS \'latest\', MIN(id) AS \'earliest\', ? AS \'id\'
FROM eps
WHERE eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
),
episode_date AS (
SELECT eps.date
FROM eps
WHERE eps.id = ?
),
episode_previous AS (
SELECT MAX(id) AS \'previous\', ? AS \'id\'
FROM eps
INNER JOIN episode_date
ON eps.date < episode_date.date
WHERE eps.id > 1
),
episode_next AS (
SELECT MIN(id) AS \'next\', ? AS \'id\'
FROM eps
INNER JOIN episode_date
ON eps.date > episode_date.date
WHERE eps.date < NOW()
),
comment_tallies AS (
SELECT
eps_id,
COUNT(eps_id) AS eps_tally
FROM comments
GROUP BY eps_id
)
SELECT eps.id, eps.date, eps.title, eps.duration,
eps.summary, eps.notes, eps.explicit, eps.license,
eps.tags, eps.version, eps.downloads, eps.valid,
episode_maxmin.latest, episode_maxmin.earliest,
episode_previous.previous, episode_next.next,
hosts.hostid, hosts.host,
miniseries.name AS \'series\', miniseries.id AS \'seriesid\',
miniseries.description AS \'series_description\',
COALESCE (comment_tallies.eps_tally, 0) AS eps_tally
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
INNER JOIN episode_maxmin ON eps.id = episode_maxmin.id
INNER JOIN episode_previous ON eps.id = episode_previous.id
INNER JOIN episode_next ON eps.id = episode_next.id
LEFT JOIN comment_tallies ON eps.id = comment_tallies.eps_id
WHERE eps.id = ?
'
%-->

View File

@@ -0,0 +1,51 @@
<!--% query_episode_maxmin = '
WITH episode_maxmin AS (
SELECT MAX(id) AS \'latest\', MIN(id) AS \'earliest\', ? AS \'id\'
FROM eps
WHERE eps.date < date(\'now\', \'+1 days\')
),
episode_date AS (
SELECT eps.date
FROM eps
WHERE eps.id = ?
),
episode_previous AS (
SELECT MAX(id) AS \'previous\', ? AS \'id\'
FROM eps
INNER JOIN episode_date
ON eps.date < episode_date.date
WHERE eps.id > 1
),
episode_next AS (
SELECT MIN(id) AS \'next\', ? AS \'id\'
FROM eps
INNER JOIN episode_date
ON eps.date > episode_date.date
WHERE eps.date < date(\'now\')
),
comment_tallies AS (
SELECT
eps_id,
COUNT(eps_id) AS eps_tally
FROM comments
GROUP BY eps_id
)
SELECT eps.id, eps.date, eps.title, eps.duration,
eps.summary, eps.notes, eps.explicit, eps.license,
eps.tags, eps.version, eps.downloads, eps.valid,
episode_maxmin.latest, episode_maxmin.earliest,
episode_previous.previous, episode_next.next,
hosts.hostid, hosts.host,
miniseries.name AS \'series\', miniseries.id AS \'seriesid\',
miniseries.description AS \'series_description\',
COALESCE (comment_tallies.eps_tally, 0) AS eps_tally
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
INNER JOIN episode_maxmin ON eps.id = episode_maxmin.id
INNER JOIN episode_previous ON eps.id = episode_previous.id
INNER JOIN episode_next ON eps.id = episode_next.id
LEFT JOIN comment_tallies ON eps.id = comment_tallies.eps_id
WHERE eps.id = ?
'
%-->

View File

@@ -0,0 +1,15 @@
<!--% query_episodes = 'SELECT
eps.id,
eps.explicit,
eps.date, eps.license, eps.title, eps.summary,
eps.duration, eps.notes, eps.tags,
hosts.hostid,
hosts.host, hosts.email, hosts.local_image,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
ORDER BY eps.id DESC'
%-->

View File

@@ -0,0 +1,15 @@
<!--% query_episodes = 'SELECT
eps.id,
eps.explicit,
eps.date, eps.license, eps.title, eps.summary,
eps.duration, eps.notes, eps.tags,
hosts.hostid,
hosts.host, hosts.email, hosts.local_image,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < date(\'now\', \'+1 days\')
ORDER BY eps.id + 0 DESC'
%-->

View File

@@ -0,0 +1,4 @@
<!--% query_ids_episode = 'select eps.id from eps
where eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY) '
%-->

View File

@@ -0,0 +1,4 @@
<!--% query_ids_episode = 'select eps.id from eps
where eps.date < date(\'now\', \'+1 days\')'
%-->

View File

@@ -0,0 +1,62 @@
<!--% query_next_available_episode = '
WITH next_id AS (
SELECT id, id + 1 AS \'id_next\', date as \'last_date\'
FROM eps
WHERE eps.date > NOW()
)
SELECT
MIN(next_id.id_next) AS \'next_id\',
DATE_FORMAT(MIN(last_date), \'%Y\') AS \'last_year\',
DATE_FORMAT(MIN(last_date), \'%d\') AS \'last_day\',
DATE_FORMAT(MIN(last_date), \'%m\') AS \'last_month\'
FROM next_id
LEFT JOIN eps ON next_id.id_next = eps.id
WHERE eps.id IS NULL
'
%-->
<!--% query_latest_episodes = '
WITH comment_tallies AS (
SELECT
eps_id,
COUNT(eps_id) AS eps_tally
FROM comments
GROUP BY eps_id
)
SELECT
eps.id,
eps.explicit,
eps.date, eps.license, eps.duration,
eps.title, eps.summary, eps.tags,
eps.notes,
hosts.local_image,
hosts.hostid,
hosts.host, hosts.email,
miniseries.name AS series, miniseries.id AS seriesid,
COALESCE (comment_tallies.eps_tally, 0) AS eps_tally
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
LEFT JOIN comment_tallies ON eps.id = comment_tallies.eps_id
WHERE eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
ORDER BY eps.id DESC
LIMIT 10
'
%-->
<!--% query_last_5_weeks_episodes = '
SELECT
eps.id,
CASE eps.explicit WHEN 1 THEN \'Explicit\' ELSE \'Clean\' END AS explicit ,
eps.date, eps.license, eps.title, eps.summary,
eps.duration, eps.notes, eps.tags,
hosts.hostid,
hosts.host, hosts.email, hosts.local_image,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
ORDER BY eps.id DESC
LIMIT 30 OFFSET 10
'
%-->

View File

@@ -0,0 +1,62 @@
<!--% query_next_available_episode = '
WITH next_id AS (
SELECT id, id + 1 AS \'id_next\', date as \'last_date\'
FROM eps
WHERE eps.date > date(\'now\')
)
SELECT
MIN(next_id.id_next) AS \'next_id\',
strftime(\'%Y\', MIN (last_date)) AS \'last_year\',
strftime(\'%d\', MIN (last_date)) AS \'last_day\',
strftime(\'%m\', MIN (last_date)) AS \'last_month\'
FROM next_id
LEFT JOIN eps ON next_id.id_next = eps.id
WHERE eps.id IS NULL
'
%-->
<!--% query_latest_episodes = '
WITH comment_tallies AS (
SELECT
eps_id,
COUNT(eps_id) AS eps_tally
FROM comments
GROUP BY eps_id
)
SELECT
eps.id,
eps.explicit,
eps.date, eps.license, eps.duration,
eps.title, eps.summary, eps.tags,
eps.notes,
hosts.local_image,
hosts.hostid,
hosts.host, hosts.email,
miniseries.name AS series, miniseries.id AS seriesid,
COALESCE (comment_tallies.eps_tally, 0) AS eps_tally
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
LEFT JOIN comment_tallies ON eps.id = comment_tallies.eps_id
WHERE eps.date < date(\'now\', \'+1 days\')
ORDER BY eps.id + 0 DESC
LIMIT 10
'
%-->
<!--% query_last_5_weeks_episodes = '
SELECT
eps.id,
CASE eps.explicit WHEN 1 THEN \'Explicit\' ELSE \'Clean\' END AS explicit ,
eps.date, eps.license, eps.title, eps.summary,
eps.duration, eps.notes, eps.tags,
hosts.hostid,
hosts.host, hosts.email, hosts.local_image,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < date(\'now\', \'+1 days\')
ORDER BY eps.id + 0 DESC
LIMIT 30 OFFSET 10
'
%-->

View File

@@ -0,0 +1,15 @@
<!--% query_episodes = 'SELECT miniseries.id, miniseries.name, miniseries.description,
miniseries.private, miniseries.image, miniseries.valid,
ep.number_of_episodes, ep.latest_show, ep.earliest_show
FROM miniseries
INNER JOIN
(SELECT series,
COUNT(eps.id) AS number_of_episodes,
MAX(eps.date) AS latest_show,
MIN(eps.date) AS earliest_show
FROM eps
WHERE eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
GROUP BY series) AS ep ON ep.series = miniseries.id
ORDER BY name'
%-->

View File

@@ -0,0 +1,15 @@
<!--% query_episodes = 'SELECT miniseries.id, miniseries.name, miniseries.description,
miniseries.private, miniseries.image, miniseries.valid,
ep.number_of_episodes, ep.latest_show, ep.earliest_show
FROM miniseries
INNER JOIN
(SELECT series,
COUNT(eps.id) AS number_of_episodes,
MAX(eps.date) AS latest_show,
MIN(eps.date) AS earliest_show
FROM eps
WHERE eps.date < date(\'now\', \'+1 days\')
GROUP BY series) AS ep ON ep.series = miniseries.id
ORDER BY name'
%-->

View File

@@ -0,0 +1,29 @@
<!--% query_series_sql = 'SELECT miniseries.id, miniseries.name,
miniseries.description,
miniseries.private, miniseries.image, miniseries.valid,
ep.number_of_episodes, ep.latest_show, ep.earliest_show
FROM miniseries
INNER JOIN
(SELECT series,
COUNT(eps.id) AS number_of_episodes,
MAX(eps.date) AS latest_show,
MIN(eps.date) AS earliest_show
FROM eps
WHERE eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
GROUP BY series) AS ep ON ep.series = miniseries.id
WHERE miniseries.id = ?
ORDER BY name'
%-->
<!--% query_shows_sql = 'SELECT
id, date, title,
duration, summary, notes,
explicit, eps.license, tags,
hosts.host, hosts.hostid
FROM eps
INNER JOIN hosts
ON eps.hostid = hosts.hostid
WHERE series = ? AND eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
ORDER BY eps.id DESC
'
%-->

View File

@@ -0,0 +1,28 @@
<!--% query_series_sql = 'SELECT miniseries.id, miniseries.name,
miniseries.description,
miniseries.private, miniseries.image, miniseries.valid,
ep.number_of_episodes, ep.latest_show, ep.earliest_show
FROM miniseries
INNER JOIN
(SELECT series,
COUNT(eps.id) AS number_of_episodes,
MAX(eps.date) AS latest_show,
MIN(eps.date) AS earliest_show
FROM eps
WHERE eps.date < date(\'now\', \'+1 days\')
GROUP BY series) AS ep ON ep.series = miniseries.id
WHERE miniseries.id = ?
ORDER BY name'
%-->
<!--% query_shows_sql = 'SELECT
id, date, title,
duration, summary, notes,
explicit, eps.license, tags,
hosts.host, hosts.hostid
FROM eps
INNER JOIN hosts
ON eps.hostid = hosts.hostid
WHERE series = ? AND eps.date < date(\'now\', \'+1 days\')
ORDER BY eps.id DESC
'
%-->

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" >
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% PROCESS 'shared-episode-summary.tpl.html' %-->
<!--% USE date %-->
<channel>
<title>Hacker Public Radio ~ Comment Feed</title>
<link><!--% baseurl %-->about.html</link>
<description>Comments Feed: Hacker Public Radio is an podcast that releases shows every weekday Monday through Friday. Our shows are produced by the community (you) and can be on any topic that are of interest to hackers and hobbyists.</description>
<language>en-us</language>
<copyright>Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License</copyright>
<managingEditor>feedback.nospam@nospam.hackerpublicradio.org (HPR Feedback)</managingEditor>
<webMaster>admin.nospam@nospam.hackerpublicradio.org (HPR Webmaster)</webMaster>
<generator>hpr_generator</generator>
<docs>http://www.rssboard.org/rss-specification</docs>
<ttl>600</ttl>
<image>
<url><!--% baseurl %-->images/hpr_feed_small.png</url>
<title>Hacker Public Radio ~ Comment Feed</title>
<link><!--% baseurl %-->about.html</link>
<description>The Hacker Public Radio Old Microphone Logo</description>
<height>164</height>
<width>144</width>
</image>
<atom:link href="<!--% baseurl %-->comments.rss" rel="self" type="application/rss+xml" />
<pubDate><!--% format_feed_date(date.now) %--></pubDate>
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% FOREACH item IN DBI.query('
SELECT C.*,
H.host, H.hostid AS host_id,
E.title AS episode_title,
E.date AS episode_date,
E.duration AS episode_duration,
M.id AS series_id, M.name AS series_name
FROM comments AS C
INNER JOIN eps AS E
ON C.eps_id = E.id
INNER JOIN hosts AS H
ON E.hostid = H.hostid
INNER JOIN miniseries AS M
ON E.series = M.id
ORDER BY C.comment_timestamp DESC
LIMIT 30
')
%-->
<item>
<title><!--% item.comment_author_name %--> says: <!--% item.comment_title %--></title>
<author>feedback.nospam@nospam.hackerpublicradio.org (<!--% item.comment_author_name %-->)</author>
<link><!--% baseurl %-->eps/hpr<!--% zero_pad_left(item.eps_id) %-->/index.html#comments</link>
<description><![CDATA[<strong>RE: hpr<!--% zero_pad_left(item.eps_id) %-->::<!--% item.episode_date %--> <em><!--% item.episode_title %--></em> by <a href="<!--% baseurl %-->correspondents/<!--% zero_pad_left(item.host_id) %-->.html"><!--% item.host %--></a></strong><!--% rss_show_series(item.series_name, item.series_id) %--><br />
<!--% display_episode_duration(item.episode_duration) %--><!--% display_listen_in(item.eps_id) %--><br /><!--% item.comment_text %-->
]]></description>
<pubDate><!--% format_feed_date(item.comment_timestamp) %--></pubDate>
<guid isPermaLink="false"><!--% baseurl %-->eps/hpr<!--% zero_pad_left(item.eps_id) %-->/index.html#comment_<!--% item.id %--></guid>
</item>
<!--% END %-->
</channel>
</rss>

View File

@@ -1,5 +1,5 @@
<!--% PROCESS 'shared-item.tpl.xml' %-->
<!--% PROCESS 'rss-query-hpr.tpl.xml' %-->
<!--% PROCESS "rss-query-hpr-${constants.database}.tpl.xml" %-->
<!--% FOREACH episode IN feed_result %-->
<!--% display_item(episode, media_file_extension, audio_mime_type) %-->
<!--% END %-->

View File

@@ -1,5 +1,5 @@
<!--% PROCESS 'shared-item.tpl.xml' %-->
<!--% PROCESS 'rss-query-hpr_total.tpl.xml' %-->
<!--% PROCESS "rss-query-hpr_total-${constants.database}.tpl.xml" %-->
<!--% FOREACH episode IN feed_result %-->
<!--% display_item(episode, media_file_extension, audio_mime_type) %-->
<!--% END %-->

View File

@@ -0,0 +1,23 @@
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% query_hpr_feed = DBI.prepare('
SELECT
eps.id,
eps.explicit,
DATE_FORMAT(eps.date, \'%H:%i:%S %d:%m:%Y\') AS \'date\',
eps.license, eps.duration,
eps.title, eps.summary, eps.tags,
eps.notes,
hosts.local_image,
hosts.hostid,
hosts.host, hosts.email,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
ORDER BY eps.date DESC
LIMIT 10
')
%-->
<!--% feed_result = query_hpr_feed.execute() %-->

View File

@@ -0,0 +1,22 @@
<!--% USE DBI(constants.driver, constants.user, constants.password) %-->
<!--% query_hpr_feed = DBI.prepare('
SELECT
eps.id,
eps.explicit,
DATE_FORMAT(eps.date, \'%H:%i:%S %d:%m:%Y\') AS \'date\',
eps.license, eps.duration,
eps.title, eps.summary, eps.tags,
eps.notes,
hosts.local_image,
hosts.hostid,
hosts.host, hosts.email,
miniseries.name AS series, miniseries.id AS seriesid
FROM eps
INNER JOIN hosts ON eps.hostid = hosts.hostid
INNER JOIN miniseries ON eps.series = miniseries.id
WHERE eps.date < DATE_ADD(NOW(), INTERVAL 1 DAY)
ORDER BY eps.date DESC
')
%-->
<!--% feed_result = query_hpr_feed.execute() %-->

View File

@@ -0,0 +1,18 @@
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% PROCESS "queries-call_for_shows-${constants.database}.tpl.html" %-->
<!--% MACRO display_call_for_shows BLOCK %-->
<!--% result_call_for_shows = DBI.prepare(query_call_for_shows)
%-->
<!--% results_call_for_shows = result_call_for_shows.execute().get_all() %-->
<!--% IF results_call_for_shows.0.request_for_shows == 1 %-->
<!--% USE date %-->
<article>
<header>
<h3>Call for shows</h3>
</header>
<p><strong><em>We are running very low on shows</em></strong> at the moment. Have a look at the <a href="<!--% absolute_path(baseurl) %-->correspondents/index.html">hosts</a> page and if you don't see "<!--% date.format(date.now, '%Y') %-->-??-??" next to your name, or if your name is not listed, you might consider sending us in something.</p>
<!-- <img src="/images/hprstats.png" alt="hpr queue showing an graph showing how few shows we have" /> -->
<p>There are no files to process on the FTP server.</p>
</article>
<!--% END %-->
<!--% END %-->

View File

@@ -1,12 +1,38 @@
<!--% PROCESS 'shared-utils.tpl.html' %-->
<!--% MACRO show_series(series, series_id) IF series != "" %-->
<label>Series:</label> <a href="<!--% absolute_path(baseurl) %-->series/<!--% zero_pad_left(series_id) %-->.html"><!--% series %--></a>.
<!--% MACRO rss_show_series(series, series_id) IF series != "general" %-->
from the series <em><a href="<!--% baseurl %-->series/<!--% zero_pad_left(series_id) %-->.html"><!--% series %--></em></a>.
<!--% END %-->
<!--% MACRO show_meta(show) BLOCK %-->
<span><label>Released:</label> <!--% show.date %-->.</span> <span><label>Duration:</label> <!--% show.duration %-->.</span> <span><label>Flag:</label> <!--% display_explicit(show.explicit) %-->.</span> <span><!--% show_series(show.series, show.seriesid) %--></span> <br>
<span><label>Tags:</label> <em><!--% show.tags %--></em>.</span>
<!--% MACRO show_series(series, series_id, label) IF series != "" %-->
<!--% IF label == "" %-->
<!--% label = "Series" %-->
<!--% END %-->
<label><!--% label %-->:</label> <a href="<!--% absolute_path(baseurl) %-->series/<!--% zero_pad_left(series_id) %-->.html"><!--% series %--></a>.
<!--% END %-->
<!--% MACRO display_tags(tags) BLOCK %-->
<span><label>Tags:</label> <em><!--% tags %--></em>.</span>
<!--% END %-->
<!--% MACRO display_listen_in(eps_id, episode_type) BLOCK %-->
<!--% IF episode_type == "" %--><!--% episode_type = 'hpr' %--><!--% END %-->
Listen in
<!--% IF episode_type == 'hpr' %-->
<a href="<!--% media_path(eps_id, episode_type, 'ogg', baseurl, media_baseurl) %-->">ogg</a>,
<a href="<!--% media_path(eps_id, episode_type, 'spx', baseurl, media_baseurl) %-->">spx</a>,
or
<!--% END %-->
<a href="<!--% media_path(eps_id, episode_type, 'mp3', baseurl, media_baseurl) %-->">mp3</a> format.
<!--% END %-->
<!--% MACRO display_comments_tally(eps_id, tally) BLOCK %-->
<a href="<!--% absolute_path(baseurl) %-->eps/hpr<!--% zero_pad_left(eps_id) %-->/index.html#comments">Comments (<!--% tally %-->)</a>.
<!--% END %-->
<!--% MACRO show_meta(show, hide_tags) BLOCK %-->
<span><label>Released:</label> <!--% show.date %-->.</span> <span><label>Duration:</label> <!--% display_episode_duration(show.duration) %-->.</span> <span><label>Flag:</label> <!--% display_explicit(show.explicit) %-->.</span> <span><!--% show_series(show.series, show.seriesid) %--></span> <br>
<!--% IF hide_tags == "" %--><!--% display_tags(tags) %--><!--% END %-->
<!--% END %-->
<!--% MACRO show_summary(show, hide_host) BLOCK %-->
@@ -19,3 +45,15 @@
<!--% show.summary %-->
</p>
<!--% END %-->
<!--% MACRO twat_show_summary(show, hide_host) BLOCK %-->
<h3 class="title"><a href="<!--% absolute_path(baseurl) %-->eps/twat<!--% zero_pad_left(show.id) %-->/index.html">twat<!--% show.id %--> :: <!--% show.title %--></a> <!--% IF hide_host == "" %-->
hosted by <a href="<!--% absolute_path(baseurl) %-->correspondents/<!--% zero_pad_left(show.hostid) %-->.html"><!--% show.host %--></a>
<!--% END %-->
</h3>
<p class="meta"><!--% show_meta(show) %--><br>
<!--% show.summary %-->
</p>
<!--% END %-->

View File

@@ -0,0 +1,16 @@
<!--% MACRO listen_now(episode, episode_type, baseurl, media_baseurl) BLOCK %-->
<h2>Listen Now</h2>
<p>Duration: <!--% display_episode_duration(episode.duration) %--></p>
<audio controls preload="none">
<source src="<!--% media_path(episode.id, episode_type, 'ogg', baseurl, media_baseurl) %-->" type="audio/ogg" >
<source src="<!--% media_path(episode.id, episode_type, 'mp3', baseurl, media_baseurl) %-->" type="audio/mpeg" >
</audio>
<ul>
<!--% IF episode_type != "twat" %-->
<li>ogg: <a href="<!--% media_path(episode.id, episode_type, 'ogg', baseurl, media_baseurl) %-->"><!--% media_path(episode.id, episode_type, 'ogg', baseurl, media_baseurl) %--></a></li>
<li>spx: <a href="<!--% media_path(episode.id, episode_type, 'spx', baseurl, media_baseurl) %-->"><!--% media_path(episode.id, episode_type, 'spx', baseurl, media_baseurl) %--></a></li>
<!--% END %-->
<li>mp3: <a href="<!--% media_path(episode.id, episode_type, 'mp3', baseurl, media_baseurl) %-->"><!--% media_path(episode.id, episode_type, 'mp3', baseurl, media_baseurl) %--></a></li>
</ul>
<!--% END %-->

View File

@@ -0,0 +1,12 @@
<!--% MACRO show_transcript(episode, episode_type, baseurl, media_baseurl) BLOCK %-->
<h2>Show Transcript</h2>
<p>Automatically generated using <a href="https://github.com/openai/whisper">whisper</a>
<pre><code>whisper --model tiny --language en hpr<!--% zero_pad_left(episode.id) %-->.wav</code></pre></p>
<ul>
<li>Text: <a href="<!--% media_path(episode.id, episode_type, 'txt', baseurl, media_baseurl) %-->">hpr<!--% zero_pad_left(episode.id) %-->.txt</a></li>
<li><a href="https://en.wikipedia.org/wiki/WebVTT">WebVTT</a>: <a href="<!--% media_path(episode.id, episode_type, 'vtt', baseurl, media_baseurl) %-->">hpr<!--% zero_pad_left(episode.id) %-->.vtt</a></li>
<li><a href="https://en.wikipedia.org/wiki/SubRip">SubRip</a>: <a href="<!--% media_path(episode.id, episode_type, 'srt', baseurl, media_baseurl) %-->">hpr<!--% zero_pad_left(episode.id) %-->.srt</a></li>
</ul>
<!--% END %-->

View File

@@ -1,6 +1,11 @@
<!--% MACRO zero_pad_left(word) BLOCK %-->
<!--% USE String(word) %-->
<!--% String.format("%04s") %-->
<!--% MACRO zero_pad_left(word, pad_length) BLOCK %-->
<!--% IF pad_length %-->
<!--% zero_pad_format = "%0${pad_length}s" %-->
<!--% ELSE %-->
<!--% zero_pad_format = "%04s" %-->
<!--% END %-->
<!--% USE String(word) %-->
<!--% String.format(zero_pad_format) %-->
<!--% END %-->
<!--% MACRO display_choice(choice, display_when_true, display_when_false) BLOCK %-->
@@ -8,6 +13,20 @@
<!--% ELSE %--><!--% display_when_false %--><!--% END %-->
<!--% END %-->
<!--% MACRO display_episode_duration(duration_sec) BLOCK %-->
<!--% seconds = duration_sec % 60 %-->
<!--% USE format %-->
<!--% minutes_only = format("%d") %-->
<!--% minutes = minutes_only(duration_sec / 60) %-->
<!--% hours_only = format("%d") %-->
<!--% hours = hours_only(minutes / 60) %-->
<!--% IF hours >= 1 %-->
<!--% minutes = minutes - hours * 60 %-->
<!--% END %-->
<!--% display_hours = format("%02d:%02d:%02d") %-->
<!--% display_hours(hours,minutes,seconds) %-->
<!--% END %-->
<!--% MACRO display_explicit(is_explicit) BLOCK %-->
<!--% display_choice(is_explicit, 'Explicit', 'Clean') %-->
<!--% END %-->
@@ -17,7 +36,7 @@
<!--% END %-->
<!--% MACRO format_feed_date(date_to_format) BLOCK %-->
<!--% USE feed_date = date(format = '%a, %e %b %Y 00:00:00 +0000', gmt=1) %-->
<!--% USE feed_date = date(format = '%a, %d %b %Y %H:%M:%S +0000', gmt=1) %-->
<!--% feed_date.format(date_to_format) %-->
<!--% END %-->
@@ -25,17 +44,47 @@
<!--% IF baseurl %-->./<!--% ELSE %-->/<!--% END %-->
<!--% END %-->
<!--% MACRO step_navigation(baseurl, links) BLOCK %-->
<small><a href="<!--% absolute_path(baseurl) %-->eps/hpr<!--% zero_pad_left(links.earliest) %-->/index.html" rel="first">&lt;&lt; First</a>,
<!--% MACRO media_basepath(baseurl, media_baseurl) BLOCK %-->
<!--% IF media_baseurl %-->
<!--% media_baseurl %--><!--% ELSE %-->
<!--% IF baseurl %--><!--% baseurl %--><!--% ELSE %-->/<!--% END %-->
<!--% END %-->
<!--% END %-->
<!--% MACRO media_path(episode_id, episode_type, media_type, baseurl, media_baseurl) BLOCK %-->
<!--% IF episode_type == "twat" %-->
<!--% padding = 3 %-->
<!--% media_folder = "eps/"; padding = 3 %-->
<!--% ELSE %-->
<!--% media_folder = "local/" %-->
<!--% END %-->
<!--% IF media_baseurl %-->
<!--% transcription_types = "txt srt vtt" %-->
<!--% USE String(transcription_types) %-->
<!--% USE String(media_baseurl) %-->
<!--% IF transcription_types.search(media_type) && media_baseurl.search('archive.org') %-->
<!--% media_baseurl = "${media_baseurl}hpr\$eps_id/" %-->
<!--% END %-->
<!--% media_folder = "" %-->
<!--% media_baseurl = media_baseurl.replace('\$eps_id', zero_pad_left(episode_id)) %-->
<!--% END %-->
<!--% media_basepath(baseurl, media_baseurl) %--><!--% media_folder %--><!--% episode_type %--><!--% zero_pad_left(episode_id, padding) %-->.<!--% media_type %-->
<!--% END %-->
<!--% MACRO step_navigation(baseurl, links, folder) BLOCK %-->
<!--% IF folder %-->
<!--% folder = folder %--><!--% ELSE %--><!--% folder = "hpr" %-->
<!--% END %-->
<small><a href="<!--% absolute_path(baseurl) %-->eps/<!--% folder %--><!--% zero_pad_left(links.earliest) %-->/index.html" rel="first">&lt;&lt; First</a>,
<!--% IF links.previous %-->
<a href="<!--% absolute_path(baseurl) %-->eps/hpr<!--% zero_pad_left(links.previous) %-->/index.html" rel="previous">&lt; Previous</a>,
<a href="<!--% absolute_path(baseurl) %-->eps/<!--% folder %--><!--% zero_pad_left(links.previous) %-->/index.html" rel="previous">&lt; Previous</a>,
<!--% ELSE %-->
<span>&lt;</span> Previous,
<!--% END %-->
<!--% IF links.next %-->
<a href="<!--% absolute_path(baseurl) %-->eps/hpr<!--% zero_pad_left(links.next) %-->/index.html" rel="next">Next &gt;</a>,
<a href="<!--% absolute_path(baseurl) %-->eps/<!--% folder %--><!--% zero_pad_left(links.next) %-->/index.html" rel="next">Next &gt;</a>,
<!--% ELSE %-->
Next <span>&gt;</span>
<!--% END %-->
<a href="<!--% absolute_path(baseurl) %-->eps/hpr<!--% zero_pad_left(links.latest) %-->/index.html" rel="last">Latest &gt;&gt;</a></small>
<a href="<!--% absolute_path(baseurl) %-->eps/<!--% folder %--><!--% zero_pad_left(links.latest) %-->/index.html" rel="last">Latest &gt;&gt;</a></small>
<!--% END %-->

184
utils/lib_utils.sh Normal file
View File

@@ -0,0 +1,184 @@
#!/bin/bash -
#===============================================================================
#
# FILE: lib_utils.sh
#
# USAGE: ./lib_utils.sh
#
# DESCRIPTION: functions for scripts used to update local HPR installations
# using the HPR static site generator
#
# OPTIONS: ---
# REQUIREMENTS: mysql2sqlite (https://github.com/dumblob/mysql2sqlite)
# BUGS: ---
# NOTES: ---
# AUTHOR: Roan "Rho`n" Horning <roan.horning@gmail.com>
# CREATED: 02/26/2023 03:27:08 PM -5 UTC
# REVISION: ---
# LICENSE: GNU AGPLv3
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#===============================================================================
set -o nounset # Treat unset variables as an error
#--- FUNCTION ----------------------------------------------------------------
# NAME: make_working_dir
# DESCRIPTION: Creates a local temporary working directory
# SEE: https://stackoverflow.com/questions/4632028/how-to-create-a-temporary-directory#answer-34676160
# PARAMETERS:
# RETURNS: The path to the working directory
#-------------------------------------------------------------------------------
function make_working_dir {
# the directory of the script
local DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# the temp directory used, within $DIR
# omit the -p parameter to create a temporal directory in
# the default location
local WORK_DIR=`mktemp -d -p "$DIR"`
# check if tmp dir was created
if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then
echo "Could not create temp dir"
exit 1
fi
echo $WORK_DIR
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: clean_working_dir
# DESCRIPTION: Remove local temporary working directory
# PARAMETERS: WORK_DIR -- Temporay directory to be delted
# RETURNS:
#-------------------------------------------------------------------------------
function clean_working_dir {
if [[ -d $1 ]] && expr $1 : '.*/tmp.*' ; then
rm -rf $1
echo "Deleted temp working directory $1"
else
echo "Did not delete directory: $1"
echo "Not a temporary directory."
fi
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: download_hpr_sql
# DESCRIPTION: Download the HPR SQL dump file into a working directory
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
function download_hpr_sql {
if [[ ! -d $1 ]] || ! expr $1 : '.*/tmp.*' ;
then
echo "Please provide the temporary directory when calling this function"
return 1
fi
local CURL=`which curl`
local WGET=`which wget`
local HPR_URL=https://www.hackerpublicradio.org/hpr.sql
if [ -f $1/hpr.sql ];
then
echo "Removing temporary hpr.sql"
rm $1/hpr.sql
else
echo "No temporary hpr.sql to remove"
fi
if [ "$CURL" != "" ];
then
curl $HPR_URL --output $1/hpr.sql
echo "Downloaded hpr.sql via curl"
elif [ "$WGET" != "" ];
then
wget --directory-prefix=$1 $HPR_URL
echo "Downloaded hpr.sql via wget"
else
echo "Could not download file. Please install either curl or wget."
return 1
fi
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: make_hpr_sqlite_db
# DESCRIPTION: Converts the hpr sql file into an sqlite db file
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
function make_hpr_sqlite_db {
if [[ ! -d $1 ]] || ! expr $1 : '.*/tmp.*' ;
then
echo "Please provide the temporary directory when calling this function"
return 1
fi
local MYSQL2SQLITE=`which mysql2sqlite`
local BIN_PATH=""
if [ "$MYSQL2SQLITE" = "" ];
then
if [ $# -gt 1 ] && [ -z "$2" ];
then
BIN_PATH=$2
else
BIN_PATH=`find . -type f -name "mysql2sqlite" -print | head -1`
if [ "$BIN_PATH" != "" ];
then
BIN_PATH=${BIN_PATH/mysql2sqlite//}
else
echo "Could not find mysql2sqlite script."
return 1
fi
fi
fi
echo $BIN_PATH
if [ -f $1/hpr.db ];
then
rm $1/hpr.db
fi
# Remove lines from hpr.sql that mysql2sqlite can't handle
sed '/^DELIMITER ;;/,/^DELIMITER ;/d' < $1/hpr.sql > $1/hpr-sqlite.sql
${BIN_PATH}mysql2sqlite $1/hpr-sqlite.sql | sqlite3 $1/hpr.db
echo "Created hpr.db"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: copy_to_public_dir
# DESCRIPTION: Move HPR sql and db files to public website folder
# PARAMETERS:
# RETURNS:
#-------------------------------------------------------------------------------
function copy_to_public_dir {
if [ $# -gt 1 ] && [ ! -z "$1" ] && [ ! -z "$2" ];
then
cp $1/hpr.sql $2/hpr.sql
cp $1/hpr.db $2/hpr.db
return 0
else
echo "Bad arguments. Can't copy files to public directory."
fi
}

289
utils/mysql2sqlite Executable file
View File

@@ -0,0 +1,289 @@
#!/usr/bin/awk -f
# Authors: @esperlu, @artemyk, @gkuenning, @dumblob
# FIXME detect empty input file and issue a warning
function printerr( s ){ print s | "cat >&2" }
BEGIN {
if( ARGC != 2 ){
printerr( \
"USAGE:\n"\
" mysql2sqlite dump_mysql.sql > dump_sqlite3.sql\n" \
" OR\n" \
" mysql2sqlite dump_mysql.sql | sqlite3 sqlite.db\n" \
"\n" \
"NOTES:\n" \
" Dash in filename is not supported, because dash (-) means stdin." )
no_END = 1
exit 1
}
# Find INT_MAX supported by both this AWK (usually an ISO C signed int)
# and SQlite.
# On non-8bit-based architectures, the additional bits are safely ignored.
# 8bit (lower precision should not exist)
s="127"
# "63" + 0 avoids potential parser misbehavior
if( (s + 0) "" == s ){ INT_MAX_HALF = "63" + 0 }
# 16bit
s="32767"
if( (s + 0) "" == s ){ INT_MAX_HALF = "16383" + 0 }
# 32bit
s="2147483647"
if( (s + 0) "" == s ){ INT_MAX_HALF = "1073741823" + 0 }
# 64bit (as INTEGER in SQlite3)
s="9223372036854775807"
if( (s + 0) "" == s ){ INT_MAX_HALF = "4611686018427387904" + 0 }
# # 128bit
# s="170141183460469231731687303715884105728"
# if( (s + 0) "" == s ){ INT_MAX_HALF = "85070591730234615865843651857942052864" + 0 }
# # 256bit
# s="57896044618658097711785492504343953926634992332820282019728792003956564819968"
# if( (s + 0) "" == s ){ INT_MAX_HALF = "28948022309329048855892746252171976963317496166410141009864396001978282409984" + 0 }
# # 512bit
# s="6703903964971298549787012499102923063739682910296196688861780721860882015036773488400937149083451713845015929093243025426876941405973284973216824503042048"
# if( (s + 0) "" == s ){ INT_MAX_HALF = "3351951982485649274893506249551461531869841455148098344430890360930441007518386744200468574541725856922507964546621512713438470702986642486608412251521024" + 0 }
# # 1024bit
# s="89884656743115795386465259539451236680898848947115328636715040578866337902750481566354238661203768010560056939935696678829394884407208311246423715319737062188883946712432742638151109800623047059726541476042502884419075341171231440736956555270413618581675255342293149119973622969239858152417678164812112068608"
# if( (s + 0) "" == s ){ INT_MAX_HALF = "44942328371557897693232629769725618340449424473557664318357520289433168951375240783177119330601884005280028469967848339414697442203604155623211857659868531094441973356216371319075554900311523529863270738021251442209537670585615720368478277635206809290837627671146574559986811484619929076208839082406056034304" + 0 }
# # higher precision probably not needed
FS=",$"
print "PRAGMA synchronous = OFF;"
print "PRAGMA journal_mode = MEMORY;"
print "BEGIN TRANSACTION;"
}
# historically 3 spaces separate non-argument local variables
function bit_to_int( str_bit, powtwo, i, res, bit, overflow ){
powtwo = 1
overflow = 0
# 011101 = 1*2^0 + 0*2^1 + 1*2^2 ...
for( i = length( str_bit ); i > 0; --i ){
bit = substr( str_bit, i, 1 )
if( overflow || ( bit == 1 && res > INT_MAX_HALF ) ){
printerr( \
NR ": WARN Bit field overflow, number truncated (LSBs saved, MSBs ignored)." )
break
}
res = res + bit * powtwo
# no warning here as it might be the last iteration
if( powtwo > INT_MAX_HALF ){ overflow = 1; continue }
powtwo = powtwo * 2
}
return res
}
# CREATE TRIGGER statements have funny commenting. Remember we are in trigger.
/^\/\*.*(CREATE.*TRIGGER|create.*trigger)/ {
gsub( /^.*(TRIGGER|trigger)/, "CREATE TRIGGER" )
print
inTrigger = 1
next
}
# The end of CREATE TRIGGER has a stray comment terminator
/(END|end) \*\/;;/ { gsub( /\*\//, "" ); print; inTrigger = 0; next }
# The rest of triggers just get passed through
inTrigger != 0 { print; next }
# CREATE VIEW looks like a TABLE in comments
/^\/\*.*(CREATE.*TABLE|create.*table)/ {
inView = 1
next
}
# end of CREATE VIEW
/^(\).*(ENGINE|engine).*\*\/;)/ {
inView = 0
next
}
# content of CREATE VIEW
inView != 0 { next }
# skip comments
/^\/\*/ { next }
# skip PARTITION statements
/^ *[(]?(PARTITION|partition) +[^ ]+/ { next }
# print all INSERT lines
( /^ *\(/ && /\) *[,;] *$/ ) || /^(INSERT|insert|REPLACE|replace)/ {
prev = ""
# first replace \\ by \_ that mysqldump never generates to deal with
# sequnces like \\n that should be translated into \n, not \<LF>.
# After we convert all escapes we replace \_ by backslashes.
gsub( /\\\\/, "\\_" )
# single quotes are escaped by another single quote
gsub( /\\'/, "''" )
gsub( /\\n/, "\n" )
gsub( /\\r/, "\r" )
gsub( /\\"/, "\"" )
gsub( /\\\032/, "\032" ) # substitute char
gsub( /\\_/, "\\" )
# sqlite3 is limited to 16 significant digits of precision
while( match( $0, /0x[0-9a-fA-F]{17}/ ) ){
hexIssue = 1
sub( /0x[0-9a-fA-F]+/, substr( $0, RSTART, RLENGTH-1 ), $0 )
}
if( hexIssue ){
printerr( \
NR ": WARN Hex number trimmed (length longer than 16 chars)." )
hexIssue = 0
}
print
next
}
# CREATE DATABASE is not supported
/^(CREATE DATABASE|create database)/ { next }
# print the CREATE line as is and capture the table name
/^(CREATE|create)/ {
if( $0 ~ /IF NOT EXISTS|if not exists/ || $0 ~ /TEMPORARY|temporary/ ){
caseIssue = 1
printerr( \
NR ": WARN Potential case sensitivity issues with table/column naming\n" \
" (see INFO at the end)." )
}
if( match( $0, /`[^`]+/ ) ){
tableName = substr( $0, RSTART+1, RLENGTH-1 )
}
aInc = 0
prev = ""
firstInTable = 1
print
next
}
# Replace `FULLTEXT KEY` (probably other `XXXXX KEY`)
/^ (FULLTEXT KEY|fulltext key)/ { gsub( /[A-Za-z ]+(KEY|key)/, " KEY" ) }
# Get rid of field lengths in KEY lines
/ (PRIMARY |primary )?(KEY|key)/ { gsub( /\([0-9]+\)/, "" ) }
aInc == 1 && /PRIMARY KEY|primary key/ { next }
# Replace COLLATE xxx_xxxx_xx statements with COLLATE BINARY
/ (COLLATE|collate) [a-z0-9_]*/ { gsub( /(COLLATE|collate) [a-z0-9_]*/, "COLLATE BINARY" ) }
# Print all fields definition lines except the `KEY` lines.
/^ / && !/^( (KEY|key)|\);)/ {
if( match( $0, /[^"`]AUTO_INCREMENT|auto_increment[^"`]/) ){
aInc = 1
gsub( /AUTO_INCREMENT|auto_increment/, "PRIMARY KEY AUTOINCREMENT" )
}
gsub( /(UNIQUE KEY|unique key) (`.*`|".*") /, "UNIQUE " )
gsub( /(CHARACTER SET|character set) [^ ]+[ ,]/, "" )
# FIXME
# CREATE TRIGGER [UpdateLastTime]
# AFTER UPDATE
# ON Package
# FOR EACH ROW
# BEGIN
# UPDATE Package SET LastUpdate = CURRENT_TIMESTAMP WHERE ActionId = old.ActionId;
# END
gsub( /(ON|on) (UPDATE|update) (CURRENT_TIMESTAMP|current_timestamp)(\(\))?/, "" )
gsub( /(DEFAULT|default) (CURRENT_TIMESTAMP|current_timestamp)(\(\))?/, "DEFAULT current_timestamp")
gsub( /(COLLATE|collate) [^ ]+ /, "" )
gsub( /(ENUM|enum)[^)]+\)/, "text " )
gsub( /(SET|set)\([^)]+\)/, "text " )
gsub( /UNSIGNED|unsigned/, "" )
gsub( /_utf8mb3/, "" )
gsub( /` [^ ]*(INT|int|BIT|bit)[^ ]*/, "` integer" )
gsub( /" [^ ]*(INT|int|BIT|bit)[^ ]*/, "\" integer" )
ere_bit_field = "[bB]'[10]+'"
if( match($0, ere_bit_field) ){
sub( ere_bit_field, bit_to_int( substr( $0, RSTART +2, RLENGTH -2 -1 ) ) )
}
# remove USING BTREE and other suffixes for USING, for example: "UNIQUE KEY
# `hostname_domain` (`hostname`,`domain`) USING BTREE,"
gsub( / USING [^, ]+/, "" )
# field comments are not supported
gsub( / (COMMENT|comment).+$/, "" )
# Get commas off end of line
gsub( /,.?$/, "" )
if( prev ){
if( firstInTable ){
print prev
firstInTable = 0
}
else {
print "," prev
}
}
else {
# FIXME check if this is correct in all cases
if( match( $1,
/(CONSTRAINT|constraint) ["].*["] (FOREIGN KEY|foreign key)/ ) ){
print ","
}
}
prev = $1
}
/ ENGINE| engine/ {
if( prev ){
if( firstInTable ){
print prev
firstInTable = 0
}
else {
print "," prev
}
}
prev=""
print ");"
next
}
# `KEY` lines are extracted from the `CREATE` block and stored in array for later print
# in a separate `CREATE KEY` command. The index name is prefixed by the table name to
# avoid a sqlite error for duplicate index name.
/^( (KEY|key)|\);)/ {
if( prev ){
if( firstInTable ){
print prev
firstInTable = 0
}
else {
print "," prev
}
}
prev = ""
if( $0 == ");" ){
print
}
else {
if( match( $0, /`[^`]+/ ) ){
indexName = substr( $0, RSTART+1, RLENGTH-1 )
}
if( match( $0, /\([^()]+/ ) ){
indexKey = substr( $0, RSTART+1, RLENGTH-1 )
}
# idx_ prefix to avoid name clashes (they really happen!)
key[tableName] = key[tableName] "CREATE INDEX \"idx_" \
tableName "_" indexName "\" ON \"" tableName "\" (" indexKey ");\n"
}
}
END {
if( no_END ){ exit 1}
# print all KEY creation lines.
for( table in key ){ printf key[table] }
print "END TRANSACTION;"
if( caseIssue ){
printerr( \
"INFO Pure sqlite identifiers are case insensitive (even if quoted\n" \
" or if ASCII) and doesnt cross-check TABLE and TEMPORARY TABLE\n" \
" identifiers. Thus expect errors like \"table T has no column named F\".")
}
}

72
utils/update-hpr.sh Executable file
View File

@@ -0,0 +1,72 @@
#!/bin/bash -
#===============================================================================
#
# FILE: update-hpr.sh
#
# USAGE: ./update-hpr.sh
#
# DESCRIPTION: Script to update local statically generated HPR website
#
# OPTIONS: ---
# REQUIREMENTS: lib_utils.sh
# BUGS: ---
# NOTES: ---
# AUTHOR: Roan "Rho`n" Horning (roan.horning@gmail.com),
# ORGANIZATION:
# CREATED: 03/03/2023 09:26:29 PM
# REVISION: ---
# LICENSE: GNU AGPLv3
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#===============================================================================
set -o nounset # Treat unset variables as an error
BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
#
# Load library functions
#
LIB="$BASEDIR/lib_utils.sh"
[ -e $LIB ] || { echo "Unable to load functions.\n$LIB not found."; exit; }
source $LIB
WORKING_DIR=`make_working_dir`
download_hpr_sql $WORKING_DIR
make_hpr_sqlite_db $WORKING_DIR
copy_to_public_dir $WORKING_DIR `pwd`
mv hpr.sql public_html/
echo "Update static HTML files"
# Clean up previously generated files
rm -rf public_html/*.html public_html/correspondents public_html/eps public_html/series
git restore public_html/will-my-show-be-of-interest-to-hackers.html
# stash changes to configuration file to preserve DB settings
git stash
git pull
git stash pop
./site-generator --quiet --all
clean_working_dir $WORKING_DIR