Skip to content

Commit dcda271

Browse files
committed
📦 login reward + fix
1 parent ef991f9 commit dcda271

File tree

6 files changed

+58
-39
lines changed

6 files changed

+58
-39
lines changed

‎api/src/routes/common/discord_auth.rs‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ async fn verify_discord_token(token: &str) -> Result<DiscordUser, DiscordAuthErr
7575
.send()
7676
.await;
7777

78-
println!("Response: {response:?}");
79-
8078
match response {
8179
Ok(resp) => {
8280
if resp.status().is_success() {

‎api/src/routes/userinfo.rs‎

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ pub struct ErrorResponse {
4848
pub struct UserInfoRequest {
4949
pub user_id: String,
5050
pub email: Option<String>,
51+
pub from_admin: bool
5152
}
5253

5354
#[get("/userinfo")]
@@ -62,59 +63,43 @@ pub async fn get_userinfo_by_id(
6263
auth: DiscordAuth,
6364
user_id: Option<&str>,
6465
) -> Result<Json<FlatUserInfoResponse>, Status> {
65-
let is_specific_user = user_id.is_some();
6666
let target_user_id = user_id
6767
.map(|s| s.to_string())
6868
.unwrap_or_else(|| auth.0.id.clone());
69-
println!("Looking for user ID: {target_user_id}");
7069

7170
// Check if the authenticated user can access this user's data
7271
if !auth.can_access_user(&target_user_id) {
73-
println!("Access denied for user: {target_user_id}");
7472
return Err(Status::Forbidden);
7573
}
7674

77-
get_userinfo_by_user_id(auth, target_user_id, is_specific_user).await
75+
let from_admin: bool = auth.0.id != target_user_id;
76+
get_userinfo_by_user_id(auth, target_user_id, from_admin).await
7877
}
7978

8079
async fn get_userinfo_by_user_id(
8180
auth: DiscordAuth,
8281
user_id: String,
83-
is_specific_user: bool,
82+
from_admin: bool,
8483
) -> Result<Json<FlatUserInfoResponse>, Status> {
85-
println!("Looking for user with ID: {user_id}");
86-
8784
// Make request to Killua bot
8885
// Don't send email if this is a specific user request (admin accessing other user's data)
89-
let email = if is_specific_user {
86+
let email = if from_admin {
9087
None
9188
} else {
9289
auth.0.email.clone()
9390
};
94-
let request_data = UserInfoRequest { user_id, email };
91+
let request_data = UserInfoRequest { user_id, email, from_admin };
9592

9693
match make_request("user/info", request_data, 0_u8).await {
9794
Ok(response) => {
98-
println!("Response: {response}");
9995
match serde_json::from_str::<FlatUserInfoResponse>(&response) {
10096
Ok(user_data) => {
101-
println!("Successfully retrieved user data");
10297
Ok(Json(user_data))
10398
}
104-
Err(_e) => match serde_json::from_str::<ErrorResponse>(&response) {
105-
Ok(error) => {
106-
println!("Error: {0}", error.error);
107-
Err(Status::InternalServerError)
108-
}
109-
Err(e) => {
110-
println!("Unknown error: {e:?}");
111-
Err(Status::InternalServerError)
112-
}
113-
},
99+
Err(_e) => Err(Status::InternalServerError)
114100
}
115101
}
116-
Err(e) => {
117-
println!("Failed to get user info: {e:?}");
102+
Err(_e) => {
118103
Err(Status::InternalServerError)
119104
}
120105
}

‎killua/cogs/api.py‎

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from zmq import ROUTER, Poller, POLLIN
1010
from zmq.asyncio import Context
1111
from io import BytesIO
12-
from logging import warning, info
12+
from asyncio import create_task
1313
from PIL import Image, ImageDraw, ImageChops
1414

1515
from killua.bot import BaseBot
@@ -429,7 +429,9 @@ async def stats(self, _) -> dict:
429429
"guilds": len(self.client.guilds),
430430
"shards": self.client.shard_count,
431431
"registered_users": await DB.teams.count_documents({}),
432-
"user_installs": (await self.client.application_info()).approximate_user_install_count,
432+
"user_installs": (
433+
await self.client.application_info()
434+
).approximate_user_install_count,
433435
"last_restart": self.client.startup_datetime.timestamp(),
434436
}
435437

@@ -488,7 +490,7 @@ def jsonify(self, obj):
488490
"""Helper function to convert objects to JSON transferable format"""
489491
return self._convert_snowflakes(self._convert_datetime(obj))
490492

491-
async def user_info(self, data) -> dict:
493+
async def user_info(self, data: dict) -> dict:
492494
"""Gets user info by Discord ID and returns it with display name and avatar URL"""
493495
user_id = data.get("user_id")
494496
if not user_id:
@@ -515,7 +517,7 @@ async def user_info(self, data) -> dict:
515517

516518
# Return flat dictionary structure with all user data and Discord info
517519
response_data = {
518-
"id": user_data.id,
520+
"id": user_data.id,
519521
"email": user_data.email,
520522
"display_name": user.display_name,
521523
"avatar_url": str(user.avatar.url) if user.avatar else None,
@@ -537,9 +539,7 @@ async def user_info(self, data) -> dict:
537539
"lootboxes": user_data.lootboxes,
538540
"boosters": user_data.boosters,
539541
"weekly_cooldown": (
540-
user_data.weekly_cooldown
541-
if user_data.weekly_cooldown
542-
else None
542+
user_data.weekly_cooldown if user_data.weekly_cooldown else None
543543
),
544544
"action_settings": user_data.action_settings,
545545
"action_stats": user_data.action_stats,
@@ -549,7 +549,35 @@ async def user_info(self, data) -> dict:
549549
"premium_tier": user_data.premium_tier,
550550
}
551551

552+
if data.get("from_admin", False) is False:
553+
# Fire and forget background task
554+
create_task(self._register_login(user, user_data))
555+
552556
return self.jsonify(response_data)
553557

558+
async def _register_login(self, user: discord.User, user_data: User) -> None:
559+
"""The actual background work you want to do"""
560+
first_login = await user_data.register_login()
561+
if not first_login:
562+
return
563+
564+
# Add free golden lootbox and 1000 Jenny to user
565+
await user_data.add_lootbox(4)
566+
await user_data.add_jenny(1000)
567+
568+
# Try to send the user a DM about their reward
569+
if user:
570+
try:
571+
await user.send(
572+
embed=discord.Embed.from_dict(
573+
{
574+
"title": "Thank you for checking out Killua's new website!",
575+
"description": "You've received a free golden lootbox and 1000 Jenny!",
576+
"color": 0x3E4A78,
577+
}
578+
)
579+
)
580+
except discord.HTTPException:
581+
pass # Ignore failure
554582

555583
Cog = IPCRoutes

‎killua/cogs/dev.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,9 @@ async def api_stats(self, ctx: commands.Context):
352352
data = []
353353
for key, val in cast(dict, json["usage"]).items():
354354
if not key in API_ROUTES:
355-
spam += val["requests"]
355+
spam += val["request_count"]
356356
continue
357-
reqs: int = cast(dict, val).get("requests")
357+
reqs: int = cast(dict, val).get("request_count")
358358
successful_res: int = cast(dict, val).get("successful_responses")
359359

360360
embed.add_field(

‎killua/cogs/prometheus.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,16 @@ async def update_api_stats(self):
6464
reqs = 0
6565
not_spam = 0
6666
for key, val in cast(dict, json["usage"]).items():
67-
reqs += val["requests"]
67+
reqs += val["request_count"]
6868
if not key in API_ROUTES:
6969
continue
70-
not_spam += val["requests"]
71-
new_requests = val["requests"] - self.api_previous.get(key, {}).get(
72-
"requests", 0
70+
not_spam += val["request_count"]
71+
new_requests = val["request_count"] - self.api_previous.get(key, {}).get(
72+
"request_count", 0
7373
)
7474
if key not in self.api_previous:
7575
self.api_previous[key] = {}
76-
self.api_previous[key]["requests"] = val["requests"]
76+
self.api_previous[key]["request_count"] = val["request_count"]
7777
API_REQUESTS_COUNTER.labels(key, "requests").inc(amount=new_requests)
7878
new_success = val["successful_responses"] - self.api_previous.get(
7979
key, {}

‎killua/utils/classes/user.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,3 +815,11 @@ async def register_user_installed_usage(self) -> None:
815815
return # No unnecessary database calls
816816
self.has_user_installed = True
817817
await self._update_val("user_installed", True)
818+
819+
async def register_login(self) -> bool:
820+
"""Registers that a user logged into the website and returns True if it was the first time"""
821+
if "logged_into_website" in self.achievements:
822+
return False
823+
self.achievements.append("logged_into_website")
824+
await self._update_val("achievements", self.achievements)
825+
return True

0 commit comments

Comments
 (0)