def main():
    client = DiscourseClient(discourse_powered_site,
                             api_username=API_USERNAME,
                             api_key=API_KEY)

    user = client.user(API_USERNAME)
    notification_count = int(user.get('notification_count'))
    print notification_count

    if path.isfile(file_path):
        # open the existing file and update the value if it has changed
        with open(file_path, 'r+') as notification_file:
            previous_count = int(notification_file.read().strip())
            print "Previous count: %d" % previous_count

            if notification_count > previous_count:
                notification_file.seek(0)
                notification_file.write(str(notification_count))
                notification_file.truncate()

                new_notification = notification_count - previous_count

                # send system notification
                system("notify-send -t 0 'FSFTN Discussion' \
                       'You have %d new notification\n<a href='http://discuss.fsftn.org'>View discussions</a>" % new_notification)

    else:
        # create the file for the first time
        with open(file_path, 'w') as notification_file:
            notification_file.write(str(notification_count))
Example #2
0
def get_discourse_data(email):
    client = DiscourseClient('http://meta.mangaki.fr', api_username=DISCOURSE_API_USERNAME, api_key=DISCOURSE_API_KEY)
    try:
        users = client._get('/admin/users/list/active.json?show_emails=true')
        for user in users:
            if user['email'] == email:
                return {'avatar': 'http://meta.mangaki.fr' + user['avatar_template'], 'created_at': user['created_at']}
        return {'avatar': '/static/img/unknown.png', 'created_at': datetime.datetime.now().isoformat() + 'Z'}
    except:
        return {'avatar': '/static/img/unknown.png', 'created_at': datetime.datetime.now().isoformat() + 'Z'}
 def __init__(self):
     plugin_config = helpers.get_plugin_config('colab_discourse')
     self.client = DiscourseClient(
         plugin_config['upstream'],
         api_key=plugin_config['api_key'],
         api_username=plugin_config['api_username']
     )
Example #4
0
def main():
    op = optparse.OptionParser()
    op.add_option('--host', default='http://localhost:4000')
    op.add_option('--api-user', default='system')
    op.add_option('-v', '--verbose', action='store_true')

    options, args = op.parse_args()
    if not options.host.startswith('http'):
        op.error('host must include protocol, eg http://')

    api_key = os.environ.get('DISCOURSE_API_KEY')
    if not api_key:
        op.error('please set DISCOURSE_API_KEY')

    client = DiscourseClient(options.host, options.api_user, api_key)

    if options.verbose:
        logging.basicConfig()
        logging.getLogger().setLevel(logging.DEBUG)

    c = DiscourseCmd(client)
    if args:
        line = ' '.join(args)
        result = c.onecmd(line)
        c.postcmd(result, line)
    else:
        c.cmdloop()
Example #5
0
def main():
    op = optparse.OptionParser()
    op.add_option("--host", default="http://localhost:4000")
    op.add_option("--api-user", default="system")
    op.add_option("-v", "--verbose", action="store_true")

    options, args = op.parse_args()
    if not options.host.startswith("http"):
        op.error("host must include protocol, eg http://")

    api_key = os.environ.get("DISCOURSE_API_KEY")
    if not api_key:
        op.error("please set DISCOURSE_API_KEY")

    client = DiscourseClient(options.host, options.api_user, api_key)

    if options.verbose:
        logging.basicConfig()
        logging.getLogger().setLevel(logging.DEBUG)

    c = DiscourseCmd(client)
    if args:
        line = " ".join(args)
        result = c.onecmd(line)
        c.postcmd(result, line)
    else:
        c.cmdloop()
Example #6
0
    def __init__(self, settings):
        self.settings = settings
        self.timeout = int(settings['url.timeout'])
        self.discourse_base_url = settings['discourse.url']
        self.discourse_public_url = settings['discourse.public_url']
        self.api_key = settings['discourse.api_key']
        self.sso_key = str(settings.get('discourse.sso_secret'))  # no unicode

        self.discourse_userid_cache = {}
        # FIXME: are we guaranteed usernames can never change? -> no!
        self.discourse_username_cache = {}

        self.client = DiscourseClient(
            self.discourse_base_url,
            api_username='******',  # the built-in Discourse user
            api_key=self.api_key,
            timeout=self.timeout)
Example #7
0
def get_discourse_data(email):
    client = DiscourseClient('http://meta.mangaki.fr',
                             api_username=DISCOURSE_API_USERNAME,
                             api_key=DISCOURSE_API_KEY)
    try:
        users = client._get('/admin/users/list/active.json?show_emails=true')
        for user in users:
            if user['email'] == email:
                return {
                    'avatar':
                    'http://meta.mangaki.fr' + user['avatar_template'],
                    'created_at': user['created_at']
                }
        return {
            'avatar': '/static/img/unknown.png',
            'created_at': datetime.datetime.now().isoformat() + 'Z'
        }
    except:
        return {
            'avatar': '/static/img/unknown.png',
            'created_at': datetime.datetime.now().isoformat() + 'Z'
        }
Example #8
0
 def post(self, user, title, content):
     client = DiscourseClient(
         'https://community.bigquant.com/',
         api_username=user,
         api_key=
         'ceaa79d2386bfbe83cdd1b71f6e7be3861c26dfb9d1c1982614aed7176db03a8')
     for i in range(0, 3):
         try:
             client.create_post(content=content,
                                category=u"AI量化百科",
                                skip_validations=True,
                                auto_track=False,
                                title=title)
             path = self._posted_path(title)
             print(title, path)
             with codecs.open(path, 'w', 'utf-8') as writer:
                 writer.write(title + '\n')
                 writer.write('\n\n')
                 writer.write(content)
             return
         except Exception as e:
             print(e)
             print(exception_trace(single_line=False))
             time.sleep(1 << i)
Example #9
0
    def __init__(self, settings):
        self.settings = settings
        self.timeout = int(settings['url.timeout'])
        self.discourse_base_url = settings['discourse.url']
        self.discourse_public_url = settings['discourse.public_url']
        self.api_key = settings['discourse.api_key']
        self.sso_key = str(settings.get('discourse.sso_secret'))  # no unicode

        self.discourse_userid_cache = {}
        # FIXME: are we guaranteed usernames can never change? -> no!
        self.discourse_username_cache = {}

        self.client = DiscourseClient(
                self.discourse_base_url,
                api_username='******',  # the built-in Discourse user
                api_key=self.api_key,
                timeout=self.timeout)
Example #10
0
import Legobot
import subprocess
import time
from creds import Creds
from bs4 import BeautifulSoup
from pydiscourse.client import DiscourseClient

creds = Creds()
HOST = creds.HOST
PORT = creds.PORT
NICK = creds.NICK
PASS = creds.PASS
CHANS = creds.CHANS

myBot = Legobot.legoBot(host=HOST,port=PORT,nick=NICK,nickpass=PASS,chans=CHANS)
client = DiscourseClient('https://0x00sec.org', api_username='******', api_key=creds.API_KEY)

def NickfromMsg(msg):
    return msg.splitMessage[0].split("!")[0][1:]

def UrlFromID(id):
  data = client.topic_posts(id)["post_stream"]["posts"][0]
  return "https://0x00sec.org/t/%s/%s" % (data["topic_slug"], data["topic_id"])


def Reconnect():


def join(msg):
    myBot.sendMsg("JOIN " + msg.arg1 + "\r\n")
Example #11
0
class APIDiscourseClient(object):
    def __init__(self, settings):
        self.settings = settings
        self.timeout = int(settings['url.timeout'])
        self.discourse_base_url = settings['discourse.url']
        self.discourse_public_url = settings['discourse.public_url']
        self.api_key = settings['discourse.api_key']
        self.sso_key = str(settings.get('discourse.sso_secret'))  # no unicode

        self.discourse_userid_cache = {}
        # FIXME: are we guaranteed usernames can never change? -> no!
        self.discourse_username_cache = {}

        self.client = DiscourseClient(
            self.discourse_base_url,
            api_username='******',  # the built-in Discourse user
            api_key=self.api_key,
            timeout=self.timeout)

    def get_userid(self, userid):
        discourse_userid = self.discourse_userid_cache.get(userid)
        if not discourse_userid:
            discourse_user = self.client.by_external_id(userid)
            discourse_userid = discourse_user['id']
            self.discourse_userid_cache[userid] = discourse_userid
            self.discourse_username_cache[userid] = discourse_user['username']
        return discourse_userid

    def get_username(self, userid):
        discourse_username = self.discourse_username_cache.get(userid)
        if not discourse_username:
            discourse_user = self.client.by_external_id(userid)
            self.discourse_userid_cache[userid] = discourse_user['id']
            discourse_username = discourse_user['username']
            self.discourse_username_cache[userid] = discourse_username
        return discourse_username

    def sync_sso(self, user):
        result = self.client.sync_sso(sso_secret=self.sso_key,
                                      name=user.name,
                                      username=user.forum_username,
                                      email=user.email,
                                      external_id=user.id)
        if result:
            self.discourse_userid_cache[user.id] = result['id']
        return result

    def logout(self, userid):
        discourse_userid = self.get_userid(userid)
        self.client.log_out(discourse_userid)
        return discourse_userid

    # Below this: SSO provider
    def decode_payload(self, payload):
        decoded = b64decode(payload.encode('utf-8')).decode('utf-8')
        assert 'nonce' in decoded
        assert len(payload) > 0
        return decoded

    def check_signature(self, payload, signature):
        key = self.sso_key.encode('utf-8')
        h = hmac.new(key, payload.encode('utf-8'), digestmod=hashlib.sha256)
        this_signature = h.hexdigest()

        if this_signature != signature:
            log.error('Signature mismatch')
            raise HTTPBadRequest('discourse login failed')

    def request_nonce(self):
        url = '%s/session/sso' % self.discourse_base_url
        try:
            r = requests.get(url, allow_redirects=False, timeout=self.timeout)
            assert r.status_code == 302
        except Exception:
            log.error('Could not request nonce', exc_info=True)
            raise Exception('Could not request nonce')

        location = r.headers['Location']
        parsed = urllib.parse.urlparse(location)
        params = urllib.parse.parse_qs(parsed.query)
        sso = params['sso'][0]
        sig = params['sig'][0]

        self.check_signature(sso, sig)
        payload = self.decode_payload(sso)
        return parse_qs(payload)['nonce'][0]

    def create_response_payload(self, user, nonce, url_part):
        assert nonce is not None, 'No nonce passed'

        params = {
            'nonce': nonce,
            'email': user.email,
            'external_id': user.id,
            'username': user.username,
            'name': user.username,
        }

        key = self.sso_key.encode('utf-8')
        r_payload = b64encode(urllib.parse.urlencode(params).encode('utf-8'))
        h = hmac.new(key, r_payload, digestmod=hashlib.sha256)
        qs = urllib.parse.urlencode({'sso': r_payload, 'sig': h.hexdigest()})
        return '%s%s?%s' % (self.discourse_base_url, url_part, qs)

    def get_nonce_from_sso(self, sso, sig):
        payload = urllib.parse.unquote(sso)
        try:
            decoded = self.decode_payload(payload)
        except Exception as e:
            log.error('Failed to decode payload', e)
            raise HTTPBadRequest('discourse login failed')

        self.check_signature(payload, sig)

        # Build the return payload
        qs = parse_qs(decoded)
        return qs['nonce'][0]

    def redirect(self, user, sso, signature):
        nonce = self.get_nonce_from_sso(sso, signature)
        return self.create_response_payload(user, nonce, '/session/sso_login')

    def redirect_without_nonce(self, user):
        nonce = self.request_nonce()
        return self.create_response_payload(user, nonce, '/session/sso_login')
Example #12
0
class APIDiscourseClient(object):

    def __init__(self, settings):
        self.settings = settings
        self.timeout = int(settings['url.timeout'])
        self.discourse_base_url = settings['discourse.url']
        self.discourse_public_url = settings['discourse.public_url']
        self.api_key = settings['discourse.api_key']
        self.sso_key = str(settings.get('discourse.sso_secret'))  # no unicode

        self.discourse_userid_cache = {}
        # FIXME: are we guaranteed usernames can never change? -> no!
        self.discourse_username_cache = {}

        self.client = DiscourseClient(
                self.discourse_base_url,
                api_username='******',  # the built-in Discourse user
                api_key=self.api_key,
                timeout=self.timeout)

    def get_userid(self, userid):
        discourse_userid = self.discourse_userid_cache.get(userid)
        if not discourse_userid:
            discourse_user = self.client.by_external_id(userid)
            discourse_userid = discourse_user['id']
            self.discourse_userid_cache[userid] = discourse_userid
            self.discourse_username_cache[userid] = discourse_user['username']
        return discourse_userid

    def get_username(self, userid):
        discourse_username = self.discourse_username_cache.get(userid)
        if not discourse_username:
            discourse_user = self.client.by_external_id(userid)
            self.discourse_userid_cache[userid] = discourse_user['id']
            discourse_username = discourse_user['username']
            self.discourse_username_cache[userid] = discourse_username
        return discourse_username

    def sync_sso(self, user):
        result = self.client.sync_sso(
            sso_secret=self.sso_key,
            name=user.name,
            username=user.forum_username,
            email=user.email,
            external_id=user.id)
        if result:
            self.discourse_userid_cache[user.id] = result['id']
        return result

    def logout(self, userid):
        discourse_userid = self.get_userid(userid)
        self.client.log_out(discourse_userid)
        return discourse_userid

    # Below this: SSO provider
    def decode_payload(self, payload):
        decoded = b64decode(payload.encode('utf-8')).decode('utf-8')
        assert 'nonce' in decoded
        assert len(payload) > 0
        return decoded

    def check_signature(self, payload, signature):
        key = self.sso_key.encode('utf-8')
        h = hmac.new(key, payload.encode('utf-8'), digestmod=hashlib.sha256)
        this_signature = h.hexdigest()

        if this_signature != signature:
            log.error('Signature mismatch')
            raise HTTPBadRequest('discourse login failed')

    def request_nonce(self):
        url = '%s/session/sso' % self.discourse_base_url
        try:
            r = requests.get(url, allow_redirects=False, timeout=self.timeout)
            assert r.status_code == 302
        except Exception:
            log.error('Could not request nonce', exc_info=True)
            raise Exception('Could not request nonce')

        location = r.headers['Location']
        parsed = urllib.parse.urlparse(location)
        params = urllib.parse.parse_qs(parsed.query)
        sso = params['sso'][0]
        sig = params['sig'][0]

        self.check_signature(sso, sig)
        payload = self.decode_payload(sso)
        return parse_qs(payload)['nonce'][0]

    def create_response_payload(self, user, nonce, url_part):
        assert nonce is not None, 'No nonce passed'

        params = {
            'nonce': nonce,
            'email': user.email,
            'external_id': user.id,
            'username': user.forum_username,
            'name': user.name,
        }

        key = self.sso_key.encode('utf-8')
        r_payload = b64encode(urllib.parse.urlencode(params).encode('utf-8'))
        h = hmac.new(key, r_payload, digestmod=hashlib.sha256)
        qs = urllib.parse.urlencode({'sso': r_payload, 'sig': h.hexdigest()})
        return '%s%s?%s' % (self.discourse_public_url, url_part, qs)

    def get_nonce_from_sso(self, sso, sig):
        payload = urllib.parse.unquote(sso)
        try:
            decoded = self.decode_payload(payload)
        except Exception as e:
            log.error('Failed to decode payload', e)
            raise HTTPBadRequest('discourse login failed')

        self.check_signature(payload, sig)

        # Build the return payload
        qs = parse_qs(decoded)
        return qs['nonce'][0]

    def redirect(self, user, sso, signature):
        nonce = self.get_nonce_from_sso(sso, signature)
        return self.create_response_payload(user, nonce, '/session/sso_login')

    def redirect_without_nonce(self, user):
        nonce = self.request_nonce()
        return self.create_response_payload(user, nonce, '/session/sso_login')
class ColabDiscoursePluginDataImporter(PluginDataImporter):
    app_label = 'colab_discourse'

    def __init__(self):
        plugin_config = helpers.get_plugin_config('colab_discourse')
        self.client = DiscourseClient(
            plugin_config['upstream'],
            api_key=plugin_config['api_key'],
            api_username=plugin_config['api_username']
        )

    def fill_object_data(self, model_class, data):
        try:
            obj = model_class.objects.get(id=data['id'])
        except model_class.DoesNotExist:
            obj = model_class()

        for field in obj._meta.fields:
            try:
                if field.name == 'badge_type':
                    obj.badge_type_id = data['badge_type_id']
                    continue

                if field.name == 'category':
                    obj.category_id = data['category_id']
                    continue

                if field.name == 'author':
                    user = User.objects.get(username=data['username'])
                    obj.author = user
                    continue

                if field.name == 'topic':
                    obj.topic_id = data['topic_id']
                    continue

                if isinstance(field, DateTimeField):
                    value = parse_datetime(data[field.name])
                else:
                    value = data[field.name]

                setattr(obj, field.name, value)
            except KeyError:
                continue

        return obj

    def fetch_data(self):
        models.DiscourseCategory.objects.all().delete()
        models.DiscourseTopic.objects.all().delete()
        models.DiscoursePost.objects.all().delete()
        models.DiscourseBadgeType.objects.all().delete()
        models.DiscourseBadge.objects.all().delete()

        self.fetch_categories()
        self.fetch_badges()
        self.fetch_topics()
        self.fetch_posts()

    def fetch_topics(self):
        topics_data = self.get_all_topics()
        for topic_data in topics_data:
            topic = self.fill_object_data(models.DiscourseTopic, topic_data)
            topic = self.complete_topic_informations(topic)

    def complete_topic_informations(self, topic):
        topic_data = self.client.topic(topic.slug, topic.id)
        created_by = topic_data['details']['created_by']['username']
        topic.created_by = User.objects.get(username=created_by)
        topic.participant_count = topic_data['participant_count']
        topic.save()

        for user_data in topic_data['details']['participants']:
            participant = User.objects.get(username=user_data['username'])
            topic.participants.add(participant)

        return topic

    def fetch_posts(self):
        topics = models.DiscourseTopic.objects.all()
        for topic in topics:
            self.fetch_posts_by_topic(topic)

    def fetch_posts_by_topic(self, topic):
        topic_info = self.client.posts(topic.id)
        posts_data = topic_info['post_stream']['posts']
        for post_data in posts_data:
            post = self.fill_object_data(models.DiscoursePost, post_data)
            post.save()

    def get_all_topics(self, page=0):
        topics = self.client.latest_topics(page=page)
        topics = topics['topic_list']['topics']
        all_topics = []
        all_topics.extend(topics)

        if topics:
            page += 1
            all_topics.extend(self.get_all_topics(page=page))

        return all_topics

    def fetch_categories(self):
        categories = self.client.categories()
        for category_data in categories:
            if category_data['slug'] != 'uncategorized':
                category = self.fill_object_data(models.DiscourseCategory,
                                                 category_data)
                category.save()

    def fetch_badges(self):
        badges_data = self.client.badges()
        self.fetch_badge_types(badges_data['badge_types'])
        for data in badges_data['badges']:
            badge = self.fill_object_data(models.DiscourseBadge, data)
            badge.save()

    def fetch_badge_types(self, data):
        for badge_type_data in data:
            badge_type = self.fill_object_data(models.DiscourseBadgeType,
                                               badge_type_data)
            badge_type.save()