From 7f4339a0d75a34ebd0e2f761579bf447fbc73928 Mon Sep 17 00:00:00 2001 From: Jonah Aragon Date: Fri, 20 Sep 2024 02:34:13 -0500 Subject: [PATCH 1/2] feat: Generate homepage topics on server side --- index-generation.sh | 104 ++++++++++++ theme/assets/javascripts/discourse-topics.js | 167 ------------------- theme/home.html | 22 +-- 3 files changed, 112 insertions(+), 181 deletions(-) create mode 100755 index-generation.sh delete mode 100644 theme/assets/javascripts/discourse-topics.js diff --git a/index-generation.sh b/index-generation.sh new file mode 100755 index 00000000..c98af91d --- /dev/null +++ b/index-generation.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +DATE_CMD="date" + +# Check if the script is running on macOS +if [[ "$OSTYPE" == "darwin"* ]]; then + DATE_CMD="gdate" +fi + +# URL of the Discourse top.json +DISCOURSE_URL="https://discuss.privacyguides.net/top.json?period=weekly" + +# Fetch the JSON data +json_data=$(curl -s $DISCOURSE_URL) + +# Extract the first 3 topics +topics=$(echo $json_data | jq -r '.topic_list.topics[:3]') + +# Generate HTML for the first 3 posts +html_output="" +for row in $(echo "${topics}" | jq -r '.[] | @base64'); do + _jq() { + echo ${row} | base64 --decode | jq -r ${1} + } + + title=$(_jq '.title') + id=$(_jq '.id') + like_count=$(_jq '.like_count') + reply_count=$(_jq '.posts_count') + views=$(_jq '.views') + last_poster_username=$(_jq '.last_poster_username') + last_posted_at=$(_jq '.last_posted_at') + readable_date=$($DATE_CMD -d "$last_posted_at" +"%b %d, %Y %H:%M") + + html_output+="
  • " + html_output+="

    ${title}

    " + html_output+="
    " + html_output+="

    " + html_output+="" + html_output+="${last_poster_username}" + html_output+=" Last updated: ${readable_date}" + html_output+="" + html_output+="

    " + html_output+="

    " + html_output+="eye" + html_output+=" ${views} " + html_output+="heart" + html_output+=" ${like_count} " + html_output+="reply" + html_output+=" ${reply_count} " + html_output+="

    " + html_output+="
  • " +done + +# Insert the HTML output between the comments in index.html +sed -i '' '//,//{//!d;}; //r /dev/stdin' /Volumes/Git/privacyguides.org/site/en/index.html <<< "$html_output" + +# URL of the Discourse latest.json +DISCOURSE_URL="https://discuss.privacyguides.net/latest.json" + +# Fetch the JSON data +json_data=$(curl -s $DISCOURSE_URL) + +# Extract the first 12 topics +topics=$(echo $json_data | jq -r '.topic_list.topics[:12]') + +# Generate HTML for the first 12 posts +html_output="" +for row in $(echo "${topics}" | jq -r '.[] | @base64'); do + _jq() { + echo ${row} | base64 --decode | jq -r ${1} + } + + title=$(_jq '.title') + id=$(_jq '.id') + like_count=$(_jq '.like_count') + reply_count=$(_jq '.posts_count') + views=$(_jq '.views') + last_poster_username=$(_jq '.last_poster_username') + last_posted_at=$(_jq '.last_posted_at') + readable_date=$($DATE_CMD -d "$last_posted_at" +"%B %d, %Y %H:%M") + + html_output+="
  • " + html_output+="

    ${title}

    " + html_output+="
    " + html_output+="

    " + html_output+="" + html_output+="${last_poster_username}" + html_output+=" Last updated: ${readable_date}" + html_output+="" + html_output+="

    " + html_output+="

    " + html_output+="eye" + html_output+=" ${views} " + html_output+="heart" + html_output+=" ${like_count} " + html_output+="reply" + html_output+=" ${reply_count} " + html_output+="

    " + html_output+="
  • " +done + +# Insert the HTML output between the comments in index.html +sed -i '' '//,//{//!d;}; //r /dev/stdin' /Volumes/Git/privacyguides.org/site/en/index.html <<< "$html_output" diff --git a/theme/assets/javascripts/discourse-topics.js b/theme/assets/javascripts/discourse-topics.js deleted file mode 100644 index 1a070aef..00000000 --- a/theme/assets/javascripts/discourse-topics.js +++ /dev/null @@ -1,167 +0,0 @@ -/** - * @overview Generates a list of topics on a Discourse forum. - * @author Jonah Aragon - * @version 3.1.0 - * @license - * Copyright (c) 2023 - 2024 Jonah Aragon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -async function getData(url) { - const response = await fetch(url); - return response.json() -} - -async function main() { - const elements = document.querySelectorAll("ul[data-forum]"); - - for (let j = 0; j < elements.length; j++) { - - var topics = elements[j]; - var dataset = topics.dataset; - - console.log("Fetching data from " + dataset.feed) - const data = await getData(dataset.feed); - var list = data['topic_list']['topics']; - var profiles = data['users']; - var count = dataset.count; - - for (var i = 0; i < count; i++) { - - if (list[i]['pinned'] == true) { - count++; - continue; - } - - var title = list[i]['title']; - var id = list[i]['id']; - - var topic = document.createElement("li"); - topic.className = "discourse-topic"; - - var h3 = document.createElement('p'); - h3.className = "discourse-title"; - var a1 = document.createElement('a'); - - a1.href = dataset.forum + '/t/' + id; - - var boldTitle = document.createElement('strong'); - boldTitle.innerText = title; - a1.appendChild(boldTitle); - h3.appendChild(a1); - - var authorinfo = document.createElement('p'); - authorinfo.className = "discourse-author"; - - var author_id = list[i]['posters'][0]['user_id']; - var author_data = profiles.find(profile => profile['id'] == author_id); - var author = document.createElement('span'); - author.className = "discourse-author"; - var avatar = document.createElement('img'); - avatar.src = dataset.forum + author_data['avatar_template'].replace("{size}", "40"); - avatar.width = 20; - avatar.height = 20; - avatar.className = "middle"; - author.appendChild(avatar); - var namespan = document.createElement('span'); - namespan.innerText = " Posted by " + author_data['username']; - author.appendChild(namespan); - authorinfo.appendChild(author); - - var postinfo = document.createElement('p'); - postinfo.className = "discourse-data"; - - var dateIcon = document.createElement('span'); - dateIcon.className = "twemoji"; - dateIcon.innerHTML = ''; - - var date = document.createElement('span'); - date.className = "discourse-date"; - var datestring = list[i]['bumped_at']; - var dateobject = new Date(datestring); - var now = new Date(); - var diff = now - dateobject; - var minutes = Math.floor(diff / 60000); - var hours = Math.floor(minutes / 60); - var days = Math.floor(hours / 24); - if (days > 0) { - if (days == 1) { - date.innerText = " 1 day ago "; - } - else { - date.innerText = " " + days + " days ago "; - } - } - else if (hours > 0){ - if (hours == 1) { - date.innerText = " 1 hour ago "; - } - else { - date.innerText = " " + hours + " hours ago "; - } - } - else { - if (minutes == 1) { - date.innerText = " 1 minute ago "; - } - else { - date.innerText = " " + minutes + " minutes ago "; - } - } - postinfo.appendChild(dateIcon); - postinfo.appendChild(date); - - var likesicon = document.createElement('span'); - likesicon.classList = "twemoji pg-red"; - likesicon.innerHTML = ''; - - var likes = document.createElement('span'); - likes.className = "discourse-likes"; - likes.innerText = " " + list[i]['like_count'] + " "; - postinfo.appendChild(likesicon); - postinfo.appendChild(likes); - - var replyIcon = document.createElement('span'); - replyIcon.classList = "twemoji"; - replyIcon.innerHTML = ''; - - var replies = document.createElement('span'); - replies.className = "discourse-replies"; - - var reply_count = list[i]['posts_count'] - 1; - if (reply_count == 1) { - replies.innerText = "1 Reply" - } - else { - replies.innerText = " " + reply_count - } - postinfo.appendChild(replyIcon); - postinfo.appendChild(replies); - - topic.appendChild(h3); - topic.appendChild(document.createElement('hr')); - topic.appendChild(authorinfo); - topic.appendChild(postinfo); - topics.appendChild(topic); - } - } -} - -main(); diff --git a/theme/home.html b/theme/home.html index 018d9345..3fa6a186 100644 --- a/theme/home.html +++ b/theme/home.html @@ -52,11 +52,10 @@ {% if config.theme.language == "en" %}

    Top discussions this week

    -
      +
        + + +
    @@ -103,11 +102,10 @@

    Latest discussions

    -
      +
        + + +
    {% endif %} {% endblock %} -{% block scripts %} - - {{ super() }} -{% endblock %} From f55170a83bf01feb1885eae4719d40f08196c94d Mon Sep 17 00:00:00 2001 From: Jonah Aragon Date: Sat, 28 Sep 2024 03:25:46 -0500 Subject: [PATCH 2/2] Add privacyguides.net homepage --- index-generation.sh | 82 +++++++----------- mkdocs.net.yml | 197 ++++++++++++++++++++++++++++++++++++++++++++ net/index.md | 42 ++++++++++ 3 files changed, 270 insertions(+), 51 deletions(-) create mode 100644 mkdocs.net.yml create mode 100644 net/index.md diff --git a/index-generation.sh b/index-generation.sh index c98af91d..e2143e1d 100755 --- a/index-generation.sh +++ b/index-generation.sh @@ -7,14 +7,42 @@ if [[ "$OSTYPE" == "darwin"* ]]; then DATE_CMD="gdate" fi +# Defaults +source="https://discuss.privacyguides.net/top.json?period=weekly" +tag="top posts" +destination="./site/en/index.html" +count=3 + +for arg in "$@" +do + case $arg in + --source=*) + source="${arg#*=}" + shift + ;; + --tag=*) + tag="${arg#*=}" + shift + ;; + --destination=*) + destination="${arg#*=}" + shift + ;; + --count=*) + count="${arg#*=}" + shift + ;; + esac +done + # URL of the Discourse top.json -DISCOURSE_URL="https://discuss.privacyguides.net/top.json?period=weekly" +DISCOURSE_URL="$source" # Fetch the JSON data json_data=$(curl -s $DISCOURSE_URL) # Extract the first 3 topics -topics=$(echo $json_data | jq -r '.topic_list.topics[:3]') +topics=$(echo $json_data | jq -r ".topic_list.topics[:$count]") # Generate HTML for the first 3 posts html_output="" @@ -53,52 +81,4 @@ for row in $(echo "${topics}" | jq -r '.[] | @base64'); do done # Insert the HTML output between the comments in index.html -sed -i '' '//,//{//!d;}; //r /dev/stdin' /Volumes/Git/privacyguides.org/site/en/index.html <<< "$html_output" - -# URL of the Discourse latest.json -DISCOURSE_URL="https://discuss.privacyguides.net/latest.json" - -# Fetch the JSON data -json_data=$(curl -s $DISCOURSE_URL) - -# Extract the first 12 topics -topics=$(echo $json_data | jq -r '.topic_list.topics[:12]') - -# Generate HTML for the first 12 posts -html_output="" -for row in $(echo "${topics}" | jq -r '.[] | @base64'); do - _jq() { - echo ${row} | base64 --decode | jq -r ${1} - } - - title=$(_jq '.title') - id=$(_jq '.id') - like_count=$(_jq '.like_count') - reply_count=$(_jq '.posts_count') - views=$(_jq '.views') - last_poster_username=$(_jq '.last_poster_username') - last_posted_at=$(_jq '.last_posted_at') - readable_date=$($DATE_CMD -d "$last_posted_at" +"%B %d, %Y %H:%M") - - html_output+="
  • " - html_output+="

    ${title}

    " - html_output+="
    " - html_output+="

    " - html_output+="" - html_output+="${last_poster_username}" - html_output+=" Last updated: ${readable_date}" - html_output+="" - html_output+="

    " - html_output+="

    " - html_output+="eye" - html_output+=" ${views} " - html_output+="heart" - html_output+=" ${like_count} " - html_output+="reply" - html_output+=" ${reply_count} " - html_output+="

    " - html_output+="
  • " -done - -# Insert the HTML output between the comments in index.html -sed -i '' '//,//{//!d;}; //r /dev/stdin' /Volumes/Git/privacyguides.org/site/en/index.html <<< "$html_output" +sed -i '' "//,//{//!d;}; //r /dev/stdin" $destination <<< "$html_output" diff --git a/mkdocs.net.yml b/mkdocs.net.yml new file mode 100644 index 00000000..ee7ccf75 --- /dev/null +++ b/mkdocs.net.yml @@ -0,0 +1,197 @@ +# Copyright (c) 2022-2024 Jonah Aragon + +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +docs_dir: "net" +site_url: "https://www.privacyguides.net/" +site_dir: "site/net" + +site_name: Privacy Guides Community +site_description: "Discover privacy tools and resources, ask questions, and stay informed at the biggest digital rights and privacy tech community online." +edit_uri_template: blob/main/net/{path}?plain=1 + +extra: + privacy_guides: + footer: + intro: + !ENV [ + FOOTER_INTRO, + "Privacy Guides is a non-profit, socially motivated website that provides information for protecting your data security and privacy.", + ] + note: + !ENV [ + FOOTER_NOTE, + "We do not make money from recommending certain products, and we do not use affiliate links.", + ] + copyright: + author: + !ENV [FOOTER_COPYRIGHT_AUTHOR, "Privacy Guides and contributors."] + date: !ENV [FOOTER_COPYRIGHT_DATE, "2019-2024"] + license: + - fontawesome/brands/creative-commons + - fontawesome/brands/creative-commons-by + - fontawesome/brands/creative-commons-sa + homepage: https://www.privacyguides.org/en/ + generator: false + context: !ENV [BUILD_CONTEXT, "production"] + offline: !ENV [BUILD_OFFLINE, false] + deploy: !ENV DEPLOY_ID + social: + - icon: simple/mastodon + link: https://mastodon.neat.computer/@privacyguides + name: !ENV [SOCIAL_MASTODON, "Mastodon"] + - icon: simple/matrix + link: https://matrix.to/#/#privacyguides:matrix.org + name: !ENV [SOCIAL_MATRIX, "Matrix"] + - icon: simple/discourse + link: https://discuss.privacyguides.net/ + name: !ENV [SOCIAL_FORUM, "Forum"] + - icon: simple/github + link: https://github.com/privacyguides + name: !ENV [SOCIAL_GITHUB, "GitHub"] + - icon: simple/torbrowser + link: http://www.xoe4vn5uwdztif6goazfbmogh6wh5jc4up35bqdflu6bkdc5cas5vjqd.onion/ + name: !ENV [SOCIAL_TOR_SITE, "Hidden service"] + +repo_url: + !ENV [BUILD_REPO_URL, "https://github.com/privacyguides/privacyguides.org"] +repo_name: "" + +theme: + name: material + language: en + custom_dir: theme + font: + text: Public Sans + code: DM Mono + palette: + - media: "(prefers-color-scheme)" + scheme: default + accent: deep purple + toggle: + icon: material/brightness-auto + name: !ENV [THEME_DARK, "Switch to dark mode"] + - media: "(prefers-color-scheme: dark)" + scheme: slate + accent: amber + toggle: + icon: material/brightness-2 + name: !ENV [THEME_LIGHT, "Switch to light mode"] + - media: "(prefers-color-scheme: light)" + scheme: default + accent: deep purple + toggle: + icon: material/brightness-5 + name: !ENV [THEME_AUTO, "Switch to system theme"] + favicon: assets/brand/logos/png/favicon-32x32.png + icon: + repo: simple/github + features: + - announce.dismiss + - navigation.tracking + - navigation.tabs + - navigation.sections + - navigation.expand + - navigation.path + - navigation.indexes + - navigation.footer + - content.action.edit + - content.tabs.link + - content.tooltips + - search.highlight + +extra_css: + - assets/stylesheets/extra.css?v=20240829 + +watch: + - theme + - includes + +plugins: + tags: {} + privacy: + enabled: !ENV [BUILD_PRIVACY, true] + offline: + enabled: !ENV [BUILD_OFFLINE, false] + group: + enabled: !ENV [BUILD_INSIDERS, true] + plugins: + macros: {} + meta: {} + optimize: + enabled: !ENV [OPTIMIZE, PRODUCTION, NETLIFY, false] + typeset: {} + social: + cards: !ENV [CARDS, true] + cards_dir: assets/img/social + cards_layout_dir: theme/layouts + cards_layout: page + +markdown_extensions: + admonition: {} + pymdownx.details: {} + pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + pymdownx.tabbed: + alternate_style: true + pymdownx.arithmatex: + generic: true + pymdownx.critic: {} + pymdownx.caret: {} + pymdownx.keys: {} + pymdownx.mark: {} + pymdownx.tilde: {} + pymdownx.snippets: + auto_append: + - !ENV [BUILD_ABBREVIATIONS, "includes/abbreviations.en.txt"] + pymdownx.tasklist: + custom_checkbox: true + attr_list: {} + def_list: {} + md_in_html: {} + meta: {} + abbr: {} + pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + tables: {} + footnotes: {} + toc: + permalink: true + toc_depth: 4 + +nav: + - !ENV [NAV_HOME, "Home"]: https://www.privacyguides.org/en/ + - !ENV [NAV_KNOWLEDGE_BASE, "Knowledge Base"]: + https://www.privacyguides.org/en/basics/why-privacy-matters/ + - !ENV [NAV_RECOMMENDATIONS, "Recommendations"]: + https://www.privacyguides.org/en/tools/ + - !ENV [NAV_BLOG, "Articles"]: https://www.privacyguides.org/articles/ + - !ENV [NAV_ABOUT, "About"]: https://www.privacyguides.org/en/about/ + - "Donate": https://www.privacyguides.org/en/about/donate/ + - !ENV [NAV_CHANGELOG, "Changelog"]: + "https://github.com/privacyguides/privacyguides.org/releases" + - !ENV [NAV_FORUM, "Forum"]: "https://discuss.privacyguides.net/" + +validation: + nav: + not_found: info diff --git a/net/index.md b/net/index.md new file mode 100644 index 00000000..198287dc --- /dev/null +++ b/net/index.md @@ -0,0 +1,42 @@ +--- +title: Weekly Discussions +meta_title: Privacy Guides Community +hide: + - footer + - toc + - navigation +schema: + - + "@context": https://schema.org + "@type": Organization + "@id": https://www.privacyguides.org/ + name: Privacy Guides + url: https://www.privacyguides.org/ + logo: https://www.privacyguides.org/en/assets/brand/logos/png/square/pg-yellow.png + sameAs: + - https://twitter.com/privacy_guides + - https://github.com/privacyguides + - https://www.wikidata.org/wiki/Q111710163 + - https://www.youtube.com/@privacyguides + - https://mastodon.neat.computer/@privacyguides + - + "@context": https://schema.org + "@type": WebSite + name: Privacy Guides + alternateName: ["Privacy Guides Community", "Privacy & Security Forum", "Privacy Discussions", "Privacy Community", "PG Community"] + url: "https://www.privacyguides.net/" + isPartOf: "https://www.privacyguides.org/" +--- + +Discover privacy tools and resources, ask questions, and stay informed at the biggest digital rights and privacy tech community online. + +[Open Forum](https://discuss.privacyguides.net){.md-button .md-button--primary} +[View Resources](https://www.privacyguides.org/en/tools/){.md-button} + +
    +
      + + + +
    +