diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..eca90bc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,52 @@ +on: + workflow_dispatch: + schedule: + - cron: "30 0 1 * *" + +jobs: + TemplateTransparencyReport: + runs-on: ubuntu-latest + name: Template the transparency report for iv-org + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.head_ref }} + + - name: "Fetch data for report" + uses: syeopite/transparency-data-fetcher-for-iv-org@v1.1 + id: data_fetch_step + with: + github-token: ${{ github.token }} + + - name: "Setup python for templating report" + uses: actions/setup-python@v2 + with: + python-version: 3.9.5 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r src/requirements.txt + + - name: Template report + run: | + python src/generate.py '${{ steps.data_fetch_step.outputs.fetched-btc-bounty-data }}' + + # Auto commit resulting md file + - name: "Auto commiting resulting markdown instance list" + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Template transparency report for ${date -d "$(date +%Y-%m)-15 last month" '+%Y-%m'} + file_pattern: ${date -d "$(date +%Y-%m)-15 last month" '+%Y-%m'}.md + + # https://github.com/iv-org/invidious/blob/ad7fefae1ca0b734fbe986eb8bb13f1996e2f5f8/.github/workflows/monthly_release.yml#L13 + - id: fetch_date + run: echo ::set-output name=date::$(date -d "$(date +%Y-%m)-15 last month" '+%B-%Y') + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v3 + with: + delete-branch: true + body: This is the template for the ${{ steps.fetch_date.outputs.date }} transparency report + title: ${{ steps.fetch_date.outputs.date }} transparency report + branch: ${{ steps.fetch_date.outputs.date }}-Report diff --git a/src/generate.py b/src/generate.py new file mode 100644 index 0000000..2368004 --- /dev/null +++ b/src/generate.py @@ -0,0 +1,101 @@ +import datetime +import json +import re +import sys +from urllib import request + +from dateutil.parser import isoparse +from dateutil.relativedelta import relativedelta +from mdutils.mdutils import MdUtils + +conversation_rate_in_time_regex = re.compile(r"avg: [$€](?P\d+)", re.MULTILINE) + + +def get_coin_conversion_rate(fiat, date=None): + # Request the converstion rate between BTC and the selected fiat currency + url = f"https://{fiat}.rate.sx/" + if date: + date = isoparse(date) + url += f"BTC@{date.strftime('%Y-%m-%d+%Hh%Mm%Ss')}" \ + f"?T&q" + else: + url += "1BTC" + + with request.urlopen(url) as connection: + conversion = connection.read().decode("utf-8") + if date: + return float(conversation_rate_in_time_regex.search(conversion)["rate"]) + else: + return float(conversion) + + +def get_fiat_conversion_rate(fiat_a, fiat_b, date=None): + # Request frankfurter.app for the converstion rate between two currencies. + # + # Parameters: + # fiat_a: Fiat A (to convert from) + # fiat_b: Fiat B (to convert two) + # date: + # If specified, requests the converstion rate between the two given currencies at the given + # + url = f"https://api.frankfurter.app" + if date: + date = isoparse(date) + url += f"/{date.strftime('%Y-%m-%d')}" + else: + url += "/latest" + url += f"?from={fiat_a}&to={fiat_b}" + with request.urlopen(url) as connection: + return json.load(connection)["rates"][fiat_b.upper()] + + +current_time = datetime.datetime.utcnow() +with open("src/known-data.json", "r") as file: + known_data = json.load(file) +new_transparency_data = json.loads(sys.argv[1]) + +# Calculate new funds +current_funds = known_data["total_current_btc_funds"] + new_transparency_data["new_btc_previous_month"] +for bounty in new_transparency_data["bounty_costs"]: + current_funds - float(bounty["bounty_cost_crypto"].strip(" BTC")) + +usd_to_btc = get_coin_conversion_rate("usd") +eur_to_btc = get_coin_conversion_rate("eur") +btc_price_str = f"~€{round(eur_to_btc, 2)} or \~${round(usd_to_btc, 2)}" + +# Create header +md = MdUtils(file_name=f"finance/{(current_time - relativedelta(months=1)).strftime('%Y-%m')}.md") +md.new_header(level=1, title=f"Finances for {(current_time - relativedelta(months=1)).strftime('%B %Y')}") + +# Donations section +md.new_header(level=2, title="Donations:") +if not new_transparency_data["new_btc_previous_month"]: + md.new_paragraph("Bitcoin (BTC): None") +else: + md.new_paragraph(f"Bitcoin (BTC): {new_transparency_data['new_btc_previous_month']} BTC worth" + f" ~€{round(new_transparency_data['new_btc_previous_month'] * eur_to_btc, 2)}" + f" at the time of publishing (Bitcoin price {btc_price_str})") + +md.new_paragraph("Monero (XMR): X XMR worth ~€X at the time of publishing (Monero price \~€X or \~$X)") + +md.new_header(level=2, title="Expenses:") +for bounty in new_transparency_data["bounty_costs"]: + usd_to_btc_rate_at_time = get_coin_conversion_rate("usd", date=bounty['date']) + usd_to_eur_rate_at_time = get_fiat_conversion_rate("usd", "eur", date=bounty['date']) + usd_bounty_cost = float(bounty['bounty_cost_crypto'].strip(' BTC')) * usd_to_btc_rate_at_time + + md.new_paragraph(f"Bounty ({bounty['url']}): {bounty['bounty_cost_crypto']} worth ~ " + f"€{round(usd_bounty_cost * usd_to_eur_rate_at_time, 2)} (~${round(usd_bounty_cost, 2)})") + +md.new_header(level=2, title="Current funds:") +md.new_paragraph(f"Bitcoin (BTC): {current_funds} BTC worth ~€{round(current_funds * eur_to_btc, 2)} " + f"(\~${round(current_funds * usd_to_btc, 2)}) at the time of publishing " + f"(Bitcoin price {btc_price_str})") + +md.new_paragraph("Monero (XMR): X XMR worth ~€X (\~$X) at the time of publishing (Monero price ~€X or \~$X)") +md.create_md_file() + +# Now we update the known data +known_data["total_current_btc_funds"] = current_funds +with open("src/known-data.json", "w") as file: + json.dump(known_data, file) diff --git a/src/known-data.json b/src/known-data.json new file mode 100644 index 0000000..af1299c --- /dev/null +++ b/src/known-data.json @@ -0,0 +1 @@ +{"total_current_btc_funds": 0.30957846} \ No newline at end of file diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 0000000..3538567 --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1,5 @@ +dateutils==0.6.12 +mdutils==1.3.1 +python-dateutil==2.8.2 +pytz==2021.1 +six==1.16.0