Files
zombieyang-sd-ppp/sdppp_python/photoshop_manager.py
T

116 lines
4.8 KiB
Python

import asyncio
from .photoshop_instance import PhotoshopInstance
DEFAULT_ID = 0
class PhotoshopManager:
_instance = None
@classmethod
def instance(cls) -> 'PhotoshopManager':
if cls._instance is None:
cls._instance = PhotoshopManager()
return cls._instance
def __init__(self):
# client id info
self.ip_to_client_id_list = {}
self.client_id_to_userid = {}
# ps instance info
self.ip_to_ps_instance_list = {}
# final match
self.client_id_to_ps_instance = {}
# get instance from client information, match new instance if not exist
def instance_from_client_info(self, ip, client_id, user_id) -> PhotoshopInstance:
if not ip: return None
if not client_id: user_id = 0
if not user_id: user_id = 0
instance = self.instance_from_client_id(client_id)
if instance is not None:
return instance
self._add_new_client(ip, client_id, user_id)
self._client_match_ps(ip, client_id, user_id)
return self.instance_from_client_id(client_id)
# get instance from client id
def instance_from_client_id(self, client_id) -> PhotoshopInstance:
return self.client_id_to_ps_instance.get(client_id, None)
# create new instance and record
async def new_ps_instance(self, sdppp, sid, ip, user_id) -> PhotoshopInstance:
if not ip: return None
if not user_id: user_id = 0
# create new instance
instance = PhotoshopInstance(sdppp, sid, user_id)
instance.on_destroy = self._on_instance_destroy
# record new instance
await self._add_new_ps_instance(ip, instance)
return instance
#------------------------------------------------------------------------------------------------------------------------------------------------
# callback when instance is destroyed and remove from record
def _on_instance_destroy(self, instance):
self._remove_instance(instance)
# record new ps instance for matching
async def _add_new_ps_instance(self, ip, instance):
# find old one and destroy
same_ip_list = self.ip_to_ps_instance_list.get(ip, [])
for check_instance in same_ip_list:
if check_instance.uid == instance.uid:
await check_instance.destroy()
# record ip to instance
ps_instance_list = self.ip_to_ps_instance_list.get(ip, [])
if instance not in ps_instance_list:
ps_instance_list.append(instance)
self.ip_to_ps_instance_list[ip] = ps_instance_list
# record new client id
def _add_new_client(self, ip, client_id, user_id):
# record client id, if exist, do nothing
client_id_list = self.ip_to_client_id_list.get(ip, [])
if client_id in client_id_list:
return
client_id_list.append(client_id)
self.ip_to_client_id_list[ip] = client_id_list
# record user_id
self.client_id_to_userid[client_id] = user_id
# match client id to ps instance for prompt use
# there are several ways to match:
# 1. one to one match(local network most likely): same ip client and ps instance, assign to it
# 2. multiple ps instance under the same ip(remote service most likely), check user id
def _client_match_ps(self, ip, client_id, user_id):
# check existing pair
instance = self.client_id_to_ps_instance.get(client_id, None)
if instance is not None:
return
# check same ip ps instance
ps_instance_list = self.ip_to_ps_instance_list.get(ip, [])
count = len(ps_instance_list)
if count <= 0:
return
# if only one same ip ps instance, assign client id
if count == 1:
self.client_id_to_ps_instance[client_id] = ps_instance_list[0]
return
# if more than one same ip ps instance, check same user_id, same ip + same user id = same ps instance
ps_user_id_list = [instance.uid for instance in ps_instance_list]
try:
check_index = ps_user_id_list.index(user_id)
except:
check_index = None
if check_index is None:
return
self.client_id_to_ps_instance[client_id] = ps_instance_list[check_index]
def _remove_instance(self, instance):
# remove id from ip to instance list
for ip, ps_instance_list in self.ip_to_ps_instance_list.items():
if instance in ps_instance_list:
ps_instance_list.remove(instance)
# remove instance from client id to instance
for client_id in list(self.client_id_to_ps_instance.keys()):
check_instance = self.client_id_to_ps_instance.get(client_id, None)
if check_instance == instance:
self.client_id_to_ps_instance.pop(client_id, None)