very good and informative
Really informative plot!

Summary

User supplied summary for the plot

Norway's top 10 weekly Google Trends: What Norwegians are searching for the most in the last 24 Hours!

Description

The below description is supplied in free-text by the user

Integrating Discord with Novem Plots

This guide explains how to automatically post a Novem plot as an image to a Discord channel (or thread) every time your job runs. Follow every step in order and you'll have it working.


Step 1: Get your Discord Webhook URL

A webhook URL is a special link that lets a script post messages into a Discord channel.

  1. Open Discord and go to the channel you want to post in
  2. Click the gear icon next to the channel name to open channel settings
  3. Click Integrations in the left sidebar → WebhooksNew Webhook
    • (If you don't see this option you don't have permission — ask a server moderator to create one for you)
  4. Give the webhook a name (anything you like), then click Copy Webhook URL
  5. Save that URL somewhere safe — you'll need it in Step 2

It will look like this: https://discord.com/api/webhooks/123456789/abcdefg-long-token-here

Optional: posting into a Thread instead of the main channel

If you want messages to go into a specific thread rather than the main channel, you need the thread's ID:

  1. In Discord, go to User SettingsAdvanced → turn on Developer Mode
  2. Right-click the thread name and click Copy Thread ID
  3. Save that ID — you'll use it as discord_thread_id in Step 2

Step 2: Store your webhook URL as an Environment Variable in Novem

Environment variables are a safe way to store secrets (like passwords and tokens) outside of your code. Instead of writing the webhook URL directly in your script, you store it in Novem and your script reads it automatically at runtime.

Never paste your webhook URL directly into your script code. If you share your code, others would be able to post to your Discord.

To add environment variables to your Novem job:

  1. Go to your job in Novem
  2. Find the Environment Variables section
  3. Add the following variables (only discord_webhook_url is required):
Variable name What to put in it
discord_webhook_url The full webhook URL you copied in Step 1
discord_thread_id (Optional) The thread ID if you want to post into a thread

Your script reads these with os.environ.get("discord_webhook_url") — you will see this in the code below.


Step 3: Fetch the plot image from Novem

After your job updates the plot data, Novem needs a few seconds to re-render it. This function waits 8 seconds then downloads the plot as a PNG image and returns its raw binary contents:

import time, requests

def fetch_plot_image(api_base: str, token: str, plot_name: str) -> bytes:
    time.sleep(8)  # wait for Novem to finish rendering the updated plot
    url = f"{api_base}/vis/plots/{plot_name}/files/plot.png"
    resp = requests.get(url, headers={"Authorization": f"Bearer {token}"}, timeout=60)
    resp.raise_for_status()  # raises an error if the request failed
    return resp.content      # returns the raw PNG bytes (binary image data)

Note: api_base and token (your Novem API token) are automatically available as environment variables inside every Novem job — you don't need to set them yourself.


Step 4: Post the image to Discord

This function takes the raw PNG bytes from Step 3 and sends them to Discord along with a text message:

import json, requests

def post_to_discord(webhook_url: str, image_bytes: bytes, plot_name: str, thread_id: str = ""):
    # image_bytes: the raw PNG binary returned by fetch_plot_image() — sent as the file attachment
    # thread_id:   leave as "" to post in the main channel, or pass a thread ID to post in a thread

    url = f"{webhook_url}?thread_id={thread_id}" if thread_id else webhook_url

    # This is the text message that appears above the image in Discord.
    # Replace the content below with whatever you want to say.
    # Replace {your_username} with your actual Novem username.
    content = (
        f"New chart just posted!\n"
        f"https://novem.io/u/{{your_username}}/p/{plot_name}"
    )

    resp = requests.post(
        url,
        files={"file": (f"{plot_name}.png", image_bytes, "image/png")},
        data={"payload_json": json.dumps({"content": content})},
        timeout=30,
    )
    resp.raise_for_status()  # raises an error if Discord rejected the request

Important: Discord requires both a file field and a payload_json field sent together. Sending only JSON (without the file) will not attach the image.


Step 5: Wire it all together

Here is a complete working script you can copy and adapt. Replace "your-plot-name" with your actual Novem plot name:

import os, time, json, requests

PLOT_NAME = "your-plot-name"  # ← change this to your plot name

def fetch_plot_image(api_base, token, plot_name):
    time.sleep(8)
    url = f"{api_base}/vis/plots/{plot_name}/files/plot.png"
    resp = requests.get(url, headers={"Authorization": f"Bearer {token}"}, timeout=60)
    resp.raise_for_status()
    return resp.content

def post_to_discord(webhook_url, image_bytes, plot_name, thread_id=""):
    url = f"{webhook_url}?thread_id={thread_id}" if thread_id else webhook_url
    content = (
        f"New chart just posted!\n"
        f"https://novem.io/u/your_username/p/{plot_name}"  # ← replace your_username
    )
    resp = requests.post(
        url,
        files={"file": (f"{plot_name}.png", image_bytes, "image/png")},
        data={"payload_json": json.dumps({"content": content})},
        timeout=30,
    )
    resp.raise_for_status()

def main():
    # These are automatically available inside every Novem job
    token    = os.environ.get("novem_token", "")
    api_base = os.environ.get("api_base", "https://api.novem.io/v1")

    # These you set yourself in the job's Environment Variables (see Step 2)
    webhook_url = os.environ.get("discord_webhook_url", "")
    thread_id   = os.environ.get("discord_thread_id", "")

    if not webhook_url:
        print("No discord_webhook_url set — skipping Discord post.")
        return

    # 1. (Your code to update the plot data goes here)

    # 2. Fetch the rendered plot image
    image_bytes = fetch_plot_image(api_base, token, PLOT_NAME)

    # 3. Post it to Discord
    post_to_discord(webhook_url, image_bytes, PLOT_NAME, thread_id=thread_id)
    print("Posted to Discord successfully.")

if __name__ == "__main__":
    main()

Summary of what each piece does

1. Your script updates the plot data in Novem
2. Wait 8 seconds for Novem to re-render the plot as a PNG
3. Download the PNG from Novem → stored in image_bytes
4. Send image_bytes + a text message to your Discord webhook URL