| 165 | |
| 166 | |
| 167 | def parse_feed_metadata(xml_bytes: bytes, feed_url: str) -> FeedMetadata: |
| 168 | try: |
| 169 | root = ET.fromstring(xml_bytes) |
| 170 | except ET.ParseError as exc: |
| 171 | raise ValueError(f"RSS/Atom XML parse failed: {exc}") from exc |
| 172 | |
| 173 | root_name = strip_namespace(root.tag) |
| 174 | title = "" |
| 175 | html_url = "" |
| 176 | |
| 177 | if root_name == "rss": |
| 178 | channel = _find_first_child(root, "channel") |
| 179 | if channel is not None: |
| 180 | title = _find_text_child(channel, "title") |
| 181 | html_url = _find_text_child(channel, "link") |
| 182 | elif root_name == "feed": |
| 183 | title = _find_text_child(root, "title") |
| 184 | html_url = _extract_atom_html_url(root) |
| 185 | elif root_name == "rdf": |
| 186 | channel = _find_first_child(root, "channel") |
| 187 | if channel is not None: |
| 188 | title = _find_text_child(channel, "title") |
| 189 | html_url = _find_text_child(channel, "link") |
| 190 | return _build_feed_metadata(root_name, title, html_url, feed_url) |
| 191 | |
| 192 | |
| 193 | def parse_feed_metadata_stream( |