mirror of
https://github.com/element-hq/synapse.git
synced 2024-11-22 01:25:44 +03:00
Reimplement the get public rooms api to work with new DB schema
This commit is contained in:
parent
2c46bb6208
commit
5002efa31b
7 changed files with 100 additions and 36 deletions
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
from synapse.api.events.room import (
|
from synapse.api.events.room import (
|
||||||
RoomTopicEvent, MessageEvent, RoomMemberEvent, FeedbackEvent,
|
RoomTopicEvent, MessageEvent, RoomMemberEvent, FeedbackEvent,
|
||||||
InviteJoinEvent, RoomConfigEvent
|
InviteJoinEvent, RoomConfigEvent, RoomNameEvent,
|
||||||
)
|
)
|
||||||
|
|
||||||
from synapse.util.stringutils import random_string
|
from synapse.util.stringutils import random_string
|
||||||
|
@ -25,6 +25,7 @@ class EventFactory(object):
|
||||||
|
|
||||||
_event_classes = [
|
_event_classes = [
|
||||||
RoomTopicEvent,
|
RoomTopicEvent,
|
||||||
|
RoomNameEvent,
|
||||||
MessageEvent,
|
MessageEvent,
|
||||||
RoomMemberEvent,
|
RoomMemberEvent,
|
||||||
FeedbackEvent,
|
FeedbackEvent,
|
||||||
|
|
|
@ -19,14 +19,37 @@ from . import SynapseEvent
|
||||||
class RoomTopicEvent(SynapseEvent):
|
class RoomTopicEvent(SynapseEvent):
|
||||||
TYPE = "m.room.topic"
|
TYPE = "m.room.topic"
|
||||||
|
|
||||||
|
internal_keys = SynapseEvent.internal_keys + [
|
||||||
|
"topic",
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
kwargs["state_key"] = ""
|
kwargs["state_key"] = ""
|
||||||
|
if "topic" in kwargs["content"]:
|
||||||
|
kwargs["topic"] = kwargs["content"]["topic"]
|
||||||
super(RoomTopicEvent, self).__init__(**kwargs)
|
super(RoomTopicEvent, self).__init__(**kwargs)
|
||||||
|
|
||||||
def get_content_template(self):
|
def get_content_template(self):
|
||||||
return {"topic": u"string"}
|
return {"topic": u"string"}
|
||||||
|
|
||||||
|
|
||||||
|
class RoomNameEvent(SynapseEvent):
|
||||||
|
TYPE = "m.room.name"
|
||||||
|
|
||||||
|
internal_keys = SynapseEvent.internal_keys + [
|
||||||
|
"name",
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
kwargs["state_key"] = ""
|
||||||
|
if "name" in kwargs["content"]:
|
||||||
|
kwargs["name"] = kwargs["content"]["name"]
|
||||||
|
super(RoomNameEvent, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def get_content_template(self):
|
||||||
|
return {"name": u"string"}
|
||||||
|
|
||||||
|
|
||||||
class RoomMemberEvent(SynapseEvent):
|
class RoomMemberEvent(SynapseEvent):
|
||||||
TYPE = "m.room.member"
|
TYPE = "m.room.member"
|
||||||
|
|
||||||
|
|
|
@ -790,5 +790,5 @@ class RoomListHandler(BaseHandler):
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def get_public_room_list(self):
|
def get_public_room_list(self):
|
||||||
chunk = yield self.store.get_rooms(is_public=True, with_topics=True)
|
chunk = yield self.store.get_rooms(is_public=True)
|
||||||
defer.returnValue({"start": "START", "end": "END", "chunk": chunk})
|
defer.returnValue({"start": "START", "end": "END", "chunk": chunk})
|
||||||
|
|
|
@ -17,7 +17,7 @@ from twisted.internet import defer
|
||||||
|
|
||||||
from synapse.api.events.room import (
|
from synapse.api.events.room import (
|
||||||
RoomMemberEvent, MessageEvent, RoomTopicEvent, FeedbackEvent,
|
RoomMemberEvent, MessageEvent, RoomTopicEvent, FeedbackEvent,
|
||||||
RoomConfigEvent
|
RoomConfigEvent, RoomNameEvent,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .directory import DirectoryStore
|
from .directory import DirectoryStore
|
||||||
|
@ -52,6 +52,10 @@ class DataStore(RoomMemberStore, RoomStore,
|
||||||
yield self._store_feedback(event)
|
yield self._store_feedback(event)
|
||||||
elif event.type == RoomConfigEvent.TYPE:
|
elif event.type == RoomConfigEvent.TYPE:
|
||||||
yield self._store_room_config(event)
|
yield self._store_room_config(event)
|
||||||
|
elif event.type == RoomNameEvent.TYPE:
|
||||||
|
yield self._store_room_name(event)
|
||||||
|
elif event.type == RoomTopicEvent.TYPE:
|
||||||
|
yield self._store_room_topic(event)
|
||||||
|
|
||||||
yield self._store_event(event)
|
yield self._store_event(event)
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ class SQLBaseStore(object):
|
||||||
if decoder:
|
if decoder:
|
||||||
return decoder(cursor)
|
return decoder(cursor)
|
||||||
else:
|
else:
|
||||||
return cursor
|
return cursor.fetchall()
|
||||||
|
|
||||||
return self._db_pool.runInteraction(interaction)
|
return self._db_pool.runInteraction(interaction)
|
||||||
|
|
||||||
|
|
|
@ -76,49 +76,73 @@ class RoomStore(SQLBaseStore):
|
||||||
)
|
)
|
||||||
|
|
||||||
@defer.inlineCallbacks
|
@defer.inlineCallbacks
|
||||||
def get_rooms(self, is_public, with_topics):
|
def get_rooms(self, is_public):
|
||||||
"""Retrieve a list of all public rooms.
|
"""Retrieve a list of all public rooms.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
is_public (bool): True if the rooms returned should be public.
|
is_public (bool): True if the rooms returned should be public.
|
||||||
with_topics (bool): True to include the current topic for the room
|
|
||||||
in the response.
|
|
||||||
Returns:
|
Returns:
|
||||||
A list of room dicts containing at least a "room_id" key, and a
|
A list of room dicts containing at least a "room_id" key, a
|
||||||
"topic" key if one is set and with_topic=True.
|
"topic" key if one is set, and a "name" key if one is set
|
||||||
"""
|
"""
|
||||||
room_data_type = RoomTopicEvent.TYPE
|
|
||||||
public = 1 if is_public else 0
|
|
||||||
|
|
||||||
latest_topic = ("SELECT max(room_data.id) FROM room_data WHERE "
|
topic_subquery = (
|
||||||
+ "room_data.type = ? GROUP BY room_id")
|
"SELECT topics.event_id as event_id, topics.room_id as room_id, topic FROM topics "
|
||||||
|
"INNER JOIN current_state_events as c "
|
||||||
query = ("SELECT rooms.*, room_data.content, room_alias FROM rooms "
|
"ON c.event_id = topics.event_id "
|
||||||
+ "LEFT JOIN "
|
|
||||||
+ "room_aliases ON room_aliases.room_id = rooms.room_id "
|
|
||||||
+ "LEFT JOIN "
|
|
||||||
+ "room_data ON rooms.room_id = room_data.room_id WHERE "
|
|
||||||
+ "(room_data.id IN (" + latest_topic + ") "
|
|
||||||
+ "OR room_data.id IS NULL) AND rooms.is_public = ?")
|
|
||||||
|
|
||||||
res = yield self._execute(
|
|
||||||
self.cursor_to_dict, query, room_data_type, public
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# return only the keys the specification expects
|
name_subquery = (
|
||||||
ret_keys = ["room_id", "topic", "room_alias"]
|
"SELECT room_names.event_id as event_id, room_names.room_id as room_id, name FROM room_names "
|
||||||
|
"INNER JOIN current_state_events as c "
|
||||||
|
"ON c.event_id = room_names.event_id "
|
||||||
|
)
|
||||||
|
|
||||||
# extract topic from the json (icky) FIXME
|
sql = (
|
||||||
for i, room_row in enumerate(res):
|
"SELECT r.room_id, n.name, t.topic, group_concat(a.room_alias) FROM rooms AS r "
|
||||||
try:
|
"LEFT JOIN (%(topic)s) AS t ON t.room_id = r.room_id "
|
||||||
content_json = json.loads(room_row["content"])
|
"LEFT JOIN (%(name)s) AS n ON n.room_id = r.room_id "
|
||||||
room_row["topic"] = content_json["topic"]
|
"INNER JOIN room_aliases AS a ON a.room_id = r.room_id "
|
||||||
except:
|
"WHERE r.is_public = ? "
|
||||||
pass # no topic set
|
"GROUP BY r.room_id "
|
||||||
# filter the dict based on ret_keys
|
) % {
|
||||||
res[i] = {k: v for k, v in room_row.iteritems() if k in ret_keys}
|
"topic": topic_subquery,
|
||||||
|
"name": name_subquery,
|
||||||
|
}
|
||||||
|
|
||||||
defer.returnValue(res)
|
rows = yield self._execute(None, sql, is_public)
|
||||||
|
|
||||||
|
ret = [
|
||||||
|
{
|
||||||
|
"room_id": r[0],
|
||||||
|
"name": r[1],
|
||||||
|
"topic": r[2],
|
||||||
|
"aliases": r[3].split(","),
|
||||||
|
}
|
||||||
|
for r in rows
|
||||||
|
]
|
||||||
|
|
||||||
|
defer.returnValue(ret)
|
||||||
|
|
||||||
|
def _store_room_topic(self, event):
|
||||||
|
return self._simple_insert(
|
||||||
|
"topics",
|
||||||
|
{
|
||||||
|
"event_id": event.event_id,
|
||||||
|
"room_id": event.room_id,
|
||||||
|
"topic": event.topic,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
def _store_room_name(self, event):
|
||||||
|
return self._simple_insert(
|
||||||
|
"room_names",
|
||||||
|
{
|
||||||
|
"event_id": event.event_id,
|
||||||
|
"room_id": event.room_id,
|
||||||
|
"name": event.name,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class RoomsTable(Table):
|
class RoomsTable(Table):
|
||||||
|
|
|
@ -51,6 +51,18 @@ CREATE TABLE IF NOT EXISTS feedback(
|
||||||
room_id TEXT
|
room_id TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS topics(
|
||||||
|
event_id TEXT NOT NULL,
|
||||||
|
room_id TEXT NOT NULL,
|
||||||
|
topic TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS room_names(
|
||||||
|
event_id TEXT NOT NULL,
|
||||||
|
room_id TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS rooms(
|
CREATE TABLE IF NOT EXISTS rooms(
|
||||||
room_id TEXT PRIMARY KEY NOT NULL,
|
room_id TEXT PRIMARY KEY NOT NULL,
|
||||||
is_public INTEGER,
|
is_public INTEGER,
|
||||||
|
|
Loading…
Reference in a new issue