!7 concept User { long userID; S name; toString { ret name; } } concept Channel { long channelID; S name; toString { ret name; } } sclass Reaction { long created; User user; S emoji; toString { ret emoji + " (" + user + ")"; } } concept Line { long msgID; bool bot, isPrivate; Channel channel; User author; S text; new L reactions; } cmodule GLines > DynCRUD { // API User uniqUser(long userID) { ret uniq_sync User(+userID); } Channel uniqChannel(long channelID) { ret uniq_sync Channel(+channelID); } Reaction nuReaction(O... params) { ret nu Reaction(params); } long getChannelID(S name) { ret getLongOrZero channelID(conceptWhere Channel(name := dropPrefix("#", name))); } Line lastLineInChannel(long channelID) { Channel channel = conceptWhere Channel(+channelID); if (channel == null) null; ret last(conceptsWhere Line(+channel)); } Line nextToLastLineInChannel(long channelID) { Channel channel = conceptWhere Channel(+channelID); if (channel == null) null; ret nextToLast(conceptsWhere Line(+channel)); } L linesInChannelBy(long channelID, long userID) { Channel channel = conceptWhere Channel(+channelID); if (channel == null) null; User user = conceptWhere User(+userID); if (user == null) null; ret conceptsWhere Line(+channel, author := user); } L linesInChannel(long channelID) { Channel channel = conceptWhere Channel(+channelID); if (channel == null) null; ret conceptsWhere Line(+channel); } long idForChannel(S name) { ret getChannelID(name); } // attention: Discord user names may change long idForUser(S name) { ret getLong userID(conceptWhere User(+name)); } }