Пример #1
0
def image():
    if request.method == 'POST':
        if 'username' in session:
            parentAcct = session['username']
            try:
                parentKey = ndb.Key(model.UserAccount, parentAcct).get().key
            except:
                flash(
                    "Image save refused. User Account key is invalid. Try logging in again"
                )
                return redirect(url_for('login'))
            uploaded_file = request.files.get('image')
            mimetype = uploaded_file.mimetype
            image_stream = uploaded_file.stream.read()
            # if user submits without selecting file, browser also submits a empty part without file type
            if mimetype == '':
                flash("No file selected. Try again")
                return redirect(url_for('image'))
            image = images.resize(image_stream, 96, 96)
            saveImage = model.Photo(
                image=image, mimetype=mimetype, parent=parentKey
            )  # stronger consistency -tied it to a parent record
            saveImage.put()
            imageID = saveImage.key.id()
            flash("Image upload complete. [{}] is its unique DB id".format(
                imageID))
            return redirect(url_for('thumbnail', id=saveImage.key.urlsafe()))
    return render_template('image.html')
Пример #2
0
 def get_photo(self, photo_id):
     if self.apikey:
         url_pattern = r'https://api.douban.com/v2/photo/{0}?apikey={1}'
         url = url_pattern.format(photo_id, self.apikey)
     else:
         url_pattern = r'https://api.douban.com/v2/photo/{0}'
         url = url_pattern.format(photo_id)
     jsonStr = self.get_html(url)
     data = json.loads(jsonStr)
     url = data['large']
     position = data['position']
     desc = data['desc']
     created = data['created']
     liked_count = data['liked_count']
     comments_count = data['comments_count']
     album_title = data['album_title']
     album_id = data['album_id']
     author_name = data['author']['name']
     author_id = data['author']['id']
     author_uid = data['author']['uid']
     return model.Photo(id,
                        url,
                        position=position,
                        desc=desc,
                        created=created,
                        liked_count=liked_count,
                        comments_count=comments_count,
                        album_title=album_title,
                        album_id=album_id,
                        author_name=author_name,
                        author_id=author_id,
                        author_uid=author_uid)
Пример #3
0
 def test_model_insert(self):
     """Model insert testing."""
     new_photo = model.Photo(
         id=3,
         name='photo4',
         width=640,
         height=480,
         date_original=datetime.datetime(2018, 1, 1, 15, 0, 2),
         aperture=2.8,
         shutter=1 / 100.0,
         iso=200,
         metering_mode='normal',
         exposure_mode='center weight',
         white_balance='daylight',
         camera='Canon EOS 70D',
         camera_id='123ABCDEF',
         lens_type='EF-S 70-200',
         lens_serial='234FDC',
         gps_lat="37 12' 34.5''N",
         gps_long="122 23'45.6''W",
         gps_alt=1.4,
         gps_datetime=datetime.datetime(2018, 1, 2, 11, 0, 0),
         comments='comment1',
         focal_length=15.5)
     self.session.add(new_photo)
     self.session.commit()
     self.assertEqual(
         new_photo,
         self.session.query(
             model.Photo).filter(model.Photo.name == new_photo.name).one())
Пример #4
0
    def process_media(self, media_array, feed=1):
        media_amount = random.randint(3, 10)
        if (media_array):
            for media in media_array:
                if feed == 0:
                    media_details = self.operation.get_photo_details(
                        media['node']['shortcode'])
                else:
                    media_details = self.operation.get_photo_details(
                        media['code'])

                if (media_details):
                    media_instance = model.Photo().from_json(media_details)
                    self.unfilteredMediaList.append(media_instance)
        else:
            return False

        # Validate and pick random photos.
        media_list = self.spam_validator.validate_photos(
            self.unfilteredMediaList)

        if (media_amount > len(media_list)):
            media_amount = len(media_list)

        self.mediaList.extend(random.sample(media_list, media_amount))

        if (len(self.mediaList) == 0):
            return False

        return True
Пример #5
0
def DeletePhoto(id):
    photo = model.Photo().get_by_id(int(id))
    if photo is not None:
        u = UpYun()
        if photo.imgurl is not None:
            path = photo.imgurl.replace('http://imgstore.b0.upaiyun.com', '')
            u.delete(path)
        photo.Album.PhotoCount -= 1
        photo.Album.put()
        photo.delete()
        memcache.delete('ALLALBUMS')
Пример #6
0
 def get_photos(self, album_id):
     if self.apikey:
         url_pattern = r'https://api.douban.com/v2/album/{0}/photos?start={1}&count=100&apikey={2}'
         url = url_pattern.format(album_id, 0, self.apikey)
     else:
         url_pattern = r'https://api.douban.com/v2/album/{0}/photos?start={1}&count=100'
         url = url_pattern.format(album_id, 0)
     jsonStr = self.get_html(url)
     data = json.loads(jsonStr)
     size = int(data['album']['size'])
     # 分N次提取。每次最多100条
     part = size / 100 if size % 100 == 0 else int(size / 100) + 1
     urls = [
         url.format(album_id, x * 100, self.apikey) for x in range(part)
     ]
     photos = []
     for url in urls:
         jsonStr = self.get_html(url)
         data = json.loads(jsonStr)
         for x in data['photos']:
             id = x['id']
             # 有的相册里没有large,那就取image
             if 'large' in x.keys():
                 url = x['large']
             elif 'image' in x.keys():
                 url = x['image']
             elif 'cover' in x.keys():
                 url = x['cover']
             position = x['position']
             desc = x['desc'].strip().strip()
             created = x['created']
             liked_count = x['liked_count']
             comments_count = x['comments_count']
             album_title = x['album_title'].strip()
             album_id = x['album_id']
             author_name = x['author']['name']
             author_id = x['author']['id']
             author_uid = x['author']['uid']
             photo = model.Photo(id,
                                 url,
                                 position=position,
                                 desc=desc,
                                 created=created,
                                 liked_count=liked_count,
                                 comments_count=comments_count,
                                 album_title=album_title,
                                 album_id=album_id,
                                 author_name=author_name,
                                 author_id=author_id,
                                 author_uid=author_uid)
             photos.append(photo)
     return photos
Пример #7
0
def GetPhoto(id):
    '''根据ID获取单张相片'''
    id = int(id)
    photo = model.Photo().get_by_id(id)
    return photo

    if photo is not None:
        #photo.ViewCount+=1
        #photo.Update()
        data['photo'] = photo
        data['prev'] = photo.Prev()
        data['next'] = photo.Next()
    return data
Пример #8
0
    def like(self, photo):
        response = self.operation.like(photo['id'])
        self.photo_repository.like(model.Photo().from_json(photo),
                                   response.status_code)

        if (response.status_code != 200):
            self.last_error_code = response.status_code
            if (response.status_code == 400):
                self.ban400 += 1
            self.failed_to_like()
            return False
        self.photo_liked()
        return True
Пример #9
0
def AddPhoto(name, description, mime, album, user, stream, imgurl=''):
    'Add Photo'
    photo = model.Photo()
    photo.Album = album
    photo.Author = user
    photo.Description = description
    photo.Mime = mime
    photo.Name = name
    photo.PhotoStream = None
    photo.Size = len(stream)
    photo.FileType, photo.Width, photo.Height = getImageInfo(stream)
    photo.imgurl = imgurl
    photo.Save()
    memcache.delete('ALLALBUMS')
    return photo
Пример #10
0
 def _create_db(self):
     """Creates database."""
     self.photos = {}
     self.backups = {}
     for backup in BACKUPS:
         self.backups[backup['id']] = model.Backup(**backup)
     for photo in PHOTOS:
         self.photos[photo['id']] = model.Photo(**photo)
     for location in LOCATIONS:
         l = model.Location(path=location['path'])
         l.backup = self.backups[location['backup_id']]
         self.photos[location['photo_id']].locations.append(l)
     for id_, photo in self.photos.items():
         self.session.add(photo)
     self.session.commit()
Пример #11
0
    def get_photos(self):
        self.photos_from_model = []
        self.users_from_model = []

        no_of_photos = random.randint(2, 10)

        for tag in self.tags:
            try:
                self.log('getting photos from tag {0}...'.format(tag))
                self.photos = self.operation.get_photos_by_tag(tag)
            except TypeError:
                self.log('oops! someting went wrong while fetching photos.')

        if not self.photos:
            return []

        for photo in self.photos:
            photo_details = self.operation.get_photo_details(photo['code'])
            if (photo_details):
                photo_instance = model.Photo().from_json(photo_details)
                self.repository.merge_photo(photo_instance)
                self.photos_from_model.append(photo_instance)

                user_details = self.operation.get_user_details(
                    photo_instance.owner_username.replace('\'', ''))
                if (user_details):
                    user_instance = model.User().from_json(user_details)
                    self.repository.merge_user(user_instance)
                    self.users_from_model.append(user_instance)

        self.filter_photos()

        if (len(self.photos_from_model) < no_of_photos):
            no_of_photos = len(self.photos_from_model)

        self.photos_from_model = random.sample(self.photos_from_model,
                                               no_of_photos)
        self.users_from_model = self.spam_validator.validate_users(
            self.users_from_model)

        return self.photos_from_model
Пример #12
0
    def test_delete_expired(self):
        """Test the flagging and deletion of expired records."""
        def run_delete_expired_task():
            """Runs the DeleteExpired task."""
            self.initialize_handler(tasks.DeleteExpired()).get()

        # This test sets up two Person entities, self.p1 and self.p2.
        # self.p1 is deleted in two stages (running DeleteExpired once during
        # the grace period, then again after the grace period); self.p2 is
        # deleted in one stage (running DeleteExpired after the grace period).

        # Setup cheerfully stolen from test_model.
        set_utcnow_for_test(datetime.datetime(2010, 1, 1))
        photo = model.Photo(bin_data='0x1111')
        photo.put()
        photo_id = photo.key().id()
        self.p1 = model.Person.create_original(
            'haiti',
            first_name='John',
            last_name='Smith',
            home_street='Washington St.',
            home_city='Los Angeles',
            home_state='California',
            home_postal_code='11111',
            home_neighborhood='Good Neighborhood',
            author_name='Alice Smith',
            author_phone='111-111-1111',
            author_email='*****@*****.**',
            photo_url='',
            photo=photo,
            source_url='https://www.source.com',
            source_date=datetime.datetime(2010, 1, 1),
            source_name='Source Name',
            entry_date=datetime.datetime(2010, 1, 1),
            expiry_date=datetime.datetime(2010, 2, 1),
            other='')
        self.p2 = model.Person.create_original(
            'haiti',
            first_name='Tzvika',
            last_name='Hartman',
            home_street='Herzl St.',
            home_city='Tel Aviv',
            home_state='Israel',
            source_date=datetime.datetime(2010, 1, 1),
            entry_date=datetime.datetime(2010, 1, 1),
            expiry_date=datetime.datetime(2010, 3, 1),
            other='')
        self.key_p1 = db.put(self.p1)
        self.key_p2 = db.put(self.p2)
        self.n1_1 = model.Note.create_original(
            'haiti',
            person_record_id=self.p1.record_id,
            linked_person_record_id=self.p2.record_id,
            status=u'believed_missing',
            found=False,
            entry_date=get_utcnow(),
            source_date=datetime.datetime(2010, 1, 2))
        note_id = self.n1_1.note_record_id
        db.put(self.n1_1)

        # Initial state: two Persons and one Note, nothing expired yet.
        eq(model.Person.all().count(), 2)
        eq(model.Person.past_due_records().count(), 0)
        assert model.Note.get('haiti', note_id)
        assert model.Photo.get_by_id(photo_id)

        run_delete_expired_task()

        # Confirm that DeleteExpired had no effect.
        eq(model.Person.all().count(), 2)
        eq(model.Person.past_due_records().count(), 0)
        eq(db.get(self.key_p1).source_date, datetime.datetime(2010, 1, 1))
        eq(db.get(self.key_p1).entry_date, datetime.datetime(2010, 1, 1))
        eq(db.get(self.key_p1).expiry_date, datetime.datetime(2010, 2, 1))
        assert model.Note.get('haiti', note_id)
        assert model.Photo.get_by_id(photo_id)

        # Advance to just after the expiry_date of self.p1.
        set_utcnow_for_test(datetime.datetime(2010, 2, 2))

        # self.p1 should now be past due.
        eq(model.Person.all().count(), 2)
        eq(model.Person.past_due_records().count(), 1)
        eq(db.get(self.key_p1).source_date, datetime.datetime(2010, 1, 1))
        eq(db.get(self.key_p1).entry_date, datetime.datetime(2010, 1, 1))
        eq(db.get(self.key_p1).expiry_date, datetime.datetime(2010, 2, 1))
        assert model.Note.get('haiti', note_id)
        assert model.Photo.get_by_id(photo_id)

        run_delete_expired_task()

        # Confirm that DeleteExpired set is_expired and updated the timestamps
        # on self.p1, but did not wipe its fields or delete the Note or Photo.
        eq(model.Person.all().count(), 1)
        eq(model.Person.past_due_records().count(), 1)
        eq(db.get(self.key_p1).source_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).entry_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).expiry_date, datetime.datetime(2010, 2, 1))
        eq(db.get(self.key_p1).is_expired, True)
        assert not model.Note.get('haiti', note_id)  # Note is hidden
        assert db.get(self.n1_1.key())  # but the Note entity still exists
        assert model.Photo.get_by_id(photo_id)

        # Advance past the end of the expiration grace period of self.p1.
        set_utcnow_for_test(datetime.datetime(2010, 2, 5))

        # Confirm that nothing has changed yet.
        eq(model.Person.all().count(), 1)
        eq(model.Person.past_due_records().count(), 1)
        eq(db.get(self.key_p1).source_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).entry_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).expiry_date, datetime.datetime(2010, 2, 1))
        eq(db.get(self.key_p1).is_expired, True)
        eq(model.Note.get('haiti', note_id), None)  # Note is hidden
        assert db.get(self.n1_1.key())  # but the Note entity still exists
        assert model.Photo.get_by_id(photo_id)

        run_delete_expired_task()

        # Confirm that the task wiped self.p1 without changing the timestamps,
        # and deleted the related Note and Photo.
        eq(model.Person.all().count(), 1)
        eq(model.Person.past_due_records().count(), 1)
        eq(db.get(self.key_p1).source_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).entry_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).expiry_date, datetime.datetime(2010, 2, 1))
        eq(db.get(self.key_p1).is_expired, True)
        eq(db.get(self.key_p1).first_name, None)
        eq(model.Note.get('haiti', note_id), None)  # Note is hidden
        eq(db.get(self.n1_1.key()), None)  # Note entity is actually gone
        eq(model.Photo.get_by_id(photo_id), None)  # Photo entity is gone

        # Advance past the end of the expiration grace period for self.p2.
        set_utcnow_for_test(datetime.datetime(2010, 3, 15))

        # Confirm that both records are now counted as past due.
        eq(model.Person.all().count(), 1)
        eq(model.Person.past_due_records().count(), 2)
        eq(db.get(self.key_p1).source_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).entry_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).expiry_date, datetime.datetime(2010, 2, 1))
        eq(db.get(self.key_p2).source_date, datetime.datetime(2010, 1, 1))
        eq(db.get(self.key_p2).entry_date, datetime.datetime(2010, 1, 1))
        eq(db.get(self.key_p2).expiry_date, datetime.datetime(2010, 3, 1))

        run_delete_expired_task()

        # Confirm that the task wiped self.p2 as well.
        eq(model.Person.all().count(), 0)
        eq(model.Person.past_due_records().count(), 2)
        eq(db.get(self.key_p1).is_expired, True)
        eq(db.get(self.key_p1).first_name, None)
        eq(db.get(self.key_p1).source_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).entry_date, datetime.datetime(2010, 2, 2))
        eq(db.get(self.key_p1).expiry_date, datetime.datetime(2010, 2, 1))
        eq(db.get(self.key_p2).is_expired, True)
        eq(db.get(self.key_p2).first_name, None)
        eq(db.get(self.key_p2).source_date, datetime.datetime(2010, 3, 15))
        eq(db.get(self.key_p2).entry_date, datetime.datetime(2010, 3, 15))
        eq(db.get(self.key_p2).expiry_date, datetime.datetime(2010, 3, 1))
Пример #13
0
def upload():
    username = session.get('username')
    if username:
        user_id = model_session.query(model.User).filter_by(username=username).first().id
    else:
        user_id = 0

    f_keys = request.form.keys()
    pattern = re.compile(r'^data:image/(png|jpeg|jpg);base64,(.*)$')
    raw_data = []
    for key in f_keys:
        if key != 'cloud_name' and key != 'choice':
            match = pattern.match(request.form[key])
            if match is None:
                raise ValueError('Invalid image data.')

            content_type = 'image/{}'.format(match.group(1))
            file_data = base64.b64decode(match.group(2))
            raw_data.append(file_data)

    user_path = 'static/uploads/%d' % user_id
    if not os.path.exists(user_path):
        # user doesn't have his/her own directory yet, so create one
        os.mkdir(user_path)

    cloud_name = request.form['cloud_name']
    algorithm = request.form['choice']

    # save cloud to database
    new_cloud = model.Cloud(user_id=user_id, name=cloud_name)
    model_session.add(new_cloud)
    model_session.commit()
    model_session.refresh(new_cloud)

    cloud_id = model_session.query(model.Cloud.id).order_by(desc(model.Cloud.id)).first()[0]

    # create a new directory inside the user's directory for uploaded photos
    path = user_path + '/' + str(cloud_id)
    if not os.path.exists(path):
        os.mkdir(path)

    for idx, d in enumerate(raw_data):
        filename = '{}.{}'.format(len(raw_data)-idx, match.group(1))
        with open(path + '/' + filename, 'w') as f:
            f.write(d)

    path = 'static/uploads/%d/%s' % (user_id, cloud_id)

    images = sorted(path + '/' + img for img in os.listdir(path) if img.rpartition('.')[2].lower() in ('jpg', 'jpeg', 'png'))
    points_path = os.path.abspath(os.path.join(path, "points"))
    reconstruct.start(algorithm, images, file_path=points_path)

    if algorithm == 'features':
        points = str(reconstruct.extract_points(points_path + "_inliers.txt"))
    elif algorithm == 'flow':
        points = str(reconstruct.extract_points(points_path + ".txt"))

    # set the path to the text file storing the 3D points of the cloud
    cloud = model_session.query(model.Cloud).filter_by(id=cloud_id).first()
    cloud.path = path
    model_session.commit()

    # save photos to database
    photos = [ img for img in os.listdir(path) if img.rpartition('.')[2].lower() in ('jpg', 'jpeg', 'png') ]

    for photo in photos:
        new_photo = model.Photo(filename=photo, path=path, cloud_id=cloud_id)
        model_session.add(new_photo)
        model_session.commit()
        model_session.refresh(new_photo)

    cloud_data = {'cloud_id': cloud_id, 'points': points}

    return jsonify(cloud_data)
Пример #14
0
    def post(self):
        """Exposed as `POST /api/photos`.

    Takes the following payload in the request body.  Payload represents a
    Photo that should be created.
    {
      'id':0,
      'ownerUserId':0,
      'ownerDisplayName':'',
      'ownerProfileUrl':'',
      'ownerProfilePhoto':'',
      'themeId':0,
      'themeDisplayName':'',
      'numVotes':0,
      'voted':false, // Whether or not the current user has voted on this.
      'created':0,
      'fullsizeUrl':'',
      'thumbnailUrl':'',
      'voteCtaUrl':'', // URL for Vote interactive post button.
      'photoContentUrl':'' // URL for Google crawler to hit to get info.
    }

    Returns the following JSON response representing the created Photo.
    {
      'id':0,
      'ownerUserId':0,
      'ownerDisplayName':'',
      'ownerProfileUrl':'',
      'ownerProfilePhoto':'',
      'themeId':0,
      'themeDisplayName':'',
      'numVotes':0,
      'voted':false, // Whether or not the current user has voted on this.
      'created':0,
      'fullsizeUrl':'',
      'thumbnailUrl':'',
      'voteCtaUrl':'', // URL for Vote interactive post button.
      'photoContentUrl':'' // URL for Google crawler to hit to get info.
    }

    Issues the following errors along with corresponding HTTP response codes:
    400: 'Bad Request' if the request is missing image data.
    401: 'Unauthorized request' (if certain parameters are present in the
         request)
    401: 'Access token expired' (there is a logged in user, but he doesn't
         have a refresh token and his access token is expiring in less than
         100 seconds, get a new token and retry)
    500: 'Error while writing app activity: ' + error from client library.
    """
        try:
            user = self.get_user_from_session()
            current_theme = model.Theme.get_current_theme()
            if current_theme:
                uploads = self.get_uploads('image')
                blob_info = uploads[0]
                photo = model.Photo(
                    owner_user_id=user.key().id(),
                    owner_display_name=user.google_display_name,
                    owner_profile_photo=user.google_public_profile_photo_url,
                    owner_profile_url=user.google_public_profile_url,
                    theme_id=current_theme.key().id(),
                    theme_display_name=current_theme.display_name,
                    created=datetime.datetime.now(),
                    num_votes=0,
                    image_blob_key=blob_info.key())
                photo.put()
                try:
                    result = self.add_photo_to_google_plus_activity(
                        user, photo)
                except apiclient.errors.HttpError as e:
                    logging.error("Error while writing app activity: %s",
                                  str(e))
                self.send_success(photo)
            else:
                self.send_error(404, 'No current theme.')
        except UserNotAuthorizedException as e:
            self.send_error(401, e.msg)