fix: 포트 충돌 회피 — note_bridge 8098, intent_service 8099

Jellyfin(8096), OrbStack(8097) 포트 충돌으로 변경.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-19 13:53:55 +09:00
parent dc08d29509
commit c2257d3a86
2709 changed files with 619549 additions and 10 deletions

View File

@@ -0,0 +1 @@
#!/usr/bin/env python

View File

@@ -0,0 +1,106 @@
#!/usr/bin/env python
import sys
from typing import ClassVar
from typing import List
from typing import Optional
from typing import Union
from lxml import etree
from lxml.etree import _Element
from caldav.lib.namespace import nsmap
from caldav.lib.python_utilities import to_unicode
if sys.version_info < (3, 9):
from typing import Iterable
else:
from collections.abc import Iterable
if sys.version_info < (3, 11):
from typing_extensions import Self
else:
from typing import Self
class BaseElement:
children: Optional[List[Self]] = None
tag: ClassVar[Optional[str]] = None
value: Optional[str] = None
attributes: Optional[dict] = None
caldav_class = None
def __init__(
self, name: Optional[str] = None, value: Union[str, bytes, None] = None
) -> None:
self.children = []
self.attributes = {}
value = to_unicode(value)
self.value = None
if name is not None:
self.attributes["name"] = name
if value is not None:
self.value = value
def __add__(
self, other: Union["BaseElement", Iterable["BaseElement"]]
) -> "BaseElement":
return self.append(other)
def __str__(self) -> str:
utf8 = etree.tostring(
self.xmlelement(), encoding="utf-8", xml_declaration=True, pretty_print=True
)
return str(utf8, "utf-8")
def xmlelement(self) -> _Element:
if self.tag is None:
## We can do better than this. tag may be a property that expands
## from the class name. Another layer of base class to indicate
## if it's the D-namespace, C-namespace or another namespace.
raise ValueError("Unexpected value None for self.tag")
if self.attributes is None:
raise ValueError("Unexpected value None for self.attributes")
root = etree.Element(self.tag, nsmap=nsmap)
if self.value is not None:
root.text = self.value
for k in self.attributes:
root.set(k, self.attributes[k])
self.xmlchildren(root)
return root
def xmlchildren(self, root: _Element) -> None:
if self.children is None:
raise ValueError("Unexpected value None for self.children")
for c in self.children:
root.append(c.xmlelement())
def append(self, element: Union[Self, Iterable[Self]]) -> Self:
if self.children is None:
raise ValueError("Unexpected value None for self.children")
if isinstance(element, Iterable):
self.children.extend(element)
else:
self.children.append(element)
return self
class NamedBaseElement(BaseElement):
def __init__(self, name: Optional[str] = None) -> None:
super(NamedBaseElement, self).__init__(name=name)
def xmlelement(self):
if self.attributes.get("name") is None:
raise Exception("name attribute must be defined")
return super(NamedBaseElement, self).xmlelement()
class ValuedBaseElement(BaseElement):
def __init__(self, value: Union[str, bytes, None] = None) -> None:
super(ValuedBaseElement, self).__init__(value=value)

View File

@@ -0,0 +1,223 @@
#!/usr/bin/env python
import logging
from datetime import datetime
from datetime import timezone
from typing import ClassVar
from typing import Optional
from .base import BaseElement
from .base import NamedBaseElement
from .base import ValuedBaseElement
from caldav.lib.namespace import ns
utc_tz = timezone.utc
def _to_utc_date_string(ts):
# type (Union[date,datetime]]) -> str
"""coerce datetimes to UTC (assume localtime if nothing is given)"""
if isinstance(ts, datetime):
try:
## for any python version, this should work for a non-native
## timestamp.
## in python 3.6 and higher, ts.astimezone() will assume a
## naive timestamp is localtime (and so do we)
ts = ts.astimezone(utc_tz)
except:
## native time stamp and the current python version is
## not able to treat it as localtime.
import tzlocal
ts = ts.replace(tzinfo=tzlocal.get_localzone())
mindate = datetime.min.replace(tzinfo=utc_tz)
maxdate = datetime.max.replace(tzinfo=utc_tz)
if mindate + ts.tzinfo.utcoffset(ts) > ts:
logging.error(
"Cannot coerce datetime %s to UTC. Changed to min-date.", ts
)
ts = mindate
elif ts > maxdate - ts.tzinfo.utcoffset(ts):
logging.error(
"Cannot coerce datetime %s to UTC. Changed to max-date.", ts
)
ts = maxdate
else:
ts = ts.astimezone(utc_tz)
return ts.strftime("%Y%m%dT%H%M%SZ")
# Operations
class CalendarQuery(BaseElement):
tag: ClassVar[str] = ns("C", "calendar-query")
class FreeBusyQuery(BaseElement):
tag: ClassVar[str] = ns("C", "free-busy-query")
class Mkcalendar(BaseElement):
tag: ClassVar[str] = ns("C", "mkcalendar")
class CalendarMultiGet(BaseElement):
tag: ClassVar[str] = ns("C", "calendar-multiget")
class ScheduleInboxURL(BaseElement):
tag: ClassVar[str] = ns("C", "schedule-inbox-URL")
class ScheduleOutboxURL(BaseElement):
tag: ClassVar[str] = ns("C", "schedule-outbox-URL")
# Filters
class Filter(BaseElement):
tag: ClassVar[str] = ns("C", "filter")
class CompFilter(NamedBaseElement):
tag: ClassVar[str] = ns("C", "comp-filter")
class PropFilter(NamedBaseElement):
tag: ClassVar[str] = ns("C", "prop-filter")
class ParamFilter(NamedBaseElement):
tag: ClassVar[str] = ns("C", "param-filter")
# Conditions
class TextMatch(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "text-match")
def __init__(self, value, collation: str = "i;octet", negate: bool = False) -> None:
super(TextMatch, self).__init__(value=value)
if self.attributes is None:
raise ValueError("Unexpected value None for self.attributes")
self.attributes["collation"] = collation
if negate:
self.attributes["negate-condition"] = "yes"
class TimeRange(BaseElement):
tag: ClassVar[str] = ns("C", "time-range")
def __init__(
self, start: Optional[datetime] = None, end: Optional[datetime] = None
) -> None:
## start and end should be an icalendar "date with UTC time",
## ref https://tools.ietf.org/html/rfc4791#section-9.9
super(TimeRange, self).__init__()
if self.attributes is None:
raise ValueError("Unexpected value None for self.attributes")
if start is not None:
self.attributes["start"] = _to_utc_date_string(start)
if end is not None:
self.attributes["end"] = _to_utc_date_string(end)
class NotDefined(BaseElement):
tag: ClassVar[str] = ns("C", "is-not-defined")
# Components / Data
class CalendarData(BaseElement):
tag: ClassVar[str] = ns("C", "calendar-data")
class Expand(BaseElement):
tag: ClassVar[str] = ns("C", "expand")
def __init__(
self, start: Optional[datetime], end: Optional[datetime] = None
) -> None:
super(Expand, self).__init__()
if self.attributes is None:
raise ValueError("Unexpected value None for self.attributes")
if start is not None:
self.attributes["start"] = _to_utc_date_string(start)
if end is not None:
self.attributes["end"] = _to_utc_date_string(end)
class Comp(NamedBaseElement):
tag: ClassVar[str] = ns("C", "comp")
# Uhhm ... can't find any references to calendar-collection in rfc4791.txt
# and newer versions of baikal gives 403 forbidden when this one is
# encountered
# class CalendarCollection(BaseElement):
# tag = ns("C", "calendar-collection")
# Properties
class CalendarUserAddressSet(BaseElement):
tag: ClassVar[str] = ns("C", "calendar-user-address-set")
class CalendarUserType(BaseElement):
tag: ClassVar[str] = ns("C", "calendar-user-type")
class CalendarHomeSet(BaseElement):
tag: ClassVar[str] = ns("C", "calendar-home-set")
# calendar resource type, see rfc4791, sec. 4.2
class Calendar(BaseElement):
tag: ClassVar[str] = ns("C", "calendar")
class CalendarDescription(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "calendar-description")
class CalendarTimeZone(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "calendar-timezone")
class SupportedCalendarComponentSet(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "supported-calendar-component-set")
class SupportedCalendarData(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "supported-calendar-data")
class MaxResourceSize(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "max-resource-size")
class MinDateTime(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "min-date-time")
class MaxDateTime(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "max-date-time")
class MaxInstances(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "max-instances")
class MaxAttendeesPerInstance(ValuedBaseElement):
tag: ClassVar[str] = ns("C", "max-attendees-per-instance")
class Allprop(BaseElement):
tag: ClassVar[str] = ns("C", "allprop")
class ScheduleTag(BaseElement):
tag: ClassVar[str] = ns("C", "schedule-tag")

View File

@@ -0,0 +1,115 @@
#!/usr/bin/env python
from typing import ClassVar
from .base import BaseElement
from .base import ValuedBaseElement
from caldav.lib.namespace import ns
# Operations
class Propfind(BaseElement):
tag: ClassVar[str] = ns("D", "propfind")
class PropertyUpdate(BaseElement):
tag: ClassVar[str] = ns("D", "propertyupdate")
class Mkcol(BaseElement):
tag: ClassVar[str] = ns("D", "mkcol")
class SyncCollection(BaseElement):
tag: ClassVar[str] = ns("D", "sync-collection")
class PrincipalPropertySearch(BaseElement):
tag: ClassVar[str] = ns("D", "principal-property-search")
class PropertySearch(BaseElement):
tag: ClassVar[str] = ns("D", "property-search")
# Filters
class Match(BaseElement):
tag: ClassVar[str] = ns("D", "match")
# Conditions
class SyncToken(BaseElement):
tag: ClassVar[str] = ns("D", "sync-token")
class SyncLevel(BaseElement):
tag: ClassVar[str] = ns("D", "sync-level")
# Components / Data
class Prop(BaseElement):
tag: ClassVar[str] = ns("D", "prop")
class Collection(BaseElement):
tag: ClassVar[str] = ns("D", "collection")
class Set(BaseElement):
tag: ClassVar[str] = ns("D", "set")
# Properties
class ResourceType(BaseElement):
tag: ClassVar[str] = ns("D", "resourcetype")
class DisplayName(ValuedBaseElement):
tag: ClassVar[str] = ns("D", "displayname")
class GetEtag(ValuedBaseElement):
tag: ClassVar[str] = ns("D", "getetag")
class Href(BaseElement):
tag: ClassVar[str] = ns("D", "href")
class SupportedReportSet(BaseElement):
tag = ns("D", "supported-report-set")
class Response(BaseElement):
tag: ClassVar[str] = ns("D", "response")
class Status(BaseElement):
tag: ClassVar[str] = ns("D", "status")
class PropStat(BaseElement):
tag: ClassVar[str] = ns("D", "propstat")
class MultiStatus(BaseElement):
tag: ClassVar[str] = ns("D", "multistatus")
class CurrentUserPrincipal(BaseElement):
tag: ClassVar[str] = ns("D", "current-user-principal")
class PrincipalCollectionSet(BaseElement):
tag: ClassVar[str] = ns("D", "principal-collection-set")
class Allprop(BaseElement):
tag: ClassVar[str] = ns("D", "allprop")
class Owner(BaseElement):
tag: ClassVar[str] = ns("D", "owner")

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env python
from typing import ClassVar
from .base import ValuedBaseElement
from caldav.lib.namespace import ns
# Properties
class CalendarColor(ValuedBaseElement):
tag: ClassVar[str] = ns("I", "calendar-color")
class CalendarOrder(ValuedBaseElement):
tag: ClassVar[str] = ns("I", "calendar-order")