# Path: channels/app.py
# def init_database(app):
# def init_disqus(app):
# def init_publisher(app):
# def get_client(key):
# 
# Path: channels/oauth.py
# def api_call(func, **kwargs):
#     access_token = get_access_token()
#     try:
#         if access_token:
#             result = func(access_token=access_token, **kwargs)
#         else:
#             result = func(**kwargs)
#     except InvalidAccessToken:
#         raise Logout
#     return result
# 
# Path: channels/utils.py
# def avatar_hash(user):
#     return md5('disqus:' + str(user['username'])).hexdigest()
# 
# def datestr_to_datetime(dt):
#     return datetime.strptime(dt, '%Y-%m-%dT%H:%M:%S')
# 
# def from_cache(callback, cache_key=None, expires=60):
#     if cache_key is None:
#         if hasattr(callback, 'im_self'):
#             cache_key = '.'.join([callback.__module__, callback.im_self.__name__, callback.__name__])
#         else:
#             cache_key = '%s.%s' % (callback.__module__, callback.__name__)
#     conn = db.get_conn(cache_key)
#     result = conn.get(cache_key)
#     if result:
#         try:
#             result = json.loads(result)
#         except Exception, e:
#             logger.exception(e)
#             result = None
# 
#     if result is None:
#         result = callback()
#         pipe = conn.pipeline()
#         pipe.set(cache_key, json.dumps(result))
#         pipe.expire(cache_key, 60)
#         pipe.execute()
#     return result
# 
# def secure_avatar(avatar_url):
#     return avatar_url.replace('http://mediacdn', 'https://securecdn')
# 
# Path: channels/views.py
# class Publisher(object):
# class View(object):
#     def __init__(self, client, buffer_size=10000):
#     def publish(self, key, value):
#     def __init__(self, redis, publisher, name, version=1):
#     def add(self, data, score, _key=None, **kwargs):
#     def add_to_set(self, id, score, _data=None, _key=None, **kwargs):
#     def incr_in_set(self, id, score, _data=None, _key=None, **kwargs):
#     def remove(self, data, _key=None, **kwargs):
#     def remove_from_set(self, id, _key=None, **kwargs):
#     def incr_counter(self, id, key, amount=1):
#     def get(self, id):
#     def get_many(self, id_list):
#     def list(self, offset=0, limit=-1, desc=True, _key=None, **kwargs):
#     def search(self, query, field, limit=100, desc=True, _key=None, **kwargs):
#     def get_key(self, keybase=None, **kwargs):
#     def get_channel_key(self, key):
#     def get_obj_key(self, id):


from datetime import datetime, timedelta
from disqusapi import Paginator
from flask import session
from channels.app import app, disqusapi, schedule
from channels.oauth import api_call
from channels.utils import avatar_hash, datestr_to_datetime, from_cache, secure_avatar
from channels.views import threads, posts, users
            'avatar': avatar,
            'name': post['author']['username'],
            'createdAtISO': post['createdAt'].isoformat(),
            'message': post['message'],
            'hash': avatar_hash(post['author'])
        }

    @classmethod
    def save(cls, post, incr_posts=True):
        dt = datestr_to_datetime(post['createdAt'])
        post['createdAt'] = dt
        result = cls.format(post)
        score = dt.strftime('%s.%m')

        posts.add(result, score, thread_id=post['thread'])

        if incr_posts:
            threads.incr_counter(post['thread'], 'posts', 1)
            threads.incr_in_set(post['thread'], 1, _key='posts')
            threads.add_to_set(post['thread'], score)

        user = User.save(post['author'])
        users.add_to_set(user['id'], score, thread_id=post['thread'])
        threads.add_to_set(post['thread'], score)
        threads.add_to_set(post['thread'], score, author_id=post['author'])

        return result

    @classmethod
    def list_by_thread(cls, thread_id, offset=0, limit=100):

# Path: channels/app.py
# def init_database(app):
# def init_disqus(app):
# def init_publisher(app):
# def get_client(key):
# 
# Path: channels/oauth.py
# def api_call(func, **kwargs):
#     access_token = get_access_token()
#     try:
#         if access_token:
#             result = func(access_token=access_token, **kwargs)
#         else:
#             result = func(**kwargs)
#     except InvalidAccessToken:
#         raise Logout
#     return result
# 
# Path: channels/utils.py
# def avatar_hash(user):
#     return md5('disqus:' + str(user['username'])).hexdigest()
# 
# def datestr_to_datetime(dt):
#     return datetime.strptime(dt, '%Y-%m-%dT%H:%M:%S')
# 
# def from_cache(callback, cache_key=None, expires=60):
#     if cache_key is None:
#         if hasattr(callback, 'im_self'):
#             cache_key = '.'.join([callback.__module__, callback.im_self.__name__, callback.__name__])
#         else:
#             cache_key = '%s.%s' % (callback.__module__, callback.__name__)
#     conn = db.get_conn(cache_key)
#     result = conn.get(cache_key)
#     if result:
#         try:
#             result = json.loads(result)
#         except Exception, e:
#             logger.exception(e)
#             result = None
# 
#     if result is None:
#         result = callback()
#         pipe = conn.pipeline()
#         pipe.set(cache_key, json.dumps(result))
#         pipe.expire(cache_key, 60)
#         pipe.execute()
#     return result
# 
# def secure_avatar(avatar_url):
#     return avatar_url.replace('http://mediacdn', 'https://securecdn')
# 
# Path: channels/views.py
# class Publisher(object):
# class View(object):
#     def __init__(self, client, buffer_size=10000):
#     def publish(self, key, value):
#     def __init__(self, redis, publisher, name, version=1):
#     def add(self, data, score, _key=None, **kwargs):
#     def add_to_set(self, id, score, _data=None, _key=None, **kwargs):
#     def incr_in_set(self, id, score, _data=None, _key=None, **kwargs):
#     def remove(self, data, _key=None, **kwargs):
#     def remove_from_set(self, id, _key=None, **kwargs):
#     def incr_counter(self, id, key, amount=1):
#     def get(self, id):
#     def get_many(self, id_list):
#     def list(self, offset=0, limit=-1, desc=True, _key=None, **kwargs):
#     def search(self, query, field, limit=100, desc=True, _key=None, **kwargs):
#     def get_key(self, keybase=None, **kwargs):
#     def get_channel_key(self, key):
#     def get_obj_key(self, id):


# Path: channels/models.py
from datetime import datetime, timedelta
from disqusapi import Paginator
from flask import session
from channels.app import app, disqusapi, schedule
from channels.oauth import api_call
from channels.utils import avatar_hash, datestr_to_datetime, from_cache, secure_avatar
from channels.views import threads, posts, users

            'avatar': avatar,
            'name': post['author']['username'],
            'createdAtISO': post['createdAt'].isoformat(),
            'message': post['message'],
            'hash': avatar_hash(post['author'])
        }

    @classmethod
    def save(cls, post, incr_posts=True):
        dt = datestr_to_datetime(post['createdAt'])
        post['createdAt'] = dt
        result = cls.format(post)
        score = dt.strftime('%s.%m')

        posts.add(result, score, thread_id=post['thread'])

        if incr_posts:
            threads.incr_counter(post['thread'], 'posts', 1)
            threads.incr_in_set(post['thread'], 1, _key='posts')
            threads.add_to_set(post['thread'], score)

        user = User.save(post['author'])
        users.add_to_set(user['id'], score, thread_id=post['thread'])
        threads.add_to_set(post['thread'], score)
        threads.add_to_set(post['thread'], score, author_id=post['author'])

        return result

    @classmethod
    def list_by_thread(cls, thread_id, offset=0, limit=100):

        result = posts.list(thread_id=thread_id, offset=offset, limit=limit)