mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-13 17:43:59 +02:00
Hopefully really fix the twitter issue
This commit is contained in:
@@ -70,12 +70,12 @@ TwitterPlugin::TwitterPlugin( const QString& pluginId )
|
|||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
if ( !Database::instance() || Database::instance()->dbid() != twitterSavedDbid() )
|
if ( Database::instance()->dbid() != twitterSavedDbid() )
|
||||||
{
|
{
|
||||||
setTwitterCachedDirectMessagesSinceId( 0 );
|
setTwitterCachedDirectMessagesSinceId( 0 );
|
||||||
setTwitterCachedFriendsSinceId( 0 );
|
setTwitterCachedFriendsSinceId( 0 );
|
||||||
setTwitterCachedMentionsSinceId( 0 );
|
setTwitterCachedMentionsSinceId( 0 );
|
||||||
setTwitterCachedPeers( QHash< QString, QVariant >() );
|
setTwitterCachedPeers( QVariantHash() );
|
||||||
}
|
}
|
||||||
|
|
||||||
setTwitterSavedDbid( Database::instance()->dbid() );
|
setTwitterSavedDbid( Database::instance()->dbid() );
|
||||||
@@ -90,9 +90,9 @@ TwitterPlugin::TwitterPlugin( const QString& pluginId )
|
|||||||
|
|
||||||
m_configWidget = QWeakPointer< TwitterConfigWidget >( new TwitterConfigWidget( this, 0 ) );
|
m_configWidget = QWeakPointer< TwitterConfigWidget >( new TwitterConfigWidget( this, 0 ) );
|
||||||
connect( m_configWidget.data(), SIGNAL( twitterAuthed( bool ) ), SLOT( configDialogAuthedSignalSlot( bool ) ) );
|
connect( m_configWidget.data(), SIGNAL( twitterAuthed( bool ) ), SLOT( configDialogAuthedSignalSlot( bool ) ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TwitterPlugin::configDialogAuthedSignalSlot( bool authed )
|
TwitterPlugin::configDialogAuthedSignalSlot( bool authed )
|
||||||
{
|
{
|
||||||
@@ -169,10 +169,16 @@ TwitterPlugin::connectPlugin( bool startup )
|
|||||||
qStableSort( peerlist.begin(), peerlist.end() );
|
qStableSort( peerlist.begin(), peerlist.end() );
|
||||||
foreach( QString screenName, peerlist )
|
foreach( QString screenName, peerlist )
|
||||||
{
|
{
|
||||||
QHash< QString, QVariant > cachedPeer = m_cachedPeers[screenName].toHash();
|
QVariantHash cachedPeer = m_cachedPeers[screenName].toHash();
|
||||||
|
if ( cachedPeer.contains( "onod" ) && cachedPeer["onod"] != Database::instance()->dbid() )
|
||||||
|
{
|
||||||
|
m_cachedPeers.remove( screenName );
|
||||||
|
syncConfig();
|
||||||
|
}
|
||||||
foreach( QString prop, cachedPeer.keys() )
|
foreach( QString prop, cachedPeer.keys() )
|
||||||
qDebug() << "TwitterPlugin : " << screenName << ", key " << prop << ", value " << ( cachedPeer[prop].canConvert< QString >() ? cachedPeer[prop].toString() : QString::number( cachedPeer[prop].toInt() ) );
|
qDebug() << "TwitterPlugin : " << screenName << ", key " << prop << ", value " << ( cachedPeer[prop].canConvert< QString >() ? cachedPeer[prop].toString() : QString::number( cachedPeer[prop].toInt() ) );
|
||||||
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&cachedPeer ) );
|
|
||||||
|
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, cachedPeer ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( twitterOAuthToken().isEmpty() || twitterOAuthTokenSecret().isEmpty() )
|
if ( twitterOAuthToken().isEmpty() || twitterOAuthTokenSecret().isEmpty() )
|
||||||
@@ -233,6 +239,7 @@ TwitterPlugin::disconnectPlugin()
|
|||||||
if( !m_twitterAuth.isNull() )
|
if( !m_twitterAuth.isNull() )
|
||||||
delete m_twitterAuth.data();
|
delete m_twitterAuth.data();
|
||||||
|
|
||||||
|
syncConfig();
|
||||||
m_cachedPeers.empty();
|
m_cachedPeers.empty();
|
||||||
m_state = Disconnected;
|
m_state = Disconnected;
|
||||||
emit stateChanged( m_state );
|
emit stateChanged( m_state );
|
||||||
@@ -347,12 +354,13 @@ TwitterPlugin::connectTimerFired()
|
|||||||
foreach( QString screenName, peerlist )
|
foreach( QString screenName, peerlist )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << " checking peer " << screenName;
|
qDebug() << Q_FUNC_INFO << " checking peer " << screenName;
|
||||||
QHash< QString, QVariant > peerData = m_cachedPeers[screenName].toHash();
|
QVariantHash peerData = m_cachedPeers[screenName].toHash();
|
||||||
|
|
||||||
if ( Servent::instance()->connectedToSession( peerData["node"].toString() ) )
|
if ( Servent::instance()->connectedToSession( peerData["node"].toString() ) )
|
||||||
{
|
{
|
||||||
peerData["lastseen"] = QDateTime::currentMSecsSinceEpoch();
|
peerData["lastseen"] = QDateTime::currentMSecsSinceEpoch();
|
||||||
m_cachedPeers[screenName] = peerData;
|
m_cachedPeers[screenName] = peerData;
|
||||||
|
syncConfig();
|
||||||
qDebug() << Q_FUNC_INFO << " already connected";
|
qDebug() << Q_FUNC_INFO << " already connected";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -361,6 +369,7 @@ TwitterPlugin::connectTimerFired()
|
|||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << " aging peer " << screenName << " out of cache";
|
qDebug() << Q_FUNC_INFO << " aging peer " << screenName << " out of cache";
|
||||||
m_cachedPeers.remove( screenName );
|
m_cachedPeers.remove( screenName );
|
||||||
|
syncConfig();
|
||||||
m_cachedAvatars.remove( screenName );
|
m_cachedAvatars.remove( screenName );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -371,7 +380,7 @@ TwitterPlugin::connectTimerFired()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&peerData ) );
|
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, peerData ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,21 +414,23 @@ TwitterPlugin::parseGotTomahawk( const QRegExp ®ex, const QString &screenName
|
|||||||
else
|
else
|
||||||
qDebug() << "TwitterPlugin parsed node " << node << " out of the tweet";
|
qDebug() << "TwitterPlugin parsed node " << node << " out of the tweet";
|
||||||
|
|
||||||
if ( screenName == myScreenName && node == Database::instance()->dbid() )
|
if ( node == Database::instance()->dbid() )
|
||||||
{
|
{
|
||||||
qDebug() << "My screen name and my dbid found; ignoring";
|
qDebug() << "My dbid found; ignoring";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash< QString, QVariant > peerData;
|
QVariantHash peerData;
|
||||||
if( m_cachedPeers.contains( screenName ) )
|
if( m_cachedPeers.contains( screenName ) )
|
||||||
{
|
{
|
||||||
peerData = m_cachedPeers[screenName].toHash();
|
peerData = m_cachedPeers[screenName].toHash();
|
||||||
//force a re-send of info but no need to re-register
|
//force a re-send of info but no need to re-register
|
||||||
peerData["resend"] = QVariant::fromValue< bool >( true );
|
peerData["resend"] = QVariant::fromValue< bool >( true );
|
||||||
|
if ( peerData["node"].toString() != node )
|
||||||
|
peerData["rekey"] = QVariant::fromValue< bool >( true );
|
||||||
}
|
}
|
||||||
peerData["node"] = QVariant::fromValue< QString >( node );
|
peerData["node"] = QVariant::fromValue< QString >( node );
|
||||||
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&peerData ) );
|
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, peerData ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -578,9 +589,9 @@ TwitterPlugin::directMessages( const QList< QTweetDMStatus > &messages )
|
|||||||
qDebug() << "TwitterPlugin found a peerstart message from " << status.senderScreenName() << " with host " << host << " and port " << port << " and pkey " << pkey << " and node " << splitNode[0] << " destined for node " << splitNode[1];
|
qDebug() << "TwitterPlugin found a peerstart message from " << status.senderScreenName() << " with host " << host << " and port " << port << " and pkey " << pkey << " and node " << splitNode[0] << " destined for node " << splitNode[1];
|
||||||
|
|
||||||
|
|
||||||
QHash< QString, QVariant > peerData = ( m_cachedPeers.contains( status.senderScreenName() ) ) ?
|
QVariantHash peerData = ( m_cachedPeers.contains( status.senderScreenName() ) ) ?
|
||||||
m_cachedPeers[status.senderScreenName()].toHash() :
|
m_cachedPeers[status.senderScreenName()].toHash() :
|
||||||
QHash< QString, QVariant >();
|
QVariantHash();
|
||||||
|
|
||||||
peerData["host"] = QVariant::fromValue< QString >( host );
|
peerData["host"] = QVariant::fromValue< QString >( host );
|
||||||
peerData["port"] = QVariant::fromValue< int >( port );
|
peerData["port"] = QVariant::fromValue< int >( port );
|
||||||
@@ -588,7 +599,7 @@ TwitterPlugin::directMessages( const QList< QTweetDMStatus > &messages )
|
|||||||
peerData["node"] = QVariant::fromValue< QString >( splitNode[0] );
|
peerData["node"] = QVariant::fromValue< QString >( splitNode[0] );
|
||||||
peerData["dirty"] = QVariant::fromValue< bool >( true );
|
peerData["dirty"] = QVariant::fromValue< bool >( true );
|
||||||
|
|
||||||
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, status.senderScreenName() ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&peerData ) );
|
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, status.senderScreenName() ), Q_ARG( QVariantHash, peerData ) );
|
||||||
|
|
||||||
if ( Database::instance()->dbid().startsWith( splitNode[1] ) )
|
if ( Database::instance()->dbid().startsWith( splitNode[1] ) )
|
||||||
{
|
{
|
||||||
@@ -603,7 +614,7 @@ TwitterPlugin::directMessages( const QList< QTweetDMStatus > &messages )
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TwitterPlugin::registerOffer( const QString &screenName, const QHash< QString, QVariant > &peerData )
|
TwitterPlugin::registerOffer( const QString &screenName, const QVariantHash &peerData )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
@@ -616,7 +627,7 @@ TwitterPlugin::registerOffer( const QString &screenName, const QHash< QString, Q
|
|||||||
if ( !m_cachedAvatars.contains( screenName ) )
|
if ( !m_cachedAvatars.contains( screenName ) )
|
||||||
QMetaObject::invokeMethod( this, "fetchAvatar", Q_ARG( QString, screenName ) );
|
QMetaObject::invokeMethod( this, "fetchAvatar", Q_ARG( QString, screenName ) );
|
||||||
|
|
||||||
QHash< QString, QVariant > _peerData( peerData );
|
QVariantHash _peerData( peerData );
|
||||||
|
|
||||||
if ( _peerData.contains( "dirty" ) )
|
if ( _peerData.contains( "dirty" ) )
|
||||||
{
|
{
|
||||||
@@ -644,8 +655,11 @@ TwitterPlugin::registerOffer( const QString &screenName, const QHash< QString, Q
|
|||||||
needToSend = true;
|
needToSend = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !m_keyCache.contains( _peerData["okey"].toString() ) )
|
if ( _peerData.contains( "rekey" ) || !m_keyCache.contains( _peerData["okey"].toString() ) )
|
||||||
|
{
|
||||||
|
_peerData.remove( "rekey" );
|
||||||
needToAddToCache = true;
|
needToAddToCache = true;
|
||||||
|
}
|
||||||
|
|
||||||
if ( !_peerData.contains( "ohst" ) || !_peerData.contains( "oprt" ) ||
|
if ( !_peerData.contains( "ohst" ) || !_peerData.contains( "oprt" ) ||
|
||||||
_peerData["ohst"].toString() != Servent::instance()->externalAddress() ||
|
_peerData["ohst"].toString() != Servent::instance()->externalAddress() ||
|
||||||
@@ -666,7 +680,7 @@ TwitterPlugin::registerOffer( const QString &screenName, const QHash< QString, Q
|
|||||||
_peerData["oprt"] = QVariant::fromValue< int >( Servent::instance()->externalPort() );
|
_peerData["oprt"] = QVariant::fromValue< int >( Servent::instance()->externalPort() );
|
||||||
peersChanged = true;
|
peersChanged = true;
|
||||||
if( !Servent::instance()->externalAddress().isEmpty() && !Servent::instance()->externalPort() == 0 )
|
if( !Servent::instance()->externalAddress().isEmpty() && !Servent::instance()->externalPort() == 0 )
|
||||||
QMetaObject::invokeMethod( this, "sendOffer", Q_ARG( QString, screenName ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&_peerData ) );
|
QMetaObject::invokeMethod( this, "sendOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, _peerData ) );
|
||||||
else
|
else
|
||||||
qDebug() << "TwitterPlugin did not send offer because external address is " << Servent::instance()->externalAddress() << " and external port is " << Servent::instance()->externalPort();
|
qDebug() << "TwitterPlugin did not send offer because external address is " << Servent::instance()->externalAddress() << " and external port is " << Servent::instance()->externalPort();
|
||||||
}
|
}
|
||||||
@@ -674,17 +688,17 @@ TwitterPlugin::registerOffer( const QString &screenName, const QHash< QString, Q
|
|||||||
if ( peersChanged )
|
if ( peersChanged )
|
||||||
{
|
{
|
||||||
_peerData["lastseen"] = QString::number( QDateTime::currentMSecsSinceEpoch() );
|
_peerData["lastseen"] = QString::number( QDateTime::currentMSecsSinceEpoch() );
|
||||||
m_cachedPeers[screenName] = QVariant::fromValue< QHash< QString, QVariant > >( _peerData );
|
m_cachedPeers[screenName] = QVariant::fromValue< QVariantHash >( _peerData );
|
||||||
setTwitterCachedPeers( m_cachedPeers );
|
syncConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( m_state == Connected && _peerData.contains( "host" ) && _peerData.contains( "port" ) && _peerData.contains( "pkey" ) )
|
if ( m_state == Connected && _peerData.contains( "host" ) && _peerData.contains( "port" ) && _peerData.contains( "pkey" ) )
|
||||||
QMetaObject::invokeMethod( this, "makeConnection", Q_ARG( QString, screenName ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&_peerData ) );
|
QMetaObject::invokeMethod( this, "makeConnection", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, _peerData ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TwitterPlugin::sendOffer( const QString &screenName, const QHash< QString, QVariant > &peerData )
|
TwitterPlugin::sendOffer( const QString &screenName, const QVariantHash &peerData )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
QString offerString = QString( "TOMAHAWKPEER:Host=%1:Port=%2:Node=%3*%4:PKey=%5" ).arg( peerData["ohst"].toString() )
|
QString offerString = QString( "TOMAHAWKPEER:Host=%1:Port=%2:Node=%3*%4:PKey=%5" ).arg( peerData["ohst"].toString() )
|
||||||
@@ -698,7 +712,7 @@ TwitterPlugin::sendOffer( const QString &screenName, const QHash< QString, QVari
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TwitterPlugin::makeConnection( const QString &screenName, const QHash< QString, QVariant > &peerData )
|
TwitterPlugin::makeConnection( const QString &screenName, const QVariantHash &peerData )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
if ( !peerData.contains( "host" ) || !peerData.contains( "port" ) || !peerData.contains( "pkey" ) || !peerData.contains( "node" ) ||
|
if ( !peerData.contains( "host" ) || !peerData.contains( "port" ) || !peerData.contains( "pkey" ) || !peerData.contains( "node" ) ||
|
||||||
@@ -1020,7 +1034,7 @@ TwitterPlugin::setTwitterCachedDirectMessagesSinceId( qint64 cachedId )
|
|||||||
TomahawkSettings::instance()->setValue( pluginId() + "/cacheddirectmessagessinceid", cachedId );
|
TomahawkSettings::instance()->setValue( pluginId() + "/cacheddirectmessagessinceid", cachedId );
|
||||||
}
|
}
|
||||||
|
|
||||||
QHash<QString, QVariant>
|
QVariantHash
|
||||||
TwitterPlugin::twitterCachedPeers() const
|
TwitterPlugin::twitterCachedPeers() const
|
||||||
{
|
{
|
||||||
TomahawkSettings* s = TomahawkSettings::instance();
|
TomahawkSettings* s = TomahawkSettings::instance();
|
||||||
@@ -1045,13 +1059,14 @@ TwitterPlugin::twitterCachedPeers() const
|
|||||||
}
|
}
|
||||||
s->endGroup();
|
s->endGroup();
|
||||||
|
|
||||||
return s->value( pluginId() + "/cachedpeers", QHash<QString, QVariant>() ).toHash();
|
return s->value( pluginId() + "/cachedpeers", QVariantHash() ).toHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TwitterPlugin::setTwitterCachedPeers( const QHash<QString, QVariant> &cachedPeers )
|
TwitterPlugin::setTwitterCachedPeers( const QVariantHash &cachedPeers )
|
||||||
{
|
{
|
||||||
TomahawkSettings::instance()->setValue( pluginId() + "/cachedpeers", cachedPeers );
|
TomahawkSettings::instance()->setValue( pluginId() + "/cachedpeers", cachedPeers );
|
||||||
|
TomahawkSettings::instance()->sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_EXPORT_PLUGIN2( sipfactory, TwitterFactory )
|
Q_EXPORT_PLUGIN2( sipfactory, TwitterFactory )
|
||||||
|
@@ -108,14 +108,15 @@ private slots:
|
|||||||
void directMessagePosted( const QTweetDMStatus &message );
|
void directMessagePosted( const QTweetDMStatus &message );
|
||||||
void directMessagePostError( QTweetNetBase::ErrorCode errorCode, const QString &message );
|
void directMessagePostError( QTweetNetBase::ErrorCode errorCode, const QString &message );
|
||||||
void directMessageDestroyed( const QTweetDMStatus &message );
|
void directMessageDestroyed( const QTweetDMStatus &message );
|
||||||
void registerOffer( const QString &screenName, const QHash< QString, QVariant > &peerdata );
|
void registerOffer( const QString &screenName, const QVariantHash &peerdata );
|
||||||
void sendOffer( const QString &screenName, const QHash< QString, QVariant > &peerdata );
|
void sendOffer( const QString &screenName, const QVariantHash &peerdata );
|
||||||
void makeConnection( const QString &screenName, const QHash< QString, QVariant > &peerdata );
|
void makeConnection( const QString &screenName, const QVariantHash &peerdata );
|
||||||
void fetchAvatar( const QString &screenName );
|
void fetchAvatar( const QString &screenName );
|
||||||
void avatarUserDataSlot( const QTweetUser &user );
|
void avatarUserDataSlot( const QTweetUser &user );
|
||||||
void profilePicReply();
|
void profilePicReply();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
inline void syncConfig() { setTwitterCachedPeers( m_cachedPeers ); }
|
||||||
bool refreshTwitterAuth();
|
bool refreshTwitterAuth();
|
||||||
void parseGotTomahawk( const QRegExp ®ex, const QString &screenName, const QString &text );
|
void parseGotTomahawk( const QRegExp ®ex, const QString &screenName, const QString &text );
|
||||||
// handle per-plugin config
|
// handle per-plugin config
|
||||||
@@ -133,8 +134,8 @@ private:
|
|||||||
void setTwitterCachedMentionsSinceId( qint64 sinceid );
|
void setTwitterCachedMentionsSinceId( qint64 sinceid );
|
||||||
qint64 twitterCachedDirectMessagesSinceId() const;
|
qint64 twitterCachedDirectMessagesSinceId() const;
|
||||||
void setTwitterCachedDirectMessagesSinceId( qint64 sinceid );
|
void setTwitterCachedDirectMessagesSinceId( qint64 sinceid );
|
||||||
QHash<QString, QVariant> twitterCachedPeers() const;
|
QVariantHash twitterCachedPeers() const;
|
||||||
void setTwitterCachedPeers( const QHash<QString, QVariant> &cachedPeers );
|
void setTwitterCachedPeers( const QVariantHash &cachedPeers );
|
||||||
|
|
||||||
QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth;
|
QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth;
|
||||||
QWeakPointer< QTweetFriendsTimeline > m_friendsTimeline;
|
QWeakPointer< QTweetFriendsTimeline > m_friendsTimeline;
|
||||||
@@ -149,7 +150,7 @@ private:
|
|||||||
qint64 m_cachedFriendsSinceId;
|
qint64 m_cachedFriendsSinceId;
|
||||||
qint64 m_cachedMentionsSinceId;
|
qint64 m_cachedMentionsSinceId;
|
||||||
qint64 m_cachedDirectMessagesSinceId;
|
qint64 m_cachedDirectMessagesSinceId;
|
||||||
QHash< QString, QVariant > m_cachedPeers;
|
QVariantHash m_cachedPeers;
|
||||||
QHash< QString, QPixmap > m_cachedAvatars;
|
QHash< QString, QPixmap > m_cachedAvatars;
|
||||||
QSet<QString> m_keyCache;
|
QSet<QString> m_keyCache;
|
||||||
bool m_finishedFriends;
|
bool m_finishedFriends;
|
||||||
|
Reference in New Issue
Block a user