-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Need help understanding and modifying the time logging function #1079
Comments
Ah! A part of the code I have not looked at in a while. As a bit of background that you might have already figured out it: SteamTinkerLaunch takes in the seconds played into Then, each line in this log file represents each session. If you play on one launch for 20 seconds, then another for 4 minutes, you'll see these in order in the file. Example from one of my playtime log files:
You might've already figured that much out, but I think it's fine to clarify a bit further. I'll answer other questions in quoted blocks.
I agree, I have it on a personal Trello board to make this customisable (there's also a comment about accommodating different date formats heh). I think the best solution would be to expose this on the UI, possibly updating the default to respect the user's locale - I'll have to see what implications this has i.e. on the Steam Deck, where locale has historically been incorrectly configured by Valve. This can be configurable based on the I have wanted to make this configurable, so at the very least, it can be exposed on the UI. If there are no issues, we can also default to using I don't think we should have any problems parsing this for existing games, since on the UI we just display the string stored in the text file. If the format changes, it's no skin off our nose from the technical side. We can't update existing entries though, as there is no "structured" format as such. We could make some assumptions but it might get messy. The playtime log file just stores the same string you would see on the Main Menu, per-session. In hindsight, we should've just stored the epoch time from
As in, the time you played at, rather than the time you played for? As in, you played on X date at Y time for Z hours/minutes/seconds. This would be possible, I'd just have to look at how best to display this on the UI. Displaying "04.08.2024 at 02:18:23 for 04:45:23" might end up being visually confusing. There is no technical reason why we couldn't do this though.
Sadly not with the current implementation. Right now we work out the seconds duration by using Bash's That doesn't mean it's impossible though, it would just need a bit of a refactor. We could store the epoch time at the beginning of a launch and then get it at the end of a launch. Instead of storing This would be a lot more precise. You can get epoch time with
Yeah, it's not totally clear, there is a comment that clarifies it takes seconds though. But if you're unfamiliar with Bash it's a bit strange to see In Bash, when you pass arguments to functions, they can be accessed in order as I don't think this is out of scope, I think there are some good points here. The main takeaways here I think are:
Definitely possible changes, the most straightforward of the bunch is probably allowing more datetime formatting customisation. Handling the epoch logging is another matter, as we'd have to accomodate existing entries using seconds, and new entries using epoch. |
I think I can confidently say that two of the most consistent things in our discussions are long comments and poking at old code or features. I suppose I have a tendency to just try stuff and...end up on a sort of digital archaeological dig 😅
Ah, sorry, yes; I meant "time you played at" for this particular part of my question. I didn't anticipate the confusion there 😳
What I personally have in the shell script at the moment is Marvel's Spider-Man Remastered.log
It works for me, but I think it looks a bit too much like a sci-fi log entry for me to recommend it for general use 😅
Glad to help 😆
Maybe something like "session start time" vs. "session duration"? 🤔
Nice 👍 It's even more out of my element than the first comment, but have you considered somehow making the Steam Tinker Launch script more modular? I can't imagine it's easy to maintain a single script with ~26500 lines...although splitting the script into separate files may have its own set of challenges 🤔 Regardless: thanks for once again giving your consideration to my random requests and stuff 💜 🙏 |
Hm, I like this idea. I'll have a think about how best to incorporate it into the UI.
Becoming more modular isn't overly feasible for a few reasons, mainly due to limitations of Steam compatibility tools. Since variables come from Steam and Steam is also picky about running multiple files and having multiple files interact, we can't really do this. Many compatibility tools will have large scripts (although not nearly as large as STL), as a good example, Valve's Proton is one large script. Essentially, when you launch a game with a compatibility tool from Steam, there is a What we can do, however, is trim the length down to some degree. There is usually tradeoff between readability (even if Bash isn't the most readable language out there) and length, but there are opportunities for better code and more re-use in SteamTinkerLaunch (unifying the download function code could probably trim ~100 lines I think), and there are bits of unmaintained code that can probably be removed. The VR stuff can probably be stripped out (I don't own any hardware to test, and no idea if it even works), Depressurizer can be removed (#1029), and there are probably others. I think in total there is scope to probably bring STL down to around 20,000 lines. Something else I'd like to do more around the codebase is organize. Some things are grouped together, and when I create new functions/groups of functions I try to organize them, and eventually I'd like to do this more. Both of these are not really making the file shorter for the sake of it, but rather it falls under general code cleanup. A lot of code in STL is almost 4 years old at this point, and some stuff from my early contributions isn't the best (I have cleaned a lot of it up as time has gone on), there is general room for cleanup though. After things on the hitlist for 14.0 are done I'll take a look at making code improvements early in 15.0's development. Making SteamTinkerLaunch more modular is not really possible due to Steam limitations (at least, as far as I'm aware). We're already way outside the realm of how compatibility tools are intended to function (if Valve start enforcing tools use Manifest v2 which enforces the Steam Linux Runtime, which all other compatibility tools I've seen so far have used, STL will stop functioning 😅) This was actually discussed very recently in #1053 :-) |
That doesn't sound very good 😨 I read some of that discussion (didn't know you were a full-time software engineer; sounds pretty legit 😁 ), and hopefully I'm not repeating what's already there, but I have a few more questions about all this:
I think that's it...for now 😄 |
It can, there's not that much restriction as long as the standard Linux desktop can run it. Python is a good example, since Python is a dependency for Steam. In the case of Python in your example, you are restricted to the standard library (perhaps even a subset). This would place large restrictions on the UI toolkit. It may be possible to use an AppImage or some binary form to get around this, but I'm unsure. I'm handy with Python, but a lot of what SteamTinkerLaunch does "internally" actually fits Bash quite well, it is essentially setting a lot of environment variables and running system commands. All of this can be done with Python, but doing it in Bash removes some hurdles. Python would help with code structure and passing data around but you'd end up with a lot of system calls anyway. The Python script would probably overall be around the same if not longer.
As far as I know it isn't a language restriction, it's simply a restriction of running a compatibility tool.
I don't think anything can resolve it. To my understanding, and the previous maintainer's understanding, it is no longer possible to launch processes the way SteamTinkerLaunch does. Any program that tries to do similar things would stop functioning. Manifest v2 is enforced from the The launch command will get built correctly, but for some reason, Steam won't let STL launch games. STL can't get the process ID for the game, which could mean Steam is a bit more hands-on with how it handles executable launches and won't just let STL do it. I recall something about the Steam Linux Runtime being enforced with manifest v2, and if so, this kind of containerization would stop STL from being able to run games. I don't know if Valve will ever enforce this, there is likely no reason for them to absolutely enforce it (and maybe for legacy reasons i.e. old Proton versions which you can still download from Steam that might still use the older manifest version, they won't remove this anytime soon). But it is a possibility. Or, they could make a manifest v3 that doesn't have this problem :-)
You could, and we could probably parse this with a I guess the format would be something like this, although to break it up into columns we'd either have to build a new string specifically for the CSV, or if we use epoch time, parse it out using
We could store date played as the epoch timestamp, and session length in milliseconds. This puts the data in the most "raw" format available. I think this should be a secondary format though, possibly behind a checkbox to store playtime in CSV. This would help handle the case of reading existing playtime data. I'm not sure how much of this is worth the effort of implementing as work would be needed to create and manage the CSV (and we'd probably want some functions to do this more generically, if we wanted to use CSV later on for something), but it would at least be possible on the technical front. To me it seems like a lot for something that is primarily for internal tracking is all. But it is possible :-) |
I'm neither handy with Bash nor Python 😆
Well, that's a bummer.
Yet another limitation 🤔
Well, that just sounds terrible 😢
Seems like I'm 0 for 4 this time 😕 Would it be possible--and this is really me reaching at this point--to hook in another script to capture and format the playtime? I don't know of any playthrough tracking apps at the moment; so maybe just writing a light script to record the time and date when the actual game window opens, then track how long it's open for. Like, I was thinking My concerns are:
Sorry if it's not a great suggestion, but I'm just trying to find a good solution to help me record my experiences 😅 |
I think this would be possible if it's an external script! However I was very silly and realised something earlier today: Epoch doesn't actually include milliseconds.
There may be a few ways. A custom command may work, but this would run with an executable. Perhaps a better solution would be to try the "User start command" and "User stop command" options. You could have two scripts for each of these. One would manage logging the start time to a file (perhaps in epoch time) and putting it in, say. You can use the epoch start time as your date played, or the end time as your date played, depending on whether you want that to reflect the date the game was opened or closed (since in cases where a game may be started before midnight but a session ends after midnight, for example, the dates would be different). If you absolutely need milliseconds there may be other options. Maybe If you are storing this in milliseconds, make sure you calculate it differently than STL does since it expects seconds. And on a similar note you may need to store the date separately, since you can't really convert the milliseconds into a date. You could still store the current date in the start/end script, depending on when you want to record the date. You could store this as an epoch so your tempfile could just have two comma-separated values: I haven't tested the custom start/end command option in STL, at least not recently (I may have used it a couple of years ago but I'm not sure). But they should essentially run when a game opens, and then when a game closes. So basically when STL starts the game process it'll run the start script, and when STL is exiting it'll run the end script, which will allow you to keep the times in sync. It may be tricky to track in milliseconds, but there is no technical reason why storing the start/end time more broadly with a custom set of scripts shouldn't work. If the start/end command features don't work as you expect that's a different matter, I haven't actually tested them but I'd give them a try first with something a bit more scaled-back just to make sure it functions as you want. For example if you have
I don't think so :-) I like this kind of tinkering at least. |
First off--sorry for the delay. For once, I actually did some work on my own: https://codeberg.org/CartoonFan/misc_helper_scripts/src/branch/main/get_formatted_time_duration.sh Right now, the script is a combined start and end demo which (hopefully) does most of what's needed. I have a sneaking--and growing--suspicion that Python would make a lot of this easier, especially with the math portions; Bash only has native support for integers, so...it got pretty tricky trying to get milliseconds in and out of the decimal zone 😅 Here's the terminal output: [jeremiah@arcadia ~]$ get_formatted_time_duration.sh
session start time: 2024-04-03 11:52:00.525500
session end time: 2024-04-03 12:55:05.000000
session start time (epoch seconds, precise to microseconds): 1712170320.525500
session end time (epoch seconds, precise to microseconds): 1712174105.000000
raw difference between start epoch and end: 3784.474500
rounded difference between start epoch and end: 3784.475
sesson length:
1 hours
3 minutes
4 seconds
475 milliseconds
XDG documents dir: /home/jeremiah/Documents
XDG home dir: /home/jeremiah And this is the CSV (pipe-delimited) format:
Even with all this...it still needs work. For example, I don't have the game or window title (either would work, but the game title would probably be better), and I haven't really come up with a system to assign the game/playthrough/session IDs--which are quite helpful in keeping things organized, Also, I assume there would be a permanent file made at some point; besides keeping the game times in one place, it's probably needed for incrementing entries. Also,
Not that it's anywhere near that scale yet, but are the user scripts allowed to be modular? As in, Steam runs STL, but then STL can launch multiple scripts (or two scripts that call a number of other scripts). With all that said, my guess of what I'm trying to do here (based largely on your suggestions):
The things I'm still not too confident doing:
Of course, there's things like database structure and such, but I actually have a tiny bit of experience there--although it's by no means settled or complete 😆
Thanks 😊 💜 🙏 As you can probably see: I am quite a novice at this sort of thing. Most of that script above was cobbled together from the Internet and Steam Tinker Launch 😓 |
You could probably write a single-line script that calls a Python script to do it in Python.
I think so, since STL forks those processes. I haven't ever tested that kind of thing, though. These two points were listed separately but I'll reply to them together since they're related:
STL gets it from Steam. Since STL is launched as a compatibility tool it gets a bunch of information given to it from the Steam environment. Scripts that call other scripts don't get access to this information, and STL has no facility to pass this to scripts directly However, in SteamTinkerLaunch writes to this on its own startup, and since your script always runs after SteamTinkerLaunch starts (because STL has to start it :-)) you should always have access to this information. You could, theoretically, get the Game Title either by calling To call SteamTinkerLaunch from Python, you can use something like this: import subprocess
app_id = 447530 # Substitute with any AppID you like :-)
# The args to subprocess.run are mostly boilerplate, don't worry much
# stdout gives us the text out, as subprocesss.run returns a CompletedProcess object and not a string
# the strip() call removes trailing newlines from the stdout, giving a clean string
#
# The fstring is just to make sure if the AppID is an int that it gets concatenated safely
app_name = subprocess.run([f'steamtinkerlaunch gt {app_id}'], shell=True, capture_output=True, text=True).stdout.strip() Of course you don't have to use STL, that's just how I would do it, and I am very biased! |
I think this can be closed now. Please re-open if you have more questions/concerns. Thanks! |
Sure thing. I've actually been working at this on and off--haven't finished yet, though 😆 I moved from Bash to Python (mainly due to Bash not natively supporting floating-point numbers), and it's been a real trip. Most of the difficulty now is some combination of learning more Python, and getting whatever AI blender I toss the code into to work the way I want. I've got the start script pretty much done, I think--it should record the start time and the rest of the important session data, then put that into a file for the end script to pick up. I'm planning on linking the scripts here at some point, so you can see them for yourself, and give your opinion--if that's all right 😅 Thanks again for helping me get here! 😆 💜 |
Oh my goodness... So, I actually managed to get something working : Start script: https://codeberg.org/CartoonFan/misc_helper_scripts/src/branch/main/save_session_start_info.py Ended up taking a lot more time and effort than I thought, mainly because I relied a bit too much on the aforementioned AI blender and had to do the whole thing from scratch again. I am not a professional developer by any stretch of the imagination. The code here likely still needs a lot of love and care, and I haven't actually tested it with any games yet, but...it works. I think 😅 Anyway, just wanted to let you know that something tangible came out of this. Feel free to use, comment, modify, share...all that good stuff 😁 I one thing I came across--relevant to what you do here--was that calling Steam Tinker Launch during my tests to get the game name actually overwrites the Once again: thanks for your help in getting me to this point. I'm just really happy to have something working that finally meets my needs 😆 💜 🙏 |
How would I send the desktop notifications, though? Would it be through Steam Tinker Launch, or from my scripts? |
You can send notifications through your script using |
I ended up going with the more over-the-top
and
Gives it more of a feel of like Mario Party or a retro video game 😆 Just curious, but is it possible to change the order that notifications appear on the screen? The starting notification is in-between the others, while the ending notification is at the very end 😅 I made the start notification a little bit longer than the end one--to balance things out somewhat--but it still seems kind of...weird that the order is different like that 🤔 |
Hmm, the urgency level may let you do this. You can set it with the So, what you can do, is use
If you have multiple notifications with varying priorities:
There is a man page for |
Thanks for all this! I noticed the urgency flag, but I didn't really know what it did, so thanks for the explanation 😅 The other thing I was kinda surprised at was how you suggested As usual, I'll tinker with stuff to see what I can come up with, but it's looking like Low Priority for both start and end is what I'm going to want 👍 |
Heh, I don't have a whole lot of experience with sending cross-platform notifications with Python. If there was going to be a library it would probably use |
Ooh, I see. I was also considering one of the options from here (https://wiki.archlinux.org/title/Desktop_notifications#Python) or desktop-notifier 😄 On the notification urgency side: Low priority seems to have the correct placing, but dunst displays it as a grey-and-black notification that's really hard to see, so I'm going to see if I can...come up with an idea to make it readable but still visually "low-priority" 🤔 😅 This whole thing has just been one thing after another:
And now, notifications. Hopefully this last step is easier than the previous ones 😅 |
All right, I think I've tweaked the config for Dunst--my notification server--enough to where it's usable now. Not much more to add at the moment, but I wanted to thank you once more for giving me the encouragement and advice to make this thing happen. As you might imagine: manually tracking all this stuff was quite tedious, and all the extra work in setting things up for each session made it hard to just jump in and have fun whenever I wanted to play something. So having this script/program/etc. available really helps 👍 I mean, I have pretty much everything I'd like (besides qualitative data) automatically gathered and recorded for me. It's wonderful The main thing I'd want more is a way to automatically record which playthrough I'm currently on, because:
However, without a way to easily obtain it--I assume that I'd need a way to hook into the game somehow--I'll just have to settle for adding it myself, I guess 😆 I mean, right? It's not something that Steam or STL picks up, yes? I assume with how flexible and subjective the idea of "starting a new playthrough" is, it'd end up more on the qualitative side of things. I'd love to hear if that's not the case, though 👀 Anyway, all that is to say: thank you very much 💜 🙏 I guess now I just have to gear up for the database work in the future 🤣 |
Oooh these look neat. I never looked too much into the Python side but these might work better in your use-case, it would be a bit more Pythonic.
Oh hmm, I guess this is related to your desktop/theme? It could be a theming bug as well. I didn't think about that, although I could see it since on KDE Plasma, high priority notifications display with some extra theming, so it isn't out of the question that other priorities would use different theming either. The Dunst GitHub repo Readme actually shows notification priority examples, and they should be readable here. Perhaps you can customise the theme? It seems like clicking the screenshot will give code examples too.
Hmm, you mean if you started a playthrough, finished a game, and then wanted to track that as one whole playthrough before starting a new save/run/etc? I think you'd need to hook into the game for that, I don't think that comes from Steam or anything. Having said that, you might not have to hook into the game yourself to accomplish this. There might be per-game projects for tracking this. I'm not sure how you'd even begin looking for a project like that. I think you got it right here unfortunately, it's too broad and subjective to have a universal solution, but I could see there being mods that let you accomplish this. Maybe there are mods that can dump data from a current playthrough to a human-readable text/JSON/some other format? And it might contain information like "game completed" or something along these lines. This would be per-game though still sadly.
No problem! I'm glad I could help at all 😄 Happy gaming! |
I might very well try implementing one of those. I mean,
Yeah, I changed the background and font colors to make it kind of work. There's a bit too much contrast now, IMO--I have a dark blue background and green/cyan fonts--so I'm probably going to change up the background color somewhat. I didn't really think of coloring the border for low/medium priority notifications, so thanks for suggesting the link! 👍
So I went on another deep dive with all this. Don't know if it'll lead anywhere, but... 😅 I was thinking: the Steam overlay has to somehow track game progress in order to unlock achievements, right? Is that something that is just between Steam and the game, or does it get sent somewhere where another program can read it (STL, for example)? It'd still be a per-game solution, and there are still some potential drawbacks:
As usual, my search led me to some interesting--yet not entirely related spots:
So yeah...no big gold mines yet 😕
You know, I don't know if I mentioned this already--and if I did, I apologize--but the whole thing behind all this was that I was into game journaling a while back. However, as I usually do, I went so deep into thinking about how to organize my database that I really didn't spend much time actually playing or logging the games. Like:
It was--and will likely still be, if I ever get back to it--pretty crazy. But a script like this will at least help with the automated quantitative stuff, which should free me up to work on the stuff that actually needs my input 😆 That's also kind of why I'd like as much of the process to be automated, if that makes sense. I was at some point trying to make either a stopwatch or a playthrough tracking app; but an automated game logger really wasn't on my radar. However, I'm definitely happy you suggested it 😁 Thanks again! 💜 🙏 |
Hey there! It's me again 😁
This one might be a bit weird, but hopefully most of it is in-scope.
Recently, after discovering Backloggd (https://www.backloggd.com/) I've been looking into journaling the details of my gaming sessions once again. Since Steam Tinker Launch records the date and the session duration, I felt like it would be an okay fit for this task.
I found this while looking at the source:
https://github.com/sonic2kk/steamtinkerlaunch/blob/7199cf53904f4956c1ee708fcdfd4ad9293900c2/steamtinkerlaunch#L19419
However, I had a few questions:
date +%d.%m.%Y
.However, the
date
manual also shows date formats like:or
I feel like one of these would work better than a specifically hardcoded date format 😅
Besides that: would it be possible to add the time as well? Something like
$(date "+%F %T")
, for example; with %T being:Related to the above: the function seems to be taking the argument
${1}
(from what I understand), but I'm not sure what${1}
actually is, in this case. Presumably, it's a number representing the duration of the session (in seconds); but can it record milliseconds (or anything else)? And is the number coming from Steam, or from somewhere else?Again, sorry if this last one's too out of scope, but I'm curious. Even if I have to try and write a program myself, it's better to understand how the source works, right? 😅
Thanks! 💜
The text was updated successfully, but these errors were encountered: