<commit_before># -*- coding: utf-8 -*-

import hmac
import hashlib
import time
import requests
from cryptotik.common import APIError, headers, ExchangeWrapper
from re import findall
from decimal import Decimal

class TheRock(ExchangeWrapper):

    url = 'https://api.therocktrading.com/v1/'
    delimiter = ""
    headers = headers

    def __init__(self, apikey=None, secret=None, timeout=None):
        '''initialize bittrex class'''

        if apikey and secret:
            self.apikey = apikey.encode("utf-8")
            self.secret = secret.encode("utf-8")

    try:
        assert timeout is not None
    except:
        timeout = (8, 15)

    @classmethod
    def format_pair(cls, pair):
        """format the pair argument to format understood by remote API."""

        return "".join(findall(r"[^\W\d_]+|\d+", pair)).upper()

    @classmethod
    def api(cls, url):
        '''call api'''

        try:
            result = requests.get(url, headers=cls.headers, timeout=3)
            assert result.status_code == 200
            return result.json()
        except requests.exceptions.RequestException as e:
            print("Error!", e)

    @classmethod
    def get_market_ticker(cls, pair):
        '''returns simple current market status report'''

        return cls.api(cls.url + "funds/" + cls.format_pair(pair) + "/ticker")

    @classmethod
    def get_market_trade_history(cls, pair, limit=10):
        '''get market trade history'''

        return cls.api(cls.url + "funds/" + cls.format_pair(pair) + "/trades" +
                                "?per_page={}".format(limit))['trades']

    @classmethod
    def get_market_orders(cls, pair):
        '''return order book for the market'''

        return cls.api(cls.url + "funds/" + cls.format_pair(pair) + "/orderbook")

    @classmethod
    def get_market_spread(cls, pair):
        '''return first buy order and first sell order'''

        order_book = cls.get_market_orders(pair)

        ask = order_book["asks"][0]['price']
        bid = order_book["bids"][0]['price']

        return Decimal(ask) - Decimal(bid)

    @classmethod
    def get_market_depth(cls, pair):
        '''return sum of all bids and asks'''

        ob = cls.get_market_orders(pair)
        return {"bids": Decimal(ob['bids'][-1]['depth']),
                "asks": Decimal(ob['asks'][-1]['depth'])}

    @classmethod
    def get_markets(cls, filter=None):
        '''Find supported markets on this exchange,
            use <filter> if needed'''

        r = cls.api(cls.url + "funds")['funds']
        pairs = [i["id"].lower() for i in r]
        if filter:
            pairs = [p for p in pairs if filter in p]
        return pairs

    @classmethod
    def get_market_volume(cls, pair):
        ''' return volume of last 24h'''

        return cls.get_market_ticker(cls.format_pair(pair))["volume"]

    def private_api(self, url, http_method='GET', params={}):
        '''handles private api methods'''

        if not self.apikey or not self.secret:
            raise ValueError("A Key and Secret needed!")

        nonce = str(self.get_nonce())
        if params:
            url += "?" + requests.compat.urlencode(sorted(params.items()))
        nonce_plus_url = str(nonce) + url
        signature = hmac.new(self.secret,
                            nonce_plus_url.encode("utf-8"),
                            hashlib.sha512).hexdigest()
        head = {"Content-Type": "application/json",
                "X-TRT-KEY": self.apikey,
                "X-TRT-SIGN": signature,
                "X-TRT-NONCE": nonce}

        result = requests.request(http_method, url, headers=head)
        #assert result.status_code == 200, {'error: ' + str(result.json())}
        return result.json()

    def get_nonce(self):
        '''return nonce integer'''

        nonce = getattr(self, '_nonce', 0)
        if nonce:
            nonce += 1
        # If the unix time is greater though, use that instead (helps low
        # concurrency multi-threaded apps always call with the largest nonce).
        self._nonce = max(int(time.time()), nonce)
        return self._nonce

    def get_balances(self):
        """get all balances from your account"""

        balances = self.private_api(self.url + "balances")
        return [i for i in balances['balances'] if i["trading_balance"] != 0.0]

    def get_deposit_address(self, currency):
        ''' get deposit address for <currency> '''

        return self.private_api(self.url + "currencies/" + currency.upper() +
                                "/addresses",
                                http_method='GET',
                                params={'unused': 'true'})

    def buy(self, pair, price, quantity):
        '''creates buy order for <pair> at <price> for <quantity>'''

        return self.private_api(self.url + "funds/"
                                + self.format_pair(pair) + "/orders",
                                params={'fund_id': self.format_pair(pair),
                                    'side': 'buy', 'amount': quantity,
                                    'price': price},
                                http_method='POST')

    def sell(self, pair, price, quantity):
        '''creates sell order for <pair> at <price> for <quantity>'''

        return self.private_api(self.url + "funds/"
                                + self.format_pair(pair) + "/orders",
                                params={'fund_id': self.format_pair(pair),
                                    'side': 'sell', 'amount': quantity,
                                    'price': price},
                                http_method='POST')

    def withdraw(self, coin, amount, address):
        '''withdraw <coin> <amount> to <address> with <address_tag> if needed'''

        return self.private_api(self.url + "atms/withdraw",
                                params={'currency': coin.upper(),
                                        'destination_address': address,
                                        'amount': amount},
                                http_method='POST')

    def get_withdraw_history(self, currency=None):
        '''Retrieves withdrawal history.'''

        if currency:
            transactions = self.private_api(self.url + "transactions",
                                        params={'currency': currency.upper()})["transactions"]
        else:
            transactions = self.private_api(self.url + "transactions")["transactions"]

        return [i for i in transactions if i["type"] == "withdraw"]

    def get_deposit_history(self, currency=None):
        '''Retreive deposit history.'''

        if currency:
            transactions = self.private_api(self.url + "transactions",
                                        params={'currency': currency})["transactions"]
        else:
            transactions = self.private_api(self.url + "transactions")["transactions"]

        return [i for i in transactions if i["type"] == "atm_payment"]

    def get_open_orders(self, pair=None):
        '''get open orders for <pair>
           or all open orders if called without an argument.'''

        if not pair:
            all_pairs=[]
            for market in self.get_markets():
                all_pairs += self.private_api(self.url + "funds/" +
                                            self.format_pair(market) + "/orders")
                return all_pairs
        else:
            return self.private_api(self.url + "funds/" + self.format_pair(pair)
                                    + "/orders")["orders"]

    def get_order(self, symbol, order_id):
        """retrieve a single order by orderId."""

        return self.private_api(self.url + "funds/" + symbol + "/orders/" + order_id,
                                http_method='GET')

    def cancel_order(self, order_id, symbol):
        """cancel order with <order_id> for <symbol>"""

        return self.private_api(self.url + "funds/" + symbol +
                                "/orders/" + order_id,
                                http_method='DELETE')

    def cancel_all_orders(self, symbol):
        """cancel all orders for <symbol> """

        return self.private_api(self.url + "funds/" + symbol +
                                "/orders/remove_all",
                                http_method='DELETE')<commit_msg>rework TheRock, add proxy support.<commit_after># -*- coding: utf-8 -*-

import hmac
import hashlib
import time
import requests
from cryptotik.common import APIError, headers, ExchangeWrapper
from re import findall
from decimal import Decimal

class TheRock(ExchangeWrapper):

    url = 'https://api.therocktrading.com/v1/'
    delimiter = ""
    headers = headers

    def __init__(self, apikey=None, secret=None, timeout=None, proxy=None):
        '''initialize bittrex class'''

        if apikey and secret:
            self.apikey = apikey.encode("utf-8")
            self.secret = secret.encode("utf-8")

        if proxy:
            assert proxy.startswith('https'), {'Error': 'Only https proxies supported.'}
        self.proxy = {'https': proxy}

        if not timeout:
            self.timeout = (8, 15)
        else:
            self.timeout = timeout

        self.api_session = requests.Session()

    @classmethod
    def format_pair(self, pair):
        """format the pair argument to format understood by remote API."""

        return "".join(findall(r"[^\W\d_]+|\d+", pair)).upper()

    def api(self, url):
        '''call api'''

        try:
            result = self.api_session.get(url, headers=self.headers,
                                          timeout=self.timeout, proxies=self.proxy)
            assert result.status_code == 200
            return result.json()

        except requests.exceptions.RequestException as e:
            raise APIError(e)

    def get_market_ticker(self, pair):
        '''returns simple current market status report'''

        return self.api(self.url + "funds/" + self.format_pair(pair) + "/ticker")

    def get_market_trade_history(self, pair, limit=10):
        '''get market trade history'''

        return self.api(self.url + "funds/" + self.format_pair(pair) + "/trades" +
                                "?per_page={}".format(limit))['trades']

    def get_market_orders(self, pair):
        '''return order book for the market'''

        return self.api(self.url + "funds/" + self.format_pair(pair) + "/orderbook")

    def get_market_spread(self, pair):
        '''return first buy order and first sell order'''

        order_book = self.get_market_orders(pair)

        ask = order_book["asks"][0]['price']
        bid = order_book["bids"][0]['price']

        return Decimal(ask) - Decimal(bid)

    def get_market_depth(self, pair):
        '''return sum of all bids and asks'''

        ob = self.get_market_orders(pair)
        return {"bids": Decimal(ob['bids'][-1]['depth']),
                "asks": Decimal(ob['asks'][-1]['depth'])}

    def get_markets(self):
        '''Find supported markets on this exchange'''

        r = self.api(self.url + "funds")['funds']
        pairs = [i["id"].lower() for i in r]

        return pairs

    def get_market_volume(self, pair):
        ''' return volume of last 24h'''

        return self.get_market_ticker(self.format_pair(pair))["volume"]

    def private_api(self, url, http_method='GET', params={}):
        '''handles private api methods'''

        if not self.apikey or not self.secret:
            raise ValueError("A Key and Secret needed!")

        nonce = str(self.get_nonce())
        if params:
            url += "?" + requests.compat.urlencode(sorted(params.items()))
        nonce_plus_url = str(nonce) + url
        signature = hmac.new(self.secret,
                             nonce_plus_url.encode("utf-8"),
                             hashlib.sha512).hexdigest()

        head = {"Content-Type": "application/json",
                "X-TRT-KEY": self.apikey,
                "X-TRT-SIGN": signature,
                "X-TRT-NONCE": nonce}

        try:
            result = self.api_session.request(http_method, url, headers=head,
                                              proxies=self.proxy)
            assert result.status_code == 200, {'error: ' + str(result.json())}
        except requests.exceptions.RequestException as e:
            raise APIError(e)

        return result.json()

    def get_nonce(self):
        '''return nonce integer'''

        nonce = getattr(self, '_nonce', 0)
        if nonce:
            nonce += 1
        # If the unix time is greater though, use that instead (helps low
        # concurrency multi-threaded apps always call with the largest nonce).
        self._nonce = max(int(time.time()), nonce)
        return self._nonce

    def get_balances(self):
        """get all balances from your account"""

        balances = self.private_api(self.url + "balances")
        return [i for i in balances['balances'] if i["trading_balance"] != 0.0]

    def get_deposit_address(self, currency):
        ''' get deposit address for <currency> '''

        return self.private_api(self.url + "currencies/" + currency.upper() +
                                "/addresses",
                                http_method='GET',
                                params={'unused': 'true'})

    def buy(self, pair, price, quantity):
        '''creates buy order for <pair> at <price> for <quantity>'''

        return self.private_api(self.url + "funds/"
                                + self.format_pair(pair) + "/orders",
                                params={'fund_id': self.format_pair(pair),
                                    'side': 'buy', 'amount': quantity,
                                    'price': price},
                                http_method='POST')

    def sell(self, pair, price, quantity):
        '''creates sell order for <pair> at <price> for <quantity>'''

        return self.private_api(self.url + "funds/"
                                + self.format_pair(pair) + "/orders",
                                params={'fund_id': self.format_pair(pair),
                                    'side': 'sell', 'amount': quantity,
                                    'price': price},
                                http_method='POST')

    def withdraw(self, coin, amount, address):
        '''withdraw <coin> <amount> to <address> with <address_tag> if needed'''

        return self.private_api(self.url + "atms/withdraw",
                                params={'currency': coin.upper(),
                                        'destination_address': address,
                                        'amount': amount},
                                http_method='POST')

    def get_withdraw_history(self, currency=None):
        '''Retrieves withdrawal history.'''

        if currency:
            transactions = self.private_api(self.url + "transactions",
                                        params={'currency': currency.upper()})["transactions"]
        else:
            transactions = self.private_api(self.url + "transactions")["transactions"]

        return [i for i in transactions if i["type"] == "withdraw"]

    def get_deposit_history(self, currency=None):
        '''Retreive deposit history.'''

        if currency:
            transactions = self.private_api(self.url + "transactions",
                                        params={'currency': currency})["transactions"]
        else:
            transactions = self.private_api(self.url + "transactions")["transactions"]

        return [i for i in transactions if i["type"] == "atm_payment"]

    def get_open_orders(self, pair=None):
        '''get open orders for <pair>
           or all open orders if called without an argument.'''

        if not pair:
            all_pairs=[]
            for market in self.get_markets():
                all_pairs += self.private_api(self.url + "funds/" +
                                            self.format_pair(market) + "/orders")
                return all_pairs
        else:
            return self.private_api(self.url + "funds/" + self.format_pair(pair)
                                    + "/orders")["orders"]

    def get_order(self, symbol, order_id):
        """retrieve a single order by orderId."""

        return self.private_api(self.url + "funds/" + symbol + "/orders/" + order_id,
                                http_method='GET')

    def cancel_order(self, order_id, symbol):
        """cancel order with <order_id> for <symbol>"""

        return self.private_api(self.url + "funds/" + symbol +
                                "/orders/" + order_id,
                                http_method='DELETE')

    def cancel_all_orders(self, symbol):
        """cancel all orders for <symbol> """

        return self.private_api(self.url + "funds/" + symbol +
                                "/orders/remove_all",
                                http_method='DELETE')<|endoftext|>


<commit_before>#!/usr/bin/python
# -*- coding: utf-8 -*-

from holmes.facters import Facter

class MetaTagsFacter(Facter):

    def get_facts(self):

        values = self.process_meta_tags()

        self.add_fact(
            key='meta.tags',
            value=values,
            title='Meta Tags',
            unit='values'
        )

        self.review.data['meta.tags'] = values

    def process_meta_tags(self):
        """
        Case 1: {'charset': 'utf-8'}

        KEY => 'charset'
        CONTENT => 'utf-8'
        PROPERTY =>

        Case 2: {"content":"website","property":"og:type"}

        KEY => 'og:type'
        CONTENT => 'website'
        PROPERTY => 'property'

        Case 3: {'content': 'text\\/html;charset=UTF-8',
                 'http-equiv': 'Content-Type'}

        KEY => 'Content-Type'
        CONTENT => 'text\\/html;charset=UTF-8'
        PROPERTY => 'http-equiv'
        """

        data = []
        for tag in self.get_meta_tags():
            if len(tag) == 1:
                key = tag.iterkeys().next()
                content = tag.itervalues().next()
                prop = None
            elif len(tag) > 1:
                if 'content' in tag:
                    content = tag.get('content')
                    tag.pop('content')
                else:
                    content = None
                key = tag.itervalues().next()
                prop = tag.iterkeys().next()
            data.append({'key': key, 'content': content, 'property': prop})
        return data

    def get_meta_tags(self):
        meta_tags = self.reviewer.current_html.cssselect('meta')
        values = []
        for tags in meta_tags:
            values.append(dict(tags.items()))
        return values
<commit_msg>Meta tags facter<commit_after>#!/usr/bin/python
# -*- coding: utf-8 -*-

from holmes.facters import Facter

class MetaTagsFacter(Facter):

    @classmethod
    def get_fact_definitions(cls):
        return {
            'meta.tags': {
                'title': 'Meta Tags',
                'description': lambda value: value,
                'unit': 'values'
            }
        }

    def get_facts(self):

        values = self.process_meta_tags()

        self.add_fact(
            key='meta.tags',
            value=values,
        )

        self.review.data['meta.tags'] = values

    def process_meta_tags(self):
        """
        Case 1: {'charset': 'utf-8'}

        KEY => 'charset'
        CONTENT => 'utf-8'
        PROPERTY =>

        Case 2: {"content":"website","property":"og:type"}

        KEY => 'og:type'
        CONTENT => 'website'
        PROPERTY => 'property'

        Case 3: {'content': 'text\\/html;charset=UTF-8',
                 'http-equiv': 'Content-Type'}

        KEY => 'Content-Type'
        CONTENT => 'text\\/html;charset=UTF-8'
        PROPERTY => 'http-equiv'
        """

        data = []
        for tag in self.get_meta_tags():
            if len(tag) == 1:
                key = tag.iterkeys().next()
                content = tag.itervalues().next()
                prop = None
            elif len(tag) > 1:
                if 'content' in tag:
                    content = tag.get('content')
                    tag.pop('content')
                else:
                    content = None
                key = tag.itervalues().next()
                prop = tag.iterkeys().next()
            data.append({'key': key, 'content': content, 'property': prop})
        return data

    def get_meta_tags(self):
        meta_tags = self.reviewer.current_html.cssselect('meta')
        values = []
        for tags in meta_tags:
            values.append(dict(tags.items()))
        return values
<|endoftext|>


<commit_before>from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import render

from .models import Fellow, Event, Expense, Blog
from .forms import FellowForm, EventForm, ExpenseForm, BlogForm

def index(request):
    context = {
            'fellows': Fellow.objects.all(),
            'events': Event.objects.all(),
            }
    return render(request, 'fellowms/index.html', context)

def dashboard(request):
    return render(request, 'fellowms/dashboard.html')

@login_required
def fellow(request):
    if request.POST:
        # Handle submission
        formset = FellowForm(request.POST, request.FILES)

        if formset.is_valid():
            fellow = formset.save()
            return HttpResponseRedirect(reverse('fellow_detail',
                args=[fellow.id,]))
    else:
        formset = FellowForm

    # Show submission form.
    context = {
            "title": "Create fellow",
            "formset": formset,
            "submit_text": "Save",
            }
    return render(request, 'fellowms/form.html', context)

def fellow_detail(request, fellow_id):
    context = {
            'fellow': Fellow.objects.get(id=fellow_id),
            }

    return render(request, 'fellowms/fellow_detail.html', context)

def event(request):
    if request.POST:
        # Handle submission
        post = request.POST.copy()
        print(post)
        fellow = Fellow.objects.get(email=post['fellow'])
        print(fellow)
        post['fellow'] = fellow.id
        formset = EventForm(post)

        if formset.is_valid():
            event = formset.save()
            return HttpResponseRedirect(reverse('event_detail',
                args=[event.id,]))
    else:
        formset = EventForm

    # Show submission form.
    context = {
            "title": "Submit event",
            "formset": formset,
            "submit_text": "Submit",
            }
    return render(request, 'fellowms/form.html', context)

def event_detail(request, event_id):
    context = {
            'event': Event.objects.get(id=event_id),
            }

    return render(request, 'fellowms/event_detail.html', context)

def expense(request):
    if request.POST:
        # Handle submission
        formset = ExpenseForm(request.POST, request.FILES)

        if formset.is_valid():
            expense = formset.save()
            return HttpResponseRedirect(reverse('expense_detail',
                args=[expense.id,]))
    else:
        formset = ExpenseForm

    # Show submission form.
    context = {
            "title": "Submit expenses",
            "formset": formset,
            "submit_text": "Submit",
            }
    return render(request, 'fellowms/form.html', context)

def expense_detail(request, expense_id):
    context = {
            'expense': Expense.objects.get(id=expense_id),
            }

    return render(request, 'fellowms/expense_detail.html', context)

def blog(request):
    if request.POST:
        # Handle submission
        formset = Blog(request.POST)

        if formset.is_valid():
            blog = formset.save()
            return HttpResponseRedirect(reverse('blog_detail',
                args=[blog.id,]))
    else:
        formset = BlogForm

    # Show submission form.
    context = {
            "title": "Submit blog",
            "formset": formset,
            "submit_text": "Submit",
            }
    return render(request, 'fellowms/form.html', context)

def blog_detail(request, blog_id):
    context = {
            'blog': Blog.objects.get(id=blog_id),
            }

    return render(request, 'fellowms/blog_detail.html', context)
<commit_msg>Fix blog view<commit_after>from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import render

from .models import Fellow, Event, Expense, Blog
from .forms import FellowForm, EventForm, ExpenseForm, BlogForm

def index(request):
    context = {
            'fellows': Fellow.objects.all(),
            'events': Event.objects.all(),
            }
    return render(request, 'fellowms/index.html', context)

def dashboard(request):
    return render(request, 'fellowms/dashboard.html')

@login_required
def fellow(request):
    if request.POST:
        # Handle submission
        formset = FellowForm(request.POST, request.FILES)

        if formset.is_valid():
            fellow = formset.save()
            return HttpResponseRedirect(reverse('fellow_detail',
                args=[fellow.id,]))
    else:
        formset = FellowForm

    # Show submission form.
    context = {
            "title": "Create fellow",
            "formset": formset,
            "submit_text": "Save",
            }
    return render(request, 'fellowms/form.html', context)

def fellow_detail(request, fellow_id):
    context = {
            'fellow': Fellow.objects.get(id=fellow_id),
            }

    return render(request, 'fellowms/fellow_detail.html', context)

def event(request):
    if request.POST:
        # Handle submission
        post = request.POST.copy()
        print(post)
        fellow = Fellow.objects.get(email=post['fellow'])
        print(fellow)
        post['fellow'] = fellow.id
        formset = EventForm(post)

        if formset.is_valid():
            event = formset.save()
            return HttpResponseRedirect(reverse('event_detail',
                args=[event.id,]))
    else:
        formset = EventForm

    # Show submission form.
    context = {
            "title": "Submit event",
            "formset": formset,
            "submit_text": "Submit",
            }
    return render(request, 'fellowms/form.html', context)

def event_detail(request, event_id):
    context = {
            'event': Event.objects.get(id=event_id),
            }

    return render(request, 'fellowms/event_detail.html', context)

def expense(request):
    if request.POST:
        # Handle submission
        formset = ExpenseForm(request.POST, request.FILES)

        if formset.is_valid():
            expense = formset.save()
            return HttpResponseRedirect(reverse('expense_detail',
                args=[expense.id,]))
    else:
        formset = ExpenseForm

    # Show submission form.
    context = {
            "title": "Submit expenses",
            "formset": formset,
            "submit_text": "Submit",
            }
    return render(request, 'fellowms/form.html', context)

def expense_detail(request, expense_id):
    context = {
            'expense': Expense.objects.get(id=expense_id),
            }

    return render(request, 'fellowms/expense_detail.html', context)

def blog(request):
    if request.POST:
        # Handle submission
        formset = BlogForm(request.POST)

        if formset.is_valid():
            blog = formset.save()
            return HttpResponseRedirect(reverse('blog_detail',
                args=[blog.id,]))
    else:
        formset = BlogForm

    # Show submission form.
    context = {
            "title": "Submit blog",
            "formset": formset,
            "submit_text": "Submit",
            }
    return render(request, 'fellowms/form.html', context)

def blog_detail(request, blog_id):
    context = {
            'blog': Blog.objects.get(id=blog_id),
            }

    return render(request, 'fellowms/blog_detail.html', context)
<|endoftext|>


<commit_before>import asyncio
import datetime
import xml.etree.ElementTree as et

import discord
from bs4 import BeautifulSoup
from discord.ext import commands
from discord.ext.commands.cooldowns import BucketType

from .exceptions import APIError

class NotiifiersMixin:
    @commands.group()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def dailynotifier(self, ctx):
        """Sends a list of dailies on server reset to specificed channel.
        First, specify a channel using $daily notifier channel <channel>
        Make sure it's toggle on using $daily notifier toggle on
        """
        if ctx.invoked_subcommand is None:
            return await self.bot.send_cmd_help(ctx)

    @commands.cooldown(1, 5, BucketType.guild)
    @dailynotifier.command(name="channel")
    async def daily_notifier_channel(self, ctx, channel: discord.TextChannel):
        """Sets the channel to send the dailies on server reset to"""
        guild = ctx.guild
        if not guild.me.permissions_in(channel).send_messages:
            return await ctx.send("I do not have permissions to send "
                                  "messages to {.mention}".format(channel))
        await self.bot.database.set_guild(guild, {"daily.channel": channel.id},
                                          self)
        doc = await self.bot.database.get_guild(guild, self)
        enabled = doc["daily"].get("on", False)
        if enabled:
            msg = ("I will now send dailies to {.mention}. "
                   "".format(channel))
        else:
            msg = ("Channel set to {.mention}. In order to receive "
                   "dailies, you still need to enable it using "
                   "`dailynotifier toggle on`.".format(channel))
        await channel.send(msg)

    @commands.cooldown(1, 5, BucketType.guild)
    @dailynotifier.command(name="toggle")
    async def daily_notifier_toggle(self, ctx, on_off: bool):
        """Toggles posting dailies at server reset"""
        guild = ctx.guild
        await self.bot.database.set_guild(guild, {"daily.on": on_off}, self)
        if on_off:
            doc = await self.bot.database.get_guild(guild, self)
            channel = doc["daily"].get("channel")
            if channel:
                channel = guild.get_channel(channel)
                if channel:
                    msg = ("I will now send dailies to {.mention}. "
                           "".format(channel))
            else:
                msg = ("Daily notifier toggled on. In order to reeceive "
                       "dailies, you still need to set a channel using "
                       "`dailynotifier channel <channel>`.".format(channel))
        else:
            msg = ("Daily notifier disabled")
        await ctx.send(msg)

    @commands.cooldown(1, 5, BucketType.guild)
    @dailynotifier.command(name="autodelete")
    async def daily_notifier_autodelete(self, ctx, on_off: bool):
        """Toggles automatically deleting last day's dailies"""
        guild = ctx.guild
        await self.bot.database.set_guild(guild, {"daily.autodelete": on_off},
                                          self)
        await ctx.send("Autodeletion for daily notifs enabled")

    @commands.cooldown(1, 5, BucketType.guild)
    @dailynotifier.command(name="categories")
    async def daily_notifier_categories(self, ctx, *categories):
        """Set daily notifier to only display specific categories

        Separate multiple categories with space, possible values:
        all
        psna
        psna_later
        pve
        pvp
        wvw
        fractals

        psna_later is psna, 8 hours later
        PSNA changes 8 hours after dailies change.

        Example: $dailynotifier categories psna psna_later pve fractals
        """
        if not categories:
            await self.bot.send_cmd_help(ctx)
            return
        guild = ctx.guild
        possible_values = [
            "all", "psna", "psna_later", "pve", "pvp", "wvw", "fractals"
        ]
        categories = [x.lower() for x in categories]
        if len(categories) > 6:
            await self.bot.send_cmd_help(ctx)
            return
        for category in categories:
            if category not in possible_values:
                await self.bot.send_cmd_help(ctx)
                return
            if categories.count(category) > 1:
                await self.bot.send_cmd_help(ctx)
                return
            if category == "all":
                categories = [
                    "psna", "psna_later", "pve", "pvp", "wvw", "fractals"
                ]
                break
        embed = await self.daily_embed(categories)
        await self.bot.database.set_guild(
            guild, {"daily.categories": categories}, self)
        await ctx.send(
            "Your categories have been saved. Here's an example of "
            "your daily notifs:",
            embed=embed)

    @commands.group()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def newsfeed(self, ctx):
        """Automatically sends new from guildwars2.com to specified channel"""
        if ctx.invoked_subcommand is None:
            return await self.bot.send_cmd_help(ctx)

    @newsfeed.command(name="channel")
    async def newsfeed_channel(self, ctx, channel: discord.TextChannel):
        """Sets the channel to send the news to"""
        guild = ctx.guild
        if not guild.me.permissions_in(channel).send_messages:
            return await ctx.send("I do not have permissions to send "
                                  "messages to {.mention}".format(channel))
        await self.bot.database.set_guild(guild, {"news.channel": channel.id},
                                          self)
        doc = await self.bot.database.get_guild(guild, self)
        enabled = doc["news"].get("on", False)
        if enabled:
            msg = ("I will now automatically send news to "
                   "{.mention}.".format(channel))
        else:
            msg = ("Channel set to {.mention}. In order to receive "
                   "news, you still need to enable it using "
                   "`newsfeed toggle on`.".format(channel))
        await channel.send(msg)

    @newsfeed.command(name="toggle")
    async def newsfeed_toggle(self, ctx, on_off: bool):
        """Toggles posting news"""
        guild = ctx.guild
        await self.bot.database.set_guild(guild, {"news.on": on_off}, self)
        if on_off:
            doc = await self.bot.database.get_guild(guild, self)
            channel = doc["news"].get("channel")
            if channel:
                channel = guild.get_channel(channel)
                if channel:  # Channel can be none now
                    msg = (
                        "I will now send news to {.mention}.".format(channel))
            else:
                msg = ("Newsfeed toggled on. In order to reeceive "
                       "news, you still need to set a channel using "
                       "`newsfeed channel <channel>`.".format(channel))
        else:
            msg = ("Newsfeed disabled")
        await ctx.send(msg)

    @commands.group()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def updatenotifier(self, ctx):
        """Sends a notification whenever GW2 is updated"""
        if ctx.invoked_subcommand is None:
            await self.bot.send_cmd_help(ctx)

    @updatenotifier.command(name="channel")
    async def update_channel(self, ctx, channel: discord.TextChannel):
        """Sets the channel to send the update announcement"""
        guild = ctx.guild
        if not guild.me.permissions_in(channel).send_messages:
            return await ctx.send("I do not have permissions to send "
                                  "messages to {.mention}".format(channel))
        await self.bot.database.set_guild(
            guild, {"updates.channel": channel.id}, self)
        doc = await self.bot.database.get_guild(guild, self)
        enabled = doc["updates"].get("on", False)
        if enabled:
            msg = (
                "I will now automatically send update notifications to "
                "{.mention}. **WARNING** these notifications include `@here` "
                "mention. Take away bot's permissions to mention everyone "
                "if you don't want it.".format(channel))
        else:
            msg = ("Channel set to {.mention}. In order to receive "
                   "update notifications, you still need to enable it using "
                   "`updatenotifier toggle on`.".format(channel))
        await channel.send(msg)

    @updatenotifier.command(name="toggle")
    async def update_toggle(self, ctx, on_off: bool):
        """Toggles sending game update notifications"""
        guild = ctx.guild
        await self.bot.database.set_guild(guild, {"updates.on": on_off}, self)
        if on_off:
            doc = await self.bot.database.get_guild(guild, self)
            channel = doc["updates"].get("channel")
            if channel:
                channel = guild.get_channel(channel)
                if channel:  # Channel can be none now
                    msg = (
                        "I will now automatically send update notifications "
                        "to {.mention}. **WARNING** these notifications "
                        "include `@here` mention. Take away bot's permissions "
                        "to mention everyone if you don't "
                        "want it.".format(channel))
            else:
                msg = ("Update notifier toggled on. In order to reeceive "
                       "update notifs, you still need to set a channel using "
                       "`updatenotifier channel <channel>`.".format(channel))
        else:
            msg = ("Update notifier disabled")
        await ctx.send(msg)

    async def get_patchnotes(self):
        url = "https://en-forum.guildwars2.com/categories/game-release-notes"
        async with self.session.get(url) as r:
            results = await r.text()
        soup = BeautifulSoup(results, 'html.parser')
        post = soup.find(class_="Title")
        return "https://forum-en.guildwars2.com" + post["href"]

    async def check_news(self):
        doc = await self.bot.database.get_cog_config(self)
        if not doc:
            return []
        last_news = doc["cache"]["news"]
        url = "https://www.guildwars2.com/en/feed/"
        async with self.session.get(url) as r:
            feed = et.fromstring(await r.text())[0]
        to_post = []
        if last_news:
            for item in feed.findall("item"):
                try:
                    if item.find("title").text not in last_news:
                        to_post.append({
                            "link":
                            item.find("link").text,
                            "title":
                            item.find("title").text,
                            "description":
                            item.find("description").text.split("</p>", 1)[0]
                        })
                except:
                    pass
        last_news = [x.find("title").text for x in feed.findall("item")]
        await self.bot.database.set_cog_config(self, {"cache.news": last_news})
        return to_post

    def news_embed(self, item):
        description = "[Click here]({0})\n{1}".format(item["link"],
                                                      item["description"])
        data = discord.Embed(
            title="{0}".format(item["title"]),
            description=description,
            color=0xc12d2b)
        return data

    async def check_day(self):
        current = datetime.datetime.utcnow().weekday()
        doc = await self.bot.database.get_cog_config(self)
        if not doc:
            return False
        cache = doc["cache"]
        day = cache.get("day")
        dailies = cache.get("dailies")
        if not dailies:
            await self.cache_dailies()
        if day != current:
            await self.bot.database.set_cog_config(self,
                                                   {"cache.day": current})
            return True
        else:
            return False

    async def check_build(self):
        doc = await self.bot.database.get_cog_config(self)
        if not doc:
            return False
        current_build = doc["cache"]["build"]
        endpoint = "build"
        try:
            results = await self.call_api(endpoint)
        except APIError:
            return False
        build = results["id"]
        if not current_build == build:
            await self.bot.database.set_cog_config(self,
                                                   {"cache.build": build})
            return True
        else:
            return False

    async def send_daily_notifs(self):
        try:
            name = self.__class__.__name__
            cursor = self.bot.database.get_guilds_cursor({
                "daily.on": True,
                "daily.channel": {
                    "$ne": None
                }
            }, self)
            daily_doc = await self.bot.database.get_cog_config(self)
            sent = 0
            deleted = 0
            forbidden = 0
            async for doc in cursor:
                try:
                    guild = doc["cogs"][name]["daily"]
                    categories = guild.get("categories")
                    if not categories:
                        categories = [
                            "psna", "psna_later", "pve", "pvp", "wvw",
                            "fractals"
                        ]
                    embed = await self.daily_embed(categories, doc=daily_doc)
                    channel = self.bot.get_channel(guild["channel"])
                    try:
                        message = await channel.send(embed=embed)
                        sent += 1
                    except discord.Forbidden:
                        forbidden += 1
                        message = await channel.send("Need permission to "
                                                     "embed links in order "
                                                     "to send daily "
                                                     "notifs!")
                    await self.bot.database.set_guild(
                        channel.guild, {"daily.message": message.id}, self)
                    autodelete = guild.get("autodelete", False)
                    if autodelete:
                        old_message = guild.get("message")
                        if old_message:
                            to_delete = await channel.get_message(old_message)
                            await to_delete.delete()
                            deleted += 1
                except:
                    pass
            self.log.info("Daily notifs: sent {}, deleted {}, forbidden {}".
                          format(sent, deleted, forbidden))
        except Exception as e:
            self.log.exception(e)
            return

    async def send_news(self, embeds):
        try:
            name = self.__class__.__name__
            cursor = self.bot.database.get_guilds_cursor({
                "news.on": True,
                "news.channel": {
                    "$ne": None
                }
            }, self)
            async for doc in cursor:
                try:
                    guild = doc["cogs"][name]["news"]
                    channel = self.bot.get_channel(guild["channel"])
                    for embed in embeds:
                        await channel.send(embed=embed)
                except:
                    pass
        except Exception as e:
            self.log.exception("Exception sending daily notifs: ", exc_info=e)

    async def send_update_notifs(self):
        try:
            name = self.__class__.__name__
            try:
                link = await self.get_patchnotes()
                patchnotes = "\nUpdate notes: " + link
                doc = await self.bot.database.get_cog_config(self)
                build = doc["cache"]["build"]
            except:
                patchnotes = ""
            message = ("@here Guild Wars 2 has just updated! New build: "
                       "`{0}`{1}".format(build, patchnotes))
            cursor = self.bot.database.get_guilds_cursor({
                "updates.on": True,
                "updates.channel": {
                    "$ne": None
                }
            }, self)
            async for doc in cursor:
                try:
                    guild = doc["cogs"][name]["updates"]
                    await self.bot.get_channel(guild["channel"]).send(message)
                except:
                    pass
        except Exception as e:
            self.log.exception(e)

    async def daily_checker(self):
        while self is self.bot.get_cog("GuildWars2"):
            try:
                if await self.check_day():
                    await asyncio.sleep(300)
                    await self.cache_dailies()
                    await self.send_daily_notifs()
                await asyncio.sleep(60)
            except Exception as e:
                self.log.exception(e)
                await asyncio.sleep(60)
                continue

    async def news_checker(self):
        while self is self.bot.get_cog("GuildWars2"):
            try:
                to_post = await self.check_news()
                if to_post:
                    embeds = []
                    for item in to_post:
                        embeds.append(self.news_embed(item))
                    await self.send_news(embeds)
                await asyncio.sleep(300)
            except Exception as e:
                self.log.exception(e)
                await asyncio.sleep(300)
                continue

    async def game_update_checker(self):
        while self is self.bot.get_cog("GuildWars2"):
            try:
                if await self.check_build():
                    await self.send_update_notifs()
                    await self.rebuild_database()
                await asyncio.sleep(60)
            except Exception as e:
                self.log.exception(e)
                await asyncio.sleep(60)
                continue
<commit_msg>Fix patchnotes returning wrong link<commit_after>import asyncio
import datetime
import xml.etree.ElementTree as et

import discord
from bs4 import BeautifulSoup
from discord.ext import commands
from discord.ext.commands.cooldowns import BucketType

from .exceptions import APIError

class NotiifiersMixin:
    @commands.group()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def dailynotifier(self, ctx):
        """Sends a list of dailies on server reset to specificed channel.
        First, specify a channel using $daily notifier channel <channel>
        Make sure it's toggle on using $daily notifier toggle on
        """
        if ctx.invoked_subcommand is None:
            return await self.bot.send_cmd_help(ctx)

    @commands.cooldown(1, 5, BucketType.guild)
    @dailynotifier.command(name="channel")
    async def daily_notifier_channel(self, ctx, channel: discord.TextChannel):
        """Sets the channel to send the dailies on server reset to"""
        guild = ctx.guild
        if not guild.me.permissions_in(channel).send_messages:
            return await ctx.send("I do not have permissions to send "
                                  "messages to {.mention}".format(channel))
        await self.bot.database.set_guild(guild, {"daily.channel": channel.id},
                                          self)
        doc = await self.bot.database.get_guild(guild, self)
        enabled = doc["daily"].get("on", False)
        if enabled:
            msg = ("I will now send dailies to {.mention}. "
                   "".format(channel))
        else:
            msg = ("Channel set to {.mention}. In order to receive "
                   "dailies, you still need to enable it using "
                   "`dailynotifier toggle on`.".format(channel))
        await channel.send(msg)

    @commands.cooldown(1, 5, BucketType.guild)
    @dailynotifier.command(name="toggle")
    async def daily_notifier_toggle(self, ctx, on_off: bool):
        """Toggles posting dailies at server reset"""
        guild = ctx.guild
        await self.bot.database.set_guild(guild, {"daily.on": on_off}, self)
        if on_off:
            doc = await self.bot.database.get_guild(guild, self)
            channel = doc["daily"].get("channel")
            if channel:
                channel = guild.get_channel(channel)
                if channel:
                    msg = ("I will now send dailies to {.mention}. "
                           "".format(channel))
            else:
                msg = ("Daily notifier toggled on. In order to reeceive "
                       "dailies, you still need to set a channel using "
                       "`dailynotifier channel <channel>`.".format(channel))
        else:
            msg = ("Daily notifier disabled")
        await ctx.send(msg)

    @commands.cooldown(1, 5, BucketType.guild)
    @dailynotifier.command(name="autodelete")
    async def daily_notifier_autodelete(self, ctx, on_off: bool):
        """Toggles automatically deleting last day's dailies"""
        guild = ctx.guild
        await self.bot.database.set_guild(guild, {"daily.autodelete": on_off},
                                          self)
        await ctx.send("Autodeletion for daily notifs enabled")

    @commands.cooldown(1, 5, BucketType.guild)
    @dailynotifier.command(name="categories")
    async def daily_notifier_categories(self, ctx, *categories):
        """Set daily notifier to only display specific categories

        Separate multiple categories with space, possible values:
        all
        psna
        psna_later
        pve
        pvp
        wvw
        fractals

        psna_later is psna, 8 hours later
        PSNA changes 8 hours after dailies change.

        Example: $dailynotifier categories psna psna_later pve fractals
        """
        if not categories:
            await self.bot.send_cmd_help(ctx)
            return
        guild = ctx.guild
        possible_values = [
            "all", "psna", "psna_later", "pve", "pvp", "wvw", "fractals"
        ]
        categories = [x.lower() for x in categories]
        if len(categories) > 6:
            await self.bot.send_cmd_help(ctx)
            return
        for category in categories:
            if category not in possible_values:
                await self.bot.send_cmd_help(ctx)
                return
            if categories.count(category) > 1:
                await self.bot.send_cmd_help(ctx)
                return
            if category == "all":
                categories = [
                    "psna", "psna_later", "pve", "pvp", "wvw", "fractals"
                ]
                break
        embed = await self.daily_embed(categories)
        await self.bot.database.set_guild(
            guild, {"daily.categories": categories}, self)
        await ctx.send(
            "Your categories have been saved. Here's an example of "
            "your daily notifs:",
            embed=embed)

    @commands.group()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def newsfeed(self, ctx):
        """Automatically sends new from guildwars2.com to specified channel"""
        if ctx.invoked_subcommand is None:
            return await self.bot.send_cmd_help(ctx)

    @newsfeed.command(name="channel")
    async def newsfeed_channel(self, ctx, channel: discord.TextChannel):
        """Sets the channel to send the news to"""
        guild = ctx.guild
        if not guild.me.permissions_in(channel).send_messages:
            return await ctx.send("I do not have permissions to send "
                                  "messages to {.mention}".format(channel))
        await self.bot.database.set_guild(guild, {"news.channel": channel.id},
                                          self)
        doc = await self.bot.database.get_guild(guild, self)
        enabled = doc["news"].get("on", False)
        if enabled:
            msg = ("I will now automatically send news to "
                   "{.mention}.".format(channel))
        else:
            msg = ("Channel set to {.mention}. In order to receive "
                   "news, you still need to enable it using "
                   "`newsfeed toggle on`.".format(channel))
        await channel.send(msg)

    @newsfeed.command(name="toggle")
    async def newsfeed_toggle(self, ctx, on_off: bool):
        """Toggles posting news"""
        guild = ctx.guild
        await self.bot.database.set_guild(guild, {"news.on": on_off}, self)
        if on_off:
            doc = await self.bot.database.get_guild(guild, self)
            channel = doc["news"].get("channel")
            if channel:
                channel = guild.get_channel(channel)
                if channel:  # Channel can be none now
                    msg = (
                        "I will now send news to {.mention}.".format(channel))
            else:
                msg = ("Newsfeed toggled on. In order to reeceive "
                       "news, you still need to set a channel using "
                       "`newsfeed channel <channel>`.".format(channel))
        else:
            msg = ("Newsfeed disabled")
        await ctx.send(msg)

    @commands.group()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def updatenotifier(self, ctx):
        """Sends a notification whenever GW2 is updated"""
        if ctx.invoked_subcommand is None:
            await self.bot.send_cmd_help(ctx)

    @updatenotifier.command(name="channel")
    async def update_channel(self, ctx, channel: discord.TextChannel):
        """Sets the channel to send the update announcement"""
        guild = ctx.guild
        if not guild.me.permissions_in(channel).send_messages:
            return await ctx.send("I do not have permissions to send "
                                  "messages to {.mention}".format(channel))
        await self.bot.database.set_guild(
            guild, {"updates.channel": channel.id}, self)
        doc = await self.bot.database.get_guild(guild, self)
        enabled = doc["updates"].get("on", False)
        if enabled:
            msg = (
                "I will now automatically send update notifications to "
                "{.mention}. **WARNING** these notifications include `@here` "
                "mention. Take away bot's permissions to mention everyone "
                "if you don't want it.".format(channel))
        else:
            msg = ("Channel set to {.mention}. In order to receive "
                   "update notifications, you still need to enable it using "
                   "`updatenotifier toggle on`.".format(channel))
        await channel.send(msg)

    @updatenotifier.command(name="toggle")
    async def update_toggle(self, ctx, on_off: bool):
        """Toggles sending game update notifications"""
        guild = ctx.guild
        await self.bot.database.set_guild(guild, {"updates.on": on_off}, self)
        if on_off:
            doc = await self.bot.database.get_guild(guild, self)
            channel = doc["updates"].get("channel")
            if channel:
                channel = guild.get_channel(channel)
                if channel:  # Channel can be none now
                    msg = (
                        "I will now automatically send update notifications "
                        "to {.mention}. **WARNING** these notifications "
                        "include `@here` mention. Take away bot's permissions "
                        "to mention everyone if you don't "
                        "want it.".format(channel))
            else:
                msg = ("Update notifier toggled on. In order to reeceive "
                       "update notifs, you still need to set a channel using "
                       "`updatenotifier channel <channel>`.".format(channel))
        else:
            msg = ("Update notifier disabled")
        await ctx.send(msg)

    async def get_patchnotes(self):
        url = "https://en-forum.guildwars2.com/categories/game-release-notes"
        async with self.session.get(url) as r:
            results = await r.text()
        soup = BeautifulSoup(results, 'html.parser')
        post = soup.find(class_="Title")
        return post["href"]

    async def check_news(self):
        doc = await self.bot.database.get_cog_config(self)
        if not doc:
            return []
        last_news = doc["cache"]["news"]
        url = "https://www.guildwars2.com/en/feed/"
        async with self.session.get(url) as r:
            feed = et.fromstring(await r.text())[0]
        to_post = []
        if last_news:
            for item in feed.findall("item"):
                try:
                    if item.find("title").text not in last_news:
                        to_post.append({
                            "link":
                            item.find("link").text,
                            "title":
                            item.find("title").text,
                            "description":
                            item.find("description").text.split("</p>", 1)[0]
                        })
                except:
                    pass
        last_news = [x.find("title").text for x in feed.findall("item")]
        await self.bot.database.set_cog_config(self, {"cache.news": last_news})
        return to_post

    def news_embed(self, item):
        description = "[Click here]({0})\n{1}".format(item["link"],
                                                      item["description"])
        data = discord.Embed(
            title="{0}".format(item["title"]),
            description=description,
            color=0xc12d2b)
        return data

    async def check_day(self):
        current = datetime.datetime.utcnow().weekday()
        doc = await self.bot.database.get_cog_config(self)
        if not doc:
            return False
        cache = doc["cache"]
        day = cache.get("day")
        dailies = cache.get("dailies")
        if not dailies:
            await self.cache_dailies()
        if day != current:
            await self.bot.database.set_cog_config(self,
                                                   {"cache.day": current})
            return True
        else:
            return False

    async def check_build(self):
        doc = await self.bot.database.get_cog_config(self)
        if not doc:
            return False
        current_build = doc["cache"]["build"]
        endpoint = "build"
        try:
            results = await self.call_api(endpoint)
        except APIError:
            return False
        build = results["id"]
        if not current_build == build:
            await self.bot.database.set_cog_config(self,
                                                   {"cache.build": build})
            return True
        else:
            return False

    async def send_daily_notifs(self):
        try:
            name = self.__class__.__name__
            cursor = self.bot.database.get_guilds_cursor({
                "daily.on": True,
                "daily.channel": {
                    "$ne": None
                }
            }, self)
            daily_doc = await self.bot.database.get_cog_config(self)
            sent = 0
            deleted = 0
            forbidden = 0
            async for doc in cursor:
                try:
                    guild = doc["cogs"][name]["daily"]
                    categories = guild.get("categories")
                    if not categories:
                        categories = [
                            "psna", "psna_later", "pve", "pvp", "wvw",
                            "fractals"
                        ]
                    embed = await self.daily_embed(categories, doc=daily_doc)
                    channel = self.bot.get_channel(guild["channel"])
                    try:
                        message = await channel.send(embed=embed)
                        sent += 1
                    except discord.Forbidden:
                        forbidden += 1
                        message = await channel.send("Need permission to "
                                                     "embed links in order "
                                                     "to send daily "
                                                     "notifs!")
                    await self.bot.database.set_guild(
                        channel.guild, {"daily.message": message.id}, self)
                    autodelete = guild.get("autodelete", False)
                    if autodelete:
                        old_message = guild.get("message")
                        if old_message:
                            to_delete = await channel.get_message(old_message)
                            await to_delete.delete()
                            deleted += 1
                except:
                    pass
            self.log.info("Daily notifs: sent {}, deleted {}, forbidden {}".
                          format(sent, deleted, forbidden))
        except Exception as e:
            self.log.exception(e)
            return

    async def send_news(self, embeds):
        try:
            name = self.__class__.__name__
            cursor = self.bot.database.get_guilds_cursor({
                "news.on": True,
                "news.channel": {
                    "$ne": None
                }
            }, self)
            async for doc in cursor:
                try:
                    guild = doc["cogs"][name]["news"]
                    channel = self.bot.get_channel(guild["channel"])
                    for embed in embeds:
                        await channel.send(embed=embed)
                except:
                    pass
        except Exception as e:
            self.log.exception("Exception sending daily notifs: ", exc_info=e)

    async def send_update_notifs(self):
        try:
            name = self.__class__.__name__
            try:
                link = await self.get_patchnotes()
                patchnotes = "\nUpdate notes: " + link
                doc = await self.bot.database.get_cog_config(self)
                build = doc["cache"]["build"]
            except:
                patchnotes = ""
            message = ("@here Guild Wars 2 has just updated! New build: "
                       "`{0}`{1}".format(build, patchnotes))
            cursor = self.bot.database.get_guilds_cursor({
                "updates.on": True,
                "updates.channel": {
                    "$ne": None
                }
            }, self)
            async for doc in cursor:
                try:
                    guild = doc["cogs"][name]["updates"]
                    await self.bot.get_channel(guild["channel"]).send(message)
                except:
                    pass
        except Exception as e:
            self.log.exception(e)

    async def daily_checker(self):
        while self is self.bot.get_cog("GuildWars2"):
            try:
                if await self.check_day():
                    await asyncio.sleep(300)
                    await self.cache_dailies()
                    await self.send_daily_notifs()
                await asyncio.sleep(60)
            except Exception as e:
                self.log.exception(e)
                await asyncio.sleep(60)
                continue

    async def news_checker(self):
        while self is self.bot.get_cog("GuildWars2"):
            try:
                to_post = await self.check_news()
                if to_post:
                    embeds = []
                    for item in to_post:
                        embeds.append(self.news_embed(item))
                    await self.send_news(embeds)
                await asyncio.sleep(300)
            except Exception as e:
                self.log.exception(e)
                await asyncio.sleep(300)
                continue

    async def game_update_checker(self):
        while self is self.bot.get_cog("GuildWars2"):
            try:
                if await self.check_build():
                    await self.send_update_notifs()
                    await self.rebuild_database()
                await asyncio.sleep(60)
            except Exception as e:
                self.log.exception(e)
                await asyncio.sleep(60)
                continue
<|endoftext|>


<commit_before>#!/usr/bin/python
# Author : jeonghoonkang, https://github.com/jeonghoonkang

devel_dir="/home/pi/devel"
tmp_dir=devel_dir+"/BerePi/apps"

from types import *
import sys
from time import strftime, localtime
import datetime
import requests
import json
import subprocess

sys.path.append(tmp_dir+"/sht20")
from sht25class import *

################
url = "http://10.0.0.43:4242/api/put"

def otsdb_restful_put():
    sht21_temp = temp_chk()
    temp_v=str(sht21_temp)
    if temp_v != "-100" :
    	print('otsdb %-5.2f `C' % (sht21_temp))
    ret = humi_chk()
    retstr = str(ret)
    if retstr != "-100" :
        print('otsdb %-5.2f %%' % (ret))

    #sname = hostname_chk()
    sname = "kang-odesk-03"
    data = {
        "metric": "z_beta.temp.sht2x.dgree",
        "timestamp": time.time(),
        "value": sht21_temp, #integer
        "tags": {
            #"eth0": macAddr,
            #"stalk": "VOLOSSH" ,
            "sensor" : "sht2x",
	        "name" : sname,
	        "floor_room": "6F_office",
	        "building": "global_rnd_center",
	        "owner": "kang",
	        "country": "kor"
        }
	#tags should be less than 9, 8 is alright, 9 returns http error
    }

    try :
        ret = requests.post(url, data=json.dumps(data))
    except requests.exceptions.Timeout :
        logger.error("http connection error, Timeout  %s", ret)
        pass
    except requests.exceptions.ConnectionError :
        logger.error("http connection error, Too many requests %s")
        pass

    return

def temp_chk():
    temperature = getTemperature()
    return temperature

def humi_chk():
    humidity = getHumidity()
    return humidity

def hostname_chk():
    cmd = "hostname"
    return run_cmd(cmd)

# check it, which is not running , thus cancel calling it
def run_cmd(cmd):
    p = Popen(cmd, shell=True, stdout=PIPE)
    output = p.communicate()[0]
    return output

<commit_msg>Update sth2x.py<commit_after>#!/usr/bin/python
# Author : jeonghoonkang, https://github.com/jeonghoonkang

devel_dir="/home/pi/devel"
tmp_dir=devel_dir+"/BerePi/apps"

from types import *
import sys
from time import strftime, localtime
import datetime
import requests
import json
import subprocess

sys.path.append(tmp_dir+"/sht20")
from sht25class import *

################

url = "http://10.0.0.43:4242/api/put"

def otsdb_restful_put(_ip = None):

    sht21_temp = temp_chk()
    temp_v=str(sht21_temp)
    if temp_v != "-100" :
    	print('otsdb %-5.2f `C' % (sht21_temp))

    ret = humi_chk()
    retstr = str(ret)
    if retstr != "-100" :
        print('otsdb %-5.2f %%' % (ret))

    #ip_add = ip_chk()
    #sname = hostname_chk()
    sname = "kang-odesk-03"
    if _ip != None : ip_add = _ip
    else: ip_add = 'unkown'
    metric = "jkraspi.rc01.temp.degree"
    print "   ", url, metric, "IPadd=",ip_add

    data = {
        "metric": metric ,
        "timestamp": time.time(),
        "value": sht21_temp, #integer
        "tags": {
            "IPadd": ip_add,
            #"stalk": "VOLOSSH" ,
            "sensor" : "sht2x",
	    "name" : sname,
            "floor_room": "6F_office",
	    "building": "global_rnd",
	    "loc": "pangyo"
            #"owner": "kang"
        }
	#tags should be less than 9, 8 is alright, 9 returns http error
    }

    try :
        ret = requests.post(url, data=json.dumps(data))
        print ret
    except requests.exceptions.Timeout :
        #logger.error("http connection error, Timeout  %s", ret)
        print("http connection error, Timeout  %s", ret)
        pass
    except requests.exceptions.ConnectionError :
        print("http connection error, Timeout  %s", ret)
        #logger.error("http connection error, Too many requests %s")
        pass

    return

def temp_chk():
    temperature = getTemperature()
    return temperature

def humi_chk():
    humidity = getHumidity()
    return humidity

def hostname_chk():
    cmd = "hostname"
    return run_cmd(cmd)

def run_cmd(cmd):
    p = Popen(cmd, shell=True, stdout=PIPE)
    output = p.communicate()[0]
    return output

<|endoftext|>


<commit_before>"""
Provides Dimension objects for tracking the properties of a value,
axis or map dimension. Also supplies the Dimensioned abstract
baseclass for classes that accept Dimension values.
"""

import numpy as np

import param

class Dimension(param.Parameterized):

    cyclic = param.Boolean(default=False, doc="""
        Whether the range of this feature is cyclic (wraps around at the high
        end).""")

    name = param.String(default="", doc="Name of the Dimension.")

    range = param.Tuple(default=(None, None), doc="""
        Lower and upper values for a Dimension.""")

    type = param.Parameter(default=None, doc="""
        Type associated with Dimension values.""")

    unit = param.String(default=None, doc="Unit string associated with"
                                          "the Dimension.")

    values = param.List(default=[], doc="""
        Values may optionally be specified to specify valid
        dimension values and/or retain a categorical ordering.""")

    format_string = param.String(default="{name}: {val}{unit}")

    def __init__(self, name, **params):
        """
        Initializes the Dimension object with a name.
        """
        if isinstance(name, Dimension):
            existing_params = dict(name.get_param_values())
        else:
            existing_params = {'name': name}
        super(Dimension, self).__init__(**dict(existing_params, **params))

    def __call__(self, name=None, **params):
        settings = dict(self.get_param_values(onlychanged=True), **params)
        if name is not None: settings['name'] = name
        return self.__class__(**settings)

    @property
    def pprint_label(self):
        unit = '' if self.unit is None else ' (%s)' % self.unit
        return self.name + unit

    def pprint_value(self, value, rounding=2):
        """
        Pretty prints the dimension name and value with the format_string
        parameter and if supplied adds the unit string parameter.
        """

        unit = '' if self.unit is None else ' ' + self.unit
        try: # Try formatting numeric types as floats with rounding
            val = round(float(value), rounding)
        except:
            val = value

        return self.format_string.format(name=self.name.capitalize(),
                                         val=val, unit=unit)

    def __hash__(self):
        return sum([hash(value) for name, value in self.get_param_values()])

    def __str__(self):
        return self.pprint_label

    def __eq__(self, other):
        "Dimensions are sorted alphanumerically by name"
        return self.name == other.name if isinstance(other, Dimension) else other

    def __lt__(self, other):
        "Dimensions are sorted alphanumerically by name"
        return self.name < other.name if isinstance(other, Dimension) else other

class Dimensioned(param.Parameterized):
    """
    Abstract baseclass implementing common methods for objects with
    associated dimensions. Dimensioned support three dimension groups:

    * index_dimensions: The Dimensioned objects should implement
                        indexing and slicing for these dimensions.

    * value_dimensions: These dimensions correspond to any data
                        held on the Dimensioned object.

    * deep_dimensions:  These are dynamically computed and
                        correspond to any dimensions on items
                        held on this object. Objects that support
                        this should enable the _deep_indexable
                        flag.

    Dimensioned also provides convenient methods to find the
    range and type of values along a particular Dimension.
    For ranges to work appropriately subclasses should define
    dimension_values methods, which return an array of all the
    values along the supplied dimension.
    """

    index_dimensions = param.List(bounds=(0, None), constant=True, doc="""
       The dimensions the values are indexed by.""")

    label = param.String(default='', constant=True, doc="""
       Optional label describing the data, e.g. where or how it
       was measured.""")

    value = param.String(default='Dimensioned', constant=True, doc="""
       A string describing what the data of the object contain.
       By default this should mirror the class name.""")

    value_dimensions = param.List(bounds=(0, None), constant=True, doc="""
       The dimensions the values are indexed by. Subclasses should
       restrict bounds to appropriate number of dimensions.""")

    __abstract = True

    _deep_indexable = False
    _sorted = False
    _dim_groups = ['index_dimensions',
                   'value_dimensions',
                   'deep_dimensions']

    def __init__(self, **params):
        self.data = None
        for group in self._dim_groups[0:2]:
            if group in params:
                dimensions = [Dimension(d) if not isinstance(d, Dimension) else d
                              for d in params.pop(group)]
                params[group] = dimensions
        super(Dimensioned, self).__init__(**params)
        self.ndims = len(self.index_dimensions)
        self._cached_index_names = [d.name for d in self.index_dimensions]
        self._cached_value_names = [d.name for d in self.value_dimensions]

    def clone(self, data=None, *args, **kwargs):
        """
        Returns a clone with matching parameter values containing the
        specified args and kwargs (empty by default).
        """
        settings = dict(self.get_param_values(), **kwargs)
        return self.__class__(data, *args, **settings)

    @property
    def deep_dimensions(self):
        if self._deep_indexable:
            return self.values()[0].dimensions
        else:
            return []

    @property
    def dimensions(self):
        return [dim for group in self._dim_groups
                for dim in getattr(self, group)]

    def get_dimension(self, dimension, default=None):
        """
        Allows querying for a Dimension by name or index.
        """
        all_dims = self.dimensions
        if isinstance(dimension, int):
            return all_dims[dimension]
        else:
            return {dim.name: dim for dim in all_dims}.get(dimension, default)

    def dimension_values(self, dimension):
        """
        Dimension values should return the values along the specified
        dimension. This method has to be implemented appropriately
        for each Dimensioned type.
        """
        raise NotImplementedError

    def range(self, dim):
        """
        Range will return the range of values along the specified dimension.
        """
        dimension = self.get_dimension(dim)
        if dimension.range != (None, None):
            return dimension.range
        dim_vals = self.dimension_values(dimension.name)
        try:
            return np.min(dim_vals), np.max(dim_vals)
        except:
            if dim in self.dimensions:
                if not self._sorted:
                    dim_vals = sorted(dim_vals)
                return (dim_vals[0], dim_vals[-1])
            else:
                return (None, None)

    def get_dimension_index(self, dim):
        """
        Returns the tuple index of the requested dimension.
        """
        if isinstance(dim, int):
            if dim < len(self.dimensions):
                return dim
            else:
                return IndexError('Dimension index out of bounds')
        try:
            return [d.name for d in self.dimensions].index(dim)
        except ValueError:
            raise Exception("Dimension %s not found in %s." %
                            (dim, self.__class__.__name__))

    def get_dimension_type(self, dim):
        """
        Returns the specified Dimension type if specified or
        if the dimension_values types are consistent otherwise
        None is returned.
        """
        dim_obj = self.get_dimension(dim)
        if dim_obj.type is not None:
            return dim_obj.type
        dim_vals = [type(v) for v in self.dimension_values(dim)]
        if len(set(dim_vals)) == 1:
            return dim_vals[0]
        else:
            return None
<commit_msg>Removed .data attribute declaration from Dimensioned<commit_after>"""
Provides Dimension objects for tracking the properties of a value,
axis or map dimension. Also supplies the Dimensioned abstract
baseclass for classes that accept Dimension values.
"""

import numpy as np

import param

class Dimension(param.Parameterized):

    cyclic = param.Boolean(default=False, doc="""
        Whether the range of this feature is cyclic (wraps around at the high
        end).""")

    name = param.String(default="", doc="Name of the Dimension.")

    range = param.Tuple(default=(None, None), doc="""
        Lower and upper values for a Dimension.""")

    type = param.Parameter(default=None, doc="""
        Type associated with Dimension values.""")

    unit = param.String(default=None, doc="Unit string associated with"
                                          "the Dimension.")

    values = param.List(default=[], doc="""
        Values may optionally be specified to specify valid
        dimension values and/or retain a categorical ordering.""")

    format_string = param.String(default="{name}: {val}{unit}")

    def __init__(self, name, **params):
        """
        Initializes the Dimension object with a name.
        """
        if isinstance(name, Dimension):
            existing_params = dict(name.get_param_values())
        else:
            existing_params = {'name': name}
        super(Dimension, self).__init__(**dict(existing_params, **params))

    def __call__(self, name=None, **params):
        settings = dict(self.get_param_values(onlychanged=True), **params)
        if name is not None: settings['name'] = name
        return self.__class__(**settings)

    @property
    def pprint_label(self):
        unit = '' if self.unit is None else ' (%s)' % self.unit
        return self.name + unit

    def pprint_value(self, value, rounding=2):
        """
        Pretty prints the dimension name and value with the format_string
        parameter and if supplied adds the unit string parameter.
        """

        unit = '' if self.unit is None else ' ' + self.unit
        try: # Try formatting numeric types as floats with rounding
            val = round(float(value), rounding)
        except:
            val = value

        return self.format_string.format(name=self.name.capitalize(),
                                         val=val, unit=unit)

    def __hash__(self):
        return sum([hash(value) for name, value in self.get_param_values()])

    def __str__(self):
        return self.pprint_label

    def __eq__(self, other):
        "Dimensions are sorted alphanumerically by name"
        return self.name == other.name if isinstance(other, Dimension) else other

    def __lt__(self, other):
        "Dimensions are sorted alphanumerically by name"
        return self.name < other.name if isinstance(other, Dimension) else other

class Dimensioned(param.Parameterized):
    """
    Abstract baseclass implementing common methods for objects with
    associated dimensions. Dimensioned support three dimension groups:

    * index_dimensions: The Dimensioned objects should implement
                        indexing and slicing for these dimensions.

    * value_dimensions: These dimensions correspond to any data
                        held on the Dimensioned object.

    * deep_dimensions:  These are dynamically computed and
                        correspond to any dimensions on items
                        held on this object. Objects that support
                        this should enable the _deep_indexable
                        flag.

    Dimensioned also provides convenient methods to find the
    range and type of values along a particular Dimension.
    For ranges to work appropriately subclasses should define
    dimension_values methods, which return an array of all the
    values along the supplied dimension.
    """

    index_dimensions = param.List(bounds=(0, None), constant=True, doc="""
       The dimensions the values are indexed by.""")

    label = param.String(default='', constant=True, doc="""
       Optional label describing the data, e.g. where or how it
       was measured.""")

    value = param.String(default='Dimensioned', constant=True, doc="""
       A string describing what the data of the object contain.
       By default this should mirror the class name.""")

    value_dimensions = param.List(bounds=(0, None), constant=True, doc="""
       The dimensions the values are indexed by. Subclasses should
       restrict bounds to appropriate number of dimensions.""")

    __abstract = True

    _deep_indexable = False
    _sorted = False
    _dim_groups = ['index_dimensions',
                   'value_dimensions',
                   'deep_dimensions']

    def __init__(self, **params):
        for group in self._dim_groups[0:2]:
            if group in params:
                dimensions = [Dimension(d) if not isinstance(d, Dimension) else d
                              for d in params.pop(group)]
                params[group] = dimensions
        super(Dimensioned, self).__init__(**params)
        self.ndims = len(self.index_dimensions)
        self._cached_index_names = [d.name for d in self.index_dimensions]
        self._cached_value_names = [d.name for d in self.value_dimensions]

    def clone(self, data=None, *args, **kwargs):
        """
        Returns a clone with matching parameter values containing the
        specified args and kwargs (empty by default).
        """
        settings = dict(self.get_param_values(), **kwargs)
        return self.__class__(data, *args, **settings)

    @property
    def deep_dimensions(self):
        if self._deep_indexable:
            return self.values()[0].dimensions
        else:
            return []

    @property
    def dimensions(self):
        return [dim for group in self._dim_groups
                for dim in getattr(self, group)]

    def get_dimension(self, dimension, default=None):
        """
        Allows querying for a Dimension by name or index.
        """
        all_dims = self.dimensions
        if isinstance(dimension, int):
            return all_dims[dimension]
        else:
            return {dim.name: dim for dim in all_dims}.get(dimension, default)

    def dimension_values(self, dimension):
        """
        Dimension values should return the values along the specified
        dimension. This method has to be implemented appropriately
        for each Dimensioned type.
        """
        raise NotImplementedError

    def range(self, dim):
        """
        Range will return the range of values along the specified dimension.
        """
        dimension = self.get_dimension(dim)
        if dimension.range != (None, None):
            return dimension.range
        dim_vals = self.dimension_values(dimension.name)
        try:
            return np.min(dim_vals), np.max(dim_vals)
        except:
            if dim in self.dimensions:
                if not self._sorted:
                    dim_vals = sorted(dim_vals)
                return (dim_vals[0], dim_vals[-1])
            else:
                return (None, None)

    def get_dimension_index(self, dim):
        """
        Returns the tuple index of the requested dimension.
        """
        if isinstance(dim, int):
            if dim < len(self.dimensions):
                return dim
            else:
                return IndexError('Dimension index out of bounds')
        try:
            return [d.name for d in self.dimensions].index(dim)
        except ValueError:
            raise Exception("Dimension %s not found in %s." %
                            (dim, self.__class__.__name__))

    def get_dimension_type(self, dim):
        """
        Returns the specified Dimension type if specified or
        if the dimension_values types are consistent otherwise
        None is returned.
        """
        dim_obj = self.get_dimension(dim)
        if dim_obj.type is not None:
            return dim_obj.type
        dim_vals = [type(v) for v in self.dimension_values(dim)]
        if len(set(dim_vals)) == 1:
            return dim_vals[0]
        else:
            return None
<|endoftext|>


<commit_before>from gutenberg.acquire import load_etext
from gutenberg.query import get_etexts
from gutenberg.query import get_metadata
from sanic.request import Request
from sanic.response import json
from sanic.response import text

from gutenberg_http import app
from gutenberg_http.parameters import parse_fields
from gutenberg_http.parameters import parse_search

@app.route('/texts/<text_id:int>')
async def metadata(request: Request, text_id: int):
    fields = parse_fields(request.args.get('fields'))
    metadata_values = {field: get_metadata(field, text_id) for field in fields}

    return json({'text_id': text_id, 'metadata': metadata_values})

# noinspection PyUnusedLocal
@app.route('/texts/<text_id:int>/body')
async def body(request: Request, text_id: int):
    body_value = load_etext(text_id)

    return text(body_value)

@app.route('/search')
async def search(request: Request):
    field, value = parse_search(request.args.get('q'))
    search_results = get_etexts(field, value)

    return json({'text_ids': search_results})
<commit_msg>Avoid using query parameters for required values<commit_after>from gutenberg.acquire import load_etext
from gutenberg.query import get_etexts
from gutenberg.query import get_metadata
from sanic.request import Request
from sanic.response import json
from sanic.response import text

from gutenberg_http import app
from gutenberg_http.parameters import parse_fields
from gutenberg_http.parameters import parse_search

@app.route('/texts/<text_id:int>')
async def metadata(request: Request, text_id: int):
    fields = parse_fields(request.args.get('fields'))
    metadata_values = {field: get_metadata(field, text_id) for field in fields}

    return json({'text_id': text_id, 'metadata': metadata_values})

# noinspection PyUnusedLocal
@app.route('/texts/<text_id:int>/body')
async def body(request: Request, text_id: int):
    body_value = load_etext(text_id)

    return text(body_value)

# noinspection PyUnusedLocal
@app.route('/search/<query>')
async def search(request: Request, query: str):
    field, value = parse_search(query)
    search_results = get_etexts(field, value)

    return json({'text_ids': search_results})
<|endoftext|>


<commit_before>"""
Rules for Accounts
"""

from smart.views import *
from smart.models.rdf_rest_operations import *
from smart.models.record_object import *

try:
    from smart.plugins import *
except ImportError: pass

def check_token_for_record_wrapper(token):
        def check_token_for_record(request, view_func, view_args, view_kwargs):
            return token.share.record.id == view_kwargs['record_id']
        return check_token_for_record

def check_frame_mode_wrapper(token):
    pha = PHA.objects.get(id=token.share.with_app.id)

    def r(request, view_func, view_args, view_kwargs):
        return pha.mode == "frame_ui"
    return r

def check_token_for_account_app_wrapper(token):
        def check_token_for_account_app(request, view_func, view_args, view_kwargs):
            pha = PHA.objects.get(id=token.share.with_app.id)
            acc = Account.objects.get(id=token.share.authorized_by.id)
            return pha.email == view_kwargs['pha_email'] and acc.email == view_kwargs['account_email']
        return check_token_for_account_app

def grant(accesstoken, permset):
    """
    grant the permissions of an account to this permset
    """

    check_token_for_record = check_token_for_record_wrapper(accesstoken)

    permset.grant(home)
    permset.grant(record_by_token)

    permset.grant(do_webhook)
    permset.grant(record_delete_all_objects, [check_token_for_record])
    permset.grant(record_delete_object, [check_token_for_record])
    permset.grant(record_put_object, [check_token_for_record])
    permset.grant(record_post_objects, [check_token_for_record])
    permset.grant(record_get_all_objects, [check_token_for_record])

    permset.grant(record_get_object, [check_token_for_record])

    permset.grant(record_get_filtered_labs, [check_token_for_record])
    permset.grant(record_get_allergies, [check_token_for_record])

    try:
        permset.grant(record_proxy_backend.proxy_get, [check_token_for_record])
    except:
        pass

    permset.grant(put_demographics, [check_token_for_record])
    permset.grant(record_post_alert, [check_token_for_record])
    permset.grant(user_search)
    permset.grant(user_get)

    check_frame_mode = check_frame_mode_wrapper(accesstoken)
    permset.grant(resolve_activity_with_app, [])
    permset.grant(resolve_manifest, [check_frame_mode])
    permset.grant(all_manifests, [check_frame_mode])
    permset.grant(record_search, [check_frame_mode])

    check_token_for_account_app = check_token_for_account_app_wrapper(accesstoken)
    permset.grant(preferences_get, [check_token_for_account_app])
    permset.grant(preferences_put, [check_token_for_account_app])
    permset.grant(preferences_delete, [check_token_for_account_app])<commit_msg>Allow regular apps to view manifests (to help them call other apps)<commit_after>"""
Rules for Accounts
"""

from smart.views import *
from smart.models.rdf_rest_operations import *
from smart.models.record_object import *

try:
    from smart.plugins import *
except ImportError: pass

def check_token_for_record_wrapper(token):
        def check_token_for_record(request, view_func, view_args, view_kwargs):
            return token.share.record.id == view_kwargs['record_id']
        return check_token_for_record

def check_frame_mode_wrapper(token):
    pha = PHA.objects.get(id=token.share.with_app.id)

    def r(request, view_func, view_args, view_kwargs):
        return pha.mode == "frame_ui"
    return r

def check_token_for_account_app_wrapper(token):
        def check_token_for_account_app(request, view_func, view_args, view_kwargs):
            pha = PHA.objects.get(id=token.share.with_app.id)
            acc = Account.objects.get(id=token.share.authorized_by.id)
            return pha.email == view_kwargs['pha_email'] and acc.email == view_kwargs['account_email']
        return check_token_for_account_app

def grant(accesstoken, permset):
    """
    grant the permissions of an account to this permset
    """

    check_token_for_record = check_token_for_record_wrapper(accesstoken)

    permset.grant(home)
    permset.grant(record_by_token)

    permset.grant(do_webhook)
    permset.grant(record_delete_all_objects, [check_token_for_record])
    permset.grant(record_delete_object, [check_token_for_record])
    permset.grant(record_put_object, [check_token_for_record])
    permset.grant(record_post_objects, [check_token_for_record])
    permset.grant(record_get_all_objects, [check_token_for_record])

    permset.grant(record_get_object, [check_token_for_record])

    permset.grant(record_get_filtered_labs, [check_token_for_record])
    permset.grant(record_get_allergies, [check_token_for_record])

    try:
        permset.grant(record_proxy_backend.proxy_get, [check_token_for_record])
    except:
        pass

    permset.grant(put_demographics, [check_token_for_record])
    permset.grant(record_post_alert, [check_token_for_record])
    permset.grant(user_search)
    permset.grant(user_get)

    check_frame_mode = check_frame_mode_wrapper(accesstoken)
    permset.grant(resolve_activity_with_app, [])
    permset.grant(resolve_manifest, [])
    permset.grant(all_manifests, [])
    permset.grant(record_search, [check_frame_mode])

    check_token_for_account_app = check_token_for_account_app_wrapper(accesstoken)
    permset.grant(preferences_get, [check_token_for_account_app])
    permset.grant(preferences_put, [check_token_for_account_app])
    permset.grant(preferences_delete, [check_token_for_account_app])
<|endoftext|>


<commit_before>import argparse
import logging
import os

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import ENVVAR, get_project_settings

from . import get_version

def run_spider(args):
    username = args.username
    domain = args.domain
    file_name = args.file_name
    file_format = args.file_format

    settings = get_project_settings()
    settings.set('FEED_FORMAT', file_format)
    settings.set('FEED_URI', file_name)
    settings.set('LOG_LEVEL', logging.ERROR)

    process = CrawlerProcess(settings)
    process.crawl('favorites', username=username, domain=domain)
    process.start()

def parse():
    settings = get_project_settings()
    domains = settings['HABRA_FAVORITES_DOMAINS']

    description = (
        'Process favorites posts from ' + ', '.join(d.capitalize() for d in domains)
    )
    parser = argparse.ArgumentParser(description=description)

    parser.add_argument('username', help='Nickname')
    parser.add_argument('--version', action='version', version=get_version())
    parser.add_argument(
        '-d', '--domain',
        choices=domains + ['all'],
        dest='domain',
        default='habrahabr.ru',
        help='choose DOMAIN for scrapping',
        metavar='DOMAIN',
    )
    parser.add_argument(
        '-f', '--format',
        choices=['html', 'json', 'csv', 'xml'],
        dest='file_format',
        default='html',
        help='choose FORMAT of the result file',
        metavar='FORMAT',
    )
    parser.add_argument(
        '-o', '--output',
        default='favorites.html',
        dest='file_name',
        help='choose NAME for the result file',
        metavar='NAME',
    )

    return parser.parse_args()

def main():
    os.environ.setdefault(ENVVAR, 'habra_favorites.settings')
    run_spider(parse())

if __name__ == '__main__':
    main()
<commit_msg>Added ability for feed-exporter to finish exporting.<commit_after>import argparse
import logging
import os

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import ENVVAR, get_project_settings

from . import get_version

def run_spider(args):
    username = args.username
    domain = args.domain
    file_name = args.file_name
    file_format = args.file_format

    settings = get_project_settings()
    settings.set('FEED_FORMAT', file_format)
    settings.set('FEED_URI', file_name)
    settings.set('FEED_STORE_EMPTY', True)
    settings.set('LOG_LEVEL', logging.ERROR)

    process = CrawlerProcess(settings)
    process.crawl('favorites', username=username, domain=domain)
    process.start()

def parse():
    settings = get_project_settings()
    domains = settings['HABRA_FAVORITES_DOMAINS']

    description = (
        'Process favorites posts from ' + ', '.join(d.capitalize() for d in domains)
    )
    parser = argparse.ArgumentParser(description=description)

    parser.add_argument('username', help='Nickname')
    parser.add_argument('--version', action='version', version=get_version())
    parser.add_argument(
        '-d', '--domain',
        choices=domains + ['all'],
        dest='domain',
        default='habrahabr.ru',
        help='choose DOMAIN for scrapping',
        metavar='DOMAIN',
    )
    parser.add_argument(
        '-f', '--format',
        choices=['html', 'json', 'csv', 'xml'],
        dest='file_format',
        default='html',
        help='choose FORMAT of the result file',
        metavar='FORMAT',
    )
    parser.add_argument(
        '-o', '--output',
        default='favorites.html',
        dest='file_name',
        help='choose NAME for the result file',
        metavar='NAME',
    )

    return parser.parse_args()

def main():
    os.environ.setdefault(ENVVAR, 'habra_favorites.settings')
    run_spider(parse())

if __name__ == '__main__':
    main()
<|endoftext|>