Initial commit

This commit is contained in:
Andrew 2026-01-16 10:56:58 +10:00
parent 623fb58a7e
commit 30b9481ea0
7 changed files with 253 additions and 0 deletions

View file

@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "cpc-roster",
"private_key_id": "87b13e5388800e0e1d552884956ef64be34036b5",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCLvDVVYkEqyh8F\nzGrxG4b0jvtt+rRbE6LcJu9l1l3n2esqXJtd2CtYXLMQGEsRxjkdVlqNM0VbCFg7\n5iae/zn2+t7Gw5sJd+kP7+BT7+r3J3r0qS2GqvZUlpXyq/8oG5NUMUV5n6aAoT9j\nKKqcacMV0cLptymCvD/q4GgZLLqNPYPGsI88OOV20nFOVTxk3nRSHX9TbA01Cd+w\nQwhd7DYXtVKB3s9Ka9dS8o1EAMv/95yyzYUY+KqyeiXKS5aPEodToagAEZimSoYF\nbfp7SSVpTPa2AFY+aBksa3G6anSzN/xwuo2ceJvejsJkFVr9SXe8ZvXtAQF0uVHX\ned3cKfk7AgMBAAECggEAGvs79yEyQR9nDxkSGz07+VP0g59xnNZ1T3orJqhWWJLx\nACyCiYPYlsbLgpOWRzfVxm7qrDIWtcWuN96wXWod2K1HP+z8Lj9bnsqsL7j3T0Lt\n0HksQ8EWMG4lRQbmDWoJsCuVZS8pGNRJ540uKGaZl0h6EOPfnZFY7DLpltbWrLfH\nf/aluEW4ozqKWe0vAs650TGcOj/rtiFjVXBeOujooVtrXBEwYxYglK9i0kPwKima\nEJNZ/jKQwjX70zBSepd/RCLkLrw2SCJZDM5dsXfqa7zdt+mCXuIRPNb1Pt6T4x+4\nH1GWIT0rCpARUQ5oUxUgLDbGh2Jyn6THgvSrj9ZK8QKBgQDBJbG9c/dNRemxWGnx\nNnsJQmCNxP19Duqyb9Imdro+JRnrSuwxUaxaAjdem/1GhuM0PTe9XYJ6jEHlQztj\nF0EPLudBiU/TuqWzKKS8m/oyunNaMAuXsxG2/4qmcQbpbCPWp9haIYIV0cmeL7nO\n18BdRLEpwIk8Sah1xGFeWUnq8QKBgQC5NPl8M3dRJPriZx15sKeFFC4UyihoCCjB\nocDJj5ORMcD8bltJrZAl5ThA+0j+EmMWfnpTpts1D0D7BipGKYn1k52OVacYfllP\nx4GBmwUcYktI0PGiH5V1Q59rVFEMdksTuovkGfwSMsesMBMOSUCnnYLIZcegtkUp\nPKy4/pgu6wKBgAUT859SfC745pL2Cxr/Xq64owc3JZ7zFHKKhBDk0DKwEQVhm+IU\nDp7zLfd7zGXdR/3omh2NZs/H/jeD0/zf8KLwjb3oWUPsxUx3hhU7WJGa20uEtdlQ\nKOgRwdhsYk0ivbJ4CTUdamkecdmJ0a3BeFo7YxkA6dq+6QHnntO3Lz1RAoGATW0u\nF5RUf2HcWKYPFn6ZqfLjyOEyvzsZ/skmlZ0mbf7E1UM1ernKl20adWAYBc+eCRta\n/Hm3DpmP6uGK7sYS3M2XgpegQYcgw09+frZWDqWxH4HqYoKdsuZQUUhwkasqe9bz\nAKs0TE9aVkvKy6AoHWql8C1MpY1NoI2zD6uv530CgYBBgtLxiOZQtxf08GWFKxan\n1mPXAYBkni0DWOau2eL9lNgcYhwMDbYHFmNIenl+Tg5VTDyWCtxLP7/6vohai7e6\nXE8vvuuWNifHM2hoW29gJByewmslztXY68JjWWBd/m9M6bdsSWjIj2Lr8s1VQyce\nPgYpw0rTVL4NjY8+0bm/eg==\n-----END PRIVATE KEY-----\n",
"client_email": "cpcmusic@cpc-roster.iam.gserviceaccount.com",
"client_id": "100783042323775881315",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/cpcmusic%40cpc-roster.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

View file

@ -0,0 +1,35 @@
# Messenger Desktop Wrapper
A lightweight Python desktop wrapper for Facebook Messenger using PyWebView.
## Features
- Native desktop window for Messenger
- System tray icon for background running
- Persistent login sessions
- Minimize to tray on close
## Installation
1. **Install Python dependencies:**
```bash
pip install -r requirements.txt
```
2. **Run the application:**
```bash
python messenger_app.py
```
## Usage
- **Close button** minimizes to system tray (app continues running)
- **Right-click tray icon** for options (Show/Quit)
- **Double-click tray icon** to restore window
## Building an Executable (Optional)
To create a standalone `.exe` file:
```bash
pip install pyinstaller
pyinstaller --onefile --windowed --icon=messenger.ico messenger_app.py
```

View file

@ -0,0 +1,201 @@
"""
Messenger Desktop Wrapper
A lightweight desktop application for Facebook Messenger using PyWebView.
"""
import webview
import threading
import sys
import os
# Try to import system tray libraries (optional feature)
try:
import pystray
from PIL import Image
TRAY_AVAILABLE = True
except ImportError:
TRAY_AVAILABLE = False
print("Note: pystray/Pillow not installed. System tray disabled.")
# Configuration
MESSENGER_URL = "https://www.messenger.com"
WINDOW_TITLE = "Messenger"
WINDOW_WIDTH = 1200
WINDOW_HEIGHT = 800
# Get the directory where this script is located
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ICON_PATH = os.path.join(SCRIPT_DIR, "messenger_icon.png")
ICO_PATH = os.path.join(SCRIPT_DIR, "messenger_icon.ico")
class MessengerApp:
def __init__(self):
self.window = None
self.tray_icon = None
self.is_quitting = False
# Set AppUserModelID early - MUST be before window creation
# This tells Windows to use our app identity instead of python.exe
if sys.platform == 'win32':
try:
import ctypes
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("MessengerDesktopWrapper")
except Exception as e:
print(f"Warning: Could not set AppUserModelID: {e}")
def create_tray_image(self):
"""Load the Messenger icon from PNG file."""
size = 64
# Try to load the PNG icon
if os.path.exists(ICON_PATH):
try:
image = Image.open(ICON_PATH)
image = image.resize((size, size), Image.Resampling.LANCZOS)
return image.convert('RGBA')
except Exception as e:
print(f"Warning: Could not load icon: {e}")
# Fallback: create a simple icon programmatically
from PIL import ImageDraw
image = Image.new('RGBA', (size, size), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.ellipse([4, 4, size-4, size-4], fill=(0, 132, 255))
draw.ellipse([16, 20, size-16, size-20], fill=(255, 255, 255))
return image
def show_window(self, icon=None, item=None):
"""Show the main window."""
if self.window:
self.window.show()
self.window.restore()
def quit_app(self, icon=None, item=None):
"""Quit the application completely."""
self.is_quitting = True
if self.tray_icon:
self.tray_icon.stop()
if self.window:
self.window.destroy()
def on_closing(self):
"""Handle window close - minimize to tray instead of quitting."""
if TRAY_AVAILABLE and not self.is_quitting:
self.window.hide()
return False # Prevent window destruction
return True # Allow window destruction
def setup_tray(self):
"""Set up the system tray icon."""
if not TRAY_AVAILABLE:
return
menu = pystray.Menu(
pystray.MenuItem("Show Messenger", self.show_window, default=True),
pystray.MenuItem("Quit", self.quit_app)
)
self.tray_icon = pystray.Icon(
"Messenger",
self.create_tray_image(),
"Messenger",
menu
)
# Run tray icon in a separate thread
tray_thread = threading.Thread(target=self.tray_icon.run, daemon=True)
tray_thread.start()
def set_window_icon(self):
"""Set the window icon using Windows API."""
if sys.platform != 'win32' or not os.path.exists(ICO_PATH):
return
try:
import ctypes
from ctypes import wintypes
import time
# Windows API constants
WM_SETICON = 0x0080
ICON_SMALL = 0
ICON_BIG = 1
IMAGE_ICON = 1
LR_LOADFROMFILE = 0x0010
LR_DEFAULTSIZE = 0x0040
user32 = ctypes.windll.user32
# Load icon from file
hicon = user32.LoadImageW(
None,
ICO_PATH,
IMAGE_ICON,
0, 0,
LR_LOADFROMFILE | LR_DEFAULTSIZE
)
if not hicon:
print(f"Warning: Failed to load icon from {ICO_PATH}")
return
# Small delay to ensure window is fully created
time.sleep(0.5)
# Try FindWindowW first
hwnd = user32.FindWindowW(None, WINDOW_TITLE)
# Fallback to GetForegroundWindow if FindWindowW fails
if not hwnd:
hwnd = user32.GetForegroundWindow()
if hwnd:
# Set both small (title bar) and big (taskbar/Alt-Tab) icons
user32.SendMessageW(hwnd, WM_SETICON, ICON_SMALL, hicon)
user32.SendMessageW(hwnd, WM_SETICON, ICON_BIG, hicon)
print("Window icon set successfully")
else:
print("Warning: Could not find window handle")
except Exception as e:
print(f"Warning: Could not set window icon: {e}")
def run(self):
"""Start the Messenger application."""
# Set up system tray first
self.setup_tray()
# Create the main webview window
self.window = webview.create_window(
title=WINDOW_TITLE,
url=MESSENGER_URL,
width=WINDOW_WIDTH,
height=WINDOW_HEIGHT,
resizable=True,
min_size=(400, 300)
)
# Set up close handler for minimize-to-tray behavior
if TRAY_AVAILABLE:
self.window.events.closing += self.on_closing
# Start the webview with icon callback
webview.start(
self.set_window_icon, # Called when window is ready
private_mode=False, # Enable cookies/session persistence
storage_path=None # Use default storage location
)
# Clean up tray icon when done
if self.tray_icon:
self.tray_icon.stop()
def main():
"""Entry point for the application."""
app = MessengerApp()
app.run()
if __name__ == "__main__":
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 KiB

View file

@ -0,0 +1 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Messenger</title><path fill="#0084FF" d="M12 0C5.24 0 0 4.952 0 11.64c0 3.499 1.434 6.521 3.769 8.61a.96.96 0 0 1 .323.683l.065 2.135a.96.96 0 0 0 1.347.85l2.381-1.053a.96.96 0 0 1 .641-.046A13 13 0 0 0 12 23.28c6.76 0 12-4.952 12-11.64S18.76 0 12 0m6.806 7.44c.522-.03.971.567.63 1.094l-4.178 6.457a.707.707 0 0 1-.977.208l-3.87-2.504a.44.44 0 0 0-.49.007l-4.363 3.01c-.637.438-1.415-.317-.995-.966l4.179-6.457a.706.706 0 0 1 .977-.21l3.87 2.505c.15.097.344.094.491-.007l4.362-3.008a.7.7 0 0 1 .364-.13"/></svg>

After

Width:  |  Height:  |  Size: 591 B

View file

@ -0,0 +1,3 @@
pywebview>=4.0
pystray
Pillow