def scrape_id(self, id, since=None): # excluding replies was a personal choice. i haven't made an easy setting for this yet toots = self.mastodon.account_statuses(id, since_id=since, exclude_replies=self.exclude_replies) # if this fails, there are no new toots and we just return old pointer try: new_since_id = toots[0]['id'] except: return since bufferfile = 'buffer.txt' corpusfile = 'corpus/%s.txt' % id i = 0 with open(bufferfile, 'w') as output: while toots != None: # writes current amount of scraped toots without breaking line i = i + len(toots) sys.stdout.write('\r%d' % i) sys.stdout.flush() filtered_toots = list(filter(lambda x: x['spoiler_text'] == "" and x['reblog'] is None and x['visibility'] in ["public", "unlisted"], toots)) for toot in filtered_toots: output.write(html_strip_tags(toot['content'], True, chr(31))+'\n') toots = self.mastodon.fetch_next(toots) # buffer is appended to the top of old corpus if os.path.exists(corpusfile): with open(corpusfile,'r') as old_corpus: output.write(old_corpus.read()) directory = os.path.dirname(corpusfile) if not os.path.exists(directory): os.makedirs(directory) os.rename(bufferfile,corpusfile) sys.stdout.write('\n') sys.stdout.flush() return new_since_id
def post_response(self, mention, user): msg = html_strip_tags(mention["content"]) rsp = random.choice(self.responses) tgt = user["acct"] if tgt in ["*****@*****.**", "*****@*****.**" ] and rsp.find("rides") >= 0: rsp = rsp.replace(r"foot", "tail") if tgt in ["*****@*****.**", "*****@*****.**" ] and rsp.find("leg") >= 0: rsp = rsp.replace(r"leg", "tail") irt = mention["id"] vis = mention["visibility"] print("Received toot from {}: {}".format(tgt, msg)) try: tgt_rec = self.recents[tgt] except KeyError: tgt_rec = 0 if "mom?" in msg or "moms?" in msg: self.mastodon.status_post( "{} *holds up a picture of @[email protected]".format(tgt), in_reply_to_id=irt, visibility=vis) else: if tgt_rec < self.max_recents or vis == 'direct': print("Responding with {} visibility: {}".format(vis, rsp)) self.mastodon.status_post("@{} *{}*".format(tgt, rsp), in_reply_to_id=irt, visibility=vis) if vis != 'direct': self.recents[tgt] = tgt_rec + 1 print("self.recents updated: ", end="") pprint(self.recents) else: print("...but I've responded to {} too recently.".format(tgt))
def post_reply(self, mention, user): if self.reply_to_mentions == True: msg = html_strip_tags(mention["content"], True, chr(31)) rsp = self.generate(300) tgt = user["acct"] irt = mention["id"] vis = mention["visibility"] print("Received toot from {}: {}".format( tgt, msg.replace(chr(31), "\n"))) if (tgt not in self.recent_replies.keys() or self.recent_replies[tgt] < self.max_replies or self.max_replies == -1): print("Responding with {} visibility: {}".format(vis, rsp)) final_rsp = "@{} {}".format(tgt, rsp) final_rsp = final_rsp[:500] self.mastodon.status_post(final_rsp, in_reply_to_id=irt, visibility=vis) if tgt in self.recent_replies.keys(): self.recent_replies[tgt] = self.recent_replies[tgt] + 1 else: self.recent_replies[tgt] = 1 else: print("...but I've talked to them too much recently.") else: pass @interval(300) def reset_replies(self): self.recent_replies = {}
def post_reply(self, mention, user): msg = html_strip_tags(mention["content"]) rsp = self.generate(400) tgt = user["acct"] irt = mention["id"] vis = mention["visibility"] print("Received toot from {}: {}".format(tgt, msg)) print("Responding with {} visibility: {}".format(vis, rsp)) final_rsp = "@{} {}".format(tgt, rsp) final_rsp = final_rsp[:500] self.mastodon.status_post(final_rsp, in_reply_to_id=irt, visibility=vis)
def scrape_account(self, account, since=None): # excluding replies was a personal choice. i haven't made an easy # setting for this yet toots = self.mastodon.account_statuses( account, since_id=since, exclude_replies=self.exclude_replies) # if this fails, there are no new toots and we just return old pointer try: since = toots[0].id except IndexError: return since total = 0 count = 0 buffer = "" while toots is not None and len(toots) > 0: for toot in toots: total += 1 if (toot.spoiler_text == "" and toot.reblog is None and toot.visibility in ["public", "unlisted"]): content = html_strip_tags(toot.content, linebreaks=True).strip() + "\n" if re.search("@\w", content) is None: buffer += content count += 1 toots = self.mastodon.fetch_next(toots) self.log("scrape_account", "scraped {} toots from {}".format(total, account)) self.log("scrape_account", "added {} toots to the corpus".format(count, account)) corpusfile = "corpus/{}.txt".format(account) directory = os.path.dirname(corpusfile) if not os.path.exists(directory): os.makedirs(directory) # buffer is appended to the top of old corpus try: f = open(corpusfile, "r+") buffer += f.read() f.seek(0) except OSError: f = open(corpusfile, "a+") f.write(buffer) f.truncate() f.close() return since
def on_reply(self, mention, user): msg = html_strip_tags(mention.content, linebreaks=True) msg = remove_prefix(msg.strip(), "@tts").strip() msg = msg.replace("@", "@\u200b") self.log("on_reply", "Received toot from {}: \"{}\"".format(user.acct, msg)) if "!delete" in msg and user.acct == self.config.admin: self.log("on_reply", "Deleting toot: {}".format(mention.in_reply_to_id)) self.mastodon.status_delete(mention.in_reply_to_id) return with tempfile.NamedTemporaryFile(suffix=".wav") as af: subprocess.check_call([ "espeak", msg, "-w", af.name, ]) with tempfile.NamedTemporaryFile(suffix=".mp4") as vf: subprocess.check_call([ "ffmpeg", "-i", af.name, "-i", "speechbot.png", "-profile:v", "baseline", "-pix_fmt", "yuv420p", "-y", "-hide_banner", "-nostats", "-loglevel", "panic", vf.name, ]) self.log("on_reply", "Generated video, posting...") media = self.mastodon.media_post(vf.name) self.mastodon.status_post("@{} {}".format(user.acct, msg), in_reply_to_id=mention, visibility=mention.visibility, media_ids=media)
def add_toot_to_corpus(self, toot): if toot['reblog']: return False if toot['spoiler_text']: return False text_content = ananas.html_strip_tags(toot['content']) db_conn = self.connect_to_sqlite() cursor = db_conn.cursor() try: toot_input = (toot['id'], text_content) cursor.execute("INSERT INTO toots VALUES (?, ?)", toot_input) db_conn.commit() except sqlite3.IntegrityError: pass # Toot is already in DB, nevermind return True
def on_reply(self, mention, user): msg = html_strip_tags(mention.content, linebreaks=True) self.log("on_reply", "Received toot from {}: \"{}\"".format(user.acct, msg)) if "!delete" in msg and user.acct == self.config.admin: self.log("on_reply", "Deleting toot: {}".format(mention.in_reply_to_id)) self.mastodon.status_delete(mention.in_reply_to_id) return if "!followme" in msg: self.mastodon.account_follow(user.id) self.reply_toot(mention, user, "kapow!") return if "!unfollowme" in msg: self.mastodon.account_unfollow(user.id) self.reply_toot(mention, user, "kabam!") return matches = re.search( r"(?:gimme|can i get)(?: some| a)?(?: uh+)? (\")?(?P<s>(?(1).*(?=\")|\w+))", msg, flags=re.IGNORECASE) if matches is not None: s = matches.group("s") if s in self.corpus: response = "too lazy, giving up." for _ in range(0, 100): r = self.model.make_short_sentence(400, tries=100) if s in r: response = r break else: response = "no." else: response = self.model.make_short_sentence(400, tries=100) self.reply_toot(mention, user, response)
def handle_roll(self, mention, user): raw = html_strip_tags(mention["content"]) username = user["acct"] self.log("handle_roll", "Parsing dice in '{}' from @{}".format(raw, username)) message = "" try: rolls = parse_dice(raw) except Exception as e: self.report_error("{}\n{}".format(repr(e), traceback.format_exc())) rolls = [] if len(rolls) == 0: rolls = [('r', 1, 6)] message = "I'm confused, so I'm just going to roll a d6.\n" return # TODO cheeky message? else: self.log("debug", "rolls: {}".format(rolls)) for i, r in enumerate(rolls): try: #r = fixup_tree(r) line = "Rolling {}: ".format(spec_dice(r)) dice = roll_dice(r) expr = sum_dice(dice) sum = eval_dice(dice) line += "{} = {}".format(visit_dice(dice), visit_sum_dice(expr)) if (not isinstance(expr, int)): line += " = {}".format(sum) message = line + "\n" except SillyDiceError as e: message += str(e) + "\n" self.mastodon.status_post("@{}\n{}".format(username, message), in_reply_to_id=mention["id"], visibility=mention["visibility"])
def respond_weather(self, status, user): try: # post a reply of the form "@<user account>" global location username = user["acct"] msg_rec = html_strip_tags(status["content"], True, chr(31)) bs = BeautifulSoup(status["content"], "lxml") # strip out mentions for mention in status["mentions"]: for a in bs.find_all(href=mention["url"]): a.extract() # put all the lines in a list for br in bs.find_all("br"): br.replace_with('\n') # then replace consecutive p tags with a double newline Input = [Input.text for Input in bs.find_all('p')] Input = '\n\n'.join(Input) # finally split all the lines up at the newlines we just added Input = [ Input.strip() for line in Input.splitlines() if Input.strip() ] if len(Input) == 0: msg_date = "The weatherbot can query the weather conditions in the next three days" + '\n========\n' + "1.Please @ Weatherbot + 'location' + ',' + 'Today' or 'Tomorrow' or 'Day After Tomorrow' to query (e.g. London,Today)" + '\n========\n' + "2.If the query result is not in the desired area, please @ Weatherbot + ’location’ + ',' + 'country code' + 'Today' or 'Tomorrow' or 'Day After Tomorrow'(e.g. London,GB,Today). The country code query address: https://www.iso.org/iso-3166-country-codes.html" self.mastodon.toot(msg_date) else: # According to "," split list elements location_date = Input[0].split(",") # If the length of the returned list after element separation is 1, it means that there is no "," in the original list; the purpose of user input is to query the location Id if len(location_date) == 2: location = location_date[0].capitalize() print(location_date[0], location_date[1]) tm_hour, tm_min = self.get_time() if location_date[1].capitalize() == "Today": msg = self.today(tm_hour, tm_min) self.mastodon.toot("@{} {}".format( username, '\n' + msg)) elif location_date[1].capitalize() == "Tomorrow": msg = self.tomorrow(tm_hour, tm_min) self.mastodon.toot("@{} {}".format( username, '\n' + msg)) elif location_date[1].title() == "Day After Tomorrow": msg = self.the_day_after_tomorrow(tm_hour, tm_min) self.mastodon.toot("@{} {}".format( username, '\n' + msg)) # Otherwise, the user's purpose is to check weather conditions elif len(location_date) == 3: url = APIURL_locid + location_date[0].capitalize( ) + "&range=" + location_date[1].lower() + KEY locid_res = requests.get(url) locid_res_json = locid_res.json() location = locid_res_json["location"][0]["id"] print(location_date[0], location, location_date[1], location_date[2]) tm_hour, tm_min = self.get_time() if location_date[2].capitalize() == "Today": msg = self.today(tm_hour, tm_min) self.mastodon.toot("@{} {}".format( username, '\n' + msg)) elif location_date[2].capitalize() == "Tomorrow": msg = self.tomorrow(tm_hour, tm_min) self.mastodon.toot("@{} {}".format( username, '\n' + msg)) elif location_date[2].title() == "Day After Tomorrow": msg = self.the_day_after_tomorrow(tm_hour, tm_min) self.mastodon.toot("@{} {}".format( username, '\n' + msg)) except: msg = "This location is not found or Your input is incorrect, please re-enter" self.mastodon.toot("@{} {}".format(username, '\n' + msg)) print("Received toot from {}: {}".format( username, msg_rec.replace(chr(31), "\n")))