Upload Improvements: - Standardize upload endpoint configuration in constants.py - Centralize upload headers (x-tenant-id, x-goog-upload-protocol) in Headers.UPLOAD - Update upload_file.py to reference Headers constants instead of hardcoded values Code Cleanup: - Remove unused imports from client.py (Task, GRPC, ImageGenerationError) - Remove unused logger import from parsing.py - Fix ImageStatus import for image mode status checking
149 lines
4.7 KiB
Python
149 lines
4.7 KiB
Python
from enum import Enum, IntEnum, StrEnum
|
|
|
|
|
|
class Endpoint(StrEnum):
|
|
GOOGLE = "https://www.google.com"
|
|
INIT = "https://gemini.google.com/app"
|
|
GENERATE = "https://gemini.google.com/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate"
|
|
ROTATE_COOKIES = "https://accounts.google.com/RotateCookies"
|
|
UPLOAD = "https://push.clients6.google.com/upload/"
|
|
BATCH_EXEC = "https://gemini.google.com/_/BardChatUi/data/batchexecute"
|
|
|
|
|
|
class GRPC(StrEnum):
|
|
"""
|
|
Google RPC ids used in Gemini API.
|
|
"""
|
|
|
|
# Chat methods
|
|
LIST_CHATS = "MaZiqc"
|
|
READ_CHAT = "hNvQHb"
|
|
|
|
# Gem methods
|
|
LIST_GEMS = "CNgdBe"
|
|
CREATE_GEM = "oMH3Zd"
|
|
UPDATE_GEM = "kHv0Vd"
|
|
DELETE_GEM = "UXcSJb"
|
|
|
|
# Content generation (batchexecute)
|
|
TEXT_GENERATE = "qpEbW" # Text/Chat generation
|
|
IMAGE_GENERATE = "aPya6c" # Image generation
|
|
HEARTBEAT = "ESY5D" # Session heartbeat
|
|
|
|
|
|
class Headers(Enum):
|
|
GEMINI = {
|
|
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
|
|
"Host": "gemini.google.com",
|
|
"Origin": "https://gemini.google.com",
|
|
"Referer": "https://gemini.google.com/",
|
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
|
|
"X-Same-Domain": "1",
|
|
"x-goog-ext-73010989-jspb": "[0]",
|
|
}
|
|
ROTATE_COOKIES = {
|
|
"Content-Type": "application/json",
|
|
}
|
|
UPLOAD = {
|
|
"Push-ID": "feeds/mcudyrk2a4khkz",
|
|
"x-goog-upload-protocol": "resumable",
|
|
"x-tenant-id": "bard-storage",
|
|
}
|
|
IMAGE_MODE = {
|
|
"x-goog-ext-525001261-jspb": "[1,null,null,null,null,null,null,0,[4],null,null,2]",
|
|
"x-goog-ext-73010989-jspb": "[0]",
|
|
}
|
|
BROWSER = {
|
|
"x-browser-channel": "stable",
|
|
"x-browser-copyright": "Copyright 2026 Google LLC. All Rights reserved.",
|
|
"x-browser-year": "2026",
|
|
}
|
|
|
|
|
|
class Model(Enum):
|
|
UNSPECIFIED = ("unspecified", {}, False)
|
|
G_3_0_PRO = (
|
|
"gemini-3-pro",
|
|
{
|
|
"x-goog-ext-525001261-jspb": '[1,null,null,null,"e6fa609c3fa255c0",null,null,0,[4],null,null,2]',
|
|
"x-goog-ext-73010989-jspb": "[0]",
|
|
},
|
|
False,
|
|
)
|
|
G_2_5_PRO = (
|
|
"gemini-3-thinking",
|
|
{
|
|
"x-goog-ext-525001261-jspb": '[1,null,null,null,"4af6c7f5da75d65d",null,null,0,[4],null,null,2]',
|
|
"x-goog-ext-73010989-jspb": "[0]",
|
|
},
|
|
False,
|
|
)
|
|
G_2_5_FLASH = (
|
|
"gemini-3-flash",
|
|
{
|
|
"x-goog-ext-525001261-jspb": '[1,null,null,null,"9ec249fc9ad08861",null,null,0,[4],null,null,2]',
|
|
"x-goog-ext-73010989-jspb": "[0]",
|
|
},
|
|
False,
|
|
)
|
|
|
|
def __init__(self, name, header, advanced_only):
|
|
self.model_name = name
|
|
self.model_header = header
|
|
self.advanced_only = advanced_only
|
|
|
|
@classmethod
|
|
def from_name(cls, name: str):
|
|
for model in cls:
|
|
if model.model_name == name:
|
|
return model
|
|
|
|
raise ValueError(
|
|
f"Unknown model name: {name}. Available models: {', '.join([model.model_name for model in cls])}"
|
|
)
|
|
|
|
@classmethod
|
|
def from_dict(cls, model_dict: dict):
|
|
if "model_name" not in model_dict or "model_header" not in model_dict:
|
|
raise ValueError(
|
|
"When passing a custom model as a dictionary, 'model_name' and 'model_header' keys must be provided."
|
|
)
|
|
|
|
if not isinstance(model_dict["model_header"], dict):
|
|
raise ValueError(
|
|
"When passing a custom model as a dictionary, 'model_header' must be a dictionary containing valid header strings."
|
|
)
|
|
|
|
custom_model = cls.UNSPECIFIED
|
|
custom_model.model_name = model_dict["model_name"]
|
|
custom_model.model_header = model_dict["model_header"]
|
|
return custom_model
|
|
|
|
|
|
class ErrorCode(IntEnum):
|
|
"""
|
|
Known error codes returned from server.
|
|
"""
|
|
|
|
CONTENT_SAFETY_3 = 3 # Safety filter rejection
|
|
CONTENT_SAFETY_4 = 4 # Safety filter rejection (alternate)
|
|
TEMPORARY_ERROR_1013 = 1013 # Randomly raised when generating with certain models, but disappears soon after
|
|
USAGE_LIMIT_EXCEEDED = 1037
|
|
MODEL_INCONSISTENT = 1050
|
|
MODEL_HEADER_INVALID = 1052
|
|
IP_TEMPORARILY_BLOCKED = 1060
|
|
|
|
|
|
class ImageStatus(IntEnum):
|
|
"""
|
|
Status codes for image generation response parsing.
|
|
Found at candidate[12][6][0] in the response structure.
|
|
"""
|
|
|
|
PENDING = 1 # Image generation started
|
|
IN_PROGRESS = 2 # Image generation in progress
|
|
COMPLETE = 3 # Image generation complete, images available
|
|
SAFETY_BLOCKED = 4 # Blocked by safety filters
|
|
ERROR = 5 # Generation failed
|
|
|