flake8 style

main
Bob Mottram 2020-04-01 19:11:39 +00:00
parent ae5b9f579f
commit 65d3ace372
1 changed files with 260 additions and 237 deletions

View File

@ -7,8 +7,6 @@ __email__="bob@freedombone.net"
__status__ = "Production" __status__ = "Production"
import os import os
import time
import json
from pprint import pprint from pprint import pprint
from utils import removePostFromCache from utils import removePostFromCache
from utils import getStatusNumber from utils import getStatusNumber
@ -26,7 +24,8 @@ from session import postJson
from webfinger import webfingerHandle from webfinger import webfingerHandle
from auth import createBasicAuthHeader from auth import createBasicAuthHeader
def outboxAnnounce(recentPostsCache: {}, \
def outboxAnnounce(recentPostsCache: {},
baseDir: str, messageJson: {}, debug: bool) -> bool: baseDir: str, messageJson: {}, debug: bool) -> bool:
""" Adds or removes announce entries from the shares collection """ Adds or removes announce entries from the shares collection
within a given post within a given post
@ -45,9 +44,10 @@ def outboxAnnounce(recentPostsCache: {}, \
print('WARN: no nickname found in '+messageJson['actor']) print('WARN: no nickname found in '+messageJson['actor'])
return False return False
domain, port = getDomainFromActor(messageJson['actor']) domain, port = getDomainFromActor(messageJson['actor'])
postFilename=locatePost(baseDir,nickname,domain,messageJson['object']) postFilename = locatePost(baseDir, nickname, domain,
messageJson['object'])
if postFilename: if postFilename:
updateAnnounceCollection(recentPostsCache,baseDir,postFilename, \ updateAnnounceCollection(recentPostsCache, baseDir, postFilename,
messageJson['actor'], domain, debug) messageJson['actor'], domain, debug)
return True return True
if messageJson['type'] == 'Undo': if messageJson['type'] == 'Undo':
@ -63,19 +63,19 @@ def outboxAnnounce(recentPostsCache: {}, \
print('WARN: no nickname found in ' + messageJson['actor']) print('WARN: no nickname found in ' + messageJson['actor'])
return False return False
domain, port = getDomainFromActor(messageJson['actor']) domain, port = getDomainFromActor(messageJson['actor'])
postFilename= \ postFilename = locatePost(baseDir, nickname, domain,
locatePost(baseDir,nickname,domain, \
messageJson['object']['object']) messageJson['object']['object'])
if postFilename: if postFilename:
undoAnnounceCollectionEntry(recentPostsCache, \ undoAnnounceCollectionEntry(recentPostsCache,
baseDir,postFilename, \ baseDir, postFilename,
messageJson['actor'], \ messageJson['actor'],
domain, debug) domain, debug)
return True return True
return False return False
def undoAnnounceCollectionEntry(recentPostsCache: {}, \
baseDir: str,postFilename: str, \ def undoAnnounceCollectionEntry(recentPostsCache: {},
baseDir: str, postFilename: str,
actor: str, domain: str, debug: bool) -> None: actor: str, domain: str, debug: bool) -> None:
"""Undoes an announce for a particular actor by removing it from """Undoes an announce for a particular actor by removing it from
the "shares" collection within a post. Note that the "shares" the "shares" collection within a post. Note that the "shares"
@ -87,8 +87,8 @@ def undoAnnounceCollectionEntry(recentPostsCache: {}, \
# remove any cached version of this announce so that the announce # remove any cached version of this announce so that the announce
# icon is changed # icon is changed
nickname = getNicknameFromActor(actor) nickname = getNicknameFromActor(actor)
cachedPostFilename= \ cachedPostFilename = getCachedPostFilename(baseDir, nickname, domain,
getCachedPostFilename(baseDir,nickname,domain,postJsonObject) postJsonObject)
if cachedPostFilename: if cachedPostFilename:
if os.path.isfile(cachedPostFilename): if os.path.isfile(cachedPostFilename):
os.remove(cachedPostFilename) os.remove(cachedPostFilename)
@ -118,21 +118,25 @@ def undoAnnounceCollectionEntry(recentPostsCache: {}, \
if announceItem['actor'] == actor: if announceItem['actor'] == actor:
if debug: if debug:
print('DEBUG: Announce was removed for ' + actor) print('DEBUG: Announce was removed for ' + actor)
postJsonObject['object']['shares']['items'].remove(announceItem) anIt = announceItem
postJsonObject['object']['shares']['items'].remove(anIt)
itemFound = True itemFound = True
break break
if itemFound: if itemFound:
if totalItems == 1: if totalItems == 1:
if debug: if debug:
print('DEBUG: shares (announcements) was removed from post') print('DEBUG: shares (announcements) ' +
'was removed from post')
del postJsonObject['object']['shares'] del postJsonObject['object']['shares']
else: else:
postJsonObject['object']['shares']['totalItems']= \ itlen = len(postJsonObject['object']['shares']['items'])
len(postJsonObject['object']['shares']['items']) postJsonObject['object']['shares']['totalItems'] = itlen
saveJson(postJsonObject, postFilename) saveJson(postJsonObject, postFilename)
def updateAnnounceCollection(recentPostsCache: {}, \
baseDir: str,postFilename: str, \ def updateAnnounceCollection(recentPostsCache: {},
baseDir: str, postFilename: str,
actor: str, domain: str, debug: bool) -> None: actor: str, domain: str, debug: bool) -> None:
"""Updates the announcements collection within a post """Updates the announcements collection within a post
Confusingly this is known as "shares", but isn't the Confusingly this is known as "shares", but isn't the
@ -144,8 +148,8 @@ def updateAnnounceCollection(recentPostsCache: {}, \
# remove any cached version of this announce so that the announce # remove any cached version of this announce so that the announce
# icon is changed # icon is changed
nickname = getNicknameFromActor(actor) nickname = getNicknameFromActor(actor)
cachedPostFilename= \ cachedPostFilename = getCachedPostFilename(baseDir, nickname, domain,
getCachedPostFilename(baseDir,nickname,domain,postJsonObject) postJsonObject)
if cachedPostFilename: if cachedPostFilename:
if os.path.isfile(cachedPostFilename): if os.path.isfile(cachedPostFilename):
os.remove(cachedPostFilename) os.remove(cachedPostFilename)
@ -154,14 +158,14 @@ def updateAnnounceCollection(recentPostsCache: {}, \
if not postJsonObject.get('object'): if not postJsonObject.get('object'):
if debug: if debug:
pprint(postJsonObject) pprint(postJsonObject)
print('DEBUG: post '+announceUrl+' has no object') print('DEBUG: post ' + postFilename + ' has no object')
return return
if not isinstance(postJsonObject['object'], dict): if not isinstance(postJsonObject['object'], dict):
return return
postUrl = postJsonObject['id'].replace('/activity', '') + '/shares' postUrl = postJsonObject['id'].replace('/activity', '') + '/shares'
if not postJsonObject['object'].get('shares'): if not postJsonObject['object'].get('shares'):
if debug: if debug:
print('DEBUG: Adding initial shares (announcements) to '+ \ print('DEBUG: Adding initial shares (announcements) to ' +
postUrl) postUrl)
announcementsJson = { announcementsJson = {
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
@ -176,7 +180,8 @@ def updateAnnounceCollection(recentPostsCache: {}, \
postJsonObject['object']['shares'] = announcementsJson postJsonObject['object']['shares'] = announcementsJson
else: else:
if postJsonObject['object']['shares'].get('items'): if postJsonObject['object']['shares'].get('items'):
for announceItem in postJsonObject['object']['shares']['items']: sharesItems = postJsonObject['object']['shares']['items']
for announceItem in sharesItems:
if announceItem.get('actor'): if announceItem.get('actor'):
if announceItem['actor'] == actor: if announceItem['actor'] == actor:
return return
@ -185,17 +190,19 @@ def updateAnnounceCollection(recentPostsCache: {}, \
'actor': actor 'actor': actor
} }
postJsonObject['object']['shares']['items'].append(newAnnounce) postJsonObject['object']['shares']['items'].append(newAnnounce)
postJsonObject['object']['shares']['totalItems']= \ itlen = len(postJsonObject['object']['shares']['items'])
len(postJsonObject['object']['shares']['items']) postJsonObject['object']['shares']['totalItems'] = itlen
else: else:
if debug: if debug:
print('DEBUG: shares (announcements) section of post has no items list') print('DEBUG: shares (announcements) section of post ' +
'has no items list')
if debug: if debug:
print('DEBUG: saving post with shares (announcements) added') print('DEBUG: saving post with shares (announcements) added')
pprint(postJsonObject) pprint(postJsonObject)
saveJson(postJsonObject, postFilename) saveJson(postJsonObject, postFilename)
def announcedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool: def announcedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool:
"""Returns True if the given post is announced by the given person """Returns True if the given post is announced by the given person
""" """
@ -212,13 +219,14 @@ def announcedByPerson(postJsonObject: {},nickname: str,domain: str) -> bool:
return True return True
return False return False
def createAnnounce(session,baseDir: str,federationList: [], \
nickname: str,domain: str,port: int, \ def createAnnounce(session, baseDir: str, federationList: [],
toUrl: str,ccUrl: str,httpPrefix: str, \ nickname: str, domain: str, port: int,
objectUrl: str,saveToFile: bool, \ toUrl: str, ccUrl: str, httpPrefix: str,
clientToServer: bool, \ objectUrl: str, saveToFile: bool,
sendThreads: [],postLog: [], \ clientToServer: bool,
personCache: {},cachedWebfingers: {}, \ sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
debug: bool, projectVersion: str) -> {}: debug: bool, projectVersion: str) -> {}:
"""Creates an announce message """Creates an announce message
Typically toUrl will be https://www.w3.org/ns/activitystreams#Public Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
@ -238,12 +246,14 @@ def createAnnounce(session,baseDir: str,federationList: [], \
fullDomain = domain + ':' + str(port) fullDomain = domain + ':' + str(port)
statusNumber, published = getStatusNumber() statusNumber, published = getStatusNumber()
newAnnounceId= \ newAnnounceId = httpPrefix + '://' + fullDomain + \
httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber '/users/' + nickname + '/statuses/' + statusNumber
atomUriStr = httpPrefix + '://' + fullDomain + '/users/' + nickname + \
'/statuses/' + statusNumber
newAnnounce = { newAnnounce = {
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname, 'actor': httpPrefix+'://'+fullDomain+'/users/'+nickname,
'atomUri': httpPrefix+'://'+fullDomain+'/users/'+nickname+'/statuses/'+statusNumber, 'atomUri': atomUriStr,
'cc': [], 'cc': [],
'id': newAnnounceId+'/activity', 'id': newAnnounceId+'/activity',
'object': objectUrl, 'object': objectUrl,
@ -269,20 +279,21 @@ def createAnnounce(session,baseDir: str,federationList: [], \
announceDomain, announcePort = getDomainFromActor(objectUrl) announceDomain, announcePort = getDomainFromActor(objectUrl)
if announceNickname and announceDomain: if announceNickname and announceDomain:
sendSignedJson(newAnnounce,session,baseDir, \ sendSignedJson(newAnnounce, session, baseDir,
nickname,domain,port, \ nickname, domain, port,
announceNickname,announceDomain,announcePort,None, \ announceNickname, announceDomain, announcePort, None,
httpPrefix,True,clientToServer,federationList, \ httpPrefix, True, clientToServer, federationList,
sendThreads,postLog,cachedWebfingers,personCache, \ sendThreads, postLog, cachedWebfingers, personCache,
debug, projectVersion) debug, projectVersion)
return newAnnounce return newAnnounce
def announcePublic(session,baseDir: str,federationList: [], \
nickname: str,domain: str,port: int,httpPrefix: str, \ def announcePublic(session, baseDir: str, federationList: [],
objectUrl: str,clientToServer: bool, \ nickname: str, domain: str, port: int, httpPrefix: str,
sendThreads: [],postLog: [], \ objectUrl: str, clientToServer: bool,
personCache: {},cachedWebfingers: {}, \ sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
debug: bool, projectVersion: str) -> {}: debug: bool, projectVersion: str) -> {}:
"""Makes a public announcement """Makes a public announcement
""" """
@ -293,22 +304,24 @@ def announcePublic(session,baseDir: str,federationList: [], \
fromDomain = domain + ':' + str(port) fromDomain = domain + ':' + str(port)
toUrl = 'https://www.w3.org/ns/activitystreams#Public' toUrl = 'https://www.w3.org/ns/activitystreams#Public'
ccUrl=httpPrefix+'://'+fromDomain+'/users/'+nickname+'/followers' ccUrl = httpPrefix + '://' + fromDomain + '/users/' + nickname + \
return createAnnounce(session,baseDir,federationList, \ '/followers'
nickname,domain,port, \ return createAnnounce(session, baseDir, federationList,
toUrl,ccUrl,httpPrefix, \ nickname, domain, port,
objectUrl,True,clientToServer, \ toUrl, ccUrl, httpPrefix,
sendThreads,postLog, \ objectUrl, True, clientToServer,
personCache,cachedWebfingers, \ sendThreads, postLog,
personCache, cachedWebfingers,
debug, projectVersion) debug, projectVersion)
def repeatPost(session,baseDir: str,federationList: [], \
nickname: str, domain: str, port: int, httpPrefix: str, \ def repeatPost(session, baseDir: str, federationList: [],
announceNickname: str, announceDomain: str, \ nickname: str, domain: str, port: int, httpPrefix: str,
announcePort: int, announceHttpsPrefix: str, \ announceNickname: str, announceDomain: str,
announceStatusNumber: int,clientToServer: bool, \ announcePort: int, announceHttpsPrefix: str,
sendThreads: [],postLog: [], \ announceStatusNumber: int, clientToServer: bool,
personCache: {},cachedWebfingers: {}, \ sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
debug: bool, projectVersion: str) -> {}: debug: bool, projectVersion: str) -> {}:
"""Repeats a given status post """Repeats a given status post
""" """
@ -321,20 +334,21 @@ def repeatPost(session,baseDir: str,federationList: [], \
objectUrl = announceHttpsPrefix + '://' + announcedDomain + '/users/' + \ objectUrl = announceHttpsPrefix + '://' + announcedDomain + '/users/' + \
announceNickname + '/statuses/' + str(announceStatusNumber) announceNickname + '/statuses/' + str(announceStatusNumber)
return announcePublic(session,baseDir,federationList, \ return announcePublic(session, baseDir, federationList,
nickname,domain,port,httpPrefix, \ nickname, domain, port, httpPrefix,
objectUrl,clientToServer, \ objectUrl, clientToServer,
sendThreads,postLog, \ sendThreads, postLog,
personCache,cachedWebfingers, \ personCache, cachedWebfingers,
debug, projectVersion) debug, projectVersion)
def undoAnnounce(session,baseDir: str,federationList: [], \
nickname: str,domain: str,port: int, \ def undoAnnounce(session, baseDir: str, federationList: [],
toUrl: str,ccUrl: str,httpPrefix: str, \ nickname: str, domain: str, port: int,
objectUrl: str,saveToFile: bool, \ toUrl: str, ccUrl: str, httpPrefix: str,
clientToServer: bool, \ objectUrl: str, saveToFile: bool,
sendThreads: [],postLog: [], \ clientToServer: bool,
personCache: {},cachedWebfingers: {}, \ sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
debug: bool) -> {}: debug: bool) -> {}:
"""Undoes an announce message """Undoes an announce message
Typically toUrl will be https://www.w3.org/ns/activitystreams#Public Typically toUrl will be https://www.w3.org/ns/activitystreams#Public
@ -381,20 +395,22 @@ def undoAnnounce(session,baseDir: str,federationList: [], \
announceDomain, announcePort = getDomainFromActor(objectUrl) announceDomain, announcePort = getDomainFromActor(objectUrl)
if announceNickname and announceDomain: if announceNickname and announceDomain:
sendSignedJson(newUndoAnnounce,session,baseDir, \ sendSignedJson(newUndoAnnounce, session, baseDir,
nickname,domain,port, \ nickname, domain, port,
announceNickname,announceDomain,announcePort, \ announceNickname, announceDomain, announcePort,
'https://www.w3.org/ns/activitystreams#Public', \ 'https://www.w3.org/ns/activitystreams#Public',
httpPrefix,True,clientToServer,federationList, \ httpPrefix, True, clientToServer, federationList,
sendThreads,postLog,cachedWebfingers,personCache,debug) sendThreads, postLog, cachedWebfingers,
personCache, debug)
return newUndoAnnounce return newUndoAnnounce
def undoAnnouncePublic(session,baseDir: str,federationList: [], \
nickname: str,domain: str,port: int,httpPrefix: str, \ def undoAnnouncePublic(session, baseDir: str, federationList: [],
objectUrl: str,clientToServer: bool, \ nickname: str, domain: str, port: int, httpPrefix: str,
sendThreads: [],postLog: [], \ objectUrl: str, clientToServer: bool,
personCache: {},cachedWebfingers: {}, \ sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
debug: bool) -> {}: debug: bool) -> {}:
"""Undoes a public announcement """Undoes a public announcement
""" """
@ -405,22 +421,24 @@ def undoAnnouncePublic(session,baseDir: str,federationList: [], \
fromDomain = domain + ':' + str(port) fromDomain = domain + ':' + str(port)
toUrl = 'https://www.w3.org/ns/activitystreams#Public' toUrl = 'https://www.w3.org/ns/activitystreams#Public'
ccUrl=httpPrefix+'://'+fromDomain+'/users/'+nickname+'/followers' ccUrl = httpPrefix + '://' + fromDomain + '/users/' + nickname + \
return undoAnnounce(session,baseDir,federationList, \ '/followers'
nickname,domain,port, \ return undoAnnounce(session, baseDir, federationList,
toUrl,ccUrl,httpPrefix, \ nickname, domain, port,
objectUrl,True,clientToServer, \ toUrl, ccUrl, httpPrefix,
sendThreads,postLog, \ objectUrl, True, clientToServer,
personCache,cachedWebfingers, \ sendThreads, postLog,
personCache, cachedWebfingers,
debug) debug)
def undoRepeatPost(session,baseDir: str,federationList: [], \
nickname: str,domain: str,port: int,httpPrefix: str, \ def undoRepeatPost(session, baseDir: str, federationList: [],
announceNickname: str,announceDomain: str, \ nickname: str, domain: str, port: int, httpPrefix: str,
announcePort: int,announceHttpsPrefix: str, \ announceNickname: str, announceDomain: str,
announceStatusNumber: int,clientToServer: bool, \ announcePort: int, announceHttpsPrefix: str,
sendThreads: [],postLog: [], \ announceStatusNumber: int, clientToServer: bool,
personCache: {},cachedWebfingers: {}, \ sendThreads: [], postLog: [],
personCache: {}, cachedWebfingers: {},
debug: bool) -> {}: debug: bool) -> {}:
"""Undoes a status post repeat """Undoes a status post repeat
""" """
@ -433,18 +451,19 @@ def undoRepeatPost(session,baseDir: str,federationList: [], \
objectUrl = announceHttpsPrefix + '://' + announcedDomain + '/users/' + \ objectUrl = announceHttpsPrefix + '://' + announcedDomain + '/users/' + \
announceNickname + '/statuses/' + str(announceStatusNumber) announceNickname + '/statuses/' + str(announceStatusNumber)
return undoAnnouncePublic(session,baseDir,federationList, \ return undoAnnouncePublic(session, baseDir, federationList,
nickname,domain,port,httpPrefix, \ nickname, domain, port, httpPrefix,
objectUrl,clientToServer, \ objectUrl, clientToServer,
sendThreads,postLog, \ sendThreads, postLog,
personCache,cachedWebfingers, \ personCache, cachedWebfingers,
debug) debug)
def sendAnnounceViaServer(baseDir: str,session, \
def sendAnnounceViaServer(baseDir: str, session,
fromNickname: str, password: str, fromNickname: str, password: str,
fromDomain: str,fromPort: int, \ fromDomain: str, fromPort: int,
httpPrefix: str,repeatObjectUrl: str, \ httpPrefix: str, repeatObjectUrl: str,
cachedWebfingers: {},personCache: {}, \ cachedWebfingers: {}, personCache: {},
debug: bool, projectVersion: str) -> {}: debug: bool, projectVersion: str) -> {}:
"""Creates an announce message via c2s """Creates an announce message via c2s
""" """
@ -452,8 +471,6 @@ def sendAnnounceViaServer(baseDir: str,session, \
print('WARN: No session for sendAnnounceViaServer') print('WARN: No session for sendAnnounceViaServer')
return 6 return 6
withDigest=True
fromDomainFull = fromDomain fromDomainFull = fromDomain
if fromPort: if fromPort:
if fromPort != 80 and fromPort != 443: if fromPort != 80 and fromPort != 443:
@ -461,11 +478,11 @@ def sendAnnounceViaServer(baseDir: str,session, \
fromDomainFull = fromDomain + ':' + str(fromPort) fromDomainFull = fromDomain + ':' + str(fromPort)
toUrl = 'https://www.w3.org/ns/activitystreams#Public' toUrl = 'https://www.w3.org/ns/activitystreams#Public'
ccUrl=httpPrefix+'://'+fromDomainFull+'/users/'+fromNickname+'/followers' ccUrl = httpPrefix + '://' + fromDomainFull + '/users/' + fromNickname + \
'/followers'
statusNumber, published = getStatusNumber() statusNumber, published = getStatusNumber()
newAnnounceId= \ newAnnounceId = httpPrefix + '://' + fromDomainFull + '/users/' + \
httpPrefix+'://'+fromDomainFull+'/users/'+ \
fromNickname + '/statuses/' + statusNumber fromNickname + '/statuses/' + statusNumber
newAnnounceJson = { newAnnounceJson = {
"@context": "https://www.w3.org/ns/activitystreams", "@context": "https://www.w3.org/ns/activitystreams",
@ -482,8 +499,8 @@ def sendAnnounceViaServer(baseDir: str,session, \
handle = httpPrefix + '://' + fromDomainFull + '/@' + fromNickname handle = httpPrefix + '://' + fromDomainFull + '/@' + fromNickname
# lookup the inbox for the To handle # lookup the inbox for the To handle
wfRequest= \ wfRequest = webfingerHandle(session, handle, httpPrefix,
webfingerHandle(session,handle,httpPrefix,cachedWebfingers, \ cachedWebfingers,
fromDomain, projectVersion) fromDomain, projectVersion)
if not wfRequest: if not wfRequest:
if debug: if debug:
@ -493,9 +510,13 @@ def sendAnnounceViaServer(baseDir: str,session, \
postToBox = 'outbox' postToBox = 'outbox'
# get the actor inbox for the To handle # get the actor inbox for the To handle
inboxUrl,pubKeyId,pubKey,fromPersonId,sharedInbox,capabilityAcquisition,avatarUrl,displayName= \ (inboxUrl, pubKeyId, pubKey, fromPersonId,
getPersonBox(baseDir,session,wfRequest,personCache, \ sharedInbox, capabilityAcquisition,
projectVersion,httpPrefix,fromNickname,fromDomain,postToBox) avatarUrl, displayName) = getPersonBox(baseDir, session, wfRequest,
personCache,
projectVersion, httpPrefix,
fromNickname, fromDomain,
postToBox)
if not inboxUrl: if not inboxUrl:
if debug: if debug:
@ -509,12 +530,14 @@ def sendAnnounceViaServer(baseDir: str,session, \
authHeader = createBasicAuthHeader(fromNickname, password) authHeader = createBasicAuthHeader(fromNickname, password)
headers = { headers = {
'host': fromDomain, \ 'host': fromDomain,
'Content-type': 'application/json', \ 'Content-type': 'application/json',
'Authorization': authHeader 'Authorization': authHeader
} }
postResult= \ postResult = postJson(session, newAnnounceJson, [], inboxUrl,
postJson(session,newAnnounceJson,[],inboxUrl,headers,"inbox:write") headers, "inbox:write")
if not postResult:
print('WARN: Announce not posted')
if debug: if debug:
print('DEBUG: c2s POST announce success') print('DEBUG: c2s POST announce success')