Remilia Profile Poker

Automatically navigates through friend profiles and pokes users on Remilia

Size

11.7 KB

Version

1.0.1

Created

Oct 18, 2025

Updated

5 days ago

1// ==UserScript==
2// @name		Remilia Profile Poker
3// @description		Automatically navigates through friend profiles and pokes users on Remilia
4// @version		1.0.1
5// @match		https://*.remilia.com/*
6// @icon		https://remilia.com/favicon.ico
7// ==/UserScript==
8(function() {
9    'use strict';
10
11    console.log('Remilia Profile Poker: Extension loaded');
12
13    // State management
14    let visitedProfiles = new Set();
15    let isRunning = false;
16    let currentCycle = 0;
17
18    // Debounce helper
19    function debounce(func, wait) {
20        let timeout;
21        return function executedFunction(...args) {
22            const later = () => {
23                clearTimeout(timeout);
24                func(...args);
25            };
26            clearTimeout(timeout);
27            timeout = setTimeout(later, wait);
28        };
29    }
30
31    // Get current profile username from URL
32    function getCurrentProfile() {
33        const match = window.location.pathname.match(/\/~([^\/]+)/);
34        return match ? match[1] : null;
35    }
36
37    // Find and click the Poke button
38    async function clickPokeButton() {
39        console.log('Attempting to click Poke button...');
40        
41        // Wait a bit for page to fully load
42        await new Promise(resolve => setTimeout(resolve, 2000));
43        
44        // Try multiple selectors for the Poke button
45        const pokeSelectors = [
46            'button.btn.poke:not(.poke-cooldown)',
47            'button.btn.poke[data-state="not-poked"]',
48            'button.btn.poke:not([data-state="already-poked"])',
49            '.friendship-row button.poke:not(.poke-cooldown)'
50        ];
51        
52        for (const selector of pokeSelectors) {
53            const pokeButton = document.querySelector(selector);
54            if (pokeButton) {
55                console.log('Found Poke button, clicking...');
56                pokeButton.click();
57                await new Promise(resolve => setTimeout(resolve, 1000));
58                return true;
59            }
60        }
61        
62        // Check if already poked
63        const alreadyPoked = document.querySelector('button.btn.poke.poke-cooldown, button.btn.poke[data-state="already-poked"]');
64        if (alreadyPoked) {
65            console.log('User already poked (on cooldown)');
66            return false;
67        }
68        
69        console.log('Poke button not found');
70        return false;
71    }
72
73    // Get list of friend profile links
74    function getFriendLinks() {
75        const friendsSection = document.querySelector('.friends-grid');
76        if (!friendsSection) {
77            console.log('Friends section not found');
78            return [];
79        }
80        
81        const links = Array.from(friendsSection.querySelectorAll('a.profile-link[href^="/~"]'));
82        console.log(`Found ${links.length} friend links`);
83        return links;
84    }
85
86    // Navigate to next unvisited friend
87    async function navigateToNextFriend() {
88        console.log('Looking for next friend to visit...');
89        
90        const friendLinks = getFriendLinks();
91        
92        // Filter out already visited profiles
93        const unvisitedLinks = friendLinks.filter(link => {
94            const username = link.getAttribute('href').replace('/~', '');
95            return !visitedProfiles.has(username);
96        });
97        
98        console.log(`Unvisited friends: ${unvisitedLinks.length}`);
99        
100        if (unvisitedLinks.length > 0) {
101            const nextLink = unvisitedLinks[0];
102            const username = nextLink.getAttribute('href').replace('/~', '');
103            console.log(`Navigating to friend: ${username}`);
104            visitedProfiles.add(username);
105            nextLink.click();
106            return true;
107        }
108        
109        console.log('No unvisited friends found');
110        return false;
111    }
112
113    // Navigate to notifications and click a random profile
114    async function navigateToNotifications() {
115        console.log('Navigating to notifications to find new profiles...');
116        
117        // Click notifications bell
118        const notificationBell = document.querySelector('.nav-item-wrapper.notifications, .nav-item.notifications');
119        if (!notificationBell) {
120            console.log('Notification bell not found');
121            return false;
122        }
123        
124        console.log('Clicking notification bell...');
125        notificationBell.click();
126        
127        // Wait for notifications panel to open
128        await new Promise(resolve => setTimeout(resolve, 2000));
129        
130        // Find profile links in notifications
131        const notificationLinks = Array.from(document.querySelectorAll('.notification a[href^="/~"], .notifications-panel a[href^="/~"]'));
132        
133        if (notificationLinks.length === 0) {
134            console.log('No profile links found in notifications');
135            // Close notifications and try to go back
136            const closeButton = document.querySelector('.notifications-panel .close, .modal-close');
137            if (closeButton) closeButton.click();
138            return false;
139        }
140        
141        // Pick a random profile
142        const randomLink = notificationLinks[Math.floor(Math.random() * notificationLinks.length)];
143        const username = randomLink.getAttribute('href').replace('/~', '');
144        console.log(`Clicking random notification profile: ${username}`);
145        
146        // Clear visited profiles for new cycle
147        visitedProfiles.clear();
148        currentCycle++;
149        console.log(`Starting new cycle #${currentCycle}`);
150        
151        randomLink.click();
152        return true;
153    }
154
155    // Main automation loop
156    async function automationLoop() {
157        if (!isRunning) return;
158        
159        console.log('=== Automation Loop Iteration ===');
160        
161        const currentProfile = getCurrentProfile();
162        console.log(`Current profile: ${currentProfile}`);
163        
164        // Step 1: Try to poke current user
165        await clickPokeButton();
166        
167        // Wait before navigating
168        await new Promise(resolve => setTimeout(resolve, 2000));
169        
170        // Step 2: Try to navigate to next friend
171        const foundFriend = await navigateToNextFriend();
172        
173        if (foundFriend) {
174            // Wait for navigation and continue loop
175            await new Promise(resolve => setTimeout(resolve, 3000));
176            automationLoop();
177        } else {
178            // Step 3: Dead-end reached, go to notifications
179            console.log('Dead-end reached, switching to notifications...');
180            await new Promise(resolve => setTimeout(resolve, 2000));
181            
182            const foundNotification = await navigateToNotifications();
183            
184            if (foundNotification) {
185                // Wait for navigation and continue loop
186                await new Promise(resolve => setTimeout(resolve, 3000));
187                automationLoop();
188            } else {
189                console.log('Could not find new profiles, stopping automation');
190                stopAutomation();
191            }
192        }
193    }
194
195    // Start automation
196    function startAutomation() {
197        if (isRunning) {
198            console.log('Automation already running');
199            return;
200        }
201        
202        console.log('Starting Remilia Profile Poker automation...');
203        isRunning = true;
204        visitedProfiles.clear();
205        currentCycle = 0;
206        
207        // Update button
208        const startButton = document.getElementById('remilia-poker-start');
209        if (startButton) {
210            startButton.textContent = '⏸️ STOP';
211            startButton.style.backgroundColor = '#ef4444';
212        }
213        
214        automationLoop();
215    }
216
217    // Stop automation
218    function stopAutomation() {
219        console.log('Stopping automation...');
220        isRunning = false;
221        
222        // Update button
223        const startButton = document.getElementById('remilia-poker-start');
224        if (startButton) {
225            startButton.textContent = '▶️ START';
226            startButton.style.backgroundColor = '#10b981';
227        }
228    }
229
230    // Toggle automation
231    function toggleAutomation() {
232        if (isRunning) {
233            stopAutomation();
234        } else {
235            startAutomation();
236        }
237    }
238
239    // Create control panel UI
240    function createControlPanel() {
241        // Check if already exists
242        if (document.getElementById('remilia-poker-panel')) return;
243        
244        const panel = document.createElement('div');
245        panel.id = 'remilia-poker-panel';
246        panel.style.cssText = `
247            position: fixed;
248            top: 80px;
249            right: 20px;
250            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
251            color: white;
252            padding: 16px;
253            border-radius: 12px;
254            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
255            z-index: 999999;
256            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
257            min-width: 200px;
258            backdrop-filter: blur(10px);
259        `;
260        
261        panel.innerHTML = `
262            <div style="font-weight: bold; font-size: 14px; margin-bottom: 12px; text-align: center;">
263                🎯 Profile Poker
264            </div>
265            <button id="remilia-poker-start" style="
266                width: 100%;
267                padding: 10px;
268                background-color: #10b981;
269                color: white;
270                border: none;
271                border-radius: 8px;
272                font-weight: bold;
273                cursor: pointer;
274                font-size: 13px;
275                transition: all 0.2s;
276                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
277            ">▶️ START</button>
278            <div id="remilia-poker-stats" style="
279                margin-top: 12px;
280                font-size: 11px;
281                text-align: center;
282                opacity: 0.9;
283                line-height: 1.6;
284            ">
285                <div>Visited: <span id="visited-count">0</span></div>
286                <div>Cycle: <span id="cycle-count">0</span></div>
287            </div>
288        `;
289        
290        document.body.appendChild(panel);
291        
292        // Add button hover effect
293        const startButton = document.getElementById('remilia-poker-start');
294        startButton.addEventListener('mouseenter', () => {
295            startButton.style.transform = 'scale(1.05)';
296        });
297        startButton.addEventListener('mouseleave', () => {
298            startButton.style.transform = 'scale(1)';
299        });
300        
301        // Add click handler
302        startButton.addEventListener('click', toggleAutomation);
303        
304        console.log('Control panel created');
305    }
306
307    // Update stats display
308    function updateStats() {
309        const visitedCountEl = document.getElementById('visited-count');
310        const cycleCountEl = document.getElementById('cycle-count');
311        
312        if (visitedCountEl) visitedCountEl.textContent = visitedProfiles.size;
313        if (cycleCountEl) cycleCountEl.textContent = currentCycle;
314    }
315
316    // Update stats periodically
317    setInterval(updateStats, 1000);
318
319    // Initialize when page loads
320    function init() {
321        console.log('Initializing Remilia Profile Poker...');
322        
323        // Wait for page to be ready
324        if (document.readyState === 'loading') {
325            document.addEventListener('DOMContentLoaded', init);
326            return;
327        }
328        
329        // Create control panel after a short delay
330        setTimeout(createControlPanel, 1000);
331        
332        // Observe DOM changes to recreate panel if needed
333        const observer = new MutationObserver(debounce(() => {
334            if (!document.getElementById('remilia-poker-panel')) {
335                createControlPanel();
336            }
337        }, 1000));
338        
339        observer.observe(document.body, {
340            childList: true,
341            subtree: true
342        });
343    }
344
345    // Start initialization
346    init();
347})();
Remilia Profile Poker | Robomonkey