Example #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)
Example #2
0
class Detector:
    def __init__(self) -> None:
        self.client = ActivityWatchClient("status-checker")

    # TODO: Move to aw-client?
    # TODO: Doesn't care if the event was old (as can happen if you have a dead watcher)
    def _get_last_event(self, bucket_id: str) -> Event:
        last_events = self.client.get_events(bucket_id, limit=1)
        if last_events:
            return last_events[0]
        else:
            raise Exception("no event found")

    def get_bucket_id(self, type: str) -> str:
        # TODO: Doesn't care about hostname
        # TODO (maybe): Create a better way to query buckets
        buckets = self.client.get_buckets()
        # print(buckets)
        window_bucket = find(
            lambda bucket: bucket["type"] == type and "testing" not in bucket[
                "id"], buckets.values())
        if window_bucket is None:
            raise Exception("Bucket not found")
        return window_bucket["id"]

    def detect(self, bucket_id: str, filter_str: str) -> Optional[Event]:
        last_event = self._get_last_event(bucket_id)
        return last_event if find(lambda label: filter_str in label.lower(),
                                  last_event.labels) else None
Example #3
0
def main() -> None:
    now = datetime.now(tz=timezone.utc)
    td30d = timedelta(days=7)

    aw = ActivityWatchClient()
    print("Querying...")
    data = aw.query(_query, [(now - td30d, now)])

    events = [{
        "timestamp": e["timestamp"],
        "duration": timedelta(seconds=e["duration"]),
        **e["data"],
    } for e in data[0]["events"]]

    df = pd.json_normalize(events)
    df["timestamp"] = pd.to_datetime(df["timestamp"],
                                     infer_datetime_format=True)
    df.set_index("timestamp", inplace=True)

    print(df)

    answer = input("Do you want to export to CSV? (y/N): ")
    if answer == "y":
        filename = "output.csv"
        df.to_csv(filename)
        print(f"Wrote to {filename}")
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))
Example #5
0
    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 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)
Example #7
0
def bucket_report(bucket_name,start_date,end_date):
    client = ActivityWatchClient("aw-watcher-cli", testing=False)
    bucket_id = "{}_{}".format(bucket_name, client.hostname)
    query = "RETURN = query_bucket('{}');".format(bucket_id)
    events = client.query(query,start_date,end_date)[0]
    if len(events) == 0:
        print("No events")
        exit()
    events.reverse() #oder from oldest to newest
    # first date
    date = parser.parse(events[0]["timestamp"],default=datetime.now()) - timedelta(hours=6) #- CST
    print(date.date()) #print first date
    day_duration = 0
    total_duration = 0
    cnt = 1
    for event in events:
        total_duration += event["duration"]
        timestamp = parser.parse(event["timestamp"],default=datetime.now()) - timedelta(hours=6) #- CST
        if date.date() != timestamp.date():
            date = timestamp
            print("sum:\t{}".format(format_duration(day_duration))) #duration from prev block
            print("")
            day_duration = event["duration"] #reset duration
            print(date.date()) #print next date
        else:
            day_duration += event["duration"]
        print("{}.\t{}\t{}".format(cnt,format_duration(event["duration"]),event["data"]["label"]))
        cnt += 1
        #print last day_duration when last event is reached
        if event == events[-1]:
            print("sum:\t{}".format(format_duration(day_duration)))
            #Print total report duration
            print("total:\t{}".format(format_duration(total_duration)))
    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 __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)
Example #10
0
    def __init__(self):
        self.aw_client = ActivityWatchClient()

        self.all_buckets = {}
        self.bucket = self._get_main_bucket()
        self.aw_watcher_window_id = self.bucket['id']

        self._all_buckets_events = {}
Example #11
0
def client():
    c = ActivityWatchClient("client-test", testing=True)
    yield c

    # Delete test buckets after all tests needing the fixture have been run
    buckets = c.get_buckets()
    for bucket_id in buckets:
        if bucket_id.startswith("test-"):
            c.delete_bucket(bucket_id)
Example #12
0
 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
Example #13
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)
Example #14
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))
Example #15
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)
Example #16
0
def test_filter_short():
    # TODO: This was used in dev and does not work.
    awapi = ActivityWatchClient("cleaner", testing=True)
    events = awapi.get_events(BUCKET_WEB, limit=-1)
    filter_short(events, threshold=1)

    events = awapi.get_events(BUCKET_WINDOW, limit=-1)
    filter_short(events, threshold=1)

    events = awapi.get_events(BUCKET_AFK, limit=-1)
    filter_short(events, threshold=30)
def aw_client():
    # TODO: Could it be possible to write a sisterclass of ActivityWatchClient
    # which calls aw_server.api directly? Would it be of use? Would add another
    # layer of integration tests that are actually more like unit tests.
    c = ActivityWatchClient("client-test", testing=True)
    yield c

    # Delete test buckets after all tests needing the fixture have been run
    buckets = c.get_buckets()
    for bucket_id in buckets:
        if bucket_id.startswith("test-"):
            c.delete_bucket(bucket_id)
Example #18
0
def aw_client():
    # TODO: Could it be possible to write a sisterclass of ActivityWatchClient
    # which calls aw_server.api directly? Would it be of use? Would add another
    # layer of integration tests that are actually more like unit tests.
    c = ActivityWatchClient("client-test", testing=True)
    yield c

    # Delete test buckets after all tests needing the fixture have been run
    buckets = c.get_buckets()
    for bucket_id in buckets:
        if bucket_id.startswith("test-"):
            c.delete_bucket(bucket_id)
def get_begin_time(bucket_name: str = BUCKET_NAME) -> datetime.datetime:
    client = ActivityWatchClient()
    buckets = client.get_buckets()
    selected_bucket = None
    for bucket in buckets.values():
        if bucket["id"] == bucket_name + "_" + bucket["hostname"]:
            selected_bucket = bucket
    if selected_bucket is None:
        raise ValueError(
            f"bucket {bucket_name} does not exist, run project watcher")

    return datetime.datetime.fromisoformat(selected_bucket["created"]).replace(
        tzinfo=get_localzone(), hour=0, minute=0, second=0)
Example #20
0
def test_filter_short():
    # TODO: This was used in dev and does not work.
    awapi = ActivityWatchClient("cleaner", testing=True)
    events = awapi.get_events("aw-watcher-web-test", limit=-1)
    filter_short(events, threshold=1)

    events = awapi.get_events("aw-watcher-window-testing_erb-main2-arch",
                              limit=-1)
    filter_short(events, threshold=1)

    events = awapi.get_events("aw-watcher-afk-testing_erb-main2-arch",
                              limit=-1)
    filter_short(events, threshold=30)
Example #21
0
def _get_window_events(n=1000):
    client = ActivityWatchClient("aw-analyser", testing=True)
    buckets = client.get_buckets()

    bucket_id = None
    for _bid in buckets.keys():
        if "window" in _bid and "testing" not in _bid:
            bucket_id = _bid

    if bucket_id:
        return client.get_events(bucket_id, limit=n)
    else:
        print("Did not find bucket")
        return []
Example #22
0
def get_events(
    hostname: str,
    since: datetime,
    end: datetime,
    include_smartertime="auto",
    include_toggl=None,
    testing: bool = False,
) -> List[Event]:
    awc = ActivityWatchClient("test", testing=testing)

    query = build_query(hostname)
    logger.debug(f"Query:\n{query}")

    result = awc.query(query, timeperiods=[(since, end)])
    events = [Event(**e) for e in result[0]]

    if include_smartertime:
        events = union_no_overlap(
            events, _get_events_smartertime(since,
                                            filepath=include_smartertime))
        events = sorted(events, key=lambda e: e.timestamp)

    if include_toggl:
        events = union_no_overlap(
            events, _get_events_toggl(since, filepath=include_toggl))
        events = sorted(events, key=lambda e: e.timestamp)

    # Filter by time
    events = [
        e for e in events
        if since.astimezone(timezone.utc) < e.timestamp and e.timestamp +
        e.duration < end.astimezone(timezone.utc)
    ]
    assert all(since.astimezone(timezone.utc) < e.timestamp for e in events)
    assert all(e.timestamp + e.duration < end.astimezone(timezone.utc)
               for e in events)

    # Filter out events without data (which sometimes happens for whatever reason)
    events = [e for e in events if e.data]

    for event in events:
        if "app" not in event.data:
            if "url" in event.data:
                event.data["app"] = urlparse(event.data["url"]).netloc
            else:
                print("Unexpected event: ", event)

    events = [e for e in events if e.data]
    return events
def main():
    global DRYRUN
    if "--wet" in sys.argv:
        DRYRUN = False

    global aw
    aw = ActivityWatchClient(testing=True)

    buckets = aw.get_buckets()
    print("Buckets: ")
    print("\n".join([" - " + bid for bid in buckets.keys()]) + "\n")

    bid_to_redact = input(
        "In which bucket are the events you want to redact? (* for all): "
    )
    assert bid_to_redact == "*" or bid_to_redact in buckets, "Not a valid option"

    regex_or_string = input(
        "Do you want to search by regex or string? (regex/string): "
    )
    assert regex_or_string in ["regex", "string"], "Not a valid option"

    print("\nNOTE: Matching is not case sensitive!")
    pattern: Union[str, Pattern]
    if regex_or_string == "string":
        pattern = input("Enter a string indicating sensitive content: ").lower()
    else:
        pattern = re.compile(
            input("Enter a regex indicating sensitive content: ").lower()
        )

    print("")
    if DRYRUN:
        print(
            "NOTE: Performing a dry run, no events will be modified. Run with --wet to modify events."
        )
    else:
        print(
            "WARNING: Note that this performs an operation that cannot be undone. We strongly recommend that you backup/export your data before proceeding."
        )
    input("Press ENTER to continue, or Ctrl-C to abort")

    if bid_to_redact == "*":
        for bucket_id in buckets.keys():
            if bucket_id.startswith("aw-watcher-afk"):
                return
            _redact_bucket(bucket_id, pattern)
    else:
        _redact_bucket(bid_to_redact, pattern)
def get_activity(
        project: str,
        begin: Optional[datetime.datetime] = None,
        end: Optional[datetime.datetime] = None,
        activity_buckets: Sequence[str] = DEFAULT_ACTIVITY_BUCKETS
) -> Activity:
    if begin is None:
        begin = get_begin_time()
    if end is None:
        end = get_default_end_time()
    time_periods = [(begin, end)]
    client = ActivityWatchClient()
    query = _get_activity_query(project, activity_buckets)
    events: List[ActivityData] = client.query(query, time_periods)
    return Activity(events[0]['aw_watcher_window_events'])
    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)
Example #26
0
def delete_prev_buckets():
    logging.info("Deleting old buckets")
    client = ActivityWatchClient("aw-fake-client", testing=True)
    client.client_hostname = hostname
    client.connect()
    try:
        client.delete_bucket(window_bucket_name)
    except HTTPError:
        pass
    try:
        client.delete_bucket(afk_bucket_name)
    except HTTPError:
        pass
Example #27
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
Example #28
0
def get_events(hostname: str,
               since: datetime,
               end: datetime,
               include_smartertime='auto',
               include_toggl=None) -> List[Event]:
    awc = ActivityWatchClient("test", testing=False)

    # print(query_complete)
    query = build_query(hostname)
    result = awc.query(query, start=since, end=end)
    events = [Event(**e) for e in result[0]]

    if include_smartertime:
        events = _union_no_overlap(
            events, _get_events_smartertime(since,
                                            filepath=include_smartertime))
        events = sorted(events, key=lambda e: e.timestamp)

    if include_toggl:
        events = _union_no_overlap(
            events, _get_events_toggl(since, filepath=include_toggl))
        events = sorted(events, key=lambda e: e.timestamp)

    # Filter by time
    events = [
        e for e in events
        if since.astimezone(timezone.utc) < e.timestamp and e.timestamp +
        e.duration < end.astimezone(timezone.utc)
    ]
    assert all(since.astimezone(timezone.utc) < e.timestamp for e in events)
    assert all(e.timestamp + e.duration < end.astimezone(timezone.utc)
               for e in events)

    # Filter out events without data (which sometimes happens for whatever reason)
    events = [e for e in events if e.data]

    for event in events:
        if 'app' not in event.data:
            if 'url' in event.data:
                event.data['app'] = urlparse(event.data['url']).netloc
            else:
                print('Unexpected event: ', event)

    events = [e for e in events if e.data]
    return events
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)
Example #30
0
def test_full():
    now = datetime.now(timezone.utc)

    client_name = "aw-test-client"
    bucket_name = "test-bucket"
    bucket_etype = "test"

    # Test context manager
    with ActivityWatchClient(client_name, testing=True) as client:
        time.sleep(1)

        # Check that client name is set correctly
        assert client.client_name == client_name

        # Delete bucket before creating it, and handle error if it doesn't already exist
        try:
            client.delete_bucket(bucket_name)
        except HTTPError:
            pass

        # Create bucket
        client.create_bucket(bucket_name, bucket_etype)

        # Check bucket
        buckets = client.get_buckets()
        assert bucket_name in buckets
        assert bucket_name == buckets[bucket_name]["id"]
        assert bucket_etype == buckets[bucket_name]["type"]

        # Insert events
        e1 = create_unique_event()
        e2 = create_unique_event()
        e3 = create_unique_event()
        events = [e1, e2, e3]
        client.insert_events(bucket_name, events)

        # Get events
        fetched_events = client.get_events(bucket_name, limit=len(events))

        # Assert events
        assert [(e.timestamp, e.duration, e.data) for e in fetched_events] == [
            (e.timestamp, e.duration, e.data) for e in events
        ]

        # Check eventcount
        eventcount = client.get_eventcount(bucket_name)
        assert eventcount == len(events)

        result = client.query(
            f"RETURN = query_bucket('{bucket_name}');",
            timeperiods=[(now - timedelta(hours=1), now + timedelta(hours=1))],
        )
        assert len(result) == 1
        assert len(result[0]) == 3

        # Delete bucket
        client.delete_bucket(bucket_name)
Example #31
0
def all_active_webactivity():
    """Returns activity during non-afk events or when tab is audible"""
    awapi = ActivityWatchClient("test", testing=True)

    start = datetime.now() - timedelta(days=7)
    tabevents = awapi.get_events("aw-watcher-web-chrome", start=start)
    afkevents = awapi.get_events("aw-watcher-afk_erb-laptop2-arch",
                                 start=start)

    afkevents_notafk = list(
        filter(lambda e: e.data["status"] == "not-afk", afkevents))
    tabevents_audible = list(
        filter(lambda e: "audible" in e.data and e.data["audible"], tabevents))

    # TODO: Implement merge
    # activeevents = merge(afkevents_notafk, tabevents_audible)
    # This isn't perfect, buggy when a notafk/audible events is contained by another
    activeevents = afkevents_notafk + tabevents_audible

    return filter_period_intersect(tabevents, activeevents)
Example #32
0
def main(dryrun=True):
    # TODO: Use wordlist instead of argument
    sensitive_words = ["sensitive"]

    aw = ActivityWatchClient(testing=True)

    re_word = r'\b{}\b'

    buckets = aw.get_buckets()
    for bid in buckets.keys():
        if "window" not in bid:
            continue

        print("Checking bucket: {}".format(bid))

        events = aw.get_events(bid, limit=-1)
        old_matches = set()
        for event in events:
            for key, val in event.data.items():
                if isinstance(val, str):
                    matches = [re.findall(re_word.format(word), val.lower())
                               for word in sensitive_words]
                    matches = set(sum(matches, []))
                    if matches:
                        event.data[key] = "REDACTED"
                        if val not in old_matches:
                            print(f"{'(DRYRUN) ' if dryrun else ''} Matches: {matches}, redacting: {val}")
                            old_matches.add(val)
                        if not dryrun:
                            aw.insert_event(bid, event)
Example #33
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
Example #34
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))
Example #35
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)
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']
#!/usr/bin/env python3

from time import sleep
from datetime import datetime, timedelta, timezone

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)
# Usage:
#   python3 test_continous_events.py aw-watcher-afk-testing_{hostname}
#
# Example:
#   python3 test_continous_events.py aw-watcher-afk-testing_erb-laptop-ubuntu

import sys
from datetime import timedelta

from aw_client import ActivityWatchClient

client = ActivityWatchClient("aw-watcher-afk-test", testing=True)
print(client.get_buckets())

bucket_id = sys.argv[1]
events = client.get_events(bucket_id)  # For example "aw-watcher-afk-testing_erb-laptop-ubuntu"

print("\n\n")

last_event = None
wrong_events = 0
for event in sorted(events, key=lambda e: e.timestamp):
    if last_event:
        # The diff is the gap between the two events, should be zero
        # In reality it is currently sometimes negative and almost always larger than 1s
        diff = (event.timestamp - last_event.timestamp) - last_event.duration

        print("{} at {}".format(event.label, event.timestamp))
        print("Duration: {}".format(event.duration))

        if not timedelta(seconds=1) > abs(diff):
#!/usr/bin/env python3

from time import sleep
from datetime import datetime, timedelta, 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)

# Make the bucket_id unique for both the client and host
# The convention is to use client-name_hostname as bucket name,
# but if you have multiple buckets in one client you can add a
# suffix such as client-name-event-type or similar
bucket_id = "{}_{}".format("test-client-bucket", client.hostname)
# A short and descriptive event type name
# Will be used by visualizers (such as aw-webui) to detect what type and format the events are in
# Can for example be "currentwindow", "afkstatus", "ping" or "currentsong"
event_type = "dummydata"

# First we need a bucket to send events/heartbeats to.
# If the bucket already exists aw-server will simply return 304 NOT MODIFIED,
# so run this every time the clients starts up to verify that the bucket exists.
# If the client was unable to connect to aw-server or something failed
# during the creation of the bucket, an exception will be raised.
client.create_bucket(bucket_id, event_type="test")

# Asynchronous loop example
with client:
#!/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