• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / fx-private-relay / b2e067fe-ce4e-4099-9bef-07b368e99782

15 Apr 2024 04:18PM CUT coverage: 75.544% (+0.002%) from 75.542%
b2e067fe-ce4e-4099-9bef-07b368e99782

push

circleci

jwhitlock
Enable pyupgrade, fix issues

2443 of 3405 branches covered (71.75%)

Branch coverage included in aggregate %.

56 of 59 new or added lines in 14 files covered. (94.92%)

234 existing lines in 24 files now uncovered.

6793 of 8821 relevant lines covered (77.01%)

20.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.71
/privaterelay/management/commands/update_phone_remaining_stats.py
1
import logging
1✔
2
from datetime import UTC, datetime, timedelta
1✔
3

4
from django.conf import settings
1✔
5
from django.contrib.auth.models import User
1✔
6
from django.core.management.base import BaseCommand
1✔
7

8
from emails.models import Profile
1✔
9
from privaterelay.management.utils import (
1✔
10
    get_free_phone_social_accounts,
11
    get_phone_subscriber_social_accounts,
12
)
13

14
if settings.PHONES_ENABLED:
1!
15
    from phones.models import RelayNumber
1✔
16

17
logger = logging.getLogger("events")
1✔
18

19

20
def reset_phone_remaining_stats(user: User) -> None:
1✔
21
    # re-set remaining_texts and remaining_seconds to the maximum value
22
    try:
1✔
23
        relay_number = RelayNumber.objects.get(user=user)
1✔
24
    except RelayNumber.DoesNotExist:
1✔
25
        # no RelayNumber set, do nothing
26
        return
1✔
27
    relay_number.remaining_texts = settings.MAX_TEXTS_PER_BILLING_CYCLE
1✔
28
    relay_number.remaining_seconds = settings.MAX_MINUTES_PER_BILLING_CYCLE * 60
1✔
29
    relay_number.save()
1✔
30

31

32
def get_next_reset_date(profile: Profile) -> datetime:
1✔
33
    # TODO: consider moving this as a property in Profile model
34
    # assumes that profile being passed have already been checked to have
35
    # phone subscription or a free phone user
36
    if profile.date_phone_subscription_reset is None:
1✔
37
        # there is a problem with the sync_phone_related_dates_on_profile
38
        # or a new foxfooder whose date_phone_subscription_reset did not get set in
39
        if profile.fxa:
1!
40
            fxa_uid = profile.fxa.uid
1✔
41
        else:
UNCOV
42
            fxa_uid = "None"
×
43
        logger.error(
1✔
44
            "phone_user_profile_dates_not_set",
45
            extra={
46
                "fxa_uid": fxa_uid,
47
                "date_subscribed_phone": profile.date_phone_subscription_end,
48
                "date_phone_subscription_start": profile.date_phone_subscription_start,
49
                "date_phone_subscription_reset": profile.date_phone_subscription_reset,
50
                "date_phone_subscription_end": profile.date_phone_subscription_end,
51
            },
52
        )
53
        return datetime.now(UTC) - timedelta(minutes=15)
1✔
54

55
    calculated_next_reset_date = profile.date_phone_subscription_reset + timedelta(
1✔
56
        settings.MAX_DAYS_IN_MONTH
57
    )
58
    if profile.date_phone_subscription_end is None:
1✔
59
        return calculated_next_reset_date
1✔
60
    if profile.date_phone_subscription_end < calculated_next_reset_date:
1✔
61
        # return the past or the closest next reset date
62
        return profile.date_phone_subscription_end
1✔
63
    return calculated_next_reset_date
1✔
64

65

66
def update_phone_remaining_stats() -> tuple[int, int]:
1✔
67
    social_accounts_with_phones = get_phone_subscriber_social_accounts()
1✔
68
    free_phones_social_accounts = get_free_phone_social_accounts()
1✔
69
    social_accounts_with_phones.update(free_phones_social_accounts)
1✔
70

71
    if not settings.PHONES_ENABLED or len(social_accounts_with_phones) == 0:
1✔
72
        return 0, 0
1✔
73

74
    updated_profiles = []
1✔
75
    datetime_now = datetime.now(UTC)
1✔
76
    for social_account in social_accounts_with_phones:
1✔
77
        profile = social_account.user.profile
1✔
78
        next_reset_date = get_next_reset_date(profile)
1✔
79
        if next_reset_date > datetime_now:
1✔
80
            continue
1✔
81
        # next reset day is now or in the past
82
        reset_phone_remaining_stats(profile.user)
1✔
83
        profile.date_phone_subscription_reset = datetime_now
1✔
84
        profile.save()
1✔
85
        updated_profiles.append(profile)
1✔
86
    return len(social_accounts_with_phones), len(updated_profiles)
1✔
87

88

89
class Command(BaseCommand):
1✔
90
    help = "Update all phone users' subscription and stats."
1✔
91

92
    def handle(self, *args, **options):
1✔
93
        num_profiles_w_phones, num_profiles_updated = update_phone_remaining_stats()
1✔
94
        print(
1✔
95
            f"Out of {num_profiles_w_phones} profiles,"
96
            f" {num_profiles_updated} limits were reset"
97
        )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc