Fix local broken repo and commit all lost changes.

- XDG specification for data and file config
 - Better logger
 - Add Remote Roster Manager (compatible with Prosody)
 - Remove Chatstates notification (making bug, have to investigate)
 - Add an admin that have privilege
 - Add Ad-Hoc commands :
   - Uptime
   - Send message broadcast
 - Bugs fixe
This commit is contained in:
chteufleur 2016-10-23 19:08:14 +02:00
parent 795d443878
commit a4518d3f6b
9 changed files with 584 additions and 249 deletions

View File

@ -0,0 +1,98 @@
package configuration
import (
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/database"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/gateway"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/logger"
"github.com/jimlawless/cfg"
"os"
"strings"
)
const (
XdgDirectoryName = "xmpp4steam"
configurationFilePath = "xmpp4steam/xmpp4steam.conf"
PathConfEnvVariable = "XDG_CONFIG_DIRS"
DefaultXdgConfigDirs = "/etc/xdg"
PathDataEnvVariable = "XDG_DATA_DIRS"
DefaultXdgDataDirs = "/usr/local/share/:/usr/share/"
PreferedPathDataDir = "/usr/local/share"
)
var (
MapConfig = make(map[string]string)
)
func Init() {
loadConfigFile()
dataPathDir := locateDataDirPath()
database.DatabaseFile = dataPathDir + "/" + database.DatabaseFileName
database.Init()
gateway.ServerAddrs = dataPathDir + "/" + gateway.ServerAddrs
gateway.SentryDirectory = dataPathDir + "/" + gateway.SentryDirectory
os.MkdirAll(gateway.SentryDirectory, 0700)
}
func loadConfigFile() bool {
ret := false
envVariable := os.Getenv(PathConfEnvVariable)
if envVariable == "" {
envVariable = DefaultXdgConfigDirs
}
for _, path := range strings.Split(envVariable, ":") {
logger.Debug.Println("Try to find configuration file into " + path)
configFile := path + "/" + configurationFilePath
if _, err := os.Stat(configFile); err == nil {
// The config file exist
if cfg.Load(configFile, MapConfig) == nil {
// And has been loaded succesfully
logger.Info.Println("Find configuration file at " + configFile)
ret = true
break
}
}
}
return ret
}
func locateDataDirPath() string {
ret := ""
isDirFound := false
envVariable := os.Getenv(PathDataEnvVariable)
if envVariable == "" {
envVariable = DefaultXdgDataDirs
}
for _, path := range strings.Split(envVariable, ":") {
logger.Debug.Printf("Try to find data base directory into " + path)
dbDir := path + "/" + XdgDirectoryName
if fi, err := os.Stat(dbDir); err == nil && fi.IsDir() {
// The database file exist
logger.Info.Printf("Find data base directory at " + dbDir)
isDirFound = true
ret = dbDir
break
}
}
if !isDirFound {
if strings.Contains(envVariable, PreferedPathDataDir) {
ret = PreferedPathDataDir + "/" + XdgDirectoryName
} else {
ret = strings.Split(envVariable, ":")[0] + "/" + XdgDirectoryName
}
if os.MkdirAll(ret, 0700) == nil {
logger.Info.Printf("Creating new data base directory at " + ret)
} else {
logger.Error.Printf("Fail to create data base directory at " + ret)
os.Exit(1)
}
}
return ret
}

View File

@ -2,22 +2,19 @@ package database
import (
"database/sql"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/logger"
_ "github.com/mattn/go-sqlite3"
"log"
)
const (
databaseFile = "go_xmpp4steam.db"
DatabaseFileName = "go_xmpp4steam.db"
createDatabaseStmt = "create table if not exists users (jid text not null primary key, steamLogin text, steamPwd text, debug int);"
insertDatabaseStmt = "insert into users (jid, steamLogin, steamPwd, debug) values(?, ?, ?, ?)"
deleteDatabaseStmt = "delete from users where jid=?"
selectDatabaseStmt = "select jid, steamLogin, steamPwd, debug from users where jid=?"
selectAllDatabaseStmt = "select jid, steamLogin, steamPwd, debug from users"
updateDatabaseStmt = "update users set steamLogin=?, steamPwd=?, debug=? where jid=?"
LogInfo = "\t[SQLITE INFO]\t"
LogError = "\t[SQLITE ERROR]\t"
LogDebug = "\t[SQLITE DEBUG]\t"
)
type DatabaseLine struct {
@ -29,18 +26,23 @@ type DatabaseLine struct {
var (
db = new(sql.DB)
DatabaseFile = ""
)
func init() {
d, err := sql.Open("sqlite3", databaseFile)
}
func Init() {
logger.Info.Printf("Init database (file %s)", DatabaseFile)
d, err := sql.Open("sqlite3", DatabaseFile)
if err != nil {
log.Printf("%sError on openning database", LogError, err)
logger.Error.Printf("Error on openning database", err)
}
db = d
_, err = db.Exec(createDatabaseStmt)
if err != nil {
log.Printf("%sFailed to create table", LogError, err)
logger.Error.Printf("Failed to create table", err)
}
}
@ -49,7 +51,7 @@ func Close() {
}
func (newLine *DatabaseLine) AddLine() bool {
log.Printf("%sAdd new line %v", LogInfo, newLine)
logger.Info.Printf("Add new line %v", newLine)
isUserRegistred := getLine(newLine.Jid) != nil
if isUserRegistred {
@ -58,7 +60,7 @@ func (newLine *DatabaseLine) AddLine() bool {
stmt, err := db.Prepare(insertDatabaseStmt)
if err != nil {
log.Printf("%sError on insert jid %s", LogError, newLine.Jid, err)
logger.Error.Printf("Error on insert jid %s", newLine.Jid, err)
return false
}
defer stmt.Close()
@ -68,7 +70,7 @@ func (newLine *DatabaseLine) AddLine() bool {
}
_, err = stmt.Exec(newLine.Jid, newLine.SteamLogin, newLine.SteamPwd, debug)
if err != nil {
log.Printf("%sError on creating SQL statement", LogError, err)
logger.Error.Printf("Error on creating SQL statement", err)
return false
}
@ -76,10 +78,10 @@ func (newLine *DatabaseLine) AddLine() bool {
}
func (newLine *DatabaseLine) UpdateLine() bool {
log.Printf("%sUpdate line %s", LogInfo, newLine.Jid)
logger.Info.Printf("Update line %s", newLine.Jid)
stmt, err := db.Prepare(updateDatabaseStmt)
if err != nil {
log.Printf("%sError on update ", LogError, err)
logger.Error.Printf("Error on update ", err)
return false
}
defer stmt.Close()
@ -93,7 +95,7 @@ func (newLine *DatabaseLine) UpdateLine() bool {
}
_, err = stmt.Exec(newLine.SteamLogin, newLine.SteamPwd, debug, newLine.Jid)
if err != nil {
log.Printf("%sError on updating SQL statement", LogError, err)
logger.Error.Printf("Error on updating SQL statement", err)
return false
}
@ -118,26 +120,26 @@ func RemoveLine(jid string) bool {
line.Jid = jid
line.UpdateLine()
log.Printf("%sRemove line %s", LogInfo, jid)
logger.Info.Printf("Remove line %s", jid)
stmt, err := db.Prepare(deleteDatabaseStmt)
if err != nil {
log.Printf("%sError on delete jid %s", LogError, jid, err)
logger.Error.Printf("Error on delete jid %s", jid, err)
return false
}
defer stmt.Close()
res, err := stmt.Exec(jid)
if err != nil {
log.Printf("%sError on delete SQL statement", LogError, err)
logger.Error.Printf("Error on delete SQL statement", err)
return false
}
affect, err := res.RowsAffected()
if err != nil {
log.Printf("%sError on delete SQL statement", LogError, err)
logger.Error.Printf("Error on delete SQL statement", err)
return false
}
if affect == 0 {
log.Printf("%sNo line affected", LogDebug)
logger.Debug.Printf("No line affected")
return false
}
@ -148,7 +150,7 @@ func GetLine(jid string) *DatabaseLine {
ret := getLine(jid)
if ret == nil || ret.SteamLogin == "" {
log.Printf("%sLine empty", LogDebug)
logger.Debug.Printf("Line empty")
return nil
}
@ -156,19 +158,19 @@ func GetLine(jid string) *DatabaseLine {
}
func getLine(jid string) *DatabaseLine {
log.Printf("%sGet line %s", LogInfo, jid)
logger.Info.Printf("Get line %s", jid)
ret := new(DatabaseLine)
stmt, err := db.Prepare(selectDatabaseStmt)
if err != nil {
log.Printf("%sError on select line", LogError, err)
logger.Error.Printf("Error on select line", err)
return nil
}
defer stmt.Close()
debug := 0
err = stmt.QueryRow(jid).Scan(&ret.Jid, &ret.SteamLogin, &ret.SteamPwd, &debug)
if err != nil {
log.Printf("%sError on select scan", LogError, err)
logger.Error.Printf("Error on select scan", err)
return nil
}
if debug == 1 {
@ -181,18 +183,24 @@ func getLine(jid string) *DatabaseLine {
}
func GetAllLines() []DatabaseLine {
log.Printf("%sGet all lines", LogInfo)
logger.Info.Printf("Get all lines")
var ret []DatabaseLine
rows, err := db.Query("select jid, steamLogin, steamPwd from users")
rows, err := db.Query(selectAllDatabaseStmt)
if err != nil {
log.Printf("%sError on select query", LogError, err)
logger.Error.Printf("Error on select query", err)
}
defer rows.Close()
for rows.Next() {
user := new(DatabaseLine)
rows.Scan(&user.Jid, &user.SteamLogin, &user.SteamPwd)
debug := 0
rows.Scan(&user.Jid, &user.SteamLogin, &user.SteamPwd, &debug)
if user.SteamLogin != "" {
if debug == 1 {
user.Debug = true
} else {
user.Debug = false
}
ret = append(ret, *user)
}
}

View File

@ -2,14 +2,22 @@ package gateway
import (
"github.com/Philipp15b/go-steam"
"time"
)
const (
SentryDirectory = "sentries/"
resource = "go-xmpp4steam"
)
var (
SentryDirectory = "sentries/"
XmppGroupUser = "Steam"
RemoteRosterRequestPermission = "remote-roster-request-permission"
RemoteRosterRequestRoster = "remote-roster-request-roster"
)
type GatewayInfo struct {
// Steam
SteamLogin string
@ -27,6 +35,8 @@ type GatewayInfo struct {
XMPP_Connected_Client map[string]bool
XMPP_Composing_Timers map[string]*time.Timer
DebugMessage bool
XMPP_IQ_RemoteRoster_Request map[string]string
AllowEditRoster bool
}
type StatusSteamFriend struct {
@ -45,11 +55,17 @@ func (g *GatewayInfo) SetSteamAuthCode(authCode string) {
}
func (g *GatewayInfo) Disconnect() {
g.XMPP_Disconnect()
go g.XMPP_Disconnect()
go g.SteamDisconnect()
g.SteamConnecting = false
}
func (g *GatewayInfo) Delete() {
g.Deleting = true
if g.AllowEditRoster {
g.removeAllUserFromRoster()
}
g.Disconnect()
}

View File

@ -1,21 +1,18 @@
package gateway
import (
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/logger"
"github.com/Philipp15b/go-steam"
"github.com/Philipp15b/go-steam/protocol/steamlang"
"github.com/Philipp15b/go-steam/steamid"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"strconv"
"time"
)
const (
serverAddrs = "servers.addr"
State_Offline = steamlang.EPersonaState_Offline
State_Online = steamlang.EPersonaState_Online
State_Busy = steamlang.EPersonaState_Busy
@ -24,28 +21,34 @@ const (
State_LookingToTrade = steamlang.EPersonaState_LookingToTrade
State_LookingToPlay = steamlang.EPersonaState_LookingToPlay
State_Max = steamlang.EPersonaState_Max
)
LogSteamInfo = "\t[STEAM INFO]\t"
LogSteamError = "\t[STEAM ERROR]\t"
LogSteamDebug = "\t[STEAM DEBUG]\t"
var (
ServerAddrs = "servers.addr"
)
func (g *GatewayInfo) SteamRun() {
if g.Deleting {
log.Printf("%sDeleting gateway", LogSteamInfo)
logger.Info.Printf("[%s] Deleting gateway", g.XMPP_JID_Client)
return
}
log.Printf("%sRunning", LogSteamInfo)
logger.Info.Printf("[%s] Running", g.XMPP_JID_Client)
steam.InitializeSteamDirectory()
g.setLoginInfos()
if g.SteamClient == nil {
g.SteamClient = steam.NewClient()
}
g.SteamConnecting = false
g.SteamClient.ConnectionTimeout = 10 * time.Second
g.mainSteam()
log.Printf("%sReach main method's end", LogSteamInfo)
go g.SteamRun()
logger.Info.Printf("[%s] Reach main method's end", g.XMPP_JID_Client)
return
g.Disconnect()
go g.XMPP_Disconnect()
g.Run()
}
func (g *GatewayInfo) mainSteam() {
@ -54,7 +57,7 @@ func (g *GatewayInfo) mainSteam() {
case *steam.ConnectedEvent:
// Connected on server
g.SteamConnecting = false
log.Printf("%sConnected on Steam serveur", LogSteamDebug)
logger.Debug.Printf("[%s] Connected on Steam serveur", g.XMPP_JID_Client)
g.SteamClient.Auth.LogOn(g.SteamLoginInfo)
case *steam.MachineAuthUpdateEvent:
@ -66,26 +69,37 @@ func (g *GatewayInfo) mainSteam() {
g.SendSteamPresence(steamlang.EPersonaState_Online)
g.SendXmppMessage(XmppJidComponent, "", "Connected on Steam network")
case *steam.LoggedOffEvent:
logger.Error.Printf("[%s] LoggedOffEvent: ", g.XMPP_JID_Client, e)
g.SendXmppMessage(XmppJidComponent, "", fmt.Sprintf("Disconnected of Steam network (%v)", e))
g.SteamConnecting = false
case steam.FatalErrorEvent:
log.Printf("%sFatalError: ", LogSteamError, e)
g.SendXmppMessage(XmppJidComponent, "", "Steam Fatal Error : "+e.Error())
logger.Error.Printf("[%s] FatalError: ", g.XMPP_JID_Client, e)
g.SendXmppMessage(XmppJidComponent, "", fmt.Sprintf("Steam Fatal Error : %v", e))
g.DisconnectAllSteamFriend()
return
g.SteamConnecting = false
case *steam.DisconnectedEvent:
logger.Info.Printf("[%s] Disconnected event", g.XMPP_JID_Client)
g.SendXmppMessage(XmppJidComponent, "", fmt.Sprintf("Steam Error : %v", e))
g.DisconnectAllSteamFriend()
g.SteamConnecting = false
case error:
log.Printf("%s", LogSteamError, e)
logger.Error.Printf("[%s] ", g.XMPP_JID_Client, e)
g.SendXmppMessage(XmppJidComponent, "", "Steam Error : "+e.Error())
case *steam.LogOnFailedEvent:
logger.Error.Printf("[%s] Login failed", g.XMPP_JID_Client, e)
g.SendXmppMessage(XmppJidComponent, "", fmt.Sprintf("Login failed : %v", e.Result))
g.SteamConnecting = false
case *steam.ClientCMListEvent:
// Save servers addresses
b, err := json.Marshal(*e)
if err != nil {
log.Printf("%sFailed to json.Marshal() servers list", LogSteamError)
} else {
ioutil.WriteFile(serverAddrs, b, 0666)
}
// Doing nothing with server list
case *steam.PersonaStateEvent:
logger.Debug.Printf("[%s] Received PersonaStateEvent: %v", g.XMPP_JID_Client, e)
// Presenc received
if _, ok := g.SteamClient.Social.Friends.GetCopy()[e.FriendId]; !ok {
// Is not in friend list
@ -130,6 +144,7 @@ func (g *GatewayInfo) mainSteam() {
g.SendXmppPresence(status, tpye, "", steamId+"@"+XmppJidComponent, gameName, name)
case *steam.ChatMsgEvent:
logger.Debug.Printf("[%s] Received ChatMsgEvent: %v", g.XMPP_JID_Client, e)
// Message received
from := e.ChatterId.ToString() + "@" + XmppJidComponent
if e.EntryType == steamlang.EChatEntryType_Typing {
@ -141,6 +156,7 @@ func (g *GatewayInfo) mainSteam() {
}
case *steam.ChatInviteEvent:
logger.Debug.Printf("[%s] Received ChatInviteEvent: %v", g.XMPP_JID_Client, e)
// Invitation to play
if fromFriend, ok := g.SteamClient.Social.Friends.GetCopy()[e.FriendChatId]; ok {
messageToSend := fmt.Sprintf("Currently playing to « %s », would you like to join ?", fromFriend.GameName)
@ -148,7 +164,8 @@ func (g *GatewayInfo) mainSteam() {
}
default:
log.Printf("%s", LogSteamDebug, e)
logger.Debug.Printf("[%s] Steam unmatch event (Type: %T): %v", g.XMPP_JID_Client, e, e)
g.SendXmppMessage(XmppJidComponent, "", fmt.Sprintf("Steam unmatch event (Type: %T): %v", e, e))
}
}
}
@ -164,7 +181,7 @@ func (g *GatewayInfo) setLoginInfos() {
if err == nil {
g.SteamLoginInfo.SentryFileHash = sentryHash
}
log.Printf("%sAuthentification of (%s, %s)", LogSteamDebug, g.XMPP_JID_Client, g.SteamLoginInfo.Username)
logger.Debug.Printf("Authentification of (%s, %s)", g.XMPP_JID_Client, g.SteamLoginInfo.Username)
}
func (g *GatewayInfo) IsSteamConnected() bool {
@ -175,43 +192,36 @@ func (g *GatewayInfo) IsSteamConnected() bool {
ret = g.SteamClient.Connected()
}
}
logger.Debug.Printf("[%s] Is Steam connected (Connected: %v)", g.XMPP_JID_Client, ret)
return ret
}
func (g *GatewayInfo) SteamConnect() {
if g.IsSteamConnected() {
log.Printf("%sTry to connect, but already connected", LogSteamDebug)
logger.Debug.Printf("[%s] Try to connect, but already connected", g.XMPP_JID_Client)
return
}
if g.SteamConnecting {
log.Printf("%sTry to connect, but currently connecting…", LogSteamDebug)
logger.Debug.Printf("[%s] Try to connect, but currently connecting…", g.XMPP_JID_Client)
return
}
g.SteamConnecting = true
b, err := ioutil.ReadFile(serverAddrs)
if err == nil {
var toList steam.ClientCMListEvent
err := json.Unmarshal(b, &toList)
if err != nil {
log.Printf("%sFailed to json.Unmarshal() servers list", LogSteamError)
} else {
log.Printf("%sConnecting...", LogSteamInfo, toList.Addresses[0])
g.SteamClient.ConnectTo(toList.Addresses[0])
}
} else {
log.Printf("%sFailed to read servers list file", LogSteamError)
log.Printf("%sConnecting...", LogSteamInfo)
g.SteamClient.Connect()
}
go func() {
logger.Info.Printf("[%s] Connecting...", g.XMPP_JID_Client)
g.SendXmppMessage(XmppJidComponent, "", "Connecting...")
addr := g.SteamClient.Connect()
logger.Info.Printf("[%s] Connected on %v", g.XMPP_JID_Client, addr)
g.SendXmppMessage(XmppJidComponent, "", fmt.Sprintf("Connected on %v", addr))
}()
}
func (g *GatewayInfo) SteamDisconnect() {
if !g.IsSteamConnected() {
log.Printf("%sTry to disconnect, but already disconnected", LogSteamDebug)
logger.Debug.Printf("[%s] Try to disconnect, but already disconnected", g.XMPP_JID_Client)
return
}
log.Printf("%sSteam disconnect", LogSteamInfo)
logger.Info.Printf("[%s] Steam disconnect", g.XMPP_JID_Client)
g.XMPP_Disconnect()
g.DisconnectAllSteamFriend()
@ -219,6 +229,7 @@ func (g *GatewayInfo) SteamDisconnect() {
}
func (g *GatewayInfo) DisconnectAllSteamFriend() {
logger.Debug.Printf("[%s] Disconnect all Steam friend", g.XMPP_JID_Client)
for sid, _ := range g.FriendSteamId {
g.SendXmppPresence(Status_offline, Type_unavailable, "", sid+"@"+XmppJidComponent, "", "")
delete(g.FriendSteamId, sid)
@ -239,22 +250,24 @@ func (g *GatewayInfo) SendSteamMessageLeaveConversation(steamId string) {
func (g *GatewayInfo) sendSteamMessage(steamId, message string, chatEntryType steamlang.EChatEntryType) {
if !g.IsSteamConnected() {
log.Printf("%sTry to send message, but disconnected", LogSteamDebug)
logger.Debug.Printf("[%s] Try to send message, but disconnected", g.XMPP_JID_Client)
return
}
steamIdUint64, err := strconv.ParseUint(steamId, 10, 64)
if err == nil {
logger.Debug.Printf("[%s] Send message to %v", g.XMPP_JID_Client, steamIdUint64)
g.SteamClient.Social.SendMessage(steamid.SteamId(steamIdUint64), chatEntryType, message)
} else {
log.Printf("%sFailed to get SteamId from %s", LogSteamError, steamId)
logger.Error.Printf("[%s] Failed to get SteamId from %s", g.XMPP_JID_Client, steamId)
}
}
func (g *GatewayInfo) SendSteamPresence(status steamlang.EPersonaState) {
if !g.IsSteamConnected() {
log.Printf("%sTry to send presence, but disconnected", LogSteamDebug)
logger.Debug.Printf("[%s] Try to send presence, but disconnected", g.XMPP_JID_Client)
return
}
logger.Debug.Printf("[%s] Send presence (Status: %v)", g.XMPP_JID_Client, status)
g.SteamClient.Social.SetPersonaState(status)
}

View File

@ -2,9 +2,10 @@ package gateway
import (
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/logger"
"github.com/Philipp15b/go-steam/protocol/steamlang"
"log"
"strconv"
"strings"
"time"
)
@ -29,16 +30,20 @@ const (
ActionConnexion = "action_xmpp_connexion"
ActionDeconnexion = "action_xmpp_deconnexion"
ActionMainMethodEnded = "action_xmpp_main_method_ended"
LogXmppInfo = "\t[XMPP INFO]\t"
LogXmppError = "\t[XMPP ERROR]\t"
LogXmppDebug = "\t[XMPP DEBUG]\t"
)
var (
XmppJidComponent = ""
iqId = uint64(0)
)
func NextIqId() string {
iqId += 1
ret := strconv.FormatUint(iqId, 10)
return ret
}
func (g *GatewayInfo) ReceivedXMPP_Presence(presence *xmpp.Presence) {
if presence.Type == Type_error {
return
@ -77,19 +82,7 @@ func (g *GatewayInfo) ReceivedXMPP_Presence(presence *xmpp.Presence) {
if len(g.XMPP_Connected_Client) <= 0 {
g.Disconnect()
}
} else if presence.Type == Type_available {
go g.SteamConnect()
transfertPresence = true
}
} else {
// Destination is Steam user
if presence.Type == Type_unavailable {
// Disconnect
if len(g.XMPP_Connected_Client) <= 0 {
g.Disconnect()
}
} else if presence.Type == Type_available {
go g.SteamConnect()
transfertPresence = true
}
@ -118,7 +111,7 @@ func (g *GatewayInfo) ReceivedXMPP_Presence(presence *xmpp.Presence) {
if g.IsSteamConnected() {
g.SendSteamPresence(steamStatus)
g.SendXmppPresence(presence.Show, presence.Type, presence.From, "", presence.Status, "")
g.SendXmppPresence(presence.Show, presence.Type, "", "", presence.Status, "")
}
}
}
@ -140,6 +133,52 @@ func (g *GatewayInfo) ReceivedXMPP_Message(message *xmpp.Message) {
}
}
func (g *GatewayInfo) ReceivedXMPP_IQ(iq *xmpp.Iq) bool {
ret := false
if g.XMPP_IQ_RemoteRoster_Request[iq.Id] == RemoteRosterRequestPermission {
delete(g.XMPP_IQ_RemoteRoster_Request, iq.Id)
if iq.Type == xmpp.IQTypeError && iq.Error.Condition() == xmpp.ErrorForbidden {
g.AllowEditRoster = false
logger.Info.Printf("Set allow roster edition to %v", g.AllowEditRoster)
} else if iq.Type == xmpp.IQTypeSet && iq.PayloadName().Space == xmpp.NSRemoteRosterManager {
remoteRosterQuery := &xmpp.RemoteRosterManagerQuery{}
iq.PayloadDecode(remoteRosterQuery)
if remoteRosterQuery.Type == xmpp.RemoteRosterManagerTypeAllowed {
g.AllowEditRoster = true
} else if remoteRosterQuery.Type == xmpp.RemoteRosterManagerTypeRejected {
g.AllowEditRoster = false
} else {
g.AllowEditRoster = false
}
logger.Info.Printf("Set allow roster edition to %v", g.AllowEditRoster)
g.SendXmppMessage(XmppJidComponent, "", "Set allow roster edition to "+strconv.FormatBool(g.AllowEditRoster))
} else {
logger.Info.Printf("Check roster edition authorisation by querying roster's user")
// Remote roster namespace may not be supported (like prosody), so we send a roster query
iqId := NextIqId()
g.XMPP_IQ_RemoteRoster_Request[iqId] = RemoteRosterRequestRoster
iqSend := &xmpp.Iq{Id: iqId, Type: xmpp.IQTypeGet, From: iq.To, To: iq.From}
iqSend.PayloadEncode(&xmpp.RosterQuery{})
g.XMPP_Out <- iqSend
}
ret = true
} else if g.XMPP_IQ_RemoteRoster_Request[iq.Id] == RemoteRosterRequestRoster {
delete(g.XMPP_IQ_RemoteRoster_Request, iq.Id)
if iq.Type == xmpp.IQTypeResult && iq.PayloadName().Space == xmpp.NSRoster {
g.AllowEditRoster = true
} else {
g.AllowEditRoster = false
}
logger.Info.Printf("Set allow roster edition to %v", g.AllowEditRoster)
g.SendXmppMessage(XmppJidComponent, "", "Set allow roster edition to "+strconv.FormatBool(g.AllowEditRoster))
ret = true
}
return ret
}
func (g *GatewayInfo) XMPP_Disconnect() {
g.SendXmppPresence(Status_offline, Type_unavailable, "", "", "", "")
}
@ -165,18 +204,53 @@ func (g *GatewayInfo) SendXmppPresence(status, tpye, to, from, message, nick str
p.To = to
}
if from == "" {
// TODO add an option to allow message comming directly from the gateway
p.From = XmppJidComponent + "/" + resource
} else {
p.From = from + "/" + resource
}
log.Printf("%sSend presence %v", LogXmppInfo, p)
if tpye == Type_subscribe && g.AllowEditRoster {
g.addUserIntoRoster(from, nick)
} else {
logger.Info.Printf("Send presence %v", p)
g.XMPP_Out <- p
}
}
func (g *GatewayInfo) addUserIntoRoster(jid, nick string) {
iq := xmpp.Iq{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, Id: NextIqId()}
query := &xmpp.RosterQuery{}
queryItem := &xmpp.RosterItem{JID: jid, Name: nick, Subscription: xmpp.RosterSubscriptionBoth}
queryItem.Groupes = append(queryItem.Groupes, XmppGroupUser)
query.Items = append(query.Items, *queryItem)
iq.PayloadEncode(query)
logger.Info.Printf("Add user into roster %v", iq)
g.XMPP_Out <- iq
}
func (g *GatewayInfo) removeAllUserFromRoster() {
// Friends
for steamId, _ := range g.SteamClient.Social.Friends.GetCopy() {
iq := xmpp.Iq{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, Id: NextIqId()}
query := &xmpp.RosterQuery{}
query.Items = append(query.Items, *&xmpp.RosterItem{JID: steamId.ToString() + "@" + XmppJidComponent, Subscription: xmpp.RosterSubscriptionRemove})
iq.PayloadEncode(query)
logger.Info.Printf("Remove steam user roster")
g.XMPP_Out <- iq
}
// Myself
iq := xmpp.Iq{To: g.XMPP_JID_Client, Type: xmpp.IQTypeSet, Id: NextIqId()}
query := &xmpp.RosterQuery{}
query.Items = append(query.Items, *&xmpp.RosterItem{JID: g.SteamClient.SteamId().ToString() + "@" + XmppJidComponent, Subscription: xmpp.RosterSubscriptionRemove})
iq.PayloadEncode(query)
logger.Info.Printf("Remove steam user roster")
g.XMPP_Out <- iq
}
func (g *GatewayInfo) SendXmppMessage(from, subject, message string) {
g.sendXmppMessage(from, subject, message, &xmpp.Active{})
return
g.stopComposingTimer(from)
// Make inactive after 2 min if nothing happen
@ -188,11 +262,15 @@ func (g *GatewayInfo) SendXmppMessage(from, subject, message string) {
func (g *GatewayInfo) SendXmppMessageLeaveConversation(from string) {
g.sendXmppMessage(from, "", "", &xmpp.Gone{})
return
g.stopComposingTimer(from)
}
func (g *GatewayInfo) SendXmppMessageComposing(from string) {
g.sendXmppMessage(from, "", "", &xmpp.Composing{})
return
g.stopComposingTimer(from)
timer := time.AfterFunc(20*time.Second, func() {
@ -240,7 +318,7 @@ func (g *GatewayInfo) sendXmppMessage(from, subject, message string, chatState i
m.Active = &xmpp.Active{}
}
log.Printf("%sSend message %v", LogXmppInfo, m)
logger.Info.Printf("Send message %v", m)
g.XMPP_Out <- m
}
}

18
logger/logger.go Normal file
View File

@ -0,0 +1,18 @@
package logger
import (
"io"
"log"
)
var (
Info *log.Logger
Debug *log.Logger
Error *log.Logger
)
func Init(infoHandle io.Writer, warningHandle io.Writer, errorHandle io.Writer) {
Info = log.New(infoHandle, "INFO : ", log.Ldate|log.Ltime|log.Lshortfile)
Debug = log.New(warningHandle, "DEBUG : ", log.Ldate|log.Ltime|log.Lshortfile)
Error = log.New(errorHandle, "ERROR : ", log.Ldate|log.Ltime|log.Lshortfile)
}

38
main.go
View File

@ -1,51 +1,51 @@
package main
import (
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/configuration"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/database"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/gateway"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/logger"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/xmpp"
"github.com/jimlawless/cfg"
"log"
"os"
"os/signal"
"strings"
"syscall"
"time"
)
const (
Version = "v1.1-dev"
configurationFilePath = "xmpp4steam.cfg"
)
var (
mapConfig = make(map[string]string)
)
func init() {
logger.Init(os.Stdout, os.Stdout, os.Stderr)
configuration.Init()
logger.Info.Println("Running go-xmpp4steam " + Version)
xmpp.SoftVersion = Version
err := cfg.Load(configurationFilePath, mapConfig)
if err != nil {
log.Fatal("Failed to load configuration file.", err)
}
// XMPP config
xmpp.Addr = mapConfig["xmpp_server_address"] + ":" + mapConfig["xmpp_server_port"]
xmpp.JidStr = mapConfig["xmpp_hostname"]
xmpp.Secret = mapConfig["xmpp_secret"]
xmpp.Debug = mapConfig["xmpp_debug"] == "true"
xmpp.Addr = configuration.MapConfig["xmpp_server_address"] + ":" + configuration.MapConfig["xmpp_server_port"]
xmpp.JidStr = configuration.MapConfig["xmpp_hostname"]
xmpp.Secret = configuration.MapConfig["xmpp_secret"]
xmpp.Debug = configuration.MapConfig["xmpp_debug"] == "true"
if configuration.MapConfig["xmpp_group"] != "" {
gateway.XmppGroupUser = configuration.MapConfig["xmpp_group"]
}
gateway.XmppJidComponent = xmpp.JidStr
os.MkdirAll(gateway.SentryDirectory, 0700)
for _, admin := range strings.Split(configuration.MapConfig["xmpp_admins"], ";") {
xmpp.AdminUsers[admin] = true
}
}
func main() {
go xmpp.Run()
time.Sleep(1 * time.Second)
allDbUsers := database.GetAllLines()
for _, dbUser := range allDbUsers {
xmpp.AddNewUser(dbUser.Jid, dbUser.SteamLogin, dbUser.SteamPwd, dbUser.Debug)
}
go xmpp.Run()
sigchan := make(chan os.Signal, 1)
signal.Notify(sigchan, os.Interrupt)
@ -55,6 +55,6 @@ func main() {
xmpp.Disconnect()
log.Println("Exit main()")
logger.Info.Println("Exit main()")
time.Sleep(1 * time.Second)
}

View File

@ -3,9 +3,11 @@ package xmpp
import (
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/database"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/logger"
"log"
"fmt"
"strings"
"time"
)
const (
@ -14,6 +16,8 @@ const (
CommandDisconnectSteam = "disconnectSteam"
CommandRemoveRegistration = "removeRegistration"
CommandToggleDebugMode = "toggleDebugMode"
CommandUptimeMode = "uptime"
CommandMessageBroadcast = "messageBroadcast"
)
var (
@ -23,7 +27,7 @@ var (
)
func execDiscoCommand(iq *xmpp.Iq) {
log.Printf("%sAd-Hoc Command", LogInfo)
logger.Info.Printf("Ad-Hoc Command")
// Disco Ad-Hoc
reply := iq.Response(xmpp.IQTypeResult)
@ -49,6 +53,13 @@ func execDiscoCommand(iq *xmpp.Iq) {
discoItem.Item = append(discoItem.Item, *discoI)
discoI = &xmpp.DiscoItem{JID: jid.Domain, Node: CommandToggleDebugMode, Name: "Toggle debug mode"}
discoItem.Item = append(discoItem.Item, *discoI)
discoI = &xmpp.DiscoItem{JID: jid.Domain, Node: CommandUptimeMode, Name: "Uptime"}
discoItem.Item = append(discoItem.Item, *discoI)
}
if AdminUsers[jidBareFrom] {
discoI := &xmpp.DiscoItem{JID: jid.Domain, Node: CommandMessageBroadcast, Name: "Broadcast a message"}
discoItem.Item = append(discoItem.Item, *discoI)
}
}
@ -57,7 +68,7 @@ func execDiscoCommand(iq *xmpp.Iq) {
}
func execDisco(iq *xmpp.Iq) {
log.Printf("%sDisco Feature", LogInfo)
logger.Info.Printf("Disco Feature")
jidBareTo := strings.SplitN(iq.To, "/", 2)[0]
discoInfoReceived := &xmpp.DiscoItems{}
@ -69,14 +80,18 @@ func execDisco(iq *xmpp.Iq) {
discoInfo := &xmpp.DiscoInfo{}
if jidBareTo == jid.Domain {
// Only gateway
discoInfo.Identity = append(discoInfo.Identity, *identityGateway)
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NodeAdHocCommand})
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSJabberClient})
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSRegister})
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSPing})
} else {
// Only steam users
discoInfo.Identity = append(discoInfo.Identity, *identityClients)
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSChatStatesNotification})
}
// Both
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSDiscoInfo})
discoInfo.Feature = append(discoInfo.Feature, xmpp.DiscoFeature{Var: xmpp.NSDiscoItems})
@ -99,10 +114,11 @@ func execDisco(iq *xmpp.Iq) {
func execCommandAdHoc(iq *xmpp.Iq) {
adHoc := &xmpp.AdHocCommand{}
iq.PayloadDecode(adHoc)
jidBareFrom := strings.SplitN(iq.From, "/", 2)[0]
if adHoc.SessionID == "" && adHoc.Action == xmpp.ActionAdHocExecute {
// First step in the command
log.Printf("%sAd-Hoc command (Node : %s). First step.", LogInfo, adHoc.Node)
logger.Info.Printf("Ad-Hoc command (Node : %s). First step.", adHoc.Node)
reply := iq.Response(xmpp.IQTypeResult)
cmd := &xmpp.AdHocCommand{Node: adHoc.Node, Status: xmpp.StatusAdHocExecute, SessionID: xmpp.SessionID()}
@ -120,13 +136,13 @@ func execCommandAdHoc(iq *xmpp.Iq) {
cmd.XForm = *cmdXForm
} else if adHoc.Node == CommandDisconnectSteam {
// Command steam deconnection
cmd.Status = xmpp.StatusAdHocCompleted
cmdXForm := &xmpp.AdHocXForm{Type: xmpp.TypeAdHocResult, Title: "Force Steam deconnexion"}
cmd.XForm = *cmdXForm
note := &xmpp.AdHocNote{Type: xmpp.TypeAdHocNoteInfo}
jidBare := strings.SplitN(iq.From, "/", 2)[0]
g := MapGatewayInfo[jidBare]
g := MapGatewayInfo[jidBareFrom]
if g != nil {
g.Disconnect()
note.Value = "Send deconnexion on Steam network"
@ -135,13 +151,13 @@ func execCommandAdHoc(iq *xmpp.Iq) {
}
cmd.Note = *note
} else if adHoc.Node == CommandRemoveRegistration {
// Command remove registration
cmd.Status = xmpp.StatusAdHocCompleted
cmdXForm := &xmpp.AdHocXForm{Type: xmpp.TypeAdHocResult, Title: "Remove registration"}
cmd.XForm = *cmdXForm
note := &xmpp.AdHocNote{Type: xmpp.TypeAdHocNoteInfo}
jidBare := strings.SplitN(iq.From, "/", 2)[0]
if RemoveUser(jidBare) {
if RemoveUser(jidBareFrom) {
note.Value = "Remove registration success."
} else {
note.Value = "Failed to remove your registration."
@ -149,16 +165,16 @@ func execCommandAdHoc(iq *xmpp.Iq) {
cmd.Note = *note
} else if adHoc.Node == CommandToggleDebugMode {
// Command toggle debug mode
cmd.Status = xmpp.StatusAdHocCompleted
cmdXForm := &xmpp.AdHocXForm{Type: xmpp.TypeAdHocResult, Title: "Toggle debug mode"}
cmd.XForm = *cmdXForm
note := &xmpp.AdHocNote{Type: xmpp.TypeAdHocNoteInfo}
jidBare := strings.SplitN(iq.From, "/", 2)[0]
dbUser := database.GetLine(jidBare)
dbUser := database.GetLine(jidBareFrom)
if dbUser != nil {
dbUser.Debug = !dbUser.Debug
g := MapGatewayInfo[jidBare]
g := MapGatewayInfo[jidBareFrom]
ok := dbUser.UpdateLine()
if ok && g != nil {
g.DebugMessage = dbUser.Debug
@ -175,12 +191,29 @@ func execCommandAdHoc(iq *xmpp.Iq) {
}
cmd.Note = *note
} else if adHoc.Node == CommandUptimeMode {
// Command get uptime
cmd.Status = xmpp.StatusAdHocCompleted
cmdXForm := &xmpp.AdHocXForm{Type: xmpp.TypeAdHocResult, Title: "Uptime"}
cmd.XForm = *cmdXForm
deltaT := time.Since(startTime)
val := fmt.Sprintf("%dj %dh %dm %ds", int64(deltaT.Hours()/24), int64(deltaT.Hours())%24, int64(deltaT.Minutes())%60, int64(deltaT.Seconds())%60)
note := &xmpp.AdHocNote{Type: xmpp.TypeAdHocNoteInfo, Value: val}
cmd.Note = *note
} else if adHoc.Node == CommandMessageBroadcast && AdminUsers[jidBareFrom] {
// Command send broadcast message
cmdXForm := &xmpp.AdHocXForm{Type: xmpp.TypeAdHocForm, Title: "Broadcast a message", Instructions: "Message to broadcast to all user."}
field := &xmpp.AdHocField{Var: "message", Label: "Message", Type: xmpp.TypeAdHocFieldTextSingle}
cmdXForm.Fields = append(cmdXForm.Fields, *field)
cmd.XForm = *cmdXForm
}
reply.PayloadEncode(cmd)
comp.Out <- reply
} else if adHoc.Action == xmpp.ActionAdHocExecute || adHoc.Action == xmpp.ActionAdHocNext {
// Last step in the command
log.Printf("%sAd-Hoc command (Node : %s). Last step.", LogInfo, adHoc.Node)
logger.Info.Printf("Ad-Hoc command (Node : %s). Last step.", adHoc.Node)
reply := iq.Response(xmpp.IQTypeResult)
cmd := &xmpp.AdHocCommand{Node: adHoc.Node, Status: xmpp.StatusAdHocCompleted, SessionID: adHoc.SessionID}
@ -200,8 +233,7 @@ func execCommandAdHoc(iq *xmpp.Iq) {
}
if authCode != "" {
// Succeded
jidBare := strings.SplitN(iq.From, "/", 2)[0]
g := MapGatewayInfo[jidBare]
g := MapGatewayInfo[jidBareFrom]
if g != nil {
g.SetSteamAuthCode(authCode)
note.Value = "Command succeded !"
@ -233,13 +265,39 @@ func execCommandAdHoc(iq *xmpp.Iq) {
note.Value = "Failed because Steam login or Steam password is empty."
}
cmd.Note = *note
} else if adHoc.Node == CommandMessageBroadcast && AdminUsers[jidBareFrom] {
cmdXForm := &xmpp.AdHocXForm{Type: xmpp.TypeAdHocResult, Title: "Broadcast a message"}
cmd.XForm = *cmdXForm
note := &xmpp.AdHocNote{Type: xmpp.TypeAdHocNoteInfo}
// Command Auth Code
message := ""
fields := adHoc.XForm.Fields
for _, field := range fields {
if field.Var == "message" {
message = field.Value
break
}
}
if message != "" {
// Succeded
for userJID, _ := range MapGatewayInfo {
SendMessage(userJID, "", message)
}
note.Value = "Message sended to all registered users"
} else {
// Failed
note.Value = "There is no message to send"
}
cmd.Note = *note
}
reply.PayloadEncode(cmd)
comp.Out <- reply
} else if adHoc.Action == xmpp.ActionAdHocCancel {
// command canceled
log.Printf("%sAd-Hoc command (Node : %s). Command canceled.", LogInfo, adHoc.Node)
logger.Info.Printf("Ad-Hoc command (Node : %s). Command canceled.", adHoc.Node)
reply := iq.Response(xmpp.IQTypeResult)
cmd := &xmpp.AdHocCommand{Node: adHoc.Node, Status: xmpp.StatusAdHocCanceled, SessionID: adHoc.SessionID}
reply.PayloadEncode(cmd)
@ -272,9 +330,9 @@ func getUser(fields []xmpp.AdHocField, iq *xmpp.Iq) *database.DatabaseLine {
}
if steamLogin != "" {
// Succeded
jidBare := strings.SplitN(iq.From, "/", 2)[0]
jidBareFrom := strings.SplitN(iq.From, "/", 2)[0]
dbUser := new(database.DatabaseLine)
dbUser.Jid = jidBare
dbUser.Jid = jidBareFrom
dbUser.SteamLogin = steamLogin
dbUser.SteamPwd = steamPwd
dbUser.Debug = false

View File

@ -4,8 +4,9 @@ import (
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/database"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/gateway"
"git.kingpenguin.tk/chteufleur/go-xmpp4steam.git/logger"
"log"
"os"
"strings"
"time"
)
@ -14,10 +15,6 @@ const (
ActionConnexion = "action_xmpp_connexion"
ActionDeconnexion = "action_xmpp_deconnexion"
ActionMainMethodEnded = "action_xmpp_main_method_ended"
LogInfo = "\t[XMPP COMPONENT INFO]\t"
LogError = "\t[XMPP COMPONENT ERROR]\t"
LogDebug = "\t[XMPP COMPONENT DEBUG]\t"
)
var (
@ -36,21 +33,25 @@ var (
Debug = true
MapGatewayInfo = make(map[string]*gateway.GatewayInfo)
AdminUsers = make(map[string]bool)
startTime = time.Now()
)
func Run() {
log.Printf("%sRunning", LogInfo)
logger.Info.Printf("Running")
// Create stream and configure it as a component connection.
jid = must(xmpp.ParseJID(JidStr)).(xmpp.JID)
stream = must(xmpp.NewStream(Addr, &xmpp.StreamConfig{LogStanzas: Debug})).(*xmpp.Stream)
comp = must(xmpp.NewComponentXMPP(stream, jid, Secret)).(*xmpp.XMPP)
mainXMPP()
log.Printf("%sReach main method's end", LogInfo)
time.Sleep(1 * time.Second)
logger.Info.Printf("Reach XMPP Run method's end")
go Run()
}
func mainXMPP() {
defer logger.Info.Printf("Reach main method's end")
// Define xmpp out for all users
for _, u := range MapGatewayInfo {
u.XMPP_Out = comp.Out
@ -60,10 +61,14 @@ func mainXMPP() {
switch v := x.(type) {
case *xmpp.Presence:
jidBareFrom := strings.SplitN(v.From, "/", 2)[0]
jidBareTo := strings.SplitN(v.To, "/", 2)[0]
g := MapGatewayInfo[jidBareFrom]
if g != nil {
log.Printf("%sPresence transfered to %s", LogDebug, jidBareFrom)
g.ReceivedXMPP_Presence(v)
if jidBareTo == jid.Domain {
// Forward only if presence is for componant, in order to to not spam set presence on Steam
logger.Debug.Printf("Presence transfered to %s", jidBareFrom)
go g.ReceivedXMPP_Presence(v)
}
} else {
if v.Type != gateway.Type_error && v.Type != gateway.Type_probe {
SendPresence(gateway.Status_offline, gateway.Type_unavailable, jid.Domain, v.From, "Your are not registred", "")
@ -74,15 +79,24 @@ func mainXMPP() {
jidBareFrom := strings.SplitN(v.From, "/", 2)[0]
g := MapGatewayInfo[jidBareFrom]
if g != nil {
log.Printf("%sMessage transfered to %s", LogDebug, jidBareFrom)
g.ReceivedXMPP_Message(v)
logger.Debug.Printf("Message transfered to %s", jidBareFrom)
go g.ReceivedXMPP_Message(v)
} else {
SendMessage(v.From, "", "Your are not registred. If you want to register, please, send an Ad-Hoc command.")
}
case *xmpp.Iq:
jidBareFrom := strings.SplitN(v.From, "/", 2)[0]
jidBareTo := strings.SplitN(v.To, "/", 2)[0]
g := MapGatewayInfo[jidBareFrom]
iqTreated := false
if g != nil {
logger.Debug.Printf("Iq transfered to %s", jidBareFrom)
iqTreated = g.ReceivedXMPP_IQ(v)
}
if !iqTreated {
switch v.PayloadName().Space {
case xmpp.NSDiscoInfo:
execDisco(v)
@ -118,11 +132,46 @@ func mainXMPP() {
case xmpp.NSRegister:
if jidBareTo == jid.Domain {
reply := v.Response(xmpp.IQTypeResult)
jidBareFrom := strings.SplitN(v.From, "/", 2)[0]
treatmentNSRegister(v)
} else {
sendNotSupportedFeature(v)
}
case xmpp.NSRoster:
// Do nothing
case xmpp.NSPing:
if jidBareTo == jid.Domain {
treatmentNSPing(v)
} else {
sendNotSupportedFeature(v)
}
default:
sendNotSupportedFeature(v)
}
}
default:
logger.Debug.Printf("recv: %v", x)
}
}
}
func must(v interface{}, err error) interface{} {
if err != nil {
logger.Debug.Printf("%v", err)
os.Exit(1)
}
return v
}
func treatmentNSRegister(iq *xmpp.Iq) {
reply := iq.Response(xmpp.IQTypeResult)
jidBareFrom := strings.SplitN(iq.From, "/", 2)[0]
registerQuery := &xmpp.RegisterQuery{}
if v.Type == xmpp.IQTypeGet {
if iq.Type == xmpp.IQTypeGet {
registerQuery.Instructions = "Please provide your Steam login and password (Please, be aware that the given Steam account information will be saved into an un-encrypted SQLite database)."
dbUser := database.GetLine(jidBareFrom)
@ -136,13 +185,13 @@ func mainXMPP() {
}
reply.PayloadEncode(registerQuery)
} else if v.Type == xmpp.IQTypeSet {
v.PayloadDecode(registerQuery)
} else if iq.Type == xmpp.IQTypeSet {
iq.PayloadDecode(registerQuery)
if registerQuery.Remove != nil {
RemoveUser(jidBareFrom)
} else {
dbUser := getUser(registerQuery.XForm.Fields, v)
dbUser := getUser(registerQuery.XForm.Fields, iq)
if dbUser != nil {
if dbUser.UpdateUser() {
AddNewUser(dbUser.Jid, dbUser.SteamLogin, dbUser.SteamPwd, dbUser.Debug)
@ -157,41 +206,27 @@ func mainXMPP() {
}
}
comp.Out <- reply
} else {
sendNotSupportedFeature(v)
}
default:
sendNotSupportedFeature(v)
}
default:
log.Printf("%srecv: %v", LogDebug, x)
}
}
// Send deconnexion
SendPresence(gateway.Status_offline, gateway.Type_unavailable, "", "", "", "")
}
func must(v interface{}, err error) interface{} {
if err != nil {
log.Fatal(LogError, err)
}
return v
func treatmentNSPing(iq *xmpp.Iq) {
reply := iq.Response(xmpp.IQTypeResult)
comp.Out <- reply
}
func sendNotSupportedFeature(iq *xmpp.Iq) {
if iq.Type != xmpp.IQTypeError && iq.Type != xmpp.IQTypeResult {
reply := iq.Response(xmpp.IQTypeError)
reply.PayloadEncode(xmpp.NewError("cancel", xmpp.ErrorFeatureNotImplemented, ""))
comp.Out <- reply
}
}
func Disconnect() {
log.Printf("%sXMPP disconnect", LogInfo)
logger.Info.Printf("XMPP disconnect")
for _, u := range MapGatewayInfo {
u.SteamDisconnect()
}
comp.Close()
}
func SendPresence(status, tpye, from, to, message, nick string) {
@ -228,18 +263,18 @@ func SendMessage(to, subject, message string) {
m.Subject = subject
}
log.Printf("%sSenp message %v", LogInfo, m)
logger.Info.Printf("Senp message %v", m)
comp.Out <- m
}
func AddNewUser(jid, steamLogin, steamPwd string, debugMessage bool) {
log.Printf("%sAdd user %s to the map", LogInfo, jid)
func AddNewUser(jidUser, steamLogin, steamPwd string, debugMessage bool) {
logger.Info.Printf("Add user %s to the map (debug mode set to %v)", jidUser, debugMessage)
g := new(gateway.GatewayInfo)
g.SteamLogin = steamLogin
g.SteamPassword = steamPwd
g.XMPP_JID_Client = jid
g.SentryFile = gateway.SentryDirectory + jid
g.XMPP_JID_Client = jidUser
g.SentryFile = gateway.SentryDirectory + jidUser
g.FriendSteamId = make(map[string]*gateway.StatusSteamFriend)
g.Deleting = false
@ -247,9 +282,20 @@ func AddNewUser(jid, steamLogin, steamPwd string, debugMessage bool) {
g.XMPP_Connected_Client = make(map[string]bool)
g.XMPP_Composing_Timers = make(map[string]*time.Timer)
g.DebugMessage = debugMessage
g.XMPP_IQ_RemoteRoster_Request = make(map[string]string)
g.AllowEditRoster = false
MapGatewayInfo[jid] = g
MapGatewayInfo[jidUser] = g
go g.Run()
logger.Info.Printf("Check roster edition by asking with remote roster manager namespace")
// Ask if remote roster is allow
iqId := gateway.NextIqId()
g.XMPP_IQ_RemoteRoster_Request[iqId] = gateway.RemoteRosterRequestPermission
iq := xmpp.Iq{To: jidUser, From: jid.Domain, Type: xmpp.IQTypeGet, Id: iqId}
// iq.PayloadEncode(&xmpp.RosterQuery{})
iq.PayloadEncode(&xmpp.RemoteRosterManagerQuery{Reason: "Manage contacts in the Steam contact list", Type: xmpp.RemoteRosterManagerTypeRequest})
comp.Out <- iq
}
func RemoveUser(jidBare string) bool {