def get_comments(date_time): global LAST_REQUEST seconds_since_last_request = (utils.datetime_now() - LAST_REQUEST).total_seconds() if seconds_since_last_request < 1: log.info(f"Sleeping: {1 - seconds_since_last_request}") time.sleep(1 - seconds_since_last_request) url = f"https://api.pushshift.io/reddit/comment/search?limit=500&sort=desc&before={int(date_time.timestamp()) + 1}" LAST_REQUEST = utils.datetime_now() for i in range(10): try: response = requests.get(url, headers={'User-Agent': USER_AGENT}, timeout=10) if response.status_code != 200: log.warning( f"Bad response code, trying again: {response.status_code}") time.sleep(5) continue comments = response.json()['data'] return comments except Exception as err: log.warning(f"Exception in request, trying again: {err}") time.sleep(5) continue log.warning(f"Hit 10 exceptions, giving up") return None
def test_comment_in_thread(database, reddit): comment_id = reddit_test.random_id() thread_id = reddit_test.random_id() comment = reddit_test.RedditObject( body=f"{static.TRIGGER}! 1 day", author="Watchful1", created=utils.datetime_now(), id=comment_id, link_id="t3_" + thread_id, permalink=f"/r/test/{thread_id}/_/{comment_id}/", subreddit="test") reddit.add_comment(comment) comments.process_comment(comment.get_pushshift_dict(), reddit, database) comment_id_2 = reddit_test.random_id() comment_2 = reddit_test.RedditObject( body=f"{static.TRIGGER}! 1 day", author="Watchful1", created=utils.datetime_now(), id=comment_id_2, link_id="t3_" + thread_id, permalink=f"/r/test/{thread_id}/_/{comment_id_2}/", subreddit="test") reddit.add_comment(comment_2) comments.process_comment(comment_2.get_pushshift_dict(), reddit, database) assert len(comment_2.children) == 0 assert len(reddit.sent_messages) == 1 assert reddit.sent_messages[0].author.name == static.ACCOUNT_NAME assert "I've already replied to another comment in this thread" in reddit.sent_messages[ 0].body
def test_add_recurring_reminder(database, reddit): created = utils.datetime_now() username = "******" keyword = "reminderstring" id = reddit_test.random_id() message = reddit_test.RedditObject( body=f"[{keyword}]\n{static.TRIGGER_RECURRING}! 1 day", author=username, created=created, id=id) messages.process_message(message, reddit, database) result = message.get_first_child().body assert "reminderstring" in result assert "and then every `1 day`" in result assert "This time has already passed" not in result assert "Could not find a time in message" not in result assert "Could not parse date" not in result assert "Can't use a default for a recurring reminder" not in result assert "I got the same date rather than one after it" not in result assert "I got a date before that rather than one after it" not in result reminders = database.get_all_user_reminders(username) assert len(reminders) == 1 assert reminders[0].user.name == username assert reminders[0].message == keyword assert reminders[0].source == utils.message_link(id) assert reminders[0].requested_date == created assert reminders[0].target_date == created + timedelta(hours=24) assert reminders[0].id is not None assert reminders[0].recurrence == "1 day"
def charge(self): """ Set up the event loop for the async API polls, do a first poll, then run the main loop (using the event loop...) """ loop = asyncio.get_event_loop() if not self.config['operation']: LOGGER.warning( 'Operation mode off: not sending any commands to aircons') if self.csv: LOGGER.info('Logging runtime analytics to %s', self.csv.file.name) [(_, pv_generation), *_] = loop.run_until_complete( asyncio.gather(self.solar.check_se_load(), *[unit.get_basic_info() for unit in self.ac], *self.get_load_ac_status_requests())) now = datetime_now() self.last_updated = now if pv_generation <= self.config['sleep_threshold']: LOGGER.info('Inverter off, started in sleep mode') self.is_sleep_mode = True else: # Schedule first set in 3 read steps self.last_set = now - datetime.timedelta( seconds=self.config['set_interval'] - 3 * self.config['read_interval']) for unit in self.ac: LOGGER.info(unit) loop.run_until_complete(self.server.start()) loop.run_until_complete(self.main_loop())
def __init__(self, config, aircons, solar, server, csv=None, recent_values=None): """ Args: config a dictionary containing settings from the yaml config file aircons a list of Aircon instances solar a SolarInfo instance server a BrickBatteryHTTPServer instance to expose controls and status through a web API csv an optional CSVLogger instance to write analytics information to, defaults to None if no logging is required recent_values an optional container of time-series accessed through the web API for plotting """ self.config = config self.ac = aircons self.ac_consumption = float('NaN') self.solar = solar self.csv = csv self.server = server self.server.register_controller(self) self.last_updated = None self.last_set = None self.csv_last_save = datetime_now() self.is_sleep_mode = False self.recent_values = recent_values
def test_add_reminder(database, reddit): created = utils.datetime_now() username = "******" keyword = "reminderstring" id = utils.random_id() message = reddit_test.RedditObject( body=f"[{keyword}]\n{static.TRIGGER}! 1 day", author=username, created=created, id=id) messages.process_message(message, reddit, database) result = message.get_first_child().body assert "reminderstring" in result assert "This time has already passed" not in result assert "Could not find a time in message" not in result assert "Could not parse date" not in result reminders = database.get_user_reminders(username) assert len(reminders) == 1 assert reminders[0].user == username assert reminders[0].message == keyword assert reminders[0].source == utils.message_link(id) assert reminders[0].requested_date == created assert reminders[0].target_date == created + timedelta(hours=24) assert reminders[0].db_id is not None
def test_process_comment_timezone(database, reddit): user = database.get_or_add_user(user_name="Watchful1") user.timezone = "America/Los_Angeles" username = "******" comment_id = reddit_test.random_id() thread_id = reddit_test.random_id() created = utils.datetime_now() comment = reddit_test.RedditObject( body=f"{static.TRIGGER}! 1 day", author=username, created=created, id=comment_id, link_id="t3_" + thread_id, permalink=f"/r/test/{thread_id}/_/{comment_id}/", subreddit="test") reddit.add_comment(comment) comments.process_comment(comment.get_pushshift_dict(), reddit, database) result = comment.get_first_child().body assert "default time zone" in result assert "`America/Los_Angeles`" in result reminders = database.get_all_user_reminders(username) assert reminders[0].target_date == created + timedelta(hours=24)
def test_process_comment(database, reddit): created = utils.datetime_now() username = "******" comment_id = reddit_test.random_id() thread_id = reddit_test.random_id() comment = reddit_test.RedditObject( body=f"{static.TRIGGER}! 1 day", author=username, created=created, id=comment_id, link_id="t3_" + thread_id, permalink=f"/r/test/{thread_id}/_/{comment_id}/", subreddit="test") reddit.add_comment(comment) comments.process_comment(comment.get_pushshift_dict(), reddit, database) result = comment.get_first_child().body assert "CLICK THIS LINK" in result reminders = database.get_all_user_reminders(username) assert len(reminders) == 1 assert reminders[0].user.name == username assert reminders[0].message is None assert reminders[0].source == utils.reddit_link(comment.permalink) assert reminders[0].requested_date == created assert reminders[0].target_date == created + timedelta(hours=24) assert reminders[0].id is not None assert reminders[0].recurrence is None
def __init__(self, body=None, author=None, created=None, id=None, permalink=None, link_id=None, prefix="t4", subreddit=None): self.body = body if isinstance(author, User): self.author = author else: self.author = User(author) if id is None: self.id = utils.random_id() else: self.id = id self.fullname = f"{prefix}_{self.id}" if created is None: self.created_utc = utils.datetime_now().timestamp() else: self.created_utc = created.timestamp() self.permalink = permalink self.link_id = link_id self.subreddit = subreddit self.parent = None self.children = []
def database_get_seen(database): result = database.get_keystore("comment_timestamp") if result is None: log.warning("Comment time not in database, returning now") now = utils.datetime_now() database_set_seen(database, now) return now return utils.parse_datetime_string(result)
def get_subreddit_banned(self, subreddit): log.debug(f"Getting subreddit ban: {subreddit}") days_ago = utils.datetime_now() - timedelta(days=30) return self.session.query(Subreddit)\ .filter_by(subreddit=subreddit)\ .filter_by(banned=True)\ .filter(Subreddit.ban_checked > days_ago)\ .scalar() is not None
async def insert_into_order(self, user_id, order_time, phone, address, order_products, cart_id): result = await self._conn.execute(orders.insert().values( tms_create=datetime_now(), user_id=user_id, order_time=order_time, phone=phone, address=address, order_products=order_products, cart_id=cart_id, code=str(random.randrange(100000, 999999)), status="active"))
async def insert_into_carts(self, user_id): result = await self._conn.execute(carts.insert().values( user_id=user_id, status="cart", tms_create=datetime_now(), )) async for row in result: cart_id = row[0] return cart_id
def backup(self): log.info("Backing up database") self.close(True) if not os.path.exists(static.BACKUP_FOLDER_NAME): os.makedirs(static.BACKUP_FOLDER_NAME) copyfile( static.DATABASE_NAME, static.BACKUP_FOLDER_NAME + "/" + utils.datetime_now().strftime("%Y-%m-%d_%H-%M") + ".db") self.init(self.debug, False, False)
def send_reminders(reddit, database): timestamp = utils.datetime_now() count_reminders = database.get_count_pending_reminders(timestamp) counters.queue.set(count_reminders) reminders_sent = 0 if count_reminders > 0: reminders = database.get_pending_reminders( utils.requests_available(count_reminders), timestamp) for reminder in reminders: reminders_sent += 1 counters.notifications.inc() counters.queue.dec() log.info( f"{reminders_sent}/{len(reminders)}/{count_reminders}: Sending reminder to u/{reminder.user.name} : " f"{reminder.id} : {utils.get_datetime_string(reminder.target_date)}" ) bldr = utils.get_footer(reminder.render_notification()) result = reddit.send_message(reminder.user.name, "RemindMeBot Here!", ''.join(bldr)) if result in [ ReturnType.INVALID_USER, ReturnType.USER_DOESNT_EXIST ]: log.info(f"User doesn't exist: u/{reminder.user.name}") if result in [ReturnType.NOT_WHITELISTED_BY_USER_MESSAGE]: log.info( f"User blocked notification message: u/{reminder.user.name}" ) if reminder.recurrence is not None: if reminder.user.recurring_sent > static.RECURRING_LIMIT: log.info( f"User u/{reminder.user.name} hit their recurring limit, deleting reminder {reminder.id}" ) database.delete_reminder(reminder) else: new_target_date = utils.parse_time(reminder.recurrence, reminder.target_date, reminder.user.timezone) log.info( f"{reminder.id} recurring from {utils.get_datetime_string(reminder.target_date)} to " f"{utils.get_datetime_string(new_target_date)}") reminder.target_date = new_target_date reminder.user.recurring_sent += 1 else: log.debug(f"{reminder.id} deleted") database.delete_reminder(reminder) database.commit() else: log.debug("No reminders to send") return reminders_sent
def process_cakeday_message(message, database): log.info("Processing cakeday") if database.get_cakeday(message.author.name) is not None: log.info("Cakeday already exists") return ["It looks like you already have a cakeday reminder set."] account_created = utils.datetime_from_timestamp(message.author.created_utc) next_anniversary = utils.add_years( account_created, utils.datetime_now().year - account_created.year) if next_anniversary < utils.datetime_now(): next_anniversary = utils.add_years(next_anniversary, 1) log.debug( f"u/{message.author.name} created {utils.get_datetime_string(account_created)}, " f"anniversary {utils.get_datetime_string(next_anniversary)}") cakeday = Cakeday(message.author.name, next_anniversary) database.add_cakeday(cakeday) return cakeday.render_confirmation( database.get_settings(message.author.name).timezone)
async def insert_into_users(self, user_code, client_type): result = await self._conn.execute(users.insert().values( user_code=user_code, client_type=client_type, name=None, phone=None, address=None, tms_create=datetime_now(), )) async for row in result: user_id = row[0] return user_id
def ban_subreddit(self, subreddit): log.debug(f"Banning subreddit: {subreddit}") c = self.dbConn.cursor() c.execute( ''' SELECT Banned FROM subreddits WHERE Subreddit = ? ''', (subreddit, )) result = c.fetchone() if result is None or len(result) == 0: try: c.execute( ''' INSERT INTO subreddits (Subreddit, Banned, BanChecked) VALUES (?, ?, ?) ''', (subreddit, True, utils.get_datetime_string(utils.datetime_now()))) except sqlite3.IntegrityError as err: log.warning(f"Failed to ban subreddit: {err}") return False else: try: c.execute( ''' UPDATE subreddits SET Banned = ? ,BanChecked = ? WHERE Subreddit = ? ''', (True, utils.get_datetime_string(utils.datetime_now()), subreddit)) except sqlite3.IntegrityError as err: log.warning(f"Failed to update subreddit ban: {err}") return False self.dbConn.commit() return True
def __init__(self, domain, period, hyperparameters, domain_limits): self.LAT_S, self.LAT_N, self.LON_W, self.LON_E = domain self.domain = domain d_str = '_'.join(str(i) for i in self.domain) self.dir_str = f'{d_str}' self.iterations, self.gridsize, self.training_mode, self.sigma, self.learning_rate, self.random_seed = hyperparameters self.dir_hp_str = f'{d_str}_{self.iterations}iter_{self.gridsize}x{self.gridsize}_{self.sigma}sig_{self.learning_rate}lr' self.period = period self.hyperparameters = hyperparameters self.RUN_datetime = utils.datetime_now() self.RUN_time = utils.time_now() self.domain_limits = domain_limits self.domain_limits_str = '_'.join(str(i) for i in domain_limits) # evaluation params self.ALPHAs = None # i.d. of PSI split dataset, distributed automatically
def test_commenting_deleted(database, reddit): comment_id = reddit_test.random_id() thread_id = reddit_test.random_id() comment = reddit_test.RedditObject( body=f"{static.TRIGGER}! 1 day", author="Watchful1", created=utils.datetime_now(), id=comment_id, link_id="t3_" + thread_id, permalink=f"/r/test/{thread_id}/_/{comment_id}/", subreddit="test") comments.process_comment(comment.get_pushshift_dict(), reddit, database) assert len(comment.children) == 0 assert len(reddit.sent_messages) == 1 assert "it was deleted before I could get to it" in reddit.sent_messages[ 0].body
def check_curriculum_updated(uid): """Checks if the curriculum has updated within `CURR_UPDATE_TIME_LIMIT`\n Return: `bool`""" res = db.session.execute( text('SELECT * FROM Course.curriculum_check WHERE uid=:uid'), {'uid': uid}) if res.rowcount: if res.rowcount > 1: raise RuntimeError('More than one uid existed in curriculum_check') p = res.fetchone() # person dt = utils.datetime_from_timestamp(p['time']) now = utils.datetime_now() if DISABLE_CURR_UPDATE_TIME_LIMIT: return False return now - dt < CURR_UPDATE_TIME_LIMIT else: return False
def get_subreddit_banned(self, subreddit): log.debug(f"Getting subreddit ban: {subreddit}") c = self.dbConn.cursor() c.execute( ''' SELECT Banned FROM subreddits WHERE Subreddit = ? AND BanChecked > ? ''', (subreddit, utils.get_datetime_string(utils.datetime_now() - timedelta(days=30)))) result = c.fetchone() if result is None or len(result) == 0: log.debug("Not banned") return False log.debug(f"Value: {result[0] == 1}") return result[0] == 1
def test_commenting_locked(database, reddit): thread_id = reddit_test.random_id() reddit.lock_thread(thread_id) comment_id = reddit_test.random_id() comment = reddit_test.RedditObject( body=f"{static.TRIGGER}! 1 day", author="Watchful1", created=utils.datetime_now(), id=comment_id, link_id="t3_" + thread_id, permalink=f"/r/test/{thread_id}/_/{comment_id}/", subreddit="test") reddit.add_comment(comment) comments.process_comment(comment.get_pushshift_dict(), reddit, database) assert len(comment.children) == 0 assert len(reddit.sent_messages) == 1 assert "the thread is locked" in reddit.sent_messages[0].body
def test_commenting_banned(database, reddit): reddit.ban_subreddit("test") comment_id = reddit_test.random_id() thread_id = reddit_test.random_id() comment = reddit_test.RedditObject( body=f"{static.TRIGGER}! 1 day", author="Watchful1", created=utils.datetime_now(), id=comment_id, link_id="t3_" + thread_id, permalink=f"/r/test/{thread_id}/_/{comment_id}/", subreddit=reddit.subreddits["test"]) reddit.add_comment(comment) comments.process_comment(comment.get_pushshift_dict(), reddit, database) assert len(comment.children) == 0 assert len(reddit.sent_messages) == 1 assert "I'm not allowed to reply in this subreddit" in reddit.sent_messages[ 0].body
def test_timezone_reminder_message(database, reddit): user = database.get_or_add_user(user_name="Watchful1") user.timezone = "America/Los_Angeles" created = utils.datetime_now() target = created + timedelta(hours=24) username = "******" message = reddit_test.RedditObject( body= f"{static.TRIGGER}! {utils.get_datetime_string(utils.datetime_as_timezone(target, user.timezone))}", author=username, created=created) messages.process_message(message, reddit, database) reminders = database.get_all_user_reminders(username) assert len(reminders) == 1 assert reminders[0].requested_date == created assert reminders[0].target_date == utils.datetime_as_utc( pytz.timezone(user.timezone).localize(target.replace(tzinfo=None)))
def test_process_comment_split_not_start(database, reddit): created = utils.datetime_now() username = "******" comment_id = reddit_test.random_id() thread_id = reddit_test.random_id() comment = reddit_test.RedditObject( body=f"this is a test {static.TRIGGER_SPLIT}! 1 day", author=username, created=created, id=comment_id, link_id="t3_" + thread_id, permalink=f"/r/test/{thread_id}/_/{comment_id}/", subreddit="test") reddit.add_comment(comment) comments.process_comment(comment.get_pushshift_dict(), reddit, database) assert len(comment.children) == 0 reminders = database.get_all_user_reminders(username) assert len(reminders) == 0
def init(self, debug, publish, clone): if debug: if clone: if os.path.exists(static.DATABASE_DEBUG_NAME): os.remove(static.DATABASE_DEBUG_NAME) copyfile(static.DATABASE_NAME, static.DATABASE_DEBUG_NAME) self.dbConn = sqlite3.connect(static.DATABASE_DEBUG_NAME) else: self.dbConn = sqlite3.connect(static.DATABASE_NAME) c = self.dbConn.cursor() if publish: for table in Database.tables: c.execute(f"DROP TABLE IF EXISTS {table}") for table in Database.tables: c.execute(Database.tables[table]) if self.get_keystore("remindme_comment") is None: self.save_keystore("remindme_comment", utils.get_datetime_string(utils.datetime_now())) self.dbConn.commit()
def test_add_reminder_no_date(database, reddit): created = utils.datetime_now() username = "******" id = reddit_test.random_id() message = reddit_test.RedditObject( body=f"{static.TRIGGER}! \"error test\"", author=username, created=created, id=id) messages.process_message(message, reddit, database) result = message.get_first_child().body assert "This time has already passed" not in result assert "Could not find a time in message, defaulting to one day" in result reminders = database.get_all_user_reminders(username) assert len(reminders) == 1 assert reminders[0].user.name == username assert reminders[0].message == "error test" assert reminders[0].source == utils.message_link(id) assert reminders[0].requested_date == created assert reminders[0].target_date == created + timedelta(hours=24) assert reminders[0].id is not None
def get_reminders_string(user_name, database, previous=False, include_all=False): result_messages = [] bldr = utils.str_bldr() regular_reminders, recurring_reminders = database.get_user_reminders( user_name) if len(regular_reminders) or len(recurring_reminders): if previous: bldr.append("Your previous reminders:") else: bldr.append("Your current reminders:") bldr.append("\n\n") if len(regular_reminders) + len(recurring_reminders) > 1: bldr.append("[Click here to delete all your reminders](") bldr.append( utils.build_message_link(static.ACCOUNT_NAME, "Remove All", "RemoveAll!")) bldr.append(")\n\n") user = database.get_or_add_user(user_name) if user.timezone is not None: bldr.append("Your timezone is currently set to: `") bldr.append(user.timezone) bldr.append("`\n\n") for reminders in [recurring_reminders, regular_reminders]: if len(reminders): log.debug(f"Building list with {len(reminders)} reminders") add_list_header(bldr, reminders[0].recurrence is not None) for reminder in reminders: bldr.append("|") if "reddit.com" in reminder.source: bldr.append("[Source](") bldr.append( utils.check_append_context_to_link( reminder.source)) bldr.append(")") else: bldr.append(reminder.source) bldr.append("|") if reminder.message is not None: bldr.append(reminder.message.replace("|", "|")) bldr.append("|") bldr.append( utils.render_time(reminder.target_date, reminder.user)) bldr.append("|") bldr.append( utils.render_time_diff(utils.datetime_now(), reminder.target_date)) if reminder.recurrence is not None: bldr.append("|") bldr.append(reminder.recurrence) bldr.append("|") bldr.append("[Remove](") bldr.append( utils.build_message_link(static.ACCOUNT_NAME, "Remove", f"Remove! {reminder.id}")) bldr.append(")") bldr.append("|\n") if utils.bldr_length(bldr) > 9000: if include_all: result_messages.append(''.join(bldr)) bldr = [] add_list_header( bldr, reminders[0].recurrence is not None) else: bldr.append("\nToo many reminders to display.") break bldr.append("\n") else: bldr.append("You don't have any reminders.") result_messages.append(''.join(bldr)) return result_messages
log = discord_logging.init_logging() import utils cal = parsedatetime.Calendar() input_string = '''RemindMe May 7, 2021 16:00 PM "Reminder, an AMA with Shane Mauss, Dr. Peter McGraw - Comedian Shane Mauss Dr. Peter McGraw behavioral economist to start in /r/IAmA right now!"''' base_time_string = None #"2020-07-25 20:00:00 -0800" timezone_string = None #"America/Los_Angeles" if base_time_string: base_time = utils.datetime_as_timezone( utils.parse_datetime_string(base_time_string, False, '%Y-%m-%d %H:%M:%S %z'), "UTC") else: base_time = utils.datetime_now() format_string = '%Y-%m-%d %H:%M:%S %Z' log.info(f"Input string: {input_string}") times = re.findall(r'(?:remindme.? +)(.*?)(?:\[|\n|\"|“|$)', input_string.lower(), flags=re.IGNORECASE) if len(times) > 0 and times[0] != "": log.info(f"Result: {times[0]}") time_string = times[0][:50] log.info(f"Result truncated: {time_string}") else: log.info(f"No string found") sys.exit(0)