Cat Feeder  1.0.0
The Cat feeder project
Loading...
Searching...
No Matches
favicon_user.py
Go to the documentation of this file.
1"""
2# +==== BEGIN CatFeeder =================+
3# LOGO:
4# ..............(..../\\
5# ...............)..(.')
6# ..............(../..)
7# ...............\\(__)|
8# Inspired by Joan Stark
9# source https://www.asciiart.eu/
10# animals/cats
11# /STOP
12# PROJECT: CatFeeder
13# FILE: favicon_user.py
14# CREATION DATE: 05-01-2026
15# LAST Modified: 11:55:14 12-01-2026
16# DESCRIPTION:
17# This is the backend server in charge of making the actual website work.
18# /STOP
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: This is the class for handling user favicons.
21# // AR
22# +==== END CatFeeder =================+
23"""
24
25from typing import TYPE_CHECKING, Optional, List, Union, Dict, Any
26
27from fastapi import Response
28from display_tty import Disp, initialise_logger
29
30from . import favicon_constants as FAV_CONST
31from . import favicon_helpers as FAV_HELPERS
32from . import favicon_error_class as FAV_ERR
33
34from ..utils import CONST
35from ..core import FinalSingleton
36from ..http_codes import HCI, HttpDataTypes
37from ..core.runtime_manager import RI, RuntimeManager
38from ..image_reducer import IR_ERROR, FileFormat
39
40if TYPE_CHECKING:
41 from ..sql import SQL
42 from ..bucket import Bucket
43 from ..image_reducer import ImageReducer
44 from ..server_header import ServerHeaders
45 from ..boilerplates.responses import BoilerplateResponses
46
47
49
50 # --------------------------------------------------------------------------
51 # STATIC CLASS VALUES
52 # --------------------------------------------------------------------------
53
54 # -------------- Initialise the logger globally in the class. --------------
55 disp: Disp = initialise_logger(__qualname__, False)
56
57 # --------------------------------------------------------------------------
58 # CONSTRUCTOR & DESTRUCTOR
59 # --------------------------------------------------------------------------
60
61 def __init__(self, success: int = 0, error: int = 84, debug: bool = False) -> None:
62 """Initialize the ImageReducer instance with dependencies.
63
64 Keyword Arguments:
65 debug: Enable debug logging when True. Defaults to False.
66 """
67 # ------------------------ The logging function ------------------------
68 self.disp.update_disp_debug(debug)
69 self.success = success
70 self.error = error
71 self.disp.log_debug("Initialising...")
72 self.runtime_manager: RuntimeManager = RI
73 self.boilerplate_response: "BoilerplateResponses" = self.runtime_manager.get(
74 "BoilerplateResponses")
75 self.server_header: "ServerHeaders" = self.runtime_manager.get(
76 "ServerHeaders")
77 self.bucket: "Bucket" = self.runtime_manager.get("Bucket")
78 self.sql: "SQL" = self.runtime_manager.get("SQL")
79 self.image_reducerimage_reducer: Optional["ImageReducer"] = self.runtime_manager.get_if_exists(
80 "ImageReducer", None)
81 self.disp.log_debug("Initialised")
82
83 def _no_user_id(self, title: str, token: Optional[str] = None) -> Response:
84 self.disp.log_error("There is no specified user id.")
85 return self.boilerplate_response.user_not_found(title, token)
86
87 def _no_data(self, title: str, token: Optional[str] = None) -> Response:
88 self.disp.log_error("There is no data available.")
89 body = self.boilerplate_response.build_response_body(
90 title=title,
91 message="No icon available",
92 resp="No data",
93 token=token,
94 error=True
95 )
96 return HCI.not_found(
97 content=body,
98 content_type=HttpDataTypes.JSON,
99 headers=self.server_header.for_json()
100 )
101
102 def reducer_type_to_data_type(self, reducer_type: FileFormat) -> HttpDataTypes:
103 """(This is a wrapper of the same function in the constants)
104 Convert an ImageReducer FileFormat to an HttpDataTypes value.
105
106 Args:
107 reducer_type (IR_CONST.FileFormat): The image reducer file format.
108
109 Returns:
110 HttpDataTypes: The corresponding HTTP data type.
111 """
112 return FAV_CONST.reducer_type_to_data_type(reducer_type)
113
114 def list_user_favicons(self, user_id: Optional[int] = None, *, title: str = "list_user_favicon", token: Optional[str] = None) -> Union[List[Dict[str, Any]], Response]:
115 table: str = FAV_CONST.FAVICON_USER_OWNED_TABLE
116 if user_id is None:
117 self.disp.log_error(
118 "There is no specified user to search for, returning []"
119 )
120 return self._no_user_id(title, token)
121 self.disp.log_debug(
122 f"Gathering the list of uploaded user icons from table '{table}' and user id='{user_id}'"
123 )
124 resp = self.sql.get_data_from_table(
125 table=table,
126 column="*",
127 where=f"user_id={user_id}"
128 )
129 if isinstance(resp, int):
130 self.disp.log_error(
131 f"Failed to gather data for table '{table}' and user id='{user_id}'"
132 )
133 return self._no_data(title, token)
134 self.disp.log_debug(
135 f"Data gathered for table '{table}' and user id='{user_id}':\n{resp}"
136 )
137 return resp
138
139 def list_active_user_favicons(self, user_id: Optional[int] = None, *, title: str = "list_active_user_favicon", token: Optional[str] = None) -> Union[List[Dict[str, Any]], Response]:
140 table: str = FAV_CONST.FAVICON_USER_ACTIVE_TABLE
141 if user_id is None:
142 self.disp.log_error(
143 "There is no specified user to search for, returning []"
144 )
145 return self._no_user_id(title, token)
146 self.disp.log_debug(
147 f"Gathering the list of uploaded user icons from table '{table}' and user id='{user_id}'"
148 )
149 resp = self.sql.get_data_from_table(
150 table=table,
151 column="*",
152 where=f"user_id={user_id}"
153 )
154 if isinstance(resp, int):
155 self.disp.log_error(
156 f"Failed to gather data for table '{table}' and user id='{user_id}'"
157 )
158 return self._no_data(title, token)
159 self.disp.log_debug(
160 f"Data gathered for table '{table}' and user id='{user_id}':\n{resp}"
161 )
162 return resp
163
164 def get_user_favicon(self, user_id, favicon_id, *, title: str = "list_user_favicon", token: Optional[str] = None) -> Union[FAV_CONST.FaviconData, Response]:
165 table: str = FAV_CONST.FAVICON_USER_ACTIVE_TABLE
166 final_resp: FAV_CONST.FaviconData = FAV_CONST.FaviconData()
167 if user_id is None:
168 self.disp.log_error(
169 "There is no specified user to search for"
170 )
171 return self._no_user_id(title, token)
172 self.disp.log_debug(
173 f"Gathering the list of uploaded user icons from table '{table}' and user id='{user_id}'"
174 )
175 sql_resp = self.sql.get_data_from_table(
176 table=table,
177 column="*",
178 where=[f"user_id={user_id}", f"icon_id={favicon_id}"]
179 )
180 if isinstance(sql_resp, int):
181 self.disp.log_error(
182 f"Failed to gather data for table '{table}' and user id='{user_id}'"
183 )
184 return self._no_data(title, token)
185 if len(sql_resp) == 0:
186 return final_resp
187 sql_raw_data = self.sql.get_data_from_table(
188 table=FAV_CONST.FAVICON_TABLE_MAIN,
189 column="*",
190 where=f"id={favicon_id}"
191 )
192 if isinstance(sql_raw_data, int):
193 self.disp.log_error(
194 f"Failed to gather raw data for table '{FAV_CONST.FAVICON_TABLE_MAIN}' and icon id='{favicon_id}'"
195 )
196 return self._no_data(title, token)
197 if len(sql_raw_data) == 0:
198 return final_resp
199 final_resp.data = CONST.clean_dict(
200 sql_raw_data[0].copy(),
201 (FAV_CONST.FAVICON_IMAGE_PATH_KEY, ""),
202 self.disp
203 )
204 if sql_raw_data[0][FAV_CONST.FAVICON_IMAGE_PATH_KEY] is None or sql_raw_data[0][FAV_CONST.FAVICON_IMAGE_PATH_KEY] == "":
205 self.disp.log_error(
206 f"There is no image path for icon id='{favicon_id}'"
207 )
208 return final_resp
209 img_path = sql_raw_data[0][FAV_CONST.FAVICON_IMAGE_PATH_KEY]
210 bucket_resp = self.bucket.download_stream(
211 bucket_name=FAV_CONST.FAVICON_BUCKET_NAME,
212 key_name=img_path
213 )
214 if isinstance(bucket_resp, int):
215 self.disp.log_error(
216 f"Failed to download image data from bucket '{FAV_CONST.FAVICON_BUCKET_NAME}' and path '{img_path}'"
217 )
218 return final_resp
219 final_resp.img = bucket_resp
221 "ImageReducer", self.image_reducerimage_reducer)
222 if self.image_reducerimage_reducer is None:
223 self.disp.log_error(
224 "There is no ImageReducer instance available in the runtime manager"
225 )
226 return final_resp
227 final_resp.img_type = self.reducer_type_to_data_type(
228 self.image_reducerimage_reducer.detect_file_format(final_resp.img)
229 )
230 self.disp.log_debug(
231 f"Data gathered for table '{table}' and user id='{user_id}':\n{final_resp}"
232 )
233 return final_resp
Union[List[Dict[str, Any]], Response] list_active_user_favicons(self, Optional[int] user_id=None, *, str title="list_active_user_favicon", Optional[str] token=None)
Response _no_data(self, str title, Optional[str] token=None)
Response _no_user_id(self, str title, Optional[str] token=None)
Union[List[Dict[str, Any]], Response] list_user_favicons(self, Optional[int] user_id=None, *, str title="list_user_favicon", Optional[str] token=None)
None __init__(self, int success=0, int error=84, bool debug=False)
HttpDataTypes reducer_type_to_data_type(self, FileFormat reducer_type)
Union[FAV_CONST.FaviconData, Response] get_user_favicon(self, user_id, favicon_id, *, str title="list_user_favicon", Optional[str] token=None)