epicyon/epicyon.py

2597 lines
97 KiB
Python
Raw Normal View History

2020-04-03 10:08:04 +00:00
__filename__ = "epicyon.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
2021-01-26 10:07:42 +00:00
__version__ = "1.2.0"
2020-04-03 10:08:04 +00:00
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
2021-06-15 15:08:12 +00:00
__module_group__ = "Commandline Interface"
2019-06-28 18:55:29 +00:00
2021-03-02 14:32:25 +00:00
import os
import shutil
import sys
import time
import argparse
2021-03-13 11:13:35 +00:00
import getpass
2021-03-11 18:15:04 +00:00
from person import getActorJson
2019-06-28 18:55:29 +00:00
from person import createPerson
2019-10-04 12:39:46 +00:00
from person import createGroup
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
2019-06-28 18:55:29 +00:00
from webfinger import webfingerHandle
2021-03-20 10:43:52 +00:00
from bookmarks import sendBookmarkViaServer
from bookmarks import sendUndoBookmarkViaServer
2021-03-20 21:20:41 +00:00
from posts import sendMuteViaServer
from posts import sendUndoMuteViaServer
2021-03-18 11:03:39 +00:00
from posts import c2sBoxJson
from posts import downloadFollowCollection
2020-09-25 13:09:20 +00:00
from posts import getPublicPostDomains
from posts import getPublicPostDomainsBlocked
2020-04-01 20:13:42 +00:00
from posts import sendBlockViaServer
from posts import sendUndoBlockViaServer
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: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
2020-09-25 13:21:56 +00:00
from posts import checkDomains
2019-06-28 18:55:29 +00:00
from session import createSession
2019-06-29 16:47:37 +00:00
from session import getJson
2020-10-04 09:51:12 +00:00
from newswire import getRSS
2019-07-14 20:50:27 +00:00
from filters import addFilter
from filters import removeFilter
2019-06-28 18:55:29 +00:00
from pprint import pprint
from daemon import runDaemon
from follow import getFollowRequestsViaServer
2021-03-24 12:43:24 +00:00
from follow import getFollowingViaServer
2021-03-24 13:52:20 +00:00
from follow import getFollowersViaServer
2019-06-29 18:23:13 +00:00
from follow import clearFollows
from follow import followerOfPerson
2020-04-03 10:08:04 +00:00
from follow import sendFollowRequestViaServer
from follow import sendUnfollowRequestViaServer
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
2021-03-17 20:18:00 +00:00
from tests import testUpdateActor
2019-06-30 21:20:02 +00:00
from tests import runAllTests
2019-07-05 09:44:15 +00:00
from auth import storeBasicCredentials
2019-07-05 11:27:18 +00:00
from auth import createPassword
2020-12-23 10:57:44 +00:00
from utils import hasUsersPath
2020-12-16 10:30:54 +00:00
from utils import getFullDomain
2020-10-06 08:58:44 +00:00
from utils import setConfigParam
from utils import getConfigParam
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
2020-06-11 12:26:15 +00:00
from utils import getProtocolPrefixes
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-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
2020-04-03 10:08:04 +00:00
from announce import sendAnnounceViaServer
2020-07-08 12:28:41 +00:00
from socnet import instancesGraph
from migrate import migrateAccounts
2021-03-17 10:04:49 +00:00
from desktop_client import runDesktopClient
2019-06-30 21:20:02 +00:00
2020-04-03 10:08:04 +00:00
2020-09-25 09:10:21 +00:00
def str2bool(v) -> bool:
"""Returns true if the given value is a boolean
"""
2019-07-03 09:24:55 +00:00
if isinstance(v, bool):
2020-04-03 10:08:04 +00:00
return v
2019-07-03 09:24:55 +00:00
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
2020-04-03 10:08:04 +00:00
parser = argparse.ArgumentParser(description='ActivityPub Server')
parser.add_argument('-n', '--nickname', dest='nickname', type=str,
default=None,
2019-07-09 15:51:31 +00:00
help='Nickname of the account to use')
2021-03-02 14:32:25 +00:00
parser.add_argument('--screenreader', dest='screenreader', type=str,
2021-03-09 21:25:12 +00:00
default=None,
help='Name of the screen reader: espeak/picospeaker')
2020-04-03 10:08:04 +00:00
parser.add_argument('--fol', '--follow', dest='follow', type=str,
default=None,
2019-07-09 15:51:31 +00:00
help='Handle of account to follow. eg. nickname@domain')
2020-04-03 10:08:04 +00:00
parser.add_argument('--unfol', '--unfollow', dest='unfollow', type=str,
default=None,
help='Handle of account stop following. ' +
'eg. nickname@domain')
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')
parser.add_argument('--notificationType', '--notifyType',
dest='notificationType', type=str,
default='notify-send',
help='Type of desktop notification command: ' +
2021-03-11 10:02:12 +00:00
'notify-send/zenity/osascript/New-BurntToastNotification')
2020-04-03 10:08:04 +00:00
parser.add_argument('-o', '--onion', dest='onion', type=str,
default=None,
help='Onion domain name of the server if ' +
'primarily on clearnet')
parser.add_argument('--i2pDomain', dest='i2pDomain', type=str,
default=None,
help='i2p domain name of the server if ' +
'primarily on clearnet')
2020-04-03 10:08:04 +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')
parser.add_argument('--postsPerSource',
dest='maxNewswirePostsPerSource', type=int,
default=4,
help='Maximum newswire posts per feed or account')
parser.add_argument('--dormantMonths',
dest='dormantMonths', type=int,
default=3,
help='How many months does a followed account need to ' +
'be unseen for before being considered dormant')
parser.add_argument('--sendThreadsTimeoutMins',
dest='sendThreadsTimeoutMins', type=int,
default=30,
help='How many minutes before a thread to send out ' +
'posts expires')
parser.add_argument('--maxNewswirePosts',
dest='maxNewswirePosts', type=int,
default=20,
help='Maximum newswire posts in the right column')
parser.add_argument('--maxFeedSize',
dest='maxNewswireFeedSizeKb', type=int,
default=10240,
help='Maximum newswire rss/atom feed size in K')
parser.add_argument('--maxFeedItemSizeKb',
dest='maxFeedItemSizeKb', type=int,
default=2048,
help='Maximum size of an individual rss/atom ' +
'feed item in K')
2020-10-19 16:33:58 +00:00
parser.add_argument('--maxMirroredArticles',
dest='maxMirroredArticles', type=int,
default=100,
help='Maximum number of news articles to mirror.' +
' Set to zero for indefinite mirroring.')
2020-10-21 10:39:09 +00:00
parser.add_argument('--maxNewsPosts',
dest='maxNewsPosts', type=int,
default=0,
help='Maximum number of news timeline posts to keep. ' +
'Zero for no expiry.')
parser.add_argument('--maxFollowers',
dest='maxFollowers', type=int,
default=2000,
help='Maximum number of followers per account. ' +
'Zero for no limit.')
2021-01-10 21:38:28 +00:00
parser.add_argument('--followers',
dest='followers', type=str,
default='',
help='Show list of followers for the given actor')
2020-04-03 10:08:04 +00:00
parser.add_argument('--postcache', dest='maxRecentPosts', type=int,
2020-08-26 10:25:08 +00:00
default=512,
help='The maximum number of recent posts to store in RAM')
2020-04-03 10:08:04 +00:00
parser.add_argument('--proxy', dest='proxyPort', type=int, default=None,
2019-08-14 13:52:19 +00:00
help='Proxy port number to run on')
2020-04-03 10:08:04 +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')
parser.add_argument('--ytdomain', dest='YTReplacementDomain',
type=str, default=None,
help='Domain used to replace youtube.com')
2020-04-03 10:08:04 +00:00
parser.add_argument('--language', dest='language',
type=str, default=None,
2019-11-11 17:49:08 +00:00
help='Language code, eg. en/fr/de/es')
2020-04-03 10:08:04 +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')
2020-04-03 10:08:04 +00:00
parser.add_argument('-g', '--addgroup', dest='addgroup',
type=str, default=None,
2019-10-04 12:39:46 +00:00
help='Adds a new group')
2020-04-03 10:08:04 +00:00
parser.add_argument('--activate', dest='activate',
type=str, default=None,
2019-11-05 10:40:44 +00:00
help='Activate a previously deactivated account')
2020-04-03 10:08:04 +00:00
parser.add_argument('--deactivate', dest='deactivate',
type=str, default=None,
2019-11-05 10:37:37 +00:00
help='Deactivate an account')
2020-04-03 10:08:04 +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')
2020-04-03 10:08:04 +00:00
parser.add_argument('--rmgroup', dest='rmgroup',
type=str, default=None,
2019-10-04 12:59:31 +00:00
help='Remove a group')
2020-04-03 10:08:04 +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')
2020-04-03 10:08:04 +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')
2020-04-03 10:08:04 +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')
2020-04-03 10:08:04 +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')
2020-07-08 10:09:51 +00:00
parser.add_argument('--postDomains', dest='postDomains', type=str,
default=None,
help='Show domains referenced in public '
'posts for the given handle')
parser.add_argument('--postDomainsBlocked', dest='postDomainsBlocked',
type=str, default=None,
help='Show blocked domains referenced in public '
'posts for the given handle')
2020-09-25 12:33:28 +00:00
parser.add_argument('--checkDomains', dest='checkDomains', type=str,
default=None,
help='Check domains of non-mutual followers for '
'domains which are globally blocked by this instance')
2020-07-08 12:28:41 +00:00
parser.add_argument('--socnet', dest='socnet', type=str,
default=None,
help='Show dot diagram for social network '
'of federated instances')
2020-04-03 10:08:04 +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')
2020-04-03 10:08:04 +00:00
parser.add_argument('--json', dest='json', type=str, default=None,
2019-07-12 10:53:49 +00:00
help='Show the json for a given activitypub url')
2020-10-03 21:50:05 +00:00
parser.add_argument('--rss', dest='rss', type=str, default=None,
help='Show an rss feed for a given url')
2020-04-03 10:08:04 +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')
2021-03-24 13:52:20 +00:00
parser.add_argument("--following", "--followingList",
dest='followingList',
2021-03-24 12:43:24 +00:00
type=str2bool, nargs='?',
2021-03-24 13:15:43 +00:00
const=True, default=False,
2021-03-24 12:43:24 +00:00
help="Get the following list. Use nickname and " +
"domain options to specify the account")
2021-03-24 13:52:20 +00:00
parser.add_argument("--followersList",
dest='followersList',
type=str2bool, nargs='?',
const=True, default=False,
help="Get the followers list. Use nickname and " +
"domain options to specify the account")
parser.add_argument("--followRequestsList",
dest='followRequestsList',
type=str2bool, nargs='?',
const=True, default=False,
help="Get the follow requests list. Use nickname and " +
"domain options to specify the account")
2020-08-21 17:40:50 +00:00
parser.add_argument("--repliesEnabled", "--commentsEnabled",
dest='commentsEnabled',
type=str2bool, nargs='?',
const=True, default=True,
help="Enable replies to a post")
parser.add_argument("--showPublishAsIcon",
dest='showPublishAsIcon',
type=str2bool, nargs='?',
const=True, default=True,
help="Whether to show newswire publish " +
"as an icon or a button")
parser.add_argument("--fullWidthTimelineButtonHeader",
dest='fullWidthTimelineButtonHeader',
type=str2bool, nargs='?',
const=True, default=False,
help="Whether to show the timeline " +
"button header containing inbox and outbox " +
"as the full width of the screen")
2020-10-25 20:38:01 +00:00
parser.add_argument("--iconsAsButtons",
dest='iconsAsButtons',
type=str2bool, nargs='?',
const=True, default=False,
help="Show header icons as buttons")
2021-06-09 15:19:30 +00:00
parser.add_argument("--logLoginFailures",
dest='logLoginFailures',
type=str2bool, nargs='?',
const=True, default=False,
help="Whether to log longin failures")
parser.add_argument("--rssIconAtTop",
dest='rssIconAtTop',
type=str2bool, nargs='?',
const=True, default=True,
help="Whether to show the rss icon at teh top or bottom" +
"of the timeline")
2020-10-26 21:32:08 +00:00
parser.add_argument("--publishButtonAtTop",
dest='publishButtonAtTop',
type=str2bool, nargs='?',
const=True, default=False,
help="Whether to show the publish button at the top of " +
"the newswire column")
parser.add_argument("--allowLocalNetworkAccess",
dest='allowLocalNetworkAccess',
type=str2bool, nargs='?',
const=True, default=False,
help="Whether to allow access to local network " +
"addresses. This might be useful when deploying in " +
"a mesh network")
parser.add_argument("--verifyAllSignatures",
dest='verifyAllSignatures',
type=str2bool, nargs='?',
const=True, default=False,
help="Whether to require that all incoming " +
"posts have valid jsonld signatures")
2021-02-15 22:06:53 +00:00
parser.add_argument("--brochMode",
dest='brochMode',
type=str2bool, nargs='?',
const=True, default=False,
help="Enable broch mode")
parser.add_argument("--nodeinfoaccounts",
dest='showNodeInfoAccounts',
type=str2bool, nargs='?',
const=True, default=False,
help="Show numbers of accounts within nodeinfo metadata")
parser.add_argument("--nodeinfoversion",
dest='showNodeInfoVersion',
type=str2bool, nargs='?',
const=True, default=False,
help="Show version number within nodeinfo metadata")
parser.add_argument("--noKeyPress",
dest='noKeyPress',
type=str2bool, nargs='?',
const=True, default=False,
help="Notification daemon does not wait for keypresses")
parser.add_argument("--notifyShowNewPosts",
dest='notifyShowNewPosts',
type=str2bool, nargs='?',
const=True, default=False,
2021-03-17 10:04:49 +00:00
help="Desktop client shows/speaks new posts " +
"as they arrive")
2020-07-12 12:31:28 +00:00
parser.add_argument("--noapproval", type=str2bool, nargs='?',
const=True, default=False,
help="Allow followers without approval")
2020-04-03 10:08:04 +00:00
parser.add_argument("--mediainstance", type=str2bool, nargs='?',
const=True, default=False,
2019-11-28 16:16:43 +00:00
help="Media Instance - favor media over text")
parser.add_argument("--dateonly", type=str2bool, nargs='?',
const=True, default=False,
help="Only show the date at the bottom of posts")
2020-04-03 10:08:04 +00:00
parser.add_argument("--blogsinstance", type=str2bool, nargs='?',
const=True, default=False,
2020-02-24 14:39:25 +00:00
help="Blogs Instance - favor blogs over microblogging")
2020-10-07 09:10:42 +00:00
parser.add_argument("--newsinstance", type=str2bool, nargs='?',
const=True, default=False,
help="News Instance - favor news over microblogging")
parser.add_argument("--positivevoting", type=str2bool, nargs='?',
const=True, default=False,
help="On newswire, whether moderators vote " +
"positively for or veto against items")
2020-04-03 10:08:04 +00:00
parser.add_argument("--debug", type=str2bool, nargs='?',
const=True, default=False,
2019-07-06 20:19:49 +00:00
help="Show debug messages")
parser.add_argument("--notificationSounds", type=str2bool, nargs='?',
const=True, default=True,
help="Play notification sounds")
2020-04-03 10:08:04 +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")
parser.add_argument("--http", type=str2bool, nargs='?',
const=True, default=False,
2019-07-06 20:19:49 +00:00
help="Use http only")
2020-06-09 11:51:51 +00:00
parser.add_argument("--gnunet", type=str2bool, nargs='?',
const=True, default=False,
help="Use gnunet protocol only")
2020-04-03 10:08:04 +00:00
parser.add_argument("--dat", type=str2bool, nargs='?',
const=True, default=False,
2019-07-06 20:19:49 +00:00
help="Use dat protocol only")
2020-05-17 09:37:59 +00:00
parser.add_argument("--hyper", type=str2bool, nargs='?',
const=True, default=False,
help="Use hypercore protocol only")
2020-04-03 10:08:04 +00:00
parser.add_argument("--i2p", type=str2bool, nargs='?',
const=True, default=False,
2020-02-17 17:18:21 +00:00
help="Use i2p protocol only")
2020-04-03 10:08:04 +00:00
parser.add_argument("--tor", type=str2bool, nargs='?',
const=True, default=False,
2019-07-06 20:19:49 +00:00
help="Route via Tor")
parser.add_argument("--migrations", type=str2bool, nargs='?',
const=True, default=False,
help="Migrate moved accounts")
2020-04-03 10:08:04 +00:00
parser.add_argument("--tests", type=str2bool, nargs='?',
const=True, default=False,
2019-07-06 20:19:49 +00:00
help="Run unit tests")
2020-04-03 10:08:04 +00:00
parser.add_argument("--testsnetwork", type=str2bool, nargs='?',
const=True, default=False,
2019-07-06 20:19:49 +00:00
help="Run network unit tests")
2020-04-03 10:08:04 +00:00
parser.add_argument("--testdata", type=str2bool, nargs='?',
const=True, default=False,
2019-07-06 20:19:49 +00:00
help="Generate some data for testing purposes")
2020-04-03 10:08:04 +00:00
parser.add_argument('--icon', '--avatar', dest='avatar', type=str,
default=None,
2019-07-12 14:31:56 +00:00
help='Set the avatar filename for an account')
2020-04-03 10:08:04 +00:00
parser.add_argument('--image', '--background', dest='backgroundImage',
type=str, default=None,
help='Set the profile background image for an account')
2020-04-03 10:08:04 +00:00
parser.add_argument('--archive', dest='archive', type=str,
default=None,
2019-07-12 20:43:55 +00:00
help='Archive old files to the given directory')
2020-12-08 14:09:54 +00:00
parser.add_argument('--archiveweeks', dest='archiveWeeks', type=int,
default=4,
2020-04-03 10:08:04 +00:00
help='Specify the number of weeks after which ' +
2020-12-08 14:09:54 +00:00
'media will be archived')
parser.add_argument('--maxposts', dest='archiveMaxPosts', type=int,
default=32000,
2019-07-12 20:43:55 +00:00
help='Maximum number of posts in in/outbox')
2020-10-08 19:53:30 +00:00
parser.add_argument('--minimumvotes', dest='minimumvotes', type=int,
default=1,
2020-10-08 17:49:03 +00:00
help='Minimum number of votes to remove or add' +
' a newswire item')
2020-10-09 12:15:20 +00:00
parser.add_argument('--votingtime', dest='votingtime', type=int,
default=1440,
help='Time to vote on newswire items in minutes')
2020-04-03 10:08:04 +00:00
parser.add_argument('--message', dest='message', type=str,
default=None,
2019-07-12 22:29:10 +00:00
help='Message content')
2020-04-03 10:08:04 +00:00
parser.add_argument('--delete', dest='delete', type=str,
default=None,
2019-07-17 17:29:33 +00:00
help='Delete a specified post')
2020-04-03 10:08:04 +00:00
parser.add_argument("--allowdeletion", type=str2bool, nargs='?',
const=True, default=False,
2019-07-17 17:44:26 +00:00
help="Do not allow deletions")
2020-04-03 10:08:04 +00:00
parser.add_argument('--repeat', '--announce', dest='announce', type=str,
default=None,
2019-07-16 20:08:30 +00:00
help='Announce/repeat a url')
2021-03-18 11:03:39 +00:00
parser.add_argument('--box', type=str,
default=None,
help='Returns the json for a given timeline, ' +
'with authentication')
parser.add_argument('--page', '--pageNumber', dest='pageNumber', type=int,
default=1,
help='Page number when using the --box option')
2020-04-03 10:08:04 +00:00
parser.add_argument('--favorite', '--like', dest='like', type=str,
default=None, help='Like a url')
parser.add_argument('--undolike', '--unlike', dest='undolike', type=str,
default=None, help='Undo a like of a url')
2021-03-20 10:43:52 +00:00
parser.add_argument('--bookmark', '--bm', dest='bookmark', type=str,
default=None,
help='Bookmark the url of a post')
parser.add_argument('--unbookmark', '--unbm', dest='unbookmark', type=str,
default=None,
help='Undo a bookmark given the url of a post')
2020-04-03 10:08:04 +00:00
parser.add_argument('--sendto', dest='sendto', type=str,
default=None, help='Address to send a post to')
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')
2021-05-09 19:11:05 +00:00
parser.add_argument('--city', dest='city', type=str,
2021-05-09 19:29:53 +00:00
default='London, England',
2021-05-09 19:11:05 +00:00
help='Spoofed city for image metadata misdirection')
2020-04-03 10:08:04 +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')
2020-04-03 10:08:04 +00:00
parser.add_argument('--reply', '--replyto', dest='replyto', type=str,
default=None, help='Url of post to reply to')
parser.add_argument("--followersonly", type=str2bool, nargs='?',
const=True, default=True,
2019-07-13 09:22:25 +00:00
help="Send to followers only")
2020-04-03 10:08:04 +00:00
parser.add_argument("--followerspending", type=str2bool, nargs='?',
const=True, default=False,
help="Show a list of followers pending")
2020-04-03 10:08:04 +00:00
parser.add_argument('--approve', dest='approve', type=str, default=None,
help='Approve a follow request')
2020-04-03 10:08:04 +00:00
parser.add_argument('--deny', dest='deny', type=str, default=None,
help='Deny a follow request')
2020-04-03 10:08:04 +00:00
parser.add_argument("-c", "--client", type=str2bool, nargs='?',
const=True, default=False,
2019-07-13 09:22:25 +00:00
help="Use as an ActivityPub client")
2020-04-03 10:08:04 +00:00
parser.add_argument('--maxreplies', dest='maxReplies', type=int, default=64,
2019-07-13 21:00:12 +00:00
help='Maximum number of replies to a post')
2020-04-03 10:08:04 +00:00
parser.add_argument('--maxMentions', '--hellthread', dest='maxMentions',
type=int, default=10,
2019-09-30 10:15:20 +00:00
help='Maximum number of mentions within a post')
2020-04-03 10:08:04 +00:00
parser.add_argument('--maxEmoji', '--maxemoji', dest='maxEmoji',
type=int, default=10,
2019-11-16 14:49:21 +00:00
help='Maximum number of emoji within a post')
2020-04-03 10:08:04 +00:00
parser.add_argument('--role', dest='role', type=str, default=None,
help='Set a role for a person')
2020-04-03 10:08:04 +00:00
parser.add_argument('--skill', dest='skill', type=str, default=None,
help='Set a skill for a person')
2020-04-03 10:08:04 +00:00
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')
parser.add_argument('--status', '--availability', dest='availability',
type=str, default=None,
2019-07-14 13:30:59 +00:00
help='Set an availability status')
2021-03-16 22:14:03 +00:00
parser.add_argument('--desktop', dest='desktop',
2021-03-01 19:16:33 +00:00
type=str, default=None,
2021-03-16 22:11:54 +00:00
help='Run desktop client')
2020-04-03 10:08:04 +00:00
parser.add_argument('--block', dest='block', type=str, default=None,
2019-07-14 19:57:05 +00:00
help='Block a particular address')
2020-04-03 10:08:04 +00:00
parser.add_argument('--unblock', dest='unblock', type=str, default=None,
2019-07-14 19:57:05 +00:00
help='Remove a block on a particular address')
2021-03-20 21:20:41 +00:00
parser.add_argument('--mute', dest='mute', type=str, default=None,
help='Mute a particular post URL')
parser.add_argument('--unmute', dest='unmute', type=str, default=None,
help='Unmute a particular post URL')
2020-04-03 10:08:04 +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,
2019-07-14 20:50:27 +00:00
help='Remove a filter on a particular word or phrase')
2020-04-03 10:08:04 +00:00
parser.add_argument('--domainmax', dest='domainMaxPostsPerDay', type=int,
default=8640,
help='Maximum number of received posts ' +
'from a domain per day')
parser.add_argument('--accountmax', dest='accountMaxPostsPerDay', type=int,
default=8640,
help='Maximum number of received posts ' +
'from an account per day')
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')
2020-04-03 10:08:04 +00:00
parser.add_argument('--undoItemName', dest='undoItemName', type=str,
default=None,
2019-07-23 21:45:53 +00:00
help='Name of an shared item to remove')
2020-04-03 10:08:04 +00:00
parser.add_argument('--summary', dest='summary', type=str,
default=None,
2019-07-23 21:39:07 +00:00
help='Description of an item being shared')
2020-04-03 10:08:04 +00:00
parser.add_argument('--itemImage', dest='itemImage', type=str,
default=None,
2019-07-23 21:39:07 +00:00
help='Filename of an image for an item being shared')
2020-04-03 10:08:04 +00:00
parser.add_argument('--itemType', dest='itemType', type=str,
default=None,
2019-07-23 21:39:07 +00:00
help='Type of item being shared')
2020-04-03 10:08:04 +00:00
parser.add_argument('--itemCategory', dest='itemCategory', type=str,
default=None,
2019-07-23 21:39:07 +00:00
help='Category of item being shared')
2020-04-03 10:08:04 +00:00
parser.add_argument('--location', dest='location', type=str, default=None,
2019-07-23 21:39:07 +00:00
help='Location/City of item being shared')
2020-04-03 10:08:04 +00:00
parser.add_argument('--duration', dest='duration', type=str, default=None,
2019-07-23 21:39:07 +00:00
help='Duration for which to share an item')
2020-04-03 10:08:04 +00:00
parser.add_argument('--registration', dest='registration', type=str,
2021-06-04 14:45:47 +00:00
default='open',
2019-08-08 10:50:58 +00:00
help='Whether new registrations are open or closed')
2020-04-03 10:08:04 +00:00
parser.add_argument("--nosharedinbox", type=str2bool, nargs='?',
const=True, default=False,
2019-11-15 22:07:06 +00:00
help='Disable shared inbox')
2020-04-03 10:08:04 +00:00
parser.add_argument('--maxregistrations', dest='maxRegistrations',
2021-06-04 14:45:47 +00:00
type=int, default=10,
2019-08-08 10:50:58 +00:00
help='The maximum number of new registrations')
2020-04-03 10:08:04 +00:00
parser.add_argument("--resetregistrations", type=str2bool, nargs='?',
const=True, default=False,
2019-08-08 10:50:58 +00:00
help="Reset the number of remaining registrations")
2019-07-03 10:31:02 +00:00
2020-04-03 10:08:04 +00:00
args = parser.parse_args()
debug = False
2019-07-03 16:14:45 +00:00
if args.debug:
2020-04-03 10:08:04 +00:00
debug = True
2021-03-14 19:24:57 +00:00
else:
if os.path.isfile('debug'):
debug = True
2019-07-03 16:14:45 +00:00
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()
2021-03-17 20:18:00 +00:00
testUpdateActor()
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
2020-04-03 10:08:04 +00:00
httpPrefix = 'https'
2020-06-19 11:12:26 +00:00
if args.http or args.i2p:
2020-04-03 10:08:04 +00:00
httpPrefix = 'http'
2020-06-09 12:07:43 +00:00
elif args.gnunet:
httpPrefix = 'gnunet'
2019-07-19 13:32:58 +00:00
2020-04-03 10:08:04 +00:00
baseDir = args.baseDir
2019-08-20 10:10:33 +00:00
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:
2020-07-08 09:21:36 +00:00
if '/users/' in args.posts:
postsNickname = getNicknameFromActor(args.posts)
postsDomain, postsPort = getDomainFromActor(args.posts)
2020-12-16 10:30:54 +00:00
args.posts = \
getFullDomain(postsNickname + '@' + postsDomain, postsPort)
2020-07-08 09:21:36 +00:00
else:
print('Syntax: --posts nickname@domain')
sys.exit()
2019-07-19 16:59:14 +00:00
if not args.http:
2020-04-03 10:08:04 +00:00
args.port = 443
nickname = args.posts.split('@')[0]
domain = args.posts.split('@')[1]
2020-06-09 11:03:59 +00:00
proxyType = None
if args.tor or domain.endswith('.onion'):
proxyType = 'tor'
2020-07-08 09:21:36 +00:00
if domain.endswith('.onion'):
args.port = 80
2020-06-09 11:03:59 +00:00
elif args.i2p or domain.endswith('.i2p'):
proxyType = 'i2p'
2020-07-08 09:21:36 +00:00
if domain.endswith('.i2p'):
args.port = 80
2020-06-09 11:51:51 +00:00
elif args.gnunet:
proxyType = 'gnunet'
2020-04-03 10:08:04 +00:00
getPublicPostsOfPerson(baseDir, nickname, domain, False, True,
2020-06-09 11:03:59 +00:00
proxyType, args.port, httpPrefix, debug,
2019-08-14 20:12:27 +00:00
__version__)
2019-07-03 11:24:38 +00:00
sys.exit()
2020-07-08 10:09:51 +00:00
if args.postDomains:
if '@' not in args.postDomains:
if '/users/' in args.postDomains:
2020-12-09 22:55:15 +00:00
postsNickname = getNicknameFromActor(args.postDomains)
postsDomain, postsPort = getDomainFromActor(args.postDomains)
2020-12-16 10:30:54 +00:00
args.postDomains = \
getFullDomain(postsNickname + '@' + postsDomain, postsPort)
2020-07-08 10:09:51 +00:00
else:
2020-07-08 10:17:30 +00:00
print('Syntax: --postDomains nickname@domain')
2020-07-08 10:09:51 +00:00
sys.exit()
if not args.http:
args.port = 443
nickname = args.postDomains.split('@')[0]
domain = args.postDomains.split('@')[1]
proxyType = None
if args.tor or domain.endswith('.onion'):
proxyType = 'tor'
if domain.endswith('.onion'):
args.port = 80
elif args.i2p or domain.endswith('.i2p'):
proxyType = 'i2p'
if domain.endswith('.i2p'):
args.port = 80
elif args.gnunet:
proxyType = 'gnunet'
wordFrequency = {}
2020-07-08 10:30:29 +00:00
domainList = []
2020-09-25 13:09:20 +00:00
domainList = getPublicPostDomains(None,
baseDir, nickname, domain,
proxyType, args.port,
httpPrefix, debug,
__version__,
wordFrequency, domainList)
2020-07-08 10:09:51 +00:00
for postDomain in domainList:
print(postDomain)
sys.exit()
if args.postDomainsBlocked:
# Domains which were referenced in public posts by a
# given handle but which are globally blocked on this instance
if '@' not in args.postDomainsBlocked:
if '/users/' in args.postDomainsBlocked:
2020-12-09 22:55:15 +00:00
postsNickname = getNicknameFromActor(args.postDomainsBlocked)
postsDomain, postsPort = \
getDomainFromActor(args.postDomainsBlocked)
2020-12-16 10:30:54 +00:00
args.postDomainsBlocked = \
getFullDomain(postsNickname + '@' + postsDomain, postsPort)
else:
print('Syntax: --postDomainsBlocked nickname@domain')
sys.exit()
if not args.http:
args.port = 443
nickname = args.postDomainsBlocked.split('@')[0]
domain = args.postDomainsBlocked.split('@')[1]
proxyType = None
if args.tor or domain.endswith('.onion'):
proxyType = 'tor'
if domain.endswith('.onion'):
args.port = 80
elif args.i2p or domain.endswith('.i2p'):
proxyType = 'i2p'
if domain.endswith('.i2p'):
args.port = 80
elif args.gnunet:
proxyType = 'gnunet'
wordFrequency = {}
domainList = []
2020-09-25 13:09:20 +00:00
domainList = getPublicPostDomainsBlocked(None,
baseDir, nickname, domain,
proxyType, args.port,
httpPrefix, debug,
__version__,
wordFrequency, domainList)
for postDomain in domainList:
print(postDomain)
sys.exit()
2020-09-25 12:33:28 +00:00
if args.checkDomains:
# Domains which were referenced in public posts by a
# given handle but which are globally blocked on this instance
if '@' not in args.checkDomains:
if '/users/' in args.checkDomains:
postsNickname = getNicknameFromActor(args.posts)
postsDomain, postsPort = getDomainFromActor(args.posts)
2020-12-16 10:30:54 +00:00
args.checkDomains = \
getFullDomain(postsNickname + '@' + postsDomain, postsPort)
2020-09-25 12:33:28 +00:00
else:
print('Syntax: --checkDomains nickname@domain')
sys.exit()
if not args.http:
args.port = 443
nickname = args.checkDomains.split('@')[0]
domain = args.checkDomains.split('@')[1]
proxyType = None
if args.tor or domain.endswith('.onion'):
proxyType = 'tor'
if domain.endswith('.onion'):
args.port = 80
elif args.i2p or domain.endswith('.i2p'):
proxyType = 'i2p'
if domain.endswith('.i2p'):
args.port = 80
elif args.gnunet:
proxyType = 'gnunet'
2020-09-25 14:38:21 +00:00
maxBlockedDomains = 0
2020-09-25 13:21:56 +00:00
checkDomains(None,
baseDir, nickname, domain,
proxyType, args.port,
httpPrefix, debug,
__version__,
maxBlockedDomains, False)
2020-09-25 12:33:28 +00:00
sys.exit()
2020-07-08 12:28:41 +00:00
if args.socnet:
if ',' not in args.socnet:
print('Syntax: '
'--socnet nick1@domain1,nick2@domain2,nick3@domain3')
sys.exit()
if not args.http:
args.port = 443
proxyType = 'tor'
dotGraph = instancesGraph(baseDir, args.socnet,
proxyType, args.port,
httpPrefix, debug,
__version__)
try:
2020-07-12 20:04:58 +00:00
with open('socnet.dot', 'w+') as fp:
2020-07-08 12:28:41 +00:00
fp.write(dotGraph)
print('Saved to socnet.dot')
except BaseException:
pass
sys.exit()
2019-07-03 11:24:38 +00:00
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')
2020-03-22 21:16:02 +00:00
sys.exit()
2019-07-19 16:59:14 +00:00
if not args.http:
2020-04-03 10:08:04 +00:00
args.port = 443
nickname = args.postsraw.split('@')[0]
domain = args.postsraw.split('@')[1]
2020-06-09 11:03:59 +00:00
proxyType = None
if args.tor or domain.endswith('.onion'):
proxyType = 'tor'
elif args.i2p or domain.endswith('.i2p'):
proxyType = 'i2p'
2020-06-09 11:51:51 +00:00
elif args.gnunet:
proxyType = 'gnunet'
2020-04-03 10:08:04 +00:00
getPublicPostsOfPerson(baseDir, nickname, domain, False, False,
2020-06-09 11:03:59 +00:00
proxyType, args.port, httpPrefix, debug,
2019-08-14 20:12:27 +00:00
__version__)
2019-07-03 10:33:55 +00:00
sys.exit()
2019-11-13 10:50:16 +00:00
if args.json:
2020-06-09 11:03:59 +00:00
session = createSession(None)
2020-04-03 10:08:04 +00:00
profileStr = 'https://www.w3.org/ns/activitystreams'
asHeader = {
'Accept': 'application/ld+json; profile="' + profileStr + '"'
2020-03-22 20:36:19 +00:00
}
2020-04-03 10:08:04 +00:00
testJson = getJson(session, args.json, asHeader, None,
2021-03-14 20:55:37 +00:00
debug, __version__, httpPrefix, None)
2019-11-13 10:50:16 +00:00
pprint(testJson)
sys.exit()
2019-08-20 10:10:33 +00:00
# create cache for actors
2020-04-03 10:08:04 +00:00
if not os.path.isdir(baseDir + '/cache'):
os.mkdir(baseDir + '/cache')
if not os.path.isdir(baseDir + '/cache/actors'):
2019-08-20 10:10:33 +00:00
print('Creating actors cache')
2020-04-03 10:08:04 +00:00
os.mkdir(baseDir + '/cache/actors')
if not os.path.isdir(baseDir + '/cache/announce'):
2019-08-20 12:39:59 +00:00
print('Creating announce cache')
2020-04-03 10:08:04 +00:00
os.mkdir(baseDir + '/cache/announce')
2019-07-05 09:20:54 +00:00
# set the theme in config.json
2020-04-03 10:08:04 +00:00
themeName = getConfigParam(baseDir, 'theme')
if not themeName:
2020-04-03 10:08:04 +00:00
setConfigParam(baseDir, 'theme', 'default')
themeName = 'default'
2019-11-13 12:45:41 +00:00
2019-11-28 16:16:43 +00:00
if not args.mediainstance:
2020-04-03 10:08:04 +00:00
mediaInstance = getConfigParam(baseDir, 'mediaInstance')
if mediaInstance is not None:
args.mediainstance = mediaInstance
if args.mediainstance:
args.blogsinstance = False
2020-10-07 09:10:42 +00:00
args.newsinstance = False
if not args.newsinstance:
newsInstance = getConfigParam(baseDir, 'newsInstance')
if newsInstance is not None:
args.newsinstance = newsInstance
if args.newsinstance:
args.blogsinstance = False
args.mediainstance = False
2020-02-24 14:39:25 +00:00
if not args.blogsinstance:
2020-04-03 10:08:04 +00:00
blogsInstance = getConfigParam(baseDir, 'blogsInstance')
if blogsInstance is not None:
args.blogsinstance = blogsInstance
if args.blogsinstance:
args.mediainstance = False
2020-10-07 09:10:42 +00:00
args.newsinstance = False
2020-03-22 21:16:02 +00:00
2019-11-13 12:45:41 +00:00
# set the instance title in config.json
2020-04-03 10:08:04 +00:00
title = getConfigParam(baseDir, 'instanceTitle')
2019-11-13 12:45:41 +00:00
if not title:
2020-04-03 10:08:04 +00:00
setConfigParam(baseDir, 'instanceTitle', 'Epicyon')
2019-11-13 12:45:41 +00:00
# set the instance description in config.json
2020-04-03 10:08:04 +00:00
descFull = getConfigParam(baseDir, 'instanceDescription')
2019-11-13 12:45:41 +00:00
if not descFull:
2020-04-03 10:08:04 +00:00
setConfigParam(baseDir, 'instanceDescription',
'Just another ActivityPub server')
2019-11-13 12:45:41 +00:00
# set the short instance description in config.json
2020-04-03 10:08:04 +00:00
descShort = getConfigParam(baseDir, 'instanceDescriptionShort')
2019-11-13 12:45:41 +00:00
if not descShort:
2020-04-03 10:08:04 +00:00
setConfigParam(baseDir, 'instanceDescriptionShort',
'Just another ActivityPub server')
2019-11-13 12:45:41 +00:00
2019-07-19 18:12:50 +00:00
if args.domain:
2020-04-03 10:08:04 +00:00
domain = args.domain
setConfigParam(baseDir, 'domain', domain)
2019-11-11 17:49:08 +00:00
2020-12-02 17:07:47 +00:00
if args.rss:
session = createSession(None)
testRSS = getRSS(baseDir, domain, session, args.rss,
False, False, 1000, 1000, 1000, 1000)
pprint(testRSS)
sys.exit()
if args.onion:
if not args.onion.endswith('.onion'):
2020-04-03 10:08:04 +00:00
print(args.onion + ' does not look like an onion domain')
sys.exit()
if '://' in args.onion:
2020-04-03 10:08:04 +00:00
args.onion = args.onion.split('://')[1]
onionDomain = args.onion
setConfigParam(baseDir, 'onion', onionDomain)
i2pDomain = None
if args.i2pDomain:
if not args.i2pDomain.endswith('.i2p'):
print(args.i2pDomain + ' does not look like an i2p domain')
sys.exit()
if '://' in args.i2pDomain:
args.onion = args.onion.split('://')[1]
i2pDomain = args.i2pDomain
setConfigParam(baseDir, 'i2pDomain', i2pDomain)
2019-11-11 17:49:08 +00:00
if not args.language:
2020-04-03 10:08:04 +00:00
languageCode = getConfigParam(baseDir, 'language')
2019-11-11 17:49:08 +00:00
if languageCode:
2020-04-03 10:08:04 +00:00
args.language = languageCode
2019-11-11 17:49:08 +00:00
2019-08-08 10:50:58 +00:00
# maximum number of new registrations
if not args.maxRegistrations:
2020-04-03 10:08:04 +00:00
maxRegistrations = getConfigParam(baseDir, 'maxRegistrations')
2019-08-08 10:50:58 +00:00
if not maxRegistrations:
2020-04-03 10:08:04 +00:00
maxRegistrations = 10
setConfigParam(baseDir, 'maxRegistrations', str(maxRegistrations))
2019-08-08 10:50:58 +00:00
else:
2020-04-03 10:08:04 +00:00
maxRegistrations = int(maxRegistrations)
2019-08-08 10:50:58 +00:00
else:
2020-04-03 10:08:04 +00:00
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
2020-04-03 10:08:04 +00:00
if not getConfigParam(baseDir, 'registration'):
2021-06-12 22:34:33 +00:00
if args.registration.lower() == 'open':
setConfigParam(baseDir, 'registration', 'open')
setConfigParam(baseDir, 'maxRegistrations', str(maxRegistrations))
2021-06-13 09:01:22 +00:00
setConfigParam(baseDir, 'registrationsRemaining',
str(maxRegistrations))
2019-08-08 10:50:58 +00:00
2020-03-22 21:16:02 +00:00
if args.resetregistrations:
2020-04-03 10:08:04 +00:00
setConfigParam(baseDir, 'registrationsRemaining', str(maxRegistrations))
print('Number of new registrations reset to ' + str(maxRegistrations))
2020-03-22 21:16:02 +00:00
2019-08-02 12:49:34 +00:00
# unique ID for the instance
2020-04-03 10:08:04 +00:00
instanceId = getConfigParam(baseDir, 'instanceId')
2019-08-02 12:49:34 +00:00
if not instanceId:
2020-04-03 10:08:04 +00:00
instanceId = createPassword(32)
setConfigParam(baseDir, 'instanceId', instanceId)
print('Instance ID: ' + instanceId)
2019-08-02 12:49:34 +00:00
2019-07-05 09:20:54 +00:00
# get domain name from configuration
2020-04-03 10:08:04 +00:00
configDomain = getConfigParam(baseDir, 'domain')
2019-07-05 09:20:54 +00:00
if configDomain:
2020-04-03 10:08:04 +00:00
domain = configDomain
2019-07-05 09:20:54 +00:00
else:
2020-04-03 10:08:04 +00:00
domain = 'localhost'
2019-07-05 09:20:54 +00:00
# get onion domain name from configuration
2020-04-03 10:08:04 +00:00
configOnionDomain = getConfigParam(baseDir, 'onion')
if configOnionDomain:
2020-04-03 10:08:04 +00:00
onionDomain = configOnionDomain
else:
2021-02-28 18:21:12 +00:00
onionDomain = None
# get i2p domain name from configuration
configi2pDomain = getConfigParam(baseDir, 'i2pDomain')
if configi2pDomain:
i2pDomain = configi2pDomain
else:
i2pDomain = None
2019-07-05 09:20:54 +00:00
# get port number from configuration
2020-04-03 10:08:04 +00:00
configPort = getConfigParam(baseDir, 'port')
2019-07-05 09:20:54 +00:00
if configPort:
2020-04-03 10:08:04 +00:00
port = configPort
2019-07-05 09:20:54 +00:00
else:
2021-02-02 12:25:30 +00:00
if domain.endswith('.onion') or \
domain.endswith('.i2p'):
port = 80
else:
port = 443
2019-07-05 09:20:54 +00:00
2020-04-03 10:08:04 +00:00
configProxyPort = getConfigParam(baseDir, 'proxyPort')
2019-08-14 13:52:19 +00:00
if configProxyPort:
2020-04-03 10:08:04 +00:00
proxyPort = configProxyPort
2019-08-14 13:52:19 +00:00
else:
2020-04-03 10:08:04 +00:00
proxyPort = port
2019-08-14 13:52:19 +00:00
2020-04-03 10:08:04 +00:00
nickname = None
2019-07-09 15:51:31 +00:00
if args.nickname:
2020-04-03 10:08:04 +00:00
nickname = nickname
2019-07-09 15:51:31 +00:00
2020-04-03 10:08:04 +00:00
federationList = []
2019-07-09 15:51:31 +00:00
if args.federationList:
2020-04-03 10:08:04 +00:00
if len(args.federationList) == 1:
if not (args.federationList[0].lower() == 'any' or
args.federationList[0].lower() == 'all' or
args.federationList[0].lower() == '*'):
2019-07-09 15:51:31 +00:00
for federationDomain in args.federationList:
if '@' in federationDomain:
2020-04-03 10:08:04 +00:00
print(federationDomain +
': Federate with domains, not individual accounts')
2019-07-09 15:51:31 +00:00
sys.exit()
2020-04-03 10:08:04 +00:00
federationList = args.federationList.copy()
setConfigParam(baseDir, 'federationList', federationList)
2019-07-09 15:51:31 +00:00
else:
2020-04-03 10:08:04 +00:00
configFederationList = getConfigParam(baseDir, 'federationList')
2019-07-09 15:51:31 +00:00
if configFederationList:
2020-04-03 10:08:04 +00:00
federationList = configFederationList
2019-07-09 15:51:31 +00:00
2020-06-09 11:03:59 +00:00
proxyType = None
if args.tor or domain.endswith('.onion'):
proxyType = 'tor'
elif args.i2p or domain.endswith('.i2p'):
proxyType = 'i2p'
2020-06-09 11:51:51 +00:00
elif args.gnunet:
proxyType = 'gnunet'
2019-07-09 15:58:51 +00:00
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()
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
sendThreads = []
postLog = []
cachedWebfingers = {}
personCache = {}
manualApproveFollowRequest(session, baseDir,
2019-07-20 18:25:40 +00:00
httpPrefix,
2020-04-03 10:08:04 +00:00
args.nickname, domain, port,
args.approve,
federationList,
sendThreads, postLog,
cachedWebfingers, personCache,
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()
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
sendThreads = []
postLog = []
cachedWebfingers = {}
personCache = {}
manualDenyFollowRequest(session, baseDir,
httpPrefix,
2020-04-03 10:08:04 +00:00
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()
2020-04-03 10:08:04 +00:00
accountsDir = baseDir + '/accounts/' + args.nickname + '@' + domain
approveFollowsFilename = accountsDir + '/followrequests.txt'
approveCtr = 0
if os.path.isfile(approveFollowsFilename):
with open(approveFollowsFilename, 'r') as approvefile:
for approve in approvefile:
2020-05-22 11:32:38 +00:00
print(approve.replace('\n', '').replace('\r', ''))
2020-04-03 10:08:04 +00:00
approveCtr += 1
if approveCtr == 0:
print('There are no follow requests pending approval.')
sys.exit()
2020-03-22 21:16:02 +00:00
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()
2020-03-22 21:16:02 +00:00
2019-07-16 16:43:28 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-03-22 21:16:02 +00:00
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2019-07-16 16:43:28 +00:00
if not args.sendto:
print('Specify an account to sent to: --sendto [nickname@domain]')
2020-03-22 21:16:02 +00:00
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:
2020-04-03 10:08:04 +00:00
toNickname = args.sendto.split('@')[0]
2020-05-22 11:32:38 +00:00
toDomain = args.sendto.split('@')[1]
toDomain = toDomain.replace('\n', '').replace('\r', '')
2020-04-03 10:08:04 +00:00
toPort = 443
2019-07-17 14:43:51 +00:00
if ':' in toDomain:
2020-04-03 10:08:04 +00:00
toPort = toDomain.split(':')[1]
toDomain = toDomain.split(':')[0]
2019-07-17 14:43:51 +00:00
else:
if args.sendto.endswith('followers'):
2020-04-03 10:08:04 +00:00
toNickname = None
toDomain = 'followers'
toPort = port
2019-07-17 14:43:51 +00:00
else:
2020-04-03 10:08:04 +00:00
toNickname = None
toDomain = 'public'
toPort = port
# ccUrl=httpPrefix+'://'+domain+'/users/'+nickname+'/followers'
ccUrl = None
sendMessage = args.message
followersOnly = args.followersonly
clientToServer = args.client
attachedImageDescription = args.imageDescription
2021-05-09 19:29:53 +00:00
city = 'London, England'
2020-04-03 10:08:04 +00:00
sendThreads = []
postLog = []
personCache = {}
cachedWebfingers = {}
subject = args.subject
attach = args.attach
mediaType = None
2019-08-30 15:50:20 +00:00
if attach:
2020-04-03 10:08:04 +00:00
mediaType = getAttachmentMediaType(attach)
replyTo = args.replyto
followersOnly = False
isArticle = False
print('Sending post to ' + args.sendto)
sendPostViaServer(__version__,
baseDir, session, args.nickname, args.password,
domain, port,
toNickname, toDomain, toPort, ccUrl,
httpPrefix, sendMessage, followersOnly,
2020-08-21 17:40:50 +00:00
args.commentsEnabled, attach, mediaType,
2021-05-09 19:11:05 +00:00
attachedImageDescription, city,
2020-04-03 10:08:04 +00:00
cachedWebfingers, personCache, isArticle,
args.debug, replyTo, replyTo, subject)
2019-07-16 16:43:28 +00:00
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()
2020-03-22 21:16:02 +00:00
2019-07-16 20:08:30 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-03-22 21:16:02 +00:00
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending announce/repeat of ' + args.announce)
2019-07-16 20:08:30 +00:00
2020-04-03 10:08:04 +00:00
sendAnnounceViaServer(baseDir, session, args.nickname, args.password,
domain, port,
httpPrefix, args.announce,
cachedWebfingers, personCache,
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()
2021-03-18 11:03:39 +00:00
if args.box:
if not domain:
print('Specify a domain with the --domain option')
sys.exit()
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
proxyType = None
if args.tor or domain.endswith('.onion'):
proxyType = 'tor'
if domain.endswith('.onion'):
args.port = 80
elif args.i2p or domain.endswith('.i2p'):
proxyType = 'i2p'
if domain.endswith('.i2p'):
args.port = 80
elif args.gnunet:
proxyType = 'gnunet'
session = createSession(proxyType)
boxJson = c2sBoxJson(baseDir, session,
args.nickname, args.password,
domain, port, httpPrefix,
args.box, args.pageNumber,
args.debug)
if boxJson:
pprint(boxJson)
else:
print('Box not found: ' + args.box)
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:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2019-07-23 21:39:07 +00:00
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.summary:
2020-04-03 10:08:04 +00:00
print('Specify a description for your shared item ' +
'with the --summary option')
2019-07-23 21:39:07 +00:00
sys.exit()
if not args.itemType:
print('Specify a type of shared item with the --itemType option')
sys.exit()
if not args.itemCategory:
2020-04-03 10:08:04 +00:00
print('Specify a category of shared item ' +
'with the --itemCategory option')
2019-07-23 21:39:07 +00:00
sys.exit()
if not args.location:
2020-04-03 10:08:04 +00:00
print('Specify a location or city where theshared ' +
'item resides with the --location option')
2019-07-23 21:39:07 +00:00
sys.exit()
if not args.duration:
2020-04-03 10:08:04 +00:00
print('Specify a duration to share the object ' +
'with the --duration option')
sys.exit()
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending shared item: ' + args.itemName)
sendShareViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix,
args.itemName,
args.summary,
args.itemImage,
args.itemType,
args.itemCategory,
args.location,
args.duration,
cachedWebfingers, personCache,
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:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2019-07-23 21:45:53 +00:00
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending undo of shared item: ' + args.undoItemName)
2019-07-23 21:45:53 +00:00
sendUndoShareViaServer(baseDir, session,
2020-04-03 10:08:04 +00:00
args.nickname, args.password,
domain, port,
httpPrefix,
args.undoItemName,
cachedWebfingers, personCache,
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()
2020-03-22 21:16:02 +00:00
2019-07-17 18:33:41 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-03-22 21:16:02 +00:00
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending like of ' + args.like)
2019-07-17 18:33:41 +00:00
2020-04-03 10:08:04 +00:00
sendLikeViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix, args.like,
cachedWebfingers, personCache,
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()
2020-03-22 21:16:02 +00:00
2019-07-17 19:04:00 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-03-22 21:16:02 +00:00
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending undo like of ' + args.undolike)
2019-07-17 19:04:00 +00:00
2020-04-03 10:08:04 +00:00
sendUndoLikeViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix, args.undolike,
cachedWebfingers, personCache,
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()
2021-03-20 10:43:52 +00:00
if args.bookmark:
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
session = createSession(proxyType)
personCache = {}
cachedWebfingers = {}
print('Sending bookmark of ' + args.bookmark)
sendBookmarkViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix, args.bookmark,
cachedWebfingers, personCache,
True, __version__)
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
if args.unbookmark:
if not args.nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
session = createSession(proxyType)
personCache = {}
cachedWebfingers = {}
print('Sending undo bookmark of ' + args.unbookmark)
sendUndoBookmarkViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix, args.unbookmark,
cachedWebfingers, personCache,
True, __version__)
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()
2020-03-22 21:16:02 +00:00
2019-07-17 17:29:33 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-03-22 21:16:02 +00:00
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending delete request of ' + args.delete)
2019-07-17 17:29:33 +00:00
2020-04-03 10:08:04 +00:00
sendDeleteViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix, args.delete,
cachedWebfingers, personCache,
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:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-03-22 21:16:02 +00:00
2020-04-03 10:08:04 +00:00
followNickname = getNicknameFromActor(args.follow)
2019-09-02 09:43:43 +00:00
if not followNickname:
2020-04-03 10:08:04 +00:00
print('Unable to find nickname in ' + args.follow)
2020-03-22 21:16:02 +00:00
sys.exit()
2020-04-03 10:08:04 +00:00
followDomain, followPort = getDomainFromActor(args.follow)
2019-07-09 15:51:31 +00:00
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
followHttpPrefix = httpPrefix
2019-07-09 15:51:31 +00:00
if args.follow.startswith('https'):
2020-04-03 10:08:04 +00:00
followHttpPrefix = 'https'
sendFollowRequestViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
followNickname, followDomain, followPort,
httpPrefix,
cachedWebfingers, personCache,
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:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-03-22 21:16:02 +00:00
2020-04-03 10:08:04 +00:00
followNickname = getNicknameFromActor(args.unfollow)
2019-09-02 09:43:43 +00:00
if not followNickname:
2020-04-03 10:08:04 +00:00
print('WARN: unable to find nickname in ' + args.unfollow)
2020-03-22 21:16:02 +00:00
sys.exit()
2020-04-03 10:08:04 +00:00
followDomain, followPort = getDomainFromActor(args.unfollow)
2019-07-17 12:25:02 +00:00
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
followHttpPrefix = httpPrefix
2019-07-17 12:25:02 +00:00
if args.follow.startswith('https'):
2020-04-03 10:08:04 +00:00
followHttpPrefix = 'https'
sendUnfollowRequestViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
followNickname, followDomain, followPort,
httpPrefix,
cachedWebfingers, personCache,
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()
2021-03-24 13:52:20 +00:00
if args.followingList:
2021-03-24 12:43:24 +00:00
# following list via c2s protocol
if not args.nickname:
print('Please specify the nickname for the account with --nickname')
sys.exit()
if not args.password:
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
session = createSession(proxyType)
personCache = {}
cachedWebfingers = {}
followHttpPrefix = httpPrefix
followingJson = \
getFollowingViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix, args.pageNumber,
cachedWebfingers, personCache,
debug, __version__)
if followingJson:
pprint(followingJson)
sys.exit()
2021-03-24 13:52:20 +00:00
if args.followersList:
# following list via c2s protocol
if not args.nickname:
print('Please specify the nickname for the account with --nickname')
sys.exit()
if not args.password:
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
session = createSession(proxyType)
personCache = {}
cachedWebfingers = {}
followHttpPrefix = httpPrefix
followersJson = \
getFollowersViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix, args.pageNumber,
cachedWebfingers, personCache,
debug, __version__)
if followersJson:
pprint(followersJson)
sys.exit()
if args.followRequestsList:
# follow requests list via c2s protocol
if not args.nickname:
print('Please specify the nickname for the account with --nickname')
sys.exit()
if not args.password:
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
session = createSession(proxyType)
personCache = {}
cachedWebfingers = {}
followHttpPrefix = httpPrefix
followRequestsJson = \
getFollowRequestsViaServer(baseDir, session,
args.nickname, args.password,
domain, port,
httpPrefix, args.pageNumber,
cachedWebfingers, personCache,
debug, __version__)
if followRequestsJson:
pprint(followRequestsJson)
sys.exit()
2020-04-03 10:08:04 +00:00
nickname = 'admin'
2019-07-05 09:20:54 +00:00
if args.domain:
2020-04-03 10:08:04 +00:00
domain = args.domain
setConfigParam(baseDir, 'domain', domain)
2019-07-05 09:20:54 +00:00
if args.port:
2020-04-03 10:08:04 +00:00
port = args.port
setConfigParam(baseDir, 'port', port)
2019-08-14 13:52:19 +00:00
if args.proxyPort:
2020-04-03 10:08:04 +00:00
proxyPort = args.proxyPort
setConfigParam(baseDir, 'proxyPort', proxyPort)
2020-06-09 11:51:51 +00:00
if args.gnunet:
httpPrefix = 'gnunet'
2019-07-03 19:00:03 +00:00
if args.dat:
2020-04-03 10:08:04 +00:00
httpPrefix = 'dat'
2020-05-17 09:37:59 +00:00
if args.hyper:
httpPrefix = 'hyper'
2020-02-17 17:18:21 +00:00
if args.i2p:
2020-06-19 11:12:26 +00:00
httpPrefix = 'http'
2019-07-04 22:44:32 +00:00
if args.migrations:
cachedWebfingers = {}
if args.http or domain.endswith('.onion'):
httpPrefix = 'http'
port = 80
proxyType = 'tor'
elif domain.endswith('.i2p'):
httpPrefix = 'http'
port = 80
proxyType = 'i2p'
elif args.gnunet:
httpPrefix = 'gnunet'
port = 80
proxyType = 'gnunet'
else:
httpPrefix = 'https'
port = 443
session = createSession(proxyType)
ctr = migrateAccounts(baseDir, session,
httpPrefix, cachedWebfingers,
True)
if ctr == 0:
print('No followed accounts have moved')
else:
print(str(ctr) + ' followed accounts were migrated')
sys.exit()
2019-07-05 15:53:26 +00:00
if args.actor:
2021-03-17 20:31:55 +00:00
getActorJson(args.actor, args.http, args.gnunet, debug)
2019-07-05 15:53:26 +00:00
sys.exit()
2021-01-10 21:38:28 +00:00
if args.followers:
originalActor = args.followers
if '/@' in args.followers or \
'/users/' in args.followers or \
args.followers.startswith('http') or \
args.followers.startswith('dat'):
# format: https://domain/@nick
prefixes = getProtocolPrefixes()
for prefix in prefixes:
args.followers = args.followers.replace(prefix, '')
args.followers = args.followers.replace('/@', '/users/')
if not hasUsersPath(args.followers):
print('Expected actor format: ' +
'https://domain/@nick or https://domain/users/nick')
sys.exit()
if '/users/' in args.followers:
nickname = args.followers.split('/users/')[1]
nickname = nickname.replace('\n', '').replace('\r', '')
domain = args.followers.split('/users/')[0]
elif '/profile/' in args.followers:
nickname = args.followers.split('/profile/')[1]
nickname = nickname.replace('\n', '').replace('\r', '')
domain = args.followers.split('/profile/')[0]
elif '/channel/' in args.followers:
nickname = args.followers.split('/channel/')[1]
nickname = nickname.replace('\n', '').replace('\r', '')
domain = args.followers.split('/channel/')[0]
elif '/accounts/' in args.followers:
nickname = args.followers.split('/accounts/')[1]
nickname = nickname.replace('\n', '').replace('\r', '')
domain = args.followers.split('/accounts/')[0]
2021-02-09 17:00:35 +00:00
elif '/u/' in args.followers:
nickname = args.followers.split('/u/')[1]
nickname = nickname.replace('\n', '').replace('\r', '')
domain = args.followers.split('/u/')[0]
2021-01-10 21:38:28 +00:00
else:
# format: @nick@domain
if '@' not in args.followers:
print('Syntax: --actor nickname@domain')
sys.exit()
if args.followers.startswith('@'):
args.followers = args.followers[1:]
if '@' not in args.followers:
print('Syntax: --actor nickname@domain')
sys.exit()
nickname = args.followers.split('@')[0]
domain = args.followers.split('@')[1]
domain = domain.replace('\n', '').replace('\r', '')
cachedWebfingers = {}
if args.http or domain.endswith('.onion'):
httpPrefix = 'http'
port = 80
proxyType = 'tor'
elif domain.endswith('.i2p'):
httpPrefix = 'http'
port = 80
proxyType = 'i2p'
elif args.gnunet:
httpPrefix = 'gnunet'
port = 80
proxyType = 'gnunet'
else:
httpPrefix = 'https'
port = 443
session = createSession(proxyType)
if nickname == 'inbox':
nickname = domain
handle = nickname + '@' + domain
wfRequest = webfingerHandle(session, handle,
httpPrefix, cachedWebfingers,
2021-03-14 19:22:58 +00:00
None, __version__, debug)
2021-01-10 21:38:28 +00:00
if not wfRequest:
print('Unable to webfinger ' + handle)
sys.exit()
if not isinstance(wfRequest, dict):
print('Webfinger for ' + handle + ' did not return a dict. ' +
str(wfRequest))
sys.exit()
personUrl = None
if wfRequest.get('errors'):
print('wfRequest error: ' + str(wfRequest['errors']))
if hasUsersPath(args.followers):
personUrl = originalActor
else:
sys.exit()
profileStr = 'https://www.w3.org/ns/activitystreams'
asHeader = {
'Accept': 'application/activity+json; profile="' + profileStr + '"'
}
if not personUrl:
personUrl = getUserUrl(wfRequest)
if nickname == domain:
personUrl = personUrl.replace('/users/', '/actor/')
personUrl = personUrl.replace('/accounts/', '/actor/')
personUrl = personUrl.replace('/channel/', '/actor/')
personUrl = personUrl.replace('/profile/', '/actor/')
2021-02-09 17:00:35 +00:00
personUrl = personUrl.replace('/u/', '/actor/')
2021-01-10 21:38:28 +00:00
if not personUrl:
# try single user instance
personUrl = httpPrefix + '://' + domain
profileStr = 'https://www.w3.org/ns/activitystreams'
asHeader = {
'Accept': 'application/ld+json; profile="' + profileStr + '"'
}
if '/channel/' in personUrl or '/accounts/' in personUrl:
profileStr = 'https://www.w3.org/ns/activitystreams'
asHeader = {
'Accept': 'application/ld+json; profile="' + profileStr + '"'
}
followersList = \
downloadFollowCollection('followers', session,
httpPrefix, personUrl, 1, 3)
2021-01-10 21:38:28 +00:00
if followersList:
for actor in followersList:
print(actor)
sys.exit()
2019-07-04 22:44:32 +00:00
if args.addaccount:
if '@' in args.addaccount:
2020-04-03 10:08:04 +00:00
nickname = args.addaccount.split('@')[0]
domain = args.addaccount.split('@')[1]
2019-07-04 22:44:32 +00:00
else:
2020-04-03 10:08:04 +00:00
nickname = args.addaccount
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()
configuredDomain = getConfigParam(baseDir, 'domain')
if configuredDomain:
if domain != configuredDomain:
print('The account domain is expected to be ' + configuredDomain)
sys.exit()
2020-04-03 10:08:04 +00:00
if not validNickname(domain, nickname):
print(nickname + ' is a reserved name. Use something different.')
2020-03-22 21:16:02 +00:00
sys.exit()
2021-03-13 11:49:05 +00:00
2019-07-05 09:20:54 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-04-03 10:08:04 +00:00
if len(args.password.strip()) < 8:
2019-07-05 09:20:54 +00:00
print('Password should be at least 8 characters')
2020-03-22 21:16:02 +00:00
sys.exit()
2020-04-03 10:08:04 +00:00
if os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
2019-07-04 22:50:40 +00:00
print('Account already exists')
sys.exit()
2020-04-03 10:08:04 +00:00
if os.path.isdir(baseDir + '/deactivated/' + nickname + '@' + domain):
print('Account is deactivated')
sys.exit()
2021-02-02 11:47:49 +00:00
if domain.endswith('.onion') or \
domain.endswith('.i2p'):
2021-02-02 12:25:30 +00:00
port = 80
httpPrefix = 'http'
2020-04-03 10:08:04 +00:00
createPerson(baseDir, nickname, domain, port, httpPrefix,
2020-07-12 12:31:28 +00:00
True, not args.noapproval, args.password.strip())
2020-04-03 10:08:04 +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:
2020-04-03 10:08:04 +00:00
nickname = args.addgroup.split('@')[0]
domain = args.addgroup.split('@')[1]
2019-10-04 12:39:46 +00:00
else:
2020-04-03 10:08:04 +00:00
nickname = args.addgroup
if not args.domain or not getConfigParam(baseDir, 'domain'):
2019-10-04 12:39:46 +00:00
print('Use the --domain option to set the domain name')
sys.exit()
2020-04-03 10:08:04 +00:00
if not validNickname(domain, nickname):
print(nickname + ' is a reserved name. Use something different.')
2019-10-04 12:39:46 +00:00
sys.exit()
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2020-04-03 10:08:04 +00:00
if len(args.password.strip()) < 8:
2019-10-04 12:39:46 +00:00
print('Password should be at least 8 characters')
sys.exit()
2020-04-03 10:08:04 +00:00
if os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
2019-10-04 12:39:46 +00:00
print('Group already exists')
sys.exit()
2020-04-03 10:08:04 +00:00
createGroup(baseDir, nickname, domain, port, httpPrefix,
True, args.password.strip())
if os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
print('Group created for ' + nickname + '@' + domain)
2019-10-04 12:39:46 +00:00
else:
print('Group creation failed')
sys.exit()
2019-10-04 12:59:31 +00:00
if args.rmgroup:
2020-04-03 10:08:04 +00:00
args.rmaccount = args.rmgroup
2019-10-04 12:59:31 +00:00
2019-11-05 10:37:37 +00:00
if args.deactivate:
2020-04-03 10:08:04 +00:00
args.rmaccount = args.deactivate
2019-11-05 10:37:37 +00:00
2019-07-04 22:50:40 +00:00
if args.rmaccount:
if '@' in args.rmaccount:
2020-04-03 10:08:04 +00:00
nickname = args.rmaccount.split('@')[0]
domain = args.rmaccount.split('@')[1]
2019-07-04 22:50:40 +00:00
else:
2020-04-03 10:08:04 +00:00
nickname = args.rmaccount
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()
if args.domain:
domain = args.domain
else:
domain = getConfigParam(baseDir, 'domain')
configuredDomain = getConfigParam(baseDir, 'domain')
if configuredDomain:
if domain != configuredDomain:
print('The account domain is expected to be ' + configuredDomain)
sys.exit()
2019-11-05 10:37:37 +00:00
if args.deactivate:
2020-04-03 10:08:04 +00:00
if deactivateAccount(baseDir, nickname, domain):
print('Account for ' + nickname + '@' + domain +
' was deactivated')
2019-11-05 10:37:37 +00:00
else:
2020-04-03 10:08:04 +00:00
print('Account for ' + nickname + '@' + domain + ' was not found')
2019-11-05 10:37:37 +00:00
sys.exit()
2020-04-03 10:08:04 +00:00
if removeAccount(baseDir, nickname, domain, port):
2019-10-04 12:59:31 +00:00
if not args.rmgroup:
2020-04-03 10:08:04 +00:00
print('Account for ' + nickname + '@' + domain + ' was removed')
2019-10-04 12:59:31 +00:00
else:
2020-04-03 10:08:04 +00:00
print('Group ' + nickname + '@' + domain + ' was removed')
2019-10-04 12:59:31 +00:00
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:
2020-04-03 10:08:04 +00:00
nickname = args.activate.split('@')[0]
domain = args.activate.split('@')[1]
2019-11-05 10:40:44 +00:00
else:
2020-04-03 10:08:04 +00:00
nickname = args.activate
if not args.domain or not getConfigParam(baseDir, 'domain'):
2019-11-05 10:40:44 +00:00
print('Use the --domain option to set the domain name')
sys.exit()
2020-04-03 10:08:04 +00:00
if activateAccount(baseDir, nickname, domain):
print('Account for ' + nickname + '@' + domain + ' was activated')
2019-11-05 10:40:44 +00:00
else:
2020-04-03 10:08:04 +00:00
print('Deactivated account for ' + nickname + '@' + domain +
' was not found')
2019-11-05 10:40:44 +00:00
sys.exit()
2019-07-05 09:44:15 +00:00
if args.changepassword:
2020-04-03 10:08:04 +00:00
if len(args.changepassword) != 2:
2019-07-05 09:44:15 +00:00
print('--changepassword [nickname] [new password]')
sys.exit()
if '@' in args.changepassword[0]:
2020-04-03 10:08:04 +00:00
nickname = args.changepassword[0].split('@')[0]
domain = args.changepassword[0].split('@')[1]
2019-07-05 09:44:15 +00:00
else:
2020-04-03 10:08:04 +00:00
nickname = args.changepassword[0]
if not args.domain or not getConfigParam(baseDir, 'domain'):
2019-07-05 09:44:15 +00:00
print('Use the --domain option to set the domain name')
sys.exit()
2020-04-03 10:08:04 +00:00
newPassword = args.changepassword[1]
if len(newPassword) < 8:
2019-07-05 09:44:15 +00:00
print('Password should be at least 8 characters')
sys.exit()
2020-04-03 10:08:04 +00:00
if not os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
print('Account ' + nickname + '@' + domain + ' not found')
2019-07-05 09:58:58 +00:00
sys.exit()
2020-04-03 10:08:04 +00:00
passwordFile = baseDir + '/accounts/passwords'
2019-07-05 09:44:15 +00:00
if os.path.isfile(passwordFile):
2020-04-03 10:08:04 +00:00
if nickname + ':' in open(passwordFile).read():
storeBasicCredentials(baseDir, nickname, newPassword)
print('Password for ' + nickname + ' was changed')
2019-07-05 09:44:15 +00:00
else:
2020-04-03 10:08:04 +00:00
print(nickname + ' is not in the passwords file')
2019-07-05 09:44:15 +00:00
else:
print('Passwords file not found')
sys.exit()
2019-07-12 20:51:02 +00:00
if args.archive:
if args.archive.lower().endswith('null') or \
args.archive.lower().endswith('delete') or \
args.archive.lower().endswith('none'):
2020-04-03 10:08:04 +00:00
args.archive = None
2019-07-12 20:51:02 +00:00
print('Archiving with deletion of old posts...')
else:
2020-04-03 10:08:04 +00:00
print('Archiving to ' + args.archive + '...')
2020-12-08 14:09:54 +00:00
archiveMedia(baseDir, args.archive, args.archiveWeeks)
archivePosts(baseDir, httpPrefix, args.archive, {}, args.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):
2020-04-03 10:08:04 +00:00
print(args.avatar + ' is not an image filename')
2019-07-12 14:31:56 +00:00
sys.exit()
if not args.nickname:
print('Specify a nickname with --nickname [name]')
sys.exit()
2021-05-09 19:29:53 +00:00
city = 'London, England'
2020-04-03 10:08:04 +00:00
if setProfileImage(baseDir, httpPrefix, args.nickname, domain,
2021-05-09 19:11:05 +00:00
port, args.avatar, 'avatar', '128x128', city):
2020-04-03 10:08:04 +00:00
print('Avatar added for ' + args.nickname)
2019-07-12 14:31:56 +00:00
else:
2020-04-03 10:08:04 +00:00
print('Avatar was not added for ' + args.nickname)
2020-03-22 21:16:02 +00:00
sys.exit()
if args.backgroundImage:
if not os.path.isfile(args.backgroundImage):
2020-04-03 10:08:04 +00:00
print(args.backgroundImage + ' is not an image filename')
sys.exit()
if not args.nickname:
print('Specify a nickname with --nickname [name]')
sys.exit()
2021-05-09 19:29:53 +00:00
city = 'London, England'
2020-04-03 10:08:04 +00:00
if setProfileImage(baseDir, httpPrefix, args.nickname, domain,
2021-05-09 19:11:05 +00:00
port, args.backgroundImage, 'background',
'256x256', city):
2020-04-03 10:08:04 +00:00
print('Background image added for ' + args.nickname)
else:
2020-04-03 10:08:04 +00:00
print('Background image was not added for ' + args.nickname)
2020-03-22 21:16:02 +00:00
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()
2020-03-22 21:16:02 +00:00
2019-07-19 10:01:24 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2019-07-19 10:01:24 +00:00
if not args.skillLevelPercent:
print('Specify a skill level in the range 0-100')
sys.exit()
2020-04-03 10:08:04 +00:00
if int(args.skillLevelPercent) < 0 or \
int(args.skillLevelPercent) > 100:
2019-07-19 10:01:24 +00:00
print('Skill level should be a percentage in the range 0-100')
sys.exit()
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending ' + args.skill + ' skill level ' +
str(args.skillLevelPercent) + ' for ' + nickname)
2019-07-19 10:01:24 +00:00
2020-04-03 10:08:04 +00:00
sendSkillViaServer(baseDir, session,
nickname, args.password,
domain, port,
httpPrefix,
args.skill, args.skillLevelPercent,
cachedWebfingers, personCache,
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()
2020-03-22 21:16:02 +00:00
2019-07-19 11:38:37 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2019-07-19 11:38:37 +00:00
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending availability status of ' + nickname +
' as ' + args.availability)
2019-07-19 11:38:37 +00:00
2020-04-03 10:08:04 +00:00
sendAvailabilityViaServer(baseDir, session, nickname, args.password,
domain, port,
httpPrefix,
args.availability,
cachedWebfingers, personCache,
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()
2021-03-16 22:14:03 +00:00
if args.desktop:
2021-03-01 19:16:33 +00:00
# Announce posts as they arrive in your inbox using text-to-speech
2021-03-16 22:15:49 +00:00
if args.desktop.startswith('@'):
args.desktop = args.desktop[1:]
if '@' not in args.desktop:
print('Specify the handle to notify: nickname@domain')
2021-03-01 19:16:33 +00:00
sys.exit()
2021-03-16 22:15:49 +00:00
nickname = args.desktop.split('@')[0]
domain = args.desktop.split('@')[1]
2021-03-01 19:16:33 +00:00
if not nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
2021-03-13 11:13:35 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
2021-03-01 19:16:33 +00:00
2021-03-13 11:15:52 +00:00
args.password = args.password.replace('\n', '')
2021-03-01 19:16:33 +00:00
proxyType = None
if args.tor or domain.endswith('.onion'):
proxyType = 'tor'
if domain.endswith('.onion'):
args.port = 80
elif args.i2p or domain.endswith('.i2p'):
proxyType = 'i2p'
if domain.endswith('.i2p'):
args.port = 80
elif args.gnunet:
proxyType = 'gnunet'
# only store inbox posts if we are not running as a daemon
storeInboxPosts = not args.noKeyPress
2021-03-17 10:04:49 +00:00
runDesktopClient(baseDir, proxyType, httpPrefix,
nickname, domain, port, args.password,
args.screenreader, args.language,
args.notificationSounds,
args.notificationType,
args.noKeyPress,
storeInboxPosts,
args.notifyShowNewPosts,
2021-03-18 17:27:46 +00:00
args.language,
2021-03-17 10:04:49 +00:00
args.debug)
2021-03-01 19:16:33 +00:00
sys.exit()
2019-07-05 09:20:54 +00:00
if federationList:
2020-04-03 10:08:04 +00:00
print('Federating with: ' + str(federationList))
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()
2020-03-22 21:16:02 +00:00
2019-07-17 22:09:09 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2019-07-17 22:09:09 +00:00
if '@' in args.block:
2020-05-22 11:32:38 +00:00
blockedDomain = args.block.split('@')[1]
blockedDomain = blockedDomain.replace('\n', '').replace('\r', '')
2020-04-03 10:08:04 +00:00
blockedNickname = args.block.split('@')[0]
blockedActor = httpPrefix + '://' + blockedDomain + \
'/users/' + blockedNickname
args.block = blockedActor
2019-07-17 22:09:09 +00:00
else:
if '/users/' not in args.block:
2020-04-03 10:08:04 +00:00
print(args.block + ' does not look like an actor url')
2019-07-17 22:09:09 +00:00
sys.exit()
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending block of ' + args.block)
2019-07-17 22:09:09 +00:00
2020-04-03 10:08:04 +00:00
sendBlockViaServer(baseDir, session, nickname, args.password,
domain, port,
httpPrefix, args.block,
cachedWebfingers, personCache,
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()
2021-03-20 21:20:41 +00:00
if args.mute:
if not nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
session = createSession(proxyType)
personCache = {}
cachedWebfingers = {}
print('Sending mute of ' + args.mute)
sendMuteViaServer(baseDir, session, nickname, args.password,
domain, port,
httpPrefix, args.mute,
cachedWebfingers, personCache,
True, __version__)
for i in range(10):
# TODO detect send success/fail
time.sleep(1)
sys.exit()
if args.unmute:
if not nickname:
print('Specify a nickname with the --nickname option')
sys.exit()
if not args.password:
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
session = createSession(proxyType)
personCache = {}
cachedWebfingers = {}
print('Sending undo mute of ' + args.unmute)
sendUndoMuteViaServer(baseDir, session, nickname, args.password,
domain, port,
httpPrefix, args.unmute,
cachedWebfingers, personCache,
True, __version__)
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()
2020-03-22 21:16:02 +00:00
2019-07-17 22:09:09 +00:00
if not args.password:
2021-03-13 11:49:05 +00:00
args.password = getpass.getpass('Password: ')
if not args.password:
print('Specify a password with the --password option')
sys.exit()
args.password = args.password.replace('\n', '')
2019-07-17 22:09:09 +00:00
if '@' in args.unblock:
2020-05-22 11:32:38 +00:00
blockedDomain = args.unblock.split('@')[1]
blockedDomain = blockedDomain.replace('\n', '').replace('\r', '')
2020-04-03 10:08:04 +00:00
blockedNickname = args.unblock.split('@')[0]
blockedActor = httpPrefix + '://' + blockedDomain + \
'/users/' + blockedNickname
args.unblock = blockedActor
2019-07-17 22:09:09 +00:00
else:
if '/users/' not in args.unblock:
2020-04-03 10:08:04 +00:00
print(args.unblock + ' does not look like an actor url')
2019-07-17 22:09:09 +00:00
sys.exit()
2020-06-09 11:03:59 +00:00
session = createSession(proxyType)
2020-04-03 10:08:04 +00:00
personCache = {}
cachedWebfingers = {}
print('Sending undo block of ' + args.unblock)
2019-07-17 22:09:09 +00:00
2020-04-03 10:08:04 +00:00
sendUndoBlockViaServer(baseDir, session, nickname, args.password,
domain, port,
httpPrefix, args.unblock,
cachedWebfingers, personCache,
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()
2020-04-03 10:08:04 +00:00
if addFilter(baseDir, args.nickname, domain, args.filterStr):
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()
2020-04-03 10:08:04 +00:00
if removeFilter(baseDir, args.nickname, domain, args.unfilterStr):
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:
2021-05-09 19:29:53 +00:00
city = 'London, England'
2020-04-03 10:08:04 +00:00
nickname = 'testuser567'
password = 'boringpassword'
print('Generating some test data for user: ' + nickname)
if os.path.isdir(baseDir + '/tags'):
shutil.rmtree(baseDir + '/tags')
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')
setConfigParam(baseDir, 'registrationsRemaining',
str(maxRegistrations))
createPerson(baseDir, 'maxboardroom', domain, port, httpPrefix,
2020-07-12 12:31:28 +00:00
True, False, password)
2020-04-03 10:08:04 +00:00
createPerson(baseDir, 'ultrapancake', domain, port, httpPrefix,
2020-07-12 12:31:28 +00:00
True, False, password)
2020-04-03 10:08:04 +00:00
createPerson(baseDir, 'drokk', domain, port, httpPrefix,
2020-07-12 12:31:28 +00:00
True, False, password)
2020-04-03 10:08:04 +00:00
createPerson(baseDir, 'sausagedog', domain, port, httpPrefix,
2020-07-12 12:31:28 +00:00
True, False, password)
2020-04-03 10:08:04 +00:00
createPerson(baseDir, nickname, domain, port, httpPrefix,
2020-07-12 12:31:28 +00:00
True, False, 'likewhateveryouwantscoob')
2020-04-03 10:08:04 +00:00
setSkillLevel(baseDir, nickname, domain, 'testing', 60)
setSkillLevel(baseDir, nickname, domain, 'typing', 50)
setRole(baseDir, nickname, domain, 'admin')
2020-04-03 10:08:04 +00:00
setAvailability(baseDir, nickname, domain, 'busy')
addShare(baseDir,
httpPrefix, nickname, domain, port,
"spanner",
"It's a spanner",
"img/shares1.png",
"tool",
"mechanical",
"City",
2019-07-23 22:12:19 +00:00
"2 months",
2021-05-09 19:11:05 +00:00
debug, city)
2020-04-03 10:08:04 +00:00
addShare(baseDir,
httpPrefix, nickname, domain, port,
"witch hat",
"Spooky",
"img/shares2.png",
"hat",
"clothing",
"City",
2019-07-23 22:12:19 +00:00
"3 months",
2021-05-09 19:11:05 +00:00
debug, city)
2020-03-22 21:16:02 +00:00
2020-04-03 10:08:04 +00:00
deleteAllPosts(baseDir, nickname, domain, 'inbox')
deleteAllPosts(baseDir, nickname, domain, 'outbox')
testFollowersOnly = False
testSaveToFile = True
2021-03-17 20:18:00 +00:00
testC2S = False
testCommentsEnabled = True
testAttachImageFilename = None
testMediaType = None
testImageDescription = None
2021-05-09 19:29:53 +00:00
testCity = 'London, England'
2020-04-03 10:08:04 +00:00
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"like this is totally just a #test man",
testFollowersOnly,
testSaveToFile,
2021-03-17 20:18:00 +00:00
testC2S,
testCommentsEnabled,
testAttachImageFilename,
2021-05-09 19:11:05 +00:00
testMediaType, testImageDescription, testCity)
2020-04-03 10:08:04 +00:00
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Zoiks!!!",
testFollowersOnly,
testSaveToFile,
2021-03-17 20:18:00 +00:00
testC2S,
testCommentsEnabled,
testAttachImageFilename,
2021-05-09 19:11:05 +00:00
testMediaType, testImageDescription, testCity)
2020-04-03 10:08:04 +00:00
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Hey scoob we need like a hundred more #milkshakes",
testFollowersOnly,
testSaveToFile,
2021-03-17 20:18:00 +00:00
testC2S,
testCommentsEnabled,
testAttachImageFilename,
2021-05-09 19:11:05 +00:00
testMediaType, testImageDescription, testCity)
2020-04-03 10:08:04 +00:00
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"Getting kinda spooky around here",
testFollowersOnly,
testSaveToFile,
2021-03-17 20:18:00 +00:00
testC2S,
testCommentsEnabled,
testAttachImageFilename,
2021-05-09 19:11:05 +00:00
testMediaType, testImageDescription, testCity,
'someone')
2020-04-03 10:08:04 +00:00
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"And they would have gotten away with it too" +
"if it wasn't for those pesky hackers",
testFollowersOnly,
testSaveToFile,
2021-03-17 20:18:00 +00:00
testC2S,
testCommentsEnabled,
'img/logo.png', 'image/png',
2021-05-09 19:11:05 +00:00
'Description of image', testCity)
2020-04-03 10:08:04 +00:00
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"man these centralized sites are like the worst!",
testFollowersOnly,
testSaveToFile,
2021-03-17 20:18:00 +00:00
testC2S,
testCommentsEnabled,
testAttachImageFilename,
2021-05-09 19:11:05 +00:00
testMediaType, testImageDescription, testCity)
2020-04-03 10:08:04 +00:00
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"another mystery solved #test",
testFollowersOnly,
testSaveToFile,
2021-03-17 20:18:00 +00:00
testC2S,
testCommentsEnabled,
testAttachImageFilename,
2021-05-09 19:11:05 +00:00
testMediaType, testImageDescription, testCity)
2020-04-03 10:08:04 +00:00
createPublicPost(baseDir, nickname, domain, port, httpPrefix,
"let's go bowling",
testFollowersOnly,
testSaveToFile,
2021-03-17 20:18:00 +00:00
testC2S,
testCommentsEnabled,
testAttachImageFilename,
2021-05-09 19:11:05 +00:00
testMediaType, testImageDescription, testCity)
2020-04-03 10:08:04 +00:00
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)
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
2020-04-03 10:08:04 +00:00
if args.maxMentions < 4:
args.maxMentions = 4
2019-11-13 10:32:12 +00:00
2020-04-03 10:08:04 +00:00
registration = getConfigParam(baseDir, 'registration')
2019-11-13 10:32:12 +00:00
if not registration:
2020-04-03 10:08:04 +00:00
registration = False
minimumvotes = getConfigParam(baseDir, 'minvotes')
if minimumvotes:
args.minimumvotes = int(minimumvotes)
2020-10-10 13:52:50 +00:00
votingtime = getConfigParam(baseDir, 'votingtime')
if votingtime:
args.votingtime = votingtime
2020-10-10 15:56:44 +00:00
# only show the date at the bottom of posts
dateonly = getConfigParam(baseDir, 'dateonly')
if dateonly:
args.dateonly = dateonly
# set the maximum number of newswire posts per account or rss feed
maxNewswirePostsPerSource = \
getConfigParam(baseDir, 'maxNewswirePostsPerSource')
if maxNewswirePostsPerSource:
2020-10-19 16:33:58 +00:00
args.maxNewswirePostsPerSource = int(maxNewswirePostsPerSource)
# set the maximum number of newswire posts appearing in the right column
maxNewswirePosts = \
getConfigParam(baseDir, 'maxNewswirePosts')
if maxNewswirePosts:
args.maxNewswirePosts = int(maxNewswirePosts)
# set the maximum size of a newswire rss/atom feed in Kilobytes
maxNewswireFeedSizeKb = \
getConfigParam(baseDir, 'maxNewswireFeedSizeKb')
if maxNewswireFeedSizeKb:
2020-10-19 16:33:58 +00:00
args.maxNewswireFeedSizeKb = int(maxNewswireFeedSizeKb)
maxMirroredArticles = \
getConfigParam(baseDir, 'maxMirroredArticles')
if maxMirroredArticles is not None:
args.maxMirroredArticles = int(maxMirroredArticles)
2020-10-21 11:08:57 +00:00
maxNewsPosts = \
getConfigParam(baseDir, 'maxNewsPosts')
if maxNewsPosts is not None:
args.maxNewsPosts = int(maxNewsPosts)
maxFollowers = \
getConfigParam(baseDir, 'maxFollowers')
if maxFollowers is not None:
args.maxFollowers = int(maxFollowers)
maxFeedItemSizeKb = \
getConfigParam(baseDir, 'maxFeedItemSizeKb')
if maxFeedItemSizeKb is not None:
args.maxFeedItemSizeKb = int(maxFeedItemSizeKb)
dormantMonths = \
getConfigParam(baseDir, 'dormantMonths')
if dormantMonths is not None:
args.dormantMonths = int(dormantMonths)
sendThreadsTimeoutMins = \
getConfigParam(baseDir, 'sendThreadsTimeoutMins')
if sendThreadsTimeoutMins is not None:
args.sendThreadsTimeoutMins = int(sendThreadsTimeoutMins)
showPublishAsIcon = \
getConfigParam(baseDir, 'showPublishAsIcon')
if showPublishAsIcon is not None:
args.showPublishAsIcon = bool(showPublishAsIcon)
2020-10-25 20:38:01 +00:00
iconsAsButtons = \
getConfigParam(baseDir, 'iconsAsButtons')
if iconsAsButtons is not None:
args.iconsAsButtons = bool(iconsAsButtons)
rssIconAtTop = \
getConfigParam(baseDir, 'rssIconAtTop')
if rssIconAtTop is not None:
args.rssIconAtTop = bool(rssIconAtTop)
2020-10-26 21:32:08 +00:00
publishButtonAtTop = \
getConfigParam(baseDir, 'publishButtonAtTop')
if publishButtonAtTop is not None:
args.publishButtonAtTop = bool(publishButtonAtTop)
fullWidthTimelineButtonHeader = \
getConfigParam(baseDir, 'fullWidthTimelineButtonHeader')
if fullWidthTimelineButtonHeader is not None:
args.fullWidthTimelineButtonHeader = bool(fullWidthTimelineButtonHeader)
2020-11-20 11:49:11 +00:00
allowLocalNetworkAccess = \
getConfigParam(baseDir, 'allowLocalNetworkAccess')
if allowLocalNetworkAccess is not None:
args.allowLocalNetworkAccess = bool(allowLocalNetworkAccess)
verifyAllSignatures = \
getConfigParam(baseDir, 'verifyAllSignatures')
if verifyAllSignatures is not None:
args.verifyAllSignatures = bool(verifyAllSignatures)
2021-02-15 22:06:53 +00:00
brochMode = \
getConfigParam(baseDir, 'brochMode')
if brochMode is not None:
args.brochMode = bool(brochMode)
2021-06-09 15:19:30 +00:00
logLoginFailures = \
getConfigParam(baseDir, 'logLoginFailures')
if logLoginFailures is not None:
args.logLoginFailures = bool(logLoginFailures)
showNodeInfoAccounts = \
getConfigParam(baseDir, 'showNodeInfoAccounts')
if showNodeInfoAccounts is not None:
args.showNodeInfoAccounts = bool(showNodeInfoAccounts)
showNodeInfoVersion = \
getConfigParam(baseDir, 'showNodeInfoVersion')
if showNodeInfoVersion is not None:
args.showNodeInfoVersion = bool(showNodeInfoVersion)
2021-05-09 19:11:05 +00:00
city = \
getConfigParam(baseDir, 'city')
if city is not None:
args.city = city
YTDomain = getConfigParam(baseDir, 'youtubedomain')
if YTDomain:
if '://' in YTDomain:
YTDomain = YTDomain.split('://')[1]
if '/' in YTDomain:
YTDomain = YTDomain.split('/')[0]
2020-08-02 11:17:26 +00:00
if '.' in YTDomain:
args.YTReplacementDomain = YTDomain
if setTheme(baseDir, themeName, domain,
args.allowLocalNetworkAccess, args.language):
2020-04-03 10:08:04 +00:00
print('Theme set to ' + themeName)
2021-06-13 10:48:52 +00:00
# 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')
if __name__ == "__main__":
2021-06-09 15:19:30 +00:00
runDaemon(args.logLoginFailures,
args.city,
2021-05-09 19:11:05 +00:00
args.showNodeInfoAccounts,
args.showNodeInfoVersion,
args.brochMode,
2021-02-15 22:06:53 +00:00
args.verifyAllSignatures,
args.sendThreadsTimeoutMins,
args.dormantMonths,
args.maxNewswirePosts,
args.allowLocalNetworkAccess,
args.maxFeedItemSizeKb,
args.publishButtonAtTop,
2020-10-26 21:32:08 +00:00
args.rssIconAtTop,
args.iconsAsButtons,
2020-10-25 20:38:01 +00:00
args.fullWidthTimelineButtonHeader,
args.showPublishAsIcon,
args.maxFollowers,
args.maxNewsPosts,
2020-10-21 10:39:09 +00:00
args.maxMirroredArticles,
2020-10-19 16:33:58 +00:00
args.maxNewswireFeedSizeKb,
args.maxNewswirePostsPerSource,
args.dateonly,
args.votingtime,
2020-10-09 12:15:20 +00:00
args.positivevoting,
2020-10-08 19:53:30 +00:00
args.minimumvotes,
args.newsinstance,
2020-10-07 09:10:42 +00:00
args.blogsinstance, args.mediainstance,
args.maxRecentPosts,
not args.nosharedinbox,
registration, args.language, __version__,
instanceId, args.client, baseDir,
domain, onionDomain, i2pDomain,
args.YTReplacementDomain,
port, proxyPort, httpPrefix,
federationList, args.maxMentions,
args.maxEmoji, args.authenticatedFetch,
proxyType, args.maxReplies,
args.domainMaxPostsPerDay,
args.accountMaxPostsPerDay,
args.allowdeletion, debug, False,
args.instanceOnlySkillsSearch, [],
not args.noapproval)