Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 26 additions & 13 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from sclack.themes import themes

from sclack.widgets.set_snooze import SetSnoozeWidget
from sclack.utils.channel import is_dm, is_group, is_channel

loop = asyncio.get_event_loop()

Expand Down Expand Up @@ -157,26 +158,27 @@ def mount_sidebar(self, executor):

# Prepare list of Star users and channels
for dm in self.store.state.stars:
# Group chat is not supported, prefer to https://github.com/haskellcamargo/sclack/issues/67
if self.store.is_dm(dm['channel']):
if is_dm(dm['channel']):
detail = self.store.get_channel_info(dm['channel'])
user = self.store.find_user_by_id(detail['user'])

if user:
stars_user_id.append(user['id'])
star_user_tmp.append(Dm(
dm['channel'],
name=self.store.get_user_display_name(user),
user=dm['channel'],
user=user['id'],
you=False
))
elif self.store.is_channel(dm['channel']):
elif is_channel(dm['channel']) or is_group(dm['channel']):
channel = self.store.get_channel_info(dm['channel'])
if channel:
# Group chat (is_mpim) is not supported, prefer to https://github.com/haskellcamargo/sclack/issues/67
if channel and not channel.get('is_archived', False) and not channel.get('is_mpim', False):
stars_channel_id.append(channel['id'])
stars.append(Channel(
id=channel['id'],
name=channel['name'],
is_private=channel['is_private']
is_private=channel.get('is_private', True)
))
stars.extend(star_user_tmp)

Expand Down Expand Up @@ -206,9 +208,9 @@ def mount_sidebar(self, executor):

self.sidebar = SideBar(profile, channels, dms, stars=stars, title=self.store.state.auth['team'])
urwid.connect_signal(self.sidebar, 'go_to_channel', self.go_to_channel)
loop.create_task(self.get_channels_info(executor, channels))
loop.create_task(self.get_presences(executor, dms))
loop.create_task(self.get_dms_unread(executor, dms))
loop.create_task(self.get_channels_info(executor, self.sidebar.get_all_channels()))
loop.create_task(self.get_presences(executor, self.sidebar.get_all_dms()))
loop.create_task(self.get_dms_unread(executor, self.sidebar.get_all_dms()))

@asyncio.coroutine
def get_presences(self, executor, dm_widgets):
Expand Down Expand Up @@ -693,16 +695,27 @@ def stop_typing(*args):
self.chatbox.message_box.typing = None

alarm = None

while self.store.slack.server.connected is True:
events = self.store.slack.rtm_read()

for event in events:
if event.get('type') == 'hello':
pass
elif event.get('type') in ('channel_marked', 'group_marked'):
elif event.get('type') in ('channel_marked', 'group_marked', 'im_marked'):
unread = event.get('unread_count_display', 0)
for channel in self.sidebar.channels:
if channel.id == event['channel']:
channel.set_unread(unread)

if event.get('type') == 'channel_marked':
targets = self.sidebar.get_all_channels()
elif event.get('type') == 'group_marked':
targets = self.sidebar.get_all_groups()
else:
targets = self.sidebar.get_all_dms()

for target in targets:
if target.id == event['channel']:
target.set_unread(unread)

elif event['type'] == 'message':
loop.create_task(
self.update_chat(event)
Expand Down
96 changes: 81 additions & 15 deletions sclack/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .emoji import emoji_codemap
from .markdown import MarkdownText
from .store import Store
from sclack.utils.channel import is_group, is_channel, is_dm


MARK_READ_ALARM_PERIOD = 3
Expand Down Expand Up @@ -370,16 +371,21 @@ def handle_floating_date(self, size):


class Dm(urwid.AttrMap):
def __init__(self, id, name, user, you=False, unread=0):
def __init__(self, id, name, user, you=False, unread=0, is_selected=False):
self.id = id
self.user = user
self.name = name
self.you = you
self.presence = 'away'
self.unread = unread
self.body = urwid.SelectableIcon(self.get_markup())
self.is_selected = False
super(Dm, self).__init__(self.body, 'inactive', 'active_channel')
self.is_selected = is_selected

attr_map = 'inactive'
if is_selected:
attr_map = 'selected_channel'

super(Dm, self).__init__(self.body, attr_map, 'active_channel')

def get_markup(self, presence='away'):
if self.user == 'USLACKBOT':
Expand Down Expand Up @@ -417,11 +423,11 @@ def get_markup(self, presence='away'):

def set_unread(self, count):
self.unread = count

if count > 0:
self.attr_map = {None: 'unread_channel'}
else:
self.attr_map = {None: 'inactive'}
if not self.is_selected:
if count > 0:
self.attr_map = {None: 'unread_channel'}
else:
self.attr_map = {None: 'inactive'}

self.body.set_text(self.get_markup(self.presence))

Expand All @@ -440,12 +446,15 @@ def select(self):
'presence_away': 'selected_channel'
}
self.set_presence(self.presence)
self.attr_map = {None: 'selected_channel'}
self.focus_map = {None: 'selected_channel'}

def deselect(self):
self.is_selected = False
self.attr_map = {None: None}
self.set_presence(self.presence)


class Fields(urwid.Pile):
def chunks(self, list, size):
for i in range(0, len(list), size):
Expand Down Expand Up @@ -650,6 +659,7 @@ def text(self, text):
self.prompt_widget.set_edit_text(text)
self.prompt_widget.set_edit_pos(len(text))


class MessagePrompt(urwid_readline.ReadlineEdit):
__metaclass__ = urwid.MetaSignals
signals = ['submit_message', 'go_to_last_message']
Expand Down Expand Up @@ -748,6 +758,7 @@ def __init__(self, profile, channels=(), dms=(), stars=(), title=''):
self.channels = channels
self.stars = stars
self.dms = dms
self.groups = ()

# Subscribe to receive message from channels to select them
for channel in self.channels:
Expand All @@ -768,13 +779,72 @@ def __init__(self, profile, channels=(), dms=(), stars=(), title=''):
self.listbox = urwid.ListBox(self.walker)
super(SideBar, self).__init__(self.listbox, header=header, footer=footer)

def get_all_channels(self):
"""
List Channels including Starred items
:return:
"""
channels_starred = list(filter(
lambda starred: is_channel(starred.id),
self.stars
))
channels_starred.extend(self.channels)

return channels_starred

def get_all_dms(self):
"""
List DM including Starred items
:return:
"""
dms = list(filter(
lambda starred: is_dm(starred.id),
self.stars
))
dms.extend(self.dms)

return dms

def get_all_groups(self):
"""
List Groups including Starred items
:return:
"""
groups = list(filter(
lambda starred: is_group(starred.id),
self.stars
))
groups.extend(self.groups)

return groups

def get_targets_by_id(self, channel_id):
"""
For different channel_id we get different data from: Groups, DMs, Channels
:param channel_id:
:return:
"""
targets = None
if is_channel(channel_id):
targets = self.get_all_channels()
elif is_dm(channel_id):
targets = self.get_all_dms()
elif is_group(channel_id):
targets = self.get_all_groups()
return targets

def select_channel(self, channel_id):
for channel in self.channels:
"""
:param channel_id:
:return:
"""
for channel in self.get_all_channels():
if channel.id == channel_id:
channel.select()
else:
channel.deselect()
for dm in self.dms:

for dm in self.get_all_dms():
if dm.id == channel_id:
dm.select()
else:
Expand All @@ -787,11 +857,7 @@ def update_items(self, event):
:return:
"""
channel_id = event.get('channel')

if channel_id[0] == 'D':
target = self.dms
else:
target = self.channels
target = self.get_targets_by_id(channel_id)

chat_detail = Store.instance.get_channel_info(event.get('channel'))
new_count = chat_detail.get('unread_count_display', 0)
Expand Down
4 changes: 3 additions & 1 deletion sclack/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ def __init__(self):
self.online_users = set()
self.is_snoozed = False


class Cache:
def __init__(self):
self.avatar = {}
self.picture = {}


class Store:
def __init__(self, workspaces, config):
self.workspaces = workspaces
Expand Down Expand Up @@ -165,7 +167,7 @@ def load_stars(self):
:return:
"""
self.state.stars = list(filter(
lambda star: star.get('type', '') in ('channel', 'im', 'group', ),
lambda star: star.get('type', '') in ('channel', 'im', 'group',),
self.slack.api_call('stars.list')['items']
))

Expand Down
48 changes: 48 additions & 0 deletions sclack/utils/channel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
def get_group_name(group_raw_name):
"""
TODO Remove last number
:param group_raw_name:
:return:
"""
if group_raw_name[:5] == 'mpdm-':
group_parts = group_raw_name[5:].split('--')
group_parts = ['@{}'.format(item) for item in group_parts]
return ', '.join(group_parts)

return group_raw_name


def is_valid_channel_id(channel_id):
"""
Check whether channel_id is valid
:param channel_id:
:return:
"""
return channel_id[0] in ('C', 'G', 'D')


def is_channel(channel_id):
"""
Is a channel
:param channel_id:
:return:
"""
return channel_id[0] == 'C'


def is_dm(channel_id):
"""
Is direct message
:param channel_id:
:return:
"""
return channel_id[0] == 'D'


def is_group(channel_id):
"""
Is a group
:param channel_id:
:return:
"""
return channel_id[0] == 'G'