Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Add list of monthly/annual members to website #2927

Draft
wants to merge 17 commits into
base: main
Choose a base branch
from
Draft
2 changes: 2 additions & 0 deletions .github/workflows/build-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ jobs:
continue-on-error: false
privileged: ${{ fromJSON(needs.metadata.outputs.privileged) }}
strict: true
secrets:
RO_DISCOURSE_API_KEY: ${{ secrets.RO_DISCOURSE_API_KEY }}

build_i18n:
if: ${{ contains(github.event.pull_request.labels.*.name, 'ci:build i18n') }}
Expand Down
27 changes: 23 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ on:
cache:
type: boolean
default: true
secrets:
RO_DISCOURSE_API_KEY:
required: false

permissions:
contents: read
Expand Down Expand Up @@ -172,23 +175,31 @@ jobs:
sudo apt install pngquant
echo "EXTRA_FLAGS=""$EXTRA_FLAGS" --cmd=mkdocs"" >> "$GITHUB_ENV"

- name: Generate Donating Members List
continue-on-error: true
env:
DISCOURSE_API_KEY: ${{ secrets.RO_DISCOURSE_API_KEY }}
run: |
pip install requests
python generate-members.py > includes/members.md

- name: Build Website
run: |
eval ./run.sh --build --lang=${{ inputs.lang }} "$EXTRA_FLAGS"

- name: Run index-generation.sh for top posts
- name: Run generate-topics.sh for top posts
if: inputs.lang == 'en'
run: |
bash index-generation.sh \
bash generate-topics.sh \
--source='https://discuss.privacyguides.net/top.json?period=weekly' \
--tag="top posts" \
--destination="./site/en/index.html" \
--count=3

- name: Run index-generation.sh for latest posts
- name: Run generate-topics.sh for latest posts
if: inputs.lang == 'en'
run: |
bash index-generation.sh \
bash generate-topics.sh \
--source='https://discuss.privacyguides.net/latest.json' \
--tag="latest posts" \
--destination="./site/en/index.html" \
Expand Down Expand Up @@ -259,6 +270,14 @@ jobs:
path: site-${{ inputs.config }}-${{ inputs.lang }}.tar.gz
retention-days: 1

- name: Upload members list
uses: actions/upload-artifact@v4
if: inputs.lang == 'en'
with:
name: members.md
path: includes/members.md
retention-days: 1

offline_package:
if: inputs.config == 'offline' && inputs.lang == 'en'
needs: build
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ jobs:
context: production
continue-on-error: false
cache: false
secrets:
RO_DISCOURSE_API_KEY: ${{ secrets.RO_DISCOURSE_API_KEY }}

build_blog:
needs: submodule
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/update-discussions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,17 @@ jobs:
source: /en/index.html
target: ./site/en/

- name: Run index-generation.sh for top posts
- name: Run generate-topics.sh for top posts
run: |
bash index-generation.sh \
bash generate-topics.sh \
--source='https://discuss.privacyguides.net/top.json?period=weekly' \
--tag="top posts" \
--destination="./site/en/index.html" \
--count=3

- name: Run index-generation.sh for latest posts
- name: Run generate-topics.sh for latest posts
run: |
bash index-generation.sh \
bash generate-topics.sh \
--source='https://discuss.privacyguides.net/latest.json' \
--tag="latest posts" \
--destination="./site/en/index.html" \
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ node_modules
.venv
.env
.mkdocs-insiders-*

# Automatically generated
includes/members.md
1 change: 1 addition & 0 deletions .vscode/ltex.dictionary.en-US.txt
Original file line number Diff line number Diff line change
Expand Up @@ -510,3 +510,4 @@ Subprocessor
Subprocessors
Triplebit
Fediverse
Safing
1 change: 0 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ mkdocs-macros-plugin = "~=1.0"
jieba = "~=0.42"
mkdocs-rss-plugin = "*"
mkdocs-glightbox = "*"
mkdocs-minify-html-plugin = "*"

[dev-packages]
scour = "~=0.38"
Expand Down
217 changes: 4 additions & 213 deletions Pipfile.lock

Large diffs are not rendered by default.

96 changes: 78 additions & 18 deletions docs/about/donate.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,90 @@ description: The charitable mission of Privacy Guides relies on contributions fr
<!-- markdownlint-disable MD036 -->
Donate to Privacy Guides and support our mission to defend digital rights and spread the word about mass surveillance programs and other daily privacy invasions. You can help Privacy Guides researchers, activists, and maintainers create informative content, host private digital services, and protect privacy rights at a time when the world needs it most.

Privacy Guides has been a nonstop effort for over 5 years to stay up to date with the world of cybersecurity and privacy, and to promote the benefits of privacy overall. This is a **non-profit, community-driven** project that would not be possible without the generous support of all our [contributors](contributors.md).
[:material-heart:{ .pg-red } Become a Member](https://donate.magicgrants.org/privacyguides/membership){ class="md-button md-button--primary" }
[:material-hand-coin: Make a Donation](https://donate.magicgrants.org/privacyguides/donate/privacyguides){ class="md-button md-button--primary" }

## Donate
<small markdown>

MAGIC Grants is our fiscal host, and their custom, open-source donation platform allows you to donate to our project with **Monero**, **Bitcoin**, or **debit/credit card**.
MAGIC Grants is our fiscal host, and their custom, open-source donation platform allows you to donate to our project with **Monero**, **Bitcoin**, or **debit/credit card**. You can also donate using [:simple-github: GitHub Sponsors](https://github.com/sponsors/privacyguides).

[:material-heart:{ .pg-red } Donate](https://donate.magicgrants.org/privacyguides){ class="md-button md-button--primary" }
[Sponsor on GitHub](https://github.com/sponsors/privacyguides){ class="md-button" }
</small>

Donating with Monero will maximize your donation by lowering our transaction fees while simultaneously [preserving your privacy](../cryptocurrency.md), win-win! You can also donate to us via GitHub Sponsors if you prefer, or if you would like to publicize your support. GitHub does not charge us any fees if you donate as an individual, but may charge us fees if you donate with a GitHub organization, if this is a concern for you.
## Organizational Members

## How We Use Donations
Thank you to those who have significantly supported Privacy Guides. A membership offers your organization the opportunity to join our movement for a more private future. (1)
{ .annotate }

Privacy Guides is a **non-profit** project. Your donation will go to a [dedicated fund](https://magicgrants.org/funds/privacy_guides) within [MAGIC Grants](https://magicgrants.org), a 501(c)(3) organization and our fiscal host. The funds will **only** be used for this project specifically.
1. Please contact <info@magicgrants.org> to inquire about giving. This is not a guarantee or transaction, and Privacy Guides reserves the right to rescind the membership of those who are unaligned with our mission or organization at any time.

<div class="mdx-specialthanks" markdown>

[![Power Up Privacy]](https://powerupprivacy.com){ rel=nofollow target=_blank title="Power Up Privacy" }

[Power Up Privacy]: ../assets/img/donors/power-up-privacy.webp

</div>

### Past Supporters

- [Safing](https://safing.io){ rel=nofollow target=_blank }: 2019 – 2021

## Active Members

Privacy Guides would not be possible without those generous enough to donate on a monthly or yearly basis. (1)
{ .annotate }

1. If you become a member and [link your donation](https://discuss.privacyguides.net/t/getting-your-member-flair-on-the-forum/25453) to your forum account, you're automatically added here with a link to your profile and avatar to show your support for Privacy Guides. If you link your forum account but don't set your flair or title, you'll be a silent +1. You can change your visibility any time. This chart is updated upon each website release.

<div class="mdx-donors" data-mdx-component="donors">
<div class="mdx-donors__list">

--8<-- "includes/members.md"

</div>
</div>

<small markdown>

This is a list of our **active** [members](https://donate.magicgrants.org/privacyguides/membership), plus donors on GitHub, who have chosen to make their donation public. Hundreds more have donated in the past or privately, and their support is hugely appreciated as well.

</small>

## Merchandise

Another option to support us is by buying our merchandise from HelloTux. We get a small commission for each item sold, and you get a quality product to show for it.

[Buy on HelloTux.com](https://hellotux.com/privacyguides){ class="md-button" }

## Non-Financial Support

It takes a lot of [people](contributors.md) and [work](https://github.com/privacyguides/privacyguides.org/pulse/monthly) to keep Privacy Guides up to date and spread the word about privacy and mass surveillance. If you're looking for other ways to help out, consider getting involved by [editing the site](https://github.com/privacyguides/privacyguides.org), [joining our forum](https://discuss.privacyguides.net), or [contributing translations](https://crowdin.com/project/privacyguides).

## FAQ

### What is an organizational membership?

Organizational membership to Privacy Guides is open to any company, private foundation, or organization that donates at least $5,000 per year and agrees to our membership pledge (below). While Privacy Guides does not endorse private companies or their products, we're grateful for their contributions. As a 501(c)(3) public charity the donation may be tax-deductible, and we will provide you with a receipt.

You can become an organizational member by reaching out to <info@magicgrants.org> for more information.

*Pledge*: By supporting Privacy Guides we share a commitment to improving access to privacy-friendly technology and education to all people around the world, without discrimination on the basis of race, religion, color, national origin, ancestry, physical disability, mental disability, medical condition, genetic information, marital status, sex, gender, gender identity, gender expression, or age. We also understand that Privacy Guides does not endorse private companies or their products or services, regardless of organizational membership status. We will not use Privacy Guides badges or any other branding in a way which implies that Privacy Guides has endorsed our organization.

### How are organizational members recognized?

Organizational members that choose to be recognized publicly are included in our organizational members section (above), and occasionally at other opportunities where appropriate. Organizational member links include the rel="nofollow" attribute: We adopted this policy to screen out potential abuse of our program and site to raise the rank of third parties in search algorithms. Unfortunately, this is a growing problem for nonprofits. This was a complex decision since we know many of the sincere supporters behind these companies, but we decided that it was the best choice for us.

### What is an active membership?

Your monthly or yearly membership sustains Privacy Guides's services and public activism for privacy and cybersecurity year round. If you become a member we will recognize your support here on our website and our community forum, and occasionally in other areas like our videos, if you choose to make your membership publicly known.

Our membership program is brand new, and we are still exploring other ways that we can share a token of our appreciation with you, while maintaining sustainable and ethical boundaries. Stay tuned!

### How does Privacy Guides use donations?

Privacy Guides has been a nonstop effort for over 5 years to stay up to date with the world of cybersecurity and privacy, and to promote the benefits of privacy overall. This is a **non-profit, community-driven** project that would not be possible without the generous support of all our [contributors](contributors.md), in addition to our regularly donating members above.

Your donation go to a [dedicated fund](https://magicgrants.org/funds/privacy_guides) within [MAGIC Grants](https://magicgrants.org), a 501(c)(3) organization and our fiscal host. The funds will **only** be used for this project specifically.

You may qualify for a tax deduction. When you donate to us [here](https://donate.magicgrants.org/privacyguides) with cryptocurrency or card you have the option to receive a receipt from MAGIC Grants for this purpose. If you have questions about other transactions please email <info@magicgrants.org>.

Expand Down Expand Up @@ -47,13 +117,3 @@ We use donations for a variety of purposes, including:
Thank you to all those who support our mission! :material-heart:{ .pg-red }

We strictly **cannot** use donations to support political campaigns/candidates or attempt to influence legislation. Earnings also will **not** inure to the benefit of any private shareholder or individual.

## Merchandise

Another option to support us is by buying our merchandise from HelloTux. We get a small commission for each item sold, and you get a quality product to show for it.

[Buy on HelloTux.com](https://hellotux.com/privacyguides){ class="md-button" }

## Non-Financial Support

It takes a lot of [people](contributors.md) and [work](https://github.com/privacyguides/privacyguides.org/pulse/monthly) to keep Privacy Guides up to date and spread the word about privacy and mass surveillance. If you're looking for other ways to help out, consider getting involved by [editing the site](https://github.com/privacyguides/privacyguides.org), [joining our forum](https://discuss.privacyguides.net), or [contributing translations](https://crowdin.com/project/privacyguides).
93 changes: 93 additions & 0 deletions generate-members.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import requests
import os

GITHUB_API_URL = "https://api.github.com/graphql"
GITHUB_TOKEN = os.getenv("GH_TOKEN")
ORG_NAME = "privacyguides"

# Fetch members from the API
members_api_url = "https://discuss.privacyguides.net/g/members/members.json?offset=0&order=added_at&asc=true"
headers = {
"Api-Key": os.getenv("DISCOURSE_API_KEY"),
"Api-Username": "system"
}
members_response = requests.get(members_api_url, headers=headers)
members_data = members_response.json()

if 'members' not in members_data:
raise KeyError("Response JSON does not contain 'members' key")

members = members_data['members']
private_members_count = 0

html_output = ""
for member in members:
flair_name = member.get('flair_name')
title = member.get('title')
if flair_name == "members" or title == "Member":
username = member['username']
avatar_template = member['avatar_template']
avatar_url = f"https://discuss.privacyguides.net{avatar_template.replace('{size}', '128')}"
profile_url = f"https://discuss.privacyguides.net/u/{username}"
html_output += f'<a href="{profile_url}" target="_blank" title="@{username}" class="mdx-donors__item"><img loading="lazy" src="{avatar_url}"></a>'
else:
private_members_count += 1

# print(html_output)

query = """
{
organization(login: "%s") {
sponsorshipsAsMaintainer(first: 100) {
nodes {
sponsorEntity {
... on User {
login
avatarUrl
url
}
... on Organization {
login
avatarUrl
url
}
}
createdAt
}
}
}
}
""" % ORG_NAME

headers = {
"Authorization": f"Bearer {GITHUB_TOKEN}",
"Content-Type": "application/json"
}

response = requests.post(GITHUB_API_URL, json={'query': query}, headers=headers)
data = response.json()

if 'errors' in data:
raise Exception(f"GraphQL query failed with errors: {data['errors']}")
if 'data' not in data:
raise KeyError(f"Response JSON does not contain 'data' key: {data}")

sponsors = data['data']['organization']['sponsorshipsAsMaintainer']['nodes']

# Sort sponsors by the date they began their sponsorship
sponsors.sort(key=lambda x: x['createdAt'])

for sponsor in sponsors:
sponsor_entity = sponsor['sponsorEntity']
login = sponsor_entity['login']
avatar_url = sponsor_entity['avatarUrl']
url = sponsor_entity['url']
html_output += f'<a href="{url}" title="@{login}" rel="ugc nofollow" target="_blank" class="mdx-donors__item"><img loading="lazy" src="{avatar_url}&size=120"></a>'

private_members_count += 6

# Append the count of private members
if private_members_count > 0:
html_output += f'<a href="https://donate.magicgrants.org/privacyguides" class="mdx-donors__item mdx-donors__item--private">+{private_members_count}</a>'

print(html_output)
File renamed without changes.
9 changes: 4 additions & 5 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,11 @@ theme:
- search.highlight

extra_css:
- assets/stylesheets/extra.css?v=20240802
- assets/stylesheets/extra.css?v=20250306
extra_javascript:
- path: assets/javascripts/randomize-element.js?v=20240801
- path: assets/javascripts/randomize-element.js?v=20250306
defer: true
- path: assets/javascripts/feedback.js?v=20240801
- path: assets/javascripts/feedback.js?v=20250306
defer: true

watch:
Expand All @@ -305,7 +305,6 @@ plugins:
enabled: !ENV [BUILD_PRIVACY, true]
offline:
enabled: !ENV [BUILD_OFFLINE, false]
minify_html: {}
group:
enabled: !ENV [BUILD_INSIDERS, false]
plugins:
Expand Down Expand Up @@ -474,7 +473,7 @@ nav:
- "meta/uploading-images.md"
- "meta/git-recommendations.md"
- "meta/commit-messages.md"
- !ENV [NAV_DONATE, "Donate"]: https://donate.magicgrants.org/privacyguides
- !ENV [NAV_DONATE, "Donate"]: /en/about/donate/
- !ENV [NAV_FORUM, "Forum"]:
!ENV [NAV_FORUM_LINK, "https://discuss.privacyguides.net/"]

Expand Down
Binary file added theme/assets/img/donors/power-up-privacy.webp
Binary file not shown.
Loading