예제 #1
0
파일: person.py 프로젝트: miklobit/epicyon
def personBoxJson(baseDir: str,domain: str,port: int,path: str, \
                  httpPrefix: str,noOfItems: int,boxname: str, \
                  authorized: bool,ocapAlways: bool) -> []:
    """Obtain the inbox/outbox/moderation feed for the given person
    """
    if boxname!='inbox' and boxname!='dm' and \
       boxname!='outbox' and boxname!='moderation':
        return None

    if not '/' + boxname in path:
        return None

    # Only show the header by default
    headerOnly = True

    # handle page numbers
    pageNumber = None
    if '?page=' in path:
        pageNumber = path.split('?page=')[1]
        if pageNumber == 'true':
            pageNumber = 1
        else:
            try:
                pageNumber = int(pageNumber)
            except:
                pass
        path = path.split('?page=')[0]
        headerOnly = False

    if not path.endswith('/' + boxname):
        return None
    nickname = None
    if path.startswith('/users/'):
        nickname = path.replace('/users/', '', 1).replace('/' + boxname, '')
    if path.startswith('/@'):
        nickname = path.replace('/@', '', 1).replace('/' + boxname, '')
    if not nickname:
        return None
    if not validNickname(domain, nickname):
        return None
    if boxname == 'inbox':
        return createInbox(baseDir,nickname,domain,port,httpPrefix, \
                           noOfItems,headerOnly,ocapAlways,pageNumber)
    if boxname == 'dm':
        return createDMTimeline(baseDir,nickname,domain,port,httpPrefix, \
                                noOfItems,headerOnly,ocapAlways,pageNumber)
    elif boxname == 'outbox':
        return createOutbox(baseDir,nickname,domain,port,httpPrefix, \
                            noOfItems,headerOnly,authorized,pageNumber)
    elif boxname == 'moderation':
        return createModeration(baseDir,nickname,domain,port,httpPrefix, \
                                noOfItems,headerOnly,authorized,pageNumber)
    return None
예제 #2
0
파일: person.py 프로젝트: miklobit/epicyon
def createPerson(baseDir: str,nickname: str,domain: str,port: int, \
                 httpPrefix: str, saveToFile: bool,password=None) -> (str,str,{},{}):
    """Returns the private key, public key, actor and webfinger endpoint
    """
    if not validNickname(domain, nickname):
        return None, None, None, None

    # If a config.json file doesn't exist then don't decrement
    # remaining registrations counter
    remainingConfigExists = getConfigParam(baseDir, 'registrationsRemaining')
    if remainingConfigExists:
        registrationsRemaining = int(remainingConfigExists)
        if registrationsRemaining <= 0:
            return None, None, None, None

    privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint = \
        createPersonBase(baseDir,nickname,domain,port,httpPrefix,saveToFile,password)
    if noOfAccounts(baseDir) == 1:
        #print(nickname+' becomes the instance admin and a moderator')
        setRole(baseDir, nickname, domain, 'instance', 'admin')
        setRole(baseDir, nickname, domain, 'instance', 'moderator')
        setRole(baseDir, nickname, domain, 'instance', 'delegator')
        setConfigParam(baseDir, 'admin', nickname)

    if not os.path.isdir(baseDir + '/accounts'):
        os.mkdir(baseDir + '/accounts')
    if not os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
        os.mkdir(baseDir + '/accounts/' + nickname + '@' + domain)

    if os.path.isfile(baseDir + '/img/default-avatar.png'):
        copyfile(
            baseDir + '/img/default-avatar.png',
            baseDir + '/accounts/' + nickname + '@' + domain + '/avatar.png')
    if os.path.isfile(baseDir + '/img/image.png'):
        copyfile(
            baseDir + '/img/image.png',
            baseDir + '/accounts/' + nickname + '@' + domain + '/image.png')
    if os.path.isfile(baseDir + '/img/banner.png'):
        copyfile(
            baseDir + '/img/banner.png',
            baseDir + '/accounts/' + nickname + '@' + domain + '/banner.png')
    if remainingConfigExists:
        registrationsRemaining -= 1
        setConfigParam(baseDir, 'registrationsRemaining',
                       str(registrationsRemaining))
    return privateKeyPem, publicKeyPem, newPerson, webfingerEndpoint
예제 #3
0
파일: person.py 프로젝트: miklobit/epicyon
def registerAccount(baseDir: str,httpPrefix: str,domain: str,port: int, \
                    nickname: str,password: str) -> bool:
    """Registers a new account from the web interface
    """
    if accountExists(baseDir, nickname, domain):
        return False
    if not validNickname(domain, nickname):
        print('REGISTER: Nickname ' + nickname + ' is invalid')
        return False
    if len(password) < 8:
        print('REGISTER: Password should be at least 8 characters')
        return False
    privateKeyPem,publicKeyPem,newPerson,webfingerEndpoint= \
        createPerson(baseDir,nickname,domain,port, \
                     httpPrefix,True,password)
    if privateKeyPem:
        return True
    return False
예제 #4
0
파일: person.py 프로젝트: miklobit/epicyon
def personLookup(domain: str, path: str, baseDir: str) -> {}:
    """Lookup the person for an given nickname
    """
    if path.endswith('#main-key'):
        path = path.replace('#main-key', '')
    # is this a shared inbox lookup?
    isSharedInbox = False
    if path == '/inbox' or path == '/users/inbox' or path == '/sharedInbox':
        # shared inbox actor on @domain@domain
        path = '/users/' + domain
        isSharedInbox = True
    else:
        notPersonLookup=['/inbox','/outbox','/outboxarchive', \
                         '/followers','/following','/featured', \
                         '.png','.jpg','.gif','.mpv']
        for ending in notPersonLookup:
            if path.endswith(ending):
                return None
    nickname = None
    if path.startswith('/users/'):
        nickname = path.replace('/users/', '', 1)
    if path.startswith('/@'):
        nickname = path.replace('/@', '', 1)
    if not nickname:
        return None
    if not isSharedInbox and not validNickname(domain, nickname):
        return None
    if ':' in domain:
        domain = domain.split(':')[0]
    handle = nickname + '@' + domain
    filename = baseDir + '/accounts/' + handle + '.json'
    if not os.path.isfile(filename):
        return None
    personJson = {"user": "******"}
    try:
        with open(filename, 'r') as fp:
            personJson = commentjson.load(fp)
    except:
        print('WARN: Failed to load actor ' + filename)
        return None
    return personJson
예제 #5
0
파일: person.py 프로젝트: miklobit/epicyon
def personInboxJson(baseDir: str,domain: str,port: int,path: str, \
                    httpPrefix: str,noOfItems: int,ocapAlways: bool) -> []:
    """Obtain the inbox feed for the given person
    Authentication is expected to have already happened
    """
    if not '/inbox' in path:
        return None

    # Only show the header by default
    headerOnly = True

    # handle page numbers
    pageNumber = None
    if '?page=' in path:
        pageNumber = path.split('?page=')[1]
        if pageNumber == 'true':
            pageNumber = 1
        else:
            try:
                pageNumber = int(pageNumber)
            except:
                pass
        path = path.split('?page=')[0]
        headerOnly = False

    if not path.endswith('/inbox'):
        return None
    nickname = None
    if path.startswith('/users/'):
        nickname = path.replace('/users/', '', 1).replace('/inbox', '')
    if path.startswith('/@'):
        nickname = path.replace('/@', '', 1).replace('/inbox', '')
    if not nickname:
        return None
    if not validNickname(domain, nickname):
        return None
    return createInbox(baseDir,nickname,domain,port,httpPrefix, \
                       noOfItems,headerOnly,ocapAlways,pageNumber)
예제 #6
0
파일: shares.py 프로젝트: miklobit/epicyon
def getSharesFeedForPerson(baseDir: str, \
                           domain: str,port: int, \
                           path: str,httpPrefix: str, \
                           sharesPerPage=12) -> {}:
    """Returns the shares for an account from GET requests
    """
    if '/shares' not in path:
        return None
    # handle page numbers
    headerOnly = True
    pageNumber = None
    if '?page=' in path:
        pageNumber = path.split('?page=')[1]
        if pageNumber == 'true':
            pageNumber = 1
        else:
            try:
                pageNumber = int(pageNumber)
            except:
                pass
        path = path.split('?page=')[0]
        headerOnly = False

    if not path.endswith('/shares'):
        return None
    nickname = None
    if path.startswith('/users/'):
        nickname = path.replace('/users/', '', 1).replace('/shares', '')
    if path.startswith('/@'):
        nickname = path.replace('/@', '', 1).replace('/shares', '')
    if not nickname:
        return None
    if not validNickname(domain, nickname):
        return None

    if port:
        if port != 80 and port != 443:
            if ':' not in domain:
                domain = domain + ':' + str(port)

    handleDomain = domain
    if ':' in handleDomain:
        handleDomain = domain.split(':')[0]
    handle = nickname + '@' + handleDomain
    sharesFilename = baseDir + '/accounts/' + handle + '/shares.json'

    if headerOnly:
        noOfShares = 0
        if os.path.isfile(sharesFilename):
            with open(sharesFilename, 'r') as fp:
                sharesJson = commentjson.load(fp)
                noOfShares = len(sharesJson.items())
        shares = {
            '@context': 'https://www.w3.org/ns/activitystreams',
            'first': httpPrefix + '://' + domain + '/users/' + nickname +
            '/shares?page=1',
            'id':
            httpPrefix + '://' + domain + '/users/' + nickname + '/shares',
            'totalItems': str(noOfShares),
            'type': 'OrderedCollection'
        }
        return shares

    if not pageNumber:
        pageNumber = 1

    nextPageNumber = int(pageNumber + 1)
    shares = {
        '@context':
        'https://www.w3.org/ns/activitystreams',
        'id':
        httpPrefix + '://' + domain + '/users/' + nickname + '/shares?page=' +
        str(pageNumber),
        'orderedItems': [],
        'partOf':
        httpPrefix + '://' + domain + '/users/' + nickname + '/shares',
        'totalItems':
        0,
        'type':
        'OrderedCollectionPage'
    }

    if not os.path.isfile(sharesFilename):
        print("test5")
        return shares
    currPage = 1
    pageCtr = 0
    totalCtr = 0

    with open(sharesFilename, 'r') as fp:
        sharesJson = commentjson.load(fp)
        for itemID, item in sharesJson.items():
            pageCtr += 1
            totalCtr += 1
            if currPage == pageNumber:
                shares['orderedItems'].append(item)
            if pageCtr >= sharesPerPage:
                pageCtr = 0
                currPage += 1
    shares['totalItems'] = totalCtr
    lastPage = int(totalCtr / sharesPerPage)
    if lastPage < 1:
        lastPage = 1
    if nextPageNumber > lastPage:
        shares[
            'next'] = httpPrefix + '://' + domain + '/users/' + nickname + '/shares?page=' + str(
                lastPage)
    return shares
예제 #7
0
def getFollowingFeed(baseDir: str,domain: str,port: int,path: str, \
                     httpPrefix: str, authenticated: bool,
                     followsPerPage=12, \
                     followFile='following') -> {}:
    """Returns the following and followers feeds from GET requests
    """
    # Show a small number of follows to non-authenticated viewers
    if not authenticated:
        followsPerPage=6

    if '/'+followFile not in path:
        return None
    # handle page numbers
    headerOnly=True
    pageNumber=None    
    if '?page=' in path:
        pageNumber=path.split('?page=')[1]
        if pageNumber=='true' or not authenticated:
            pageNumber=1
        else:
            try:
                pageNumber=int(pageNumber)
            except:
                pass
        path=path.split('?page=')[0]
        headerOnly=False
    
    if not path.endswith('/'+followFile):
        return None
    nickname=None
    if path.startswith('/users/'):
        nickname=path.replace('/users/','',1).replace('/'+followFile,'')
    if path.startswith('/@'):
        nickname=path.replace('/@','',1).replace('/'+followFile,'')
    if not nickname:
        return None
    if not validNickname(domain,nickname):
        return None

    if port:
        if port!=80 and port!=443:
            if ':' not in domain:
                domain=domain+':'+str(port)

    if headerOnly:
        following = {
            '@context': 'https://www.w3.org/ns/activitystreams',
            'first': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page=1',
            'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile,
            'totalItems': getNoOfFollows(baseDir,nickname,domain,authenticated),
            'type': 'OrderedCollection'}
        return following

    if not pageNumber:
        pageNumber=1

    nextPageNumber=int(pageNumber+1)
    following = {
        '@context': 'https://www.w3.org/ns/activitystreams',
        'id': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page='+str(pageNumber),
        'orderedItems': [],
        'partOf': httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile,
        'totalItems': 0,
        'type': 'OrderedCollectionPage'}        

    handleDomain=domain
    if ':' in handleDomain:
        handleDomain=domain.split(':')[0]
    handle=nickname.lower()+'@'+handleDomain.lower()
    filename=baseDir+'/accounts/'+handle+'/'+followFile+'.txt'
    if not os.path.isfile(filename):
        return following
    currPage=1
    pageCtr=0
    totalCtr=0
    with open(filename, "r") as f:
        lines = f.readlines()
        for line in lines:
            if '#' not in line:
                if '@' in line and not line.startswith('http'):
                    pageCtr += 1
                    totalCtr += 1
                    if currPage==pageNumber:
                        url = httpPrefix + '://' + line.lower().replace('\n','').split('@')[1] + \
                            '/users/' + line.lower().replace('\n','').split('@')[0]
                        following['orderedItems'].append(url)
                elif (line.startswith('http') or line.startswith('dat')) and '/users/' in line:
                    pageCtr += 1
                    totalCtr += 1
                    if currPage==pageNumber:
                        following['orderedItems'].append(line.lower().replace('\n',''))
            if pageCtr>=followsPerPage:
                pageCtr=0
                currPage += 1
    following['totalItems']=totalCtr
    lastPage=int(totalCtr/followsPerPage)
    if lastPage<1:
        lastPage=1
    if nextPageNumber>lastPage:
        following['next']=httpPrefix+'://'+domain+'/users/'+nickname+'/'+followFile+'?page='+str(lastPage)
    return following