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))
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'] )
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()
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()
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_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 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)
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")
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')
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()