diff --git a/server/.sqlx/query-945c4148b733e041016e96b2f073b1301e77e1237f64d9f8a866ed32a0d0d898.json b/server/.sqlx/query-02f7e30a5c34e3318b9d58c3127ed16992b77138f681cfe312f95233c22d9f54.json similarity index 63% rename from server/.sqlx/query-945c4148b733e041016e96b2f073b1301e77e1237f64d9f8a866ed32a0d0d898.json rename to server/.sqlx/query-02f7e30a5c34e3318b9d58c3127ed16992b77138f681cfe312f95233c22d9f54.json index dd8155a..29b2001 100644 --- a/server/.sqlx/query-945c4148b733e041016e96b2f073b1301e77e1237f64d9f8a866ed32a0d0d898.json +++ b/server/.sqlx/query-02f7e30a5c34e3318b9d58c3127ed16992b77138f681cfe312f95233c22d9f54.json @@ -1,70 +1,75 @@ { "db_name": "PostgreSQL", - "query": "SELECT\n users.name,\n period_type,\n total_score,\n executed_prs,\n largest_score,\n prs_opened,\n prs_merged,\n best as streak_best,\n amount as streak_amount,\n user_period_data.total_rating as total_rating,\n period as streak_type,\n streak.name as streak_name,\n latest_time_string as streak_latest_time_string\nFROM\n user_period_data\n JOIN users ON users.id = user_period_data.user_id\n JOIN streak_user_data ON streak_user_data.user_id = users.id\n JOIN streak ON streak.id = streak_user_data.streak_id\nWHERE\n period_type = $1\n and streak_user_data.streak_id = $2\nORDER BY\n total_rating DESC\nLIMIT\n $3 OFFSET $4\n", + "query": "SELECT\n users.login,\n users.full_name,\n period_type,\n total_score,\n executed_prs,\n largest_score,\n prs_opened,\n prs_merged,\n best as streak_best,\n amount as streak_amount,\n user_period_data.total_rating as total_rating,\n period as streak_type,\n streak.name as streak_name,\n latest_time_string as streak_latest_time_string\nFROM\n user_period_data\n JOIN users ON users.id = user_period_data.user_id\n JOIN streak_user_data ON streak_user_data.user_id = users.id\n JOIN streak ON streak.id = streak_user_data.streak_id\nWHERE\n period_type = $1\n and streak_user_data.streak_id = $2\nORDER BY\n total_rating DESC\nLIMIT\n $3 OFFSET $4\n", "describe": { "columns": [ { "ordinal": 0, - "name": "name", + "name": "login", "type_info": "Text" }, { "ordinal": 1, - "name": "period_type", + "name": "full_name", "type_info": "Text" }, { "ordinal": 2, + "name": "period_type", + "type_info": "Text" + }, + { + "ordinal": 3, "name": "total_score", "type_info": "Int4" }, { - "ordinal": 3, + "ordinal": 4, "name": "executed_prs", "type_info": "Int4" }, { - "ordinal": 4, + "ordinal": 5, "name": "largest_score", "type_info": "Int4" }, { - "ordinal": 5, + "ordinal": 6, "name": "prs_opened", "type_info": "Int4" }, { - "ordinal": 6, + "ordinal": 7, "name": "prs_merged", "type_info": "Int4" }, { - "ordinal": 7, + "ordinal": 8, "name": "streak_best", "type_info": "Int4" }, { - "ordinal": 8, + "ordinal": 9, "name": "streak_amount", "type_info": "Int4" }, { - "ordinal": 9, + "ordinal": 10, "name": "total_rating", "type_info": "Int4" }, { - "ordinal": 10, + "ordinal": 11, "name": "streak_type", "type_info": "Text" }, { - "ordinal": 11, + "ordinal": 12, "name": "streak_name", "type_info": "Text" }, { - "ordinal": 12, + "ordinal": 13, "name": "streak_latest_time_string", "type_info": "Text" } @@ -79,6 +84,7 @@ }, "nullable": [ false, + true, false, false, false, @@ -93,5 +99,5 @@ false ] }, - "hash": "945c4148b733e041016e96b2f073b1301e77e1237f64d9f8a866ed32a0d0d898" + "hash": "02f7e30a5c34e3318b9d58c3127ed16992b77138f681cfe312f95233c22d9f54" } diff --git a/server/.sqlx/query-a6d2cc2e8772f290d27753429a10e78e5ddac82bf2845d4d6c164786547ee08f.json b/server/.sqlx/query-06a502fc4e5f176ce836fc4c6f084b9eb65cd1b5c0ac0b5caedf6ca1e18cb72f.json similarity index 67% rename from server/.sqlx/query-a6d2cc2e8772f290d27753429a10e78e5ddac82bf2845d4d6c164786547ee08f.json rename to server/.sqlx/query-06a502fc4e5f176ce836fc4c6f084b9eb65cd1b5c0ac0b5caedf6ca1e18cb72f.json index 2d507d2..d2af9d9 100644 --- a/server/.sqlx/query-a6d2cc2e8772f290d27753429a10e78e5ddac82bf2845d4d6c164786547ee08f.json +++ b/server/.sqlx/query-06a502fc4e5f176ce836fc4c6f084b9eb65cd1b5c0ac0b5caedf6ca1e18cb72f.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE organizations\n SET name = $1\n WHERE name = $1\n RETURNING id\n ", + "query": "\n UPDATE organizations\n SET login = $1\n WHERE login = $1\n RETURNING id\n ", "describe": { "columns": [ { @@ -18,5 +18,5 @@ false ] }, - "hash": "a6d2cc2e8772f290d27753429a10e78e5ddac82bf2845d4d6c164786547ee08f" + "hash": "06a502fc4e5f176ce836fc4c6f084b9eb65cd1b5c0ac0b5caedf6ca1e18cb72f" } diff --git a/server/.sqlx/query-09411dc84f140bfa95686ac7e14c676c5f7c64f13c3039c2c63ee70dc40f9cb5.json b/server/.sqlx/query-09411dc84f140bfa95686ac7e14c676c5f7c64f13c3039c2c63ee70dc40f9cb5.json deleted file mode 100644 index b4b6292..0000000 --- a/server/.sqlx/query-09411dc84f140bfa95686ac7e14c676c5f7c64f13c3039c2c63ee70dc40f9cb5.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO organizations (name)\n VALUES ($1)\n ON CONFLICT (name) DO NOTHING\n RETURNING id\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [ - "Text" - ] - }, - "nullable": [ - false - ] - }, - "hash": "09411dc84f140bfa95686ac7e14c676c5f7c64f13c3039c2c63ee70dc40f9cb5" -} diff --git a/server/.sqlx/query-a9363078d89dfe3a80a6de0f8ba07306e5eb358961a2cd5032e9be101d5310a7.json b/server/.sqlx/query-122194a677b7cc0c726947f174a8dd848cbf6ec09d5555397cda08147f38f21f.json similarity index 50% rename from server/.sqlx/query-a9363078d89dfe3a80a6de0f8ba07306e5eb358961a2cd5032e9be101d5310a7.json rename to server/.sqlx/query-122194a677b7cc0c726947f174a8dd848cbf6ec09d5555397cda08147f38f21f.json index 894c68b..4542b0b 100644 --- a/server/.sqlx/query-a9363078d89dfe3a80a6de0f8ba07306e5eb358961a2cd5032e9be101d5310a7.json +++ b/server/.sqlx/query-122194a677b7cc0c726947f174a8dd848cbf6ec09d5555397cda08147f38f21f.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO users (name, permanent_bonus)\n VALUES ($1, $2)\n ON CONFLICT (name) DO NOTHING\n RETURNING id\n ", + "query": "\n INSERT INTO users (login, permanent_bonus)\n VALUES ($1, $2)\n ON CONFLICT (login) DO NOTHING\n RETURNING id\n ", "describe": { "columns": [ { @@ -19,5 +19,5 @@ false ] }, - "hash": "a9363078d89dfe3a80a6de0f8ba07306e5eb358961a2cd5032e9be101d5310a7" + "hash": "122194a677b7cc0c726947f174a8dd848cbf6ec09d5555397cda08147f38f21f" } diff --git a/server/.sqlx/query-4fdc9da3f2c4d30d414fa5e9db1c31a9b4eb134f7be5f88718a07e53bbb0516c.json b/server/.sqlx/query-1e3e583599dd9070c0105d1eee21146e588bbd383e6b8fedcf8c34eb9ff01ba1.json similarity index 68% rename from server/.sqlx/query-4fdc9da3f2c4d30d414fa5e9db1c31a9b4eb134f7be5f88718a07e53bbb0516c.json rename to server/.sqlx/query-1e3e583599dd9070c0105d1eee21146e588bbd383e6b8fedcf8c34eb9ff01ba1.json index ba98384..04f10e1 100644 --- a/server/.sqlx/query-4fdc9da3f2c4d30d414fa5e9db1c31a9b4eb134f7be5f88718a07e53bbb0516c.json +++ b/server/.sqlx/query-1e3e583599dd9070c0105d1eee21146e588bbd383e6b8fedcf8c34eb9ff01ba1.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE users\n SET permanent_bonus = $2\n WHERE name = $1\n RETURNING id\n ", + "query": "\n UPDATE users\n SET permanent_bonus = $2\n WHERE login = $1\n RETURNING id\n ", "describe": { "columns": [ { @@ -19,5 +19,5 @@ false ] }, - "hash": "4fdc9da3f2c4d30d414fa5e9db1c31a9b4eb134f7be5f88718a07e53bbb0516c" + "hash": "1e3e583599dd9070c0105d1eee21146e588bbd383e6b8fedcf8c34eb9ff01ba1" } diff --git a/server/.sqlx/query-351b518e126183771b384b1fabfdcc4a139db1ceb8c094dc69a792491d65261a.json b/server/.sqlx/query-351b518e126183771b384b1fabfdcc4a139db1ceb8c094dc69a792491d65261a.json new file mode 100644 index 0000000..4263064 --- /dev/null +++ b/server/.sqlx/query-351b518e126183771b384b1fabfdcc4a139db1ceb8c094dc69a792491d65261a.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO user_cached_metadata (user_id, image_base64, load_time)\n VALUES ((SELECT id FROM users WHERE login = $1), $2, now())\n ON CONFLICT (user_id) DO NOTHING\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "351b518e126183771b384b1fabfdcc4a139db1ceb8c094dc69a792491d65261a" +} diff --git a/server/.sqlx/query-372e6570d05e95c58850c536362e80ac57258a34e4667c71bb83cfa1cc66910c.json b/server/.sqlx/query-372e6570d05e95c58850c536362e80ac57258a34e4667c71bb83cfa1cc66910c.json new file mode 100644 index 0000000..63a4b73 --- /dev/null +++ b/server/.sqlx/query-372e6570d05e95c58850c536362e80ac57258a34e4667c71bb83cfa1cc66910c.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE organizations\n SET full_name = $2\n WHERE login = $1\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "372e6570d05e95c58850c536362e80ac57258a34e4667c71bb83cfa1cc66910c" +} diff --git a/server/.sqlx/query-1e372913d39da6d53b2ef1c5f6e82b5b812644776c228d4f3da1b44059d7e514.json b/server/.sqlx/query-3a6d252b20ad7fd73ff9decf1a5a263e8896768a74012837cb9cd85a6c01fe2e.json similarity index 73% rename from server/.sqlx/query-1e372913d39da6d53b2ef1c5f6e82b5b812644776c228d4f3da1b44059d7e514.json rename to server/.sqlx/query-3a6d252b20ad7fd73ff9decf1a5a263e8896768a74012837cb9cd85a6c01fe2e.json index 4203e79..85841d6 100644 --- a/server/.sqlx/query-1e372913d39da6d53b2ef1c5f6e82b5b812644776c228d4f3da1b44059d7e514.json +++ b/server/.sqlx/query-3a6d252b20ad7fd73ff9decf1a5a263e8896768a74012837cb9cd85a6c01fe2e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT id\n FROM users\n WHERE name = $1\n ", + "query": "\n SELECT id\n FROM users\n WHERE login = $1\n ", "describe": { "columns": [ { @@ -18,5 +18,5 @@ false ] }, - "hash": "1e372913d39da6d53b2ef1c5f6e82b5b812644776c228d4f3da1b44059d7e514" + "hash": "3a6d252b20ad7fd73ff9decf1a5a263e8896768a74012837cb9cd85a6c01fe2e" } diff --git a/server/.sqlx/query-3c4d2d65488bc4304e5528b7c83c016d284232feb8e3180873b78b5ce4e5609c.json b/server/.sqlx/query-3c4d2d65488bc4304e5528b7c83c016d284232feb8e3180873b78b5ce4e5609c.json new file mode 100644 index 0000000..007b705 --- /dev/null +++ b/server/.sqlx/query-3c4d2d65488bc4304e5528b7c83c016d284232feb8e3180873b78b5ce4e5609c.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE users\n SET full_name = $2\n WHERE login = $1\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "3c4d2d65488bc4304e5528b7c83c016d284232feb8e3180873b78b5ce4e5609c" +} diff --git a/server/.sqlx/query-47d0040a2a85df6e20fd86576941278a0267fefd8af5f7432d5d0942045f9147.json b/server/.sqlx/query-47d0040a2a85df6e20fd86576941278a0267fefd8af5f7432d5d0942045f9147.json deleted file mode 100644 index d0c6ac7..0000000 --- a/server/.sqlx/query-47d0040a2a85df6e20fd86576941278a0267fefd8af5f7432d5d0942045f9147.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT full_name, image_base64, load_time\n FROM user_cached_metadata\n JOIN users u ON user_id = u.id\n WHERE u.name = $1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "full_name", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "image_base64", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "load_time", - "type_info": "Timestamp" - } - ], - "parameters": { - "Left": [ - "Text" - ] - }, - "nullable": [ - false, - false, - false - ] - }, - "hash": "47d0040a2a85df6e20fd86576941278a0267fefd8af5f7432d5d0942045f9147" -} diff --git a/server/.sqlx/query-4a8aa888147239609e339e96ecf098b1b51e391e93b63c5f73590007100f5349.json b/server/.sqlx/query-4a8aa888147239609e339e96ecf098b1b51e391e93b63c5f73590007100f5349.json new file mode 100644 index 0000000..cc29cac --- /dev/null +++ b/server/.sqlx/query-4a8aa888147239609e339e96ecf098b1b51e391e93b63c5f73590007100f5349.json @@ -0,0 +1,26 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT login, full_name\n FROM organizations", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "login", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "full_name", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + true + ] + }, + "hash": "4a8aa888147239609e339e96ecf098b1b51e391e93b63c5f73590007100f5349" +} diff --git a/server/.sqlx/query-59cefd3454bc060cbec64da575842112e683941ba2f41931edaa90b71b1784d0.json b/server/.sqlx/query-59cefd3454bc060cbec64da575842112e683941ba2f41931edaa90b71b1784d0.json new file mode 100644 index 0000000..f68901a --- /dev/null +++ b/server/.sqlx/query-59cefd3454bc060cbec64da575842112e683941ba2f41931edaa90b71b1784d0.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO organizations (login)\n VALUES ($1)\n ON CONFLICT (login) DO NOTHING\n RETURNING id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "59cefd3454bc060cbec64da575842112e683941ba2f41931edaa90b71b1784d0" +} diff --git a/server/.sqlx/query-6b3a9a77b1c069095c67db105dfedcbbb2be485cd8f5cebd2cd9f9f449bf1a20.json b/server/.sqlx/query-5dc98d0d987d8e6dda917c7c839600fb005df6574b6366411bdb37d31cab5e4a.json similarity index 54% rename from server/.sqlx/query-6b3a9a77b1c069095c67db105dfedcbbb2be485cd8f5cebd2cd9f9f449bf1a20.json rename to server/.sqlx/query-5dc98d0d987d8e6dda917c7c839600fb005df6574b6366411bdb37d31cab5e4a.json index bd2f098..4bc8b53 100644 --- a/server/.sqlx/query-6b3a9a77b1c069095c67db105dfedcbbb2be485cd8f5cebd2cd9f9f449bf1a20.json +++ b/server/.sqlx/query-5dc98d0d987d8e6dda917c7c839600fb005df6574b6366411bdb37d31cab5e4a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n UPDATE user_cached_metadata\n SET full_name = $2, image_base64 = $3, load_time = now()\n WHERE user_id = (SELECT id FROM users WHERE name = $1)\n RETURNING user_id\n ", + "query": "\n UPDATE user_cached_metadata\n SET image_base64 = $2, load_time = now()\n WHERE user_id = (SELECT id FROM users WHERE login = $1)\n RETURNING user_id\n ", "describe": { "columns": [ { @@ -11,7 +11,6 @@ ], "parameters": { "Left": [ - "Text", "Text", "Text" ] @@ -20,5 +19,5 @@ false ] }, - "hash": "6b3a9a77b1c069095c67db105dfedcbbb2be485cd8f5cebd2cd9f9f449bf1a20" + "hash": "5dc98d0d987d8e6dda917c7c839600fb005df6574b6366411bdb37d31cab5e4a" } diff --git a/server/.sqlx/query-d837b680c8f84885e92d0b1c9b98daf2d9ef4fd174cee42f50ea2240521abf5d.json b/server/.sqlx/query-67eb2d1983238f99a994c8509262024560c2a7759194fae5d6983b961300646c.json similarity index 57% rename from server/.sqlx/query-d837b680c8f84885e92d0b1c9b98daf2d9ef4fd174cee42f50ea2240521abf5d.json rename to server/.sqlx/query-67eb2d1983238f99a994c8509262024560c2a7759194fae5d6983b961300646c.json index 07a3fdc..a2d4858 100644 --- a/server/.sqlx/query-d837b680c8f84885e92d0b1c9b98daf2d9ef4fd174cee42f50ea2240521abf5d.json +++ b/server/.sqlx/query-67eb2d1983238f99a994c8509262024560c2a7759194fae5d6983b961300646c.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, permanent_bonus FROM users WHERE name = $1", + "query": "SELECT id, full_name, permanent_bonus FROM users \n WHERE login = $1", "describe": { "columns": [ { @@ -10,6 +10,11 @@ }, { "ordinal": 1, + "name": "full_name", + "type_info": "Text" + }, + { + "ordinal": 2, "name": "permanent_bonus", "type_info": "Int4" } @@ -21,8 +26,9 @@ }, "nullable": [ false, + true, false ] }, - "hash": "d837b680c8f84885e92d0b1c9b98daf2d9ef4fd174cee42f50ea2240521abf5d" + "hash": "67eb2d1983238f99a994c8509262024560c2a7759194fae5d6983b961300646c" } diff --git a/server/.sqlx/query-685549314e9958fc798d1330fff85796d8b4672be537c68bd023d5ebd7ba6adf.json b/server/.sqlx/query-685549314e9958fc798d1330fff85796d8b4672be537c68bd023d5ebd7ba6adf.json new file mode 100644 index 0000000..a546d5e --- /dev/null +++ b/server/.sqlx/query-685549314e9958fc798d1330fff85796d8b4672be537c68bd023d5ebd7ba6adf.json @@ -0,0 +1,26 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT login, full_name\n FROM users", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "login", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "full_name", + "type_info": "Text" + } + ], + "parameters": { + "Left": [] + }, + "nullable": [ + false, + true + ] + }, + "hash": "685549314e9958fc798d1330fff85796d8b4672be537c68bd023d5ebd7ba6adf" +} diff --git a/server/.sqlx/query-7c14c644826adb21fba8126afc90bbd69d1f012e6d54f353d74f525f7b123377.json b/server/.sqlx/query-7c14c644826adb21fba8126afc90bbd69d1f012e6d54f353d74f525f7b123377.json new file mode 100644 index 0000000..f617648 --- /dev/null +++ b/server/.sqlx/query-7c14c644826adb21fba8126afc90bbd69d1f012e6d54f353d74f525f7b123377.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT image_base64, load_time\n FROM user_cached_metadata\n JOIN users u ON user_id = u.id\n WHERE u.login = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "image_base64", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "load_time", + "type_info": "Timestamp" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "7c14c644826adb21fba8126afc90bbd69d1f012e6d54f353d74f525f7b123377" +} diff --git a/server/.sqlx/query-8bfaeb773397952288cdfaedc6bfc86f4f6d0806ce980133f71bcb606255ba10.json b/server/.sqlx/query-8bfaeb773397952288cdfaedc6bfc86f4f6d0806ce980133f71bcb606255ba10.json deleted file mode 100644 index 5818b64..0000000 --- a/server/.sqlx/query-8bfaeb773397952288cdfaedc6bfc86f4f6d0806ce980133f71bcb606255ba10.json +++ /dev/null @@ -1,71 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "WITH top_contributors AS (\n SELECT\n pr.repo_id,\n u.name AS contributor_name,\n SUM(pr.score) AS total_score,\n ROW_NUMBER() OVER (\n PARTITION BY pr.repo_id\n ORDER BY\n SUM(pr.score) DESC\n ) AS rank\n FROM\n pull_requests pr\n JOIN users u ON pr.author_id = u.id\n GROUP BY\n pr.repo_id,\n u.id\n)\nSELECT\n o.name AS organization,\n r.name AS name,\n COALESCE(COUNT(pr.id), 0) AS total_prs,\n COALESCE(SUM(pr.score), 0) AS total_score,\n tc.contributor_name AS top_contributor,\n r.primary_language,\n r.open_issues,\n r.stars,\n r.forks\nFROM\n repos r\n JOIN organizations o ON r.organization_id = o.id\n LEFT JOIN pull_requests pr ON pr.repo_id = r.id\n LEFT JOIN top_contributors tc ON tc.repo_id = r.id\n AND tc.rank = 1\nGROUP BY\n o.name,\n r.name,\n tc.contributor_name,\n r.primary_language,\n r.open_issues,\n r.stars,\n r.forks\nORDER BY\n total_prs DESC,\n total_score DESC\nLIMIT\n $1 OFFSET $2;\n", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "organization", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 2, - "name": "total_prs", - "type_info": "Int8" - }, - { - "ordinal": 3, - "name": "total_score", - "type_info": "Int8" - }, - { - "ordinal": 4, - "name": "top_contributor", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "primary_language", - "type_info": "Text" - }, - { - "ordinal": 6, - "name": "open_issues", - "type_info": "Int4" - }, - { - "ordinal": 7, - "name": "stars", - "type_info": "Int4" - }, - { - "ordinal": 8, - "name": "forks", - "type_info": "Int4" - } - ], - "parameters": { - "Left": [ - "Int8", - "Int8" - ] - }, - "nullable": [ - false, - false, - null, - null, - false, - true, - true, - true, - true - ] - }, - "hash": "8bfaeb773397952288cdfaedc6bfc86f4f6d0806ce980133f71bcb606255ba10" -} diff --git a/server/.sqlx/query-30a16d6f56b3c3f31ae89171e6767b8e32f2b5bd59ced2671fbc3a4f6ff0a52e.json b/server/.sqlx/query-a45ec4786689df719d3484e0369fe458436521320fda2e43a12fb5fda21e2e60.json similarity index 58% rename from server/.sqlx/query-30a16d6f56b3c3f31ae89171e6767b8e32f2b5bd59ced2671fbc3a4f6ff0a52e.json rename to server/.sqlx/query-a45ec4786689df719d3484e0369fe458436521320fda2e43a12fb5fda21e2e60.json index d3b65bb..a2023dc 100644 --- a/server/.sqlx/query-30a16d6f56b3c3f31ae89171e6767b8e32f2b5bd59ced2671fbc3a4f6ff0a52e.json +++ b/server/.sqlx/query-a45ec4786689df719d3484e0369fe458436521320fda2e43a12fb5fda21e2e60.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "select\n r.id as repo_id,\n r.name as repo,\n o.name as organization\nfrom\n repos as r\n JOIN organizations o ON r.organization_id = o.id\n", + "query": "select\n r.id as repo_id,\n r.name as repo,\n o.login as organization,\n o.full_name as organization_full_name\nfrom\n repos as r\n JOIN organizations o ON r.organization_id = o.id\n", "describe": { "columns": [ { @@ -17,6 +17,11 @@ "ordinal": 2, "name": "organization", "type_info": "Text" + }, + { + "ordinal": 3, + "name": "organization_full_name", + "type_info": "Text" } ], "parameters": { @@ -25,8 +30,9 @@ "nullable": [ false, false, - false + false, + true ] }, - "hash": "30a16d6f56b3c3f31ae89171e6767b8e32f2b5bd59ced2671fbc3a4f6ff0a52e" + "hash": "a45ec4786689df719d3484e0369fe458436521320fda2e43a12fb5fda21e2e60" } diff --git a/server/.sqlx/query-03d60c54fabe2b3c31df9a6c6f24c5114b4959a9df410db8a9bfd6a6bef5bd2d.json b/server/.sqlx/query-d1e176a1263f3e90e5a92608643017036cfbca2de09f1105dbd55647268c89c2.json similarity index 56% rename from server/.sqlx/query-03d60c54fabe2b3c31df9a6c6f24c5114b4959a9df410db8a9bfd6a6bef5bd2d.json rename to server/.sqlx/query-d1e176a1263f3e90e5a92608643017036cfbca2de09f1105dbd55647268c89c2.json index c869b88..291f588 100644 --- a/server/.sqlx/query-03d60c54fabe2b3c31df9a6c6f24c5114b4959a9df410db8a9bfd6a6bef5bd2d.json +++ b/server/.sqlx/query-d1e176a1263f3e90e5a92608643017036cfbca2de09f1105dbd55647268c89c2.json @@ -1,16 +1,16 @@ { "db_name": "PostgreSQL", - "query": "SELECT\n users.name as name,\n o.name as organization,\n r.name as repo,\n pr.number as number,\n pr.created_at as created_at,\n pr.merged_at as merged_at,\n pr.score as score,\n pr.executed as executed,\n pr.permanent_bonus as percentage_multiplier,\n pr.streak_bonus as streak_bonus_rating,\n pr.rating as rating\nFROM\n users\n JOIN pull_requests pr ON pr.author_id = users.id\n JOIN repos r ON pr.repo_id = r.id\n JOIN organizations o ON r.organization_id = o.id\nWHERE\n users.name = $1\nGROUP BY\n users.name,\n o.name,\n r.name,\n pr.number,\n pr.created_at,\n pr.merged_at,\n pr.score,\n pr.executed,\n pr.permanent_bonus,\n pr.streak_bonus,\n pr.rating\nORDER BY\n pr.created_at DESC\nLIMIT\n $2 OFFSET $3\n", + "query": "SELECT\n o.login as organization_login,\n o.full_name as organization_full_name,\n r.name as repo,\n pr.number as number,\n pr.created_at as created_at,\n pr.merged_at as merged_at,\n pr.score as score,\n pr.executed as executed,\n pr.permanent_bonus as percentage_multiplier,\n pr.streak_bonus as streak_bonus_rating,\n pr.rating as rating\nFROM\n users\n JOIN pull_requests pr ON pr.author_id = users.id\n JOIN repos r ON pr.repo_id = r.id\n JOIN organizations o ON r.organization_id = o.id\nWHERE\n users.login = $1\nGROUP BY\n o.login,\n o.full_name,\n r.name,\n pr.number,\n pr.created_at,\n pr.merged_at,\n pr.score,\n pr.executed,\n pr.permanent_bonus,\n pr.streak_bonus,\n pr.rating\nORDER BY\n pr.created_at DESC\nLIMIT\n $2 OFFSET $3\n", "describe": { "columns": [ { "ordinal": 0, - "name": "name", + "name": "organization_login", "type_info": "Text" }, { "ordinal": 1, - "name": "organization", + "name": "organization_full_name", "type_info": "Text" }, { @@ -68,7 +68,7 @@ }, "nullable": [ false, - false, + true, false, false, false, @@ -80,5 +80,5 @@ false ] }, - "hash": "03d60c54fabe2b3c31df9a6c6f24c5114b4959a9df410db8a9bfd6a6bef5bd2d" + "hash": "d1e176a1263f3e90e5a92608643017036cfbca2de09f1105dbd55647268c89c2" } diff --git a/server/.sqlx/query-da25415073c344a2a6b4a797f3911b99cc5c2f9c784cbed28f749a969510bb85.json b/server/.sqlx/query-da25415073c344a2a6b4a797f3911b99cc5c2f9c784cbed28f749a969510bb85.json deleted file mode 100644 index 9f95816..0000000 --- a/server/.sqlx/query-da25415073c344a2a6b4a797f3911b99cc5c2f9c784cbed28f749a969510bb85.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT users.name, SUM(pr.score) as total_score\n FROM organizations o\n JOIN repos r ON r.organization_id = o.id\n JOIN pull_requests pr ON pr.repo_id = r.id\n JOIN users ON pr.author_id = users.id\n WHERE pr.created_at >= (now() - INTERVAL '1 MONTH')\n AND r.name = $1\n AND o.name = $2\n GROUP BY users.name\n ORDER BY COUNT(pr.id) DESC\n LIMIT 3\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "name", - "type_info": "Text" - }, - { - "ordinal": 1, - "name": "total_score", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Text", - "Text" - ] - }, - "nullable": [ - false, - null - ] - }, - "hash": "da25415073c344a2a6b4a797f3911b99cc5c2f9c784cbed28f749a969510bb85" -} diff --git a/server/.sqlx/query-e896f0f165b24540cf91b975c894564aa4e5c85d92a897747f392576a7eeedb5.json b/server/.sqlx/query-e896f0f165b24540cf91b975c894564aa4e5c85d92a897747f392576a7eeedb5.json new file mode 100644 index 0000000..8c18449 --- /dev/null +++ b/server/.sqlx/query-e896f0f165b24540cf91b975c894564aa4e5c85d92a897747f392576a7eeedb5.json @@ -0,0 +1,83 @@ +{ + "db_name": "PostgreSQL", + "query": "WITH top_contributors AS (\n SELECT\n pr.repo_id,\n u.login AS contributor_login,\n u.full_name AS contributor_full_name,\n SUM(pr.score) AS total_score,\n ROW_NUMBER() OVER (\n PARTITION BY pr.repo_id\n ORDER BY\n SUM(pr.score) DESC\n ) AS rank\n FROM\n pull_requests pr\n JOIN users u ON pr.author_id = u.id\n GROUP BY\n pr.repo_id,\n u.id\n)\nSELECT\n o.login AS organization,\n o.full_name AS organization_full_name,\n r.name AS name,\n COALESCE(COUNT(pr.id), 0) AS total_prs,\n COALESCE(SUM(pr.score), 0) AS total_score,\n tc.contributor_full_name AS contributor_full_name,\n tc.contributor_login AS contributor_login,\n r.primary_language,\n r.open_issues,\n r.stars,\n r.forks\nFROM\n repos r\n JOIN organizations o ON r.organization_id = o.id\n LEFT JOIN pull_requests pr ON pr.repo_id = r.id\n LEFT JOIN top_contributors tc ON tc.repo_id = r.id\n AND tc.rank = 1\nGROUP BY\n o.login,\n o.full_name,\n r.name,\n tc.contributor_login,\n tc.contributor_full_name,\n r.primary_language,\n r.open_issues,\n r.stars,\n r.forks\nORDER BY\n total_prs DESC,\n total_score DESC\nLIMIT\n $1 OFFSET $2;\n", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "organization", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "organization_full_name", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "name", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "total_prs", + "type_info": "Int8" + }, + { + "ordinal": 4, + "name": "total_score", + "type_info": "Int8" + }, + { + "ordinal": 5, + "name": "contributor_full_name", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "contributor_login", + "type_info": "Text" + }, + { + "ordinal": 7, + "name": "primary_language", + "type_info": "Text" + }, + { + "ordinal": 8, + "name": "open_issues", + "type_info": "Int4" + }, + { + "ordinal": 9, + "name": "stars", + "type_info": "Int4" + }, + { + "ordinal": 10, + "name": "forks", + "type_info": "Int4" + } + ], + "parameters": { + "Left": [ + "Int8", + "Int8" + ] + }, + "nullable": [ + false, + true, + false, + null, + null, + true, + false, + true, + true, + true, + true + ] + }, + "hash": "e896f0f165b24540cf91b975c894564aa4e5c85d92a897747f392576a7eeedb5" +} diff --git a/server/.sqlx/query-e9547c4ba525b565b29439b8022ba11c3f470516945c606bbf9b4e1398701ac8.json b/server/.sqlx/query-e9547c4ba525b565b29439b8022ba11c3f470516945c606bbf9b4e1398701ac8.json deleted file mode 100644 index 78ae22e..0000000 --- a/server/.sqlx/query-e9547c4ba525b565b29439b8022ba11c3f470516945c606bbf9b4e1398701ac8.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO user_cached_metadata (user_id, full_name, image_base64, load_time)\n VALUES ((SELECT id FROM users WHERE name = $1), $2, $3, now())\n ON CONFLICT (user_id) DO NOTHING\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Text", - "Text", - "Text" - ] - }, - "nullable": [] - }, - "hash": "e9547c4ba525b565b29439b8022ba11c3f470516945c606bbf9b4e1398701ac8" -} diff --git a/server/.sqlx/query-f16f7eeba56dc74b3a3dd3f8975e8b08a0d6cfdfdb15ca102a5d2887a4d6a8d7.json b/server/.sqlx/query-f16f7eeba56dc74b3a3dd3f8975e8b08a0d6cfdfdb15ca102a5d2887a4d6a8d7.json new file mode 100644 index 0000000..38da7e8 --- /dev/null +++ b/server/.sqlx/query-f16f7eeba56dc74b3a3dd3f8975e8b08a0d6cfdfdb15ca102a5d2887a4d6a8d7.json @@ -0,0 +1,29 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT users.login, SUM(pr.score) as total_score\n FROM organizations o\n JOIN repos r ON r.organization_id = o.id\n JOIN pull_requests pr ON pr.repo_id = r.id\n JOIN users ON pr.author_id = users.id\n WHERE pr.created_at >= (now() - INTERVAL '1 MONTH')\n AND r.name = $1\n AND o.login = $2\n GROUP BY users.login\n ORDER BY COUNT(pr.id) DESC\n LIMIT 3\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "login", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "total_score", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [ + false, + null + ] + }, + "hash": "f16f7eeba56dc74b3a3dd3f8975e8b08a0d6cfdfdb15ca102a5d2887a4d6a8d7" +} diff --git a/server/.sqlx/query-16f5688f235e51d2e2290f0a190d7308cd0a7b003205822f50ca5fd71c53763e.json b/server/.sqlx/query-f2a1f58ce3c430838ed5aedfcc44a7425e45cb7687cb33880e315427afe2bd5a.json similarity index 74% rename from server/.sqlx/query-16f5688f235e51d2e2290f0a190d7308cd0a7b003205822f50ca5fd71c53763e.json rename to server/.sqlx/query-f2a1f58ce3c430838ed5aedfcc44a7425e45cb7687cb33880e315427afe2bd5a.json index 84d76d9..f88fc35 100644 --- a/server/.sqlx/query-16f5688f235e51d2e2290f0a190d7308cd0a7b003205822f50ca5fd71c53763e.json +++ b/server/.sqlx/query-f2a1f58ce3c430838ed5aedfcc44a7425e45cb7687cb33880e315427afe2bd5a.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT COUNT(DISTINCT(pr.id)) as id\n FROM pull_requests pr\n JOIN users ON pr.author_id = users.id\n WHERE users.name = $1\n ", + "query": "SELECT COUNT(DISTINCT(pr.id)) as id\n FROM pull_requests pr\n JOIN users ON pr.author_id = users.id\n WHERE users.login = $1\n ", "describe": { "columns": [ { @@ -18,5 +18,5 @@ null ] }, - "hash": "16f5688f235e51d2e2290f0a190d7308cd0a7b003205822f50ca5fd71c53763e" + "hash": "f2a1f58ce3c430838ed5aedfcc44a7425e45cb7687cb33880e315427afe2bd5a" } diff --git a/server/migrations/20240526132957_create-table.sql b/server/migrations/20240526132957_create-table.sql index 96b1823..4856ebc 100644 --- a/server/migrations/20240526132957_create-table.sql +++ b/server/migrations/20240526132957_create-table.sql @@ -1,6 +1,7 @@ CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, - name TEXT UNIQUE NOT NULL + login TEXT UNIQUE NOT NULL, + full_name TEXT ); CREATE TABLE IF NOT EXISTS user_period_data ( diff --git a/server/migrations/20240605105927_prs_and_repo_data.sql b/server/migrations/20240605105927_prs_and_repo_data.sql index 2f4cf8a..c241fc0 100644 --- a/server/migrations/20240605105927_prs_and_repo_data.sql +++ b/server/migrations/20240605105927_prs_and_repo_data.sql @@ -1,6 +1,7 @@ CREATE TABLE IF NOT EXISTS organizations ( id SERIAL PRIMARY KEY, - name TEXT UNIQUE NOT NULL + login TEXT UNIQUE NOT NULL, + full_name TEXT ); CREATE TABLE IF NOT EXISTS repos ( diff --git a/server/migrations/20240612131906_user-cache.sql b/server/migrations/20240612131906_user-cache.sql index f08e190..5085c96 100644 --- a/server/migrations/20240612131906_user-cache.sql +++ b/server/migrations/20240612131906_user-cache.sql @@ -1,7 +1,6 @@ -- Add migration script here CREATE TABLE IF NOT EXISTS user_cached_metadata ( user_id INTEGER PRIMARY KEY, - full_name TEXT NOT NULL, image_base64 TEXT NOT NULL, load_time TIMESTAMP NOT NULL, FOREIGN KEY (user_id) REFERENCES users(id) diff --git a/server/sql/get_leaderboard.sql b/server/sql/get_leaderboard.sql index eca0c85..0b77f17 100644 --- a/server/sql/get_leaderboard.sql +++ b/server/sql/get_leaderboard.sql @@ -1,5 +1,6 @@ SELECT - users.name, + users.login, + users.full_name, period_type, total_score, executed_prs, diff --git a/server/sql/get_repo_leaderboard.sql b/server/sql/get_repo_leaderboard.sql index 4f6a054..0cfa997 100644 --- a/server/sql/get_repo_leaderboard.sql +++ b/server/sql/get_repo_leaderboard.sql @@ -1,7 +1,8 @@ WITH top_contributors AS ( SELECT pr.repo_id, - u.name AS contributor_name, + u.login AS contributor_login, + u.full_name AS contributor_full_name, SUM(pr.score) AS total_score, ROW_NUMBER() OVER ( PARTITION BY pr.repo_id @@ -16,11 +17,13 @@ WITH top_contributors AS ( u.id ) SELECT - o.name AS organization, + o.login AS organization, + o.full_name AS organization_full_name, r.name AS name, COALESCE(COUNT(pr.id), 0) AS total_prs, COALESCE(SUM(pr.score), 0) AS total_score, - tc.contributor_name AS top_contributor, + tc.contributor_full_name AS contributor_full_name, + tc.contributor_login AS contributor_login, r.primary_language, r.open_issues, r.stars, @@ -32,9 +35,11 @@ FROM LEFT JOIN top_contributors tc ON tc.repo_id = r.id AND tc.rank = 1 GROUP BY - o.name, + o.login, + o.full_name, r.name, - tc.contributor_name, + tc.contributor_login, + tc.contributor_full_name, r.primary_language, r.open_issues, r.stars, diff --git a/server/sql/get_repos.sql b/server/sql/get_repos.sql index cce8f67..fbfdac2 100644 --- a/server/sql/get_repos.sql +++ b/server/sql/get_repos.sql @@ -1,7 +1,8 @@ select r.id as repo_id, r.name as repo, - o.name as organization + o.login as organization, + o.full_name as organization_full_name from repos as r JOIN organizations o ON r.organization_id = o.id diff --git a/server/sql/get_user_contributions.sql b/server/sql/get_user_contributions.sql index a3ef2f9..b459048 100644 --- a/server/sql/get_user_contributions.sql +++ b/server/sql/get_user_contributions.sql @@ -1,6 +1,6 @@ SELECT - users.name as name, - o.name as organization, + o.login as organization_login, + o.full_name as organization_full_name, r.name as repo, pr.number as number, pr.created_at as created_at, @@ -16,10 +16,10 @@ FROM JOIN repos r ON pr.repo_id = r.id JOIN organizations o ON r.organization_id = o.id WHERE - users.name = $1 + users.login = $1 GROUP BY - users.name, - o.name, + o.login, + o.full_name, r.name, pr.number, pr.created_at, diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index 1618356..62b24c6 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -15,8 +15,8 @@ pub mod types; use types::LeaderboardRecord; use self::types::{ - RepoLeaderboardRecord, RepoRecord, StreakRecord, UserCachedMetadata, UserContributionRecord, - UserPeriodRecord, UserRecord, + RepoLeaderboardRecord, RepoRecord, StreakRecord, User, UserCachedMetadata, + UserContributionRecord, UserPeriodRecord, UserRecord, }; impl DB { @@ -26,7 +26,7 @@ impl DB { r#" UPDATE users SET permanent_bonus = $2 - WHERE name = $1 + WHERE login = $1 RETURNING id "#, user, @@ -41,9 +41,9 @@ impl DB { } else { let rec = sqlx::query!( r#" - INSERT INTO users (name, permanent_bonus) + INSERT INTO users (login, permanent_bonus) VALUES ($1, $2) - ON CONFLICT (name) DO NOTHING + ON CONFLICT (login) DO NOTHING RETURNING id "#, user, @@ -56,13 +56,47 @@ impl DB { } } + pub async fn update_user_full_name(&self, user: &str, full_name: &str) -> anyhow::Result<()> { + sqlx::query!( + r#" + UPDATE users + SET full_name = $2 + WHERE login = $1 + "#, + user, + full_name + ) + .execute(&self.0) + .await?; + Ok(()) + } + + pub async fn update_organization_full_name( + &self, + organization: &str, + full_name: &str, + ) -> anyhow::Result<()> { + sqlx::query!( + r#" + UPDATE organizations + SET full_name = $2 + WHERE login = $1 + "#, + organization, + full_name + ) + .execute(&self.0) + .await?; + Ok(()) + } + pub async fn upsert_organization(&self, name: &str) -> anyhow::Result { // First try to update the organization let rec = sqlx::query!( r#" UPDATE organizations - SET name = $1 - WHERE name = $1 + SET login = $1 + WHERE login = $1 RETURNING id "#, name @@ -76,9 +110,9 @@ impl DB { } else { let rec = sqlx::query!( r#" - INSERT INTO organizations (name) + INSERT INTO organizations (login) VALUES ($1) - ON CONFLICT (name) DO NOTHING + ON CONFLICT (login) DO NOTHING RETURNING id "#, name @@ -308,17 +342,18 @@ impl DB { pub async fn get_user( &self, - name: &str, + login: &str, place_strings: &[String], ) -> anyhow::Result> { - let (user_rec, percent) = match sqlx::query!( - "SELECT id, permanent_bonus FROM users WHERE name = $1", - name + let (user_rec, full_name, percent) = match sqlx::query!( + "SELECT id, full_name, permanent_bonus FROM users + WHERE login = $1", + login ) .fetch_optional(&self.0) .await? { - Some(rec) => (rec.id, rec.permanent_bonus), + Some(rec) => (rec.id, rec.full_name, rec.permanent_bonus), None => return Ok(None), }; @@ -346,7 +381,8 @@ impl DB { } let user = UserRecord { - name: name.to_string(), + login: login.to_string(), + name: full_name, lifetime_percent: percent, period_data: period_data_recs, streaks: streak_recs, @@ -450,7 +486,7 @@ impl DB { r#"SELECT COUNT(DISTINCT(pr.id)) as id FROM pull_requests pr JOIN users ON pr.author_id = users.id - WHERE users.name = $1 + WHERE users.login = $1 "#, user ) @@ -466,15 +502,15 @@ impl DB { ) -> anyhow::Result> { let rec = sqlx::query!( r#" - SELECT users.name, SUM(pr.score) as total_score + SELECT users.login, SUM(pr.score) as total_score FROM organizations o JOIN repos r ON r.organization_id = o.id JOIN pull_requests pr ON pr.repo_id = r.id JOIN users ON pr.author_id = users.id WHERE pr.created_at >= (now() - INTERVAL '1 MONTH') AND r.name = $1 - AND o.name = $2 - GROUP BY users.name + AND o.login = $2 + GROUP BY users.login ORDER BY COUNT(pr.id) DESC LIMIT 3 "#, @@ -486,7 +522,7 @@ impl DB { Ok(rec .into_iter() - .map(|r| (r.name, r.total_score.unwrap_or_default())) + .map(|r| (r.login, r.total_score.unwrap_or_default())) .collect()) } @@ -498,6 +534,32 @@ impl DB { Ok(rec) } + pub async fn get_users(&self) -> anyhow::Result> { + let rec = sqlx::query_as!( + User, + r#" + SELECT login, full_name + FROM users"# + ) + .fetch_all(&self.0) + .await?; + + Ok(rec) + } + + pub async fn get_organizations(&self) -> anyhow::Result> { + let rec = sqlx::query_as!( + User, + r#" + SELECT login, full_name + FROM organizations"# + ) + .fetch_all(&self.0) + .await?; + + Ok(rec) + } + pub async fn clear_prs(&self) -> anyhow::Result<()> { sqlx::query!("DELETE FROM pull_requests") .execute(&self.0) @@ -510,7 +572,7 @@ impl DB { r#" SELECT id FROM users - WHERE name = $1 + WHERE login = $1 "#, name ) @@ -527,10 +589,10 @@ impl DB { Ok(sqlx::query_as!( UserCachedMetadata, r#" - SELECT full_name, image_base64, load_time + SELECT image_base64, load_time FROM user_cached_metadata JOIN users u ON user_id = u.id - WHERE u.name = $1 + WHERE u.login = $1 "#, username ) @@ -541,19 +603,17 @@ impl DB { pub async fn upsert_user_cached_metadata( &self, username: &str, - full_name: &str, image_base64: &str, ) -> anyhow::Result<()> { // First try to update the user let rec = sqlx::query!( r#" UPDATE user_cached_metadata - SET full_name = $2, image_base64 = $3, load_time = now() - WHERE user_id = (SELECT id FROM users WHERE name = $1) + SET image_base64 = $2, load_time = now() + WHERE user_id = (SELECT id FROM users WHERE login = $1) RETURNING user_id "#, username, - full_name, image_base64 ) .fetch_optional(&self.0) @@ -563,12 +623,11 @@ impl DB { if rec.is_none() { sqlx::query!( r#" - INSERT INTO user_cached_metadata (user_id, full_name, image_base64, load_time) - VALUES ((SELECT id FROM users WHERE name = $1), $2, $3, now()) + INSERT INTO user_cached_metadata (user_id, image_base64, load_time) + VALUES ((SELECT id FROM users WHERE login = $1), $2, now()) ON CONFLICT (user_id) DO NOTHING "#, username, - full_name, image_base64 ) .execute(&self.0) diff --git a/server/src/db/types.rs b/server/src/db/types.rs index 616a2d8..d4707ce 100644 --- a/server/src/db/types.rs +++ b/server/src/db/types.rs @@ -2,7 +2,8 @@ use serde::{Deserialize, Serialize}; use shared::{GithubHandle, TimePeriodString}; #[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)] pub struct LeaderboardRecord { - pub name: String, + pub login: String, + pub full_name: Option, pub total_score: i32, pub total_rating: i32, pub period_type: TimePeriodString, @@ -38,9 +39,16 @@ pub struct StreakRecord { pub latest_time_string: String, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct User { + pub login: String, + pub full_name: Option, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UserRecord { - pub name: String, + pub login: String, + pub name: Option, pub lifetime_percent: i32, pub period_data: Vec, pub streaks: Vec, @@ -48,9 +56,10 @@ pub struct UserRecord { } impl UserRecord { - pub fn newcommer(name: String) -> Self { + pub fn newcommer(login: String) -> Self { Self { - name, + login, + name: None, period_data: vec![], streaks: vec![], leaderboard_places: vec![], @@ -62,10 +71,12 @@ impl UserRecord { #[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)] pub struct RepoLeaderboardRecord { pub organization: String, + pub organization_full_name: Option, pub name: String, pub total_prs: i64, pub total_score: i64, - pub top_contributor: Option, + pub contributor_login: Option, + pub contributor_full_name: Option, pub stars: i32, pub open_issues: i32, pub primary_language: Option, @@ -74,8 +85,8 @@ pub struct RepoLeaderboardRecord { #[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)] pub struct UserContributionRecord { - pub name: String, - pub organization: String, + pub organization_login: String, + pub organization_full_name: Option, pub repo: String, pub number: i32, pub score: Option, @@ -91,12 +102,12 @@ pub struct UserContributionRecord { pub struct RepoRecord { pub organization: String, pub repo: String, + pub organization_full_name: Option, pub repo_id: i32, } #[derive(Debug, Clone, sqlx::FromRow, Serialize, Deserialize)] pub struct UserCachedMetadata { - pub full_name: String, pub image_base64: String, pub load_time: chrono::NaiveDateTime, } diff --git a/server/src/entrypoints/types.rs b/server/src/entrypoints/types.rs index e491e84..1debcbc 100644 --- a/server/src/entrypoints/types.rs +++ b/server/src/entrypoints/types.rs @@ -34,14 +34,15 @@ impl PaginatedResponse { #[derive(Clone, Debug, Serialize, Deserialize, ToSchema)] pub struct GithubMeta { - name: String, + login: String, + name: Option, image: String, } impl GithubMeta { - pub fn new(name: String) -> Self { - let image = format!("https://github.com/{}.png", name); - Self { name, image } + pub fn new(login: String, name: Option) -> Self { + let image = format!("https://github.com/{}.png", login); + Self { login, name, image } } } @@ -53,7 +54,7 @@ pub struct RepoResponse { pub stars: u32, pub forks: u32, pub open_issues: u32, - pub contributor_of_the_month: Option, + pub contributor_of_the_month: Option, pub contributions_with_sloth: u32, pub total_score: u32, } @@ -62,12 +63,14 @@ impl From for RepoResponse { fn from(record: RepoLeaderboardRecord) -> Self { Self { name: record.name, - organization: GithubMeta::new(record.organization), + organization: GithubMeta::new(record.organization, record.organization_full_name), repo_language: record.primary_language, stars: record.stars as u32, forks: record.forks as u32, open_issues: record.open_issues as u32, - contributor_of_the_month: record.top_contributor, + contributor_of_the_month: record + .contributor_login + .map(|login| GithubMeta::new(login, record.contributor_full_name)), contributions_with_sloth: record.total_prs as u32, total_score: record.total_score as u32, } @@ -87,7 +90,7 @@ pub struct LeaderboardResponse { impl From for LeaderboardResponse { fn from(record: LeaderboardRecord) -> Self { Self { - user: GithubMeta::new(record.name), + user: GithubMeta::new(record.login, record.full_name), rating: record.total_rating as u32, contributions: record.prs_opened as u32, streak: Streak::new( @@ -165,7 +168,7 @@ impl From for UserProfile { .map(|x| (x.prs_opened, x.total_rating)) .unwrap_or_default(); Self { - user: GithubMeta::new(record.name), + user: GithubMeta::new(record.login, record.name), rating: rating as u32, contributions: contributions as u32, streaks: record @@ -207,7 +210,7 @@ impl From for UserContributionResponse { fn from(record: UserContributionRecord) -> Self { let pull_request_link = format!( "https://github.com/{}/{}/pull/{}", - record.organization, record.repo, record.number + record.organization_login, record.repo, record.number ); let status = if record.executed { @@ -223,7 +226,7 @@ impl From for UserContributionResponse { Self { pull_request_link, repository: record.repo, - organization: GithubMeta::new(record.organization), + organization: GithubMeta::new(record.organization_login, record.organization_full_name), status: status.to_string(), score: record.score, created_at: record.created_at, diff --git a/server/src/entrypoints/user.rs b/server/src/entrypoints/user.rs index d18c7fa..68dead0 100644 --- a/server/src/entrypoints/user.rs +++ b/server/src/entrypoints/user.rs @@ -68,7 +68,6 @@ async fn fetch_user_metadata_lazily( let user = client.get_user(username).await?; let user_image_url = user.avatar_url; - let full_name = user.name.unwrap_or_else(|| format!("@{}", username)); let res = client.octocrab._get(user_image_url.as_str()).await?; @@ -76,11 +75,10 @@ async fn fetch_user_metadata_lazily( let image_base64 = base64::engine::general_purpose::STANDARD.encode(image); - db.upsert_user_cached_metadata(username, &full_name, &image_base64) + db.upsert_user_cached_metadata(username, &image_base64) .await?; Ok(UserCachedMetadata { - full_name, image_base64, load_time: chrono::Utc::now().naive_utc(), }) diff --git a/server/src/github_pull.rs b/server/src/github_pull.rs index 4fc1be8..f339f10 100644 --- a/server/src/github_pull.rs +++ b/server/src/github_pull.rs @@ -61,6 +61,38 @@ async fn fetch_repos_metadata(github: &GithubClient, db: &DB) -> anyhow::Result< Ok(()) } +async fn fetch_missing_user_organization_metadata( + github: &GithubClient, + db: &DB, +) -> anyhow::Result<()> { + let users = db.get_users().await?; + for user in users { + if user.full_name.is_some() { + // TODO: add user entry to sync cache + continue; + } + + let profile = github.get_user(&user.login).await?; + if let Some(full_name) = &profile.name { + db.update_user_full_name(&user.login, full_name).await?; + } + } + + let orgs = db.get_organizations().await?; + for org in orgs { + if org.full_name.is_some() { + continue; + } + + let profile = github.get_user(&org.login).await?; + if let Some(full_name) = &profile.name { + db.update_organization_full_name(&org.login, full_name) + .await?; + } + } + Ok(()) +} + pub fn stage( github_client: GithubClient, sleep_duration: Duration, @@ -94,6 +126,16 @@ pub fn stage( e ); } + + if let Err(e) = + fetch_missing_user_organization_metadata(&github_client, &db) + .await + { + rocket::error!( + "Failed to fetch and store github data: {:#?}", + e + ); + } } }); }) diff --git a/server/src/svg.rs b/server/src/svg.rs index ac37b25..37bef3b 100644 --- a/server/src/svg.rs +++ b/server/src/svg.rs @@ -35,7 +35,12 @@ pub fn generate_svg_badge( .unwrap_or_else(|| "N/A".to_string()); let svg_icon = std::fs::read_to_string("./public/badge_template.svg")?; - let svg_icon = svg_icon.replace("{name}", &user_metadata.full_name); + let svg_icon = svg_icon.replace( + "{name}", + &user_record + .name + .unwrap_or_else(|| format!("@{}", user_record.login)), + ); let svg_icon = svg_icon.replace( "{total-contributions}", &total_period.prs_opened.to_string(),