Spoof gps metadata on images

merge-requests/30/head
Bob Mottram 2021-05-09 20:11:05 +01:00
parent 53fb8b9923
commit 05f1ada1c1
13 changed files with 4456 additions and 138 deletions

View File

@ -428,7 +428,7 @@ class PubServer(BaseHTTPRequestHandler):
answer, False, False, False, answer, False, False, False,
commentsEnabled, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, self.server.city,
inReplyTo, inReplyTo,
inReplyToAtomUri, inReplyToAtomUri,
subject, subject,
@ -1170,7 +1170,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.debug, self.server.debug,
self.server.YTReplacementDomain, self.server.YTReplacementDomain,
self.server.showPublishedDateOnly, self.server.showPublishedDateOnly,
self.server.allowLocalNetworkAccess) self.server.allowLocalNetworkAccess,
self.server.city)
def _postToOutboxThread(self, messageJson: {}) -> bool: def _postToOutboxThread(self, messageJson: {}) -> bool:
"""Creates a thread to send a post """Creates a thread to send a post
@ -4075,8 +4076,8 @@ class PubServer(BaseHTTPRequestHandler):
os.remove(postImageFilename + '.etag') os.remove(postImageFilename + '.etag')
except BaseException: except BaseException:
pass pass
processMetaData(baseDir, nickname, domain, processMetaData(baseDir, nickname,
filename, postImageFilename) filename, postImageFilename, self.server.city)
if os.path.isfile(postImageFilename): if os.path.isfile(postImageFilename):
print('profile update POST ' + mType + print('profile update POST ' + mType +
' image or font saved to ' + postImageFilename) ' image or font saved to ' + postImageFilename)
@ -13055,8 +13056,8 @@ class PubServer(BaseHTTPRequestHandler):
postImageFilename = filename.replace('.temp', '') postImageFilename = filename.replace('.temp', '')
print('Removing metadata from ' + postImageFilename) print('Removing metadata from ' + postImageFilename)
processMetaData(self.server.baseDir, processMetaData(self.server.baseDir,
nickname, self.server.domain, nickname, filename, postImageFilename,
filename, postImageFilename) self.server.city)
if os.path.isfile(postImageFilename): if os.path.isfile(postImageFilename):
print('POST media saved to ' + postImageFilename) print('POST media saved to ' + postImageFilename)
else: else:
@ -13171,6 +13172,7 @@ class PubServer(BaseHTTPRequestHandler):
False, False, False, commentsEnabled, False, False, False, commentsEnabled,
filename, attachmentMediaType, filename, attachmentMediaType,
fields['imageDescription'], fields['imageDescription'],
self.server.city,
fields['replyTo'], fields['replyTo'], fields['replyTo'], fields['replyTo'],
fields['subject'], fields['schedulePost'], fields['subject'], fields['schedulePost'],
fields['eventDate'], fields['eventTime'], fields['eventDate'], fields['eventTime'],
@ -13316,7 +13318,8 @@ class PubServer(BaseHTTPRequestHandler):
postJsonObject['object'], postJsonObject['object'],
filename, filename,
attachmentMediaType, attachmentMediaType,
imgDescription) imgDescription,
self.server.city)
replaceYouTube(postJsonObject, replaceYouTube(postJsonObject,
self.server.YTReplacementDomain) self.server.YTReplacementDomain)
@ -13347,6 +13350,7 @@ class PubServer(BaseHTTPRequestHandler):
False, False, False, commentsEnabled, False, False, False, commentsEnabled,
filename, attachmentMediaType, filename, attachmentMediaType,
fields['imageDescription'], fields['imageDescription'],
self.server.city,
fields['replyTo'], fields['replyTo'],
fields['replyTo'], fields['replyTo'],
fields['subject'], fields['subject'],
@ -13379,6 +13383,7 @@ class PubServer(BaseHTTPRequestHandler):
commentsEnabled, commentsEnabled,
filename, attachmentMediaType, filename, attachmentMediaType,
fields['imageDescription'], fields['imageDescription'],
self.server.city,
fields['replyTo'], fields['replyTo'],
fields['replyTo'], fields['replyTo'],
fields['subject'], fields['subject'],
@ -13431,6 +13436,7 @@ class PubServer(BaseHTTPRequestHandler):
False, False, commentsEnabled, False, False, commentsEnabled,
filename, attachmentMediaType, filename, attachmentMediaType,
fields['imageDescription'], fields['imageDescription'],
self.server.city,
fields['subject'], fields['subject'],
fields['schedulePost'], fields['schedulePost'],
fields['eventDate'], fields['eventDate'],
@ -13468,6 +13474,7 @@ class PubServer(BaseHTTPRequestHandler):
commentsEnabled, commentsEnabled,
filename, attachmentMediaType, filename, attachmentMediaType,
fields['imageDescription'], fields['imageDescription'],
self.server.city,
fields['replyTo'], fields['replyTo'],
fields['replyTo'], fields['replyTo'],
fields['subject'], fields['subject'],
@ -13506,6 +13513,7 @@ class PubServer(BaseHTTPRequestHandler):
True, False, False, False, True, False, False, False,
filename, attachmentMediaType, filename, attachmentMediaType,
fields['imageDescription'], fields['imageDescription'],
self.server.city,
None, None, None, None,
fields['subject'], fields['subject'],
True, fields['schedulePost'], True, fields['schedulePost'],
@ -13538,6 +13546,7 @@ class PubServer(BaseHTTPRequestHandler):
True, False, False, True, True, False, False, True,
filename, attachmentMediaType, filename, attachmentMediaType,
fields['imageDescription'], fields['imageDescription'],
self.server.city,
self.server.debug, fields['subject']) self.server.debug, fields['subject'])
if messageJson: if messageJson:
if self._postToOutbox(messageJson, __version__, nickname): if self._postToOutbox(messageJson, __version__, nickname):
@ -13568,6 +13577,7 @@ class PubServer(BaseHTTPRequestHandler):
commentsEnabled, commentsEnabled,
filename, attachmentMediaType, filename, attachmentMediaType,
fields['imageDescription'], fields['imageDescription'],
self.server.city,
fields['subject'], fields['subject'],
int(fields['duration'])) int(fields['duration']))
if messageJson: if messageJson:
@ -13603,7 +13613,8 @@ class PubServer(BaseHTTPRequestHandler):
fields['category'], fields['category'],
fields['location'], fields['location'],
durationStr, durationStr,
self.server.debug) self.server.debug,
self.server.city)
if filename: if filename:
if os.path.isfile(filename): if os.path.isfile(filename):
os.remove(filename) os.remove(filename)
@ -14665,7 +14676,8 @@ def loadTokens(baseDir: str, tokensDict: {}, tokensLookup: {}) -> None:
break break
def runDaemon(showNodeInfoAccounts: bool, def runDaemon(city: str,
showNodeInfoAccounts: bool,
showNodeInfoVersion: bool, showNodeInfoVersion: bool,
brochMode: bool, brochMode: bool,
verifyAllSignatures: bool, verifyAllSignatures: bool,
@ -14823,6 +14835,13 @@ def runDaemon(showNodeInfoAccounts: bool,
print('ERROR: no translations were loaded') print('ERROR: no translations were loaded')
sys.exit() sys.exit()
# spoofed city for gps location misdirection
httpd.city = city
cityFilename = baseDir + '/accounts/city.txt'
if os.path.isfile(cityFilename):
with open(cityFilename, 'r') as fp:
httpd.city = fp.read().replace('\n', '')
# For moderated newswire feeds this is the amount of time allowed # For moderated newswire feeds this is the amount of time allowed
# for voting after the post arrives # for voting after the post arrives
httpd.votingTimeMins = votingTimeMins httpd.votingTimeMins = votingTimeMins

View File

@ -458,6 +458,7 @@ def _desktopReplyToPost(session, postId: str,
isArticle = False isArticle = False
subject = None subject = None
commentsEnabled = True commentsEnabled = True
city = 'London'
sayStr = 'Sending reply' sayStr = 'Sending reply'
_sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak) _sayCommand(sayStr, sayStr, screenreader, systemLanguage, espeak)
if sendPostViaServer(__version__, if sendPostViaServer(__version__,
@ -466,7 +467,7 @@ def _desktopReplyToPost(session, postId: str,
toNickname, toDomain, toPort, ccUrl, toNickname, toDomain, toPort, ccUrl,
httpPrefix, replyMessage, followersOnly, httpPrefix, replyMessage, followersOnly,
commentsEnabled, attach, mediaType, commentsEnabled, attach, mediaType,
attachedImageDescription, attachedImageDescription, city,
cachedWebfingers, personCache, isArticle, cachedWebfingers, personCache, isArticle,
debug, postId, postId, subject) == 0: debug, postId, postId, subject) == 0:
sayStr = 'Reply sent' sayStr = 'Reply sent'
@ -514,6 +515,7 @@ def _desktopNewPost(session,
attach = None attach = None
mediaType = None mediaType = None
attachedImageDescription = None attachedImageDescription = None
city = 'London'
isArticle = False isArticle = False
subject = None subject = None
commentsEnabled = True commentsEnabled = True
@ -526,7 +528,7 @@ def _desktopNewPost(session,
None, '#Public', port, ccUrl, None, '#Public', port, ccUrl,
httpPrefix, newMessage, followersOnly, httpPrefix, newMessage, followersOnly,
commentsEnabled, attach, mediaType, commentsEnabled, attach, mediaType,
attachedImageDescription, attachedImageDescription, city,
cachedWebfingers, personCache, isArticle, cachedWebfingers, personCache, isArticle,
debug, None, None, subject) == 0: debug, None, None, subject) == 0:
sayStr = 'Post sent' sayStr = 'Post sent'
@ -1158,6 +1160,7 @@ def _desktopNewDMbase(session, toHandle: str,
attach = None attach = None
mediaType = None mediaType = None
attachedImageDescription = None attachedImageDescription = None
city = 'London'
isArticle = False isArticle = False
subject = None subject = None
commentsEnabled = True commentsEnabled = True
@ -1206,7 +1209,7 @@ def _desktopNewDMbase(session, toHandle: str,
toNickname, toDomain, toPort, ccUrl, toNickname, toDomain, toPort, ccUrl,
httpPrefix, newMessage, followersOnly, httpPrefix, newMessage, followersOnly,
commentsEnabled, attach, mediaType, commentsEnabled, attach, mediaType,
attachedImageDescription, attachedImageDescription, city,
cachedWebfingers, personCache, isArticle, cachedWebfingers, personCache, isArticle,
debug, None, None, subject) == 0: debug, None, None, subject) == 0:
sayStr = 'Direct message sent' sayStr = 'Direct message sent'

View File

@ -464,6 +464,9 @@ parser.add_argument('--attach', dest='attach', type=str,
default=None, help='File to attach to a post') default=None, help='File to attach to a post')
parser.add_argument('--imagedescription', dest='imageDescription', type=str, parser.add_argument('--imagedescription', dest='imageDescription', type=str,
default=None, help='Description of an attached image') default=None, help='Description of an attached image')
parser.add_argument('--city', dest='city', type=str,
default='London',
help='Spoofed city for image metadata misdirection')
parser.add_argument('--warning', '--warn', '--cwsubject', '--subject', parser.add_argument('--warning', '--warn', '--cwsubject', '--subject',
dest='subject', type=str, default=None, dest='subject', type=str, default=None,
help='Subject of content warning') help='Subject of content warning')
@ -1110,6 +1113,7 @@ if args.message:
followersOnly = args.followersonly followersOnly = args.followersonly
clientToServer = args.client clientToServer = args.client
attachedImageDescription = args.imageDescription attachedImageDescription = args.imageDescription
city = 'London'
sendThreads = [] sendThreads = []
postLog = [] postLog = []
personCache = {} personCache = {}
@ -1130,7 +1134,7 @@ if args.message:
toNickname, toDomain, toPort, ccUrl, toNickname, toDomain, toPort, ccUrl,
httpPrefix, sendMessage, followersOnly, httpPrefix, sendMessage, followersOnly,
args.commentsEnabled, attach, mediaType, args.commentsEnabled, attach, mediaType,
attachedImageDescription, attachedImageDescription, city,
cachedWebfingers, personCache, isArticle, cachedWebfingers, personCache, isArticle,
args.debug, replyTo, replyTo, subject) args.debug, replyTo, replyTo, subject)
for i in range(10): for i in range(10):
@ -1959,8 +1963,9 @@ if args.avatar:
if not args.nickname: if not args.nickname:
print('Specify a nickname with --nickname [name]') print('Specify a nickname with --nickname [name]')
sys.exit() sys.exit()
city = 'London'
if setProfileImage(baseDir, httpPrefix, args.nickname, domain, if setProfileImage(baseDir, httpPrefix, args.nickname, domain,
port, args.avatar, 'avatar', '128x128'): port, args.avatar, 'avatar', '128x128', city):
print('Avatar added for ' + args.nickname) print('Avatar added for ' + args.nickname)
else: else:
print('Avatar was not added for ' + args.nickname) print('Avatar was not added for ' + args.nickname)
@ -1973,8 +1978,10 @@ if args.backgroundImage:
if not args.nickname: if not args.nickname:
print('Specify a nickname with --nickname [name]') print('Specify a nickname with --nickname [name]')
sys.exit() sys.exit()
city = 'London'
if setProfileImage(baseDir, httpPrefix, args.nickname, domain, if setProfileImage(baseDir, httpPrefix, args.nickname, domain,
port, args.backgroundImage, 'background', '256x256'): port, args.backgroundImage, 'background',
'256x256', city):
print('Background image added for ' + args.nickname) print('Background image added for ' + args.nickname)
else: else:
print('Background image was not added for ' + args.nickname) print('Background image was not added for ' + args.nickname)
@ -2347,6 +2354,7 @@ if args.unfilterStr:
sys.exit() sys.exit()
if args.testdata: if args.testdata:
city = 'London'
nickname = 'testuser567' nickname = 'testuser567'
password = 'boringpassword' password = 'boringpassword'
print('Generating some test data for user: ' + nickname) print('Generating some test data for user: ' + nickname)
@ -2394,7 +2402,7 @@ if args.testdata:
"mechanical", "mechanical",
"City", "City",
"2 months", "2 months",
debug) debug, city)
addShare(baseDir, addShare(baseDir,
httpPrefix, nickname, domain, port, httpPrefix, nickname, domain, port,
"witch hat", "witch hat",
@ -2404,7 +2412,7 @@ if args.testdata:
"clothing", "clothing",
"City", "City",
"3 months", "3 months",
debug) debug, city)
deleteAllPosts(baseDir, nickname, domain, 'inbox') deleteAllPosts(baseDir, nickname, domain, 'inbox')
deleteAllPosts(baseDir, nickname, domain, 'outbox') deleteAllPosts(baseDir, nickname, domain, 'outbox')
@ -2416,6 +2424,7 @@ if args.testdata:
testAttachImageFilename = None testAttachImageFilename = None
testMediaType = None testMediaType = None
testImageDescription = None testImageDescription = None
testCity = 'London'
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"like this is totally just a #test man", "like this is totally just a #test man",
@ -2424,7 +2433,7 @@ if args.testdata:
testC2S, testC2S,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testImageDescription) testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Zoiks!!!", "Zoiks!!!",
testFollowersOnly, testFollowersOnly,
@ -2432,7 +2441,7 @@ if args.testdata:
testC2S, testC2S,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testImageDescription) testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Hey scoob we need like a hundred more #milkshakes", "Hey scoob we need like a hundred more #milkshakes",
testFollowersOnly, testFollowersOnly,
@ -2440,7 +2449,7 @@ if args.testdata:
testC2S, testC2S,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testImageDescription) testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Getting kinda spooky around here", "Getting kinda spooky around here",
testFollowersOnly, testFollowersOnly,
@ -2448,7 +2457,7 @@ if args.testdata:
testC2S, testC2S,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testImageDescription, testMediaType, testImageDescription, testCity,
'someone') 'someone')
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"And they would have gotten away with it too" + "And they would have gotten away with it too" +
@ -2458,7 +2467,7 @@ if args.testdata:
testC2S, testC2S,
testCommentsEnabled, testCommentsEnabled,
'img/logo.png', 'image/png', 'img/logo.png', 'image/png',
'Description of image') 'Description of image', testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"man these centralized sites are like the worst!", "man these centralized sites are like the worst!",
testFollowersOnly, testFollowersOnly,
@ -2466,7 +2475,7 @@ if args.testdata:
testC2S, testC2S,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testImageDescription) testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"another mystery solved #test", "another mystery solved #test",
testFollowersOnly, testFollowersOnly,
@ -2474,7 +2483,7 @@ if args.testdata:
testC2S, testC2S,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testImageDescription) testMediaType, testImageDescription, testCity)
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"let's go bowling", "let's go bowling",
testFollowersOnly, testFollowersOnly,
@ -2482,7 +2491,7 @@ if args.testdata:
testC2S, testC2S,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testImageDescription) testMediaType, testImageDescription, testCity)
domainFull = domain + ':' + str(port) domainFull = domain + ':' + str(port)
clearFollows(baseDir, nickname, domain) clearFollows(baseDir, nickname, domain)
@ -2620,6 +2629,11 @@ showNodeInfoVersion = \
if showNodeInfoVersion is not None: if showNodeInfoVersion is not None:
args.showNodeInfoVersion = bool(showNodeInfoVersion) args.showNodeInfoVersion = bool(showNodeInfoVersion)
city = \
getConfigParam(baseDir, 'city')
if city is not None:
args.city = city
YTDomain = getConfigParam(baseDir, 'youtubedomain') YTDomain = getConfigParam(baseDir, 'youtubedomain')
if YTDomain: if YTDomain:
if '://' in YTDomain: if '://' in YTDomain:
@ -2634,7 +2648,8 @@ if setTheme(baseDir, themeName, domain,
print('Theme set to ' + themeName) print('Theme set to ' + themeName)
if __name__ == "__main__": if __name__ == "__main__":
runDaemon(args.showNodeInfoAccounts, runDaemon(args.city,
args.showNodeInfoAccounts,
args.showNodeInfoVersion, args.showNodeInfoVersion,
args.brochMode, args.brochMode,
args.verifyAllSignatures, args.verifyAllSignatures,

View File

@ -2183,6 +2183,7 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str,
attachImageFilename = None attachImageFilename = None
mediaType = None mediaType = None
imageDescription = '' imageDescription = ''
city = 'London'
inReplyTo = removeIdEnding(senderPostId) inReplyTo = removeIdEnding(senderPostId)
inReplyToAtomUri = None inReplyToAtomUri = None
schedulePost = False schedulePost = False
@ -2195,7 +2196,7 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str,
saveToFile, clientToServer, saveToFile, clientToServer,
commentsEnabled, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
inReplyTo, inReplyToAtomUri, inReplyTo, inReplyToAtomUri,
subject, debug, schedulePost, subject, debug, schedulePost,
eventDate, eventTime, location) eventDate, eventTime, location)

4188
locations.txt 100644

File diff suppressed because it is too large Load Diff

132
media.py
View File

@ -54,76 +54,105 @@ def _removeMetaData(imageFilename: str, outputFilename: str) -> None:
os.system('/usr/bin/mogrify -strip ' + outputFilename) # nosec os.system('/usr/bin/mogrify -strip ' + outputFilename) # nosec
def _spoofMetaData(nickname: str, def spoofGeolocation(baseDir: str,
imageFilename: str, outputFilename: str, city: str, currTime,
spoofFilename: str) -> None: citiesList: []) -> (float, float, str, str):
"""Given a city and the current time spoofs the location
for an image
returns latitude, longitude, N/S, E/W
"""
locationsFilename = baseDir + '/custom_locations.txt'
if not os.path.isfile(locationsFilename):
locationsFilename = baseDir + '/locations.txt'
variance = 0.2
default_latitude = 51.5069
default_longitude = -0.1114
default_latdirection = 'N'
default_longdirection = 'E'
if citiesList:
cities = citiesList
else:
if not os.path.isfile(locationsFilename):
return (default_latitude, default_longitude,
default_latdirection, default_longdirection)
cities = []
with open(locationsFilename, "r") as f:
cities = f.readlines()
city = city.lower()
for cityName in cities:
if city in cityName.lower():
latitude = cityName.split(':')[1]
longitude = cityName.split(':')[2]
latdirection = 'N'
longdirection = 'E'
if 'S' in latitude:
latdirection = 'S'
latitude = latitude.replace('S', '')
if 'W' in longitude:
longdirection = 'W'
longitude = longitude.replace('W', '')
# add some randomness
fraction = randint(0, 100000) / 100000
fraction = fraction * fraction
latitude = float(latitude) + \
(fraction * variance) - (variance / 2.0)
latitude = int(latitude * 10000) / 10000.0
fraction = randint(0, 100000) / 100000
fraction = fraction * fraction
longitude = float(longitude) + \
(fraction * variance) - (variance / 2.0)
longitude = int(longitude * 10000) / 10000.0
return latitude, longitude, latdirection, longdirection
return (default_latitude, default_longitude,
default_latdirection, default_longdirection)
def _spoofMetaData(baseDir: str, nickname: str,
outputFilename: str, spoofCity: str) -> None:
"""Use reference images to spoof the metadata """Use reference images to spoof the metadata
""" """
copyfile(imageFilename, outputFilename)
if not os.path.isfile(outputFilename): if not os.path.isfile(outputFilename):
print('ERROR: unable to spoof metadata from ' + imageFilename) print('ERROR: unable to spoof metadata within ' + outputFilename)
return
if not os.path.isfile(spoofFilename):
print('ERROR: No spoof reference image ' + spoofFilename)
return return
if os.path.isfile('/usr/bin/exiftool'): if os.path.isfile('/usr/bin/exiftool'):
print('Spoofing metadata in ' + outputFilename + ' using exiftool') print('Spoofing metadata in ' + outputFilename + ' using exiftool')
os.system('exiftool -TagsFromFile ' +
spoofFilename + ' ' + outputFilename) # nosec
currTimeAdjusted = \ currTimeAdjusted = \
datetime.datetime.utcnow() - \ datetime.datetime.utcnow() - \
datetime.timedelta(minutes=randint(2, 120)) datetime.timedelta(minutes=randint(2, 120))
published = currTimeAdjusted.strftime("%Y:%m:%d %H:%M:%S+00:00") published = currTimeAdjusted.strftime("%Y:%m:%d %H:%M:%S+00:00")
(latitude, longitude, latitudeRef, longitudeRef) = \
spoofGeolocation(baseDir, spoofCity, currTimeAdjusted, None)
os.system('exiftool -artist="' + nickname + '" ' + os.system('exiftool -artist="' + nickname + '" ' +
'-time:all="' + published + '" ' + '-DateTimeOriginal="' + published + '" ' +
'-FileModifyDate="' + published + '" ' +
'-CreateDate="' + published + '" ' +
'-GPSLongitudeRef=' + longitudeRef + ' ' +
'-GPSAltitude=0 ' +
'-GPSLongitude=' + str(longitude) + ' ' +
'-GPSLatitudeRef=' + latitudeRef + ' ' +
'-GPSLatitude=' + str(latitude) + ' ' +
'-Comment="" ' +
outputFilename) # nosec outputFilename) # nosec
else: else:
print('ERROR: exiftool is not installed') print('ERROR: exiftool is not installed')
return return
def processMetaData(baseDir: str, nickname: str, domain: str, def processMetaData(baseDir: str, nickname: str,
imageFilename: str, outputFilename: str) -> None: imageFilename: str, outputFilename: str,
city: str) -> None:
"""Handles image metadata. This tries to spoof the metadata """Handles image metadata. This tries to spoof the metadata
if possible, but otherwise just removes it if possible, but otherwise just removes it
""" """
accountDir = baseDir + '/accounts/' + nickname + '@' + domain # first remove the metadata
spoofImagesDir = accountDir + '/ref/images'
if os.path.isdir(spoofImagesDir):
imageTypes = getImageExtensions()
# get the format of the target image
ext = None
for mType in imageTypes:
if outputFilename.endswith('.' + mType):
ext = mType
break
if ext:
spoofList = []
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for f in files:
filename = os.path.join(spoofImagesDir, f)
# what is the format of this file?
currExt = None
for mType in imageTypes:
if filename.endswith('.' + mType):
currExt = mType
break
# if this the same format as the target?
if currExt:
if currExt == ext:
spoofList.append(filename)
break
if spoofList:
# choose a reference at random
index = randint(0, len(spoofList))
spoofFilename = spoofList[index]
_spoofMetaData(nickname,
imageFilename, outputFilename,
spoofFilename)
return
# if we can't spoof then just remove metadata
_removeMetaData(imageFilename, outputFilename) _removeMetaData(imageFilename, outputFilename)
# now add some spoofed data to misdirect surveillance capitalists
_spoofMetaData(baseDir, nickname, outputFilename, city)
def _isMedia(imageFilename: str) -> bool: def _isMedia(imageFilename: str) -> bool:
"""Is the given file a media file? """Is the given file a media file?
@ -206,7 +235,8 @@ def _updateEtag(mediaFilename: str) -> None:
def attachMedia(baseDir: str, httpPrefix: str, def attachMedia(baseDir: str, httpPrefix: str,
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
postJson: {}, imageFilename: str, postJson: {}, imageFilename: str,
mediaType: str, description: str) -> {}: mediaType: str, description: str,
city: str) -> {}:
"""Attaches media to a json object post """Attaches media to a json object post
The description can be None The description can be None
""" """
@ -252,8 +282,8 @@ def attachMedia(baseDir: str, httpPrefix: str,
if baseDir: if baseDir:
if mediaType.startswith('image/'): if mediaType.startswith('image/'):
processMetaData(baseDir, nickname, domain, processMetaData(baseDir, nickname,
imageFilename, mediaFilename) imageFilename, mediaFilename, city)
else: else:
copyfile(imageFilename, mediaFilename) copyfile(imageFilename, mediaFilename)
_updateEtag(mediaFilename) _updateEtag(mediaFilename)

View File

@ -527,11 +527,17 @@ def _convertRSStoActivityPub(baseDir: str, httpPrefix: str,
# NOTE: the id when the post is created will not be # NOTE: the id when the post is created will not be
# consistent (it's based on the current time, not the # consistent (it's based on the current time, not the
# published time), so we change that later # published time), so we change that later
saveToFile = False
attachImageFilename = None
mediaType = None
imageDescription = None
city = 'London'
blog = createNewsPost(baseDir, blog = createNewsPost(baseDir,
domain, port, httpPrefix, domain, port, httpPrefix,
rssDescription, rssDescription,
followersOnly, False, followersOnly, saveToFile,
None, None, None, attachImageFilename, mediaType,
imageDescription, city,
rssTitle) rssTitle)
if not blog: if not blog:
continue continue

View File

@ -176,7 +176,8 @@ def postMessageToOutbox(session, translate: {},
proxyType: str, version: str, debug: bool, proxyType: str, version: str, debug: bool,
YTReplacementDomain: str, YTReplacementDomain: str,
showPublishedDateOnly: bool, showPublishedDateOnly: bool,
allowLocalNetworkAccess: bool) -> bool: allowLocalNetworkAccess: bool,
city: str) -> bool:
"""post is received by the outbox """post is received by the outbox
Client to server message post Client to server message post
https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery
@ -545,7 +546,7 @@ def postMessageToOutbox(session, translate: {},
print('DEBUG: handle share uploads') print('DEBUG: handle share uploads')
outboxShareUpload(baseDir, httpPrefix, outboxShareUpload(baseDir, httpPrefix,
postToNickname, domain, postToNickname, domain,
port, messageJson, debug) port, messageJson, debug, city)
if debug: if debug:
print('DEBUG: handle undo share uploads') print('DEBUG: handle undo share uploads')

View File

@ -74,7 +74,7 @@ def generateRSAKey() -> (str, str):
def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str, def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
port: int, imageFilename: str, imageType: str, port: int, imageFilename: str, imageType: str,
resolution: str) -> bool: resolution: str, city: str) -> bool:
"""Saves the given image file as an avatar or background """Saves the given image file as an avatar or background
image for the given person image for the given person
""" """
@ -135,8 +135,8 @@ def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
'/usr/bin/convert ' + imageFilename + ' -size ' + \ '/usr/bin/convert ' + imageFilename + ' -size ' + \
resolution + ' -quality 50 ' + profileFilename resolution + ' -quality 50 ' + profileFilename
subprocess.call(cmd, shell=True) subprocess.call(cmd, shell=True)
processMetaData(baseDir, nickname, domain, processMetaData(baseDir, nickname,
profileFilename, profileFilename) profileFilename, profileFilename, city)
return True return True
return False return False

View File

@ -867,7 +867,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
followersOnly: bool, saveToFile: bool, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, attachImageFilename: str,
mediaType: str, imageDescription: str, mediaType: str, imageDescription: str, city: str,
isModerationReport: bool, isModerationReport: bool,
isArticle: bool, isArticle: bool,
inReplyTo=None, inReplyTo=None,
@ -1107,7 +1107,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
newPost['object'] = \ newPost['object'] = \
attachMedia(baseDir, httpPrefix, nickname, domain, port, attachMedia(baseDir, httpPrefix, nickname, domain, port,
newPost['object'], attachImageFilename, newPost['object'], attachImageFilename,
mediaType, imageDescription) mediaType, imageDescription, city)
_appendEventFields(newPost['object'], eventUUID, eventStatus, _appendEventFields(newPost['object'], eventUUID, eventStatus,
anonymousParticipationEnabled, anonymousParticipationEnabled,
repliesModerationOption, repliesModerationOption,
@ -1157,7 +1157,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
newPost = \ newPost = \
attachMedia(baseDir, httpPrefix, nickname, domain, port, attachMedia(baseDir, httpPrefix, nickname, domain, port,
newPost, attachImageFilename, newPost, attachImageFilename,
mediaType, imageDescription) mediaType, imageDescription, city)
_appendEventFields(newPost, eventUUID, eventStatus, _appendEventFields(newPost, eventUUID, eventStatus,
anonymousParticipationEnabled, anonymousParticipationEnabled,
repliesModerationOption, repliesModerationOption,
@ -1397,7 +1397,7 @@ def createPublicPost(baseDir: str,
content: str, followersOnly: bool, saveToFile: bool, content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None, subject=None, inReplyTo=None, inReplyToAtomUri=None, subject=None,
schedulePost=False, schedulePost=False,
eventDate=None, eventTime=None, location=None, eventDate=None, eventTime=None, location=None,
@ -1423,7 +1423,7 @@ def createPublicPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
isModerationReport, isArticle, isModerationReport, isArticle,
inReplyTo, inReplyToAtomUri, subject, inReplyTo, inReplyToAtomUri, subject,
schedulePost, eventDate, eventTime, location, schedulePost, eventDate, eventTime, location,
@ -1470,7 +1470,7 @@ def createBlogPost(baseDir: str,
content: str, followersOnly: bool, saveToFile: bool, content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None, subject=None, inReplyTo=None, inReplyToAtomUri=None, subject=None,
schedulePost=False, schedulePost=False,
eventDate=None, eventTime=None, location=None) -> {}: eventDate=None, eventTime=None, location=None) -> {}:
@ -1480,7 +1480,7 @@ def createBlogPost(baseDir: str,
content, followersOnly, saveToFile, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
inReplyTo, inReplyToAtomUri, subject, inReplyTo, inReplyToAtomUri, subject,
schedulePost, schedulePost,
eventDate, eventTime, location, True) eventDate, eventTime, location, True)
@ -1495,7 +1495,7 @@ def createNewsPost(baseDir: str,
domain: str, port: int, httpPrefix: str, domain: str, port: int, httpPrefix: str,
content: str, followersOnly: bool, saveToFile: bool, content: str, followersOnly: bool, saveToFile: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
subject: str) -> {}: subject: str) -> {}:
clientToServer = False clientToServer = False
inReplyTo = None inReplyTo = None
@ -1510,7 +1510,7 @@ def createNewsPost(baseDir: str,
content, followersOnly, saveToFile, content, followersOnly, saveToFile,
clientToServer, False, clientToServer, False,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
inReplyTo, inReplyToAtomUri, subject, inReplyTo, inReplyToAtomUri, subject,
schedulePost, schedulePost,
eventDate, eventTime, location, True) eventDate, eventTime, location, True)
@ -1524,7 +1524,7 @@ def createQuestionPost(baseDir: str,
followersOnly: bool, saveToFile: bool, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
subject: str, durationDays: int) -> {}: subject: str, durationDays: int) -> {}:
"""Question post with multiple choice options """Question post with multiple choice options
""" """
@ -1537,7 +1537,7 @@ def createQuestionPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
False, False, None, None, subject, False, False, None, None, subject,
False, None, None, None, None, None, False, None, None, None, None, None,
None, None, None, None, None, None,
@ -1568,7 +1568,7 @@ def createUnlistedPost(baseDir: str,
content: str, followersOnly: bool, saveToFile: bool, content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None, subject=None, inReplyTo=None, inReplyToAtomUri=None, subject=None,
schedulePost=False, schedulePost=False,
eventDate=None, eventTime=None, location=None) -> {}: eventDate=None, eventTime=None, location=None) -> {}:
@ -1582,8 +1582,9 @@ def createUnlistedPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
False, False, inReplyTo, inReplyToAtomUri, subject, False, False,
inReplyTo, inReplyToAtomUri, subject,
schedulePost, eventDate, eventTime, location, schedulePost, eventDate, eventTime, location,
None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None) None, None, None, None, None)
@ -1596,7 +1597,7 @@ def createFollowersOnlyPost(baseDir: str,
saveToFile: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None, inReplyTo=None, inReplyToAtomUri=None,
subject=None, schedulePost=False, subject=None, schedulePost=False,
eventDate=None, eventTime=None, eventDate=None, eventTime=None,
@ -1611,8 +1612,9 @@ def createFollowersOnlyPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
False, False, inReplyTo, inReplyToAtomUri, subject, False, False,
inReplyTo, inReplyToAtomUri, subject,
schedulePost, eventDate, eventTime, location, schedulePost, eventDate, eventTime, location,
None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None) None, None, None, None, None)
@ -1625,7 +1627,7 @@ def createEventPost(baseDir: str,
saveToFile: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
subject=None, schedulePost=False, subject=None, schedulePost=False,
eventDate=None, eventTime=None, eventDate=None, eventTime=None,
location=None, category=None, joinMode=None, location=None, category=None, joinMode=None,
@ -1658,7 +1660,7 @@ def createEventPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
False, False, None, None, subject, False, False, None, None, subject,
schedulePost, eventDate, eventTime, location, schedulePost, eventDate, eventTime, location,
eventUUID, category, joinMode, eventUUID, category, joinMode,
@ -1710,7 +1712,7 @@ def createDirectMessagePost(baseDir: str,
saveToFile: bool, clientToServer: bool, saveToFile: bool, clientToServer: bool,
commentsEnabled: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
inReplyTo=None, inReplyToAtomUri=None, inReplyTo=None, inReplyToAtomUri=None,
subject=None, debug=False, subject=None, debug=False,
schedulePost=False, schedulePost=False,
@ -1733,8 +1735,9 @@ def createDirectMessagePost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
False, False, inReplyTo, inReplyToAtomUri, subject, False, False,
inReplyTo, inReplyToAtomUri, subject,
schedulePost, eventDate, eventTime, location, schedulePost, eventDate, eventTime, location,
None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None) None, None, None, None, None)
@ -1754,7 +1757,7 @@ def createReportPost(baseDir: str,
content: str, followersOnly: bool, saveToFile: bool, content: str, followersOnly: bool, saveToFile: bool,
clientToServer: bool, commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
debug: bool, subject=None) -> {}: debug: bool, subject=None) -> {}:
"""Send a report to moderators """Send a report to moderators
""" """
@ -1823,7 +1826,7 @@ def createReportPost(baseDir: str,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
True, False, None, None, subject, True, False, None, None, subject,
False, None, None, None, None, None, False, None, None, None, None, None,
None, None, None, None, None, None,
@ -1908,7 +1911,7 @@ def sendPost(projectVersion: str,
saveToFile: bool, clientToServer: bool, saveToFile: bool, clientToServer: bool,
commentsEnabled: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
federationList: [], sendThreads: [], postLog: [], federationList: [], sendThreads: [], postLog: [],
cachedWebfingers: {}, personCache: {}, cachedWebfingers: {}, personCache: {},
isArticle: bool, isArticle: bool,
@ -1967,7 +1970,7 @@ def sendPost(projectVersion: str,
followersOnly, saveToFile, clientToServer, followersOnly, saveToFile, clientToServer,
commentsEnabled, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
False, isArticle, inReplyTo, False, isArticle, inReplyTo,
inReplyToAtomUri, subject, inReplyToAtomUri, subject,
False, None, None, None, None, None, False, None, None, None, None, None,
@ -2029,7 +2032,7 @@ def sendPostViaServer(projectVersion: str,
httpPrefix: str, content: str, followersOnly: bool, httpPrefix: str, content: str, followersOnly: bool,
commentsEnabled: bool, commentsEnabled: bool,
attachImageFilename: str, mediaType: str, attachImageFilename: str, mediaType: str,
imageDescription: str, imageDescription: str, city: str,
cachedWebfingers: {}, personCache: {}, cachedWebfingers: {}, personCache: {},
isArticle: bool, debug=False, inReplyTo=None, isArticle: bool, debug=False, inReplyTo=None,
inReplyToAtomUri=None, subject=None) -> int: inReplyToAtomUri=None, subject=None) -> int:
@ -2106,7 +2109,7 @@ def sendPostViaServer(projectVersion: str,
followersOnly, saveToFile, clientToServer, followersOnly, saveToFile, clientToServer,
commentsEnabled, commentsEnabled,
attachImageFilename, mediaType, attachImageFilename, mediaType,
imageDescription, imageDescription, city,
False, isArticle, inReplyTo, False, isArticle, inReplyTo,
inReplyToAtomUri, subject, inReplyToAtomUri, subject,
False, None, None, None, None, None, False, None, None, None, None, None,

View File

@ -108,7 +108,8 @@ def _updatePostSchedule(baseDir: str, handle: str, httpd,
httpd.debug, httpd.debug,
httpd.YTReplacementDomain, httpd.YTReplacementDomain,
httpd.showPublishedDateOnly, httpd.showPublishedDateOnly,
httpd.allowLocalNetworkAccess): httpd.allowLocalNetworkAccess,
httpd.city):
indexLines.remove(line) indexLines.remove(line)
os.remove(postFilename) os.remove(postFilename)
continue continue

View File

@ -73,7 +73,7 @@ def addShare(baseDir: str,
httpPrefix: str, nickname: str, domain: str, port: int, httpPrefix: str, nickname: str, domain: str, port: int,
displayName: str, summary: str, imageFilename: str, displayName: str, summary: str, imageFilename: str,
itemType: str, itemCategory: str, location: str, itemType: str, itemCategory: str, location: str,
duration: str, debug: bool) -> None: duration: str, debug: bool, city: str) -> None:
"""Adds a new share """Adds a new share
""" """
sharesFilename = baseDir + '/accounts/' + \ sharesFilename = baseDir + '/accounts/' + \
@ -129,8 +129,9 @@ def addShare(baseDir: str,
formats = getImageExtensions() formats = getImageExtensions()
for ext in formats: for ext in formats:
if imageFilename.endswith('.' + ext): if imageFilename.endswith('.' + ext):
processMetaData(baseDir, nickname, domain, processMetaData(baseDir, nickname,
imageFilename, itemIDfile + '.' + ext) imageFilename, itemIDfile + '.' + ext,
city)
if moveImage: if moveImage:
os.remove(imageFilename) os.remove(imageFilename)
imageUrl = \ imageUrl = \
@ -513,7 +514,7 @@ def sendUndoShareViaServer(baseDir: str, session,
def outboxShareUpload(baseDir: str, httpPrefix: str, def outboxShareUpload(baseDir: str, httpPrefix: str,
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
messageJson: {}, debug: bool) -> None: messageJson: {}, debug: bool, city: str) -> None:
""" When a shared item is received by the outbox from c2s """ When a shared item is received by the outbox from c2s
""" """
if not messageJson.get('type'): if not messageJson.get('type'):
@ -565,7 +566,7 @@ def outboxShareUpload(baseDir: str, httpPrefix: str,
messageJson['object']['itemCategory'], messageJson['object']['itemCategory'],
messageJson['object']['location'], messageJson['object']['location'],
messageJson['object']['duration'], messageJson['object']['duration'],
debug) debug, city)
if debug: if debug:
print('DEBUG: shared item received via c2s') print('DEBUG: shared item received via c2s')

View File

@ -10,6 +10,7 @@ import time
import os import os
import shutil import shutil
import json import json
import datetime
from time import gmtime, strftime from time import gmtime, strftime
from pprint import pprint from pprint import pprint
from httpsig import signPostHeaders from httpsig import signPostHeaders
@ -75,6 +76,7 @@ from like import likePost
from like import sendLikeViaServer from like import sendLikeViaServer
from announce import announcePublic from announce import announcePublic
from announce import sendAnnounceViaServer from announce import sendAnnounceViaServer
from media import spoofGeolocation
from media import getMediaPath from media import getMediaPath
from media import getAttachmentMediaType from media import getAttachmentMediaType
from delete import sendDeleteViaServer from delete import sendDeleteViaServer
@ -463,6 +465,7 @@ def createServerAlice(path: str, domain: str, port: int,
testAttachImageFilename = None testAttachImageFilename = None
testMediaType = None testMediaType = None
testImageDescription = None testImageDescription = None
testCity = 'London'
createPublicPost(path, nickname, domain, port, httpPrefix, createPublicPost(path, nickname, domain, port, httpPrefix,
"No wise fish would go anywhere without a porpoise", "No wise fish would go anywhere without a porpoise",
testFollowersOnly, testFollowersOnly,
@ -471,7 +474,7 @@ def createServerAlice(path: str, domain: str, port: int,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testMediaType,
testImageDescription) testImageDescription, testCity)
createPublicPost(path, nickname, domain, port, httpPrefix, createPublicPost(path, nickname, domain, port, httpPrefix,
"Curiouser and curiouser!", "Curiouser and curiouser!",
testFollowersOnly, testFollowersOnly,
@ -480,7 +483,7 @@ def createServerAlice(path: str, domain: str, port: int,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testMediaType,
testImageDescription) testImageDescription, testCity)
createPublicPost(path, nickname, domain, port, httpPrefix, createPublicPost(path, nickname, domain, port, httpPrefix,
"In the gardens of memory, in the palace " + "In the gardens of memory, in the palace " +
"of dreams, that is where you and I shall meet", "of dreams, that is where you and I shall meet",
@ -490,7 +493,7 @@ def createServerAlice(path: str, domain: str, port: int,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testMediaType,
testImageDescription) testImageDescription, testCity)
global testServerAliceRunning global testServerAliceRunning
testServerAliceRunning = True testServerAliceRunning = True
maxMentions = 10 maxMentions = 10
@ -506,8 +509,10 @@ def createServerAlice(path: str, domain: str, port: int,
brochMode = False brochMode = False
showNodeInfoAccounts = True showNodeInfoAccounts = True
showNodeInfoVersion = True showNodeInfoVersion = True
city = 'London'
print('Server running: Alice') print('Server running: Alice')
runDaemon(showNodeInfoAccounts, runDaemon(city,
showNodeInfoAccounts,
showNodeInfoVersion, showNodeInfoVersion,
brochMode, brochMode,
verifyAllSignatures, verifyAllSignatures,
@ -564,6 +569,7 @@ def createServerBob(path: str, domain: str, port: int,
testAttachImageFilename = None testAttachImageFilename = None
testImageDescription = None testImageDescription = None
testMediaType = None testMediaType = None
testCity = 'London'
createPublicPost(path, nickname, domain, port, httpPrefix, createPublicPost(path, nickname, domain, port, httpPrefix,
"It's your life, live it your way.", "It's your life, live it your way.",
testFollowersOnly, testFollowersOnly,
@ -572,7 +578,7 @@ def createServerBob(path: str, domain: str, port: int,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testMediaType,
testImageDescription) testImageDescription, testCity)
createPublicPost(path, nickname, domain, port, httpPrefix, createPublicPost(path, nickname, domain, port, httpPrefix,
"One of the things I've realised is that " + "One of the things I've realised is that " +
"I am very simple", "I am very simple",
@ -582,7 +588,7 @@ def createServerBob(path: str, domain: str, port: int,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testMediaType,
testImageDescription) testImageDescription, testCity)
createPublicPost(path, nickname, domain, port, httpPrefix, createPublicPost(path, nickname, domain, port, httpPrefix,
"Quantum physics is a bit of a passion of mine", "Quantum physics is a bit of a passion of mine",
testFollowersOnly, testFollowersOnly,
@ -591,7 +597,7 @@ def createServerBob(path: str, domain: str, port: int,
testCommentsEnabled, testCommentsEnabled,
testAttachImageFilename, testAttachImageFilename,
testMediaType, testMediaType,
testImageDescription) testImageDescription, testCity)
global testServerBobRunning global testServerBobRunning
testServerBobRunning = True testServerBobRunning = True
maxMentions = 10 maxMentions = 10
@ -607,8 +613,10 @@ def createServerBob(path: str, domain: str, port: int,
brochMode = False brochMode = False
showNodeInfoAccounts = True showNodeInfoAccounts = True
showNodeInfoVersion = True showNodeInfoVersion = True
city = 'London'
print('Server running: Bob') print('Server running: Bob')
runDaemon(showNodeInfoAccounts, runDaemon(city,
showNodeInfoAccounts,
showNodeInfoVersion, showNodeInfoVersion,
brochMode, brochMode,
verifyAllSignatures, verifyAllSignatures,
@ -662,8 +670,10 @@ def createServerEve(path: str, domain: str, port: int, federationList: [],
brochMode = False brochMode = False
showNodeInfoAccounts = True showNodeInfoAccounts = True
showNodeInfoVersion = True showNodeInfoVersion = True
city = 'London'
print('Server running: Eve') print('Server running: Eve')
runDaemon(showNodeInfoAccounts, runDaemon(city,
showNodeInfoAccounts,
showNodeInfoVersion, showNodeInfoVersion,
brochMode, brochMode,
verifyAllSignatures, verifyAllSignatures,
@ -768,6 +778,7 @@ def testPostMessageBetweenServers():
mediaType = getAttachmentMediaType(attachedImageFilename) mediaType = getAttachmentMediaType(attachedImageFilename)
attachedImageDescription = 'Logo' attachedImageDescription = 'Logo'
isArticle = False isArticle = False
city = 'London'
# nothing in Alice's outbox # nothing in Alice's outbox
outboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/outbox' outboxPath = aliceDir + '/accounts/alice@' + aliceDomain + '/outbox'
assert len([name for name in os.listdir(outboxPath) assert len([name for name in os.listdir(outboxPath)
@ -782,7 +793,7 @@ def testPostMessageBetweenServers():
followersOnly, followersOnly,
saveToFile, clientToServer, True, saveToFile, clientToServer, True,
attachedImageFilename, mediaType, attachedImageFilename, mediaType,
attachedImageDescription, federationList, attachedImageDescription, city, federationList,
aliceSendThreads, alicePostLog, aliceCachedWebfingers, aliceSendThreads, alicePostLog, aliceCachedWebfingers,
alicePersonCache, isArticle, inReplyTo, alicePersonCache, isArticle, inReplyTo,
inReplyToAtomUri, subject) inReplyToAtomUri, subject)
@ -1085,13 +1096,14 @@ def testFollowBetweenServers():
aliceCachedWebfingers = {} aliceCachedWebfingers = {}
alicePostLog = [] alicePostLog = []
isArticle = False isArticle = False
city = 'London'
sendResult = \ sendResult = \
sendPost(__version__, sendPost(__version__,
sessionAlice, aliceDir, 'alice', aliceDomain, alicePort, sessionAlice, aliceDir, 'alice', aliceDomain, alicePort,
'bob', bobDomain, bobPort, ccUrl, 'bob', bobDomain, bobPort, ccUrl,
httpPrefix, 'Alice message', followersOnly, saveToFile, httpPrefix, 'Alice message', followersOnly, saveToFile,
clientToServer, True, clientToServer, True,
None, None, None, federationList, None, None, None, city, federationList,
aliceSendThreads, alicePostLog, aliceCachedWebfingers, aliceSendThreads, alicePostLog, aliceCachedWebfingers,
alicePersonCache, isArticle, inReplyTo, alicePersonCache, isArticle, inReplyTo,
inReplyToAtomUri, subject) inReplyToAtomUri, subject)
@ -1390,7 +1402,7 @@ def testCreatePerson():
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"G'day world!", False, True, clientToServer, "G'day world!", False, True, clientToServer,
True, None, None, None, None, True, None, None, None, None,
'Not suitable for Vogons') 'Not suitable for Vogons', 'London')
os.chdir(currDir) os.chdir(currDir)
shutil.rmtree(baseDir) shutil.rmtree(baseDir)
@ -1593,6 +1605,7 @@ def testClientToServer():
attachedImageFilename = baseDir + '/img/logo.png' attachedImageFilename = baseDir + '/img/logo.png'
mediaType = getAttachmentMediaType(attachedImageFilename) mediaType = getAttachmentMediaType(attachedImageFilename)
attachedImageDescription = 'Logo' attachedImageDescription = 'Logo'
city = 'London'
isArticle = False isArticle = False
cachedWebfingers = {} cachedWebfingers = {}
personCache = {} personCache = {}
@ -1611,7 +1624,7 @@ def testClientToServer():
httpPrefix, 'Sent from my ActivityPub client', httpPrefix, 'Sent from my ActivityPub client',
followersOnly, True, followersOnly, True,
attachedImageFilename, mediaType, attachedImageFilename, mediaType,
attachedImageDescription, attachedImageDescription, city,
cachedWebfingers, personCache, isArticle, cachedWebfingers, personCache, isArticle,
True, None, None, None) True, None, None, None)
print('sendResult: ' + str(sendResult)) print('sendResult: ' + str(sendResult))
@ -2822,11 +2835,21 @@ def testReplyToPublicPost() -> None:
port = 443 port = 443
httpPrefix = 'https' httpPrefix = 'https'
postId = httpPrefix + '://rat.site/users/ninjarodent/statuses/63746173435' postId = httpPrefix + '://rat.site/users/ninjarodent/statuses/63746173435'
content = "@ninjarodent@rat.site This is a test."
followersOnly = False
saveToFile = False
clientToServer = False
commentsEnabled = True
attachImageFilename = None
mediaType = None
imageDescription = 'Some description'
city = 'London'
reply = \ reply = \
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"@ninjarodent@rat.site This is a test.", content, followersOnly, saveToFile,
False, False, False, True, clientToServer, commentsEnabled,
None, None, False, postId) attachImageFilename, mediaType,
imageDescription, city, postId)
# print(str(reply)) # print(str(reply))
assert reply['object']['content'] == \ assert reply['object']['content'] == \
'<p><span class=\"h-card\">' + \ '<p><span class=\"h-card\">' + \
@ -3244,11 +3267,20 @@ def testLinksWithinPost() -> None:
httpPrefix = 'https' httpPrefix = 'https'
content = 'This is a test post with links.\n\n' + \ content = 'This is a test post with links.\n\n' + \
'ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/\n\nhttps://freedombone.net' 'ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/\n\nhttps://freedombone.net'
followersOnly = False
saveToFile = False
clientToServer = False
commentsEnabled = True
mediaType = None
imageDescription = None
city = 'London'
postJsonObject = \ postJsonObject = \
createPublicPost(baseDir, nickname, domain, port, httpPrefix, createPublicPost(baseDir, nickname, domain, port, httpPrefix,
content, content, followersOnly, saveToFile,
False, False, False, True, clientToServer, commentsEnabled,
None, None, False, None) mediaType, imageDescription, city,
False, None)
assert postJsonObject['object']['content'] == \ assert postJsonObject['object']['content'] == \
'<p>This is a test post with links.<br><br>' + \ '<p>This is a test post with links.<br><br>' + \
'<a href="ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/" ' + \ '<a href="ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/v4/" ' + \
@ -3636,9 +3668,27 @@ def testRemovePostInteractions() -> None:
assert not removePostInteractions(postJsonObject, False) assert not removePostInteractions(postJsonObject, False)
def testSpoofGeolocation() -> None:
print('testSpoofGeolocation')
citiesList = [
'NEW YORK, USA:40.6397:W73.7789',
'LOS ANGELES, USA:33.9425:W118.408',
'HOUSTON, USA:29.9803:W95.3397'
]
currTime = datetime.datetime.utcnow()
coords = spoofGeolocation('', 'los angeles', currTime, citiesList)
assert coords[0] >= 33.9425 - 0.1
assert coords[0] <= 33.9425 + 0.1
assert coords[1] >= 118.408 - 0.1
assert coords[1] <= 118.408 + 0.1
assert coords[2] == 'N'
assert coords[3] == 'W'
def runAllTests(): def runAllTests():
print('Running tests...') print('Running tests...')
testFunctions() testFunctions()
testSpoofGeolocation()
testRemovePostInteractions() testRemovePostInteractions()
testExtractPGPPublicKey() testExtractPGPPublicKey()
testEmojiImages() testEmojiImages()