Initial commit
This commit is contained in:
parent
623fb58a7e
commit
30b9481ea0
7 changed files with 253 additions and 0 deletions
13
church-tools/service_account.json
Normal file
13
church-tools/service_account.json
Normal 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"
|
||||||
|
}
|
||||||
35
prod_tools/messenger-wrapper/README.md
Normal file
35
prod_tools/messenger-wrapper/README.md
Normal 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
|
||||||
|
```
|
||||||
201
prod_tools/messenger-wrapper/messenger_app.py
Normal file
201
prod_tools/messenger-wrapper/messenger_app.py
Normal 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()
|
||||||
BIN
prod_tools/messenger-wrapper/messenger_icon.ico
Normal file
BIN
prod_tools/messenger-wrapper/messenger_icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
BIN
prod_tools/messenger-wrapper/messenger_icon.png
Normal file
BIN
prod_tools/messenger-wrapper/messenger_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 454 KiB |
1
prod_tools/messenger-wrapper/messenger_icon.svg
Normal file
1
prod_tools/messenger-wrapper/messenger_icon.svg
Normal 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 |
3
prod_tools/messenger-wrapper/requirements.txt
Normal file
3
prod_tools/messenger-wrapper/requirements.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
pywebview>=4.0
|
||||||
|
pystray
|
||||||
|
Pillow
|
||||||
Loading…
Add table
Reference in a new issue