Skip to content

Commit

Permalink
Merge pull request #2603 from ujh/track-user-agents
Browse files Browse the repository at this point in the history
Keep track of user agents
  • Loading branch information
ujh authored Jan 7, 2025
2 parents ba52fb8 + 9da931b commit f595eb7
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 5 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ gem "sprockets-rails"
gem "strong_migrations"
gem "pghero"
gem "pg_query", ">= 2"
gem "user_agent_parser"

group :development, :test do
gem "byebug", platform: :mri
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ GEM
concurrent-ruby (~> 1.0)
uber (0.1.0)
uri (1.0.2)
user_agent_parser (2.18.0)
useragent (0.16.11)
warden (1.2.9)
rack (>= 2.0.9)
Expand Down Expand Up @@ -626,6 +627,7 @@ DEPENDENCIES
syntax_tree (~> 6.2)
syntax_tree-haml (~> 4.0)
syntax_tree-rbs (~> 1.0.0)
user_agent_parser
web-console
webmock

Expand Down
23 changes: 23 additions & 0 deletions app/controllers/admins/graphs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def show
bot_signups
when "spam"
spam
when "user-agents"
user_agents
end
render json: data
end
Expand Down Expand Up @@ -67,6 +69,27 @@ def spam
end
end

def user_agents
base_relation = UserAgent.where("day > ?", 2.months.ago)
base_relation
.select(:name)
.distinct
.pluck(:name)
.reject { |name| name.blank? }
.map do |name|
{
name: name,
data:
base_relation
.where(name: name)
.group(:day)
.order(day: :asc)
.pluck(Arel.sql("day, count(*)"))
.map { |d| [d.first.to_datetime.to_i * 1000, d.last] }
}
end
end

def collected_inks
build CollectedInk
end
Expand Down
10 changes: 10 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
around_action :set_time_zone
before_action :save_user_agent

if !Rails.env.development?
rescue_from ActionView::MissingTemplate do |exception|
Expand All @@ -17,4 +18,13 @@ def set_time_zone
yield
end
end

def save_user_agent
user_agent = request.user_agent
UserAgent.create(
name: UserAgentParser.parse(user_agent).family,
raw_name: user_agent,
day: Date.current
)
end
end
38 changes: 38 additions & 0 deletions app/javascript/src/admin/graphs/UserAgents.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { useEffect, useState } from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";

import { Spinner } from "../components/Spinner";
import { getRequest } from "../../fetch";

export const UserAgents = () => {
const [data, setData] = useState(null);
useEffect(() => {
getRequest("/admins/graphs/user-agents.json")
.then((res) => res.json())
.then((json) => setData(json));
}, []);
if (data) {
const options = {
chart: { type: "spline" },
legend: { enabled: true },
series: data,
title: { text: "User Agents" },
xAxis: {
type: "datetime"
},
yAxis: { title: { text: "" } }
};
return (
<div>
<HighchartsReact highcharts={Highcharts} options={options} />
</div>
);
} else {
return (
<div>
<Spinner />
</div>
);
}
};
9 changes: 9 additions & 0 deletions app/javascript/src/admin/graphs/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CurrentlyInked } from "./CurrentlyInked";
import { UsageRecords } from "./UsageRecords";
import { BotSignUps } from "./BotSignUps";
import { Spam } from "./Spam";
import { UserAgents } from "./UserAgents";

document.addEventListener("DOMContentLoaded", () => {
const el = document.getElementById("signups-graph");
Expand All @@ -17,6 +18,14 @@ document.addEventListener("DOMContentLoaded", () => {
}
});

document.addEventListener("DOMContentLoaded", () => {
const el = document.getElementById("user-agents-graph");
if (el) {
const root = createRoot(el);
root.render(<UserAgents />);
}
});

document.addEventListener("DOMContentLoaded", () => {
const el = document.getElementById("bot-signups-graph");
if (el) {
Expand Down
4 changes: 2 additions & 2 deletions app/javascript/stylesheets/admin/graphs.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#graphs {
.row {
box-shadow: none;
.row div {
margin-bottom: 5px;
}

.loader {
Expand Down
2 changes: 2 additions & 0 deletions app/models/user_agent.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class UserAgent < ApplicationRecord
end
8 changes: 5 additions & 3 deletions app/views/admins/dashboards/show.html.slim
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@ div#graphs
div#currently-inked-graph
div.col-sm-12.col-lg-6
div#usage-records-graph
div.col-sm-12.col-md-6.col-lg-4
div.col-sm-12.col-lg-6
div#signups-graph
div.col-sm-12.col-md-6.col-lg-4
div.col-sm-12.col-lg-6
div#bot-signups-graph
div.col-sm-12.col-md-6.col-lg-4
div.col-sm-12.col-lg-6
div#spam-graph
div.col-sm-12.col-lg-6
div#user-agents-graph
12 changes: 12 additions & 0 deletions db/migrate/20250107083051_create_user_agents.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateUserAgents < ActiveRecord::Migration[8.0]
def change
create_table :user_agents do |t|
t.string :name
t.string :raw_name
t.date :day

t.index %i[name day]
t.timestamps
end
end
end
56 changes: 56 additions & 0 deletions db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,39 @@ CREATE SEQUENCE public.usage_records_id_seq
ALTER SEQUENCE public.usage_records_id_seq OWNED BY public.usage_records.id;


--
-- Name: user_agents; Type: TABLE; Schema: public; Owner: -
--

CREATE TABLE public.user_agents (
id bigint NOT NULL,
name character varying,
raw_name character varying,
day date,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);


--
-- Name: user_agents_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--

CREATE SEQUENCE public.user_agents_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;


--
-- Name: user_agents_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--

ALTER SEQUENCE public.user_agents_id_seq OWNED BY public.user_agents.id;


--
-- Name: users; Type: TABLE; Schema: public; Owner: -
--
Expand Down Expand Up @@ -1092,6 +1125,13 @@ ALTER TABLE ONLY public.reading_statuses ALTER COLUMN id SET DEFAULT nextval('pu
ALTER TABLE ONLY public.usage_records ALTER COLUMN id SET DEFAULT nextval('public.usage_records_id_seq'::regclass);


--
-- Name: user_agents id; Type: DEFAULT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.user_agents ALTER COLUMN id SET DEFAULT nextval('public.user_agents_id_seq'::regclass);


--
-- Name: users id; Type: DEFAULT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -1297,6 +1337,14 @@ ALTER TABLE ONLY public.usage_records
ADD CONSTRAINT usage_records_pkey PRIMARY KEY (id);


--
-- Name: user_agents user_agents_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.user_agents
ADD CONSTRAINT user_agents_pkey PRIMARY KEY (id);


--
-- Name: users users_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -1657,6 +1705,13 @@ CREATE INDEX index_reading_statuses_on_user_id ON public.reading_statuses USING
CREATE UNIQUE INDEX index_usage_records_on_currently_inked_id_and_used_on ON public.usage_records USING btree (currently_inked_id, used_on);


--
-- Name: index_user_agents_on_name_and_day; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX index_user_agents_on_name_and_day ON public.user_agents USING btree (name, day);


--
-- Name: index_users_on_confirmation_token; Type: INDEX; Schema: public; Owner: -
--
Expand Down Expand Up @@ -1926,6 +1981,7 @@ ALTER TABLE ONLY public.collected_inks
SET search_path TO "$user", public;

INSERT INTO "schema_migrations" (version) VALUES
('20250107083051'),
('20241228204210'),
('20241228202733'),
('20241211115823'),
Expand Down
7 changes: 7 additions & 0 deletions spec/factories/user_agents.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FactoryBot.define do
factory :user_agent do
name { "MyString" }
raw_name { "MyString" }
day { "2025-01-07" }
end
end
5 changes: 5 additions & 0 deletions spec/models/user_agent_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require "rails_helper"

RSpec.describe UserAgent, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end

0 comments on commit f595eb7

Please sign in to comment.