mirror of
https://github.com/System-End/hackatime.git
synced 2026-04-19 19:55:16 +00:00
Fix dispatch_timeout in leaderboard job
This commit is contained in:
parent
27c88ab70b
commit
5cc7ae265b
11 changed files with 159 additions and 25 deletions
13
app/avo/resources/sailors_log_leaderboard.rb
Normal file
13
app/avo/resources/sailors_log_leaderboard.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
class Avo::Resources::SailorsLogLeaderboard < Avo::BaseResource
|
||||
# self.includes = []
|
||||
# self.attachments = []
|
||||
# self.search = {
|
||||
# query: -> { query.ransack(id_eq: params[:q], m: "or").result(distinct: false) }
|
||||
# }
|
||||
|
||||
def fields
|
||||
field :id, as: :id
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# This controller has been generated to enable Rails' resource routes.
|
||||
# More information on https://docs.avohq.io/3.0/controllers.html
|
||||
class Avo::SailorsLogLeaderboardsController < Avo::ResourcesController
|
||||
end
|
||||
|
|
@ -2,6 +2,10 @@ class SailorsLogController < ApplicationController
|
|||
skip_before_action :verify_authenticity_token
|
||||
before_action :verify_slack_request
|
||||
|
||||
# allow usage of short_time_simple
|
||||
include ApplicationHelper
|
||||
helper_method :short_time_simple
|
||||
|
||||
# Handle slack commands
|
||||
def create
|
||||
case params[:text].downcase.strip
|
||||
|
|
@ -19,26 +23,23 @@ class SailorsLogController < ApplicationController
|
|||
text: ":white_check_mark: Coding notifications have been turned off in this channel."
|
||||
}
|
||||
when "leaderboard"
|
||||
leaderboard = SailorsLog.generate_leaderboard(params[:channel_id])
|
||||
message = "*:boat: Sailor's Log - Today*"
|
||||
medals = [ "first_place_medal", "second_place_medal", "third_place_medal" ]
|
||||
# ex.
|
||||
# :first_place_medal: @Irtaza: 2h 6m → Farmworks [C#]: 125m
|
||||
# :second_place_medal: @Cigan: 1h 33m → Gitracker-1 [JAVA]: 49m + Dupe [JAVA]: 41m + Lovac-Integration [JAVA]: 2m
|
||||
leaderboard.each_with_index do |entry, index|
|
||||
medal = medals[index] || "white_small_square"
|
||||
message += "\n:#{medal}: `<@#{entry[:user_id]}>`: #{entry[:duration]} → "
|
||||
message += entry[:projects].map do |project|
|
||||
language = project[:language_emoji] ? "#{project[:language_emoji]} #{project[:language]}" : project[:language]
|
||||
"#{project[:name]} [#{language}]"
|
||||
end.join(" + ")
|
||||
end
|
||||
# Acknowledge receipt
|
||||
head :ok
|
||||
|
||||
puts message
|
||||
render json: {
|
||||
response_type: "in_channel",
|
||||
text: message
|
||||
}
|
||||
# Send loading message first
|
||||
response = HTTP.post(params[:response_url], json: {
|
||||
response_type: "ephemeral",
|
||||
text: ":beachball: #{FlavorText.loading_messages.sample}",
|
||||
trigger_id: params[:trigger_id]
|
||||
})
|
||||
|
||||
puts "Response: #{response.body}"
|
||||
|
||||
# Process in background
|
||||
SailorsLogLeaderboardJob.perform_later(
|
||||
params[:channel_id],
|
||||
params[:response_url],
|
||||
)
|
||||
else
|
||||
render json: {
|
||||
response_type: "ephemeral",
|
||||
|
|
|
|||
34
app/jobs/sailors_log_leaderboard_job.rb
Normal file
34
app/jobs/sailors_log_leaderboard_job.rb
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
class SailorsLogLeaderboardJob < ApplicationJob
|
||||
queue_as :default
|
||||
include ApplicationHelper
|
||||
|
||||
def perform(channel_id, response_url)
|
||||
# Generate leaderboard
|
||||
leaderboard = SailorsLog.generate_leaderboard(channel_id)
|
||||
message = "*:boat: Sailor's Log - Today*"
|
||||
medals = [ "first_place_medal", "second_place_medal", "third_place_medal" ]
|
||||
|
||||
leaderboard.each_with_index do |entry, index|
|
||||
medal = medals[index] || "white_small_square"
|
||||
message += "\n:#{medal}: `<@#{entry[:user_id]}>`: #{short_time_simple entry[:duration]} → "
|
||||
message += entry[:projects].map do |project|
|
||||
language = project[:language_emoji] ? "#{project[:language_emoji]} #{project[:language]}" : project[:language]
|
||||
|
||||
project_entry = []
|
||||
project_entry << "#{project[:name]}"
|
||||
project_entry << "[#{language}]" unless language.nil?
|
||||
project_entry << "#{short_time_simple project[:duration]}"
|
||||
project_entry.join(" ")
|
||||
end.join(" + ")
|
||||
end
|
||||
|
||||
# Update with final message
|
||||
response = HTTP.post(response_url, json: {
|
||||
response_type: "in_channel",
|
||||
replace_original: true,
|
||||
text: message
|
||||
})
|
||||
|
||||
puts "Response: #{response.body}"
|
||||
end
|
||||
end
|
||||
|
|
@ -46,6 +46,7 @@ class SailorsLog < ApplicationRecord
|
|||
.duration_seconds
|
||||
|
||||
projects = project_durations.map do |project, duration|
|
||||
print "project: #{project}, duration: #{duration}, language: #{most_common_languages[project]}"
|
||||
{
|
||||
name: project,
|
||||
duration: duration,
|
||||
|
|
@ -54,6 +55,8 @@ class SailorsLog < ApplicationRecord
|
|||
}
|
||||
end
|
||||
|
||||
projects = projects.filter { |project| project[:duration] > 1.minute }.sort_by { |project| -project[:duration] }
|
||||
|
||||
{
|
||||
user_id: user_id,
|
||||
duration: user_durations[user_id],
|
||||
|
|
@ -63,21 +66,22 @@ class SailorsLog < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.language_emoji(language)
|
||||
case language.downcase
|
||||
language = language.downcase
|
||||
case language
|
||||
when "ruby"
|
||||
":ruby:"
|
||||
":#{language}:"
|
||||
when "javascript"
|
||||
":js:"
|
||||
when "typescript"
|
||||
":ts:"
|
||||
when "html"
|
||||
":html:"
|
||||
":#{language}:"
|
||||
when "java"
|
||||
[ ":java:", ":java_duke:" ].sample
|
||||
when "unity"
|
||||
[ ":unity:", ":unity_new:" ].sample
|
||||
when "c++"
|
||||
":c++:"
|
||||
":#{language}:"
|
||||
when "c"
|
||||
[ ":c:", ":c_1:" ].sample
|
||||
when "rust"
|
||||
|
|
@ -89,7 +93,9 @@ class SailorsLog < ApplicationRecord
|
|||
when "go"
|
||||
[ ":golang:", ":gopher:", ":gothonk:" ].sample
|
||||
when "kotlin"
|
||||
":kotlin:"
|
||||
":#{language}:"
|
||||
when "astro"
|
||||
":#{language}:"
|
||||
else
|
||||
nil
|
||||
end
|
||||
|
|
|
|||
2
app/models/sailors_log_leaderboard.rb
Normal file
2
app/models/sailors_log_leaderboard.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
class SailorsLogLeaderboard < ApplicationRecord
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
class CreateSailorsLogLeaderboards < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
create_table :sailors_log_leaderboards do |t|
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
7
db/schema.rb
generated
7
db/schema.rb
generated
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_02_22_082500) do
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_02_23_072034) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_catalog.plpgsql"
|
||||
|
||||
|
|
@ -122,6 +122,11 @@ ActiveRecord::Schema[8.0].define(version: 2025_02_22_082500) do
|
|||
t.datetime "deleted_at"
|
||||
end
|
||||
|
||||
create_table "sailors_log_leaderboards", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "sailors_log_notification_preferences", force: :cascade do |t|
|
||||
t.string "slack_uid", null: false
|
||||
t.string "slack_channel_id", null: false
|
||||
|
|
|
|||
44
lib/flavor_text.rb
Normal file
44
lib/flavor_text.rb
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
class FlavorText
|
||||
def self.loading_messages
|
||||
[
|
||||
"Generating leaderboard...",
|
||||
"Crunching the numbers...",
|
||||
"Hold tight, I'm working on it...",
|
||||
"chugging the data juice",
|
||||
"chugging *Stat-Cola©*, for those who want to know things™",
|
||||
"that's numberwang!",
|
||||
"crunching the numbers",
|
||||
"munching the numbers",
|
||||
"gurgling the bits",
|
||||
"juggling the electrons",
|
||||
"chomping the bytes",
|
||||
"playing the photons on bass",
|
||||
"reticulating the splines",
|
||||
"rolling down data hills",
|
||||
"frolicking through fields of numbers",
|
||||
"skiing the data slopes",
|
||||
"zooming through the cyber-pipes",
|
||||
"grabbing the stats",
|
||||
"switching the dependent and independent variables",
|
||||
"flipping a coin to choose which axis to use",
|
||||
"warming up the powerhouse of the cell",
|
||||
"calculating significant figures...",
|
||||
"p-hacking the n value",
|
||||
"computing P = NP",
|
||||
"realizing P ≠ NP",
|
||||
"so, uh... come here often?",
|
||||
"*powertool noises*",
|
||||
"spinning violently around the y-axis",
|
||||
"serializing first-time coders experiences",
|
||||
"tokenizing personal experiences",
|
||||
"waking up the bits",
|
||||
"petting the bits",
|
||||
"testing patience",
|
||||
"npm installing 3 of 27594 packages",
|
||||
"spinning the rgbs",
|
||||
"Installing dependencies",
|
||||
"shoveling the overflowed pixels",
|
||||
".split() === :large_blue_circle::large_green_circle::large_yellow_circle::large_orange_circle::red_circle::large_purple_circle: "
|
||||
]
|
||||
end
|
||||
end
|
||||
11
test/fixtures/sailors_log_leaderboards.yml
vendored
Normal file
11
test/fixtures/sailors_log_leaderboards.yml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
# This model initially had no columns defined. If you add columns to the
|
||||
# model remove the "{}" from the fixture names and add the columns immediately
|
||||
# below each fixture, per the syntax in the comments below
|
||||
#
|
||||
one: {}
|
||||
# column: value
|
||||
#
|
||||
two: {}
|
||||
# column: value
|
||||
7
test/models/sailors_log_leaderboard_test.rb
Normal file
7
test/models/sailors_log_leaderboard_test.rb
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class SailorsLogLeaderboardTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue