Exemple #1
0
def main():
    # Verify python version is >=3.5
    #   req_version is 3.5 due to usage of subprocess.run
    assert_version((3, 5))

    if sys.platform.startswith("linux") and ("DISPLAY" not in os.environ
                                             or not os.environ["DISPLAY"]):
        raise Exception("DISPLAY environment variable not set")

    # Read settings from config
    config = load_config()
    args = parse_args(default_poll_time=config.getfloat("poll_time"),
                      default_exclude_title=config.getboolean("exclude_title"))

    setup_logging(name="aw-watcher-window",
                  testing=args.testing,
                  verbose=args.verbose,
                  log_stderr=True,
                  log_file=True)

    client = ActivityWatchClient("aw-watcher-window", testing=args.testing)

    bucket_id = "{}_{}".format(client.client_name, client.client_hostname)
    event_type = "currentwindow"

    client.create_bucket(bucket_id, event_type, queued=True)

    logger.info("aw-watcher-window started")
    sleep(1)  # wait for server to start
    with client:
        heartbeat_loop(client,
                       bucket_id,
                       poll_time=args.poll_time,
                       exclude_title=args.exclude_title)
Exemple #2
0
def heartbeat(bucket_name,start_time,activity):
    client = ActivityWatchClient("aw-watcher-cli", testing=False)
    bucket_id = "{}_{}".format(bucket_name, client.hostname)
    event_type = "cli_ping"
    client.create_bucket(bucket_id, event_type=event_type)
    # Asynchronous loop
    with client:
        heartbeat_data = {"label": "heartbeat"}
        now = datetime.now(timezone.utc)
        heartbeat_event = Event(timestamp=now, data=heartbeat_data)
        sleeptime = 1
        #Sending hearbeat until keyboard interrup
        second = 1
        while(True):
            # The duration between the heartbeats will be less than pulsetime, so they will get merged.
            rd = relativedelta.relativedelta (now, start_time)
            print("Doing: {} for {:02}:{:02}:{:02}".format(activity,rd.hours, rd.minutes, rd.seconds),end="\r")
            client.heartbeat(bucket_id, heartbeat_event, pulsetime=sleeptime+1, queued=True)
            # Sleep a second until next heartbeat
            sleep(sleeptime)
            # Update timestamp for next heartbeat
            heartbeat_event.timestamp = datetime.now(timezone.utc)
            # update now
            now = heartbeat_event.timestamp
            second += 1
def main():
    # Verify python version is >=3.5
    #   req_version is 3.5 due to usage of subprocess.run
    assert_version((3, 5))

    if sys.platform.startswith("linux") and ("DISPLAY" not in os.environ or not os.environ["DISPLAY"]):
        raise Exception("DISPLAY environment variable not set")

    # Read settings from config
    config = load_config()
    args = parse_args(default_poll_time=config.getfloat("poll_time"))

    setup_logging(name="aw-watcher-window", testing=args.testing, verbose=args.verbose,
                  log_stderr=True, log_file=True)

    client = ActivityWatchClient("aw-watcher-window", testing=args.testing)

    bucket_id = "{}_{}".format(client.client_name, client.client_hostname)
    event_type = "currentwindow"

    client.create_bucket(bucket_id, event_type, queued=True)

    logger.info("aw-watcher-window started")
    sleep(1)  # wait for server to start
    with client:
        heartbeat_loop(client, bucket_id, poll_time=args.poll_time, exclude_title=args.exclude_title)
def main():
    import argparse

    parser = argparse.ArgumentParser("A watcher for ping")
    parser.add_argument("--testing", action="store_true")

    args = parser.parse_args()

    logging.basicConfig(level=logging.DEBUG if args.testing else logging.INFO)
    client = ActivityWatchClient("aw-watcher-network", testing=args.testing)

    bucketname = "{}_{}".format(client.client_name, client.client_hostname)
    eventtype = "ping"
    client.create_bucket(bucketname, eventtype)
    logger.info("Starting to log ping")


    while True:
        t = datetime.utcnow()
        sleeptime = 60 - (t.second + t.microsecond/1000000.0)
        sleep(sleeptime)
        timestamp = datetime.now(pytz.utc)
        wifiname = Wireless().current()
        try:
            out = ping(30)
            client.send_events(bucketname, createEvents(out,timestamp,wifiname))
            logger.info("Sent events")
                
        except Exception as e:
            import sys, traceback
            traceback.print_exc()
            logger.error("Exception thrown while pinging {}".format(e))
Exemple #5
0
def main():
    import argparse

    parser = argparse.ArgumentParser("A watcher for ping")
    parser.add_argument("--testing", action="store_true")

    args = parser.parse_args()

    logging.basicConfig(level=logging.DEBUG if args.testing else logging.INFO)
    client = ActivityWatchClient("aw-watcher-network", testing=args.testing)

    bucketname = "{}_{}".format(client.client_name, client.client_hostname)
    eventtype = "ping"
    client.create_bucket(bucketname, eventtype)
    logger.info("Starting to log ping")

    while True:
        t = datetime.utcnow()
        sleeptime = 60 - (t.second + t.microsecond / 1000000.0)
        sleep(sleeptime)
        timestamp = datetime.now(pytz.utc)
        wifiname = Wireless().current()
        try:
            out = ping(30)
            client.send_events(bucketname,
                               createEvents(out, timestamp, wifiname))
            logger.info("Sent events")

        except Exception as e:
            import sys, traceback
            traceback.print_exc()
            logger.error("Exception thrown while pinging {}".format(e))
Exemple #6
0
def main():
    import argparse

    poll_time = 1.0

    parser = argparse.ArgumentParser("A watcher for windows in X11")
    parser.add_argument("--testing", action="store_true")

    args = parser.parse_args()

    logging.basicConfig(level=logging.DEBUG if args.testing else logging.INFO)
    client = ActivityWatchClient("x11watcher", testing=args.testing)

    bucketname = "{}_{}".format(client.client_name, client.client_hostname)
    eventtype = "currentwindow"
    client.create_bucket(bucketname, eventtype)

    # get_only_active = True

    last_window = []
    while True:
        try:
            # wids = xprop.get_window_ids()
            active_window_id = xprop.get_active_window_id()
            if active_window_id == "0x0":
                print("Failed to find active window, id found was 0x0")
                sleep(poll_time)
                continue

            # Always true, getting all windows currently not supported
            # if get_only_active:
            current_window = xprop.get_windows([active_window_id],
                                               active_window_id)[0]
            # else:
            #    current_windows = get_windows(wids, active_window_id)
            """
            if last_windows != current_windows:
                last_windows = current_windows
                print("Windows changed")
                client.send_event(Event(windows=last_windows, timestamp=datetime.now()))
                print(current_windows)
            """

            if last_window != current_window:
                last_window = current_window
                print("Window changed")
                labels = ["title:" + current_window["name"]]
                labels.extend(
                    ["class:" + cls for cls in set(current_window["class"])])
                client.send_event(
                    bucketname,
                    Event(label=labels, timestamp=datetime.now(pytz.utc)))
                print(current_window)
        except Exception as e:
            logger.error(
                "Exception thrown while trying to get active window: {}".
                format(e))
            traceback.print_exc(e)
        sleep(poll_time)
Exemple #7
0
def shutdown(bucket_name,start_time,end_time,activity):
    client = ActivityWatchClient("aw-watcher-cli", testing=False)
    bucket_id = "{}_{}".format(bucket_name, client.hostname)
    event_type = "cli_activity"
    client.create_bucket(bucket_id, event_type=event_type)
    shutdown_data = {"label": activity}
    shutdown_event = Event(timestamp=start_time, data=shutdown_data, duration=(end_time -start_time))
    inserted_event = client.insert_event(bucket_id, shutdown_event)
    rd = relativedelta.relativedelta (end_time, start_time)
    print("Spent {:02}:{:02}:{:02} doing {}:".format(rd.hours, rd.minutes, rd.seconds,activity))
Exemple #8
0
def windows_watcher_run() -> None:
    client = ActivityWatchClient("aw-watcher-window", testing=False)

    bucket_id = "{}_{}".format(client.client_name, client.client_hostname)
    event_type = "currentwindow"

    client.create_bucket(bucket_id, event_type, queued=True)
    sleep(1)  # wait for server to start
    with client:
        heartbeat_loop(client, bucket_id, poll_time=2.0, exclude_title=False)
Exemple #9
0
def main():
    import argparse

    poll_time = 1.0

    parser = argparse.ArgumentParser("A watcher for windows in X11")
    parser.add_argument("--testing", action="store_true")

    args = parser.parse_args()

    logging.basicConfig(level=logging.DEBUG if args.testing else logging.INFO)
    client = ActivityWatchClient("x11watcher", testing=args.testing)

    bucketname = "{}_{}".format(client.client_name, client.client_hostname)
    eventtype = "currentwindow"
    client.create_bucket(bucketname, eventtype)

    # get_only_active = True

    last_window = []
    while True:
        try:
            # wids = xprop.get_window_ids()
            active_window_id = xprop.get_active_window_id()
            if active_window_id == "0x0":
                print("Failed to find active window, id found was 0x0")
                sleep(poll_time)
                continue

            # Always true, getting all windows currently not supported
            # if get_only_active:
            current_window = xprop.get_windows([active_window_id], active_window_id)[0]
            # else:
            #    current_windows = get_windows(wids, active_window_id)

            """
            if last_windows != current_windows:
                last_windows = current_windows
                print("Windows changed")
                client.send_event(Event(windows=last_windows, timestamp=datetime.now()))
                print(current_windows)
            """

            if last_window != current_window:
                last_window = current_window
                print("Window changed")
                labels = ["title:" + current_window["name"]]
                labels.extend(["class:" + cls for cls in set(current_window["class"])])
                client.send_event(bucketname,
                                  Event(label=labels, timestamp=datetime.now(pytz.utc)))
                print(current_window)
        except Exception as e:
            logger.error("Exception thrown while trying to get active window: {}".format(e))
            traceback.print_exc(e)
        sleep(poll_time)
Exemple #10
0
def setup_client():
    logging.info("Setting up client")
    client = ActivityWatchClient("aw-fake-client", testing=True)
    client.client_hostname = hostname

    eventtype = "currentwindow"
    client.create_bucket(window_bucket_name, eventtype)

    eventtype = "afkstatus"
    client.create_bucket(afk_bucket_name, eventtype)

    client.connect()
    return client
Exemple #11
0
def main():
    import argparse

    parser = argparse.ArgumentParser(
        "A watcher for applications with activationPolicy=regular")
    parser.add_argument("--testing", action="store_true")

    args = parser.parse_args()

    logging.basicConfig(level=logging.DEBUG if args.testing else logging.INFO)
    client = ActivityWatchClient("macoswatcher", testing=args.testing)

    bucketname = "{}_{}".format(client.client_name, client.client_hostname)
    eventtype = "currentwindow"
    client.create_bucket(bucketname, eventtype)

    last_app = ""
    last_title = ""
    info = getInfo()
    print(info)
    active_app = getApp(info)
    active_title = getTitle(info)
    if (active_title == ""):
        logger.error(
            "Title of active window not found. Does the terminal have access to accessibility API? See README for how to give access!"
        )

    while True:
        try:
            info = getInfo()
            active_app = getApp(info)
            active_title = getTitle(info)

            if (last_app != active_app or last_title != active_title):
                last_app = active_app
                last_title = active_title
                client.send_event(
                    bucketname,
                    Event(label=[active_app, active_title],
                          timestamp=datetime.now(pytz.utc)))
                print(active_app + ", " + active_title)
        except Exception as e:
            logger.error(
                "Exception thrown while trying to get active applications {}".
                format(e))
        sleep(0.5)
def end_current_event(start_ts, category, item, end_dt=None):
    start_dt = datetime.utcfromtimestamp(start_ts)
    if end_dt is None:
        end_dt = datetime.utcnow()
    app.logger.debug('Instantiating client (127.0.0.1:5600)')
    client = ActivityWatchClient(
        "aw-watcher-manual-flaskweb", host='127.0.0.1:5600'
    )
    bucket_id = "{}_{}".format("aw-watcher-manual-flaskweb", client.hostname)
    app.logger.debug('Creating bucket: %s', bucket_id)
    client.create_bucket(bucket_id, event_type="currentwindow")
    t = 'manual: %s/%s' % (category, item)
    evt = Event(
        timestamp=start_dt, duration=(end_dt - start_dt).total_seconds(),
        data={'app': t, 'title': t, 'category': category, 'item': item}
    )
    inserted_event = client.insert_event(bucket_id, evt)
    app.logger.info('Inserted event: %s', inserted_event)
Exemple #13
0
def send_to_activitywatch(events):
    print("Sending events to ActivityWatch...")

    hostname = "macos-screentime-test"

    # NOTE: 'aw-watcher-android' string is only there for aw-webui to detect it as a mobile device
    bucket = f"aw-watcher-android_aw-import-screentime_{hostname}"

    aw = ActivityWatchClient(client_name="aw-import-screentime")
    aw.client_hostname = hostname

    # buckets = aw.get_buckets()
    # if bucket in buckets.keys():
    #     ans = input("Bucket already found, overwrite? (y/N): ")
    #     if ans == "y":
    #         aw.delete_bucket(bucket, force=True)

    aw.create_bucket(bucket, "currentwindow")
    aw.send_events(bucket, events)
Exemple #14
0
class CLIWatcher:
    def __init__(self, bucket, etype, testing=False):
        self.client = ActivityWatchClient("aw-watcher-cli", testing=testing)
        self.bucketname = bucket
        self.etype = etype
        self.client.create_bucket(self.bucketname, event_type=self.etype)

    def run(self):
        logger.info(
            "aw-watcher-cli started for bucket '%s' containing events of type '%s'"
            % (self.bucketname, self.etype))

    def updateLastEvent(self):
        logger.info("Updating previous event duration.")
        try:
            last = self.client.get_events(bucket_id=self.bucketname,
                                          limit=1)[0]
        except IndexError:
            logger.info("No previous event found.")
            return

        duration = abs((datetime.now(timezone.utc) - last.timestamp).seconds)
        logger.info(
            "Previous event '%s' occurred at %s. Duration since: %ss" %
            (last.data, last.timestamp.strftime("%Y-%m-%d %T%z"), duration))
        last.duration = duration
        self.client.insert_event(self.bucketname, last)

    def addStringEvent(self, eventString, duration):
        logger.info("Adding event %s (duration: %s) to bucket %s" %
                    (eventString, duration, self.bucketname))
        data = {"label": eventString}
        event = Event(timestamp=datetime.now(timezone.utc),
                      data=data,
                      duration=duration)
        inserted_event = self.client.insert_event(self.bucketname, event)

        assert inserted_event.id is not None
Exemple #15
0
def main():
    # Read settings from config
    config = load_config()
    args = parse_args(
        default_poll_time=config.getfloat("poll_time"),
        default_exclude_title=config.getboolean("exclude_title"),
    )

    if sys.platform.startswith("linux") and ("DISPLAY" not in os.environ
                                             or not os.environ["DISPLAY"]):
        raise Exception("DISPLAY environment variable not set")

    setup_logging(name="aw-watcher-window",
                  testing=args.testing,
                  verbose=args.verbose,
                  log_stderr=True,
                  log_file=True)

    if sys.platform == "darwin":
        from . import macos
        macos.background_ensure_permissions()

    client = ActivityWatchClient("aw-watcher-window", testing=args.testing)

    bucket_id = "{}_{}".format(client.client_name, client.client_hostname)
    event_type = "currentwindow"

    client.create_bucket(bucket_id, event_type, queued=True)

    logger.info("aw-watcher-window started")

    sleep(1)  # wait for server to start
    with client:
        heartbeat_loop(client,
                       bucket_id,
                       poll_time=args.poll_time,
                       exclude_title=args.exclude_title)
Exemple #16
0
def setup_client() -> ActivityWatchClient:
    logger.info("Setting up client")

    # Default is to run in testing mode, can be run in prod mode if set to exactly 'false'
    testing = os.getenv("AW_TESTING", "true").lower() not in ["false"]
    if testing:
        logger.info(
            "Using testing parameters (set the env var AW_TESTING to false to run in prod mode)"
        )

    client = ActivityWatchClient(client_name, testing=testing)
    client.client_hostname = hostname

    buckets = client.get_buckets()
    logger.info("Deleting old buckets")
    buckets_all = [
        bucket_afk,
        bucket_window,
        bucket_browser_chrome,
        bucket_browser_firefox,
    ]

    if not testing:
        ans = input(
            f"Running in prod, are you sure you want to delete all existing buckets?\n{buckets_all}\nAre you sure? (y/N)"
        )
        if ans != "y":
            print("Exiting")
            sys.exit(0)

    for bucket in [
        bucket_window,
        bucket_afk,
        bucket_browser_chrome,
        bucket_browser_firefox,
    ]:
        if bucket in buckets:
            client.delete_bucket(bucket, force=True)

    client.create_bucket(bucket_window, "currentwindow")
    client.create_bucket(bucket_afk, "afkstatus")

    client.create_bucket(bucket_browser_chrome, "web.tab.current")
    client.create_bucket(bucket_browser_firefox, "web.tab.current")

    client.connect()
    return client
def test_failqueue():
    client_name = "aw-test-client-" + str(randint(0, 10000))
    bucket_id = "test-bucket-" + str(randint(0, 10000))
    bucket_etype = "test"

    input("Make sure aw-server isn't running, then press enter > ")
    client1 = ActivityWatchClient(client_name, testing=True)
    client1.create_bucket(bucket_id, bucket_etype, queued=True)

    print("Creating events")
    events = [create_unique_event() for _ in range(3)]
    for i, e in enumerate(events):
        e.timestamp += timedelta(seconds=i)
        client1.heartbeat(bucket_id, e, pulsetime=1, queued=True)

    print("Trying to send events (should fail)")
    with client1:
        time.sleep(1)

    input("Start aw-server with --testing, then press enter > ")

    client2 = ActivityWatchClient(client_name, testing=True)
    client2.create_bucket(bucket_id, bucket_etype, queued=True)

    # Here the previously queued events should be sent
    with client2:
        time.sleep(1)

    print("Getting events")
    recv_events = client2.get_events(bucket_id)

    print("Asserting latest event")
    pprint(recv_events)
    pprint(recv_events[0].data['label'])
    pprint(events[2].data['label'])
    assert recv_events[0].data['label'] == events[2].data['label']
Exemple #18
0
def test_failqueue():
    client_name = "aw-test-client-" + str(randint(0, 10000))
    bucket_id = "test-bucket-" + str(randint(0, 10000))
    bucket_etype = "test"

    input("Make sure aw-server isn't running, then press enter > ")
    client1 = ActivityWatchClient(client_name, testing=True)
    client1.create_bucket(bucket_id, bucket_etype, queued=True)

    print("Creating events")
    events = [create_unique_event() for _ in range(3)]
    for i, e in enumerate(events):
        e.timestamp += timedelta(seconds=i)
        client1.heartbeat(bucket_id, e, pulsetime=1, queued=True)

    print("Trying to send events (should fail)")
    with client1:
        time.sleep(1)

    input("Start aw-server with --testing, then press enter > ")

    client2 = ActivityWatchClient(client_name, testing=True)
    client2.create_bucket(bucket_id, bucket_etype, queued=True)

    # Here the previously queued events should be sent
    with client2:
        time.sleep(1)

    print("Getting events")
    recv_events = client2.get_events(bucket_id)

    print("Asserting latest event")
    pprint(recv_events)
    pprint(recv_events[0].data['label'])
    pprint(events[2].data['label'])
    assert recv_events[0].data['label'] == events[2].data['label']
Exemple #19
0
now = datetime.now(tz=timezone.utc)

# We'll run with testing=True so we don't mess up any production instance.
# Make sure you've started aw-server with the `--testing` flag as well.
client = ActivityWatchClient("test-client", testing=True)
bucket_id = "test-bucket"
example_data = {"label": "example"}
example_event = Event(timestamp=now, data=example_data)

# Asynchronous example
with client:
    # This context manager starts the queue dispatcher thread and stops it when done, always use it when setting queued=True.

    # First we need a bucket to send events/heartbeats to.
    client.create_bucket(bucket_id, event_type="test", queued=True)

    # Now we can send some heartbeats.
    # The duration between them will be less than pulsetime, so they will get merged.
    client.heartbeat(bucket_id, example_event, pulsetime=10, queued=True)

    example_event.timestamp += timedelta(seconds=5)
    client.heartbeat(bucket_id, example_event, pulsetime=10, queued=True)

    # Give the dispatcher thread some time to complete sending the events
    sleep(1)

# Synchronous example
example_event.timestamp += timedelta(minutes=1)
inserted_event = client.insert_event(bucket_id, example_event)
Exemple #20
0
    return Event(timestamp=datetime.now(timezone.utc),
                 duration=timedelta(),
                 data={"label": str(random())})


client = ActivityWatchClient("aw-test-client", testing=True)
client.connect()

bucket_name = "test-bucket"
bucket_etype = "test"
# Delete bucket before creating it, and handle error if it doesn't already exist
try:
    client.delete_bucket(bucket_name)
except HTTPError as e:
    pass
client.create_bucket(bucket_name, bucket_etype)

e1 = create_unique_event()
client.insert_event(bucket_name, e1)

print("Getting events")
events = client.get_events(bucket_name)

print("Asserting events")
assert events[0]['data']['label'] == e1['data']['label']

print("Getting eventcount")
eventcount = client.get_eventcount(bucket_name)
assert eventcount == 1

print("Getting bucket")
from aw_core.models import Event
from aw_client import ActivityWatchClient

client = ActivityWatchClient("test-client", testing=True)

now = datetime.now(timezone.utc)
start = now

query = "RETURN=0;"
res = client.query(query, "1970-01-01", "2100-01-01")
print(res) # Should print 0

bucket_id = "{}_{}".format("test-client-bucket", client.hostname)
event_type = "dummydata"
client.create_bucket(bucket_id, event_type="test")

def insert_events(label: str, count: int):
    global now
    events = []
    for i in range(count):
        e = Event(timestamp=now,
                   duration=timedelta(seconds=1),
                   data={"label": label})
        events.append(e)
        now = now + timedelta(seconds=1)
    client.insert_events(bucket_id, events)

insert_events("a", 5)

query = "RETURN = query_bucket('{}');".format(bucket_id)
Exemple #22
0
class AfkRunner:
    def __init__(self, poll_time: int = 5, timeout: int = 180) -> None:
        self.client = ActivityWatchClient("aw-watcher-afk", testing=False)
        self.bucketname = "{}_{}".format(
            self.client.client_name,
            self.client.client_hostname
        )
        self.poll_time = poll_time
        self.timeout = timeout
        self.initiated_shutdown: bool = False

    def ping(self,
             afk: bool,
             timestamp: datetime,
             duration: float = 0
             ) -> None:
        data = {"status": "afk" if afk else "not-afk"}
        e = Event(timestamp=timestamp, duration=duration, data=data)
        pulsetime = self.timeout + self.poll_time
        self.client.heartbeat(
            self.bucketname,
            e,
            pulsetime=pulsetime,
            queued=True
        )

    def run(self) -> None:
        # Initialization
        sleep(1)

        eventtype = "afkstatus"
        self.client.create_bucket(self.bucketname, eventtype, queued=True)

        with self.client:
            self.heartbeat_loop()

    def stop(self) -> None:
        self.initiated_shutdown = True

    def heartbeat_loop(self) -> None:
        afk = False
        while True:
            if self.initiated_shutdown:
                self.initiated_shutdown = False
                break
            try:
                if system() in ["Darwin", "Linux"] and os.getppid() == 1:
                    break

                now = datetime.now(timezone.utc)
                seconds_since_input = seconds_since_last_input()
                last_input = now - timedelta(seconds=seconds_since_input)

                # If no longer AFK
                if afk and seconds_since_input < self.timeout:
                    self.ping(afk, timestamp=last_input)
                    afk = False
                    self.ping(afk, timestamp=last_input)
                # If becomes AFK
                elif not afk and seconds_since_input >= self.timeout:
                    self.ping(afk, timestamp=last_input)
                    afk = True
                    self.ping(
                        afk,
                        timestamp=last_input,
                        duration=seconds_since_input
                    )
                # Send a heartbeat if no state change was made
                else:
                    if afk:
                        self.ping(
                            afk,
                            timestamp=last_input,
                            duration=seconds_since_input
                        )
                    else:
                        self.ping(afk, timestamp=last_input)

                sleep(self.poll_time)

            except KeyboardInterrupt:
                break
Exemple #23
0
            # print(title)
            # print(start, duration)
            # if attendees:
            #     for attendee in attendees:
            #         print(attendee)
            # print(e)
            # print(component)
            # print(80 * "-")
    return events


if __name__ == "__main__":
    filename = sys.argv.pop()
    events = load_events(filename)
    print(f"Loaded {len(events)} events")
    aw = ActivityWatchClient(testing=True)

    bucket_name = 'ical-import'

    if bucket_name in aw.get_buckets():
        aw.delete_bucket(bucket_name)

    aw.create_bucket(bucket_name, 'calendar')
    aw.insert_events(bucket_name, events)
"""
Basic query:

events = query_bucket(find_bucket('ical-import'));
RETURN = filter_keyvals_regex(events, 'title', '\<\>'));
"""
class MessageHandler:
    def __init__(self,
                 testing=False,
                 send_commands=True,
                 send_heartbeats=True):
        # Create client
        self._client = ActivityWatchClient(client_id, testing=testing)
        self._client.connect()
        self._init_buckets()

        # Settings
        self.pulsetime = 10
        self.send_commands = send_commands
        self.send_heartbeats = send_heartbeats

        # Initialize the EventQueue
        self._event_queue = EventQueue(callback=self._handle_event,
                                       time_buffer=(self.pulsetime / 2))

        self._event_handlers = {
            'preopen': self._preopen,
            'preexec': self._preexec,
            'precmd': self._precmd,
            'preclose': self._preclose
        }

        self._terminal_sessions = {}

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._client.disconnect()

    def _init_buckets(self):
        """Set self._buckets and create these buckets if not existing"""
        self._buckets = {
            'commands': {
                'id': "{}-commands_{}".format(client_id,
                                              self._client.hostname),
                'event_type': 'app.terminal.command'
            },
            'activity': {
                'id': "{}-activity_{}".format(client_id,
                                              self._client.hostname),
                'event_type': 'app.terminal.activity'
            }
        }

        # Create buckets if not existing
        for key, bucket in self._buckets.items():
            logger.debug("Creating bucket: {}".format(bucket['id']))
            self._client.create_bucket(bucket['id'],
                                       bucket['event_type'],
                                       queued=True)

    def update_event_queue(self):
        self._event_queue.update()

    def handle_fifo_message(self, message):
        for line in message.split('\n'):
            if not len(line):
                continue

            cli_args = shlex.split(line)
            args, unknown_args = parser_base.parse_known_args(cli_args)

            # Make sure that events are called in the right order
            # (based on args.timestamp) by passing it to the event queue
            # The event queue will trigger the callback when the time_buffer
            # is exceeded
            logger.debug("adding event to event_queue: {}".format(cli_args))
            self._event_queue.add_event(cli_args, args.timestamp)

    def _handle_event(self, cli_args):
        logger.debug("handling event: {}".format(cli_args))
        args, unknown_args = parser_base.parse_known_args(cli_args)

        # Store terminal session if not already existing
        pid = args.pid
        if pid not in self._terminal_sessions:
            self._terminal_sessions[pid] = TerminalSessionData(pid)

        if self.send_commands:
            if args.event not in self._event_handlers:
                logger.error("Unknown event: {}".format(args.event))
            else:
                self._event_handlers[args.event](cli_args)

        if self.send_heartbeats:
            self._heartbeat(cli_args)

    def _preopen(self, cli_args: list) -> None:
        """Handle terminal creation"""
        pass

    def _preexec(self, cli_args: list) -> None:
        """Send event containing command execution data"""
        args, unknown_args = parser_preexec.parse_known_args(cli_args)

        process = self._terminal_sessions[args.pid]
        event_data = {
            'command': args.command,
            'path': args.path,
            'shell': args.shell,
            'exit_code': 'unknown',
            'session_id': process.unique_id
        }
        process.event = self._insert_event(data=event_data,
                                           timestamp=args.timestamp)

    def _precmd(self, cli_args: list) -> None:
        """Update the stored event with duration and exit_code"""
        args, unknown_args = parser_precmd.parse_known_args(cli_args)
        process = self._terminal_sessions[args.pid]

        if process.event is None:
            return

        event_data = process.event.data

        # Calculate time delta between preexec and precmd
        timestamp = process.event.timestamp
        cur_time = args.timestamp
        time_delta = cur_time - timestamp

        event_data['exit_code'] = args.exit_code

        self._insert_event(data=event_data,
                           id=process.event.id,
                           timestamp=timestamp,
                           duration=time_delta)
        process.event = None

    def _preclose(self, args: argparse.Namespace, args_raw: list) -> None:
        """Remove pid and related data from terminal_processes_data"""
        args, unknown_args = parser_preclose.parse_known_args(cli_args)
        self._terminal_sessions.pop(args.pid)

    def _heartbeat(self, cli_args: list) -> None:
        """Send heartbeat to activity bucket"""
        args, unknown_args = parser_heartbeat.parse_known_args(cli_args)
        process = self._terminal_sessions[args.pid]

        event_data = {
            'session_id': process.unique_id,
            'shell': args.shell,
            'path': args.path
        }
        event = Event(data=event_data, timestamp=args.timestamp)

        inserted_heartbeat = self._client.heartbeat(
            self._buckets['activity']['id'],
            event,
            pulsetime=self.pulsetime,
            queued=True)

        if inserted_heartbeat and inserted_heartbeat.id:
            logger.debug('Successfully sent heartbeat')

    def _insert_event(self, *args, **kwargs) -> Event:
        """Send event to the aw-server"""
        event = Event(*args, **kwargs)
        inserted_event = self._client.insert_event(
            self._buckets['commands']['id'], event)

        # aw-server assigned the event an id
        assert inserted_event.id is not None
        logger.debug("Successfully sent event")

        return inserted_event
Exemple #25
0
#!/usr/bin/env python3

from datetime import datetime, timezone

from aw_core.models import Event
from aw_client import ActivityWatchClient

# We'll run with testing=True so we don't mess up any production instance.
# Make sure you've started aw-server with the `--testing` flag as well.
client = ActivityWatchClient("test-client", testing=True)

bucket_id = "{}_{}".format("test-client-bucket", client.client_hostname)
client.create_bucket(bucket_id, event_type="dummydata")

shutdown_data = {"label": "some interesting data"}
now = datetime.now(timezone.utc)
shutdown_event = Event(timestamp=now, data=shutdown_data)
inserted_event = client.insert_event(bucket_id, shutdown_event)

events = client.get_events(bucket_id=bucket_id, limit=1)
print(events) # Should print a single event in a list

client.delete_bucket(bucket_id)
class AFKWatcher:
    def __init__(self, testing=False):
        # Read settings from config
        configsection = "aw-watcher-afk" if not testing else "aw-watcher-afk-testing"
        self.settings = Settings(watcher_config[configsection])

        self.client = ActivityWatchClient("aw-watcher-afk", testing=testing)
        self.bucketname = "{}_{}".format(self.client.client_name,
                                         self.client.client_hostname)

    def ping(self, afk: bool, timestamp: datetime, duration: float = 0):
        data = {"status": "afk" if afk else "not-afk"}
        e = Event(timestamp=timestamp, duration=duration, data=data)
        pulsetime = self.settings.timeout + self.settings.poll_time
        self.client.heartbeat(self.bucketname,
                              e,
                              pulsetime=pulsetime,
                              queued=True)

    def run(self):
        logger.info("aw-watcher-afk started")

        # Initialization
        sleep(1)

        eventtype = "afkstatus"
        self.client.create_bucket(self.bucketname, eventtype, queued=True)

        # Start afk checking loop
        with self.client:
            self.heartbeat_loop()

    def heartbeat_loop(self):
        afk = False
        while True:
            try:
                if system in ["Darwin", "Linux"] and os.getppid() == 1:
                    # TODO: This won't work with PyInstaller which starts a bootloader process which will become the parent.
                    #       There is a solution however.
                    #       See: https://github.com/ActivityWatch/aw-qt/issues/19#issuecomment-316741125
                    logger.info(
                        "afkwatcher stopped because parent process died")
                    break

                now = datetime.now(timezone.utc)
                seconds_since_input = seconds_since_last_input()
                last_input = now - timedelta(seconds=seconds_since_input)
                logger.debug(
                    "Seconds since last input: {}".format(seconds_since_input))

                # If no longer AFK
                if afk and seconds_since_input < self.settings.timeout:
                    logger.info("No longer AFK")
                    self.ping(afk, timestamp=last_input)
                    afk = False
                    self.ping(afk, timestamp=last_input)
                # If becomes AFK
                elif not afk and seconds_since_input >= self.settings.timeout:
                    logger.info("Became AFK")
                    self.ping(afk, timestamp=last_input)
                    afk = True
                    self.ping(afk,
                              timestamp=last_input,
                              duration=seconds_since_input)
                # Send a heartbeat if no state change was made
                else:
                    if afk:
                        self.ping(afk,
                                  timestamp=last_input,
                                  duration=seconds_since_input)
                    else:
                        self.ping(afk, timestamp=last_input)

                sleep(self.settings.poll_time)

            except KeyboardInterrupt:
                logger.info("aw-watcher-afk stopped by keyboard interrupt")
                break
#!/usr/bin/env python3

from datetime import datetime, timezone

from aw_core.models import Event
from aw_client import ActivityWatchClient

# We'll run with testing=True so we don't mess up any production instance.
# Make sure you've started aw-server with the `--testing` flag as well.
client = ActivityWatchClient("test-client", testing=True)

bucket_id = "{}_{}".format("test-client-bucket", client.hostname)
client.create_bucket(bucket_id, event_type="dummydata")

shutdown_data = {"label": "some interesting data"}
now = datetime.now(timezone.utc)
shutdown_event = Event(timestamp=now, data=shutdown_data)
inserted_event = client.insert_event(bucket_id, shutdown_event)

events = client.get_events(bucket_id=bucket_id, limit=1)
print(events) # Should print a single event in a list

client.delete_bucket(bucket_id)
class AFKWatcher:
    def __init__(self, testing=False):
        # Read settings from config
        configsection = "aw-watcher-afk" if not testing else "aw-watcher-afk-testing"
        self.settings = Settings(watcher_config[configsection])

        self.client = ActivityWatchClient("aw-watcher-afk", testing=testing)
        self.bucketname = "{}_{}".format(self.client.client_name, self.client.client_hostname)

    def ping(self, afk: bool, timestamp: datetime, duration: float = 0):
        data = {"status": "afk" if afk else "not-afk"}
        e = Event(timestamp=timestamp, duration=duration, data=data)
        pulsetime = self.settings.timeout + self.settings.poll_time
        self.client.heartbeat(self.bucketname, e, pulsetime=pulsetime, queued=True)

    def run(self):
        logger.info("aw-watcher-afk started")

        # Initialization
        sleep(1)

        eventtype = "afkstatus"
        self.client.create_bucket(self.bucketname, eventtype, queued=True)

        # Start afk checking loop
        with self.client:
            self.heartbeat_loop()

    def heartbeat_loop(self):
        afk = False
        while True:
            try:
                if system in ["Darwin", "Linux"] and os.getppid() == 1:
                    # TODO: This won't work with PyInstaller which starts a bootloader process which will become the parent.
                    #       There is a solution however.
                    #       See: https://github.com/ActivityWatch/aw-qt/issues/19#issuecomment-316741125
                    logger.info("afkwatcher stopped because parent process died")
                    break

                now = datetime.now(timezone.utc)
                seconds_since_input = seconds_since_last_input()
                last_input = now - timedelta(seconds=seconds_since_input)
                logger.debug("Seconds since last input: {}".format(seconds_since_input))

                # If no longer AFK
                if afk and seconds_since_input < self.settings.timeout:
                    logger.info("No longer AFK")
                    self.ping(afk, timestamp=last_input)
                    afk = False
                    self.ping(afk, timestamp=last_input)
                # If becomes AFK
                elif not afk and seconds_since_input >= self.settings.timeout:
                    logger.info("Became AFK")
                    self.ping(afk, timestamp=last_input)
                    afk = True
                    self.ping(afk, timestamp=last_input, duration=seconds_since_input)
                # Send a heartbeat if no state change was made
                else:
                    if afk:
                        self.ping(afk, timestamp=last_input, duration=seconds_since_input)
                    else:
                        self.ping(afk, timestamp=last_input)

                sleep(self.settings.poll_time)

            except KeyboardInterrupt:
                logger.info("aw-watcher-afk stopped by keyboard interrupt")
                break
Exemple #29
0
            # print(title)
            # print(start, duration)
            # if attendees:
            #     for attendee in attendees:
            #         print(attendee)
            # print(e)
            # print(component)
            # print(80 * "-")
    return events


if __name__ == "__main__":
    filename = sys.argv.pop()
    events = load_events(filename)
    print(f"Loaded {len(events)} events")
    aw = ActivityWatchClient(testing=True)

    bucket_name = "ical-import"

    if bucket_name in aw.get_buckets():
        aw.delete_bucket(bucket_name)

    aw.create_bucket(bucket_name, "calendar")
    aw.insert_events(bucket_name, events)
"""
Basic query:

events = query_bucket(find_bucket('ical-import'));
RETURN = filter_keyvals_regex(events, 'title', '\<\>'));
"""
Exemple #30
0
class TableWatcher:
    def __init__(self, testing=False):
        config_section = "aw-watcher-table" if not testing else "aw-watcher-table-testing"
        self.settings = Settings(watcher_config[config_section])

        self.client = ActivityWatchClient("aw-watcher-table", testing=testing)
        self.bucket_id = "{}_{}".format(self.client.client_name,
                                        self.client.client_hostname)

    def run(self):
        logger.info("aw-watcher-table started")

        # Initialization
        sleep(1)

        self.client.create_bucket(self.bucket_id,
                                  event_type='table_state',
                                  queued=True)

        # Start table checking loop
        with self.client:
            self.heartbeat_loop()

    def ping(self, table_height: Optional[int]):
        event = Event(timestamp=datetime.datetime.now(datetime.timezone.utc),
                      data={"status": self.get_table_status(table_height)})
        # 10 seconds request timeout
        self.client.heartbeat(self.bucket_id,
                              event,
                              pulsetime=self.settings.poll_time + 1 + 10,
                              queued=True)

    def get_table_height(self) -> Optional[int]:
        try:
            r = requests.get(f'http://{self.settings.ip}/measure')
            return r.json()['table_height']

        except Exception as ex:
            logger.warning(
                f'aw-watcher-table: Measurement failed! Please make sure http://{self.settings.ip}/measure '
                f'delivers a JSON object which includes the field "table_height"'
            )
            return None

    def get_table_status(self, table_height):
        return self.settings.get_height_level(table_height)

    def heartbeat_loop(self):
        while True:
            try:
                table_height = self.get_table_height()
                if table_height is None:
                    logger.warning(
                        f'aw-watcher-table: table_height corrected from None to -1!'
                    )
                    table_height = -1
                self.ping(table_height)
                sleep(self.settings.poll_time)
            except KeyboardInterrupt:
                logger.info("aw-watcher-table stopped by keyboard interrupt")
                break