File size: 5,902 Bytes
b115c19
15c5812
b115c19
3baac0d
b115c19
 
 
 
 
 
3baac0d
 
 
 
06942ac
3baac0d
 
 
b115c19
 
 
2d5b0bc
b115c19
06942ac
b115c19
2d5b0bc
 
 
b115c19
2d5b0bc
 
 
 
 
 
 
 
 
3baac0d
2d5b0bc
 
 
 
b115c19
e15c1ef
2d5b0bc
da0675a
2d5b0bc
 
 
 
da0675a
2d5b0bc
 
 
 
 
 
b115c19
2d5b0bc
b115c19
8246dde
2d5b0bc
 
 
b115c19
 
2d5b0bc
da0675a
2d5b0bc
 
 
 
da08f38
 
2d5b0bc
 
e15c1ef
2d5b0bc
e15c1ef
 
2d5b0bc
 
 
8246dde
4ce5d19
2d5b0bc
da0675a
 
 
 
 
 
 
 
 
4ce5d19
89abe58
2d5b0bc
 
da08f38
2d5b0bc
8246dde
 
2d5b0bc
 
 
 
15c5812
2d5b0bc
da0675a
8246dde
 
2d5b0bc
 
8246dde
2d5b0bc
 
 
 
 
 
8969612
 
2d5b0bc
da0675a
 
 
 
 
 
 
 
 
8969612
 
2d5b0bc
 
8969612
3baac0d
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
import os
from typing import Any
from motor.motor_asyncio import AsyncIOMotorClient
from utils.logger import log

class Database:
    def __init__(self):
        self.client = None
        self.db = None

    async def init_db(self):
        await self.connect()
        try:
            await self.db.command("ping")
            log("✅ Database connection established and verified to 'username_sniper'.")
        except Exception as e:
            raise ConnectionError(f"🚨 Database failed to ping: {e}")

    async def connect(self):
        uri = os.environ.get("MONGO_URI")
        if not uri:
            raise ValueError("MONGO_URI not set.")
        self.client = AsyncIOMotorClient(uri)
        self.db = self.client["username_sniper"]

    # --- SETTINGS MANAGER ---
    async def load_settings(self, state_dict: dict):
        if self.db is None: return
        doc = await self.db.settings.find_one({"_id": "bot_settings"})
        if not doc: return
        
        keys = [
            "checking_active", "sniping_active", "cycle_paused",
            "check_interval", "snipe_interval", "autoclaim_on", "db_filter_on",
            "total_checked", "total_available", "total_claimed",
            "channel_claim_priority", "preferred_channel_account", 
            "watchdog_poll_interval", "fragment_sniping_active", 
            "fragment_autoclaim_on", "fragment_workers", "custom_claim_message",
            "mute_minor_alerts", "smart_menu_on", "camper_interval", "custom_claim_gif", "custom_success_text"
        ]
        for key in keys:
            if key in doc:
                state_dict[key] = doc[key]

    async def save_setting(self, key: str, value):
        if self.db is not None:
            await self.db.settings.update_one({"_id": "bot_settings"}, {"$set": {key: value}}, upsert=True)

    # --- ADMIN MANAGER ---
    async def add_admin(self, user_id: int):
        if self.db is not None:
            await self.db.admins.update_one({"user_id": user_id}, {"$set": {"user_id": user_id}}, upsert=True)

    async def get_admins(self) -> set:
        if self.db is None: return set()
        cursor = self.db.admins.find({}, {"user_id": 1})
        docs = await cursor.to_list(length=None)
        return {doc["user_id"] for doc in docs}

    # --- UNAVAILABLE SET ---
    async def get_unavailable_set(self) -> set:
        if self.db is None: return set()
        cursor = self.db.unavailable.find({}, {"username": 1})
        docs = await cursor.to_list(length=None)
        return {doc["username"] for doc in docs}

    async def add_unavailable(self, username: str):
        if self.db is not None:
            await self.db.unavailable.update_one({"username": username}, {"$set": {"username": username}}, upsert=True)

    async def remove_unavailable(self, username: str):
        if self.db is not None:
            await self.db.unavailable.delete_one({"username": username})

    async def clear_unavailable(self):
        if self.db is not None:
            await self.db.unavailable.delete_many({})

    # --- CUSTOM SNIPES ---
    async def get_custom_snipes(self) -> list:
        if self.db is None: return []
        cursor = self.db.custom_snipes.find({}, {"username": 1})
        docs = await cursor.to_list(length=None)
        return [doc["username"] for doc in docs]

    async def add_custom_snipe(self, username: str):
        if self.db is not None:
            await self.db.custom_snipes.update_one({"username": username}, {"$set": {"username": username}}, upsert=True)

    # ⚡ NEW: Atomic Bulk Custom Snipe Write
    async def add_custom_snipe_bulk(self, usernames: list):
        if self.db is not None and usernames:
            from pymongo import UpdateOne
            operations = [UpdateOne({"username": u}, {"$set": {"username": u}}, upsert=True) for u in usernames]
            for i in range(0, len(operations), 10000):
                await self.db.custom_snipes.bulk_write(operations[i:i+10000])

    async def remove_custom_snipe(self, username: str):
        if self.db is not None:
            await self.db.custom_snipes.delete_one({"username": username})

    # --- WATCHDOG ---
    async def get_watchdog(self) -> dict:
        if self.db is None: return {}
        cursor = self.db.watchdog.find({}, {"username": 1, "added_by": 1})
        docs = await cursor.to_list(length=None)
        return {doc["username"]: doc.get("added_by") for doc in docs}

    async def add_watchdog(self, username: str, user_id: Any):
        if self.db is not None:
            await self.db.watchdog.update_one({"username": username}, {"$set": {"username": username, "added_by": user_id}}, upsert=True)

    async def remove_watchdog(self, username: str):
        if self.db is not None:
            await self.db.watchdog.delete_one({"username": username})

    # --- FRAGMENT CHECK ---
    async def get_fragcheck(self) -> list:
        if self.db is None: return []
        cursor = self.db.fragcheck.find({}, {"username": 1})
        docs = await cursor.to_list(length=None)
        return [doc["username"] for doc in docs]

    async def add_fragcheck(self, username: str):
        if self.db is not None:
            await self.db.fragcheck.update_one({"username": username}, {"$set": {"username": username}}, upsert=True)

    # ⚡ NEW: Atomic Bulk Fragment Write
    async def add_fragcheck_bulk(self, usernames: list):
        if self.db is not None and usernames:
            from pymongo import UpdateOne
            operations = [UpdateOne({"username": u}, {"$set": {"username": u}}, upsert=True) for u in usernames]
            for i in range(0, len(operations), 10000):
                await self.db.fragcheck.bulk_write(operations[i:i+10000])

    async def remove_fragcheck(self, username: str):
        if self.db is not None:
            await self.db.fragcheck.delete_one({"username": username})

db = Database()