Skip to content
This repository has been archived by the owner on Jun 26, 2019. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Tenrys committed Mar 29, 2018
0 parents commit 782918d
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 0 deletions.
26 changes: 26 additions & 0 deletions lua/autorun/discordrpc_init.lua
@@ -0,0 +1,26 @@

Msg("DiscordRPC loading: start\n")

local function load(path)
local action = CLIENT and include or AddCSLuaFile -- this is completely clientside, soo...
action(path)
print("\tLoaded: " .. path)
end

load("discordrpc/init.lua")
if SERVER then -- if server then just add the files to download
for _, fn in next, (file.Find("discordrpc/states/*.lua", "LUA")) do
load("discordrpc/states/" .. fn)
end
else -- otherwise create the function to load states later in main.lua
function discordrpc.LoadStates()
for _, fn in next, (file.Find("discordrpc/states/*.lua", "LUA")) do
load("discordrpc/states/" .. fn)
end
end
end
load("discordrpc/main.lua")


Msg("DiscordRPC loading: done!\n")

116 changes: 116 additions & 0 deletions lua/discordrpc/init.lua
@@ -0,0 +1,116 @@

-- Credits to SpiralP and Tenrys
-- Currently Discord Canary only
-- Fail message: Not authenticated or invalid scope

discordrpc = discordrpc or {}
discordrpc.port = discordrpc.port

discordrpc.states = discordrpc.states or {}
discordrpc.state = discordrpc.state

-- discordrpc.clientID (string) should be set in main.lua
-- discordrpc.state (string) should be set later in main.lua as the starting state

function discordrpc.Print(...)
local header = "[Discord RPC%s] "
local args = {...}
if type(args[1]) ~= "string" then
header = header:format(" DEBUG")
end

MsgC(Color(114, 137, 218), header)
print(...)
end
function discordrpc.Init(callback)
if not discordrpc.port then
local validPort
for port = 6463, 6473 do
local success = function(body)
if body:match("Authorization Required") and not validPort then
discordrpc.Print(("Connection success on port %s! "):format(port))
validPort = port
discordrpc.port = validPort

discordrpc.SetActivity({ details = "...", state = "..." }, function(body, err)
if not body and err:match("Not authenticated or invalid scope") then
discordrpc.Print("Warning: first SetActivity test didn't work, make sure you're using Discord Canary!")
else
discordrpc.Print("First SetActivity test was successful, should be ready to work!")
end

if callback then
callback(body, err)
end
end)
end
end
local failed = function(...)
-- do nothing
end
http.Fetch(("http://127.0.0.1:%s"):format(port), success, failed)
end
end
end
function discordrpc.SetActivity(activity, callback)
if not discordrpc.port then
ErrorNoHalt("DiscordRPC: port unset, did you Init?")
return
end

HTTP{
method = "POST",
url = ("http://127.0.0.1:%s/rpc?v=1&client_id=%s"):format(discordrpc.port, discordrpc.clientID),

type = "application/json",
body = util.TableToJSON{
cmd = "SET_ACTIVITY",
args = {
pid = 12345, -- This doesn't really matter though it would be nice if we could get GMod's process ID in Lua
activity = activity
},
nonce = tostring(SysTime())
},

success = function(status, body)
local data = util.JSONToTable(body)
if not data or data.evt == "ERROR" then
callback(false, "Discord error: " .. tostring(data.data and data.data.message or "nil"))
else
callback(data)
end
end,
failed = function(err)
callback(false, "HTTP error: " .. err)
end,
}
end
local defaultActivity = {
details = "???",
state = "Default state"
}
function discordrpc.GetActivity()
local activity = {}

if discordrpc.state then
local state = discordrpc.states[discordrpc.state]
if state then
activity = state.GetActivity and state:GetActivity() or {
details = state:GetDetails(),
state = state:GetState(),
timestamps = state:GetTimestamps(),
assets = state:GetAssets()
-- Other fields available that we can't use (atleast I don't think so): party, secrets, instance, application_id, flags
}
else
discordrpc.Print(("Error: State %s not found? Getting default activity!"):format(discordrpc.state))
activity = defaultActivity
end
else
discordrpc.Print("Warning: No state selected, getting default activity!")
activity = defaultActivity
end

return activity
end

37 changes: 37 additions & 0 deletions lua/discordrpc/main.lua
@@ -0,0 +1,37 @@

if not discordrpc then ErrorNoHalt("DiscordRPC: missing???") return end

discordrpc.clientID = "XXXXXXXXXXXXXXXXXX" -- This is your Discord application's client ID: https://discordapp.com/developers/applications/me
discordrpc.state = "example" -- This is the default state when you first load in.

http.Loaded = http.Loaded and http.Loaded or false
local function checkHTTP()
http.Fetch("http://google.com", function()
http.Loaded = true
end, function()
http.Loaded = true
end)
end
if not http.Loaded then
timer.Create("HTTPLoadedCheck", 3, 0, function()
if not http.Loaded then
checkHTTP()
else
hook.Run("HTTPLoaded")
timer.Remove("HTTPLoadedCheck")
end
end)
end

hook.Add("HTTPLoaded", "discordrpc_metastruct", function()
discordrpc.Init(function(succ, err)
if succ then
discordrpc.LoadStates()

discordrpc.SetActivity(discordrpc.GetActivity(), discordrpc.Print)
else
discordrpc.Print(succ, err)
end
end)
end)

36 changes: 36 additions & 0 deletions lua/discordrpc/states/example.lua
@@ -0,0 +1,36 @@

if not discordrpc then ErrorNoHalt("DiscordRPC: missing???") return end

local example = {}
function example:GetDetails()
return "Some details"
end
function example:GetState()
return "In Game"
end
local start = os.time() -- os.time since spawned in the server, do not edit
function example:GetTimestamps()
return {
start = start,
["end"] = nil -- nothing?
}
end
function example:GetAssets()
local assets = {}

-- Do whatever with the assets you add.

return assets
end
function example:GetActivity()
return {
details = self:GetDetails(),
state = self:GetState(),
timestamps = self:GetTimestamps(),
assets = self:GetAssets()
}
discordrpc.states.example = example

-- Follow these guidelines: https://discordapp.com/developers/docs/topics/gateway#activity-object
-- You cannot use these fields: party, secrets, instance, application_id, flags (I'm not sure actually but you should only try if you know what you're doing)

0 comments on commit 782918d

Please sign in to comment.