diff --git a/DOCS.md b/DOCS.md
index de6a819..c36d056 100644
--- a/DOCS.md
+++ b/DOCS.md
@@ -82,7 +82,9 @@ Examples can be seen in the repository (`Discord-RPC/examples`) or [here](https:
Parameters :
- state (`str`)
- details (`str`)
- - act_type (`discordrpc.Activity`) : [Activity Types](https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-types) (Activity Type `1` and `4` is currently disabled, see [#28](https://github.com/Senophyx/Discord-RPC/issues/28#issuecomment-2301287350)).
+ - act_type (`discordrpc.Activity`) : [Activity Types](#class-discordrpcactivity) (Activity Type `1` and `4` is currently disabled, see [#28](https://github.com/Senophyx/Discord-RPC/issues/28#issuecomment-2301287350)).
+ - state_url (`str`) : URL that is linked when clicking on the state text.
+ - details_url (`str`) : URL that is linked when clicking on the details text.
- ts_start (`int`) : Timestamp start.
- ts_end (`int`) : Timestamp end.
- large_image (`str`) : The name of the image that has been uploaded to the Discord Developer Portal.
@@ -94,10 +96,15 @@ Examples can be seen in the repository (`Discord-RPC/examples`) or [here](https:
- join_secret (`str`) : Secret for chat invitations and ask to join button.
- spectate_secret (`str`) : Secret for spectate button.
- match_secret (`str`) : Secret for for spectate and join button
- - buttons (`list`) : list of dicts for buttons on user's profile. You can use `discordrpc.Button` for more easier.
+ - buttons (`list`) : list of dicts for buttons on user's profile. You can use [`discordrpc.Button`](#function-discordrpcbutton) for more easier.
Return : `True` if rpc successfully connected.
+- method `RPC.clear()`
+ Clear activity status.
+
+ Return : nothing.
+
- method `RPC.disconnect()`
Disconnecting and closing RPC socket.
@@ -124,10 +131,15 @@ Examples can be seen in the repository (`Discord-RPC/examples`) or [here](https:
Return : `True` or `False`
+- variable `self.User`
+ Returns information about the user to whom the connection occurred.
+ [Available attributes](#class-discordrpcuser)
+
## class `discordrpc.Activity`
- Enum `Activity`
- Simplified Activity type payload in `RPC.set_activity`
+ Simplified Activity type payload in `RPC.set_activity`
+ [Discord docs](https://discord.com/developers/docs/topics/gateway-events#activity-object-activity-types)
Available values :
- Playing
@@ -142,13 +154,12 @@ Examples can be seen in the repository (`Discord-RPC/examples`) or [here](https:
> [Details](https://github.com/Senophyx/Discord-RPC/issues/28#issuecomment-2301287350)
-## class `discordrpc.Button()`
-- function `Button()`
- Simplified button payload in `RPC.set_activity`
+## function `discordrpc.Button()`
+- Simplified button payload in `RPC.set_activity`
Parameters :
- - text (`test`)
- - text (`url`)
+ - text (`str`)
+ - url (`str`)
Return : Payload dict.
@@ -156,6 +167,27 @@ Examples can be seen in the repository (`Discord-RPC/examples`) or [here](https:
> Discord does not display buttons in your own Activity.
> You won’t see them yourself — but other users will see them correctly.
+
+## function `discordrpc.Progressbar()`
+- Simplified `ts_start` and `ts_end` payload in `RPC.set_activity`
+
+ Parameters :
+ - current (`int`)
+ - duration (`int`)
+
+ Return : Payload dict.
+
+
+## class `discordrpc.User()`
+ Attributes :
+ - id (`int`)
+ - username (`str`)
+ - name (`str`)
+ - avatar (URL `str`)
+ - bot (`bool`)
+ - premium_type (`int`) ([details](https://discord.com/developers/docs/resources/user#user-object-premium-types))
+
+
## class `discordrpc.utils`
- variable `discordrpc.utils.timestamp()`
Return current time in epoch timestamp (`int`).
@@ -169,6 +201,9 @@ Examples can be seen in the repository (`Discord-RPC/examples`) or [here](https:
date_to_timestamp('14/06/2025-00:00:00')
```
+- function `discordrpc.utils.use_local_time()`
+ Simplified `ts_start` payload in `RPC.set_activity`
+
## Exceptions & Errors
- `RPCException`
@@ -204,6 +239,11 @@ Examples can be seen in the repository (`Discord-RPC/examples`) or [here](https:
How-to-Fix : Check if `Button` function are set correctly
+- `ProgressbarError`
+ There is an error in the `Progressbar` function, usually because the first parameter (current) is more then second parameter (duration).
+
+ How-to-Fix : Make sure that duration > current
+
## Links
- [Github Repository](https://github.com/Senophyx/Discord-RPC)
diff --git a/discordrpc/__init__.py b/discordrpc/__init__.py
index e8598b3..5782154 100644
--- a/discordrpc/__init__.py
+++ b/discordrpc/__init__.py
@@ -1,8 +1,9 @@
from .presence import RPC
from .button import Button
+from .progressbar import Progressbar
from .exceptions import *
from .types import *
-from .utils import timestamp, date_to_timestamp
+from .utils import timestamp, date_to_timestamp, use_local_time
__title__ = "Discord RPC"
__version__ = "5.1"
diff --git a/discordrpc/button.py b/discordrpc/button.py
index 154220b..de78c25 100644
--- a/discordrpc/button.py
+++ b/discordrpc/button.py
@@ -3,5 +3,5 @@
def Button(text:str, url:str):
if not url.startswith(("http://", "https://")):
- raise InvalidURL
+ raise InvalidURL()
return {"label": text, "url": url}
diff --git a/discordrpc/exceptions.py b/discordrpc/exceptions.py
index 9c44205..22ae980 100644
--- a/discordrpc/exceptions.py
+++ b/discordrpc/exceptions.py
@@ -28,6 +28,10 @@ class ButtonError(RPCException):
def __init__(self, message: str = None):
super().__init__(message=message)
+class ProgressbarError(RPCException):
+ def __init__(self, message):
+ super().__init__(message=message)
+
class InvalidActivityType(RPCException):
def __init__(self, message):
super().__init__(f"Activity type must be , not {message}")
@@ -35,4 +39,4 @@ def __init__(self, message):
# https://github.com/Senophyx/Discord-RPC/issues/28#issuecomment-2301287350
class ActivityTypeDisabled(RPCException):
def __init__(self):
- super().__init__(f"Activity type `Streaming` and `Custom` currently disabled. See https://github.com/Senophyx/Discord-RPC/issues/28#issuecomment-2301287350")
\ No newline at end of file
+ super().__init__(f"Activity type `Streaming` and `Custom` currently disabled. See https://github.com/Senophyx/Discord-RPC/issues/28#issuecomment-2301287350")
diff --git a/discordrpc/presence.py b/discordrpc/presence.py
index c8ebfee..80744ad 100644
--- a/discordrpc/presence.py
+++ b/discordrpc/presence.py
@@ -7,7 +7,7 @@
import re
from .exceptions import *
from .types import *
-from .utils import remove_none
+from .utils import *
import logging
import time
@@ -28,7 +28,9 @@ def __init__(self, app_id:int, debug:bool=False, output:bool=True, exit_if_disco
self.app_id = str(app_id)
self.exit_if_discord_close = exit_if_discord_close
self.exit_on_disconnect = exit_on_disconnect
- self.User={}
+
+ self.user_data = {}
+ self.User = User()
if debug == True:
log.setLevel(logging.DEBUG)
@@ -42,27 +44,26 @@ def __init__(self, app_id:int, debug:bool=False, output:bool=True, exit_if_disco
def _setup(self):
if sys.platform == "win32":
self.ipc = WindowsPipe(self.app_id, self.exit_if_discord_close, self.exit_on_disconnect)
- if not self.ipc.connected:
- return
-
- self.User=self.ipc.handshake()
-
else:
self.ipc = UnixPipe(self.app_id, self.exit_if_discord_close, self.exit_on_disconnect)
- if not self.ipc.connected:
- return
-
- self.User=self.ipc.handshake()
+
+ if not self.ipc.connected: return
+ self.user_data = self.ipc.handshake()
+ self.User = User(self.user_data)
def set_activity(
self,
state: str=None, details:str=None, act_type:Activity=Activity.Playing,
+ state_url:str=None, details_url:str=None,
ts_start:int=None, ts_end:int=None,
+ # progressbar:dict=None,
+ # use_local_time:bool=False,
large_image:str=None, large_text:str=None,
small_image:str=None, small_text:str=None,
party_id:str=None, party_size:list=None,
join_secret:str=None, spectate_secret:str=None,
- match_secret:str=None, buttons:list=None
+ match_secret:str=None, buttons:list=None,
+ clear=False
) -> bool:
if type(party_id) == int:
@@ -82,6 +83,8 @@ def set_activity(
"state": state,
"details": details,
"type": act_type.value,
+ "state_url": state_url,
+ "details_url": details_url,
"timestamps": {
"start": ts_start,
"end": ts_end
@@ -108,7 +111,7 @@ def set_activity(
'cmd': 'SET_ACTIVITY',
'args': {
'pid': os.getpid(),
- 'activity': remove_none(act)
+ 'activity': None if clear else remove_none(act)
},
'nonce': str(uuid.uuid4())
}
@@ -128,6 +131,9 @@ def set_activity(
log.error('Failed to set RPC')
self.disconnect()
+ def clear(self):
+ self.set_activity(clear=True)
+
def disconnect(self):
if not self.ipc.connected:
return
@@ -219,7 +225,7 @@ def handshake(self):
except KeyError:
if data['code'] == 4000:
- raise InvalidID
+ raise InvalidID()
def disconnect(self):
try:
@@ -300,7 +306,7 @@ def handshake(self):
except KeyError:
if data['code'] == 4000:
- raise InvalidID
+ raise InvalidID()
def disconnect(self):
try:
diff --git a/discordrpc/progressbar.py b/discordrpc/progressbar.py
new file mode 100644
index 0000000..67e1379
--- /dev/null
+++ b/discordrpc/progressbar.py
@@ -0,0 +1,14 @@
+import time
+from .exceptions import *
+
+
+def Progressbar(current:int, duration:int) -> dict:
+ if int(current) > int(duration):
+ raise ProgressbarError("Current cannot exceed Duration")
+
+ current_time = int(time.time()) - int(current)
+ finish_time = current_time + int(duration)
+
+ return {
+ "ts_start": current_time, "ts_end": finish_time
+ }
diff --git a/discordrpc/types.py b/discordrpc/types.py
index 31251c0..540462e 100644
--- a/discordrpc/types.py
+++ b/discordrpc/types.py
@@ -2,7 +2,6 @@
# https://discord.com/developers/docs/events/gateway-events#activity-object-activity-types
-
class Activity(Enum):
Playing = 0
Streaming = 1
@@ -10,3 +9,24 @@ class Activity(Enum):
Watching = 3
Custom = 4
Competing = 5
+
+
+class User():
+ def __init__(self, data:dict=None):
+ data = data or {}
+ self.id: int = int(data.get('id', 0))
+ self.username: str = data.get('username')
+ self.name: str = data.get('global_name')
+ self.avatar: str = self._parse_avatar(data)
+ self.bot: bool = data.get('bot', False)
+ self.premium_type: int = int(data.get('premium_type', 0)) # https://discord.com/developers/docs/resources/user#user-object-premium-types
+
+ def _parse_avatar(self, data:dict, size:int=1024) -> str:
+ if data.get('avatar'):
+ ext = "gif" if data.get('avatar').startswith("a_") else "png"
+ return f"https://cdn.discordapp.com/avatars/{self.id}/{data.get('avatar')}.{ext}?size={size}"
+ else:
+ return f"https://cdn.discordapp.com/embed/avatars/0.png"
+
+ def __str__(self):
+ return f"User({self.name})"
diff --git a/discordrpc/utils.py b/discordrpc/utils.py
index 1a702da..7667048 100644
--- a/discordrpc/utils.py
+++ b/discordrpc/utils.py
@@ -1,5 +1,5 @@
import time
-import datetime
+from datetime import datetime
# Credits to qwertyquerty
# https://github.com/qwertyquerty/pypresence/blob/master/pypresence/utils.py#L12C1-L21C13
@@ -21,5 +21,12 @@ def remove_none(d: dict):
def date_to_timestamp(date:str):
return int(time.mktime(
- datetime.datetime.strptime(date, "%d/%m/%Y-%H:%M:%S").timetuple()
- ))
\ No newline at end of file
+ datetime.strptime(date, "%d/%m/%Y-%H:%M:%S").timetuple()
+ ))
+
+def use_local_time():
+ now = datetime.now()
+ seconds_since_midnight = now.hour * 3600 + now.minute * 60 + now.second
+ return {
+ "ts_start": int(time.time()) - seconds_since_midnight
+ }
diff --git a/examples/get-user.py b/examples/get-user.py
new file mode 100644
index 0000000..9fd50bd
--- /dev/null
+++ b/examples/get-user.py
@@ -0,0 +1,10 @@
+import discordrpc
+
+rpc = discordrpc.RPC(app_id=1397914682659963050)
+
+print(rpc.User.id)
+print(rpc.User.name)
+print(f"@{rpc.User.username}")
+print(rpc.User.avatar)
+
+rpc.run()
diff --git a/examples/rpc-local-time.py b/examples/rpc-local-time.py
new file mode 100644
index 0000000..004adfd
--- /dev/null
+++ b/examples/rpc-local-time.py
@@ -0,0 +1,13 @@
+import discordrpc
+from discordrpc import use_local_time
+
+
+rpc = discordrpc.RPC(app_id=1397914682659963050)
+
+rpc.set_activity(
+ state="Wow! It's shows my clock",
+ details="Local time example",
+ **use_local_time()
+)
+
+rpc.run()
diff --git a/examples/rpc-with-progressbar.py b/examples/rpc-with-progressbar.py
new file mode 100644
index 0000000..0b2f2e4
--- /dev/null
+++ b/examples/rpc-with-progressbar.py
@@ -0,0 +1,14 @@
+import discordrpc
+from discordrpc import Activity, Progressbar
+
+
+rpc = discordrpc.RPC(app_id=1397914682659963050)
+
+rpc.set_activity(
+ state="With Progressbar",
+ details="Music",
+ act_type=Activity.Listening,
+ **Progressbar(50, 200)
+)
+
+rpc.run()