File size: 6,235 Bytes
a74b879
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
"""
Onboarding System - One-try limit, guided tour, and pricing cards
"""
import sqlite3
from datetime import datetime, timedelta
from pathlib import Path
import os
import json

OUTPUT_DIR = Path(os.environ.get('OUTPUT_DIR', './output'))
ONBOARDING_DB = OUTPUT_DIR / 'onboarding.db'

def init_onboarding_db():
    """Initialize onboarding tables"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    c = conn.cursor()
    
    # Track free trial usage
    c.execute('''CREATE TABLE IF NOT EXISTS trial_usage (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INTEGER NOT NULL UNIQUE,
        tries_used INTEGER DEFAULT 0,
        first_crawl_date TIMESTAMP,
        trial_expires TIMESTAMP,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )''')
    
    # Track onboarding progress
    c.execute('''CREATE TABLE IF NOT EXISTS onboarding_progress (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        user_id INTEGER NOT NULL UNIQUE,
        tour_completed BOOLEAN DEFAULT 0,
        tour_step INTEGER DEFAULT 0,
        pricing_shown BOOLEAN DEFAULT 0,
        last_step_date TIMESTAMP,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )''')
    
    conn.commit()
    conn.close()

def get_trial_status(user_id: int) -> dict:
    """Get user's trial status"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    c.execute('SELECT * FROM trial_usage WHERE user_id = ?', (user_id,))
    result = c.fetchone()
    conn.close()
    
    if result:
        row = dict(result)
        now = datetime.utcnow()
        trial_expires = datetime.fromisoformat(row['trial_expires']) if row['trial_expires'] else None
        
        return {
            'tries_used': row['tries_used'],
            'tries_remaining': max(0, 1 - row['tries_used']),
            'trial_expired': trial_expires and now > trial_expires if trial_expires else False,
            'trial_expires': row['trial_expires'],
            'first_crawl_date': row['first_crawl_date']
        }
    
    return {'tries_used': 0, 'tries_remaining': 1, 'trial_expired': False, 'trial_expires': None, 'first_crawl_date': None}

def init_trial(user_id: int, trial_days: int = 14) -> dict:
    """Initialize trial for new user"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    c = conn.cursor()
    
    now = datetime.utcnow()
    trial_expires = now + timedelta(days=trial_days)
    
    try:
        c.execute('''INSERT INTO trial_usage 
                     (user_id, tries_used, trial_expires)
                     VALUES (?, ?, ?)''',
                  (user_id, 0, trial_expires))
        conn.commit()
    except sqlite3.IntegrityError:
        pass
    
    conn.close()
    return get_trial_status(user_id)

def use_trial(user_id: int) -> dict:
    """Use one trial attempt"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    c = conn.cursor()
    
    now = datetime.utcnow()
    
    # Get current status
    c.execute('SELECT tries_used, first_crawl_date FROM trial_usage WHERE user_id = ?', (user_id,))
    result = c.fetchone()
    
    if not result:
        # Initialize if doesn't exist
        init_trial(user_id)
        c.execute('SELECT tries_used, first_crawl_date FROM trial_usage WHERE user_id = ?', (user_id,))
        result = c.fetchone()
    
    tries_used, first_crawl = result
    
    # Update tries and first crawl date
    if tries_used == 0:
        c.execute('''UPDATE trial_usage 
                     SET tries_used = 1, first_crawl_date = ?
                     WHERE user_id = ?''', (now, user_id))
    else:
        c.execute('''UPDATE trial_usage 
                     SET tries_used = tries_used + 1
                     WHERE user_id = ?''', (user_id,))
    
    conn.commit()
    conn.close()
    
    return get_trial_status(user_id)

def get_onboarding_progress(user_id: int) -> dict:
    """Get user's onboarding progress"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    conn.row_factory = sqlite3.Row
    c = conn.cursor()
    c.execute('SELECT * FROM onboarding_progress WHERE user_id = ?', (user_id,))
    result = c.fetchone()
    conn.close()
    
    if result:
        return dict(result)
    
    return {
        'user_id': user_id,
        'tour_completed': False,
        'tour_step': 0,
        'pricing_shown': False,
        'last_step_date': None
    }

def init_onboarding(user_id: int) -> dict:
    """Initialize onboarding for new user"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    c = conn.cursor()
    
    try:
        c.execute('''INSERT INTO onboarding_progress 
                     (user_id, tour_step)
                     VALUES (?, ?)''', (user_id, 0))
        conn.commit()
    except sqlite3.IntegrityError:
        pass
    
    conn.close()
    return get_onboarding_progress(user_id)

def update_tour_step(user_id: int, step: int) -> dict:
    """Update tour step"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    c = conn.cursor()
    
    now = datetime.utcnow()
    c.execute('''UPDATE onboarding_progress 
                 SET tour_step = ?, last_step_date = ?
                 WHERE user_id = ?''', (step, now, user_id))
    conn.commit()
    conn.close()
    
    return get_onboarding_progress(user_id)

def complete_tour(user_id: int) -> dict:
    """Mark tour as completed"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    c = conn.cursor()
    
    now = datetime.utcnow()
    c.execute('''UPDATE onboarding_progress 
                 SET tour_completed = 1, last_step_date = ?
                 WHERE user_id = ?''', (now, user_id))
    conn.commit()
    conn.close()
    
    return get_onboarding_progress(user_id)

def mark_pricing_shown(user_id: int) -> dict:
    """Mark pricing cards as shown"""
    conn = sqlite3.connect(str(ONBOARDING_DB))
    c = conn.cursor()
    
    now = datetime.utcnow()
    c.execute('''UPDATE onboarding_progress 
                 SET pricing_shown = 1, last_step_date = ?
                 WHERE user_id = ?''', (now, user_id))
    conn.commit()
    conn.close()
    
    return get_onboarding_progress(user_id)

# Initialize on import
try:
    init_onboarding_db()
except Exception as e:
    print(f"  Onboarding DB init failed: {e}")