Full program data with associated channels and streams for search results.
| 221 | |
| 222 | |
| 223 | class ProgramSearchResultSerializer(serializers.ModelSerializer): |
| 224 | """Full program data with associated channels and streams for search results.""" |
| 225 | epg_source = serializers.CharField(source='epg.epg_source.name', default=None) |
| 226 | epg_name = serializers.CharField(source='epg.name', default=None) |
| 227 | epg_icon_url = serializers.URLField(source='epg.icon_url', default=None) |
| 228 | channels = serializers.SerializerMethodField() |
| 229 | streams = serializers.SerializerMethodField() |
| 230 | |
| 231 | class Meta: |
| 232 | model = ProgramData |
| 233 | fields = [ |
| 234 | 'id', 'title', 'sub_title', 'description', |
| 235 | 'start_time', 'end_time', 'tvg_id', 'custom_properties', |
| 236 | 'epg_source', 'epg_name', 'epg_icon_url', |
| 237 | 'channels', 'streams', |
| 238 | ] |
| 239 | |
| 240 | def _accessible_channels(self, obj): |
| 241 | """Return prefetched channels filtered to those the requesting user can access.""" |
| 242 | channels = list(obj.epg.channels.all()) if obj.epg else [] |
| 243 | user = self.context.get('user') |
| 244 | if user is None or user.user_level >= 10: |
| 245 | return channels |
| 246 | custom_props = user.custom_properties or {} |
| 247 | hide_adult = custom_props.get('hide_adult_content', False) |
| 248 | return [ |
| 249 | ch for ch in channels |
| 250 | if ch.user_level <= user.user_level and (not hide_adult or not ch.is_adult) |
| 251 | ] |
| 252 | |
| 253 | def get_channels(self, obj): |
| 254 | fields = self.context.get('fields') |
| 255 | if fields is not None and 'channels' not in fields: |
| 256 | return [] |
| 257 | return ProgramSearchChannelSerializer(self._accessible_channels(obj), many=True).data |
| 258 | |
| 259 | def get_streams(self, obj): |
| 260 | fields = self.context.get('fields') |
| 261 | if fields is not None and 'streams' not in fields: |
| 262 | return [] |
| 263 | stream_ids = set() |
| 264 | streams = [] |
| 265 | for ch in self._accessible_channels(obj): |
| 266 | for s in ch.streams.all(): |
| 267 | if s.id not in stream_ids: |
| 268 | stream_ids.add(s.id) |
| 269 | streams.append(s) |
| 270 | return ProgramSearchStreamSerializer(streams, many=True).data |