1 #include "useractions.h"
2 
3 #include <wx/intl.h>
4 #include <wx/colour.h>
5 #include "settings.h"
6 #include "helper/slconfig.h"
7 #include <cmath>
8 #include "utils/customdialogs.h"
9 
10 #include "mainwindow.h"
11 #include "mainchattab.h"
12 #include "hosting/mainjoinbattletab.h"
13 #include "hosting/battleroomtab.h"
14 #include "battlelist/battlelisttab.h"
15 #include "chatpanel.h"
16 #include <options/mainoptionstab.h>
17 #include <options/groupoptionspanel.h>
18 #include <lslutils/globalsmanager.h>
19 
20 const wxColour defaultHLcolor ( 255, 0, 0 );
21 
useractions()22 UserActions& useractions()
23 {
24     static LSL::Util::LineInfo<UserActions> m( AT );
25     static LSL::Util::GlobalObjectHolder<UserActions, LSL::Util::LineInfo<UserActions> > m_useractions( m );
26     return m_useractions;
27 }
28 
UserActions()29 UserActions::UserActions()
30 {
31     Init();
32 }
33 
~UserActions()34 UserActions::~UserActions()
35 {
36 
37 }
38 
DoActionOnUser(const UserActions::ActionType action,const wxString & name)39 bool UserActions::DoActionOnUser( const UserActions::ActionType action, const wxString& name )
40 {
41     // preventing action on oneself wasn't the best idea, login gets disabled
42     //if ( m_knownUsers.Index( name ) == -1 || ui().IsThisMe(name) || action == ActNone )
43 
44     if ( m_knownUsers.Index( name ) == -1 || action == ActNone )
45         return false;
46     else
47         return ( m_actionsGroups.find( action ) != m_actionsGroups.end() && m_actionsPeople[action].Index( name ) != -1 );
48 
49     return false;
50 }
51 
Init()52 void UserActions::Init()
53 {
54 	m_actionNames.clear();
55 	m_actionNames.push_back(_("none"));
56 	m_actionNames.push_back(_("highlight"));
57 	m_actionNames.push_back(_("notify login/out"));
58 	m_actionNames.push_back(_("ignore chat"));
59 	m_actionNames.push_back(_("ignore pm"));
60 	m_actionNames.push_back(_("autokick"));
61 	m_actionNames.push_back( _("notify hosted battle"));
62 	m_actionNames.push_back(_("notify status change"));
63 
64 	m_configActionNames.clear();
65 	m_configActionNames.push_back(_T("none"));
66 	m_configActionNames.push_back(_T("highlight"));
67 	m_configActionNames.push_back(_T("notify_login"));
68 	m_configActionNames.push_back(_T("ignore_chat"));
69 	m_configActionNames.push_back(_T("ignore_pm"));
70 	m_configActionNames.push_back(_T("autokick"));
71 	m_configActionNames.push_back(_T("notify_hosted"));
72 	m_configActionNames.push_back(_T("notify_status"));
73 
74 	m_actionTooltips.clear();
75 	m_actionTooltips.push_back(_("no action at all"));
76 	m_actionTooltips.push_back(_("highlight user in nick list and battles he participates in"));
77 	m_actionTooltips.push_back(_("popup a message box when user logs in/out from  the server"));
78 	m_actionTooltips.push_back(_("you won't see message by these users in normal channels"));
79 	m_actionTooltips.push_back(_("ignore private messages of these users, no pm window will open if any of these try to contact you privately"));
80 	m_actionTooltips.push_back(_("automatically kick users from battles hosted by yourself"));
81 	m_actionTooltips.push_back(_("popup a message box when user hosts a new battle"));
82 	m_actionTooltips.push_back(_("popup a message box when user changes away status"));
83 
84 	// setup if empty
85 	if (!cfg().Exists(_T( "/Groups"))) {
86 		 AddGroup( _("Default") );
87 		 AddGroup( _("Ignore PM") );
88 		 ChangeAction( _("Ignore PM"), UserActions::ActIgnorePM );
89 		 AddGroup( _("Ignore chat") );
90 		 ChangeAction( _("Ignore chat"), UserActions::ActIgnoreChat );
91 		 AddGroup( _("Battle Autokick") );
92 		 ChangeAction( _("Battle Autokick"), UserActions::ActAutokick );
93 		 AddGroup( _("Friends") );
94 		 ChangeAction( _("Friends"), UserActions::ActNotifBattle );
95 		 ChangeAction( _("Friends"), UserActions::ActHighlight );
96 		 ChangeAction( _("Friends"), UserActions::ActNotifLogin );
97 		 // TODO select better color
98 		 SetGroupColor( _("Friends"), wxColour( 0, 0, 255 ) );
99 	}
100 
101 
102 	// read
103     m_groupNames = GetGroups();
104     m_groupMap.clear();
105     m_groupActions.clear();
106     m_actionsGroups.clear();
107     m_actionsPeople.clear();
108     m_knownUsers.Clear();
109     for ( unsigned int i = 0; i < m_groupNames.GetCount(); ++i)
110     {
111         wxString name = m_groupNames[i];
112         m_groupMap[name] = GetPeopleList( name );
113         for ( unsigned int k = 0; k < m_groupMap[name].GetCount(); ++k)
114         {
115             wxString user = m_groupMap[name][k];
116             m_knownUsers.Add( user );
117             m_peopleGroup[ user ] = name;
118         }
119         m_groupActions[name] = GetGroupActions( name );
120     }
121     for ( int i = 0; i < m_actionNames.size(); ++i)
122     {
123         UserActions::ActionType cur = (UserActions::ActionType) (int) std::pow( 2.0, i);
124         wxArrayString tmp;
125         for ( unsigned int j = 0; j < m_groupNames.GetCount(); ++j)
126         {
127             wxString name = m_groupNames[j];
128             if ( ( m_groupActions[name] & cur ) != 0 )
129             {
130                 tmp.Add( name );
131                 for ( unsigned int k = 0; k < m_groupMap[name].GetCount(); ++k)
132                 {
133                     m_actionsPeople[cur].Add( (m_groupMap[name])[k] );
134                 }
135             }
136         }
137         tmp.Sort();
138         m_actionsGroups[cur] = tmp;
139     }
140     m_actionsGroups[ActNone] = m_groupNames;
141     m_groupNames.Sort();
142     m_knownUsers.Sort();
143 }
144 
UpdateUI()145 void UserActions::UpdateUI()
146 {
147     try
148     {
149       ui().mw().GetBattleListTab().UpdateHighlights();
150     } catch(...){}
151 
152     try
153     {
154       ui().mw().GetChatTab().UpdateNicklistHighlights();
155     } catch(...){}
156 
157     try
158     {
159       ui().mw().GetJoinTab().GetBattleRoomTab().UpdateHighlights();
160     } catch(...){}
161 }
162 
GetGroupNames() const163 wxArrayString UserActions::GetGroupNames() const
164 {
165     return m_groupNames;
166 }
167 
AddUserToGroup(const wxString & group,const wxString & name)168 void UserActions::AddUserToGroup( const wxString& group, const wxString& name )
169 {
170     if ( IsKnown( name , false ) || ui().IsThisMe( name ) )
171         return;
172     m_groupMap[group].Add(name);
173     SetPeopleList( m_groupMap[group], group );
174     Init();
175     UpdateUI();
176 }
177 
DeleteGroup(const wxString & group)178 void UserActions::DeleteGroup(const wxString& group )
179 {
180 	if ( cfg().Exists( _T( "/Groups/" ) + group ) ) {
181 		cfg().DeleteGroup( _T( "/Groups/" ) + group );
182 	}
183 	Init();
184 	UpdateUI();
185 }
186 
GetPeopleList(const wxString & group) const187 wxArrayString UserActions::GetPeopleList( const wxString& group  ) const
188 {
189 	wxArrayString list;
190 	slConfig::PathGuard pathGuard ( &cfg(), _T( "/Groups/" ) + group + _T( "/Members/" ) );
191 	unsigned int friendsCount  = cfg().GetNumberOfEntries( false );
192 	for ( unsigned int i = 0; i < friendsCount ; i++ )
193 	{
194 		wxString ToAdd;
195 		if ( cfg().Read( _T( "/Groups/" ) + group + _T( "/Members/" ) +  TowxString( i ), &ToAdd ) ) list.Add( ToAdd );
196 	}
197 	return list;
198 }
199 
200 
AddGroup(const wxString & group)201 void UserActions::AddGroup(const wxString& group )
202 {
203 	if ( !cfg().Exists( _T( "/Groups/" ) + group ) ) {
204 		cfg().Write( _T( "/Groups/" ) , group );
205 		//set defaults
206 		SetGroupActions( group, UserActions::ActNone );
207 		SetGroupHLColor( defaultHLcolor, group );
208 	}
209 	Init();
210 	UpdateUI();
211 }
212 
213 
ChangeAction(const wxString & group,const ActionType action,bool add)214 void UserActions::ChangeAction( const wxString& group, const ActionType action, bool add )
215 {
216     ActionType old = m_groupActions[group];
217     old = (ActionType) ( add ? (old | action) : (old & ~action ) );
218     SetGroupActions( group, old );
219     Init();
220     UpdateUI();
221 }
222 
SetGroupActions(const wxString & group,ActionType action) const223 void UserActions::SetGroupActions( const wxString& group, ActionType action ) const
224 {
225 	wxString key = _T( "/Groups/" ) + group + _T( "/Opts/ActionsList" );
226 	cfg().DeleteGroup( key );
227 	key += _T( "/" );
228 	unsigned int tmp = action & ( ( UserActions::ActLast << 1 ) - 1 );
229 	for(auto config: m_configActionNames) {
230 		if ( tmp&1 ) cfg().Write( key + config, true );
231 		tmp >>= 1;
232 	}
233 }
234 
GetGroupActions(const wxString & group) const235 UserActions::ActionType UserActions::GetGroupActions( const wxString& group ) const
236 {
237 	wxString key = _T( "/Groups/" ) + group + _T( "/Opts/Actions" );
238 	if ( cfg().HasEntry( key ) )// Backward compatibility.
239 	{
240 		wxLogMessage( _T( "loading deprecated group actions and updating config" ) );
241 		UserActions::ActionType action = ( UserActions::ActionType )cfg().Read( key, ( long )UserActions::ActNone ) ;
242 		cfg().DeleteEntry( key );
243 
244 		SetGroupActions( group, action );
245 
246 		return action;
247 	}
248 	key = _T( "/Groups/" ) + group + _T( "/Opts/ActionsList" );
249 	if ( !cfg().Exists( key ) ) return UserActions::ActNone;
250 	key += _T( "/" );
251 	int mask = 1;
252 	int result = 0;
253 	for(auto config: m_configActionNames) {
254 		if ( cfg().Read( key + config, 0l ) ) {
255 			result |= mask;
256 		}
257 		mask <<= 1;
258 	}
259 	if ( result == 0 ) return UserActions::ActNone;
260 	return ( UserActions::ActionType )result;
261 }
262 
GetGroupAction(const wxString & group) const263 UserActions::ActionType UserActions::GetGroupAction( const wxString& group ) const
264 {
265 	const GroupActionMap::const_iterator res = m_groupActions.find(group);
266     return res->second;
267 }
268 
GetGroupOfUser(const wxString & user) const269 wxString UserActions::GetGroupOfUser( const wxString& user ) const
270 {
271 	const PeopleGroupMap::const_iterator res = m_peopleGroup.find(user);
272     return res->second;
273 }
274 
SetGroupColor(const wxString & group,const wxColour & color)275 void UserActions::SetGroupColor( const wxString& group, const wxColour& color )
276 {
277     SetGroupHLColor( color, group );
278     Init();
279     UpdateUI();
280 }
281 
GetGroupHLColor(const wxString & group) const282 wxColour UserActions::GetGroupHLColor( const wxString& group  ) const
283 {
284 	return wxColour( cfg().Read( _T( "/Groups/" ) + group + _T( "/Opts/HLColor" ) , _T( "#64648C" ) ) );
285 }
286 
SetGroupHLColor(const wxColour & color,const wxString & group)287 void UserActions::SetGroupHLColor( const wxColour& color, const wxString& group )
288 {
289 	cfg().Write( _T( "/Groups/" ) + group + _T( "/Opts/HLColor" ), color.GetAsString( wxC2S_HTML_SYNTAX ) );
290 }
291 
GetGroups()292 wxArrayString UserActions::GetGroups( )
293 {
294 	return cfg().GetGroupList( _T( "/Groups/" ) );
295 }
296 
297 
GetGroupColor(const wxString & group) const298 wxColour UserActions::GetGroupColor( const wxString& group ) const
299 {
300     return GetGroupHLColor( group );
301 }
302 
IsKnown(const wxString & name,bool outputWarning) const303 bool UserActions::IsKnown( const wxString& name, bool outputWarning ) const
304 {
305     bool ret = m_knownUsers.Index( name ) != -1;
306     if ( outputWarning ){
307         customMessageBoxNoModal( SL_MAIN_ICON, _("To prevent logical inconsistencies, adding a user to more than one group is not allowed"),
308            _("Cannot add user to group") );
309     }
310 
311     return ret;
312 }
313 
RemoveUser(const wxString & name)314 void UserActions::RemoveUser(const wxString& name )
315 {
316     wxString group = m_peopleGroup[name];
317     m_groupMap[group].Remove(name);
318     SetPeopleList( m_groupMap[group], group );
319     Init();
320     UpdateUI();
321 }
322 
SetPeopleList(const wxArrayString & friends,const wxString & group)323 void UserActions::SetPeopleList( const wxArrayString& friends, const wxString& group  )
324 {
325 	unsigned int friendsCount = friends.GetCount();
326 	cfg().DeleteGroup( _T( "/Groups/" ) + group + _T( "/Members/" ) );
327 	for ( unsigned int i = 0; i < friendsCount ; i++ )
328 	{
329 		cfg().Write( _T( "/Groups/" ) + group + _T( "/Members/" ) + TowxString( i ), friends[i] );
330 	}
331 }
332