async def check_reminders(bot, async_call, db): current_time = datetime.now() for reminder in reminder_cache: network, remind_time, added_time, user, message = reminder if remind_time <= current_time: if network not in bot.connections: # connection is invalid continue conn = bot.connections[network] if not conn.ready: return remind_text = colors.parse(time_since(added_time, count=2)) alert = colors.parse( "{}, you have a reminder from $(b){}$(clear) ago!".format( user, remind_text)) conn.message(user, alert) conn.message(user, '"{}"'.format(message)) delta = current_time - remind_time if delta > timedelta(minutes=30): late_time = time_since(remind_time, count=2) late = "(I'm sorry for delivering this message $(b){}$(clear) late," \ " it seems I was unable to deliver it on time)".format(late_time) conn.message(user, colors.parse(late)) await delete_reminder(async_call, db, network, remind_time, user) await load_cache(async_call, db)
def check_reminders(bot, async_call, db): current_time = datetime.now() for reminder in reminder_cache: network, remind_time, added_time, user, message = reminder if remind_time <= current_time: if network not in bot.connections: # connection is invalid yield from add_reminder(async_call, db, network, remind_time, user) yield from load_cache(async_call, db) continue conn = bot.connections[network] if not conn.ready: return remind_text = colors.parse(time_since(added_time, count=2)) alert = colors.parse("{}, you have a reminder from $(b){}$(clear) ago!".format(user, remind_text)) conn.message(user, alert) conn.message(user, '"{}"'.format(message)) delta = (remind_time-added_time).seconds if delta > (30*60): late_time = time_since(remind_time, count=2) late = "(I'm sorry for delivering this message $(b){}$(clear) late," \ " it seems I was unable to deliver it on time)".format(late_time) conn.message(user, colors.parse(late)) yield from delete_reminder(async_call, db, network, remind_time, user) yield from load_cache(async_call, db)
def check_reminders(bot, async_call, db): current_time = datetime.now() for reminder in reminder_cache: network, user, added_time, added_chan, message, remind_time = reminder if remind_time <= current_time: if network not in bot.connections: # connection is invalid yield from add_reminder(async_call, db, network, user, added_chan, message, remind_time, added_time) yield from load_cache(async_call, db) continue conn = bot.connections[network] if not conn.ready: return remind_text = time_since(added_time, count=2) alert = "{}, you have a reminder from $(b){}$(b) ago!".format(user, remind_text) conn.message(user, alert) conn.message(user, '"{}"'.format(message)) delta = (remind_time - added_time).seconds if delta > (30 * 60): late_time = time_since(remind_time, count=2) late = "(I'm sorry for delivering this message $(b){}$(b) late," \ " it seems I was unable to deliver it on time)".format(late_time) conn.message(user, late) yield from delete_reminder(async_call, db, network, remind_time, user) yield from load_cache(async_call, db)
def test_timesince(): then = datetime(2010, 4, 12, 12, 30, 0) then_timestamp = 1271075400.0 then_future = datetime(2012, 4, 12, 12, 30, 0) now = datetime(2010, 5, 15, 1, 50, 0) now_timestamp = 1273888200.0 # timestamp assert time_since(then_timestamp, now_timestamp) == "1 month and 2 days" # basic assert time_since(then, now) == "1 month and 2 days" # count assert time_since(then, now, count=3) == "1 month, 2 days and 13 hours" # future assert time_since(then_future, now) == "0 minutes"
def tellinput(event, conn, db, nick, notice): """ :type event: cloudbot.event.Event :type conn: cloudbot.client.Client :type db: sqlalchemy.orm.Session """ if 'showtells' in event.content.lower(): return if tell_check(conn.name, nick): tells = get_unread(db, conn.name, nick) else: return if tells: user_from, message, time_sent = tells[0] reltime = timeformat.time_since(time_sent) if reltime == 0: reltime_formatted = "just a moment" else: reltime_formatted = reltime reply = "{} sent you a message {} ago: {}".format(user_from, reltime_formatted, message) if len(tells) > 1: reply += " (+{} more, {}showtells to view)".format(len(tells) - 1, conn.config["command_prefix"]) read_tell(db, conn.name, nick, message) notice(reply)
def seen(text, nick, chan, db, event, is_nick_valid): """<nick> <channel> - tells when a nickname was last in active in one of my channels :type db: sqlalchemy.orm.Session :type event: cloudbot.event.Event """ if event.conn.nick.lower() == text.lower(): return "You need to get your eyes checked." if text.lower() == nick.lower(): return "Have you looked in a mirror lately?" if not is_nick_valid(text): return "I can't look up that name, its impossible to use!" last_seen = db.execute( select([table.c.name, table.c.time, table.c.quote]).where( and_(table.c.name == text.lower(), table.c.chan == chan))).fetchone() if last_seen: reltime = timeformat.time_since(last_seen[1]) if last_seen[2][0:1] == "\x01": return '{} was last seen {} ago: * {} {}'.format( text, reltime, text, last_seen[2][8:-1]) return '{} was last seen {} ago saying: {}'.format( text, reltime, last_seen[2]) return "I've never seen {} talking in this channel.".format(text)
def format_output(item, show_url=False): """ takes a voat post and returns a formatted string """ if not item["Title"]: item["Title"] = formatting.truncate(item["Linkdescription"], 70) else: item["Title"] = formatting.truncate(item["Title"], 70) item["link"] = voat_fill_url.format(item["Subverse"], item["Id"]) raw_time = isodate.parse_date(item["Date"]) item["timesince"] = timeformat.time_since(raw_time, count=1, simple=True) item["comments"] = formatting.pluralize(item["CommentCount"], "comment") item["points"] = formatting.pluralize(item["Likes"], "point") if item["Type"] == 2: item["warning"] = " \x02Link\x02" else: item["warning"] = "" if show_url: return ( "\x02{Title} : {Subverse}\x02 - {comments}, {points}" " - \x02{Name}\x02 {timesince} ago - {link}{warning}".format(**item) ) else: return ( "\x02{Title} : {Subverse}\x02 - {comments}, {points}" " - \x02{Name}\x02, {timesince} ago{warning}".format(**item) )
def twitter_url(match): # Find the tweet ID from the URL tweet_id = match.group(1) # Get the tweet using the tweepy API if tw_api is None: return try: tweet = tw_api.get_status(tweet_id) user = tweet.user except tweepy.error.TweepError: return # Format the return the text of the tweet text = " ".join(tweet.text.split()) if user.verified: prefix = "\u2713" else: prefix = "" time = timeformat.time_since(tweet.created_at, datetime.utcnow()) return "{}@\x02{}\x02 ({}): {} ({} ago)".format(prefix, user.screen_name, user.name, text, time)
def tellinput(event, conn, db, nick, notice): """ :type event: cloudbot.event.Event :type conn: cloudbot.client.Client :type db: sqlalchemy.orm.Session """ if 'showtells' in event.content.lower(): return if tell_check(conn.name, nick): tells = get_unread(db, conn.name, nick) else: return if tells: user_from, message, time_sent = tells[0] reltime = timeformat.time_since(time_sent) if reltime == 0: reltime_formatted = "just a moment" else: reltime_formatted = reltime reply = "{} sent you a message {} ago: {}".format( user_from, reltime_formatted, message) if len(tells) > 1: reply += " (+{} more, {}showtells to view)".format( len(tells) - 1, conn.config["command_prefix"]) read_tell(db, conn.name, nick, message) notice(reply)
def seen(text, nick, chan, db, event, conn): """<nick> <channel> - tells when a nickname was last in active in one of my channels :type db: sqlalchemy.orm.Session :type event: cloudbot.event.Event :type conn: cloudbot.client.Client """ if event.conn.nick.lower() == text.lower(): return "You need to get your eyes checked." if text.lower() == nick.lower(): return "Have you looked in a mirror lately?" if not re.match("^[A-Za-z0-9_|\^\*\`.\-\]\[\{\}\\\\]*$", text.lower()): return "I can't look up that name, its impossible to use!" db_init(db, conn.name) if '_' in text: text = text.replace("_", "/_") last_seen = db.execute("select name, time, quote from seen_user where name like :name escape '/' and chan = :chan", {'name': text, 'chan': chan}).fetchone() if last_seen: reltime = timeformat.time_since(last_seen[1]) if last_seen[0] != text.lower(): # for glob matching text = last_seen[0] if last_seen[2][0:1] == "\x01": return '{} was last seen {} ago: * {} {}'.format(text, reltime, text, last_seen[2][8:-1]) else: return '{} was last seen {} ago saying: {}'.format(text, reltime, last_seen[2]) else: return "I've never seen {} talking in this channel.".format(text)
def tell_watch(event, conn, db, chan, nick, ctcp, reply): """ :type event: cloudbot.event.Event :type conn: cloudbot.client.Client :type db: sqlalchemy.orm.Session """ if tell_check(conn.name, nick): tells = get_unread(db, conn.name, nick, chan) else: return sent = 0 ratelimit = 5 for _from, _channel, _message, _sent in tells: # format the send time reltime = timeformat.time_since(_sent, simple=True, count=1) if reltime == 0: reltime = "just now" else: reltime += " ago" out = "[{}, {}] {}".format(_from, reltime, _message) read_tell(db, conn.name, _channel, nick, _message) if sent < ratelimit: reply(out) else: if sent == ratelimit + 1: reply( "{} more tells sent privately.".format(len(tells) - sent)) ctcp(out) sent += 1
def seen(text, nick, chan, db, event, conn): """<nick> <channel> - tells when a nickname was last in active in one of my channels :type db: sqlalchemy.orm.Session :type event: cloudbot.event.Event :type conn: cloudbot.client.Client """ if event.conn.nick.lower() == text.lower(): return "You need to get your eyes checked." if text.lower() == nick.lower(): return "Have you looked in a mirror lately?" if not re.match("^[A-Za-z0-9_|.\-\]\[]*$", text.lower()): return "I can't look up that name, its impossible to use!" db_init(db, conn.name) last_seen = db.execute("select name, time, quote from seen_user where name like :name and chan = :chan", {'name': text, 'chan': chan}).fetchone() if last_seen: reltime = timeformat.time_since(last_seen[1]) if last_seen[0] != text.lower(): # for glob matching text = last_seen[0] if last_seen[2][0:1] == "\x01": return '{} was last seen {} ago: * {} {}'.format(text, reltime, text, last_seen[2][8:-1]) else: return '{} was last seen {} ago saying: {}'.format(text, reltime, last_seen[2]) else: return "I've never seen {} talking in this channel.".format(text)
def format_output(item, show_url=False): """ takes a reddit post and returns a formatted string """ item["title"] = formatting.truncate(item["title"], 70) item["link"] = short_url.format(item["id"]) raw_time = datetime.fromtimestamp(int(item["created_utc"])) item["timesince"] = timeformat.time_since(raw_time, count=1, simple=True) item["comments"] = formatting.pluralize_auto(item["num_comments"], 'comment') item["points"] = formatting.pluralize_auto(item["score"], 'point') if item["over_18"]: item["warning"] = colors.parse(" $(b, red)NSFW$(clear)") else: item["warning"] = "" if show_url: item["url"] = " - " + item["link"] else: item["url"] = "" return colors.parse( "$(b){title} : {subreddit}$(b) - {comments}, {points}" " - $(b){author}$(b) {timesince} ago{url}{warning}").format(**item)
def pre(text): """pre <query> -- searches scene releases using pre.corrupt.org""" try: headers = {'Accept-Language': 'en-US'} request = requests.get("https://pre.corrupt-net.org/search.php", params={"search": text}, headers=headers) request.raise_for_status() except requests.exceptions.HTTPError as e: return 'Unable to fetch results: {}'.format(e) split = request.text.partition('</tr><tr>') results = re.search("<tr><td id\=\"rlstype\".*>(.*)</td><td.*> (.*)<span id\=\"rlsgroup\"><font color\='#C0C0C0'>(.*)</font>.*>(\d*F).*>([\d\.]*M).* (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})</td>", split[0], flags=re.IGNORECASE) if results is None: return "No results found." date = results.group(6) section = results.group(1) name = results.group(2) + results.group(3) size = results.group(5) files = results.group(4) # parse date/time date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S") date_string = date.strftime("%d %b %Y") since = timeformat.time_since(date) return '{} - {} - {} - {} - {} ({} ago)'.format(section, name, size, files, date_string, since)
def pre(text, reply): """<query> - searches scene releases using orlydb.com""" try: request = requests.get("https://pre.corrupt-net.org/search.php", params={"search": text}, headers=HEADERS, timeout=30.0) request.raise_for_status() except requests.exceptions.HTTPError as e: reply('Unable to fetch results: {}'.format(e)) raise request.close() html = BeautifulSoup(request.text, "lxml") cols = html.find_all("td", limit=5) if len(cols) < 2 or cols[0].text.strip().startswith("Nothing found"): return "No results" #section = cols[0].text.strip() name = cols[1].text.strip() files = cols[2].text.strip().replace("F", " files") size = cols[3].text.strip() + "iB" date = cols[4].text.strip() + "UTC" # parse date/time date = datetime.strptime(date, "%Y-%m-%d %H:%M:%S%Z") since = timeformat.time_since(date, datetime.utcnow(), simple=True) return '{} [div] {} [div] {} [div] {} ({} ago)'.format(name, size, files, date, since)
def format_output(item, show_url=False): """ takes a reddit post and returns a formatted string """ item["title"] = formatting.truncate(item["title"], 70) item["link"] = short_url.format(item["id"]) raw_time = datetime.fromtimestamp(int(item["created_utc"])) item["timesince"] = timeformat.time_since(raw_time, count=1, simple=True) item["comments"] = formatting.pluralize(item["num_comments"], "comment") item["points"] = formatting.pluralize(item["score"], "point") if item["over_18"]: item["warning"] = " \x02NSFW\x02" else: item["warning"] = "" if show_url: return ( "\x02{title} : {subreddit}\x02 - {comments}, {points}" " - \x02{author}\x02 {timesince} ago - {link}{warning}".format(**item) ) else: return ( "\x02{title} : {subreddit}\x02 - {comments}, {points}" " - \x02{author}\x02, {timesince} ago{warning}".format(**item) )
def tell_watch(event, conn, db, chan, nick, ctcp, reply): """ :type event: cloudbot.event.Event :type conn: cloudbot.client.Client :type db: sqlalchemy.orm.Session """ if tell_check(conn.name, nick): tells = get_unread(db, conn.name, nick, chan) else: return sent = 0 ratelimit = 5 for _from, _channel, _message, _sent in tells: # format the send time reltime = timeformat.time_since(_sent, simple=True, count=1) if reltime == 0: reltime = "just now" else: reltime += " ago" out = "[{}, {}] {}".format(_from, reltime, _message) read_tell(db, conn.name, _channel, nick, _message) if sent < ratelimit: reply(out) else: if sent == ratelimit + 1: reply("{} more tells sent privately.".format(len(tells) - sent)) ctcp(out) sent += 1
def pre(text): """pre <query> -- searches scene releases using pre.corrupt.org""" try: headers = {'Accept-Language': 'en-US'} request = requests.get("https://pre.corrupt-net.org/search.php", params={"search": text}, headers=headers) request.raise_for_status() except requests.exceptions.HTTPError as e: return 'Unable to fetch results: {}'.format(e) split = request.text.partition('</tr><tr>') results = re.search( "<tr><td id\=\"rlstype\".*>(.*)</td><td.*> (.*)<span id\=\"rlsgroup\"><font color\='#C0C0C0'>(.*)</font>.*>(\d*F).*>([\d\.]*M).* (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})</td>", split[0], flags=re.IGNORECASE) if results is None: return "No results found." date = results.group(6) section = results.group(1) name = results.group(2) + results.group(3) size = results.group(5) files = results.group(4) # parse date/time date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S") date_string = date.strftime("%d %b %Y") since = timeformat.time_since(date) return '{} - {} - {} - {} - {} ({} ago)'.format(section, name, size, files, date_string, since)
def pre(text): """pre <query> -- searches scene releases using orlydb.com""" try: request = requests.get("http://orlydb.com/", params={"q": text}) request.raise_for_status() except requests.exceptions.HTTPError as e: return 'Unable to fetch results: {}'.format(e) h = html.fromstring(request.text) results = h.xpath("//div[@id='releases']/div/span[@class='release']/..") if not results: return "No results found." result = results[0] date = result.xpath("span[@class='timestamp']/text()")[0] section = result.xpath("span[@class='section']//text()")[0] name = result.xpath("span[@class='release']/text()")[0] # parse date/time date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S") date_string = date.strftime("%d %b %Y") since = timeformat.time_since(date) size = result.xpath("span[@class='inforight']//text()") if size: size = ' - ' + size[0].split()[0] else: size = '' return '{} - {}{} - {} ({} ago)'.format(section, name, size, date_string, since)
def format_output(item, show_url=False): """ takes a voat post and returns a formatted string """ if not item["Title"]: item["Title"] = formatting.truncate(item["Linkdescription"], 70) else: item["Title"] = formatting.truncate(item["Title"], 70) item["link"] = voat_fill_url.format(item["Subverse"], item["Id"]) raw_time = isodate.parse_date(item['Date']) item["timesince"] = timeformat.time_since(raw_time, count=1, simple=True) item["comments"] = formatting.pluralize(item["CommentCount"], 'comment') item["points"] = formatting.pluralize(item["Likes"], 'point') if item["Type"] == 2: item["warning"] = " \x02Link\x02" else: item["warning"] = "" if show_url: return "\x02{Title} : {Subverse}\x02 - {comments}, {points}" \ " - \x02{Name}\x02 {timesince} ago - {link}{warning}".format(**item) else: return "\x02{Title} : {Subverse}\x02 - {comments}, {points}" \ " - \x02{Name}\x02, {timesince} ago{warning}".format(**item)
def format_tweet(tweet, user): text = " ".join(tweet.text.split()) if user.verified: prefix = "\u2713" else: prefix = "" time = timeformat.time_since(tweet.created_at, datetime.utcnow()) return "{}@\x02{}\x02 ({}): {} ({} ago)".format(prefix, user.screen_name, user.name, html.unescape(text), time)
def showtells(nick, notice, db, conn): """- View all pending tell messages (sent in a notice).""" tells = get_unread(db, conn.name, nick) if not tells: notice("You have no pending messages.") return for tell in tells: sender, message, time_sent = tell past = timeformat.time_since(time_sent) notice("{} sent you a message {} ago: {}".format(sender, past, message)) read_all_tells(db, conn.name, nick)
def showtells(nick, notice, db, conn): """showtells -- View all pending tell messages (sent in a notice).""" tells = get_unread(db, conn.name, nick) if not tells: notice("You have no pending messages.") return for tell in tells: sender, message, time_sent = tell past = timeformat.time_since(time_sent) notice("{} sent you a message {} ago: {}".format(sender, past, message)) read_all_tells(db, conn.name, nick)
def format_tweet(tweet): if isinstance(tweet, str): return tweet user = tweet.user # Format the return the text of the tweet text = html.unescape(" ".join(tweet.full_text.split())) # Get expanded URLs urls = {} if tweet.entities.get("urls"): for item in tweet.entities["urls"]: urls[item["url"]] = item["expanded_url"] if "extended_entities" in tweet._json: high_bitrate = -1 # mp4 of gif appears to be marked 0 for item in tweet._json["extended_entities"]["media"]: # check for video if "video_info" in item: for vid in item["video_info"]["variants"]: if vid["content_type"] == "video/mp4" and vid["bitrate"] > high_bitrate: high_bitrate = vid["bitrate"] urls[item["url"]] = vid["url"] continue # Did we already set it? if not item["url"] in urls: urls[item["url"]] = item["media_url_https"] while True: m = TCO_RE.search(text) if not m: break if m.group() in urls: # Expand the URL text = TCO_RE.sub(urls[m.group()], text, count=1) else: # Ignore and move on TCO_RE.compile("(?!{}){}".format(m.group(), TCO_RE.pattern)) verified = "\u2713" if user.verified else "" time = timeformat.time_since(tweet.created_at, datetime.utcnow(), simple=True) return "{} ({}@{}) [div] {} ago [div] {}".format(user.name, verified, user.screen_name, time, text.strip())
def format_output(item, show_url=False): """ takes a reddit post and returns a formatted string """ item["title"] = html.unescape(formatting.truncate(item["title"], 200)) item["link"] = short_url.format(item["id"]) # Fix some URLs if not item["is_self"] and item["url"]: # Use .gifv links for imgur if "imgur.com/" in item["url"] and item["url"].endswith(".gif"): item["url"] += "v" # Fix i.reddituploads.com crap ("&" in URL) if "i.reddituploads.com/" in item["url"]: # Get i.redditmedia.com preview (first one is full size) item["url"] = item["preview"]["images"][0]["source"]["url"] # Unescape since reddit gives links for HTML item["url"] = html.unescape(item["url"]) raw_time = datetime.fromtimestamp(int(item["created_utc"])) item["timesince"] = timeformat.time_since(raw_time, count=1, simple=True) item["comments"] = formatting.pluralize_auto(item["num_comments"], 'comment').replace(",", "") item["points"] = formatting.pluralize_auto(item["score"], 'point').replace(",", "") out = [] if show_url and item["link"]: out.append("[h3]{link}[/h3]") out.append("{title}") if not item["is_self"]: out.append("{url}") if item["over_18"]: out.append("$(red)NSFW$(c)") out.extend(["/r/{subreddit}", "/u/{author}", "{timesince} ago", "{points}", "{comments}"]) if item["gilded"]: item["gilded"] = formatting.pluralize_auto(item["gilded"], 'gild') out.append("$(yellow){gilded}$(c)") return "[h1]Reddit:[/h1] " + " [div] ".join(out).format(**item)
def format_output(item, show_url=False): """ takes a reddit post and returns a formatted string """ item["title"] = formatting.truncate(item["title"], 70) item["link"] = short_url.format(item["id"]) raw_time = datetime.fromtimestamp(int(item["created_utc"])) item["timesince"] = timeformat.time_since(raw_time, count=1, simple=True) item["comments"] = formatting.pluralize(item["num_comments"], 'comment') item["points"] = formatting.pluralize(item["score"], 'point') if item["over_18"]: item["warning"] = " \x02NSFW\x02" else: item["warning"] = "" if show_url: return "\x02{title} : {subreddit}\x02 - {comments}, {points}" \ " - \x02{author}\x02 {timesince} ago - {link}{warning}".format(**item) else: return "\x02{title} : {subreddit}\x02 - {comments}, {points}" \ " - \x02{author}\x02, {timesince} ago{warning}".format(**item)
def lastfm(event, db, text, nick, bot): """[user] [dontsave] - displays the now playing (or last played) track of LastFM user [user]""" api_key = bot.config.get("api_keys", {}).get("lastfm") if not api_key: return "error: no api key set" # check if the user asked us not to save his details dontsave = text.endswith(" dontsave") if dontsave: user = text[:-9].strip().lower() else: user = text if not user: user = get_account(nick) if not user: event.notice_doc() return response, err = api_request('user.getrecenttracks', api_key, user=user, limit=1) if err: return err if "track" not in response["recenttracks"] or len( response["recenttracks"]["track"]) == 0: return 'No recent tracks for user "{}" found.'.format( format_user(user)) tracks = response["recenttracks"]["track"] if isinstance(tracks, list): track = tracks[0] if "@attr" in track and "nowplaying" in track["@attr"] and track[ "@attr"]["nowplaying"] == "true": # if the user is listening to something, the first track (a dict) of the # tracks list will contain an item with the "@attr" key. # this item will will contain another item with the "nowplaying" key # which value will be "true" status = 'is listening to' ending = '.' else: # otherwise, the user is not listening to anything right now status = 'last listened to' # lets see how long ago they listened to it time_listened = datetime.fromtimestamp(int(track["date"]["uts"])) time_since = timeformat.time_since(time_listened) ending = ' ({} ago)'.format(time_since) else: return "error: could not parse track listing" title = track["name"] album = track["album"]["#text"] artist = track["artist"]["#text"] url = web.try_shorten(track["url"]) tags = gettracktags(api_key, artist, title) if tags == "no tags": tags = getartisttags(api_key, artist) playcount = getusertrackplaycount(api_key, artist, title, user) out = '{} {} "{}"'.format(format_user(user), status, title) if artist: out += " by \x02{}\x02".format(artist) if album: out += " from the album \x02{}\x02".format(album) if playcount: out += " [playcount: {}]".format(playcount) else: out += " [playcount: 0]" if url: out += " {}".format(url) out += " ({})".format(tags) # append ending based on what type it was out += ending if text and not dontsave: if get_account(nick): db.execute(table.update().values(acc=user).where( table.c.nick == nick.lower())) db.commit() else: db.execute(table.insert().values(nick=nick.lower(), acc=user)) db.commit() load_cache(db) return out
def librefm(text, nick, db, bot, notice): """[user] [dontsave] - displays the now playing (or last played) track of libre.fm user [user]""" # check if the user asked us not to save his details dontsave = text.endswith(" dontsave") if dontsave: user = text[:-9].strip().lower() else: user = text if not user: user = get_account(nick) if not user: notice(librefm.__doc__) return params = {'method': 'user.getrecenttracks', 'user': user, 'limit': 1} request = requests.get(api_url, params=params) if request.status_code != requests.codes.ok: return "Failed to fetch info ({})".format(request.status_code) response = request.json() if 'error' in response: #return "libre.fm Error: {}.".format(response["message"]) return "libre.fm Error: {} Code: {}.".format(response["error"]["#text"], response["error"]["code"]) if "track" not in response["recenttracks"] or len(response["recenttracks"]["track"]) == 0: return 'No recent tracks for user "{}" found.'.format(user) tracks = response["recenttracks"]["track"] if type(tracks) == list: track = tracks[0] if "@attr" in track and "nowplaying" in track["@attr"] and track["@attr"]["nowplaying"] == "true": # if the user is listening to something, the first track (a dict) of the # tracks list will contain an item with the "@attr" key. # this item will will contain another item with the "nowplaying" key # which value will be "true" status = 'is listening to' ending = '.' elif type(tracks) == dict: track = tracks # otherwise, the user is not listening to anything right now status = 'last listened to' # lets see how long ago they listened to it time_listened = datetime.fromtimestamp(int(track["date"]["uts"])) time_since = timeformat.time_since(time_listened) ending = ' ({} ago)'.format(time_since) else: return "error: could not parse track listing" title = track["name"] album = track["album"]["#text"] artist = track["artist"]["#text"] try: url = web.try_shorten(track["url"]) except: url = track["url"] pass tags = getartisttags(artist, bot) out = '{} {} "{}"'.format(user, status, title) if artist: out += " by \x02{}\x0f".format(artist) if album: out += " from the album \x02{}\x0f".format(album) if url: out += " {}".format(url) out += " ({})".format(tags) # append ending based on what type it was out += ending if text and not dontsave: db.execute("insert or replace into librefm(nick, acc) values (:nick, :account)", {'nick': nick.lower(), 'account': user}) db.commit() load_cache(db) return out
for reminder in reminder_cache: network, remind_time, added_time, user, message = reminder if remind_time <= current_time: if network not in bot.connections: # connection is invalid yield from add_reminder(async, db, network, remind_time, user) yield from load_cache(async, db) continue conn = bot.connections[network] if not conn.ready: return remind_text = colors.parse(time_since(added_time, count=2)) alert = colors.parse("{}, you have a reminder from $(b){}$(clear) ago!".format(user, remind_text)) conn.message(user, alert) conn.message(user, '"{}"'.format(message)) delta = (remind_time - added_time).seconds if delta > (30 * 60): late_time = time_since(remind_time, count=2) late = ( "(I'm sorry for delivering this message $(b){}$(clear) late," " it seems I was unable to deliver it on time)".format(late_time) ) conn.message(user, colors.parse(late)) yield from delete_reminder(async, db, network, remind_time, user)
def lastfm(text, nick, db, bot, notice): """[user] [dontsave] - displays the now playing (or last played) track of LastFM user [user]""" api_key = bot.config.get("api_keys", {}).get("lastfm") if not api_key: return "No last.fm API key set." # check if the user asked us not to save his details dontsave = text.endswith(" dontsave") if dontsave: user = text[:-9].strip().lower() else: user = text if not user: user = get_account(nick) if not user: notice(lastfm.__doc__) return params = {'method': 'user.getrecenttracks', 'api_key': api_key, 'user': user, 'limit': 1} request = requests.get(api_url, params=params) if request.status_code != requests.codes.ok: return "Failed to fetch info ({})".format(request.status_code) response = request.json() if 'error' in response: return "Last.FM Error: {}.".format(response["message"]) if "track" not in response["recenttracks"] or len(response["recenttracks"]["track"]) == 0: return 'No recent tracks for user "{}" found.'.format(user) tracks = response["recenttracks"]["track"] if type(tracks) == list: # if the user is listening to something, the tracks entry is a list # the first item is the current track track = tracks[0] status = 'is listening to' ending = '.' elif type(tracks) == dict: # otherwise, they aren't listening to anything right now, and # the tracks entry is a dict representing the most recent track track = tracks status = 'last listened to' # lets see how long ago they listened to it time_listened = datetime.fromtimestamp(int(track["date"]["uts"])) time_since = timeformat.time_since(time_listened) ending = ' ({} ago)'.format(time_since) else: return "error: could not parse track listing" title = track["name"] album = track["album"]["#text"] artist = track["artist"]["#text"] url = web.try_shorten(track["url"]) out = '{} {} "{}"'.format(user, status, title) if artist: out += " by \x02{}\x0f".format(artist) if album: out += " from the album \x02{}\x0f".format(album) if url: out += " {}".format(url) # append ending based on what type it was out += ending if text and not dontsave: db.execute("insert or replace into lastfm(nick, acc) values (:nick, :account)", {'nick': nick.lower(), 'account': user}) db.commit() load_cache(db) return out
for reminder in reminder_cache: network, remind_time, added_chan, added_time, user, message = reminder if remind_time <= current_time: if network not in bot.connections: # connection is invalid: drop reminder yield from delete_reminder(async, db, network, remind_time, user) sent_something = True continue conn = bot.connections[network] if not conn.ready: return reltime = time_since(added_time, simple=True, count=1) conn.message( added_chan, '{}: [reminder from {} ago] {}'.format(user, reltime, message)) delta = (remind_time - added_time).seconds if delta > (30 * 60): late_time = time_since(remind_time, count=2) late = "Sorry for delivering that message $(b){}$(clear) late" \ .format(late_time) conn.message(user, colors.parse(late)) yield from delete_reminder(async, db, network, remind_time, user) sent_something = True if sent_something:
for reminder in reminder_cache: network, remind_time, added_time, user, message = reminder if remind_time <= current_time: if network not in bot.connections: # connection is invalid yield from add_reminder(async, db, network, remind_time, user) yield from load_cache(async, db) continue conn = bot.connections[network] if not conn.ready: return remind_text = colors.parse(time_since(added_time, count=2)) alert = colors.parse( "{}, you have a reminder from $(b){}$(clear) ago!".format( user, remind_text)) conn.message(user, alert) conn.message(user, '"{}"'.format(message)) delta = (remind_time - added_time).seconds if delta > (30 * 60): late_time = time_since(remind_time, count=2) late = "(I'm sorry for delivering this message $(b){}$(clear) late," \ " it seems I was unable to deliver it on time)".format(late_time) conn.message(user, colors.parse(late)) yield from delete_reminder(async, db, network, remind_time, user)
def twitter(text): """twitter <user> [n] -- Gets last/[n]th tweet from <user>""" if tw_api is None: return "This command requires a twitter API key." if re.match(r'^\d+$', text): # user is getting a tweet by id try: # get tweet by id tweet = tw_api.get_status(text) except tweepy.error.TweepError as e: if "404" in e.reason: return "Could not find tweet." else: return "Error: {}".format(e.reason) user = tweet.user elif re.match(r'^\w{1,15}$', text) or re.match(r'^\w{1,15}\s+\d+$', text): # user is getting a tweet by name if text.find(' ') == -1: username = text tweet_number = 0 else: username, tweet_number = text.split() tweet_number = int(tweet_number) - 1 if tweet_number > 200: return "This command can only find the last \x02200\x02 tweets." try: # try to get user by username user = tw_api.get_user(username) except tweepy.error.TweepError as e: if "404" in e.reason: return "Could not find user." else: return "Error: {}".format(e.reason) # get the users tweets user_timeline = tw_api.user_timeline(id=user.id, count=tweet_number + 1) # if the timeline is empty, return an error if not user_timeline: return "The user \x02{}\x02 has no tweets.".format(user.screen_name) # grab the newest tweet from the users timeline try: tweet = user_timeline[tweet_number] except IndexError: tweet_count = len(user_timeline) return "The user \x02{}\x02 only has \x02{}\x02 tweets.".format(user.screen_name, tweet_count) elif re.match(r'^#\w+$', text): # user is searching by hashtag search = tw_api.search(text) if not search: return "No tweets found." tweet = random.choice(search) user = tweet.user else: # ??? return "Invalid Input" # Format the return the text of the tweet text = " ".join(tweet.text.split()) if user.verified: prefix = "\u2713" else: prefix = "" time = timeformat.time_since(tweet.created_at, datetime.utcnow()) return "{}@\x02{}\x02 ({}): {} ({} ago)".format(prefix, user.screen_name, user.name, text, time)
current_time = datetime.now() for reminder in reminder_cache: network, remind_time, added_chan, added_time, user, message = reminder if remind_time <= current_time: if network not in bot.connections: # connection is invalid: drop reminder yield from delete_reminder(async, db, network, remind_time, user) sent_something = True continue conn = bot.connections[network] if not conn.ready: return reltime = time_since(added_time, simple=True, count=1) conn.message(added_chan, '{}: [reminder from {} ago] {}' .format(user, reltime, message)) delta = (remind_time-added_time).seconds if delta > (30*60): late_time = time_since(remind_time, count=2) late = "Sorry for delivering that message $(b){}$(clear) late" \ .format(late_time) conn.message(user, colors.parse(late)) yield from delete_reminder(async, db, network, remind_time, user) sent_something = True if sent_something: yield from load_cache(async, db)
def librefm(text, nick, db, event): """[user] [dontsave] - displays the now playing (or last played) track of libre.fm user [user]""" # check if the user asked us not to save his details dontsave = text.endswith(" dontsave") if dontsave: user = text[:-9].strip().lower() else: user = text if not user: user = get_account(nick) if not user: event.notice_doc() return response, err = api_request('user.getrecenttracks', user=user, limit=1) if err: return err if 'error' in response: # return "libre.fm Error: {}.".format(response["message"]) return "libre.fm Error: {} Code: {}.".format( response["error"]["#text"], response["error"]["code"]) if 'track' not in response['recenttracks'] or response['recenttracks'][ 'track']: return "No recent tracks for user \"{}\" found.".format(user) tracks = response["recenttracks"]["track"] if isinstance(tracks, list): track = tracks[0] if "@attr" in track and "nowplaying" in track["@attr"] and track[ "@attr"]["nowplaying"] == "true": # if the user is listening to something, the first track (a dict) of the # tracks list will contain an item with the "@attr" key. # this item will will contain another item with the "nowplaying" key # which value will be "true" status = 'is listening to' ending = '.' else: return elif isinstance(tracks, dict): track = tracks # otherwise, the user is not listening to anything right now status = 'last listened to' # lets see how long ago they listened to it time_listened = datetime.fromtimestamp(int(track["date"]["uts"])) time_since = timeformat.time_since(time_listened) ending = ' ({} ago)'.format(time_since) else: return "error: could not parse track listing" title = track["name"] album = track["album"]["#text"] artist = track["artist"]["#text"] url = web.try_shorten(track["url"]) tags = getartisttags(artist) out = '{} {} "{}"'.format(user, status, title) if artist: out += " by \x02{}\x0f".format(artist) if album: out += " from the album \x02{}\x0f".format(album) if url: out += " {}".format(url) out += " ({})".format(tags) # append ending based on what type it was out += ending if text and not dontsave: res = db.execute(table.update().values(acc=user).where( table.c.nick == nick.lower())) if res.rowcount <= 0: db.execute(table.insert().values(nick=nick.lower(), acc=user)) db.commit() load_cache(db) return out
def librefm(text, nick, db, bot, notice): """[user] [dontsave] - displays the now playing (or last played) track of libre.fm user [user]""" # check if the user asked us not to save his details dontsave = text.endswith(" dontsave") if dontsave: user = text[:-9].strip().lower() else: user = text if not user: user = get_account(nick) if not user: notice(librefm.__doc__) return params = {'method': 'user.getrecenttracks', 'user': user, 'limit': 1} request = requests.get(api_url, params=params) if request.status_code != requests.codes.ok: return "Failed to fetch info ({})".format(request.status_code) response = request.json() if 'error' in response: #return "libre.fm Error: {}.".format(response["message"]) return "libre.fm Error: {} Code: {}.".format( response["error"]["#text"], response["error"]["code"]) if "track" not in response["recenttracks"] or len( response["recenttracks"]["track"]) == 0: return 'No recent tracks for user "{}" found.'.format(user) tracks = response["recenttracks"]["track"] if type(tracks) == list: track = tracks[0] if "@attr" in track and "nowplaying" in track["@attr"] and track[ "@attr"]["nowplaying"] == "true": # if the user is listening to something, the first track (a dict) of the # tracks list will contain an item with the "@attr" key. # this item will will contain another item with the "nowplaying" key # which value will be "true" status = 'is listening to' ending = '.' elif type(tracks) == dict: track = tracks # otherwise, the user is not listening to anything right now status = 'last listened to' # lets see how long ago they listened to it time_listened = datetime.fromtimestamp(int(track["date"]["uts"])) time_since = timeformat.time_since(time_listened) ending = ' ({} ago)'.format(time_since) else: return "error: could not parse track listing" title = track["name"] album = track["album"]["#text"] artist = track["artist"]["#text"] try: url = web.try_shorten(track["url"]) except: url = track["url"] pass tags = getartisttags(artist, bot) out = '{} {} "{}"'.format(user, status, title) if artist: out += " by \x02{}\x0f".format(artist) if album: out += " from the album \x02{}\x0f".format(album) if url: out += " {}".format(url) out += " ({})".format(tags) # append ending based on what type it was out += ending if text and not dontsave: db.execute( "insert or replace into librefm(nick, acc) values (:nick, :account)", { 'nick': nick.lower(), 'account': user }) db.commit() load_cache(db) return out