Code Monkey home page Code Monkey logo

energieprijzen's Introduction

☀️ energieprijzen Go Report Card

energieprijzen ("energy prices" in Dutch) is a Telegram bot that posts tomorrow's energy prices to a Telegram channel. If, like me, you have a dynamic contract ("dynamisch (energie)contract") at ANWB Energie, this bot could help you save both time and money.

You can interact with the bot directly at @energieprijzenbot. It doesn't do much, but it can tell you about your privacy rights when using the bot. The privacy policy is only available in Dutch for now, but the long and short of it is that I'm actively disinterested in your data.

🤖 Installation and usage

You likely won't need to run the bot yourself, as you can just join the channel or start a chat with the instance I set up (see above). However, if you want to run your own instance, follow these steps:

  1. Download the latest binary from the Releases page (linux/amd64 only for now, but it should build and run on other platforms as well).

  2. Create a config.json file with your Telegram bot token and chat ID:

    {
      "telegram": {
        "token": "your-telegram-bot-token",
        "chat_id": 123456789
      },
      "cronitor": {
        "telemetry_url": "https://cronitor.link/your/telemetry/endpoint"
      }
    }
    • The cronitor section is optional.
    • The chat ID can also be a string username if you prefer.
  3. Run the bot using the following command:

    ./energieprijzen

    It'll start an infinite loop, responding to incoming messages and posting the energy prices at the right time.

  4. To check the version number and build timestamp, run:

    ./energieprijzen -v

🔨 Contributing

If you have any suggestions or improvements, feel free to open an issue or a pull request. I'd be happy to hear from you!

energieprijzen's People

Contributors

heyajulia avatar dependabot[bot] avatar

energieprijzen's Issues

Create a price data chart

It'd be nice if the bot also sent a chart to make the data available in a different way that might be easier to scan, depending on context. I've been experimenting a bit with Seaborn, and I like what I've been able to do with it relatively quickly, although it's nowhere near as pretty as I'd like it to be, and it would be quite a challenge to use it from Go.

Warning

This chart does not contain the actual data; I generated it using random.uniform.

chart

WebAssembly research

I was researching WebAssembly to hopefully be able to run the bot on
Cloudflare Workers. However, sadly I never even got to the point where I could run it
anywhere (and I'm not blaming anyone but myself). This document serves as a log of my journey.

Installing wasmtime and building the bot for WebAssembly is a piece of cake...

curl https://wasmtime.dev/install.sh -sSf | bash
GOOS=wasip1 GOARCH=wasm go build -o main.wasm cmd/bot/main.go

...but running it is a different story

wasmtime --env ENERGIEPRIJZEN_BOT_TOKEN=somevalue --env ENERGIEPRIJZEN_BOT_CHAT_ID=somevalue main.wasm
2023/11/11 14:35:58 main.go:52: Get "https://api.energyzero.nl/v1/energyprices?fromDate=2023-11-11T22%3A00%3A00Z&inclBtw=true&interval=4&tillDate=2023-11-12T21%3A59%3A59.999Z&usageType=1": dial tcp: lookup api.energyzero.nl on [::1]:53: dial udp [::1]:53: Connection refused

Side-stepping the DNS issue

Hard-coding the/an IP address also doesn't work:

Minimal reproducible example
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	const ip = `93.184.216.34` // example.com

	req, err := http.NewRequest("GET", "http://"+ip, nil)
	if err != nil {
		panic(err)
	}
	req.Host = "example.com"

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	b, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}

	fmt.Println(string(b))
}
panic: Get "http://93.184.216.34": dial tcp 93.184.216.34:80: Connection refused

goroutine 1 [running]:
main.main()
        /workspaces/energieprijzen/main.go:20 +0x2e

stealthrocket/net to the rescue?

There's stealthrocket/net, which is mentioned in a
post on the Go blog, but it doesn't seem to work for my use case:

import (
	// everything is the same as in the minimal reproducible example, except I've added this import:
	_ "github.com/stealthrocket/net/http"
)
Error: failed to run main module `main.wasm`

Caused by:
    0: failed to instantiate "main.wasm"
    1: unknown import: `wasi_snapshot_preview1::sock_open` has not been defined

The future is looking bright

My WebAssembly adventure ends here for now, but the future is looking bright. I found
the WASI HTTP proposal, which is currently in phase 2 of 5. Fingers crossed!

Include extra charges in the price

The app shows a graph of the energy rates, but it does not include some additional charges that affect the final price:

Please note that the rates in the chart do not include purchase costs, energy tax, Sustainable Energy Surcharge, and the regional surcharge for gas.

These charges are thus also missing from the prices posted to the channel. The missing charges are:

Charge Amount (including VAT) Source
Purchase costs €0.0212 per kWh https://www.anwb.nl/huis/energie/anwb-energie/veelgestelde-vragen
Energy tax €0.15 per kWh https://www.milieucentraal.nl/energie-besparen/inzicht-in-je-energierekening/energiebelasting-2023
Sustainable Energy Surcharge €0 per kWh (abolished in 2023) https://www.milieucentraal.nl/energie-besparen/inzicht-in-je-energierekening/energiebelasting-2023

I don’t know whether the energy price and each of the extra charges are taxed individually (this table assumes so). That’s something I’ll have to look into. That doesn’t matter, as $ax + bx + cx = (a + b + c) x$. Hooray for math making my life easier for once.

Strip release binary?

This saves a few MBs, but it makes debugging harder. It could also make the Repl load faster and make downloading updates faster, which is always nice.

List the price of gas

Because there’s much less variation, it would probably be enough to list the highest, lowest, and average price.

Update format string

The format string for displaying dates in the application is currently set to "Monday _2 January 2006". This causes dates with a single-digit day to have an extra space before the day number, such as "Monday 9 January 2006". The solution is to change the format string to "Monday 2 January 2006".

improvement ideas

  • remove need for CREDENTIALS_DIRECTORY env var
  • update README
  • address code TODOs
  • move to Fly.io

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.