epicyon/epicyon.py

1499 lines
57 KiB
Python
Raw Normal View History

2019-06-28 18:55:29 +00:00
__filename__ = "epicyon.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
2019-08-29 13:35:29 +00:00
__version__ = "1.0.0"
2019-06-28 18:55:29 +00:00
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
from person import createPerson
2019-10-04 12:39:46 +00:00
from person import createGroup
2019-07-05 11:27:18 +00:00
from person import createSharedInbox
from person import createCapabilitiesInbox
from person import setDisplayNickname
2019-06-28 20:00:25 +00:00
from person import setBio
2019-07-12 14:31:56 +00:00
from person import setProfileImage
2019-08-13 11:59:38 +00:00
from person import removeAccount
2019-11-05 10:40:44 +00:00
from person import activateAccount
2019-11-05 10:37:37 +00:00
from person import deactivateAccount
2019-07-19 10:01:24 +00:00
from skills import setSkillLevel
2019-07-18 15:09:23 +00:00
from roles import setRole
from person import setOrganizationScheme
2019-06-28 18:55:29 +00:00
from webfinger import webfingerHandle
2019-07-02 09:25:29 +00:00
from posts import getPosts
2019-06-29 10:08:59 +00:00
from posts import createPublicPost
2019-06-29 11:47:33 +00:00
from posts import deleteAllPosts
2019-06-29 13:17:02 +00:00
from posts import createOutbox
2019-06-29 13:44:21 +00:00
from posts import archivePosts
2019-07-16 16:43:28 +00:00
from posts import sendPostViaServer
2019-07-03 10:31:02 +00:00
from posts import getPublicPostsOfPerson
2019-07-05 15:53:26 +00:00
from posts import getUserUrl
2019-07-12 20:43:55 +00:00
from posts import archivePosts
2019-06-28 18:55:29 +00:00
from session import createSession
2019-06-29 16:47:37 +00:00
from session import getJson
2019-07-14 19:57:05 +00:00
from blocking import addBlock
from blocking import removeBlock
2019-07-14 20:50:27 +00:00
from filters import addFilter
from filters import removeFilter
2019-06-28 18:55:29 +00:00
import json
2019-06-30 22:56:37 +00:00
import os
2019-07-04 22:51:40 +00:00
import shutil
2019-06-28 18:55:29 +00:00
import sys
import requests
2019-07-19 18:12:50 +00:00
import time
2019-06-28 18:55:29 +00:00
from pprint import pprint
2019-06-30 20:14:03 +00:00
from tests import testHttpsig
2019-06-28 18:55:29 +00:00
from daemon import runDaemon
2019-06-28 19:52:35 +00:00
import socket
2019-06-29 18:23:13 +00:00
from follow import clearFollows
2019-06-29 20:21:37 +00:00
from follow import clearFollowers
2019-06-29 18:23:13 +00:00
from follow import followerOfPerson
from follow import unfollowPerson
from follow import unfollowerOfPerson
from follow import getFollowersOfPerson
2019-06-30 21:20:02 +00:00
from tests import testPostMessageBetweenServers
2019-07-06 13:49:25 +00:00
from tests import testFollowBetweenServers
2019-07-16 10:19:04 +00:00
from tests import testClientToServer
2019-06-30 21:20:02 +00:00
from tests import runAllTests
2019-07-05 09:20:54 +00:00
from config import setConfigParam
from config import getConfigParam
2019-07-05 09:44:15 +00:00
from auth import storeBasicCredentials
2019-07-05 09:49:57 +00:00
from auth import removePassword
2019-07-05 11:27:18 +00:00
from auth import createPassword
2019-07-09 15:51:31 +00:00
from utils import getDomainFromActor
from utils import getNicknameFromActor
2019-07-27 22:48:34 +00:00
from utils import followPerson
from utils import validNickname
2019-07-12 20:43:55 +00:00
from media import archiveMedia
2019-08-30 15:50:20 +00:00
from media import getAttachmentMediaType
2019-07-17 17:16:48 +00:00
from delete import sendDeleteViaServer
2019-07-17 19:04:00 +00:00
from like import sendLikeViaServer
from like import sendUndoLikeViaServer
2019-07-17 22:09:09 +00:00
from blocking import sendBlockViaServer
from blocking import sendUndoBlockViaServer
2019-07-18 15:09:23 +00:00
from roles import sendRoleViaServer
2019-07-19 10:01:24 +00:00
from skills import sendSkillViaServer
2019-07-19 11:38:37 +00:00
from availability import setAvailability
from availability import sendAvailabilityViaServer
2019-07-20 18:25:40 +00:00
from manualapprove import manualDenyFollowRequest
from manualapprove import manualApproveFollowRequest
2019-07-23 21:47:08 +00:00
from shares import sendShareViaServer
from shares import sendUndoShareViaServer
2019-07-23 22:12:19 +00:00
from shares import addShare
2019-11-23 13:04:11 +00:00
from theme import setTheme
2019-07-03 09:24:55 +00:00
import argparse
2019-06-30 21:20:02 +00:00
2019-07-03 09:24:55 +00:00
def str2bool(v):
if isinstance(v, bool):
return v
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return False
else:
raise argparse.ArgumentTypeError('Boolean value expected.')
2019-07-05 09:20:54 +00:00
2019-07-03 09:24:55 +00:00
parser = argparse.ArgumentParser(description='ActivityPub Server')
2019-07-09 15:51:31 +00:00
parser.add_argument('-n','--nickname', dest='nickname', type=str,default=None, \
help='Nickname of the account to use')
parser.add_argument('--fol','--follow', dest='follow', type=str,default=None, \
help='Handle of account to follow. eg. nickname@domain')
2019-07-17 12:25:02 +00:00
parser.add_argument('--unfol','--unfollow', dest='unfollow', type=str,default=None, \
help='Handle of account stop following. eg. nickname@domain')
2019-07-06 20:19:49 +00:00
parser.add_argument('-d','--domain', dest='domain', type=str,default=None, \
2019-07-03 09:24:55 +00:00
help='Domain name of the server')
2019-07-06 20:19:49 +00:00
parser.add_argument('-p','--port', dest='port', type=int,default=None, \
2019-07-03 09:24:55 +00:00
help='Port number to run on')
2019-08-14 13:52:19 +00:00
parser.add_argument('--proxy', dest='proxyPort', type=int,default=None, \
help='Proxy port number to run on')
2019-07-06 20:19:49 +00:00
parser.add_argument('--path', dest='baseDir', \
type=str,default=os.getcwd(), \
2019-07-03 09:24:55 +00:00
help='Directory in which to store posts')
2019-11-11 17:53:06 +00:00
parser.add_argument('--language', dest='language', \
2019-11-11 17:49:08 +00:00
type=str,default=None, \
help='Language code, eg. en/fr/de/es')
2019-07-06 20:19:49 +00:00
parser.add_argument('-a','--addaccount', dest='addaccount', \
type=str,default=None, \
2019-07-04 22:44:32 +00:00
help='Adds a new account')
2019-10-04 12:39:46 +00:00
parser.add_argument('-g','--addgroup', dest='addgroup', \
type=str,default=None, \
help='Adds a new group')
2019-11-05 10:40:44 +00:00
parser.add_argument('--activate', dest='activate', \
type=str,default=None, \
help='Activate a previously deactivated account')
2019-11-05 10:37:37 +00:00
parser.add_argument('--deactivate', dest='deactivate', \
type=str,default=None, \
help='Deactivate an account')
2019-07-06 20:19:49 +00:00
parser.add_argument('-r','--rmaccount', dest='rmaccount', \
type=str,default=None, \
2019-07-04 22:50:40 +00:00
help='Remove an account')
2019-10-04 12:59:31 +00:00
parser.add_argument('--rmgroup', dest='rmgroup', \
type=str,default=None, \
help='Remove a group')
2019-07-06 20:19:49 +00:00
parser.add_argument('--pass','--password', dest='password', \
type=str,default=None, \
2019-07-04 22:44:32 +00:00
help='Set a password for an account')
2019-07-06 20:19:49 +00:00
parser.add_argument('--chpass','--changepassword', \
nargs='+',dest='changepassword', \
2019-07-05 09:44:15 +00:00
help='Change the password for an account')
2019-07-06 20:19:49 +00:00
parser.add_argument('--actor', dest='actor', type=str,default=None, \
2019-07-05 15:53:26 +00:00
help='Show the json actor the given handle')
2019-07-06 20:19:49 +00:00
parser.add_argument('--posts', dest='posts', type=str,default=None, \
2019-07-03 10:31:02 +00:00
help='Show posts for the given handle')
2019-07-06 20:19:49 +00:00
parser.add_argument('--postsraw', dest='postsraw', type=str,default=None, \
2019-07-03 11:24:38 +00:00
help='Show raw json of posts for the given handle')
2019-07-12 10:53:49 +00:00
parser.add_argument('--json', dest='json', type=str,default=None, \
help='Show the json for a given activitypub url')
2019-07-06 20:19:49 +00:00
parser.add_argument('-f','--federate', nargs='+',dest='federationList', \
2019-07-03 09:24:55 +00:00
help='Specify federation list separated by spaces')
2019-07-06 20:19:49 +00:00
parser.add_argument("--debug", type=str2bool, nargs='?', \
const=True, default=False, \
help="Show debug messages")
2019-09-25 09:22:10 +00:00
parser.add_argument("--authenticatedFetch", type=str2bool, nargs='?', \
const=True, default=False, \
help="Enable authentication on GET requests for json (authenticated fetch)")
parser.add_argument("--instanceOnlySkillsSearch", type=str2bool, nargs='?', \
const=True, default=False, \
help="Skills searches only return results from this instance")
2019-07-06 20:19:49 +00:00
parser.add_argument("--http", type=str2bool, nargs='?', \
const=True, default=False, \
help="Use http only")
parser.add_argument("--dat", type=str2bool, nargs='?', \
const=True, default=False, \
help="Use dat protocol only")
parser.add_argument("--tor", type=str2bool, nargs='?', \
const=True, default=False, \
help="Route via Tor")
parser.add_argument("--tests", type=str2bool, nargs='?', \
const=True, default=False, \
help="Run unit tests")
parser.add_argument("--testsnetwork", type=str2bool, nargs='?', \
const=True, default=False, \
help="Run network unit tests")
parser.add_argument("--testdata", type=str2bool, nargs='?', \
const=True, default=False, \
help="Generate some data for testing purposes")
parser.add_argument("--ocap", type=str2bool, nargs='?', \
const=True, default=False, \
help="Always strictly enforce object capabilities")
2019-07-09 17:54:08 +00:00
parser.add_argument("--noreply", type=str2bool, nargs='?', \
const=True, default=False, \
help="Default capabilities don't allow replies on posts")
parser.add_argument("--nolike", type=str2bool, nargs='?', \
const=True, default=False, \
help="Default capabilities don't allow likes/favourites on posts")
2019-07-09 18:11:23 +00:00
parser.add_argument("--nopics", type=str2bool, nargs='?', \
const=True, default=False, \
help="Default capabilities don't allow attached pictures")
parser.add_argument("--noannounce","--norepeat", type=str2bool, nargs='?', \
const=True, default=False, \
help="Default capabilities don't allow announce/repeat")
parser.add_argument("--cw", type=str2bool, nargs='?', \
const=True, default=False, \
help="Default capabilities don't allow posts without content warnings")
2019-07-12 14:31:56 +00:00
parser.add_argument('--icon','--avatar', dest='avatar', type=str,default=None, \
help='Set the avatar filename for an account')
parser.add_argument('--image','--background', dest='backgroundImage', type=str,default=None, \
help='Set the profile background image for an account')
2019-07-12 20:43:55 +00:00
parser.add_argument('--archive', dest='archive', type=str,default=None, \
help='Archive old files to the given directory')
parser.add_argument('--archiveweeks', dest='archiveWeeks', type=str,default=None, \
help='Specify the number of weeks after which data will be archived')
parser.add_argument('--maxposts', dest='archiveMaxPosts', type=str,default=None, \
help='Maximum number of posts in in/outbox')
2019-07-12 22:29:10 +00:00
parser.add_argument('--message', dest='message', type=str,default=None, \
help='Message content')
2019-07-17 17:29:33 +00:00
parser.add_argument('--delete', dest='delete', type=str,default=None, \
help='Delete a specified post')
parser.add_argument("--allowdeletion", type=str2bool, nargs='?', \
2019-07-17 17:44:26 +00:00
const=True, default=False, \
help="Do not allow deletions")
2019-07-16 20:08:30 +00:00
parser.add_argument('--repeat','--announce', dest='announce', type=str,default=None, \
help='Announce/repeat a url')
2019-07-17 18:33:41 +00:00
parser.add_argument('--favorite','--like', dest='like', type=str,default=None, \
help='Like a url')
2019-07-17 19:04:00 +00:00
parser.add_argument('--undolike','--unlike', dest='undolike', type=str,default=None, \
help='Undo a like of a url')
2019-07-19 18:12:50 +00:00
parser.add_argument('--sendto', dest='sendto', type=str,default=None, \
help='Address to send a post to')
2019-07-12 22:29:10 +00:00
parser.add_argument('--attach', dest='attach', type=str,default=None, \
help='File to attach to a post')
parser.add_argument('--imagedescription', dest='imageDescription', type=str,default=None, \
help='Description of an attached image')
parser.add_argument("--blurhash", type=str2bool, nargs='?', \
const=True, default=False, \
help="Create blurhash for an image")
2019-07-15 14:45:57 +00:00
parser.add_argument('--warning','--warn','--cwsubject','--subject', dest='subject', type=str,default=None, \
2019-07-12 22:29:10 +00:00
help='Subject of content warning')
parser.add_argument('--reply','--replyto', dest='replyto', type=str,default=None, \
help='Url of post to reply to')
2019-07-13 09:22:25 +00:00
parser.add_argument("--followersonly", type=str2bool, nargs='?', \
const=True, default=True, \
help="Send to followers only")
parser.add_argument("--followerspending", type=str2bool, nargs='?', \
2019-07-20 18:50:02 +00:00
const=True, default=False, \
help="Show a list of followers pending")
parser.add_argument('--approve', dest='approve', type=str,default=None, \
help='Approve a follow request')
parser.add_argument('--deny', dest='deny', type=str,default=None, \
help='Deny a follow request')
2019-07-13 09:22:25 +00:00
parser.add_argument("-c","--client", type=str2bool, nargs='?', \
const=True, default=False, \
help="Use as an ActivityPub client")
2019-07-13 21:00:12 +00:00
parser.add_argument('--maxreplies', dest='maxReplies', type=int,default=64, \
help='Maximum number of replies to a post')
2019-09-30 10:15:20 +00:00
parser.add_argument('--maxMentions','--hellthread', dest='maxMentions', type=int,default=10, \
help='Maximum number of mentions within a post')
2019-11-16 14:49:21 +00:00
parser.add_argument('--maxEmoji','--maxemoji', dest='maxEmoji', type=int,default=10, \
help='Maximum number of emoji within a post')
parser.add_argument('--role', dest='role', type=str,default=None, \
help='Set a role for a person')
parser.add_argument('--organization','--project', dest='project', type=str,default=None, \
help='Set a project for a person')
parser.add_argument('--skill', dest='skill', type=str,default=None, \
help='Set a skill for a person')
parser.add_argument('--level', dest='skillLevelPercent', type=int,default=None, \
help='Set a skill level for a person as a percentage, or zero to remove')
2019-07-14 13:30:59 +00:00
parser.add_argument('--status','--availability', dest='availability', type=str,default=None, \
help='Set an availability status')
2019-07-14 19:57:05 +00:00
parser.add_argument('--block', dest='block', type=str,default=None, \
help='Block a particular address')
parser.add_argument('--unblock', dest='unblock', type=str,default=None, \
help='Remove a block on a particular address')
2019-07-18 16:33:36 +00:00
parser.add_argument('--delegate', dest='delegate', type=str,default=None, \
help='Address of an account to delegate a role to')
2019-07-18 16:48:35 +00:00
parser.add_argument('--undodelegate','--undelegate', dest='undelegate', type=str,default=None, \
help='Removes a delegated role for the given address')
2019-07-14 20:50:27 +00:00
parser.add_argument('--filter', dest='filterStr', type=str,default=None, \
help='Adds a word or phrase which if present will cause a message to be ignored')
parser.add_argument('--unfilter', dest='unfilterStr', type=str,default=None, \
help='Remove a filter on a particular word or phrase')
parser.add_argument('--domainmax', dest='domainMaxPostsPerDay', type=int,default=8640, \
2019-07-15 10:22:19 +00:00
help='Maximum number of received posts from a domain per day')
parser.add_argument('--accountmax', dest='accountMaxPostsPerDay', type=int,default=8640, \
2019-07-15 10:22:19 +00:00
help='Maximum number of received posts from an account per day')
2019-07-23 21:45:53 +00:00
parser.add_argument('--itemName', dest='itemName', type=str,default=None, \
2019-07-23 21:39:07 +00:00
help='Name of an item being shared')
2019-07-23 21:45:53 +00:00
parser.add_argument('--undoItemName', dest='undoItemName', type=str,default=None, \
help='Name of an shared item to remove')
2019-07-23 21:39:07 +00:00
parser.add_argument('--summary', dest='summary', type=str,default=None, \
help='Description of an item being shared')
parser.add_argument('--itemImage', dest='itemImage', type=str,default=None, \
help='Filename of an image for an item being shared')
parser.add_argument('--itemType', dest='itemType', type=str,default=None, \
help='Type of item being shared')
parser.add_argument('--itemCategory', dest='itemCategory', type=str,default=None, \
help='Category of item being shared')
parser.add_argument('--location', dest='location', type=str,default=None, \
help='Location/City of item being shared')
parser.add_argument('--duration', dest='duration', type=str,default=None, \
help='Duration for which to share an item')
2019-08-08 10:50:58 +00:00
parser.add_argument('--registration', dest='registration', type=str,default=None, \
help='Whether new registrations are open or closed')
2019-11-15 22:04:26 +00:00
parser.add_argument("--nosharedinbox", type=str2bool, nargs='?', \
2019-11-15 21:43:20 +00:00
const=True, default=False, \
2019-11-15 22:07:06 +00:00
help='Disable shared inbox')
2019-08-08 10:50:58 +00:00
parser.add_argument('--maxregistrations', dest='maxRegistrations', type=int,default=None, \
help='The maximum number of new registrations')
parser.add_argument("--resetregistrations", type=str2bool, nargs='?', \
const=True, default=False, \
help="Reset the number of remaining registrations")
2019-07-03 09:24:55 +00:00
args = parser.parse_args()
2019-07-03 10:31:02 +00:00
2019-07-03 16:14:45 +00:00
debug=False
if args.debug:
debug=True
2019-07-03 09:24:55 +00:00
if args.tests:
runAllTests()
sys.exit()
2019-07-03 10:31:02 +00:00
if args.testsnetwork:
print('Network Tests')
2019-07-18 16:48:35 +00:00
testPostMessageBetweenServers()
testFollowBetweenServers()
2019-07-16 10:19:04 +00:00
testClientToServer()
2019-07-27 22:59:01 +00:00
print('All tests succeeded')
2019-07-03 10:31:02 +00:00
sys.exit()
2019-07-05 15:53:26 +00:00
2019-07-19 13:32:58 +00:00
httpPrefix='https'
if args.http:
httpPrefix='http'
2019-08-20 10:10:33 +00:00
baseDir=args.baseDir
if baseDir.endswith('/'):
print("--path option should not end with '/'")
sys.exit()
2019-07-03 10:33:55 +00:00
if args.posts:
2019-07-05 15:53:26 +00:00
if '@' not in args.posts:
print('Syntax: --posts nickname@domain')
2019-07-19 16:59:14 +00:00
sys.exit()
if not args.http:
args.port=443
2019-07-03 10:33:55 +00:00
nickname=args.posts.split('@')[0]
domain=args.posts.split('@')[1]
2019-08-20 09:16:03 +00:00
getPublicPostsOfPerson(baseDir,nickname,domain,False,True, \
2019-08-14 20:12:27 +00:00
args.tor,args.port,httpPrefix,debug, \
__version__)
2019-07-03 11:24:38 +00:00
sys.exit()
if args.postsraw:
2019-07-06 21:58:56 +00:00
if '@' not in args.postsraw:
2019-07-05 15:53:26 +00:00
print('Syntax: --postsraw nickname@domain')
sys.exit()
2019-07-19 16:59:14 +00:00
if not args.http:
args.port=443
2019-07-03 11:24:38 +00:00
nickname=args.postsraw.split('@')[0]
domain=args.postsraw.split('@')[1]
2019-08-20 09:16:03 +00:00
getPublicPostsOfPerson(baseDir,nickname,domain,False,False, \
2019-08-14 20:12:27 +00:00
args.tor,args.port,httpPrefix,debug, \
__version__)
2019-07-03 10:33:55 +00:00
sys.exit()
2019-11-13 10:50:16 +00:00
if args.json:
session = createSession(False)
asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}
testJson = getJson(session,args.json,asHeader,None,__version__,httpPrefix,None)
pprint(testJson)
sys.exit()
2019-08-20 10:10:33 +00:00
# create cache for actors
if not os.path.isdir(baseDir+'/cache'):
os.mkdir(baseDir+'/cache')
if not os.path.isdir(baseDir+'/cache/actors'):
print('Creating actors cache')
os.mkdir(baseDir+'/cache/actors')
2019-08-20 12:39:59 +00:00
if not os.path.isdir(baseDir+'/cache/announce'):
print('Creating announce cache')
os.mkdir(baseDir+'/cache/announce')
2019-07-05 09:20:54 +00:00
# set the theme in config.json
themeName=getConfigParam(baseDir,'theme')
if not themeName:
setConfigParam(baseDir,'theme','default')
2019-11-23 13:04:11 +00:00
themeName='default'
2019-11-13 12:45:41 +00:00
# set the instance title in config.json
title=getConfigParam(baseDir,'instanceTitle')
if not title:
setConfigParam(baseDir,'instanceTitle','Epicyon')
# set the instance description in config.json
descFull=getConfigParam(baseDir,'instanceDescription')
if not descFull:
setConfigParam(baseDir,'instanceDescription','Just another ActivityPub server')
# set the short instance description in config.json
descShort=getConfigParam(baseDir,'instanceDescriptionShort')
if not descShort:
setConfigParam(baseDir,'instanceDescriptionShort','Just another ActivityPub server')
2019-07-19 18:12:50 +00:00
if args.domain:
domain=args.domain
setConfigParam(baseDir,'domain',domain)
2019-11-11 17:49:08 +00:00
if not args.language:
languageCode=getConfigParam(baseDir,'language')
if languageCode:
args.language=languageCode
2019-08-08 10:50:58 +00:00
# maximum number of new registrations
if not args.maxRegistrations:
maxRegistrations=getConfigParam(baseDir,'maxRegistrations')
if not maxRegistrations:
maxRegistrations=10
setConfigParam(baseDir,'maxRegistrations',str(maxRegistrations))
else:
maxRegistrations=int(maxRegistrations)
else:
maxRegistrations=args.maxRegistrations
setConfigParam(baseDir,'maxRegistrations',str(maxRegistrations))
2019-07-19 18:12:50 +00:00
2019-08-08 10:50:58 +00:00
# if this is the initial run then allow new registrations
if not getConfigParam(baseDir,'registration'):
setConfigParam(baseDir,'registration','open')
setConfigParam(baseDir,'maxRegistrations',str(maxRegistrations))
setConfigParam(baseDir,'registrationsRemaining',str(maxRegistrations))
if args.resetregistrations:
setConfigParam(baseDir,'registrationsRemaining',str(maxRegistrations))
print('Number of new registrations reset to '+str(maxRegistrations))
# whether new registrations are open or closed
if args.registration:
if args.registration.lower()=='open':
registration=getConfigParam(baseDir,'registration')
if not registration:
setConfigParam(baseDir,'registrationsRemaining',str(maxRegistrations))
else:
if registration!='open':
setConfigParam(baseDir,'registrationsRemaining',str(maxRegistrations))
setConfigParam(baseDir,'registration','open')
print('New registrations open')
else:
setConfigParam(baseDir,'registration','closed')
print('New registrations closed')
2019-08-02 12:49:34 +00:00
# unique ID for the instance
instanceId=getConfigParam(baseDir,'instanceId')
if not instanceId:
instanceId=createPassword(32)
setConfigParam(baseDir,'instanceId',instanceId)
print('Instance ID: '+instanceId)
2019-07-05 09:20:54 +00:00
# get domain name from configuration
configDomain=getConfigParam(baseDir,'domain')
if configDomain:
domain=configDomain
else:
domain='localhost'
# get port number from configuration
configPort=getConfigParam(baseDir,'port')
if configPort:
port=configPort
else:
port=8085
2019-08-14 13:52:19 +00:00
configProxyPort=getConfigParam(baseDir,'proxyPort')
if configProxyPort:
proxyPort=configProxyPort
else:
proxyPort=port
2019-07-09 15:51:31 +00:00
nickname=None
if args.nickname:
nickname=nickname
federationList=[]
if args.federationList:
if len(args.federationList)==1:
if not (args.federationList[0].lower()=='any' or \
args.federationList[0].lower()=='all' or \
args.federationList[0].lower()=='*'):
for federationDomain in args.federationList:
if '@' in federationDomain:
print(federationDomain+': Federate with domains, not individual accounts')
sys.exit()
federationList=args.federationList.copy()
setConfigParam(baseDir,'federationList',federationList)
else:
configFederationList=getConfigParam(baseDir,'federationList')
if configFederationList:
federationList=configFederationList
2019-07-09 15:58:51 +00:00
useTor=args.tor
if domain.endswith('.onion'):
useTor=True
if args.approve:
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
2019-07-20 14:01:07 +00:00
if '@' not in args.approve:
print('syntax: --approve nick@domain')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-20 18:25:40 +00:00
sendThreads=[]
postLog=[]
cachedWebfingers={}
personCache={}
acceptedCaps=[]
manualApproveFollowRequest(session,baseDir, \
httpPrefix,
args.nickname,domain,port, \
args.approve, \
federationList, \
sendThreads,postLog, \
cachedWebfingers,personCache, \
acceptedCaps, \
2019-08-14 20:12:27 +00:00
debug,__version__)
sys.exit()
if args.deny:
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
2019-07-20 14:01:07 +00:00
if '@' not in args.deny:
print('syntax: --deny nick@domain')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
sendThreads=[]
postLog=[]
cachedWebfingers={}
personCache={}
manualDenyFollowRequest(session,baseDir, \
httpPrefix,
args.nickname,domain,port, \
args.deny, \
federationList, \
sendThreads,postLog, \
cachedWebfingers,personCache, \
debug,__version__)
sys.exit()
if args.followerspending:
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
accountsDir=baseDir+'/accounts/'+args.nickname+'@'+domain
2019-08-07 12:55:22 +00:00
approveFollowsFilename=accountsDir+'/followrequests.txt'
approveCtr=0
if os.path.isfile(approveFollowsFilename):
with open(approveFollowsFilename, 'r') as approvefile:
for approve in approvefile:
print(approve.replace('\n',''))
approveCtr+=1
if approveCtr==0:
print('There are no follow requests pending approval.')
sys.exit()
2019-07-16 16:43:28 +00:00
if args.message:
2019-07-19 18:12:50 +00:00
if not args.nickname:
2019-07-16 16:43:28 +00:00
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-16 16:43:28 +00:00
if not args.sendto:
print('Specify an account to sent to: --sendto [nickname@domain]')
sys.exit()
2019-07-17 14:43:51 +00:00
if '@' not in args.sendto and \
not args.sendto.lower().endswith('public') and \
not args.sendto.lower().endswith('followers'):
2019-07-16 16:43:28 +00:00
print('syntax: --sendto [nickname@domain]')
2019-07-17 14:43:51 +00:00
print(' --sendto public')
print(' --sendto followers')
2019-07-12 22:29:10 +00:00
sys.exit()
2019-07-17 14:43:51 +00:00
if '@' in args.sendto:
toNickname=args.sendto.split('@')[0]
toDomain=args.sendto.split('@')[1].replace('\n','')
toPort=443
if ':' in toDomain:
toPort=toDomain.split(':')[1]
toDomain=toDomain.split(':')[0]
else:
if args.sendto.endswith('followers'):
toNickname=None
toDomain='followers'
toPort=port
else:
toNickname=None
toDomain='public'
toPort=port
2019-07-16 16:43:28 +00:00
#ccUrl=httpPrefix+'://'+domain+'/users/'+nickname+'/followers'
ccUrl=None
sendMessage=args.message
followersOnly=args.followersonly
clientToServer=args.client
attachedImageDescription=args.imageDescription
useBlurhash=args.blurhash
sendThreads = []
postLog = []
personCache={}
cachedWebfingers={}
subject=args.subject
attach=args.attach
2019-08-30 15:50:20 +00:00
mediaType=None
if attach:
mediaType=getAttachmentMediaType(attach)
2019-07-19 18:12:50 +00:00
replyTo=args.replyto
2019-07-16 16:43:28 +00:00
followersOnly=False
print('Sending post to '+args.sendto)
2019-08-14 20:12:27 +00:00
sendPostViaServer(__version__, \
baseDir,session,args.nickname,args.password, \
2019-07-16 16:43:28 +00:00
domain,port, \
toNickname,toDomain,toPort,ccUrl, \
httpPrefix,sendMessage,followersOnly, \
2019-08-30 15:50:20 +00:00
attach,mediaType, \
attachedImageDescription,useBlurhash, \
2019-07-16 16:43:28 +00:00
cachedWebfingers,personCache, \
args.debug,replyTo,replyTo,subject)
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-16 20:08:30 +00:00
if args.announce:
2019-07-19 18:12:50 +00:00
if not args.nickname:
2019-07-16 20:08:30 +00:00
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-16 20:08:30 +00:00
personCache={}
cachedWebfingers={}
print('Sending announce/repeat of '+args.announce)
2019-08-20 09:16:03 +00:00
sendAnnounceViaServer(baseDir,session,args.nickname,args.password,
2019-07-16 20:08:30 +00:00
domain,port, \
httpPrefix,args.announce, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-16 20:08:30 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-23 21:45:53 +00:00
if args.itemName:
2019-07-23 21:39:07 +00:00
if not args.password:
print('Specify a password with the --password option')
sys.exit()
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.summary:
print('Specify a description for your shared item with the --summary option')
sys.exit()
if not args.itemType:
print('Specify a type of shared item with the --itemType option')
sys.exit()
if not args.itemCategory:
print('Specify a category of shared item with the --itemCategory option')
sys.exit()
if not args.location:
print('Specify a location or city where theshared item resides with the --location option')
sys.exit()
if not args.duration:
print('Specify a duration to share the object with the --duration option')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-23 21:39:07 +00:00
personCache={}
cachedWebfingers={}
2019-07-23 21:45:53 +00:00
print('Sending shared item: '+args.itemName)
2019-07-23 21:39:07 +00:00
2019-08-20 09:16:03 +00:00
sendShareViaServer(baseDir,session, \
2019-07-23 21:41:04 +00:00
args.nickname,args.password, \
2019-07-23 21:39:07 +00:00
domain,port, \
httpPrefix, \
2019-07-23 21:45:53 +00:00
args.itemName, \
2019-07-23 21:39:07 +00:00
args.summary, \
args.itemImage, \
args.itemType, \
args.itemCategory, \
args.location, \
args.duration, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
debug,__version__)
2019-07-23 21:39:07 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-23 21:45:53 +00:00
if args.undoItemName:
if not args.password:
print('Specify a password with the --password option')
sys.exit()
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-23 21:45:53 +00:00
personCache={}
cachedWebfingers={}
print('Sending undo of shared item: '+args.undoItemName)
sendUndoShareViaServer(session, \
args.nickname,args.password, \
domain,port, \
httpPrefix, \
args.undoItemName, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
debug,__version__)
2019-07-23 21:45:53 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-17 18:33:41 +00:00
if args.like:
2019-07-19 18:12:50 +00:00
if not args.nickname:
2019-07-17 18:33:41 +00:00
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-17 18:33:41 +00:00
personCache={}
cachedWebfingers={}
print('Sending like of '+args.like)
2019-08-20 09:16:03 +00:00
sendLikeViaServer(baseDir,session, \
args.nickname,args.password, \
2019-07-17 18:33:41 +00:00
domain,port, \
httpPrefix,args.like, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-17 18:33:41 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-17 19:04:00 +00:00
if args.undolike:
2019-07-19 18:12:50 +00:00
if not args.nickname:
2019-07-17 19:04:00 +00:00
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-17 19:04:00 +00:00
personCache={}
cachedWebfingers={}
print('Sending undo like of '+args.undolike)
2019-08-20 09:16:03 +00:00
sendUndoLikeViaServer(baseDir,session, \
args.nickname,args.password, \
2019-07-17 19:04:00 +00:00
domain,port, \
httpPrefix,args.undolike, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-17 19:04:00 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-17 17:29:33 +00:00
if args.delete:
2019-07-19 18:12:50 +00:00
if not args.nickname:
2019-07-17 17:29:33 +00:00
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-17 17:29:33 +00:00
personCache={}
cachedWebfingers={}
print('Sending delete request of '+args.delete)
2019-08-20 09:16:03 +00:00
sendDeleteViaServer(baseDir,session, \
args.nickname,args.password, \
2019-07-17 17:29:33 +00:00
domain,port, \
httpPrefix,args.delete, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-17 17:29:33 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-17 12:17:54 +00:00
if args.follow:
# follow via c2s protocol
2019-07-17 12:25:02 +00:00
if '.' not in args.follow:
print("This doesn't look like a fediverse handle")
sys.exit()
2019-07-19 18:12:50 +00:00
if not args.nickname:
2019-07-17 12:17:54 +00:00
print('Please specify the nickname for the account with --nickname')
sys.exit()
if not args.password:
2019-07-19 18:12:50 +00:00
print('Please specify the password for '+args.nickname+' on '+domain)
2019-07-17 12:17:54 +00:00
sys.exit()
2019-07-09 15:51:31 +00:00
followNickname=getNicknameFromActor(args.follow)
2019-09-02 09:43:43 +00:00
if not followNickname:
print('Unable to find nickname in '+args.follow)
sys.exit()
2019-07-09 15:51:31 +00:00
followDomain,followPort=getDomainFromActor(args.follow)
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-09 15:51:31 +00:00
personCache={}
cachedWebfingers={}
followHttpPrefix=httpPrefix
if args.follow.startswith('https'):
followHttpPrefix='https'
2019-07-17 12:17:54 +00:00
2019-08-20 09:16:03 +00:00
sendFollowRequestViaServer(baseDir,session, \
args.nickname,args.password, \
2019-07-17 12:17:54 +00:00
domain,port, \
followNickname,followDomain,followPort, \
httpPrefix, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
debug,__version__)
2019-07-17 12:17:54 +00:00
for t in range(20):
2019-07-09 15:51:31 +00:00
time.sleep(1)
2019-07-17 12:17:54 +00:00
# TODO some method to know if it worked
2019-07-17 12:25:02 +00:00
print('Ok')
2019-07-09 15:51:31 +00:00
sys.exit()
2019-07-17 12:25:02 +00:00
if args.unfollow:
# unfollow via c2s protocol
if '.' not in args.follow:
print("This doesn't look like a fediverse handle")
sys.exit()
2019-07-19 18:12:50 +00:00
if not args.nickname:
2019-07-17 12:25:02 +00:00
print('Please specify the nickname for the account with --nickname')
sys.exit()
if not args.password:
2019-07-19 18:12:50 +00:00
print('Please specify the password for '+args.nickname+' on '+domain)
2019-07-17 12:25:02 +00:00
sys.exit()
followNickname=getNicknameFromActor(args.unfollow)
2019-09-02 09:43:43 +00:00
if not followNickname:
print('WARN: unable to find nickname in '+args.unfollow)
sys.exit()
2019-07-17 12:25:02 +00:00
followDomain,followPort=getDomainFromActor(args.unfollow)
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-17 12:25:02 +00:00
personCache={}
cachedWebfingers={}
followHttpPrefix=httpPrefix
if args.follow.startswith('https'):
followHttpPrefix='https'
2019-08-20 09:16:03 +00:00
sendUnfollowRequestViaServer(baseDir,session, \
args.nickname,args.password, \
2019-07-17 12:25:02 +00:00
domain,port, \
followNickname,followDomain,followPort, \
httpPrefix, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
debug,__version__)
2019-07-17 12:25:02 +00:00
for t in range(20):
time.sleep(1)
# TODO some method to know if it worked
print('Ok')
sys.exit()
2019-07-03 09:40:27 +00:00
nickname='admin'
2019-07-05 09:20:54 +00:00
if args.domain:
domain=args.domain
setConfigParam(baseDir,'domain',domain)
if args.port:
port=args.port
setConfigParam(baseDir,'port',port)
2019-08-14 13:52:19 +00:00
if args.proxyPort:
proxyPort=args.proxyPort
setConfigParam(baseDir,'proxyPort',proxyPort)
ocapAlways=False
if args.ocap:
ocapAlways=args.ocap
2019-07-03 19:00:03 +00:00
if args.dat:
httpPrefix='dat'
2019-07-04 22:44:32 +00:00
2019-07-05 15:53:26 +00:00
if args.actor:
2019-10-17 15:08:25 +00:00
originalActor=args.actor
2019-08-24 09:51:29 +00:00
if '/@' in args.actor or '/users/' in args.actor or args.actor.startswith('http') or args.actor.startswith('dat'):
# format: https://domain/@nick
args.actor=args.actor.replace('https://','').replace('http://','').replace('dat://','').replace('/@','/users/')
2019-10-17 22:26:47 +00:00
if '/users/' not in args.actor and \
'/channel/' not in args.actor and \
'/profile/' not in args.actor:
2019-08-24 11:23:12 +00:00
print('Expected actor format: https://domain/@nick or https://domain/users/nick')
sys.exit()
2019-09-09 09:41:31 +00:00
if '/users/' in args.actor:
nickname=args.actor.split('/users/')[1].replace('\n','')
domain=args.actor.split('/users/')[0]
2019-10-17 22:26:47 +00:00
elif '/profile/' in args.actor:
2019-09-09 09:41:31 +00:00
nickname=args.actor.split('/profile/')[1].replace('\n','')
domain=args.actor.split('/profile/')[0]
2019-10-17 22:26:47 +00:00
else:
nickname=args.actor.split('/channel/')[1].replace('\n','')
domain=args.actor.split('/channel/')[0]
2019-08-24 09:51:29 +00:00
else:
# format: @nick@domain
if '@' not in args.actor:
print('Syntax: --actor nickname@domain')
sys.exit()
if args.actor.startswith('@'):
args.actor=args.actor[1:]
if '@' not in args.actor:
print('Syntax: --actor nickname@domain')
sys.exit()
nickname=args.actor.split('@')[0]
domain=args.actor.split('@')[1].replace('\n','')
2019-07-05 15:53:26 +00:00
wfCache={}
2019-08-07 19:34:57 +00:00
if args.http or domain.endswith('.onion'):
2019-07-05 15:53:26 +00:00
httpPrefix='http'
port=80
else:
httpPrefix='https'
port=443
2019-11-13 10:50:16 +00:00
session=createSession(useTor)
2019-08-23 18:27:29 +00:00
if nickname=='inbox':
2019-08-23 13:47:29 +00:00
nickname=domain
2019-08-23 16:32:44 +00:00
wfRequest=webfingerHandle(session,nickname+'@'+domain,httpPrefix,wfCache, \
None,__version__)
2019-07-05 15:53:26 +00:00
if not wfRequest:
print('Unable to webfinger '+nickname+'@'+domain)
sys.exit()
2019-08-23 10:57:27 +00:00
2019-10-17 22:26:47 +00:00
pprint(wfRequest)
2019-10-17 15:08:25 +00:00
personUrl=None
2019-10-17 14:41:47 +00:00
if wfRequest.get('errors'):
print('wfRequest error: '+str(wfRequest['errors']))
2019-10-17 22:26:47 +00:00
if '/users/' in args.actor or \
'/profile/' in args.actor or \
'/channel/' in args.actor:
2019-10-17 15:08:25 +00:00
personUrl=originalActor
else:
sys.exit()
2019-10-17 14:41:47 +00:00
asHeader = {'Accept': 'application/activity+json; profile="https://www.w3.org/ns/activitystreams"'}
2019-10-17 15:08:25 +00:00
if not personUrl:
personUrl = getUserUrl(wfRequest)
if nickname==domain:
2019-10-17 22:26:47 +00:00
personUrl=personUrl.replace('/users/','/actor/').replace('/channel/','/actor/').replace('/profile/','/actor/')
2019-10-20 22:47:01 +00:00
if not personUrl:
# try single user instance
personUrl=httpPrefix+'://'+domain
asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}
2019-10-17 22:26:47 +00:00
if '/channel/' in personUrl:
asHeader = {'Accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'}
2019-08-26 14:08:41 +00:00
personJson = getJson(session,personUrl,asHeader,None,__version__,httpPrefix,None)
2019-07-05 15:53:26 +00:00
if personJson:
pprint(personJson)
else:
print('Failed to get '+personUrl)
sys.exit()
2019-07-04 22:44:32 +00:00
if args.addaccount:
if '@' in args.addaccount:
2019-07-04 22:50:40 +00:00
nickname=args.addaccount.split('@')[0]
domain=args.addaccount.split('@')[1]
2019-07-04 22:44:32 +00:00
else:
2019-07-04 22:50:40 +00:00
nickname=args.addaccount
2019-07-05 09:20:54 +00:00
if not args.domain or not getConfigParam(baseDir,'domain'):
2019-07-04 22:44:32 +00:00
print('Use the --domain option to set the domain name')
sys.exit()
2019-08-23 13:47:29 +00:00
if not validNickname(domain,nickname):
print(nickname+' is a reserved name. Use something different.')
sys.exit()
2019-07-05 09:20:54 +00:00
if not args.password:
print('Use the --password option to set the password for '+nickname)
sys.exit()
if len(args.password.strip())<8:
print('Password should be at least 8 characters')
sys.exit()
2019-07-04 22:50:40 +00:00
if os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
print('Account already exists')
sys.exit()
if os.path.isdir(baseDir+'/deactivated/'+nickname+'@'+domain):
print('Account is deactivated')
sys.exit()
2019-07-05 09:20:54 +00:00
createPerson(baseDir,nickname,domain,port,httpPrefix,True,args.password.strip())
2019-07-04 22:44:32 +00:00
if os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
print('Account created for '+nickname+'@'+domain)
2019-07-05 09:20:54 +00:00
else:
print('Account creation failed')
2019-07-04 22:44:32 +00:00
sys.exit()
2019-10-04 12:39:46 +00:00
if args.addgroup:
if '@' in args.addgroup:
nickname=args.addgroup.split('@')[0]
domain=args.addgroup.split('@')[1]
else:
nickname=args.addgroup
if not args.domain or not getConfigParam(baseDir,'domain'):
print('Use the --domain option to set the domain name')
sys.exit()
if not validNickname(domain,nickname):
print(nickname+' is a reserved name. Use something different.')
sys.exit()
if not args.password:
print('Use the --password option to set the password for '+nickname)
sys.exit()
if len(args.password.strip())<8:
print('Password should be at least 8 characters')
sys.exit()
if os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
print('Group already exists')
sys.exit()
createGroup(baseDir,nickname,domain,port,httpPrefix,True,args.password.strip())
if os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
print('Group created for '+nickname+'@'+domain)
else:
print('Group creation failed')
sys.exit()
2019-10-04 12:59:31 +00:00
if args.rmgroup:
args.rmaccount=args.rmgroup
2019-11-05 10:37:37 +00:00
if args.deactivate:
args.rmaccount=args.deactivate
2019-07-04 22:50:40 +00:00
if args.rmaccount:
if '@' in args.rmaccount:
nickname=args.rmaccount.split('@')[0]
domain=args.rmaccount.split('@')[1]
else:
nickname=args.rmaccount
2019-07-05 09:20:54 +00:00
if not args.domain or not getConfigParam(baseDir,'domain'):
2019-07-04 22:50:40 +00:00
print('Use the --domain option to set the domain name')
sys.exit()
2019-11-05 10:37:37 +00:00
if args.deactivate:
if deactivateAccount(baseDir,nickname,domain):
print('Account for '+handle+' was deactivated')
else:
print('Account for '+handle+' was not found')
sys.exit()
2019-08-13 12:14:11 +00:00
if removeAccount(baseDir,nickname,domain,port):
2019-10-04 12:59:31 +00:00
if not args.rmgroup:
print('Account for '+handle+' was removed')
else:
print('Group '+handle+' was removed')
sys.exit()
2019-07-04 22:50:40 +00:00
2019-11-05 10:40:44 +00:00
if args.activate:
if '@' in args.activate:
nickname=args.activate.split('@')[0]
domain=args.activate.split('@')[1]
else:
nickname=args.activate
if not args.domain or not getConfigParam(baseDir,'domain'):
print('Use the --domain option to set the domain name')
sys.exit()
if activateAccount(baseDir,nickname,domain):
print('Account for '+handle+' was activated')
else:
print('Deactivated account for '+handle+' was not found')
sys.exit()
2019-07-05 09:44:15 +00:00
if args.changepassword:
if len(args.changepassword)!=2:
print('--changepassword [nickname] [new password]')
sys.exit()
if '@' in args.changepassword[0]:
nickname=args.changepassword[0].split('@')[0]
domain=args.changepassword[0].split('@')[1]
else:
nickname=args.changepassword[0]
if not args.domain or not getConfigParam(baseDir,'domain'):
print('Use the --domain option to set the domain name')
sys.exit()
newPassword=args.changepassword[1]
if len(newPassword)<8:
print('Password should be at least 8 characters')
sys.exit()
2019-07-05 09:58:58 +00:00
if not os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
print('Account '+nickname+'@'+domain+' not found')
sys.exit()
2019-07-05 09:44:15 +00:00
passwordFile=baseDir+'/accounts/passwords'
if os.path.isfile(passwordFile):
if nickname+':' in open(passwordFile).read():
storeBasicCredentials(baseDir,nickname,newPassword)
print('Password for '+nickname+' was changed')
else:
print(nickname+' is not in the passwords file')
else:
print('Passwords file not found')
sys.exit()
2019-07-12 20:51:02 +00:00
archiveWeeks=4
if args.archiveWeeks:
archiveWeeks=args.archiveWeeks
2019-10-19 10:23:49 +00:00
archiveMaxPosts=32000
2019-07-12 20:51:02 +00:00
if args.archiveMaxPosts:
archiveMaxPosts=args.archiveMaxPosts
if args.archive:
if args.archive.lower().endswith('null') or \
args.archive.lower().endswith('delete') or \
args.archive.lower().endswith('none'):
args.archive=None
print('Archiving with deletion of old posts...')
else:
print('Archiving to '+args.archive+'...')
archiveMedia(baseDir,args.archive,archiveWeeks)
2019-07-14 17:02:41 +00:00
archivePosts(baseDir,httpPrefix,args.archive,archiveMaxPosts)
2019-07-12 20:51:02 +00:00
print('Archiving complete')
2019-07-14 15:43:02 +00:00
sys.exit()
2019-07-12 20:51:02 +00:00
2019-07-05 10:03:25 +00:00
if not args.domain and not domain:
2019-07-04 22:44:32 +00:00
print('Specify a domain with --domain [name]')
2019-07-03 09:24:55 +00:00
sys.exit()
2019-07-05 09:44:15 +00:00
2019-07-12 14:31:56 +00:00
if args.avatar:
if not os.path.isfile(args.avatar):
print(args.avatar+' is not an image filename')
sys.exit()
if not args.nickname:
print('Specify a nickname with --nickname [name]')
sys.exit()
if setProfileImage(baseDir,httpPrefix,args.nickname,domain, \
port,args.avatar,'avatar','128x128'):
2019-07-12 14:31:56 +00:00
print('Avatar added for '+args.nickname)
else:
print('Avatar was not added for '+args.nickname)
sys.exit()
if args.backgroundImage:
if not os.path.isfile(args.backgroundImage):
print(args.backgroundImage+' is not an image filename')
sys.exit()
if not args.nickname:
print('Specify a nickname with --nickname [name]')
sys.exit()
if setProfileImage(baseDir,httpPrefix,args.nickname,domain, \
port,args.backgroundImage,'background','256x256'):
print('Background image added for '+args.nickname)
else:
print('Background image was not added for '+args.nickname)
sys.exit()
if args.project:
2019-07-18 16:48:35 +00:00
if not args.delegate and not args.undelegate:
2019-07-18 16:33:36 +00:00
if not nickname:
print('No nickname given')
sys.exit()
2019-07-18 16:33:36 +00:00
if args.role.lower()=='none' or \
args.role.lower()=='remove' or \
args.role.lower()=='delete':
args.role=None
if args.role:
if setRole(baseDir,nickname,domain,args.project,args.role):
print('Role within '+args.project+' set to '+args.role)
else:
if setRole(baseDir,nickname,domain,args.project,None):
print('Left '+args.project)
sys.exit()
if args.skill:
2019-07-19 10:01:24 +00:00
if not nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
if not args.skillLevelPercent:
print('Specify a skill level in the range 0-100')
sys.exit()
if int(args.skillLevelPercent)<0 or int(args.skillLevelPercent)>100:
print('Skill level should be a percentage in the range 0-100')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-19 10:01:24 +00:00
personCache={}
cachedWebfingers={}
print('Sending '+args.skill+' skill level '+str(args.skillLevelPercent)+' for '+nickname)
2019-08-20 09:16:03 +00:00
sendSkillViaServer(baseDir,session, \
nickname,args.password, \
2019-07-19 10:01:24 +00:00
domain,port, \
httpPrefix, \
args.skill,args.skillLevelPercent, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-19 10:01:24 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-19 11:38:37 +00:00
if args.availability:
if not nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-19 11:38:37 +00:00
personCache={}
cachedWebfingers={}
print('Sending availability status of '+nickname+' as '+args.availability)
2019-08-20 09:16:03 +00:00
sendAvailabilityViaServer(baseDir,session,nickname,args.password,
2019-07-19 11:38:37 +00:00
domain,port, \
httpPrefix, \
args.availability, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-19 11:38:37 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-05 09:20:54 +00:00
if federationList:
2019-07-03 16:16:36 +00:00
print('Federating with: '+str(federationList))
2019-06-28 18:55:29 +00:00
2019-07-18 13:10:26 +00:00
#if not os.path.isdir(baseDir+'/accounts/'+nickname+'@'+domain):
# print('Creating default admin account '+nickname+'@'+domain)
# print('See config.json for the password. You can remove the password from config.json after moving it elsewhere.')
# adminPassword=createPassword(10)
# setConfigParam(baseDir,'adminPassword',adminPassword)
# createPerson(baseDir,nickname,domain,port,httpPrefix,True,adminPassword)
2019-07-03 12:24:54 +00:00
2019-07-14 19:57:05 +00:00
if args.block:
2019-07-17 22:09:09 +00:00
if not nickname:
print('Specify a nickname with the --nickname option')
2019-07-14 19:57:05 +00:00
sys.exit()
2019-07-17 22:09:09 +00:00
if not args.password:
print('Specify a password with the --password option')
2019-07-14 19:57:05 +00:00
sys.exit()
2019-07-17 22:09:09 +00:00
if '@' in args.block:
blockedDomain=args.block.split('@')[1].replace('\n','')
blockedNickname=args.block.split('@')[0]
blockedActor=httpPrefix+'://'+blockedDomain+'/users/'+blockedNickname
args.block=blockedActor
else:
if '/users/' not in args.block:
print(args.block+' does not look like an actor url')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-17 22:09:09 +00:00
personCache={}
cachedWebfingers={}
print('Sending block of '+args.block)
2019-08-20 09:16:03 +00:00
sendBlockViaServer(baseDir,session,nickname,args.password,
2019-07-17 22:09:09 +00:00
domain,port, \
httpPrefix,args.block, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-17 22:09:09 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
2019-07-14 19:57:05 +00:00
sys.exit()
2019-07-18 16:33:36 +00:00
if args.delegate:
if not nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
if not args.project:
print('Specify a project with the --project option')
sys.exit()
if not args.role:
print('Specify a role with the --role option')
sys.exit()
if '@' in args.delegate:
delegatedNickname=args.delegate.split('@')[0]
args.delegate=blockedActor
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-18 16:33:36 +00:00
personCache={}
cachedWebfingers={}
print('Sending delegation for '+args.delegate+' with role '+args.role+' in project '+args.project)
2019-08-20 09:16:03 +00:00
sendRoleViaServer(baseDir,session, \
nickname,args.password, \
2019-07-18 16:33:36 +00:00
domain,port, \
httpPrefix,args.delegate, \
args.project,args.role, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-18 16:48:35 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
if args.undelegate:
if not nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
print('Specify a password with the --password option')
sys.exit()
if not args.project:
print('Specify a project with the --project option')
sys.exit()
if '@' in args.undelegate:
delegatedNickname=args.undelegate.split('@')[0]
args.undelegate=blockedActor
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-18 16:48:35 +00:00
personCache={}
cachedWebfingers={}
print('Sending delegation removal for '+args.undelegate+' from role '+args.role+' in project '+args.project)
2019-08-20 09:16:03 +00:00
sendRoleViaServer(baseDir,session, \
nickname,args.password, \
2019-07-18 16:48:35 +00:00
domain,port, \
httpPrefix,args.delegate, \
args.project,None, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-18 16:33:36 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
2019-07-14 19:57:05 +00:00
if args.unblock:
2019-07-17 22:09:09 +00:00
if not nickname:
print('Specify a nickname with the --nickname option')
2019-07-14 19:57:05 +00:00
sys.exit()
2019-07-17 22:09:09 +00:00
if not args.password:
print('Specify a password with the --password option')
2019-07-14 19:57:05 +00:00
sys.exit()
2019-07-17 22:09:09 +00:00
if '@' in args.unblock:
blockedDomain=args.unblock.split('@')[1].replace('\n','')
blockedNickname=args.unblock.split('@')[0]
blockedActor=httpPrefix+'://'+blockedDomain+'/users/'+blockedNickname
args.unblock=blockedActor
else:
if '/users/' not in args.unblock:
print(args.unblock+' does not look like an actor url')
sys.exit()
2019-11-13 10:50:16 +00:00
session = createSession(useTor)
2019-07-17 22:09:09 +00:00
personCache={}
cachedWebfingers={}
print('Sending undo block of '+args.unblock)
2019-08-20 09:16:03 +00:00
sendUndoBlockViaServer(baseDir,session,nickname,args.password,
2019-07-17 22:09:09 +00:00
domain,port, \
httpPrefix,args.unblock, \
cachedWebfingers,personCache, \
2019-08-14 20:12:27 +00:00
True,__version__)
2019-07-17 22:09:09 +00:00
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
2019-07-14 19:57:05 +00:00
sys.exit()
2019-07-14 20:50:27 +00:00
if args.filterStr:
if not args.nickname:
print('Please specify a nickname')
sys.exit()
if addFilter(baseDir,args.nickname,domain,args.filterStr):
2019-07-14 20:58:50 +00:00
print('Filter added to '+args.nickname+': '+args.filterStr)
2019-07-14 20:50:27 +00:00
sys.exit()
if args.unfilterStr:
if not args.nickname:
print('Please specify a nickname')
sys.exit()
if removeFilter(baseDir,args.nickname,domain,args.unfilterStr):
2019-07-14 20:58:50 +00:00
print('Filter removed from '+args.nickname+': '+args.unfilterStr)
2019-07-14 20:50:27 +00:00
sys.exit()
2019-07-06 20:19:49 +00:00
if args.testdata:
2019-07-12 19:08:46 +00:00
useBlurhash=False
nickname='testuser567'
password='boringpassword'
2019-07-06 20:19:49 +00:00
print('Generating some test data for user: '+nickname)
2019-08-10 10:54:52 +00:00
if os.path.isdir(baseDir+'/tags'):
shutil.rmtree(baseDir+'/tags')
2019-08-10 15:33:18 +00:00
if os.path.isdir(baseDir+'/accounts'):
shutil.rmtree(baseDir+'/accounts')
if os.path.isdir(baseDir+'/keys'):
shutil.rmtree(baseDir+'/keys')
if os.path.isdir(baseDir+'/media'):
shutil.rmtree(baseDir+'/media')
if os.path.isdir(baseDir+'/sharefiles'):
shutil.rmtree(baseDir+'/sharefiles')
if os.path.isdir(baseDir+'/wfendpoints'):
shutil.rmtree(baseDir+'/wfendpoints')
2019-08-10 10:54:52 +00:00
2019-08-08 11:24:26 +00:00
setConfigParam(baseDir,'registrationsRemaining',str(maxRegistrations))
createPerson(baseDir,'maxboardroom',domain,port,httpPrefix,True,password)
createPerson(baseDir,'ultrapancake',domain,port,httpPrefix,True,password)
createPerson(baseDir,'drokk',domain,port,httpPrefix,True,password)
createPerson(baseDir,'sausagedog',domain,port,httpPrefix,True,password)
2019-07-06 20:19:49 +00:00
createPerson(baseDir,nickname,domain,port,httpPrefix,True,'likewhateveryouwantscoob')
2019-07-14 12:29:08 +00:00
setSkillLevel(baseDir,nickname,domain,'testing',60)
setSkillLevel(baseDir,nickname,domain,'typing',50)
2019-08-10 15:33:18 +00:00
setRole(baseDir,nickname,domain,'instance','admin')
2019-07-14 12:29:08 +00:00
setRole(baseDir,nickname,domain,'epicyon','hacker')
setRole(baseDir,nickname,domain,'someproject','assistant')
2019-07-14 13:30:59 +00:00
setAvailability(baseDir,nickname,domain,'busy')
2019-07-23 22:12:19 +00:00
2019-07-25 16:15:02 +00:00
addShare(baseDir, \
httpPrefix,nickname,domain,port, \
2019-07-23 22:12:19 +00:00
"spanner", \
"It's a spanner", \
"img/shares1.png", \
"tool", \
"mechanical", \
"City", \
"2 months",
debug)
2019-07-25 16:15:02 +00:00
addShare(baseDir, \
httpPrefix,nickname,domain,port, \
2019-07-23 22:12:19 +00:00
"witch hat", \
"Spooky", \
"img/shares2.png", \
"hat", \
"clothing", \
"City", \
"3 months",
debug)
2019-07-06 20:19:49 +00:00
deleteAllPosts(baseDir,nickname,domain,'inbox')
deleteAllPosts(baseDir,nickname,domain,'outbox')
2019-08-10 10:54:52 +00:00
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"like, this is totally just a #test, man",False,True,False,None,None,useBlurhash)
2019-07-12 19:08:46 +00:00
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Zoiks!!!",False,True,False,None,None,useBlurhash)
2019-08-10 10:54:52 +00:00
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Hey scoob we need like a hundred more #milkshakes",False,True,False,None,None,useBlurhash)
2019-07-21 11:20:49 +00:00
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"Getting kinda spooky around here",False,True,False,None,None,useBlurhash,'someone')
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"And they would have gotten away with it too if it wasn't for those pesky hackers",False,True,False,'img/logo.png','Description of image',useBlurhash)
2019-07-12 19:08:46 +00:00
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"man, these centralized sites are, like, the worst!",False,True,False,None,None,useBlurhash)
2019-08-10 10:54:52 +00:00
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"another mystery solved #test",False,True,False,None,None,useBlurhash)
2019-07-12 19:08:46 +00:00
createPublicPost(baseDir,nickname,domain,port,httpPrefix,"let's go bowling",False,True,False,None,None,useBlurhash)
domainFull=domain+':'+str(port)
clearFollows(baseDir,nickname,domain)
followPerson(baseDir,nickname,domain,'maxboardroom',domainFull,federationList,False)
followPerson(baseDir,nickname,domain,'ultrapancake',domainFull,federationList,False)
followPerson(baseDir,nickname,domain,'sausagedog',domainFull,federationList,False)
followPerson(baseDir,nickname,domain,'drokk',domainFull,federationList,False)
followerOfPerson(baseDir,nickname,domain,'drokk',domainFull,federationList,False)
followerOfPerson(baseDir,nickname,domain,'maxboardroom',domainFull,federationList,False)
2019-08-10 15:33:18 +00:00
setConfigParam(baseDir,'admin',nickname)
2019-09-30 10:15:20 +00:00
# set a lower bound to the maximum mentions
# so that it can't be accidentally set to zero and disable replies
if args.maxMentions<4:
args.maxMentions=4
2019-11-13 10:32:12 +00:00
registration=getConfigParam(baseDir,'registration')
if not registration:
registration=False
2019-11-23 13:04:11 +00:00
if setTheme(baseDir,themeName):
print('Theme set to '+themeName)
2019-09-30 10:15:20 +00:00
2019-11-15 22:04:26 +00:00
runDaemon(not args.nosharedinbox, \
2019-11-15 21:43:20 +00:00
registration,args.language,__version__, \
2019-08-14 20:12:27 +00:00
instanceId,args.client,baseDir, \
2019-08-14 13:52:19 +00:00
domain,port,proxyPort,httpPrefix, \
2019-09-30 10:15:20 +00:00
federationList,args.maxMentions, \
2019-11-16 14:49:21 +00:00
args.maxEmoji,args.authenticatedFetch, \
2019-07-09 18:11:23 +00:00
args.noreply,args.nolike,args.nopics, \
2019-07-13 21:00:12 +00:00
args.noannounce,args.cw,ocapAlways, \
2019-07-15 10:22:19 +00:00
useTor,args.maxReplies, \
args.domainMaxPostsPerDay,args.accountMaxPostsPerDay, \
args.allowdeletion,debug,False, \
args.instanceOnlySkillsSearch)