コード例 #1
0
ファイル: main.py プロジェクト: andreasots/lrrbot
		def new_privmsg(target, text):
			if irc.client.is_channel(target):
				username = config["username"]
				text = utils.trim_length(text, do_warn=True)
				chatlog.log_chat(irc.client.Event("pubmsg", username, target, [text]), SELF_METADATA)
				original_privmsg(target, text)
			elif self.whisperconn:
				self.whisperconn.whisper(target, text)
			else:
				log.info("Not sending private message to %s: %s", target, text)
コード例 #2
0
ファイル: live.py プロジェクト: andreasots/lrrbot
async def live(lrrbot, conn, event, respond_to):
	"""
	Command: !live

	Post the currenly live fanstreamers.
	"""

	try:
		await extract_new_channels(lrrbot.loop)
	except urllib.error.HTTPError:
		pass

	streams = await twitch.get_streams_followed()
	if streams == []:
		return conn.privmsg(respond_to, "No fanstreamers currently live.")

	streams.sort(key=lambda e: e["channel"]["display_name"])

	tag = "Currently live fanstreamers: "

	# Full message
	message = tag + ", ".join([
		"%s (%s%s)%s%s" % (
			data["channel"]["display_name"],
			data["channel"]["url"],
			space.SPACE,
			" is playing %s" % data["game"] if data.get("game") is not None else "",
			" (%s)" % data["channel"]["status"] if data["channel"].get("status") not in [None, ""] else ""
		) for data in streams
	])
	if utils.check_length(message):
		return conn.privmsg(respond_to, message)

	# Shorter message
	message = tag + ", ".join([
		"%s (%s%s)%s" % (
			data["channel"]["display_name"],
			data["channel"]["url"],
			space.SPACE,
			" is playing %s" % data["game"] if data.get("game") is not None else "",
		) for data in streams
	])
	if utils.check_length(message):
		return conn.privmsg(respond_to, message)

	# Shortest message
	message = tag + ", ".join([
		"%s (%s%s)" % (
			data["channel"]["display_name"],
			data["channel"]["url"],
			space.SPACE
		) for data in streams
	])
	return conn.privmsg(respond_to, utils.trim_length(message))
コード例 #3
0
ファイル: main.py プロジェクト: Feriority/lrrbot
 def new_privmsg(target, text):
     if irc.client.is_channel(target):
         username = config["username"]
         text = utils.trim_length(text, do_warn=True)
         chatlog.log_chat(
             irc.client.Event("pubmsg", username, target, [text]),
             SELF_METADATA)
         original_privmsg(target, text)
     elif self.whisperconn:
         self.whisperconn.whisper(target, text)
     else:
         log.info("Not sending private message to %s: %s", target, text)
コード例 #4
0
ファイル: strawpoll.py プロジェクト: andreasots/lrrbot
async def report_poll(conn, poll_id, respond_to, tag):
	url = "https://www.strawpoll.me/api/v2/polls/%s" % poll_id
	data = json.loads(await common.http.request_coro(url))
	options = sorted(zip(data["options"], data["votes"]), key=lambda e: (e[1], random.random()), reverse=True)
	options = "; ".join(map(strawpoll_format, enumerate(options)))
	response = "Poll complete: %s: %s" % (html.unescape(data["title"]), options)
	response = utils.trim_length(response)
	conn.privmsg(respond_to, response)

	if tag is not None:
		data['tag'] = tag
	await common.rpc.eventserver.event('strawpoll-complete', data)
コード例 #5
0
ファイル: live.py プロジェクト: d3fr0st/lrrbot
async def live(lrrbot, conn, event, respond_to):
    """
	Command: !live

	Post the currenly live fanstreamers.
	"""

    try:
        await extract_new_channels(lrrbot.loop)
    except urllib.error.HTTPError:
        pass

    streams = await twitch.get_streams_followed()
    if streams == []:
        return conn.privmsg(respond_to, "No fanstreamers currently live.")

    streams.sort(key=lambda e: e["channel"]["display_name"])

    tag = "Currently live fanstreamers: "

    # Full message
    message = tag + ", ".join([
        "%s (%s%s)%s%s" %
        (data["channel"]["display_name"], data["channel"]["url"], space.SPACE,
         " is playing %s" % data["game"] if data.get("game") is not None else
         "", " (%s)" % data["channel"]["status"]
         if data["channel"].get("status") not in [None, ""] else "")
        for data in streams
    ])
    if utils.check_length(message):
        return conn.privmsg(respond_to, message)

    # Shorter message
    message = tag + ", ".join([
        "%s (%s%s)%s" % (
            data["channel"]["display_name"],
            data["channel"]["url"],
            space.SPACE,
            " is playing %s" %
            data["game"] if data.get("game") is not None else "",
        ) for data in streams
    ])
    if utils.check_length(message):
        return conn.privmsg(respond_to, message)

    # Shortest message
    message = tag + ", ".join([
        "%s (%s%s)" %
        (data["channel"]["display_name"], data["channel"]["url"], space.SPACE)
        for data in streams
    ])
    return conn.privmsg(respond_to, utils.trim_length(message))
コード例 #6
0
ファイル: strawpoll.py プロジェクト: andreasots/lrrbot
def polls(lrrbot, conn, event, respond_to):
	"""
	Command: !polls
	Section: misc

	List all currently active polls.
	"""
	if not lrrbot.polls:
		return conn.privmsg(respond_to, "No active polls.")
	now = time.time()
	messages = []
	for end, title, poll_id, respond_to, tag in lrrbot.polls:
		messages += ["%s (https://www.strawpoll.me/%s%s): %s from now" % (title, poll_id, space.SPACE, common.time.nice_duration(end - now, 1))]
	conn.privmsg(respond_to, utils.trim_length("Active polls: "+"; ".join(messages)))
コード例 #7
0
def process_card(card, expansion, houses, include_reminder=False):
    # sanitise card name
    filtered = clean_text(card.get('internalname', card["card_title"]))
    if not re_check.match(filtered):
        print("Still some junk left in name %s (%s)" % (card.get(
            'internalname', card["card_title"]), json.dumps(filtered)))
        print(json.dumps(card))
        sys.exit(1)

    def build_description():
        yield card['card_title']
        yield ' ['
        if card.get('is_anomaly'):
            yield "Anomaly"
        elif card['house'] in houses:
            yield houses[card['house']]['name']
        else:
            yield card['house']
        if card.get('amber'):
            yield '\u2014'
            yield str(card['amber'])
            yield '<A>'
        yield '] | '
        yield card['card_type']
        if card.get('traits'):
            yield ' \u2014 '
            yield card['traits']
        if card['card_type'] == "Creature":
            yield ' ['
            yield str(card['power'])
            if card.get('armor'):
                yield '/'
                yield str(card['armor'])
            yield ']'
        if card.get('card_text'):
            yield ' | '
            yield process_text(card['card_text'], include_reminder)

    desc = ''.join(build_description())
    desc = re_multiplespaces.sub(' ', desc).strip()
    desc = utils.trim_length(desc)

    numbers = card['card_number'] if card.get('card_number') else []
    if not isinstance(numbers, list):
        numbers = [numbers]
    numbers = [(expansion['code'].lower(), str(i)) for i in numbers]
    hidden = 'internalname' in card

    return filtered, card['card_title'], desc, numbers, hidden
コード例 #8
0
async def report_poll(conn, poll_id, respond_to, tag):
    url = "https://www.strawpoll.me/api/v2/polls/%s" % poll_id
    data = json.loads(await common.http.request_coro(url))
    options = sorted(zip(data["options"], data["votes"]),
                     key=lambda e: (e[1], random.random()),
                     reverse=True)
    options = "; ".join(map(strawpoll_format, enumerate(options)))
    response = "Poll complete: %s: %s" % (html.unescape(
        data["title"]), options)
    response = utils.trim_length(response)
    conn.privmsg(respond_to, response)

    if tag is not None:
        data['tag'] = tag
    await common.rpc.eventserver.event('strawpoll-complete', data)
コード例 #9
0
def process_card(card, expansion, houses, include_reminder=False):
	# sanitise card name
	filtered = clean_text(card.get('internalname', card["card_title"]))
	if not re_check.match(filtered):
		print("Still some junk left in name %s (%s)" % (card.get('internalname', card["card_title"]), json.dumps(filtered)))
		print(json.dumps(card))
		sys.exit(1)

	def build_description():
		yield card['card_title']
		yield ' ['
		if card['house'] in houses:
			yield houses[card['house']]['name']
		else:
			yield card['house']
		if card.get('amber'):
			yield '\u2014'
			yield str(card['amber'])
			yield '<A>'
		yield '] | '
		yield card['card_type']
		if card.get('traits'):
			yield ' \u2014 '
			yield card['traits']
		if card.get('power') or card.get('armor') or card['card_type'] == "Creature":
			yield ' ['
			yield str(card['power'])
			if card.get('armor'):
				yield '/'
				yield str(card['armor'])
			yield ']'
		if card.get('card_text'):
			yield ' | '
			yield process_text(card['card_text'], include_reminder)

	desc = ''.join(build_description())
	desc = re_multiplespaces.sub(' ', desc).strip()
	desc = utils.trim_length(desc)

	numbers = card['card_number'] if card.get('card_number') else []
	if not isinstance(numbers, list):
		numbers = [numbers]
	numbers = [(expansion['code'].lower(), str(i)) for i in numbers]
	hidden = 'internalname' in card

	return filtered, card['card_title'], desc, numbers, hidden
コード例 #10
0
def polls(lrrbot, conn, event, respond_to):
    """
	Command: !polls
	Section: misc

	List all currently active polls.
	"""
    if not lrrbot.polls:
        return conn.privmsg(respond_to, "No active polls.")
    now = time.time()
    messages = []
    for end, title, poll_id, respond_to, tag in lrrbot.polls:
        messages += [
            "%s (https://www.strawpoll.me/%s%s): %s from now" %
            (title, poll_id, space.SPACE,
             common.time.nice_duration(end - now, 1))
        ]
    conn.privmsg(respond_to,
                 utils.trim_length("Active polls: " + "; ".join(messages)))
コード例 #11
0
ファイル: build_carddb.py プロジェクト: andreasots/lrrbot
def process_single_card(card, expansion, include_reminder=False):
	# sanitise card name
	filtered = clean_text(card.get('internalname', card["name"]))
	if not re_check.match(filtered):
		print("Still some junk left in name %s (%s)" % (card.get('internalname', card["name"]), json.dumps(filtered)))
		print(json.dumps(card))
		sys.exit(1)

	def build_description():
		yield card['name']
		if 'manaCost' in card:
			yield ' ['
			yield re_mana.sub(r"\1", card['manaCost'])
			yield ']'
		if card.get('layout') == 'flip':
			if card['name'] == card['names'][0]:
				yield ' (flip: '
				yield card['names'][1]
				yield ')'
			else:
				yield ' (unflip: '
				yield card['names'][0]
				yield ')'
		elif card.get('layout') == 'transform':
			if card['name'] == card['names'][0]:
				yield ' (back: '
				yield card['names'][1]
				yield ')'
			else:
				yield ' (front: '
				yield card['names'][0]
				yield ')'
		elif card.get('layout') == 'meld':
			card_a, melded_card, card_b = card['names']
			if card['name'] in (card_a, card_b):
				# mtgjson is inconsistent as to which of these is which
				# check if "melds with cardname" is in the card text
				if card['name'] == card_a:
					other_card = card_b
				else:
					other_card = card_a
				if '(Melds with %s.)' % other_card in card['text']:
					yield ' (melds with: '
					yield other_card
					yield '; into: '
					yield melded_card
					yield ')'
				else:
					# The names of what this melds with and into are in the rules text
					pass
			elif card['name'] == melded_card:
				yield ' (melds from: '
				yield card_a
				yield '; '
				yield card_b
				yield ')'
		yield ' | '
		yield card.get('type', '?Type missing?')
		if 'power' in card or 'toughness' in card:
			yield ' ['
			yield card.get('power', '?')
			yield '/'
			yield card.get('toughness', '?')
			yield ']'
		if 'loyalty' in card:
			yield ' ['
			yield str(card['loyalty'])
			yield ']'
		if 'hand' in card or 'life' in card:
			yield ' [hand: '
			if 'hand' in card:
				yield card['hand']
			else:
				yield "?"
			yield ', life: '
			if 'life' in card:
				yield card['life']
			else:
				yield "?"
			yield ']'
		if 'text' in card:
			yield ' | '
			yield process_text(card['text'], include_reminder)

	desc = ''.join(build_description())
	desc = re_multiplespaces.sub(' ', desc).strip()
	desc = utils.trim_length(desc)

	if card.get('layout') == 'flip' and card['name'] != card['names'][0]:
		multiverseids = numbers = []
	else:
		if card.get('layout') == 'transform':
			if card['name'] == card['names'][0]:
				if card.get('number') and 'a' not in card['number'] and 'b' not in card['number']:
					card['number'] = [card['number'], card['number'] + 'a']
			else:
				if card.get('number') and 'a' not in card['number'] and 'b' not in card['number']:
					card['number'] = card['number'] + 'b'
				card['foreignData'] = []  # mtgjson doesn't seem to have accurate foreign multiverse ids for back faces
		multiverseids = [card['multiverseId']] if card.get('multiverseId') else []
		# disabling adding foreign multiverse ids unless we decide we want them for some reason
		# they add a lot of time to the running of this script
		#for lang in card.get('foreignData', []):
		#	if lang.get('multiverseId'):
		#		multiverseids.append(lang['multiverseId'])
		numbers = card['number'] if card.get('number') else []
		if not isinstance(numbers, list):
			numbers = [numbers]
	hidden = 'internalname' in card

	# if a card has multiple variants, make "number" entries for the variants
	# to match what sort of thing we'd be seeing on scryfall
	if len(multiverseids) > 1 and len(numbers) == 1:
		orig_number = numbers[0]
		for i in range(len(multiverseids)):
			numbers.append(orig_number + chr(ord('a') + i))

	numbers = [(expansion['code'].lower(), i) for i in numbers]

	return filtered, card['name'], desc, multiverseids, numbers, hidden
コード例 #12
0
def process_single_card(card, expansion, include_reminder=False):
    # sanitise card name
    filtered = clean_text(card.get('internalname', card["name"]))
    if not re_check.match(filtered):
        print("Still some junk left in name %s (%s)" %
              (card.get('internalname', card["name"]), json.dumps(filtered)))
        print(json.dumps(card))
        sys.exit(1)

    def build_description():
        yield card['name']
        if 'manaCost' in card:
            yield ' ['
            yield re_mana.sub(r"\1", card['manaCost'])
            yield ']'
        if card.get('layout') == 'flip':
            if card['name'] == card['names'][0]:
                yield ' (flip: '
                yield card['names'][1]
                yield ')'
            else:
                yield ' (unflip: '
                yield card['names'][0]
                yield ')'
        elif card.get('layout') == 'transform':
            if card['name'] == card['names'][0]:
                yield ' (back: '
                yield card['names'][1]
                yield ')'
            else:
                yield ' (front: '
                yield card['names'][0]
                yield ')'
        elif card.get('layout') == 'meld':
            card_a, melded_card, card_b = card['names']
            if card['name'] in (card_a, card_b):
                # mtgjson is inconsistent as to which of these is which
                # check if "melds with cardname" is in the card text
                if card['name'] == card_a:
                    other_card = card_b
                else:
                    other_card = card_a
                if '(Melds with %s.)' % other_card in card['text']:
                    yield ' (melds with: '
                    yield other_card
                    yield '; into: '
                    yield melded_card
                    yield ')'
                else:
                    # The names of what this melds with and into are in the rules text
                    pass
            elif card['name'] == melded_card:
                yield ' (melds from: '
                yield card_a
                yield '; '
                yield card_b
                yield ')'
        yield ' | '
        yield card.get('type', '?Type missing?')
        if 'power' in card or 'toughness' in card:
            yield ' ['
            yield card.get('power', '?')
            yield '/'
            yield card.get('toughness', '?')
            yield ']'
        if 'loyalty' in card:
            yield ' ['
            yield str(card['loyalty'])
            yield ']'
        if 'hand' in card or 'life' in card:
            yield ' [hand: '
            if 'hand' in card:
                yield card['hand']
            else:
                yield "?"
            yield ', life: '
            if 'life' in card:
                yield card['life']
            else:
                yield "?"
            yield ']'
        if 'text' in card:
            yield ' | '
            yield process_text(card['text'], include_reminder)

    desc = ''.join(build_description())
    desc = re_multiplespaces.sub(' ', desc).strip()
    desc = utils.trim_length(desc)

    if card.get('layout') == 'flip' and card['name'] != card['names'][0]:
        multiverseids = numbers = []
    else:
        if card.get('layout') == 'transform':
            if card['name'] == card['names'][0]:
                if card.get('number') and 'a' not in card[
                        'number'] and 'b' not in card['number']:
                    card['number'] = [card['number'], card['number'] + 'a']
            else:
                if card.get('number') and 'a' not in card[
                        'number'] and 'b' not in card['number']:
                    card['number'] = card['number'] + 'b'
                card['foreignData'] = [
                ]  # mtgjson doesn't seem to have accurate foreign multiverse ids for back faces
        multiverseids = [card['multiverseId']
                         ] if card.get('multiverseId') else []
        # disabling adding foreign multiverse ids unless we decide we want them for some reason
        # they add a lot of time to the running of this script
        #for lang in card.get('foreignData', []):
        #	if lang.get('multiverseId'):
        #		multiverseids.append(lang['multiverseId'])
        numbers = card['number'] if card.get('number') else []
        if not isinstance(numbers, list):
            numbers = [numbers]
    hidden = 'internalname' in card

    # if a card has multiple variants, make "number" entries for the variants
    # to match what sort of thing we'd be seeing on scryfall
    if len(multiverseids) > 1 and len(numbers) == 1:
        orig_number = numbers[0]
        for i in range(len(multiverseids)):
            numbers.append(orig_number + chr(ord('a') + i))

    numbers = [(expansion['code'].lower(), i) for i in numbers]

    return filtered, card['name'], desc, multiverseids, numbers, hidden
コード例 #13
0
def process_single_card(card, expansion, include_reminder=False):
    # sanitise card name
    filtered = clean_text(card.get('internalname', card["name"]))
    if not re_check.match(filtered):
        print("Still some junk left in name %s (%s)" %
              (card.get('internalname', card["name"]), json.dumps(filtered)))
        print(json.dumps(card))
        sys.exit(1)

    def build_description():
        yield card['name']
        if 'manaCost' in card:
            yield ' ['
            yield re_mana.sub(r"\1", card['manaCost'])
            yield ']'
        if card.get('layout') == 'flip':
            if card['name'] == card['names'][0]:
                yield ' (flip: '
                yield card['names'][1]
                yield ')'
            else:
                yield ' (unflip: '
                yield card['names'][0]
                yield ')'
        elif card.get('layout') == 'double-faced':
            if card['name'] == card['names'][0]:
                yield ' (back: '
                yield card['names'][1]
                yield ')'
            else:
                yield ' (front: '
                yield card['names'][0]
                yield ')'
        elif card.get('layout') == 'meld':
            top_card, bottom_card, melded_card = card['names']
            if card['name'] == top_card:
                # The names of what this melds with and into are in the card text
                pass
            elif card['name'] == bottom_card:
                yield ' (melds with: '
                yield top_card
                yield '; into: '
                yield melded_card
                yield ')'
            elif card['name'] == melded_card:
                yield ' (melds from: '
                yield top_card
                yield '; '
                yield bottom_card
                yield ')'
        yield ' | '
        yield card.get('type', '?Type missing?')
        if 'power' in card or 'toughness' in card:
            yield ' ['
            yield card.get('power', '?')
            yield '/'
            yield card.get('toughness', '?')
            yield ']'
        if 'loyalty' in card:
            yield ' ['
            yield str(card['loyalty'])
            yield ']'
        if 'hand' in card or 'life' in card:
            yield ' [hand: '
            if 'hand' in card:
                yield "%+d" % card['hand']
            else:
                yield "?"
            yield ', life: '
            if 'life' in card:
                yield "%+d" % card['life']
            else:
                yield "?"
            yield ']'
        if 'text' in card:
            yield ' | '
            text = card['text']
            # Let Un-set cards keep their reminder text, since there's joeks in there
            if not include_reminder:
                text = re_remindertext.sub(
                    lambda match: ' '
                    if match.group(1) and match.group(2) else '', text)
            yield re_newlines.sub(' / ', text.strip())

    desc = ''.join(build_description())
    desc = re_multiplespaces.sub(' ', desc).strip()
    desc = utils.trim_length(desc)

    if card.get('layout') == 'flip' and card['name'] != card['names'][0]:
        multiverseids = numbers = []
    else:
        multiverseids = [card['multiverseid']
                         ] if card.get('multiverseid') else []
        if card.get('variations'):
            multiverseids.extend(card['variations'])
        numbers = card['number'] if card.get('number') else []
        if not isinstance(numbers, list):
            numbers = [numbers]
    hidden = 'internalname' in card

    # if a card has multiple variants, make "number" entries for the variants
    # to match what sort of thing we'd be seeing on scryfall
    if len(multiverseids) > 1 and len(numbers) == 1:
        orig_number = numbers[0]
        for i in range(len(multiverseids)):
            numbers.append(orig_number + chr(ord('a') + i))

    numbers = [(expansion['code'].lower(), i) for i in numbers]

    return filtered, card['name'], desc, multiverseids, numbers, hidden
コード例 #14
0
ファイル: googlecalendar.py プロジェクト: d3fr0st/lrrbot
def get_next_event_text(calendar, after=None, include_current=None, tz=None, verbose=True):
	"""
	Build the actual human-readable response to the !next command.

	The tz parameter can override the timezone used to display the event times.
	This can be an actual timezone object, or a string timezone name.
	Defaults to moonbase time.
	"""
	if after is None:
		after = datetime.datetime.now(datetime.timezone.utc)
	if not tz:
		tz = config['timezone']
	elif isinstance(tz, str):
		tz = tz.strip()
		try:
			tz = common.time.get_timezone(tz)
		except pytz.exceptions.UnknownTimeZoneError:
			return "Unknown timezone: %s" % tz

	events = get_next_event(calendar, after=after, include_current=include_current)
	if not events:
		return "There don't seem to be any upcoming scheduled streams"

	concise_strs = []
	verbose_strs = []
	for i, ev in enumerate(events):
		title = ev['title']
		if ev['location'] is not None:
			title += " (%(location)s%(space)s)" % {
				"location": ev["location"],
				"space": space.SPACE,
			}
		concise_title = title
		if ev['description'] is not None:
			title += " (%(description)s)" % {
				"description": textwrap.shorten(process_description(ev['description']), 200),
			}
		# If several events are at the same time, just show the time once after all of them
		if i == len(events) - 1 or ev['start'] != events[i+1]['start']:
			if verbose:
				if ev['start'] < after:
					nice_duration = common.time.nice_duration(after - ev['start'], 1) + " ago"
				else:
					nice_duration = common.time.nice_duration(ev['start'] - after, 1) + " from now"
				start = ev['start'].astimezone(tz).strftime(DISPLAY_FORMAT)
				concise_strs.append("%s at %s (%s)" % (concise_title, start, nice_duration))
				verbose_strs.append("%s at %s (%s)" % (title, start, nice_duration))
			else:
				concise_strs.append("%s at %s" % (ev['title'], ev['start'].astimezone(tz).strftime(DISPLAY_FORMAT)))
		else:
			concise_strs.append(concise_title if verbose else ev['title'])
			verbose_strs.append(title)

	if verbose:
		for strs in [verbose_strs, concise_strs]:
			if calendar == CALENDAR_LRL:
				response = "Next scheduled stream: %s." % ", ".join(strs)
			elif calendar == CALENDAR_FAN:
				response = "Next scheduled fan stream: %s." % ", ".join(strs)

			if utils.check_length(response):
				break
	else:
		response = ", ".join(concise_strs)

	return utils.trim_length(response) # For safety