2020-04-03 17:01:25 +00:00
|
|
|
__filename__ = "migrate.py"
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
__license__ = "AGPL3+"
|
2021-01-26 10:07:42 +00:00
|
|
|
__version__ = "1.2.0"
|
2020-04-03 17:01:25 +00:00
|
|
|
__maintainer__ = "Bob Mottram"
|
2021-09-10 16:14:50 +00:00
|
|
|
__email__ = "bob@libreserver.org"
|
2020-04-03 17:01:25 +00:00
|
|
|
__status__ = "Production"
|
2021-06-15 15:08:12 +00:00
|
|
|
__module_group__ = "Core"
|
2019-10-31 10:36:35 +00:00
|
|
|
|
|
|
|
import os
|
2021-06-25 18:02:05 +00:00
|
|
|
from utils import isAccountDir
|
2021-01-09 15:08:26 +00:00
|
|
|
from utils import getNicknameFromActor
|
|
|
|
from utils import getDomainFromActor
|
2021-07-13 21:59:53 +00:00
|
|
|
from utils import acctDir
|
2021-07-31 11:56:28 +00:00
|
|
|
from utils import hasGroupType
|
2021-01-09 15:08:26 +00:00
|
|
|
from webfinger import webfingerHandle
|
|
|
|
from blocking import isBlocked
|
|
|
|
from posts import getUserUrl
|
|
|
|
from follow import unfollowAccount
|
2021-07-03 21:42:26 +00:00
|
|
|
from person import getActorJson
|
2019-10-31 10:36:35 +00:00
|
|
|
|
2020-04-03 17:01:25 +00:00
|
|
|
|
2021-01-09 15:08:26 +00:00
|
|
|
def _moveFollowingHandlesForAccount(baseDir: str, nickname: str, domain: str,
|
|
|
|
session,
|
|
|
|
httpPrefix: str, cachedWebfingers: {},
|
2021-08-31 14:17:11 +00:00
|
|
|
debug: bool,
|
|
|
|
signingPrivateKeyPem: str) -> int:
|
2021-01-09 15:08:26 +00:00
|
|
|
"""Goes through all follows for an account and updates any that have moved
|
2019-10-31 10:36:35 +00:00
|
|
|
"""
|
2021-01-09 15:08:26 +00:00
|
|
|
ctr = 0
|
2021-07-13 21:59:53 +00:00
|
|
|
followingFilename = acctDir(baseDir, nickname, domain) + '/following.txt'
|
2021-01-09 15:08:26 +00:00
|
|
|
if not os.path.isfile(followingFilename):
|
|
|
|
return ctr
|
2021-07-13 14:40:49 +00:00
|
|
|
with open(followingFilename, 'r') as f:
|
2021-01-09 15:08:26 +00:00
|
|
|
followingHandles = f.readlines()
|
|
|
|
for followHandle in followingHandles:
|
|
|
|
followHandle = followHandle.strip("\n").strip("\r")
|
|
|
|
ctr += \
|
|
|
|
_updateMovedHandle(baseDir, nickname, domain,
|
|
|
|
followHandle, session,
|
|
|
|
httpPrefix, cachedWebfingers,
|
2021-08-31 14:17:11 +00:00
|
|
|
debug, signingPrivateKeyPem)
|
2021-01-09 15:08:26 +00:00
|
|
|
return ctr
|
|
|
|
|
|
|
|
|
|
|
|
def _updateMovedHandle(baseDir: str, nickname: str, domain: str,
|
|
|
|
handle: str, session,
|
|
|
|
httpPrefix: str, cachedWebfingers: {},
|
2021-08-31 14:17:11 +00:00
|
|
|
debug: bool, signingPrivateKeyPem: str) -> int:
|
2021-01-09 15:08:26 +00:00
|
|
|
"""Check if an account has moved, and if so then alter following.txt
|
|
|
|
for each account.
|
|
|
|
Returns 1 if moved, 0 otherwise
|
2019-10-31 10:36:35 +00:00
|
|
|
"""
|
2021-01-09 15:08:26 +00:00
|
|
|
ctr = 0
|
|
|
|
if '@' not in handle:
|
|
|
|
return ctr
|
|
|
|
if len(handle) < 5:
|
|
|
|
return ctr
|
|
|
|
if handle.startswith('@'):
|
|
|
|
handle = handle[1:]
|
|
|
|
wfRequest = webfingerHandle(session, handle,
|
|
|
|
httpPrefix, cachedWebfingers,
|
2021-09-08 12:34:13 +00:00
|
|
|
domain, __version__, debug, False,
|
2021-08-31 14:17:11 +00:00
|
|
|
signingPrivateKeyPem)
|
2021-01-09 15:08:26 +00:00
|
|
|
if not wfRequest:
|
|
|
|
print('updateMovedHandle unable to webfinger ' + handle)
|
|
|
|
return ctr
|
|
|
|
|
|
|
|
if not isinstance(wfRequest, dict):
|
|
|
|
print('updateMovedHandle webfinger for ' + handle +
|
|
|
|
' did not return a dict. ' + str(wfRequest))
|
|
|
|
return ctr
|
|
|
|
|
|
|
|
personUrl = None
|
|
|
|
if wfRequest.get('errors'):
|
|
|
|
print('wfRequest error: ' + str(wfRequest['errors']))
|
|
|
|
return ctr
|
2019-10-31 10:36:35 +00:00
|
|
|
|
2021-01-09 15:08:26 +00:00
|
|
|
if not personUrl:
|
2021-03-14 20:41:37 +00:00
|
|
|
personUrl = getUserUrl(wfRequest, 0, debug)
|
2021-01-09 15:08:26 +00:00
|
|
|
if not personUrl:
|
|
|
|
return ctr
|
|
|
|
|
2021-07-03 21:42:26 +00:00
|
|
|
gnunet = False
|
|
|
|
if httpPrefix == 'gnunet':
|
|
|
|
gnunet = True
|
2021-01-09 15:08:26 +00:00
|
|
|
personJson = \
|
2021-08-31 14:17:11 +00:00
|
|
|
getActorJson(domain, personUrl, httpPrefix, gnunet, debug, False,
|
2021-12-14 13:27:00 +00:00
|
|
|
signingPrivateKeyPem, None)
|
2021-01-09 15:08:26 +00:00
|
|
|
if not personJson:
|
|
|
|
return ctr
|
|
|
|
if not personJson.get('movedTo'):
|
|
|
|
return ctr
|
|
|
|
movedToUrl = personJson['movedTo']
|
|
|
|
if '://' not in movedToUrl:
|
|
|
|
return ctr
|
|
|
|
if '.' not in movedToUrl:
|
|
|
|
return ctr
|
|
|
|
movedToNickname = getNicknameFromActor(movedToUrl)
|
|
|
|
if not movedToNickname:
|
|
|
|
return ctr
|
|
|
|
movedToDomain, movedToPort = getDomainFromActor(movedToUrl)
|
|
|
|
if not movedToDomain:
|
|
|
|
return ctr
|
|
|
|
movedToDomainFull = movedToDomain
|
|
|
|
if movedToPort:
|
|
|
|
if movedToPort != 80 and movedToPort != 443:
|
|
|
|
movedToDomainFull = movedToDomain + ':' + str(movedToPort)
|
2021-07-31 11:56:28 +00:00
|
|
|
groupAccount = hasGroupType(baseDir, movedToUrl, None)
|
2021-01-09 15:08:26 +00:00
|
|
|
if isBlocked(baseDir, nickname, domain,
|
|
|
|
movedToNickname, movedToDomain):
|
|
|
|
# someone that you follow has moved to a blocked domain
|
|
|
|
# so just unfollow them
|
|
|
|
unfollowAccount(baseDir, nickname, domain,
|
|
|
|
movedToNickname, movedToDomainFull,
|
2021-07-30 16:06:34 +00:00
|
|
|
debug, groupAccount, 'following.txt')
|
2021-01-09 15:08:26 +00:00
|
|
|
return ctr
|
2021-01-09 20:27:17 +00:00
|
|
|
|
2021-07-13 21:59:53 +00:00
|
|
|
followingFilename = acctDir(baseDir, nickname, domain) + '/following.txt'
|
2021-01-09 20:27:17 +00:00
|
|
|
if os.path.isfile(followingFilename):
|
2021-07-13 14:40:49 +00:00
|
|
|
with open(followingFilename, 'r') as f:
|
2021-01-09 20:27:17 +00:00
|
|
|
followingHandles = f.readlines()
|
|
|
|
|
|
|
|
movedToHandle = movedToNickname + '@' + movedToDomainFull
|
|
|
|
handleLower = handle.lower()
|
|
|
|
|
|
|
|
refollowFilename = \
|
2021-07-13 21:59:53 +00:00
|
|
|
acctDir(baseDir, nickname, domain) + '/refollow.txt'
|
2021-01-09 17:41:41 +00:00
|
|
|
|
2021-01-09 20:27:17 +00:00
|
|
|
# unfollow the old handle
|
|
|
|
with open(followingFilename, 'w+') as f:
|
|
|
|
for followHandle in followingHandles:
|
|
|
|
if followHandle.strip("\n").strip("\r").lower() != \
|
|
|
|
handleLower:
|
|
|
|
f.write(followHandle)
|
2021-01-09 18:12:36 +00:00
|
|
|
else:
|
2021-01-09 20:27:17 +00:00
|
|
|
handleNickname = handle.split('@')[0]
|
|
|
|
handleDomain = handle.split('@')[1]
|
|
|
|
unfollowAccount(baseDir, nickname, domain,
|
|
|
|
handleNickname,
|
|
|
|
handleDomain,
|
2021-07-30 16:06:34 +00:00
|
|
|
debug, groupAccount, 'following.txt')
|
2021-01-09 20:27:17 +00:00
|
|
|
ctr += 1
|
|
|
|
print('Unfollowed ' + handle + ' who has moved to ' +
|
|
|
|
movedToHandle)
|
|
|
|
|
|
|
|
# save the new handles to the refollow list
|
|
|
|
if os.path.isfile(refollowFilename):
|
2021-06-21 22:53:04 +00:00
|
|
|
with open(refollowFilename, 'a+') as f:
|
|
|
|
f.write(movedToHandle + '\n')
|
2021-01-09 20:27:17 +00:00
|
|
|
else:
|
2021-06-21 22:53:04 +00:00
|
|
|
with open(refollowFilename, 'w+') as f:
|
|
|
|
f.write(movedToHandle + '\n')
|
2021-01-09 20:27:17 +00:00
|
|
|
|
|
|
|
followersFilename = \
|
2021-07-13 21:59:53 +00:00
|
|
|
acctDir(baseDir, nickname, domain) + '/followers.txt'
|
2021-01-09 20:27:17 +00:00
|
|
|
if os.path.isfile(followersFilename):
|
2021-07-13 14:40:49 +00:00
|
|
|
with open(followersFilename, 'r') as f:
|
2021-01-09 20:27:17 +00:00
|
|
|
followerHandles = f.readlines()
|
|
|
|
|
|
|
|
handleLower = handle.lower()
|
|
|
|
|
|
|
|
# remove followers who have moved
|
|
|
|
with open(followersFilename, 'w+') as f:
|
|
|
|
for followerHandle in followerHandles:
|
|
|
|
if followerHandle.strip("\n").strip("\r").lower() != \
|
|
|
|
handleLower:
|
|
|
|
f.write(followerHandle)
|
|
|
|
else:
|
|
|
|
ctr += 1
|
|
|
|
print('Removed follower who has moved ' + handle)
|
|
|
|
|
2021-01-09 15:08:26 +00:00
|
|
|
return ctr
|
|
|
|
|
|
|
|
|
|
|
|
def migrateAccounts(baseDir: str, session,
|
|
|
|
httpPrefix: str, cachedWebfingers: {},
|
2021-08-31 14:17:11 +00:00
|
|
|
debug: bool, signingPrivateKeyPem: str) -> int:
|
2021-01-09 15:08:26 +00:00
|
|
|
"""If followed accounts change then this modifies the
|
|
|
|
following lists for each account accordingly.
|
|
|
|
Returns the number of accounts migrated
|
|
|
|
"""
|
2019-10-31 10:36:35 +00:00
|
|
|
# update followers and following lists for each account
|
2021-01-09 15:08:26 +00:00
|
|
|
ctr = 0
|
2020-04-03 17:01:25 +00:00
|
|
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
2019-10-31 10:36:35 +00:00
|
|
|
for handle in dirs:
|
2021-06-25 18:02:05 +00:00
|
|
|
if not isAccountDir(handle):
|
2021-01-09 15:08:26 +00:00
|
|
|
continue
|
|
|
|
nickname = handle.split('@')[0]
|
|
|
|
domain = handle.split('@')[1]
|
|
|
|
ctr += \
|
|
|
|
_moveFollowingHandlesForAccount(baseDir, nickname, domain,
|
|
|
|
session, httpPrefix,
|
2021-08-31 14:17:11 +00:00
|
|
|
cachedWebfingers, debug,
|
|
|
|
signingPrivateKeyPem)
|
2020-12-13 22:13:45 +00:00
|
|
|
break
|
2021-01-09 15:08:26 +00:00
|
|
|
return ctr
|