Skip to content

Instantly share code, notes, and snippets.

@flexagoon
Created July 31, 2025 18:34
Show Gist options
  • Select an option

  • Save flexagoon/96212a774200ea736db08f66909ee8d0 to your computer and use it in GitHub Desktop.

Select an option

Save flexagoon/96212a774200ea736db08f66909ee8d0 to your computer and use it in GitHub Desktop.
Plot messages in a telegram chat over time. Designed to be used with https://github.com/flexagoon/ream.
# Plot messages in a telegram chat over time
# Designed to be used with https://github.com/flexagoon/ream
Mix.install([
{:tucan, "~> 0.5.0"},
{:vega_lite_convert, "~> 1.0.0"}
])
defmodule Analysis do
def parse_args(argv) do
case argv do
[id | _tl] -> id
_ -> raise ArgumentError, message: "No chat id provided"
end
end
def analyze(file) do
data =
file
|> File.read!()
|> JSON.decode!()
dates =
data["messages"]
|> Enum.map(fn message ->
message["date"]
|> String.slice(0, 10)
|> Date.from_iso8601!()
end)
min_date = Enum.min(dates, Date)
max_date = Enum.max(dates, Date)
counts = Enum.frequencies(dates)
df =
for date <- Date.range(min_date, max_date), reduce: %{dates: [], sent: [], total: []} do
acc ->
sent = Map.get(counts, date, 0)
total = List.first(acc.total, 0) + sent
%{
dates: [date | acc.dates],
sent: [sent | acc.sent],
total: [total | acc.total]
}
end
df = %{
Date: df.dates,
Sent: df.sent,
Messages: df.total
}
{data["name"], df}
end
end
chat_id = Analysis.parse_args(System.argv())
{name, df} = Analysis.analyze("./exports/#{chat_id}/export.json")
export_file = "#{name} (#{chat_id}).svg"
df
|> Tucan.area("Date", "Messages")
|> Tucan.set_size(2000, 1000)
|> Tucan.color_by("Sent", type: :quantitative)
|> Tucan.set_title(name)
|> Tucan.Export.save!(export_file)
System.cmd("xdg-open", [export_file])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment